diff --git a/.hgtags b/.hgtags index 88b9530dfc8..3392c1b99b7 100644 --- a/.hgtags +++ b/.hgtags @@ -211,3 +211,4 @@ da9a4c9312816451884aa6db6f18be51a07bff13 jdk8-b86 5ebf6c63714de2c9dcf831074086d31daec819df jdk8-b87 e517701a4d0e25ae9c7945bca6e1762a8c5d8aa6 jdk8-b88 4dec41b3c5e3bb616f0c6f15830d940905aa5d16 jdk8-b89 +f09ab0c416185e3cba371e81bcb6a16060c90f44 jdk8-b90 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 3d22910518e..f74c0bcfaa6 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -211,3 +211,4 @@ df9b5240f0a76c91cfe1a5b39da4d08df56e05be jdk8-b86 b9415faa7066a4d3b16d466556d5428446918d95 jdk8-b87 e1a929afcfc492470d50be0b6b0e8dc77d3760b9 jdk8-b88 892a0196d10c67f3a12f0eefb0bb536e423d8868 jdk8-b89 +69b773a221b956a3386933ecdbfeccee0edeac47 jdk8-b90 diff --git a/NewMakefile.gmk b/NewMakefile.gmk index b02e37f6a4d..033183289ff 100644 --- a/NewMakefile.gmk +++ b/NewMakefile.gmk @@ -73,7 +73,7 @@ else grep ^.PHONY: | head -n 1 | cut -d " " -f 2-))) $(all_phony_targets): - @$(foreach spec,$(SPEC),($(MAKE) -f NewMakefile.gmk SPEC=$(spec) $(VERBOSE) VERBOSE=$(VERBOSE) $@) &&) true + @$(foreach spec,$(SPEC),($(MAKE) -f NewMakefile.gmk SPEC=$(spec) $(VERBOSE) VERBOSE=$(VERBOSE) LOG_LEVEL=$(LOG_LEVEL) $@) &&) true endif endif diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 2172ee8ef68..a7e66a31320 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -54,9 +54,9 @@ MAKE_ARGS="SPEC=$(SPEC)" MAKE:=@MAKE@ -# Pass along the verbosity setting. +# Pass along the verbosity and log level settings. ifeq (,$(findstring VERBOSE=,$(MAKE))) - MAKE:=$(MAKE) $(VERBOSE) VERBOSE="$(VERBOSE)" + MAKE:=$(MAKE) $(VERBOSE) VERBOSE="$(VERBOSE)" LOG_LEVEL="$(LOG_LEVEL)" endif # No implicit variables or rules! diff --git a/common/makefiles/Main.gmk b/common/makefiles/Main.gmk index 145fbad91b2..d07f3e2b386 100644 --- a/common/makefiles/Main.gmk +++ b/common/makefiles/Main.gmk @@ -240,10 +240,10 @@ clean-docs: clean-test: $(call CleanComponent,testoutput) -.PHONY: langtools corba jaxp jaxws hotspot jdk nashorn images overlay-images install -.PHONY: langtools-only corba-only jaxp-only jaxws-only hotspot-only jdk-only nashorn-only images-only overlay-images-only install-only -.PHONY: all test clean dist-clean bootcycle-images start-make -.PHONY: clean-langtools clean-corba clean-jaxp clean-jaxws clean-hotspot clean-jdk clean-nashorn clean-images clean-overlay-images clean-bootcycle-build +.PHONY: langtools corba jaxp jaxws hotspot jdk nashorn images overlay-images install test docs +.PHONY: langtools-only corba-only jaxp-only jaxws-only hotspot-only jdk-only nashorn-only images-only overlay-images-only install-only test-only docs-only +.PHONY: all clean dist-clean bootcycle-images start-make +.PHONY: clean-langtools clean-corba clean-jaxp clean-jaxws clean-hotspot clean-jdk clean-nashorn clean-images clean-docs clean-test clean-overlay-images clean-bootcycle-build .PHONY: profiles profiles-only profiles-oscheck FRC: # Force target diff --git a/common/makefiles/NativeCompilation.gmk b/common/makefiles/NativeCompilation.gmk index 2e084ea410c..c3b276609c3 100644 --- a/common/makefiles/NativeCompilation.gmk +++ b/common/makefiles/NativeCompilation.gmk @@ -321,11 +321,17 @@ define SetupNativeCompilation ifneq (,$$($1_DEBUG_SYMBOLS)) ifeq ($(ENABLE_DEBUG_SYMBOLS), true) - # Programs don't get the debug symbols added in the old build. It's not clear if - # this is intentional. - ifeq ($$($1_PROGRAM),) + ifdef OPENJDK + # Always add debug symbols $1_EXTRA_CFLAGS+=$(CFLAGS_DEBUG_SYMBOLS) $1_EXTRA_CXXFLAGS+=$(CXXFLAGS_DEBUG_SYMBOLS) + else + # Programs don't get the debug symbols added in the old build. It's not clear if + # this is intentional. + ifeq ($$($1_PROGRAM),) + $1_EXTRA_CFLAGS+=$(CFLAGS_DEBUG_SYMBOLS) + $1_EXTRA_CXXFLAGS+=$(CXXFLAGS_DEBUG_SYMBOLS) + endif endif endif endif diff --git a/corba/.hgtags b/corba/.hgtags index 45d7f0a02bd..20b78fa3d32 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -211,3 +211,4 @@ a45bb25a67c7517b45f00c9682e317f46fecbba9 jdk8-b83 f1709874d55a06bc3d5dfa02dbcdfbc59f4cba34 jdk8-b87 4e3a881ebb1ee96ce0872508b0066d74f310dbfa jdk8-b88 fe4150590ee597f4e125fea950aa3b352622cc2d jdk8-b89 +c8286839d0df04aba819ec4bef12b86babccf30e jdk8-b90 diff --git a/hotspot/.hgtags b/hotspot/.hgtags index fb98d2c5ed1..f202d86f926 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -341,3 +341,5 @@ c4af77d2045476c56fbf3f914b336bb1b7cd18af hs25-b30 4ec91349972255650f97bedfd07e6423e02428cf hs25-b31 9c1fe0b419b40a9ecdd1653cc9af1b6d67a12c46 jdk8-b89 69494caf57908ba2c8efa9eaaa472b4d1875588a hs25-b32 +1ae0472ff3a0117b5b019d380ad59fface2fde14 jdk8-b90 +b19517cecc2e91636d7c16ba2f35e3d3dc628099 hs25-b33 diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index e0d9826e468..526ed2393f2 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -151,32 +151,43 @@ else $(MAKE_ARGS) BUILD_FLAVOR=product docs endif +# Output directories +C1_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_compiler1 +C2_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_compiler2 +MINIMAL1_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_minimal1 +ZERO_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_zero +SHARK_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_shark + # Build variation of hotspot $(C1_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ - $(MAKE) BUILD_FLAVOR=$(@:%1=%) VM_TARGET=$@ generic_build1 $(ALT_OUT) + $(MAKE) BUILD_DIR=$(C1_DIR) BUILD_FLAVOR=$(@:%1=%) VM_TARGET=$@ generic_build1 $(ALT_OUT) $(C2_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ - $(MAKE) BUILD_FLAVOR=$@ VM_TARGET=$@ generic_build2 $(ALT_OUT) + $(MAKE) BUILD_DIR=$(C2_DIR) BUILD_FLAVOR=$@ VM_TARGET=$@ generic_build2 $(ALT_OUT) $(ZERO_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ - $(MAKE) BUILD_FLAVOR=$(@:%zero=%) VM_TARGET=$@ \ - generic_buildzero $(ALT_OUT) + $(MAKE) BUILD_DIR=$(ZERO_DIR) BUILD_FLAVOR=$(@:%zero=%) VM_TARGET=$@ generic_buildzero $(ALT_OUT) $(SHARK_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ - $(MAKE) BUILD_FLAVOR=$(@:%shark=%) VM_TARGET=$@ \ - generic_buildshark $(ALT_OUT) + $(MAKE) BUILD_DIR=$(SHARK_DIR) BUILD_FLAVOR=$(@:%shark=%) VM_TARGET=$@ generic_buildshark $(ALT_OUT) $(MINIMAL1_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ - $(MAKE) BUILD_FLAVOR=$(@:%minimal1=%) VM_TARGET=$@ \ - generic_buildminimal1 $(ALT_OUT) + $(MAKE) BUILD_DIR=$(MINIMAL1_DIR) BUILD_FLAVOR=$(@:%minimal1=%) VM_TARGET=$@ generic_buildminimal1 $(ALT_OUT) + +# Install hotspot script in build directory +HOTSPOT_SCRIPT=$(BUILD_DIR)/$(BUILD_FLAVOR)/hotspot +$(HOTSPOT_SCRIPT): $(GAMMADIR)/make/hotspot.script + $(QUIETLY) $(MKDIR) -p $(BUILD_DIR)/$(BUILD_FLAVOR) + $(QUIETLY) cat $< | sed -e 's|@@LIBARCH@@|$(LIBARCH)|g' | sed -e 's|@@JDK_IMPORT_PATH@@|$(JDK_IMPORT_PATH)|g' > $@ + $(QUIETLY) chmod +x $@ # Build compiler1 (client) rule, different for platforms -generic_build1: +generic_build1: $(HOTSPOT_SCRIPT) $(MKDIR) -p $(OUTPUTDIR) ifeq ($(OSNAME),windows) ifeq ($(ARCH_DATA_MODEL), 32) @@ -201,7 +212,7 @@ else endif # Build compiler2 (server) rule, different for platforms -generic_build2: +generic_build2: $(HOTSPOT_SCRIPT) $(MKDIR) -p $(OUTPUTDIR) ifeq ($(OSNAME),windows) $(CD) $(OUTPUTDIR); \ @@ -217,19 +228,19 @@ else $(MAKE_ARGS) $(VM_TARGET) endif -generic_buildzero: +generic_buildzero: $(HOTSPOT_SCRIPT) $(MKDIR) -p $(OUTPUTDIR) $(CD) $(OUTPUTDIR); \ $(MAKE) -f $(ABS_OS_MAKEFILE) \ $(MAKE_ARGS) $(VM_TARGET) -generic_buildshark: +generic_buildshark: $(HOTSPOT_SCRIPT) $(MKDIR) -p $(OUTPUTDIR) $(CD) $(OUTPUTDIR); \ $(MAKE) -f $(ABS_OS_MAKEFILE) \ $(MAKE_ARGS) $(VM_TARGET) -generic_buildminimal1: +generic_buildminimal1: $(HOTSPOT_SCRIPT) ifeq ($(JVM_VARIANT_MINIMAL1),true) $(MKDIR) -p $(OUTPUTDIR) ifeq ($(ARCH_DATA_MODEL), 32) @@ -252,224 +263,210 @@ endif # Export file rule generic_export: $(EXPORT_LIST) + export_product: - $(MAKE) BUILD_FLAVOR=$(@:export_%=%) VM_SUBDIR=$(@:export_%=%) \ - generic_export + $(MAKE) BUILD_FLAVOR=$(@:export_%=%) generic_export export_fastdebug: - $(MAKE) BUILD_FLAVOR=$(@:export_%=%) VM_SUBDIR=$(@:export_%=%) \ - EXPORT_SUBDIR=/$(@:export_%=%) \ - generic_export + $(MAKE) BUILD_FLAVOR=$(@:export_%=%) EXPORT_SUBDIR=/$(@:export_%=%) generic_export export_debug: - $(MAKE) BUILD_FLAVOR=$(@:export_%=%) VM_SUBDIR=$(@:export_%=%) \ - EXPORT_SUBDIR=/$(@:export_%=%) \ - generic_export + $(MAKE) BUILD_FLAVOR=$(@:export_%=%) EXPORT_SUBDIR=/$(@:export_%=%) generic_export export_optimized: - $(MAKE) BUILD_FLAVOR=$(@:export_%=%) VM_SUBDIR=$(@:export_%=%) \ - EXPORT_SUBDIR=/$(@:export_%=%) \ - generic_export + $(MAKE) BUILD_FLAVOR=$(@:export_%=%) EXPORT_SUBDIR=/$(@:export_%=%) generic_export + export_product_jdk:: - $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) \ - VM_SUBDIR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) \ - generic_export + $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) generic_export export_optimized_jdk:: - $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) \ - VM_SUBDIR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) \ - generic_export + $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) generic_export export_fastdebug_jdk:: - $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) \ - VM_SUBDIR=$(@:export_%_jdk=%) \ - ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) \ - generic_export + $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) generic_export export_debug_jdk:: - $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) VM_SUBDIR=$(@:export_%_jdk=%) \ - ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) \ - generic_export + $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) generic_export # Export file copy rules XUSAGE=$(HS_SRC_DIR)/share/vm/Xusage.txt -DOCS_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_docs -C1_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_compiler1/$(VM_SUBDIR) -C2_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_compiler2/$(VM_SUBDIR) -MINIMAL1_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_minimal1/$(VM_SUBDIR) -ZERO_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_zero/$(VM_SUBDIR) -SHARK_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_shark/$(VM_SUBDIR) +DOCS_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_docs +C1_BUILD_DIR =$(C1_DIR)/$(BUILD_FLAVOR) +C2_BUILD_DIR =$(C2_DIR)/$(BUILD_FLAVOR) +MINIMAL1_BUILD_DIR=$(MINIMAL1_DIR)/$(BUILD_FLAVOR) +ZERO_BUILD_DIR =$(ZERO_DIR)/$(BUILD_FLAVOR) +SHARK_BUILD_DIR =$(SHARK_DIR)/$(BUILD_FLAVOR) # Server (C2) ifeq ($(JVM_VARIANT_SERVER), true) # Common -$(EXPORT_SERVER_DIR)/%.diz: $(C2_DIR)/%.diz +$(EXPORT_SERVER_DIR)/%.diz: $(C2_BUILD_DIR)/%.diz $(install-file) -$(EXPORT_LIB_DIR)/%.jar: $(C2_DIR)/../generated/%.jar +$(EXPORT_LIB_DIR)/%.jar: $(C2_BUILD_DIR)/../generated/%.jar $(install-file) -$(EXPORT_INCLUDE_DIR)/%: $(C2_DIR)/../generated/jvmtifiles/% +$(EXPORT_INCLUDE_DIR)/%: $(C2_BUILD_DIR)/../generated/jvmtifiles/% $(install-file) # Windows -$(EXPORT_SERVER_DIR)/%.dll: $(C2_DIR)/%.dll +$(EXPORT_SERVER_DIR)/%.dll: $(C2_BUILD_DIR)/%.dll $(install-file) -$(EXPORT_SERVER_DIR)/%.pdb: $(C2_DIR)/%.pdb +$(EXPORT_SERVER_DIR)/%.pdb: $(C2_BUILD_DIR)/%.pdb $(install-file) -$(EXPORT_SERVER_DIR)/%.map: $(C2_DIR)/%.map +$(EXPORT_SERVER_DIR)/%.map: $(C2_BUILD_DIR)/%.map $(install-file) -$(EXPORT_LIB_DIR)/%.lib: $(C2_DIR)/%.lib +$(EXPORT_LIB_DIR)/%.lib: $(C2_BUILD_DIR)/%.lib $(install-file) -$(EXPORT_JRE_BIN_DIR)/%.diz: $(C2_DIR)/%.diz +$(EXPORT_JRE_BIN_DIR)/%.diz: $(C2_BUILD_DIR)/%.diz $(install-file) -$(EXPORT_JRE_BIN_DIR)/%.dll: $(C2_DIR)/%.dll +$(EXPORT_JRE_BIN_DIR)/%.dll: $(C2_BUILD_DIR)/%.dll $(install-file) -$(EXPORT_JRE_BIN_DIR)/%.pdb: $(C2_DIR)/%.pdb +$(EXPORT_JRE_BIN_DIR)/%.pdb: $(C2_BUILD_DIR)/%.pdb $(install-file) -$(EXPORT_JRE_BIN_DIR)/%.map: $(C2_DIR)/%.map +$(EXPORT_JRE_BIN_DIR)/%.map: $(C2_BUILD_DIR)/%.map $(install-file) # Unix -$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C2_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(C2_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_SERVER_DIR)/64/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_SERVER_DIR)/64/%.$(LIBRARY_SUFFIX): $(C2_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C2_DIR)/%.debuginfo +$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C2_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_SERVER_DIR)/%.debuginfo: $(C2_DIR)/%.debuginfo +$(EXPORT_SERVER_DIR)/%.debuginfo: $(C2_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_SERVER_DIR)/64/%.debuginfo: $(C2_DIR)/%.debuginfo +$(EXPORT_SERVER_DIR)/64/%.debuginfo: $(C2_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(C2_DIR)/%.diz +$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(C2_BUILD_DIR)/%.diz $(install-file) -$(EXPORT_SERVER_DIR)/64/%.diz: $(C2_DIR)/%.diz +$(EXPORT_SERVER_DIR)/64/%.diz: $(C2_BUILD_DIR)/%.diz $(install-file) endif # Client (C1) ifeq ($(JVM_VARIANT_CLIENT), true) # Common -$(EXPORT_CLIENT_DIR)/%.diz: $(C1_DIR)/%.diz +$(EXPORT_CLIENT_DIR)/%.diz: $(C1_BUILD_DIR)/%.diz $(install-file) -$(EXPORT_LIB_DIR)/%.jar: $(C1_DIR)/../generated/%.jar +$(EXPORT_LIB_DIR)/%.jar: $(C1_BUILD_DIR)/../generated/%.jar $(install-file) -$(EXPORT_INCLUDE_DIR)/%: $(C1_DIR)/../generated/jvmtifiles/% +$(EXPORT_INCLUDE_DIR)/%: $(C1_BUILD_DIR)/../generated/jvmtifiles/% $(install-file) # Windows -$(EXPORT_CLIENT_DIR)/%.dll: $(C1_DIR)/%.dll +$(EXPORT_CLIENT_DIR)/%.dll: $(C1_BUILD_DIR)/%.dll $(install-file) -$(EXPORT_CLIENT_DIR)/%.pdb: $(C1_DIR)/%.pdb +$(EXPORT_CLIENT_DIR)/%.pdb: $(C1_BUILD_DIR)/%.pdb $(install-file) -$(EXPORT_CLIENT_DIR)/%.map: $(C1_DIR)/%.map +$(EXPORT_CLIENT_DIR)/%.map: $(C1_BUILD_DIR)/%.map $(install-file) -$(EXPORT_LIB_DIR)/%.lib: $(C1_DIR)/%.lib +$(EXPORT_LIB_DIR)/%.lib: $(C1_BUILD_DIR)/%.lib $(install-file) -$(EXPORT_JRE_BIN_DIR)/%.diz: $(C1_DIR)/%.diz +$(EXPORT_JRE_BIN_DIR)/%.diz: $(C1_BUILD_DIR)/%.diz $(install-file) -$(EXPORT_JRE_BIN_DIR)/%.dll: $(C1_DIR)/%.dll +$(EXPORT_JRE_BIN_DIR)/%.dll: $(C1_BUILD_DIR)/%.dll $(install-file) -$(EXPORT_JRE_BIN_DIR)/%.pdb: $(C1_DIR)/%.pdb +$(EXPORT_JRE_BIN_DIR)/%.pdb: $(C1_BUILD_DIR)/%.pdb $(install-file) -$(EXPORT_JRE_BIN_DIR)/%.map: $(C1_DIR)/%.map +$(EXPORT_JRE_BIN_DIR)/%.map: $(C1_BUILD_DIR)/%.map $(install-file) # Unix -$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C1_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_CLIENT_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_CLIENT_DIR)/%.$(LIBRARY_SUFFIX): $(C1_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_CLIENT_DIR)/64/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_CLIENT_DIR)/64/%.$(LIBRARY_SUFFIX): $(C1_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C1_DIR)/%.debuginfo +$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C1_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_CLIENT_DIR)/%.debuginfo: $(C1_DIR)/%.debuginfo +$(EXPORT_CLIENT_DIR)/%.debuginfo: $(C1_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_CLIENT_DIR)/64/%.debuginfo: $(C1_DIR)/%.debuginfo +$(EXPORT_CLIENT_DIR)/64/%.debuginfo: $(C1_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(C1_DIR)/%.diz +$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(C1_BUILD_DIR)/%.diz $(install-file) -$(EXPORT_CLIENT_DIR)/64/%.diz: $(C1_DIR)/%.diz +$(EXPORT_CLIENT_DIR)/64/%.diz: $(C1_BUILD_DIR)/%.diz $(install-file) endif # Minimal1 ifeq ($(JVM_VARIANT_MINIMAL1), true) # Common -$(EXPORT_MINIMAL_DIR)/%.diz: $(MINIMAL1_DIR)/%.diz +$(EXPORT_MINIMAL_DIR)/%.diz: $(MINIMAL1_BUILD_DIR)/%.diz $(install-file) -$(EXPORT_LIB_DIR)/%.jar: $(MINIMAL1_DIR)/../generated/%.jar +$(EXPORT_LIB_DIR)/%.jar: $(MINIMAL1_BUILD_DIR)/../generated/%.jar $(install-file) -$(EXPORT_INCLUDE_DIR)/%: $(MINIMAL1_DIR)/../generated/jvmtifiles/% +$(EXPORT_INCLUDE_DIR)/%: $(MINIMAL1_BUILD_DIR)/../generated/jvmtifiles/% $(install-file) # Windows -$(EXPORT_MINIMAL_DIR)/%.dll: $(MINIMAL1_DIR)/%.dll +$(EXPORT_MINIMAL_DIR)/%.dll: $(MINIMAL1_BUILD_DIR)/%.dll $(install-file) -$(EXPORT_MINIMAL_DIR)/%.pdb: $(MINIMAL1_DIR)/%.pdb +$(EXPORT_MINIMAL_DIR)/%.pdb: $(MINIMAL1_BUILD_DIR)/%.pdb $(install-file) -$(EXPORT_MINIMAL_DIR)/%.map: $(MINIMAL1_DIR)/%.map +$(EXPORT_MINIMAL_DIR)/%.map: $(MINIMAL1_BUILD_DIR)/%.map $(install-file) -$(EXPORT_LIB_DIR)/%.lib: $(MINIMAL1_DIR)/%.lib +$(EXPORT_LIB_DIR)/%.lib: $(MINIMAL1_BUILD_DIR)/%.lib $(install-file) -$(EXPORT_JRE_BIN_DIR)/%.diz: $(MINIMAL1_DIR)/%.diz +$(EXPORT_JRE_BIN_DIR)/%.diz: $(MINIMAL1_BUILD_DIR)/%.diz $(install-file) -$(EXPORT_JRE_BIN_DIR)/%.dll: $(MINIMAL1_DIR)/%.dll +$(EXPORT_JRE_BIN_DIR)/%.dll: $(MINIMAL1_BUILD_DIR)/%.dll $(install-file) -$(EXPORT_JRE_BIN_DIR)/%.pdb: $(MINIMAL1_DIR)/%.pdb +$(EXPORT_JRE_BIN_DIR)/%.pdb: $(MINIMAL1_BUILD_DIR)/%.pdb $(install-file) -$(EXPORT_JRE_BIN_DIR)/%.map: $(MINIMAL1_DIR)/%.map +$(EXPORT_JRE_BIN_DIR)/%.map: $(MINIMAL1_BUILD_DIR)/%.map $(install-file) # Unix -$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(MINIMAL1_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(MINIMAL1_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_MINIMAL_DIR)/%.$(LIBRARY_SUFFIX): $(MINIMAL1_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_MINIMAL_DIR)/%.$(LIBRARY_SUFFIX): $(MINIMAL1_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_MINIMAL_DIR)/64/%.$(LIBRARY_SUFFIX): $(MINIMAL1_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_MINIMAL_DIR)/64/%.$(LIBRARY_SUFFIX): $(MINIMAL1_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(MINIMAL1_DIR)/%.debuginfo +$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(MINIMAL1_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_MINIMAL_DIR)/%.debuginfo: $(MINIMAL1_DIR)/%.debuginfo +$(EXPORT_MINIMAL_DIR)/%.debuginfo: $(MINIMAL1_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_MINIMAL_DIR)/64/%.debuginfo: $(MINIMAL1_DIR)/%.debuginfo +$(EXPORT_MINIMAL_DIR)/64/%.debuginfo: $(MINIMAL1_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(MINIMAL1_DIR)/%.diz +$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(MINIMAL1_BUILD_DIR)/%.diz $(install-file) -$(EXPORT_MINIMAL_DIR)/64/%.diz: $(MINIMAL1_DIR)/%.diz +$(EXPORT_MINIMAL_DIR)/64/%.diz: $(MINIMAL1_BUILD_DIR)/%.diz $(install-file) endif # Zero ifeq ($(JVM_VARIANT_ZERO), true) # Common -$(EXPORT_LIB_DIR)/%.jar: $(ZERO_DIR)/../generated/%.jar +$(EXPORT_LIB_DIR)/%.jar: $(ZERO_BUILD_DIR)/../generated/%.jar $(install-file) -$(EXPORT_INCLUDE_DIR)/%: $(ZERO_DIR)/../generated/jvmtifiles/% +$(EXPORT_INCLUDE_DIR)/%: $(ZERO_BUILD_DIR)/../generated/jvmtifiles/% $(install-file) # Unix -$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(ZERO_DIR)/%.debuginfo +$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(ZERO_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(ZERO_DIR)/%.diz +$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(ZERO_BUILD_DIR)/%.diz $(install-file) -$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_SERVER_DIR)/%.debuginfo: $(ZERO_DIR)/%.debuginfo +$(EXPORT_SERVER_DIR)/%.debuginfo: $(ZERO_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_SERVER_DIR)/%.diz: $(ZERO_DIR)/%.diz +$(EXPORT_SERVER_DIR)/%.diz: $(ZERO_BUILD_DIR)/%.diz $(install-file) endif # Shark ifeq ($(JVM_VARIANT_ZEROSHARK), true) # Common -$(EXPORT_LIB_DIR)/%.jar: $(SHARK_DIR)/../generated/%.jar +$(EXPORT_LIB_DIR)/%.jar: $(SHARK_BUILD_DIR)/../generated/%.jar $(install-file) -$(EXPORT_INCLUDE_DIR)/%: $(SHARK_DIR)/../generated/jvmtifiles/% +$(EXPORT_INCLUDE_DIR)/%: $(SHARK_BUILD_DIR)/../generated/jvmtifiles/% $(install-file) # Unix -$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo): $(SHARK_DIR)/%.debuginfo +$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo): $(SHARK_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(SHARK_DIR)/%.diz +$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(SHARK_BUILD_DIR)/%.diz $(install-file) -$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_SERVER_DIR)/%.debuginfo: $(SHARK_DIR)/%.debuginfo +$(EXPORT_SERVER_DIR)/%.debuginfo: $(SHARK_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_SERVER_DIR)/%.diz: $(SHARK_DIR)/%.diz +$(EXPORT_SERVER_DIR)/%.diz: $(SHARK_BUILD_DIR)/%.diz $(install-file) endif diff --git a/hotspot/make/bsd/makefiles/buildtree.make b/hotspot/make/bsd/makefiles/buildtree.make index 9d0a2174c54..16a0f9a64ff 100644 --- a/hotspot/make/bsd/makefiles/buildtree.make +++ b/hotspot/make/bsd/makefiles/buildtree.make @@ -49,7 +49,6 @@ # adlc.make - # jvmti.make - generate JVMTI bindings from the spec (JSR-163) # sa.make - generate SA jar file and natives -# env.[ck]sh - environment settings # # The makefiles are split this way so that "make foo" will run faster by not # having to read the dependency files for the vm. @@ -129,9 +128,7 @@ SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make # dtrace.make is used on BSD versions that implement Dtrace (like MacOS X) -BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make \ - jvmti.make sa.make dtrace.make \ - env.sh env.csh jdkpath.sh +BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make dtrace.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) @@ -354,33 +351,6 @@ dtrace.make: $(BUILDTREE_MAKE) echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ -env.sh: $(BUILDTREE_MAKE) - @echo Creating $@ ... - $(QUIETLY) ( \ - $(BUILDTREE_COMMENT); \ - { echo "JAVA_HOME=$(JDK_IMPORT_PATH)"; }; \ - { \ - echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \ - } | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \ - echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \ - echo "export JAVA_HOME CLASSPATH HOTSPOT_BUILD_USER"; \ - ) > $@ - -env.csh: env.sh - @echo Creating $@ ... - $(QUIETLY) ( \ - $(BUILDTREE_COMMENT); \ - { echo "setenv JAVA_HOME \"$(JDK_IMPORT_PATH)\""; }; \ - sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \ - ) > $@ - -jdkpath.sh: $(BUILDTREE_MAKE) - @echo Creating $@ ... - $(QUIETLY) ( \ - $(BUILDTREE_COMMENT); \ - echo "JDK=${JAVA_HOME}"; \ - ) > $@ - FORCE: .PHONY: all FORCE diff --git a/hotspot/make/bsd/makefiles/launcher.make b/hotspot/make/bsd/makefiles/launcher.make deleted file mode 100644 index 588bf9aaebf..00000000000 --- a/hotspot/make/bsd/makefiles/launcher.make +++ /dev/null @@ -1,115 +0,0 @@ -# -# 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 -# 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. -# -# - -# Rules to build gamma launcher, used by vm.make - - -LAUNCHER_SCRIPT = hotspot -LAUNCHER = gamma - -LAUNCHERDIR := $(GAMMADIR)/src/os/posix/launcher -LAUNCHERDIR_SHARE := $(GAMMADIR)/src/share/tools/launcher -LAUNCHERFLAGS := $(ARCHFLAG) \ - -I$(LAUNCHERDIR) -I$(GAMMADIR)/src/share/vm/prims \ - -I$(LAUNCHERDIR_SHARE) \ - -DFULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \ - -DJDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \ - -DJDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \ - -DARCH=\"$(LIBARCH)\" \ - -DGAMMA \ - -DLAUNCHER_TYPE=\"gamma\" \ - -DLINK_INTO_$(LINK_INTO) \ - $(TARGET_DEFINES) -# Give the launcher task_for_pid() privileges so that it can be used to run JStack, JInfo, et al. -LFLAGS_LAUNCHER += -sectcreate __TEXT __info_plist $(GAMMADIR)/src/os/bsd/launcher/Info-privileged.plist - -ifeq ($(LINK_INTO),AOUT) - LAUNCHER.o = launcher.o $(JVM_OBJ_FILES) - LAUNCHER_MAPFILE = mapfile_reorder - LFLAGS_LAUNCHER$(LDNOMAP) += $(MAPFLAG:FILENAME=$(LAUNCHER_MAPFILE)) - LFLAGS_LAUNCHER += $(SONAMEFLAG:SONAME=$(LIBJVM)) $(STATIC_LIBGCC) - LIBS_LAUNCHER += $(STATIC_STDCXX) $(LIBS) -else - LAUNCHER.o = launcher.o - LFLAGS_LAUNCHER += -L`pwd` - - # The gamma launcher runs the JDK from $JAVA_HOME, overriding the JVM with a - # freshly built JVM at ./libjvm.{so|dylib}. This is accomplished by setting - # the library searchpath using ({DY}LD_LIBRARY_PATH) to find the local JVM - # first. Gamma dlopen()s libjava from $JAVA_HOME/jre/lib{/$arch}, which is - # statically linked with CoreFoundation framework libs. Unfortunately, gamma's - # unique searchpath results in some unresolved symbols in the framework - # libraries, because JDK libraries are inadvertently discovered first on the - # searchpath, e.g. libjpeg. On Mac OS X, filenames are case *insensitive*. - # So, the actual filename collision is libjpeg.dylib and libJPEG.dylib. - # To resolve this, gamma needs to also statically link with the CoreFoundation - # framework libraries. - - ifeq ($(OS_VENDOR),Darwin) - LFLAGS_LAUNCHER += -framework CoreFoundation - endif - - LIBS_LAUNCHER += -l$(JVM) $(LIBS) -endif - -LINK_LAUNCHER = $(LINK.CC) - -LINK_LAUNCHER/PRE_HOOK = $(LINK_LIB.CXX/PRE_HOOK) -LINK_LAUNCHER/POST_HOOK = $(LINK_LIB.CXX/POST_HOOK) - -LAUNCHER_OUT = launcher - -SUFFIXES += .d - -SOURCES := $(shell find $(LAUNCHERDIR) -name "*.c") -SOURCES_SHARE := $(shell find $(LAUNCHERDIR_SHARE) -name "*.c") - -OBJS := $(patsubst $(LAUNCHERDIR)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES)) $(patsubst $(LAUNCHERDIR_SHARE)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES_SHARE)) - -DEPFILES := $(patsubst %.o,%.d,$(OBJS)) --include $(DEPFILES) - -$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR_SHARE)/%.c - $(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); } - $(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CXXFLAGS) - -$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR)/%.c - $(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); } - $(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CXXFLAGS) - -$(LAUNCHER): $(OBJS) $(LIBJVM) $(LAUNCHER_MAPFILE) - $(QUIETLY) echo Linking launcher... - $(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK) - $(QUIETLY) $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(sort $(OBJS)) $(LIBS_LAUNCHER) - $(QUIETLY) $(LINK_LAUNCHER/POST_HOOK) - # Sign the launcher with the development certificate (if present) so that it can be used - # to run JStack, JInfo, et al. - $(QUIETLY) -codesign -s openjdk_codesign $@ - -$(LAUNCHER): $(LAUNCHER_SCRIPT) - -$(LAUNCHER_SCRIPT): $(LAUNCHERDIR)/launcher.script - $(QUIETLY) sed -e 's/@@LIBARCH@@/$(LIBARCH)/g' $< > $@ - $(QUIETLY) chmod +x $@ - diff --git a/hotspot/make/bsd/makefiles/vm.make b/hotspot/make/bsd/makefiles/vm.make index d247031a67a..f668b4e5334 100644 --- a/hotspot/make/bsd/makefiles/vm.make +++ b/hotspot/make/bsd/makefiles/vm.make @@ -331,9 +331,6 @@ install_jvm: $(LIBJVM) #---------------------------------------------------------------------- # Other files -# Gamma launcher -include $(MAKEFILES_DIR)/launcher.make - # Signal interposition library include $(MAKEFILES_DIR)/jsig.make diff --git a/hotspot/src/os/posix/launcher/launcher.script b/hotspot/make/hotspot.script similarity index 89% rename from hotspot/src/os/posix/launcher/launcher.script rename to hotspot/make/hotspot.script index e8d4281808a..c6259ba2eee 100644 --- a/hotspot/src/os/posix/launcher/launcher.script +++ b/hotspot/make/hotspot.script @@ -72,6 +72,7 @@ EMACS=emacs REL_MYDIR=`dirname $0` MYDIR=`cd $REL_MYDIR && pwd` +# # Look whether the user wants to run inside gdb case "$1" in -gdb) @@ -95,16 +96,14 @@ case "$1" in ;; esac -JDK= -if [ "${ALT_JAVA_HOME}" = "" ]; then - . ${MYDIR}/jdkpath.sh +if [ "${ALT_JAVA_HOME}" != "" ]; then + JDK=${ALT_JAVA_HOME%%/jre} else - JDK=${ALT_JAVA_HOME%%/jre}; + JDK=@@JDK_IMPORT_PATH@@ fi if [ "${JDK}" = "" ]; then - echo Failed to find JDK. ALT_JAVA_HOME is not set or ./jdkpath.sh is empty or not found. - exit 1 + echo "Failed to find JDK. Either ALT_JAVA_HOME is not set or JDK_IMPORT_PATH is empty." fi # We will set the LD_LIBRARY_PATH as follows: @@ -142,12 +141,12 @@ else export LD_LIBRARY_PATH fi -JPARMS="$@ $JAVA_ARGS"; +JPARMS="-Dsun.java.launcher=gamma -XXaltjvm=$MYDIR $@ $JAVA_ARGS"; -# Locate the gamma development launcher -LAUNCHER=${MYDIR}/gamma +# Locate the java launcher +LAUNCHER=$JDK/bin/java if [ ! -x $LAUNCHER ] ; then - echo Error: Cannot find the gamma development launcher \"$LAUNCHER\" + echo Error: Cannot find the java launcher \"$LAUNCHER\" exit 1 fi @@ -166,9 +165,10 @@ set args $JPARMS file $LAUNCHER directory $GDBSRCDIR # Get us to a point where we can set breakpoints in libjvm.so -break InitializeJVM +set breakpoint pending on +break JNI_CreateJavaVM run -# Stop in InitializeJVM +# Stop in JNI_CreateJavaVM delete 1 # We can now set breakpoints wherever we like EOF @@ -199,7 +199,7 @@ case "$MODE" in rm -f $GDBSCR ;; dbx) - $DBX -s $HOME/.dbxrc $LAUNCHER $JPARMS + $DBX -s $HOME/.dbxrc -c "loadobject -load libjvm.so; stop in JNI_CreateJavaVM; run $JPARMS; delete all" $LAUNCHER ;; valgrind) echo Warning: Defaulting to 16Mb heap to make Valgrind run faster, use -Xmx for larger heap diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index ae66a044772..db74b20d81b 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2013 HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=33 +HS_BUILD_NUMBER=34 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff --git a/hotspot/make/jprt.properties b/hotspot/make/jprt.properties index af7f321b722..5971546c6d9 100644 --- a/hotspot/make/jprt.properties +++ b/hotspot/make/jprt.properties @@ -134,14 +134,14 @@ jprt.my.windows.x64=${jprt.my.windows.x64.${jprt.tools.default.release}} jprt.build.targets.standard= \ ${jprt.my.solaris.sparc}-{product|fastdebug}, \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug}, \ + ${jprt.my.solaris.sparcv9}-{product|fastdebug|optimized}, \ ${jprt.my.solaris.i586}-{product|fastdebug}, \ ${jprt.my.solaris.x64}-{product|fastdebug}, \ ${jprt.my.linux.i586}-{product|fastdebug}, \ - ${jprt.my.linux.x64}-{product|fastdebug}, \ + ${jprt.my.linux.x64}-{product|fastdebug|optimized}, \ ${jprt.my.macosx.x64}-{product|fastdebug}, \ ${jprt.my.windows.i586}-{product|fastdebug}, \ - ${jprt.my.windows.x64}-{product|fastdebug}, \ + ${jprt.my.windows.x64}-{product|fastdebug|optimized}, \ ${jprt.my.linux.armvh}-{product|fastdebug} jprt.build.targets.open= \ diff --git a/hotspot/make/linux/makefiles/buildtree.make b/hotspot/make/linux/makefiles/buildtree.make index 0b7c12001b3..3b715773554 100644 --- a/hotspot/make/linux/makefiles/buildtree.make +++ b/hotspot/make/linux/makefiles/buildtree.make @@ -49,7 +49,6 @@ # adlc.make - # jvmti.make - generate JVMTI bindings from the spec (JSR-163) # sa.make - generate SA jar file and natives -# env.[ck]sh - environment settings # # The makefiles are split this way so that "make foo" will run faster by not # having to read the dependency files for the vm. @@ -123,8 +122,7 @@ SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) # For dependencies and recursive makes. BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make -BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make \ - env.sh env.csh jdkpath.sh +BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) @@ -349,33 +347,6 @@ sa.make: $(BUILDTREE_MAKE) echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ -env.sh: $(BUILDTREE_MAKE) - @echo Creating $@ ... - $(QUIETLY) ( \ - $(BUILDTREE_COMMENT); \ - { echo "JAVA_HOME=$(JDK_IMPORT_PATH)"; }; \ - { \ - echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \ - } | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \ - echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \ - echo "export JAVA_HOME CLASSPATH HOTSPOT_BUILD_USER"; \ - ) > $@ - -env.csh: env.sh - @echo Creating $@ ... - $(QUIETLY) ( \ - $(BUILDTREE_COMMENT); \ - { echo "setenv JAVA_HOME \"$(JDK_IMPORT_PATH)\""; }; \ - sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \ - ) > $@ - -jdkpath.sh: $(BUILDTREE_MAKE) - @echo Creating $@ ... - $(QUIETLY) ( \ - $(BUILDTREE_COMMENT); \ - echo "JDK=${JAVA_HOME}"; \ - ) > $@ - FORCE: .PHONY: all FORCE diff --git a/hotspot/make/linux/makefiles/launcher.make b/hotspot/make/linux/makefiles/launcher.make deleted file mode 100644 index 23f3edad41a..00000000000 --- a/hotspot/make/linux/makefiles/launcher.make +++ /dev/null @@ -1,93 +0,0 @@ -# -# 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 -# 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. -# -# - -# Rules to build gamma launcher, used by vm.make - - -LAUNCHER_SCRIPT = hotspot -LAUNCHER = gamma - -LAUNCHERDIR := $(GAMMADIR)/src/os/posix/launcher -LAUNCHERDIR_SHARE := $(GAMMADIR)/src/share/tools/launcher -LAUNCHERFLAGS := $(ARCHFLAG) \ - -I$(LAUNCHERDIR) -I$(GAMMADIR)/src/share/vm/prims \ - -I$(LAUNCHERDIR_SHARE) \ - -DFULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \ - -DJDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \ - -DJDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \ - -DARCH=\"$(LIBARCH)\" \ - -DGAMMA \ - -DLAUNCHER_TYPE=\"gamma\" \ - -DLINK_INTO_$(LINK_INTO) \ - $(TARGET_DEFINES) - -ifeq ($(LINK_INTO),AOUT) - LAUNCHER.o = launcher.o $(JVM_OBJ_FILES) - LAUNCHER_MAPFILE = mapfile_reorder - LFLAGS_LAUNCHER$(LDNOMAP) += $(MAPFLAG:FILENAME=$(LAUNCHER_MAPFILE)) - LFLAGS_LAUNCHER += $(SONAMEFLAG:SONAME=$(LIBJVM)) $(STATIC_LIBGCC) - LIBS_LAUNCHER += $(STATIC_STDCXX) $(LIBS) -else - LAUNCHER.o = launcher.o - LFLAGS_LAUNCHER += -L `pwd` - LIBS_LAUNCHER += -l$(JVM) $(LIBS) -endif - -LINK_LAUNCHER = $(LINK.CC) - -LINK_LAUNCHER/PRE_HOOK = $(LINK_LIB.CXX/PRE_HOOK) -LINK_LAUNCHER/POST_HOOK = $(LINK_LIB.CXX/POST_HOOK) - -LAUNCHER_OUT = launcher - -SUFFIXES += .d - -SOURCES := $(shell find $(LAUNCHERDIR) -name "*.c") -SOURCES_SHARE := $(shell find $(LAUNCHERDIR_SHARE) -name "*.c") - -OBJS := $(patsubst $(LAUNCHERDIR)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES)) $(patsubst $(LAUNCHERDIR_SHARE)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES_SHARE)) - -DEPFILES := $(patsubst %.o,%.d,$(OBJS)) --include $(DEPFILES) - -$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR_SHARE)/%.c - $(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); } - $(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CXXFLAGS) - -$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR)/%.c - $(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); } - $(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CXXFLAGS) - -$(LAUNCHER): $(OBJS) $(LIBJVM) $(LAUNCHER_MAPFILE) - $(QUIETLY) echo Linking launcher... - $(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK) - $(QUIETLY) $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(sort $(OBJS)) $(LIBS_LAUNCHER) - $(QUIETLY) $(LINK_LAUNCHER/POST_HOOK) - -$(LAUNCHER): $(LAUNCHER_SCRIPT) - -$(LAUNCHER_SCRIPT): $(LAUNCHERDIR)/launcher.script - $(QUIETLY) sed -e 's/@@LIBARCH@@/$(LIBARCH)/g' $< > $@ - $(QUIETLY) chmod +x $@ - diff --git a/hotspot/make/linux/makefiles/vm.make b/hotspot/make/linux/makefiles/vm.make index af060f8af0b..79a926a8c4f 100644 --- a/hotspot/make/linux/makefiles/vm.make +++ b/hotspot/make/linux/makefiles/vm.make @@ -372,9 +372,6 @@ install_jvm: $(LIBJVM) #---------------------------------------------------------------------- # Other files -# Gamma launcher -include $(MAKEFILES_DIR)/launcher.make - # Signal interposition library include $(MAKEFILES_DIR)/jsig.make diff --git a/hotspot/make/solaris/makefiles/buildtree.make b/hotspot/make/solaris/makefiles/buildtree.make index 989470f293f..5827c4ff7d9 100644 --- a/hotspot/make/solaris/makefiles/buildtree.make +++ b/hotspot/make/solaris/makefiles/buildtree.make @@ -49,7 +49,6 @@ # adlc.make - # jvmti.make - generate JVMTI bindings from the spec (JSR-163) # sa.make - generate SA jar file and natives -# env.[ck]sh - environment settings # # The makefiles are split this way so that "make foo" will run faster by not # having to read the dependency files for the vm. @@ -116,8 +115,7 @@ SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) # For dependencies and recursive makes. BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make -BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make \ - env.sh env.csh jdkpath.sh +BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ ARCH=$(ARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) @@ -339,33 +337,6 @@ sa.make: $(BUILDTREE_MAKE) echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ -env.sh: $(BUILDTREE_MAKE) - @echo Creating $@ ... - $(QUIETLY) ( \ - $(BUILDTREE_COMMENT); \ - { echo "JAVA_HOME=$(JDK_IMPORT_PATH)"; }; \ - { \ - echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \ - } | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \ - echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \ - echo "export JAVA_HOME LD_LIBRARY_PATH CLASSPATH HOTSPOT_BUILD_USER"; \ - ) > $@ - -env.csh: env.sh - @echo Creating $@ ... - $(QUIETLY) ( \ - $(BUILDTREE_COMMENT); \ - { echo "setenv JAVA_HOME \"$(JDK_IMPORT_PATH)\""; }; \ - sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \ - ) > $@ - -jdkpath.sh: $(BUILDTREE_MAKE) - @echo Creating $@ ... - $(QUIETLY) ( \ - $(BUILDTREE_COMMENT); \ - echo "JDK=${JAVA_HOME}"; \ - ) > $@ - FORCE: .PHONY: all FORCE diff --git a/hotspot/make/solaris/makefiles/launcher.make b/hotspot/make/solaris/makefiles/launcher.make deleted file mode 100644 index 090ff5ea7a6..00000000000 --- a/hotspot/make/solaris/makefiles/launcher.make +++ /dev/null @@ -1,108 +0,0 @@ -# -# 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 -# 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. -# -# - -# Rules to build gamma launcher, used by vm.make - -LAUNCHER_SCRIPT = hotspot -LAUNCHER = gamma - -LAUNCHERDIR = $(GAMMADIR)/src/os/posix/launcher -LAUNCHERDIR_SHARE := $(GAMMADIR)/src/share/tools/launcher -LAUNCHERFLAGS = $(ARCHFLAG) \ - -I$(LAUNCHERDIR) -I$(GAMMADIR)/src/share/vm/prims \ - -I$(LAUNCHERDIR_SHARE) \ - -DFULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \ - -DJDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \ - -DJDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \ - -DARCH=\"$(LIBARCH)\" \ - -DGAMMA \ - -DLAUNCHER_TYPE=\"gamma\" \ - -DLINK_INTO_$(LINK_INTO) \ - $(TARGET_DEFINES) - -ifeq ($(LINK_INTO),AOUT) - LAUNCHER.o = launcher.o $(JVM_OBJ_FILES) - LAUNCHER_MAPFILE = mapfile_extended - LFLAGS_LAUNCHER$(LDNOMAP) += $(MAPFLAG:FILENAME=$(LAUNCHER_MAPFILE)) - LIBS_LAUNCHER += $(LIBS) -else - LAUNCHER.o = launcher.o - LFLAGS_LAUNCHER += -L `pwd` - LIBS_LAUNCHER += -l$(JVM) $(LIBS) -endif - -LINK_LAUNCHER = $(LINK.CXX) - -LINK_LAUNCHER/PRE_HOOK = $(LINK_LIB.CXX/PRE_HOOK) -LINK_LAUNCHER/POST_HOOK = $(LINK_LIB.CXX/POST_HOOK) - -ifeq ("${Platform_compiler}", "sparcWorks") -# Enable the following LAUNCHERFLAGS addition if you need to compare the -# built ELF objects. -# -# The -g option makes static data global and the "-W0,-noglobal" -# option tells the compiler to not globalize static data using a unique -# globalization prefix. Instead force the use of a static globalization -# prefix based on the source filepath so the objects from two identical -# compilations are the same. -# -# Note: The blog says to use "-W0,-xglobalstatic", but that doesn't -# seem to work. I got "-W0,-noglobal" from Kelly and that works. -#LAUNCHERFLAGS += -W0,-noglobal -endif # Platform_compiler == sparcWorks - -LAUNCHER_OUT = launcher - -SUFFIXES += .d - -SOURCES := $(shell find $(LAUNCHERDIR) -name "*.c") -SOURCES_SHARE := $(shell find $(LAUNCHERDIR_SHARE) -name "*.c") - -OBJS := $(patsubst $(LAUNCHERDIR)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES)) $(patsubst $(LAUNCHERDIR_SHARE)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES_SHARE)) - -DEPFILES := $(patsubst %.o,%.d,$(OBJS)) --include $(DEPFILES) - -$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR_SHARE)/%.c - $(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); } - $(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CXXFLAGS) - -$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR)/%.c - $(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); } - $(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CXXFLAGS) - -$(LAUNCHER): $(OBJS) $(LIBJVM) $(LAUNCHER_MAPFILE) -ifeq ($(filter -sbfast -xsbfast, $(CFLAGS_BROWSE)),) - $(QUIETLY) echo Linking launcher... - $(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK) - $(QUIETLY) $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(sort $(OBJS)) $(LIBS_LAUNCHER) - $(QUIETLY) $(LINK_LAUNCHER/POST_HOOK) -endif # filter -sbfast -xsbfast - -$(LAUNCHER): $(LAUNCHER_SCRIPT) - -$(LAUNCHER_SCRIPT): $(LAUNCHERDIR)/launcher.script - $(QUIETLY) sed -e 's/@@LIBARCH@@/$(LIBARCH)/g' $< > $@ - $(QUIETLY) chmod +x $@ - diff --git a/hotspot/make/solaris/makefiles/vm.make b/hotspot/make/solaris/makefiles/vm.make index 62146d77f03..855f7f18861 100644 --- a/hotspot/make/solaris/makefiles/vm.make +++ b/hotspot/make/solaris/makefiles/vm.make @@ -338,9 +338,6 @@ install_jvm: $(LIBJVM) #---------------------------------------------------------------------- # Other files -# Gamma launcher -include $(MAKEFILES_DIR)/launcher.make - # Signal interposition library include $(MAKEFILES_DIR)/jsig.make diff --git a/hotspot/make/windows/makefiles/debug.make b/hotspot/make/windows/makefiles/debug.make index c19f1757b69..2fca2182841 100644 --- a/hotspot/make/windows/makefiles/debug.make +++ b/hotspot/make/windows/makefiles/debug.make @@ -33,7 +33,7 @@ GENERATED=../generated BUILD_PCH_FILE=_build_pch_file.obj !endif -default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA +default:: $(BUILD_PCH_FILE) $(AOUT) checkAndBuildSA !include ../local.make !include compile.make @@ -71,4 +71,3 @@ $(AOUT): $(Res_Files) $(Obj_Files) vm.def !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make -!include $(WorkSpace)/make/windows/makefiles/launcher.make diff --git a/hotspot/make/windows/makefiles/fastdebug.make b/hotspot/make/windows/makefiles/fastdebug.make index 0fc2329dfd9..cde98f214ea 100644 --- a/hotspot/make/windows/makefiles/fastdebug.make +++ b/hotspot/make/windows/makefiles/fastdebug.make @@ -33,7 +33,7 @@ GENERATED=../generated BUILD_PCH_FILE=_build_pch_file.obj !endif -default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA +default:: $(BUILD_PCH_FILE) $(AOUT) checkAndBuildSA !include ../local.make !include compile.make @@ -70,4 +70,3 @@ $(AOUT): $(Res_Files) $(Obj_Files) vm.def !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make -!include $(WorkSpace)/make/windows/makefiles/launcher.make diff --git a/hotspot/make/windows/makefiles/launcher.make b/hotspot/make/windows/makefiles/launcher.make deleted file mode 100644 index 10ad009eef9..00000000000 --- a/hotspot/make/windows/makefiles/launcher.make +++ /dev/null @@ -1,73 +0,0 @@ -# -# 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 -# 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. -# -# - - -LAUNCHER_FLAGS=$(CXX_FLAGS) $(ARCHFLAG) \ - /D FULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \ - /D JDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \ - /D JDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \ - /D GAMMA \ - /D LAUNCHER_TYPE=\"gamma\" \ - /D _CRT_SECURE_NO_WARNINGS \ - /D _CRT_SECURE_NO_DEPRECATE \ - /D LINK_INTO_LIBJVM \ - /I $(WorkSpace)\src\os\windows\launcher \ - /I $(WorkSpace)\src\share\tools\launcher \ - /I $(WorkSpace)\src\share\vm\prims \ - /I $(WorkSpace)\src\share\vm \ - /I $(WorkSpace)\src\cpu\$(Platform_arch)\vm \ - /I $(WorkSpace)\src\os\windows\vm - -LD_FLAGS=/manifest $(HS_INTERNAL_NAME).lib kernel32.lib user32.lib /nologo /machine:$(MACHINE) /map /debug /subsystem:console - -!if "$(COMPILER_NAME)" == "VS2005" -# This VS2005 compiler has /GS as a default and requires bufferoverflowU.lib -# on the link command line, otherwise we get missing __security_check_cookie -# externals at link time. Even with /GS-, you need bufferoverflowU.lib. -BUFFEROVERFLOWLIB = bufferoverflowU.lib -LD_FLAGS = $(LD_FLAGS) $(BUFFEROVERFLOWLIB) -!endif - -!if "$(COMPILER_NAME)" == "VS2010" && "$(BUILDARCH)" == "i486" -LD_FLAGS = /SAFESEH $(LD_FLAGS) -!endif - -LAUNCHERDIR = $(WorkSpace)/src/os/windows/launcher -LAUNCHERDIR_SHARE = $(WorkSpace)/src/share/tools/launcher - -OUTDIR = launcher - -{$(LAUNCHERDIR)}.c{$(OUTDIR)}.obj: - -mkdir $(OUTDIR) 2>NUL >NUL - $(CXX) $(LAUNCHER_FLAGS) /c /Fo$@ $< - -{$(LAUNCHERDIR_SHARE)}.c{$(OUTDIR)}.obj: - -mkdir $(OUTDIR) 2>NUL >NUL - $(CXX) $(LAUNCHER_FLAGS) /c /Fo$@ $< - -$(OUTDIR)\*.obj: $(LAUNCHERDIR)\*.c $(LAUNCHERDIR)\*.h $(LAUNCHERDIR_SHARE)\*.c $(LAUNCHERDIR_SHARE)\*.h - -launcher: $(OUTDIR)\java.obj $(OUTDIR)\java_md.obj $(OUTDIR)\jli_util.obj - echo $(JAVA_HOME) > jdkpath.txt - $(LD) $(LD_FLAGS) /out:hotspot.exe $** diff --git a/hotspot/make/windows/makefiles/product.make b/hotspot/make/windows/makefiles/product.make index f166f7377bf..407484cd46e 100644 --- a/hotspot/make/windows/makefiles/product.make +++ b/hotspot/make/windows/makefiles/product.make @@ -32,7 +32,7 @@ GENERATED=../generated BUILD_PCH_FILE=_build_pch_file.obj !endif -default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA +default:: $(BUILD_PCH_FILE) $(AOUT) checkAndBuildSA !include ../local.make !include compile.make @@ -73,4 +73,3 @@ $(AOUT): $(Res_Files) $(Obj_Files) vm.def !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make -!include $(WorkSpace)/make/windows/makefiles/launcher.make diff --git a/hotspot/make/windows/makefiles/projectcreator.make b/hotspot/make/windows/makefiles/projectcreator.make index 68d098d0de3..f142852ed12 100644 --- a/hotspot/make/windows/makefiles/projectcreator.make +++ b/hotspot/make/windows/makefiles/projectcreator.make @@ -59,7 +59,6 @@ ProjectCreatorIncludesPRIVATE=\ -relativeSrcInclude src \ -absoluteSrcInclude $(HOTSPOTBUILDSPACE) \ -ignorePath $(HOTSPOTBUILDSPACE) \ - -ignorePath launcher \ -ignorePath share\vm\adlc \ -ignorePath share\vm\shark \ -ignorePath share\tools \ @@ -105,7 +104,6 @@ ProjectCreatorIDEOptions=\ -define ALIGN_STACK_FRAMES \ -define VM_LITTLE_ENDIAN \ -prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) set JAVA_HOME=$(HOTSPOTJDKDIST) $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LD_VER)" \ - -postbuild "" "Building hotspot.exe..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) nmake -f $(HOTSPOTWORKSPACE)\make\windows\projectfiles\common\Makefile LOCAL_MAKE=$(HOTSPOTBUILDSPACE)\%f\local.make JAVA_HOME=$(HOTSPOTJDKDIST) launcher" \ -ignoreFile jsig.c \ -ignoreFile jvmtiEnvRecommended.cpp \ -ignoreFile jvmtiEnvStub.cpp \ diff --git a/hotspot/make/windows/projectfiles/common/Makefile b/hotspot/make/windows/projectfiles/common/Makefile index 125923e67b2..5556aae5149 100644 --- a/hotspot/make/windows/projectfiles/common/Makefile +++ b/hotspot/make/windows/projectfiles/common/Makefile @@ -65,7 +65,6 @@ JvmtiOutDir=$(HOTSPOTBUILDSPACE)\$(Variant)\generated\jvmtifiles !endif HS_INTERNAL_NAME=jvm -!include $(HOTSPOTWORKSPACE)/make/windows/makefiles/launcher.make default:: $(AdditionalTargets) $(JvmtiGeneratedFiles) diff --git a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp index ee330c69fa3..35886ce8ea9 100644 --- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp @@ -74,7 +74,7 @@ define_pd_global(bool, RewriteFrequentPairs, true); define_pd_global(bool, UseMembar, false); // GC Ergo Flags -define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread +define_pd_global(uintx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \ \ diff --git a/hotspot/src/cpu/x86/vm/globals_x86.hpp b/hotspot/src/cpu/x86/vm/globals_x86.hpp index fb44e2db52f..978a1d6eece 100644 --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp @@ -77,7 +77,7 @@ define_pd_global(bool, UseMembar, false); #endif // GC Ergo Flags -define_pd_global(intx, CMSYoungGenPerWorker, 64*M); // default max size of CMS young gen, per GC worker thread +define_pd_global(uintx, CMSYoungGenPerWorker, 64*M); // default max size of CMS young gen, per GC worker thread #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \ \ diff --git a/hotspot/src/cpu/zero/vm/globals_zero.hpp b/hotspot/src/cpu/zero/vm/globals_zero.hpp index a3c7d244173..71b566fceb0 100644 --- a/hotspot/src/cpu/zero/vm/globals_zero.hpp +++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp @@ -55,7 +55,7 @@ define_pd_global(bool, RewriteFrequentPairs, true); define_pd_global(bool, UseMembar, true); // GC Ergo Flags -define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread +define_pd_global(uintx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) diff --git a/hotspot/src/os/posix/launcher/java_md.c b/hotspot/src/os/posix/launcher/java_md.c deleted file mode 100644 index b5fc949813c..00000000000 --- a/hotspot/src/os/posix/launcher/java_md.c +++ /dev/null @@ -1,1936 +0,0 @@ -/* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - - -#include "java.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef GAMMA -#include "manifest_info.h" -#include "version_comp.h" -#endif - -#if defined(__linux__) || defined(_ALLBSD_SOURCE) -#include -#else -#include -#endif - -#ifdef __APPLE__ -#define JVM_DLL "libjvm.dylib" -#define JAVA_DLL "libjava.dylib" -#define LD_LIBRARY_PATH "DYLD_LIBRARY_PATH" -#else -#define JVM_DLL "libjvm.so" -#define JAVA_DLL "libjava.so" -#define LD_LIBRARY_PATH "LD_LIBRARY_PATH" -#endif - -#ifndef GAMMA /* launcher.make defines ARCH */ -/* - * If a processor / os combination has the ability to run binaries of - * two data models and cohabitation of jre/jdk bits with both data - * models is supported, then DUAL_MODE is defined. When DUAL_MODE is - * defined, the architecture names for the narrow and wide version of - * the architecture are defined in LIBARCH64NAME and LIBARCH32NAME. Currently - * only Solaris on sparc/sparcv9 and i586/amd64 is DUAL_MODE; linux - * i586/amd64 could be defined as DUAL_MODE but that is not the - * current policy. - */ - -#ifndef LIBARCHNAME -# error "The macro LIBARCHNAME was not defined on the compile line" -#endif - -#ifdef __sun -# define DUAL_MODE -# ifndef LIBARCH32NAME -# error "The macro LIBARCH32NAME was not defined on the compile line" -# endif -# ifndef LIBARCH64NAME -# error "The macro LIBARCH64NAME was not defined on the compile line" -# endif -# include -# include -# include -#endif - -#endif /* ifndef GAMMA */ - -/* pointer to environment */ -extern char **environ; - -#ifndef GAMMA -/* - * A collection of useful strings. One should think of these as #define - * entries, but actual strings can be more efficient (with many compilers). - */ -#ifdef __linux__ -static const char *system_dir = "/usr/java"; -static const char *user_dir = "/java"; -#else /* Solaris */ -static const char *system_dir = "/usr/jdk"; -static const char *user_dir = "/jdk"; -#endif - -#endif /* ifndef GAMMA */ - -/* - * Flowchart of launcher execs and options processing on unix - * - * The selection of the proper vm shared library to open depends on - * several classes of command line options, including vm "flavor" - * options (-client, -server) and the data model options, -d32 and - * -d64, as well as a version specification which may have come from - * the command line or from the manifest of an executable jar file. - * The vm selection options are not passed to the running - * virtual machine; they must be screened out by the launcher. - * - * The version specification (if any) is processed first by the - * platform independent routine SelectVersion. This may result in - * the exec of the specified launcher version. - * - * Typically, the launcher execs at least once to ensure a suitable - * LD_LIBRARY_PATH is in effect for the process. The first exec - * screens out all the data model options; leaving the choice of data - * model implicit in the binary selected to run. However, in case no - * exec is done, the data model options are screened out before the vm - * is invoked. - * - * incoming argv ------------------------------ - * | | - * \|/ | - * CheckJVMType | - * (removes -client, -server, etc.) | - * \|/ - * CreateExecutionEnvironment - * (removes -d32 and -d64, - * determines desired data model, - * sets up LD_LIBRARY_PATH, - * and exec's) - * | - * -------------------------------------------- - * | - * \|/ - * exec child 1 incoming argv ----------------- - * | | - * \|/ | - * CheckJVMType | - * (removes -client, -server, etc.) | - * | \|/ - * | CreateExecutionEnvironment - * | (verifies desired data model - * | is running and acceptable - * | LD_LIBRARY_PATH; - * | no-op in child) - * | - * \|/ - * TranslateDashJArgs... - * (Prepare to pass args to vm) - * | - * | - * | - * \|/ - * ParseArguments - * (ignores -d32 and -d64, - * processes version options, - * creates argument list for vm, - * etc.) - * - */ - -static char *SetExecname(char **argv); -static char * GetExecname(); -static jboolean GetJVMPath(const char *jrepath, const char *jvmtype, - char *jvmpath, jint jvmpathsize, char * arch); -static jboolean GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative); - -#ifndef GAMMA -const char * -GetArch() -{ - return LIBARCHNAME; -} -#endif /* ifndef GAMMA */ - -void -CreateExecutionEnvironment(int *_argcp, - char ***_argvp, - char jrepath[], - jint so_jrepath, - char jvmpath[], - jint so_jvmpath, - char **original_argv) { - /* - * First, determine if we are running the desired data model. If we - * are running the desired data model, all the error messages - * associated with calling GetJREPath, ReadKnownVMs, etc. should be - * output. However, if we are not running the desired data model, - * some of the errors should be suppressed since it is more - * informative to issue an error message based on whether or not the - * os/processor combination has dual mode capabilities. - */ - - char *execname = NULL; - int original_argc = *_argcp; - jboolean jvmpathExists; - - /* Compute the name of the executable */ - execname = SetExecname(*_argvp); - -#ifndef GAMMA - /* Set the LD_LIBRARY_PATH environment variable, check data model - flags, and exec process, if needed */ - { - char *arch = (char *)GetArch(); /* like sparc or sparcv9 */ - char * jvmtype = NULL; - int argc = *_argcp; - char **argv = original_argv; - - char *runpath = NULL; /* existing effective LD_LIBRARY_PATH - setting */ - - int running = /* What data model is being ILP32 => - 32 bit vm; LP64 => 64 bit vm */ -#ifdef _LP64 - 64; -#else - 32; -#endif - - int wanted = running; /* What data mode is being - asked for? Current model is - fine unless another model - is asked for */ - - char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */ - char* newpath = NULL; /* path on new LD_LIBRARY_PATH */ - char* lastslash = NULL; - - char** newenvp = NULL; /* current environment */ - - char** newargv = NULL; - int newargc = 0; -#ifdef __sun - char* dmpath = NULL; /* data model specific LD_LIBRARY_PATH, - Solaris only */ -#endif - - /* - * Starting in 1.5, all unix platforms accept the -d32 and -d64 - * options. On platforms where only one data-model is supported - * (e.g. ia-64 Linux), using the flag for the other data model is - * an error and will terminate the program. - */ - - { /* open new scope to declare local variables */ - int i; - - newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(*newargv)); - newargv[newargc++] = argv[0]; - - /* scan for data model arguments and remove from argument list; - last occurrence determines desired data model */ - for (i=1; i < argc; i++) { - - if (strcmp(argv[i], "-J-d64") == 0 || strcmp(argv[i], "-d64") == 0) { - wanted = 64; - continue; - } - if (strcmp(argv[i], "-J-d32") == 0 || strcmp(argv[i], "-d32") == 0) { - wanted = 32; - continue; - } - newargv[newargc++] = argv[i]; - -#ifdef JAVA_ARGS - if (argv[i][0] != '-') - continue; -#else - if (strcmp(argv[i], "-classpath") == 0 || strcmp(argv[i], "-cp") == 0) { - i++; - if (i >= argc) break; - newargv[newargc++] = argv[i]; - continue; - } - if (argv[i][0] != '-') { i++; break; } -#endif - } - - /* copy rest of args [i .. argc) */ - while (i < argc) { - newargv[newargc++] = argv[i++]; - } - newargv[newargc] = NULL; - - /* - * newargv has all proper arguments here - */ - - argc = newargc; - argv = newargv; - } - - /* If the data model is not changing, it is an error if the - jvmpath does not exist */ - if (wanted == running) { - /* Find out where the JRE is that we will be using. */ - if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) { - fprintf(stderr, "Error: could not find Java 2 Runtime Environment.\n"); - exit(2); - } - - /* Find the specified JVM type */ - if (ReadKnownVMs(jrepath, arch, JNI_FALSE) < 1) { - fprintf(stderr, "Error: no known VMs. (check for corrupt jvm.cfg file)\n"); - exit(1); - } - - jvmpath[0] = '\0'; - jvmtype = CheckJvmType(_argcp, _argvp, JNI_FALSE); - - if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch )) { - fprintf(stderr, "Error: no `%s' JVM at `%s'.\n", jvmtype, jvmpath); - exit(4); - } - } else { /* do the same speculatively or exit */ -#ifdef DUAL_MODE - if (running != wanted) { - /* Find out where the JRE is that we will be using. */ - if (!GetJREPath(jrepath, so_jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE)) { - goto EndDataModelSpeculate; - } - - /* - * Read in jvm.cfg for target data model and process vm - * selection options. - */ - if (ReadKnownVMs(jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE) < 1) { - goto EndDataModelSpeculate; - } - jvmpath[0] = '\0'; - jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE); - /* exec child can do error checking on the existence of the path */ - jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, - ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME)); - - } - EndDataModelSpeculate: /* give up and let other code report error message */ - ; -#else - fprintf(stderr, "Running a %d-bit JVM is not supported on this platform.\n", wanted); - exit(1); -#endif - } - - /* - * We will set the LD_LIBRARY_PATH as follows: - * - * o $JVMPATH (directory portion only) - * o $JRE/lib/$LIBARCHNAME - * o $JRE/../lib/$LIBARCHNAME - * - * followed by the user's previous effective LD_LIBRARY_PATH, if - * any. - */ - -#ifdef __sun - /* - * Starting in Solaris 7, ld.so.1 supports three LD_LIBRARY_PATH - * variables: - * - * 1. LD_LIBRARY_PATH -- used for 32 and 64 bit searches if - * data-model specific variables are not set. - * - * 2. LD_LIBRARY_PATH_64 -- overrides and replaces LD_LIBRARY_PATH - * for 64-bit binaries. - * - * 3. LD_LIBRARY_PATH_32 -- overrides and replaces LD_LIBRARY_PATH - * for 32-bit binaries. - * - * The vm uses LD_LIBRARY_PATH to set the java.library.path system - * property. To shield the vm from the complication of multiple - * LD_LIBRARY_PATH variables, if the appropriate data model - * specific variable is set, we will act as if LD_LIBRARY_PATH had - * the value of the data model specific variant and the data model - * specific variant will be unset. Note that the variable for the - * *wanted* data model must be used (if it is set), not simply the - * current running data model. - */ - - switch(wanted) { - case 0: - if(running == 32) { - dmpath = getenv("LD_LIBRARY_PATH_32"); - wanted = 32; - } - else { - dmpath = getenv("LD_LIBRARY_PATH_64"); - wanted = 64; - } - break; - - case 32: - dmpath = getenv("LD_LIBRARY_PATH_32"); - break; - - case 64: - dmpath = getenv("LD_LIBRARY_PATH_64"); - break; - - default: - fprintf(stderr, "Improper value at line %d.", __LINE__); - exit(1); /* unknown value in wanted */ - break; - } - - /* - * If dmpath is NULL, the relevant data model specific variable is - * not set and normal LD_LIBRARY_PATH should be used. - */ - if( dmpath == NULL) { - runpath = getenv("LD_LIBRARY_PATH"); - } - else { - runpath = dmpath; - } -#else - /* - * If not on Solaris, assume only a single LD_LIBRARY_PATH - * variable. - */ - runpath = getenv(LD_LIBRARY_PATH); -#endif /* __sun */ - -#if defined(__linux__) - /* - * On linux, if a binary is running as sgid or suid, glibc sets - * LD_LIBRARY_PATH to the empty string for security purposes. (In - * contrast, on Solaris the LD_LIBRARY_PATH variable for a - * privileged binary does not lose its settings; but the dynamic - * linker does apply more scrutiny to the path.) The launcher uses - * the value of LD_LIBRARY_PATH to prevent an exec loop. - * Therefore, if we are running sgid or suid, this function's - * setting of LD_LIBRARY_PATH will be ineffective and we should - * return from the function now. Getting the right libraries to - * be found must be handled through other mechanisms. - */ - if((getgid() != getegid()) || (getuid() != geteuid()) ) { - return; - } -#elif defined(_ALLBSD_SOURCE) - /* - * On BSD, if a binary is running as sgid or suid, libc sets - * LD_LIBRARY_PATH to the empty string for security purposes. (In - * contrast, on Solaris the LD_LIBRARY_PATH variable for a - * privileged binary does not lose its settings; but the dynamic - * linker does apply more scrutiny to the path.) The launcher uses - * the value of LD_LIBRARY_PATH to prevent an exec loop. - * Therefore, if we are running sgid or suid, this function's - * setting of LD_LIBRARY_PATH will be ineffective and we should - * return from the function now. Getting the right libraries to - * be found must be handled through other mechanisms. - */ - if(issetugid()) { - return; - } -#endif - - /* runpath contains current effective LD_LIBRARY_PATH setting */ - - jvmpath = JLI_StringDup(jvmpath); - new_runpath = JLI_MemAlloc( ((runpath!=NULL)?strlen(runpath):0) + - 2*strlen(jrepath) + 2*strlen(arch) + - strlen(jvmpath) + 52); - newpath = new_runpath + strlen(LD_LIBRARY_PATH "="); - - - /* - * Create desired LD_LIBRARY_PATH value for target data model. - */ - { - /* remove the name of the .so from the JVM path */ - lastslash = strrchr(jvmpath, '/'); - if (lastslash) - *lastslash = '\0'; - - - /* jvmpath, ((running != wanted)?((wanted==64)?"/"LIBARCH64NAME:"/.."):""), */ - - sprintf(new_runpath, LD_LIBRARY_PATH "=" - "%s:" - "%s/lib/%s:" - "%s/../lib/%s", - jvmpath, -#ifdef DUAL_MODE - jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), - jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME) -#else - jrepath, arch, - jrepath, arch -#endif - ); - - - /* - * Check to make sure that the prefix of the current path is the - * desired environment variable setting. - */ - if (runpath != NULL && - strncmp(newpath, runpath, strlen(newpath))==0 && - (runpath[strlen(newpath)] == 0 || runpath[strlen(newpath)] == ':') && - (running == wanted) /* data model does not have to be changed */ -#ifdef __sun - && (dmpath == NULL) /* data model specific variables not set */ -#endif - ) { - - return; - - } - } - - /* - * Place the desired environment setting onto the prefix of - * LD_LIBRARY_PATH. Note that this prevents any possible infinite - * loop of execv() because we test for the prefix, above. - */ - if (runpath != 0) { - strcat(new_runpath, ":"); - strcat(new_runpath, runpath); - } - - if( putenv(new_runpath) != 0) { - exit(1); /* problem allocating memory; LD_LIBRARY_PATH not set - properly */ - } - - /* - * Unix systems document that they look at LD_LIBRARY_PATH only - * once at startup, so we have to re-exec the current executable - * to get the changed environment variable to have an effect. - */ - -#ifdef __sun - /* - * If dmpath is not NULL, remove the data model specific string - * in the environment for the exec'ed child. - */ - - if( dmpath != NULL) - (void)UnsetEnv((wanted==32)?"LD_LIBRARY_PATH_32":"LD_LIBRARY_PATH_64"); -#endif - - newenvp = environ; - - { - char *newexec = execname; -#ifdef DUAL_MODE - /* - * If the data model is being changed, the path to the - * executable must be updated accordingly; the executable name - * and directory the executable resides in are separate. In the - * case of 32 => 64, the new bits are assumed to reside in, e.g. - * "olddir/LIBARCH64NAME/execname"; in the case of 64 => 32, - * the bits are assumed to be in "olddir/../execname". For example, - * - * olddir/sparcv9/execname - * olddir/amd64/execname - * - * for Solaris SPARC and Linux amd64, respectively. - */ - - if (running != wanted) { - char *oldexec = strcpy(JLI_MemAlloc(strlen(execname) + 1), execname); - char *olddir = oldexec; - char *oldbase = strrchr(oldexec, '/'); - - - newexec = JLI_MemAlloc(strlen(execname) + 20); - *oldbase++ = 0; - sprintf(newexec, "%s/%s/%s", olddir, - ((wanted==64) ? LIBARCH64NAME : ".."), oldbase); - argv[0] = newexec; - } -#endif - - (void)fflush(stdout); - (void)fflush(stderr); - execve(newexec, argv, newenvp); - perror("execve()"); - - fprintf(stderr, "Error trying to exec %s.\n", newexec); - fprintf(stderr, "Check if file exists and permissions are set correctly.\n"); - -#ifdef DUAL_MODE - if (running != wanted) { - fprintf(stderr, "Failed to start a %d-bit JVM process from a %d-bit JVM.\n", - wanted, running); -# ifdef __sun - -# ifdef __sparc - fprintf(stderr, "Verify all necessary J2SE components have been installed.\n" ); - fprintf(stderr, - "(Solaris SPARC 64-bit components must be installed after 32-bit components.)\n" ); -# else - fprintf(stderr, "Either 64-bit processes are not supported by this platform\n"); - fprintf(stderr, "or the 64-bit components have not been installed.\n"); -# endif - } -# endif -#endif - - } - - exit(1); - } - -#else /* ifndef GAMMA */ - - /* - * gamma launcher is simpler in that it doesn't handle VM flavors, data - * model, LD_LIBRARY_PATH, etc. Assuming everything is set-up correctly - * all we need to do here is to return correct path names. See also - * GetJVMPath() and GetApplicationHome(). - */ - - { char *arch = (char *) ARCH; /* like sparc or sparcv9 */ - char *p; - - if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) { - fprintf(stderr, "Error: could not find Java 2 Runtime Environment.\n"); - exit(2); - } - - if (!GetJVMPath(jrepath, NULL, jvmpath, so_jvmpath, arch )) { - fprintf(stderr, "Error: no JVM at `%s'.\n", jvmpath); - exit(4); - } - } - -#endif /* ifndef GAMMA */ -} - - -/* - * On Solaris VM choosing is done by the launcher (java.c). - */ -static jboolean -GetJVMPath(const char *jrepath, const char *jvmtype, - char *jvmpath, jint jvmpathsize, char * arch) -{ - struct stat s; - -#ifndef GAMMA - if (strchr(jvmtype, '/')) { - sprintf(jvmpath, "%s/" JVM_DLL, jvmtype); - } else { - sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype); - } -#else - /* - * For gamma launcher, JVM is either built-in or in the same directory. - * Either way we return "/libjvm.so" where is the - * directory where gamma launcher is located. - */ - - char *p; - - snprintf(jvmpath, jvmpathsize, "%s", GetExecname()); - p = strrchr(jvmpath, '/'); - if (p) { - /* replace executable name with libjvm.so */ - snprintf(p + 1, jvmpathsize - (p + 1 - jvmpath), "%s", JVM_DLL); - } else { - /* this case shouldn't happen */ - snprintf(jvmpath, jvmpathsize, "%s", JVM_DLL); - } -#endif /* ifndef GAMMA */ - - if (_launcher_debug) - printf("Does `%s' exist ... ", jvmpath); - - if (stat(jvmpath, &s) == 0) { - if (_launcher_debug) - printf("yes.\n"); - return JNI_TRUE; - } else { - if (_launcher_debug) - printf("no.\n"); - return JNI_FALSE; - } -} - -/* - * Find path to JRE based on .exe's location or registry settings. - */ -static jboolean -GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative) -{ - char libjava[MAXPATHLEN]; - - if (GetApplicationHome(path, pathsize)) { - - /* Is the JRE universal, i.e. no arch dir? */ - sprintf(libjava, "%s/jre/lib/" JAVA_DLL, path); - if (access(libjava, F_OK) == 0) { - strcat(path, "/jre"); - goto found; - } - - /* Is JRE co-located with the application? */ - sprintf(libjava, "%s/lib/%s/" JAVA_DLL, path, arch); - if (access(libjava, F_OK) == 0) { - goto found; - } - - /* Does the app ship a private JRE in /jre directory? */ - sprintf(libjava, "%s/jre/lib/%s/" JAVA_DLL, path, arch); - if (access(libjava, F_OK) == 0) { - strcat(path, "/jre"); - goto found; - } - } - - if (!speculative) - fprintf(stderr, "Error: could not find " JAVA_DLL "\n"); - return JNI_FALSE; - - found: - if (_launcher_debug) - printf("JRE path is %s\n", path); - return JNI_TRUE; -} - -jboolean -LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn) -{ -#ifdef GAMMA - /* JVM is directly linked with gamma launcher; no dlopen() */ - ifn->CreateJavaVM = JNI_CreateJavaVM; - ifn->GetDefaultJavaVMInitArgs = JNI_GetDefaultJavaVMInitArgs; - return JNI_TRUE; -#else - Dl_info dlinfo; - void *libjvm; - - if (_launcher_debug) { - printf("JVM path is %s\n", jvmpath); - } - - libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL); - if (libjvm == NULL) { -#if defined(__sparc) && !defined(_LP64) /* i.e. 32-bit sparc */ - FILE * fp; - Elf32_Ehdr elf_head; - int count; - int location; - - fp = fopen(jvmpath, "r"); - if(fp == NULL) - goto error; - - /* read in elf header */ - count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp); - fclose(fp); - if(count < 1) - goto error; - - /* - * Check for running a server vm (compiled with -xarch=v8plus) - * on a stock v8 processor. In this case, the machine type in - * the elf header would not be included the architecture list - * provided by the isalist command, which is turn is gotten from - * sysinfo. This case cannot occur on 64-bit hardware and thus - * does not have to be checked for in binaries with an LP64 data - * model. - */ - if(elf_head.e_machine == EM_SPARC32PLUS) { - char buf[257]; /* recommended buffer size from sysinfo man - page */ - long length; - char* location; - - length = sysinfo(SI_ISALIST, buf, 257); - if(length > 0) { - location = strstr(buf, "sparcv8plus "); - if(location == NULL) { - fprintf(stderr, "SPARC V8 processor detected; Server compiler requires V9 or better.\n"); - fprintf(stderr, "Use Client compiler on V8 processors.\n"); - fprintf(stderr, "Could not create the Java virtual machine.\n"); - return JNI_FALSE; - } - } - } -#endif - fprintf(stderr, "dl failure on line %d", __LINE__); - goto error; - } - - ifn->CreateJavaVM = (CreateJavaVM_t) - dlsym(libjvm, "JNI_CreateJavaVM"); - if (ifn->CreateJavaVM == NULL) - goto error; - - ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t) - dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs"); - if (ifn->GetDefaultJavaVMInitArgs == NULL) - goto error; - - return JNI_TRUE; - -error: - fprintf(stderr, "Error: failed %s, because %s\n", jvmpath, dlerror()); - return JNI_FALSE; -#endif /* ifndef GAMMA */ -} - -/* - * If app is "/foo/bin/javac", or "/foo/bin/sparcv9/javac" then put - * "/foo" into buf. - */ -jboolean -GetApplicationHome(char *buf, jint bufsize) -{ -#if defined(__linux__) || defined(_ALLBSD_SOURCE) - char *execname = GetExecname(); - if (execname) { - strncpy(buf, execname, bufsize-1); - buf[bufsize-1] = '\0'; - } else { - return JNI_FALSE; - } -#else - Dl_info dlinfo; - - dladdr((void *)GetApplicationHome, &dlinfo); - if (realpath(dlinfo.dli_fname, buf) == NULL) { - fprintf(stderr, "Error: realpath(`%s') failed.\n", dlinfo.dli_fname); - return JNI_FALSE; - } -#endif - -#ifdef GAMMA - { - /* gamma launcher uses JAVA_HOME environment variable to find JDK/JRE */ - char* java_home_var = getenv("JAVA_HOME"); - if (java_home_var == NULL) { - printf("JAVA_HOME must point to a valid JDK/JRE to run gamma\n"); - return JNI_FALSE; - } - snprintf(buf, bufsize, "%s", java_home_var); - } -#else - if (strrchr(buf, '/') == 0) { - buf[0] = '\0'; - return JNI_FALSE; - } - *(strrchr(buf, '/')) = '\0'; /* executable file */ - if (strlen(buf) < 4 || strrchr(buf, '/') == 0) { - buf[0] = '\0'; - return JNI_FALSE; - } - if (strcmp("/bin", buf + strlen(buf) - 4) != 0) - *(strrchr(buf, '/')) = '\0'; /* sparcv9 or amd64 */ - if (strlen(buf) < 4 || strcmp("/bin", buf + strlen(buf) - 4) != 0) { - buf[0] = '\0'; - return JNI_FALSE; - } - *(strrchr(buf, '/')) = '\0'; /* bin */ -#endif /* ifndef GAMMA */ - - return JNI_TRUE; -} - - -/* - * Return true if the named program exists - */ -static int -ProgramExists(char *name) -{ - struct stat sb; - if (stat(name, &sb) != 0) return 0; - if (S_ISDIR(sb.st_mode)) return 0; - return (sb.st_mode & S_IEXEC) != 0; -} - - -/* - * Find a command in a directory, returning the path. - */ -static char * -Resolve(char *indir, char *cmd) -{ - char name[PATH_MAX + 2], *real; - - if ((strlen(indir) + strlen(cmd) + 1) > PATH_MAX) return 0; - sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd); - if (!ProgramExists(name)) return 0; - real = JLI_MemAlloc(PATH_MAX + 2); - if (!realpath(name, real)) - strcpy(real, name); - return real; -} - - -/* - * Find a path for the executable - */ -static char * -FindExecName(char *program) -{ - char cwdbuf[PATH_MAX+2]; - char *path; - char *tmp_path; - char *f; - char *result = NULL; - - /* absolute path? */ - if (*program == FILE_SEPARATOR || - (FILE_SEPARATOR=='\\' && strrchr(program, ':'))) - return Resolve("", program+1); - - /* relative path? */ - if (strrchr(program, FILE_SEPARATOR) != 0) { - char buf[PATH_MAX+2]; - return Resolve(getcwd(cwdbuf, sizeof(cwdbuf)), program); - } - - /* from search path? */ - path = getenv("PATH"); - if (!path || !*path) path = "."; - tmp_path = JLI_MemAlloc(strlen(path) + 2); - strcpy(tmp_path, path); - - for (f=tmp_path; *f && result==0; ) { - char *s = f; - while (*f && (*f != PATH_SEPARATOR)) ++f; - if (*f) *f++ = 0; - if (*s == FILE_SEPARATOR) - result = Resolve(s, program); - else { - /* relative path element */ - char dir[2*PATH_MAX]; - sprintf(dir, "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)), - FILE_SEPARATOR, s); - result = Resolve(dir, program); - } - if (result != 0) break; - } - - JLI_MemFree(tmp_path); - return result; -} - - -/* Store the name of the executable once computed */ -static char *execname = NULL; - -/* - * Compute the name of the executable - * - * In order to re-exec securely we need the absolute path of the - * executable. On Solaris getexecname(3c) may not return an absolute - * path so we use dladdr to get the filename of the executable and - * then use realpath to derive an absolute path. From Solaris 9 - * onwards the filename returned in DL_info structure from dladdr is - * an absolute pathname so technically realpath isn't required. - * On Linux we read the executable name from /proc/self/exe. - * As a fallback, and for platforms other than Solaris and Linux, - * we use FindExecName to compute the executable name. - */ -static char * -SetExecname(char **argv) -{ - char* exec_path = NULL; - - if (execname != NULL) /* Already determined */ - return (execname); - -#if defined(__sun) - { - Dl_info dlinfo; - if (dladdr((void*)&SetExecname, &dlinfo)) { - char *resolved = (char*)JLI_MemAlloc(PATH_MAX+1); - if (resolved != NULL) { - exec_path = realpath(dlinfo.dli_fname, resolved); - if (exec_path == NULL) { - JLI_MemFree(resolved); - } - } - } - } -#elif defined(__linux__) - { - const char* self = "/proc/self/exe"; - char buf[PATH_MAX+1]; - int len = readlink(self, buf, PATH_MAX); - if (len >= 0) { - buf[len] = '\0'; /* readlink doesn't nul terminate */ - exec_path = JLI_StringDup(buf); - } - } -#else /* !__sun && !__linux */ - { - /* Not implemented */ - } -#endif - - if (exec_path == NULL) { - exec_path = FindExecName(argv[0]); - } - execname = exec_path; - return exec_path; -} - -/* - * Return the name of the executable. Used in java_md.c to find the JRE area. - */ -static char * -GetExecname() { - return execname; -} - -void ReportErrorMessage(char * message, jboolean always) { - if (always) { - fprintf(stderr, "%s\n", message); - } -} - -void ReportErrorMessage2(char * format, char * string, jboolean always) { - if (always) { - fprintf(stderr, format, string); - fprintf(stderr, "\n"); - } -} - -void ReportExceptionDescription(JNIEnv * env) { - (*env)->ExceptionDescribe(env); -} - -/* - * Return JNI_TRUE for an option string that has no effect but should - * _not_ be passed on to the vm; return JNI_FALSE otherwise. On - * Solaris SPARC, this screening needs to be done if: - * 1) LD_LIBRARY_PATH does _not_ need to be reset and - * 2) -d32 or -d64 is passed to a binary with a matching data model - * (the exec in SetLibraryPath removes -d options and points the - * exec to the proper binary). When this exec is not done, these options - * would end up getting passed onto the vm. - */ -jboolean RemovableMachineDependentOption(char * option) { - /* - * Unconditionally remove both -d32 and -d64 options since only - * the last such options has an effect; e.g. - * java -d32 -d64 -d32 -version - * is equivalent to - * java -d32 -version - */ - - if( (strcmp(option, "-d32") == 0 ) || - (strcmp(option, "-d64") == 0 )) - return JNI_TRUE; - else - return JNI_FALSE; -} - -void PrintMachineDependentOptions() { - fprintf(stdout, - " -d32 use a 32-bit data model if available\n" - "\n" - " -d64 use a 64-bit data model if available\n"); - return; -} - -#ifndef GAMMA -/* - * The following methods (down to ServerClassMachine()) answer - * the question about whether a machine is a "server-class" - * machine. A server-class machine is loosely defined as one - * with 2 or more processors and 2 gigabytes or more physical - * memory. The definition of a processor is a physical package, - * not a hyperthreaded chip masquerading as a multi-processor. - * The definition of memory is also somewhat fuzzy, since x86 - * machines seem not to report all the memory in their DIMMs, we - * think because of memory mapping of graphics cards, etc. - * - * This code is somewhat more confused with #ifdef's than we'd - * like because this file is used by both Solaris and Linux - * platforms, and so needs to be parameterized for SPARC and - * i586 hardware. The other Linux platforms (amd64 and ia64) - * don't even ask this question, because they only come with - * server JVMs. */ - -# define KB (1024UL) -# define MB (1024UL * KB) -# define GB (1024UL * MB) - -/* Compute physical memory by asking the OS */ -uint64_t -physical_memory(void) { - const uint64_t pages = (uint64_t) sysconf(_SC_PHYS_PAGES); - const uint64_t page_size = (uint64_t) sysconf(_SC_PAGESIZE); - const uint64_t result = pages * page_size; -# define UINT64_FORMAT "%" PRIu64 - - if (_launcher_debug) { - printf("pages: " UINT64_FORMAT - " page_size: " UINT64_FORMAT - " physical memory: " UINT64_FORMAT " (%.3fGB)\n", - pages, page_size, result, result / (double) GB); - } - return result; -} - -#if defined(__sun) && defined(__sparc) - -/* Methods for solaris-sparc: these are easy. */ - -/* Ask the OS how many processors there are. */ -unsigned long -physical_processors(void) { - const unsigned long sys_processors = sysconf(_SC_NPROCESSORS_CONF); - - if (_launcher_debug) { - printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors); - } - return sys_processors; -} - -/* The solaris-sparc version of the "server-class" predicate. */ -jboolean -solaris_sparc_ServerClassMachine(void) { - jboolean result = JNI_FALSE; - /* How big is a server class machine? */ - const unsigned long server_processors = 2UL; - const uint64_t server_memory = 2UL * GB; - const uint64_t actual_memory = physical_memory(); - - /* Is this a server class machine? */ - if (actual_memory >= server_memory) { - const unsigned long actual_processors = physical_processors(); - if (actual_processors >= server_processors) { - result = JNI_TRUE; - } - } - if (_launcher_debug) { - printf("solaris_" LIBARCHNAME "_ServerClassMachine: %s\n", - (result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE")); - } - return result; -} - -#endif /* __sun && __sparc */ - -#if defined(__sun) && defined(i586) - -/* - * A utility method for asking the CPU about itself. - * There's a corresponding version of linux-i586 - * because the compilers are different. - */ -void -get_cpuid(uint32_t arg, - uint32_t* eaxp, - uint32_t* ebxp, - uint32_t* ecxp, - uint32_t* edxp) { -#ifdef _LP64 - asm( - /* rbx is a callee-saved register */ - " movq %rbx, %r11 \n" - /* rdx and rcx are 3rd and 4th argument registers */ - " movq %rdx, %r10 \n" - " movq %rcx, %r9 \n" - " movl %edi, %eax \n" - " cpuid \n" - " movl %eax, (%rsi)\n" - " movl %ebx, (%r10)\n" - " movl %ecx, (%r9) \n" - " movl %edx, (%r8) \n" - /* Restore rbx */ - " movq %r11, %rbx"); -#else - /* EBX is a callee-saved register */ - asm(" pushl %ebx"); - /* Need ESI for storing through arguments */ - asm(" pushl %esi"); - asm(" movl 8(%ebp), %eax \n" - " cpuid \n" - " movl 12(%ebp), %esi \n" - " movl %eax, (%esi) \n" - " movl 16(%ebp), %esi \n" - " movl %ebx, (%esi) \n" - " movl 20(%ebp), %esi \n" - " movl %ecx, (%esi) \n" - " movl 24(%ebp), %esi \n" - " movl %edx, (%esi) "); - /* Restore ESI and EBX */ - asm(" popl %esi"); - /* Restore EBX */ - asm(" popl %ebx"); -#endif -} - -#endif /* __sun && i586 */ - -#if (defined(__linux__) || defined(_ALLBSD_SOURCE)) && defined(i586) - -/* - * A utility method for asking the CPU about itself. - * There's a corresponding version of solaris-i586 - * because the compilers are different. - */ -void -get_cpuid(uint32_t arg, - uint32_t* eaxp, - uint32_t* ebxp, - uint32_t* ecxp, - uint32_t* edxp) { -#ifdef _LP64 - __asm__ volatile (/* Instructions */ - " movl %4, %%eax \n" - " cpuid \n" - " movl %%eax, (%0)\n" - " movl %%ebx, (%1)\n" - " movl %%ecx, (%2)\n" - " movl %%edx, (%3)\n" - : /* Outputs */ - : /* Inputs */ - "r" (eaxp), - "r" (ebxp), - "r" (ecxp), - "r" (edxp), - "r" (arg) - : /* Clobbers */ - "%rax", "%rbx", "%rcx", "%rdx", "memory" - ); -#else - uint32_t value_of_eax = 0; - uint32_t value_of_ebx = 0; - uint32_t value_of_ecx = 0; - uint32_t value_of_edx = 0; - __asm__ volatile (/* Instructions */ - /* ebx is callee-save, so push it */ - " pushl %%ebx \n" - " movl %4, %%eax \n" - " cpuid \n" - " movl %%eax, %0 \n" - " movl %%ebx, %1 \n" - " movl %%ecx, %2 \n" - " movl %%edx, %3 \n" - /* restore ebx */ - " popl %%ebx \n" - - : /* Outputs */ - "=m" (value_of_eax), - "=m" (value_of_ebx), - "=m" (value_of_ecx), - "=m" (value_of_edx) - : /* Inputs */ - "m" (arg) - : /* Clobbers */ - "%eax", "%ecx", "%edx" - ); - *eaxp = value_of_eax; - *ebxp = value_of_ebx; - *ecxp = value_of_ecx; - *edxp = value_of_edx; -#endif -} - -#endif /* __linux__ && i586 */ - -#ifdef i586 -/* - * Routines shared by solaris-i586 and linux-i586. - */ - -enum HyperThreadingSupport_enum { - hts_supported = 1, - hts_too_soon_to_tell = 0, - hts_not_supported = -1, - hts_not_pentium4 = -2, - hts_not_intel = -3 -}; -typedef enum HyperThreadingSupport_enum HyperThreadingSupport; - -/* Determine if hyperthreading is supported */ -HyperThreadingSupport -hyperthreading_support(void) { - HyperThreadingSupport result = hts_too_soon_to_tell; - /* Bits 11 through 8 is family processor id */ -# define FAMILY_ID_SHIFT 8 -# define FAMILY_ID_MASK 0xf - /* Bits 23 through 20 is extended family processor id */ -# define EXT_FAMILY_ID_SHIFT 20 -# define EXT_FAMILY_ID_MASK 0xf - /* Pentium 4 family processor id */ -# define PENTIUM4_FAMILY_ID 0xf - /* Bit 28 indicates Hyper-Threading Technology support */ -# define HT_BIT_SHIFT 28 -# define HT_BIT_MASK 1 - uint32_t vendor_id[3] = { 0U, 0U, 0U }; - uint32_t value_of_eax = 0U; - uint32_t value_of_edx = 0U; - uint32_t dummy = 0U; - - /* Yes, this is supposed to be [0], [2], [1] */ - get_cpuid(0, &dummy, &vendor_id[0], &vendor_id[2], &vendor_id[1]); - if (_launcher_debug) { - printf("vendor: %c %c %c %c %c %c %c %c %c %c %c %c \n", - ((vendor_id[0] >> 0) & 0xff), - ((vendor_id[0] >> 8) & 0xff), - ((vendor_id[0] >> 16) & 0xff), - ((vendor_id[0] >> 24) & 0xff), - ((vendor_id[1] >> 0) & 0xff), - ((vendor_id[1] >> 8) & 0xff), - ((vendor_id[1] >> 16) & 0xff), - ((vendor_id[1] >> 24) & 0xff), - ((vendor_id[2] >> 0) & 0xff), - ((vendor_id[2] >> 8) & 0xff), - ((vendor_id[2] >> 16) & 0xff), - ((vendor_id[2] >> 24) & 0xff)); - } - get_cpuid(1, &value_of_eax, &dummy, &dummy, &value_of_edx); - if (_launcher_debug) { - printf("value_of_eax: 0x%x value_of_edx: 0x%x\n", - value_of_eax, value_of_edx); - } - if ((((value_of_eax >> FAMILY_ID_SHIFT) & FAMILY_ID_MASK) == PENTIUM4_FAMILY_ID) || - (((value_of_eax >> EXT_FAMILY_ID_SHIFT) & EXT_FAMILY_ID_MASK) != 0)) { - if ((((vendor_id[0] >> 0) & 0xff) == 'G') && - (((vendor_id[0] >> 8) & 0xff) == 'e') && - (((vendor_id[0] >> 16) & 0xff) == 'n') && - (((vendor_id[0] >> 24) & 0xff) == 'u') && - (((vendor_id[1] >> 0) & 0xff) == 'i') && - (((vendor_id[1] >> 8) & 0xff) == 'n') && - (((vendor_id[1] >> 16) & 0xff) == 'e') && - (((vendor_id[1] >> 24) & 0xff) == 'I') && - (((vendor_id[2] >> 0) & 0xff) == 'n') && - (((vendor_id[2] >> 8) & 0xff) == 't') && - (((vendor_id[2] >> 16) & 0xff) == 'e') && - (((vendor_id[2] >> 24) & 0xff) == 'l')) { - if (((value_of_edx >> HT_BIT_SHIFT) & HT_BIT_MASK) == HT_BIT_MASK) { - if (_launcher_debug) { - printf("Hyperthreading supported\n"); - } - result = hts_supported; - } else { - if (_launcher_debug) { - printf("Hyperthreading not supported\n"); - } - result = hts_not_supported; - } - } else { - if (_launcher_debug) { - printf("Not GenuineIntel\n"); - } - result = hts_not_intel; - } - } else { - if (_launcher_debug) { - printf("not Pentium 4 or extended\n"); - } - result = hts_not_pentium4; - } - return result; -} - -/* Determine how many logical processors there are per CPU */ -unsigned int -logical_processors_per_package(void) { - /* - * After CPUID with EAX==1, register EBX bits 23 through 16 - * indicate the number of logical processors per package - */ -# define NUM_LOGICAL_SHIFT 16 -# define NUM_LOGICAL_MASK 0xff - unsigned int result = 1U; - const HyperThreadingSupport hyperthreading = hyperthreading_support(); - - if (hyperthreading == hts_supported) { - uint32_t value_of_ebx = 0U; - uint32_t dummy = 0U; - - get_cpuid(1, &dummy, &value_of_ebx, &dummy, &dummy); - result = (value_of_ebx >> NUM_LOGICAL_SHIFT) & NUM_LOGICAL_MASK; - if (_launcher_debug) { - printf("logical processors per package: %u\n", result); - } - } - return result; -} - -/* Compute the number of physical processors, not logical processors */ -unsigned long -physical_processors(void) { - const long sys_processors = sysconf(_SC_NPROCESSORS_CONF); - unsigned long result = sys_processors; - - if (_launcher_debug) { - printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors); - } - if (sys_processors > 1) { - unsigned int logical_processors = logical_processors_per_package(); - if (logical_processors > 1) { - result = (unsigned long) sys_processors / logical_processors; - } - } - if (_launcher_debug) { - printf("physical processors: %lu\n", result); - } - return result; -} - -#endif /* i586 */ - -#if defined(__sun) && defined(i586) - -/* The definition of a server-class machine for solaris-i586/amd64 */ -jboolean -solaris_i586_ServerClassMachine(void) { - jboolean result = JNI_FALSE; - /* How big is a server class machine? */ - const unsigned long server_processors = 2UL; - const uint64_t server_memory = 2UL * GB; - /* - * We seem not to get our full complement of memory. - * We allow some part (1/8?) of the memory to be "missing", - * based on the sizes of DIMMs, and maybe graphics cards. - */ - const uint64_t missing_memory = 256UL * MB; - const uint64_t actual_memory = physical_memory(); - - /* Is this a server class machine? */ - if (actual_memory >= (server_memory - missing_memory)) { - const unsigned long actual_processors = physical_processors(); - if (actual_processors >= server_processors) { - result = JNI_TRUE; - } - } - if (_launcher_debug) { - printf("solaris_" LIBARCHNAME "_ServerClassMachine: %s\n", - (result == JNI_TRUE ? "true" : "false")); - } - return result; -} - -#endif /* __sun && i586 */ - -#if defined(__linux__) && defined(i586) - -/* The definition of a server-class machine for linux-i586 */ -jboolean -linux_i586_ServerClassMachine(void) { - jboolean result = JNI_FALSE; - /* How big is a server class machine? */ - const unsigned long server_processors = 2UL; - const uint64_t server_memory = 2UL * GB; - /* - * We seem not to get our full complement of memory. - * We allow some part (1/8?) of the memory to be "missing", - * based on the sizes of DIMMs, and maybe graphics cards. - */ - const uint64_t missing_memory = 256UL * MB; - const uint64_t actual_memory = physical_memory(); - - /* Is this a server class machine? */ - if (actual_memory >= (server_memory - missing_memory)) { - const unsigned long actual_processors = physical_processors(); - if (actual_processors >= server_processors) { - result = JNI_TRUE; - } - } - if (_launcher_debug) { - printf("linux_" LIBARCHNAME "_ServerClassMachine: %s\n", - (result == JNI_TRUE ? "true" : "false")); - } - return result; -} - -#endif /* __linux__ && i586 */ - -#if defined(_ALLBSD_SOURCE) && defined(i586) - -/* The definition of a server-class machine for bsd-i586 */ -jboolean -bsd_i586_ServerClassMachine(void) { - jboolean result = JNI_FALSE; - /* How big is a server class machine? */ - const unsigned long server_processors = 2UL; - const uint64_t server_memory = 2UL * GB; - /* - * We seem not to get our full complement of memory. - * We allow some part (1/8?) of the memory to be "missing", - * based on the sizes of DIMMs, and maybe graphics cards. - */ - const uint64_t missing_memory = 256UL * MB; - const uint64_t actual_memory = physical_memory(); - - /* Is this a server class machine? */ - if (actual_memory >= (server_memory - missing_memory)) { - const unsigned long actual_processors = physical_processors(); - if (actual_processors >= server_processors) { - result = JNI_TRUE; - } - } - if (_launcher_debug) { - printf("linux_" LIBARCHNAME "_ServerClassMachine: %s\n", - (result == JNI_TRUE ? "true" : "false")); - } - return result; -} - -#endif /* _ALLBSD_SOURCE && i586 */ - -/* Dispatch to the platform-specific definition of "server-class" */ -jboolean -ServerClassMachine(void) { - jboolean result = JNI_FALSE; -#if defined(NEVER_ACT_AS_SERVER_CLASS_MACHINE) - result = JNI_FALSE; -#elif defined(ALWAYS_ACT_AS_SERVER_CLASS_MACHINE) - result = JNI_TRUE; -#elif defined(__sun) && defined(__sparc) - result = solaris_sparc_ServerClassMachine(); -#elif defined(__sun) && defined(i586) - result = solaris_i586_ServerClassMachine(); -#elif defined(__linux__) && defined(i586) - result = linux_i586_ServerClassMachine(); -#elif defined(_ALLBSD_SOURCE) && defined(i586) - result = bsd_i586_ServerClassMachine(); -#else - if (_launcher_debug) { - printf("ServerClassMachine: returns default value of %s\n", - (result == JNI_TRUE ? "true" : "false")); - } -#endif - return result; -} - -/* - * Since using the file system as a registry is a bit risky, perform - * additional sanity checks on the identified directory to validate - * it as a valid jre/sdk. - * - * Return 0 if the tests fail; otherwise return non-zero (true). - * - * Note that checking for anything more than the existence of an - * executable object at bin/java relative to the path being checked - * will break the regression tests. - */ -static int -CheckSanity(char *path, char *dir) -{ - char buffer[PATH_MAX]; - - if (strlen(path) + strlen(dir) + 11 > PATH_MAX) - return (0); /* Silently reject "impossibly" long paths */ - - (void)strcat(strcat(strcat(strcpy(buffer, path), "/"), dir), "/bin/java"); - return ((access(buffer, X_OK) == 0) ? 1 : 0); -} - -/* - * Determine if there is an acceptable JRE in the directory dirname. - * Upon locating the "best" one, return a fully qualified path to - * it. "Best" is defined as the most advanced JRE meeting the - * constraints contained in the manifest_info. If no JRE in this - * directory meets the constraints, return NULL. - * - * Note that we don't check for errors in reading the directory - * (which would be done by checking errno). This is because it - * doesn't matter if we get an error reading the directory, or - * we just don't find anything interesting in the directory. We - * just return NULL in either case. - * - * The historical names of j2sdk and j2re were changed to jdk and - * jre respecively as part of the 1.5 rebranding effort. Since the - * former names are legacy on Linux, they must be recognized for - * all time. Fortunately, this is a minor cost. - */ -static char -*ProcessDir(manifest_info *info, char *dirname) -{ - DIR *dirp; - struct dirent *dp; - char *best = NULL; - int offset; - int best_offset = 0; - char *ret_str = NULL; - char buffer[PATH_MAX]; - - if ((dirp = opendir(dirname)) == NULL) - return (NULL); - - do { - if ((dp = readdir(dirp)) != NULL) { - offset = 0; - if ((strncmp(dp->d_name, "jre", 3) == 0) || - (strncmp(dp->d_name, "jdk", 3) == 0)) - offset = 3; - else if (strncmp(dp->d_name, "j2re", 4) == 0) - offset = 4; - else if (strncmp(dp->d_name, "j2sdk", 5) == 0) - offset = 5; - if (offset > 0) { - if ((JLI_AcceptableRelease(dp->d_name + offset, - info->jre_version)) && CheckSanity(dirname, dp->d_name)) - if ((best == NULL) || (JLI_ExactVersionId( - dp->d_name + offset, best + best_offset) > 0)) { - if (best != NULL) - JLI_MemFree(best); - best = JLI_StringDup(dp->d_name); - best_offset = offset; - } - } - } - } while (dp != NULL); - (void) closedir(dirp); - if (best == NULL) - return (NULL); - else { - ret_str = JLI_MemAlloc(strlen(dirname) + strlen(best) + 2); - ret_str = strcat(strcat(strcpy(ret_str, dirname), "/"), best); - JLI_MemFree(best); - return (ret_str); - } -} - -/* - * This is the global entry point. It examines the host for the optimal - * JRE to be used by scanning a set of directories. The set of directories - * is platform dependent and can be overridden by the environment - * variable JAVA_VERSION_PATH. - * - * This routine itself simply determines the set of appropriate - * directories before passing control onto ProcessDir(). - */ -char* -LocateJRE(manifest_info* info) -{ - char *path; - char *home; - char *target = NULL; - char *dp; - char *cp; - - /* - * Start by getting JAVA_VERSION_PATH - */ - if (info->jre_restrict_search) - path = JLI_StringDup(system_dir); - else if ((path = getenv("JAVA_VERSION_PATH")) != NULL) - path = JLI_StringDup(path); - else - if ((home = getenv("HOME")) != NULL) { - path = (char *)JLI_MemAlloc(strlen(home) + strlen(system_dir) + - strlen(user_dir) + 2); - path = strcat(strcat(strcat(strcpy(path, home), - user_dir), ":"), system_dir); - } else - path = JLI_StringDup(system_dir); - - /* - * Step through each directory on the path. Terminate the scan with - * the first directory with an acceptable JRE. - */ - cp = dp = path; - while (dp != NULL) { - cp = strchr(dp, (int)':'); - if (cp != NULL) - *cp = (char)NULL; - if ((target = ProcessDir(info, dp)) != NULL) - break; - dp = cp; - if (dp != NULL) - dp++; - } - JLI_MemFree(path); - return (target); -} - -/* - * Given a path to a jre to execute, this routine checks if this process - * is indeed that jre. If not, it exec's that jre. - * - * We want to actually check the paths rather than just the version string - * built into the executable, so that given version specification (and - * JAVA_VERSION_PATH) will yield the exact same Java environment, regardless - * of the version of the arbitrary launcher we start with. - */ -void -ExecJRE(char *jre, char **argv) -{ - char wanted[PATH_MAX]; - char *execname; - char *progname; - - /* - * Resolve the real path to the directory containing the selected JRE. - */ - if (realpath(jre, wanted) == NULL) { - fprintf(stderr, "Unable to resolve %s\n", jre); - exit(1); - } - - /* - * Resolve the real path to the currently running launcher. - */ - execname = SetExecname(argv); - if (execname == NULL) { - fprintf(stderr, "Unable to resolve current executable\n"); - exit(1); - } - - /* - * If the path to the selected JRE directory is a match to the initial - * portion of the path to the currently executing JRE, we have a winner! - * If so, just return. - */ - if (strncmp(wanted, execname, strlen(wanted)) == 0) - return; /* I am the droid you were looking for */ - - /* - * If this isn't the selected version, exec the selected version. - */ -#ifdef JAVA_ARGS /* javac, jar and friends. */ - progname = "java"; -#else /* java, oldjava, javaw and friends */ -#ifdef PROGNAME - progname = PROGNAME; -#else - progname = *argv; - if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) { - progname = s + 1; - } -#endif /* PROGNAME */ -#endif /* JAVA_ARGS */ - - /* - * This should never happen (because of the selection code in SelectJRE), - * but check for "impossibly" long path names just because buffer overruns - * can be so deadly. - */ - if (strlen(wanted) + strlen(progname) + 6 > PATH_MAX) { - fprintf(stderr, "Path length exceeds maximum length (PATH_MAX)\n"); - exit(1); - } - - /* - * Construct the path and exec it. - */ - (void)strcat(strcat(wanted, "/bin/"), progname); - argv[0] = progname; - if (_launcher_debug) { - int i; - printf("ReExec Command: %s (%s)\n", wanted, argv[0]); - printf("ReExec Args:"); - for (i = 1; argv[i] != NULL; i++) - printf(" %s", argv[i]); - printf("\n"); - } - (void)fflush(stdout); - (void)fflush(stderr); - execv(wanted, argv); - perror("execv()"); - fprintf(stderr, "Exec of %s failed\n", wanted); - exit(1); -} -#endif /* ifndef GAMMA */ - -/* - * "Borrowed" from Solaris 10 where the unsetenv() function is being added - * to libc thanks to SUSv3 (Standard Unix Specification, version 3). As - * such, in the fullness of time this will appear in libc on all relevant - * Solaris/Linux platforms and maybe even the Windows platform. At that - * time, this stub can be removed. - * - * This implementation removes the environment locking for multithreaded - * applications. (We don't have access to these mutexes within libc and - * the launcher isn't multithreaded.) Note that what remains is platform - * independent, because it only relies on attributes that a POSIX environment - * defines. - * - * Returns 0 on success, -1 on failure. - * - * Also removed was the setting of errno. The only value of errno set - * was EINVAL ("Invalid Argument"). - */ - -/* - * s1(environ) is name=value - * s2(name) is name(not the form of name=value). - * if names match, return value of 1, else return 0 - */ -static int -match_noeq(const char *s1, const char *s2) -{ - while (*s1 == *s2++) { - if (*s1++ == '=') - return (1); - } - if (*s1 == '=' && s2[-1] == '\0') - return (1); - return (0); -} - -/* - * added for SUSv3 standard - * - * Delete entry from environ. - * Do not free() memory! Other threads may be using it. - * Keep it around forever. - */ -static int -borrowed_unsetenv(const char *name) -{ - long idx; /* index into environ */ - - if (name == NULL || *name == '\0' || - strchr(name, '=') != NULL) { - return (-1); - } - - for (idx = 0; environ[idx] != NULL; idx++) { - if (match_noeq(environ[idx], name)) - break; - } - if (environ[idx] == NULL) { - /* name not found but still a success */ - return (0); - } - /* squeeze up one entry */ - do { - environ[idx] = environ[idx+1]; - } while (environ[++idx] != NULL); - - return (0); -} -/* --- End of "borrowed" code --- */ - -/* - * Wrapper for unsetenv() function. - */ -int -UnsetEnv(char *name) -{ - return(borrowed_unsetenv(name)); -} - -/* --- Splash Screen shared library support --- */ - -static const char* SPLASHSCREEN_SO = "libsplashscreen.so"; - -static void* hSplashLib = NULL; - -void* SplashProcAddress(const char* name) { - if (!hSplashLib) { - hSplashLib = dlopen(SPLASHSCREEN_SO, RTLD_LAZY | RTLD_GLOBAL); - } - if (hSplashLib) { - void* sym = dlsym(hSplashLib, name); - return sym; - } else { - return NULL; - } -} - -void SplashFreeLibrary() { - if (hSplashLib) { - dlclose(hSplashLib); - hSplashLib = NULL; - } -} - -/* - * Block current thread and continue execution in a new thread - */ -int -ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void * args) { - int rslt; -#if defined(__linux__) || defined(_ALLBSD_SOURCE) - pthread_t tid; - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - - if (stack_size > 0) { - pthread_attr_setstacksize(&attr, stack_size); - } - - if (pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args) == 0) { - void * tmp; - pthread_join(tid, &tmp); - rslt = (int)(intptr_t)tmp; - } else { - /* - * Continue execution in current thread if for some reason (e.g. out of - * memory/LWP) a new thread can't be created. This will likely fail - * later in continuation as JNI_CreateJavaVM needs to create quite a - * few new threads, anyway, just give it a try.. - */ - rslt = continuation(args); - } - - pthread_attr_destroy(&attr); -#else - thread_t tid; - long flags = 0; - if (thr_create(NULL, stack_size, (void *(*)(void *))continuation, args, flags, &tid) == 0) { - void * tmp; - thr_join(tid, NULL, &tmp); - rslt = (int)(intptr_t)tmp; - } else { - /* See above. Continue in current thread if thr_create() failed */ - rslt = continuation(args); - } -#endif - return rslt; -} - -/* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */ -#define MAX_PID_STR_SZ 20 - -void SetJavaLauncherPlatformProps() { - /* Linux only */ -#ifdef __linux__ - const char *substr = "-Dsun.java.launcher.pid="; - char *pid_prop_str = (char *)JLI_MemAlloc(strlen(substr) + MAX_PID_STR_SZ + 1); - sprintf(pid_prop_str, "%s%d", substr, getpid()); - AddOption(pid_prop_str, NULL); -#endif -} diff --git a/hotspot/src/os/posix/launcher/java_md.h b/hotspot/src/os/posix/launcher/java_md.h deleted file mode 100644 index 63c449a2926..00000000000 --- a/hotspot/src/os/posix/launcher/java_md.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef JAVA_MD_H -#define JAVA_MD_H - -#include -#include -#include -#ifndef GAMMA -#include "manifest_info.h" -#endif -#include "jli_util.h" - -#define PATH_SEPARATOR ':' -#define FILESEP "/" -#define FILE_SEPARATOR '/' -#define IS_FILE_SEPARATOR(c) ((c) == '/') -#ifndef MAXNAMELEN -#define MAXNAMELEN PATH_MAX -#endif - -#ifdef JAVA_ARGS -/* - * ApplicationHome is prepended to each of these entries; the resulting - * strings are concatenated (separated by PATH_SEPARATOR) and used as the - * value of -cp option to the launcher. - */ -#ifndef APP_CLASSPATH -#define APP_CLASSPATH { "/lib/tools.jar", "/classes" } -#endif -#endif - -#ifdef HAVE_GETHRTIME -/* - * Support for doing cheap, accurate interval timing. - */ -#include -#define CounterGet() (gethrtime()/1000) -#define Counter2Micros(counts) (counts) -#else -#define CounterGet() (0) -#define Counter2Micros(counts) (1) -#endif /* HAVE_GETHRTIME */ - -#ifdef _LP64 -#define JLONG_FORMAT "%ld" -#else -#define JLONG_FORMAT "%lld" -#endif - -/* - * Function prototypes. - */ -#ifndef GAMMA -char *LocateJRE(manifest_info *info); -void ExecJRE(char *jre, char **argv); -#endif -int UnsetEnv(char *name); - -#endif diff --git a/hotspot/src/os/windows/launcher/java_md.c b/hotspot/src/os/windows/launcher/java_md.c deleted file mode 100644 index 3e28755009c..00000000000 --- a/hotspot/src/os/windows/launcher/java_md.c +++ /dev/null @@ -1,1507 +0,0 @@ -/* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "java.h" -#ifndef GAMMA -#include "version_comp.h" -#endif - -#define JVM_DLL "jvm.dll" -#define JAVA_DLL "java.dll" -#define CRT_DLL "msvcr71.dll" - -/* - * Prototypes. - */ -static jboolean GetPublicJREHome(char *path, jint pathsize); -static jboolean GetJVMPath(const char *jrepath, const char *jvmtype, - char *jvmpath, jint jvmpathsize); -static jboolean GetJREPath(char *path, jint pathsize); -static void EnsureJreInstallation(const char *jrepath); - -/* We supports warmup for UI stack that is performed in parallel - * to VM initialization. - * This helps to improve startup of UI application as warmup phase - * might be long due to initialization of OS or hardware resources. - * It is not CPU bound and therefore it does not interfere with VM init. - * Obviously such warmup only has sense for UI apps and therefore it needs - * to be explicitly requested by passing -Dsun.awt.warmup=true property - * (this is always the case for plugin/javaws). - * - * Implementation launches new thread after VM starts and use it to perform - * warmup code (platform dependent). - * This thread is later reused as AWT toolkit thread as graphics toolkit - * often assume that they are used from the same thread they were launched on. - * - * At the moment we only support warmup for D3D. It only possible on windows - * and only if other flags do not prohibit this (e.g. OpenGL support requested). - */ -#undef ENABLE_AWT_PRELOAD -#ifndef JAVA_ARGS /* turn off AWT preloading for javac, jar, etc */ - #ifdef _X86_ /* for now disable AWT preloading for 64bit */ - #define ENABLE_AWT_PRELOAD - #endif -#endif - -#ifdef ENABLE_AWT_PRELOAD -/* "AWT was preloaded" flag; - * Turned on by AWTPreload(). - */ -int awtPreloaded = 0; - -/* Calls a function with the name specified. - * The function must be int(*fn)(void). - */ -int AWTPreload(const char *funcName); -/* Stops AWT preloading. */ -void AWTPreloadStop(); - -/* D3D preloading */ -/* -1: not initialized; 0: OFF, 1: ON */ -int awtPreloadD3D = -1; -/* Command line parameter to swith D3D preloading on. */ -#define PARAM_PRELOAD_D3D "-Dsun.awt.warmup" -/* D3D/OpenGL management parameters (may disable D3D preloading) */ -#define PARAM_NODDRAW "-Dsun.java2d.noddraw" -#define PARAM_D3D "-Dsun.java2d.d3d" -#define PARAM_OPENGL "-Dsun.java2d.opengl" -/* funtion in awt.dll (src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp) */ -#define D3D_PRELOAD_FUNC "preloadD3D" - - -/* Extracts value of a parameter with the specified name - * from command line argument (returns pointer in the argument). - * Returns NULL if the argument does not contains the parameter. - * e.g.: - * GetParamValue("theParam", "theParam=value") returns pointer to "value". - */ -const char * GetParamValue(const char *paramName, const char *arg) { - int nameLen = strlen(paramName); - if (strncmp(paramName, arg, nameLen) == 0) { - // arg[nameLen] is valid (may contain final NULL) - if (arg[nameLen] == '=') { - return arg + nameLen + 1; - } - } - return NULL; -} - -/* Checks if commandline argument contains property specified - * and analyze it as boolean property (true/false). - * Returns -1 if the argument does not contain the parameter; - * Returns 1 if the argument contains the parameter and its value is "true"; - * Returns 0 if the argument contains the parameter and its value is "false". - */ -int GetBoolParamValue(const char *paramName, const char *arg) { - const char * paramValue = GetParamValue(paramName, arg); - if (paramValue != NULL) { - if (stricmp(paramValue, "true") == 0) { - return 1; - } - if (stricmp(paramValue, "false") == 0) { - return 0; - } - } - return -1; -} -#endif /* ENABLE_AWT_PRELOAD */ - - -const char * -GetArch() -{ - -#ifdef _M_AMD64 - return "amd64"; -#elif defined(_M_IA64) - return "ia64"; -#else - return "i386"; -#endif -} - -/* - * - */ -void -CreateExecutionEnvironment(int *_argc, - char ***_argv, - char jrepath[], - jint so_jrepath, - char jvmpath[], - jint so_jvmpath, - char **original_argv) { -#ifndef GAMMA - char * jvmtype; - - /* Find out where the JRE is that we will be using. */ - if (!GetJREPath(jrepath, so_jrepath)) { - ReportErrorMessage("Error: could not find Java SE Runtime Environment.", - JNI_TRUE); - exit(2); - } - - /* Do this before we read jvm.cfg */ - EnsureJreInstallation(jrepath); - - /* Find the specified JVM type */ - if (ReadKnownVMs(jrepath, (char*)GetArch(), JNI_FALSE) < 1) { - ReportErrorMessage("Error: no known VMs. (check for corrupt jvm.cfg file)", - JNI_TRUE); - exit(1); - } - jvmtype = CheckJvmType(_argc, _argv, JNI_FALSE); - - jvmpath[0] = '\0'; - if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath)) { - char * message=NULL; - const char * format = "Error: no `%s' JVM at `%s'."; - message = (char *)JLI_MemAlloc((strlen(format)+strlen(jvmtype)+ - strlen(jvmpath)) * sizeof(char)); - sprintf(message,format, jvmtype, jvmpath); - ReportErrorMessage(message, JNI_TRUE); - exit(4); - } - /* If we got here, jvmpath has been correctly initialized. */ - -#else /* ifndef GAMMA */ - - /* - * gamma launcher is simpler in that it doesn't handle VM flavors, data - * model, etc. Assuming everything is set-up correctly - * all we need to do here is to return correct path names. See also - * GetJVMPath() and GetApplicationHome(). - */ - - { - if (!GetJREPath(jrepath, so_jrepath) ) { - ReportErrorMessage("Error: could not find Java SE Runtime Environment.", - JNI_TRUE); - exit(2); - } - - if (!GetJVMPath(jrepath, NULL, jvmpath, so_jvmpath)) { - char * message=NULL; - const char * format = "Error: no JVM at `%s'."; - message = (char *)JLI_MemAlloc((strlen(format)+ - strlen(jvmpath)) * sizeof(char)); - sprintf(message, format, jvmpath); - ReportErrorMessage(message, JNI_TRUE); - exit(4); - } - } - -#endif /* ifndef GAMMA */ - -} - - -static jboolean -LoadMSVCRT() -{ - // Only do this once - static int loaded = 0; - char crtpath[MAXPATHLEN]; - - if (!loaded) { - /* - * The Microsoft C Runtime Library needs to be loaded first. A copy is - * assumed to be present in the "JRE path" directory. If it is not found - * there (or "JRE path" fails to resolve), skip the explicit load and let - * nature take its course, which is likely to be a failure to execute. - */ - if (GetJREPath(crtpath, MAXPATHLEN)) { - (void)strcat(crtpath, "\\bin\\" CRT_DLL); /* Add crt dll */ - if (_launcher_debug) { - printf("CRT path is %s\n", crtpath); - } - if (_access(crtpath, 0) == 0) { - if (LoadLibrary(crtpath) == 0) { - ReportErrorMessage2("Error loading: %s", crtpath, JNI_TRUE); - return JNI_FALSE; - } - } - } - loaded = 1; - } - return JNI_TRUE; -} - -/* - * The preJVMStart is a function in the jkernel.dll, which - * performs the final step of synthesizing back the decomposed - * modules (partial install) to the full JRE. Any tool which - * uses the JRE must peform this step to ensure the complete synthesis. - * The EnsureJreInstallation function calls preJVMStart based on - * the conditions outlined below, noting that the operation - * will fail silently if any of conditions are not met. - * NOTE: this call must be made before jvm.dll is loaded, or jvm.cfg - * is read, since jvm.cfg will be modified by the preJVMStart. - * 1. Are we on a supported platform. - * 2. Find the location of the JRE or the Kernel JRE. - * 3. check existence of JREHOME/lib/bundles - * 4. check jkernel.dll and invoke the entry-point - */ -typedef VOID (WINAPI *PREJVMSTART)(); - -static void -EnsureJreInstallation(const char* jrepath) -{ - HINSTANCE handle; - char tmpbuf[MAXPATHLEN]; - PREJVMSTART PreJVMStart; - struct stat s; - - /* 32 bit windows only please */ - if (strcmp(GetArch(), "i386") != 0 ) { - if (_launcher_debug) { - printf("EnsureJreInstallation:unsupported platform\n"); - } - return; - } - /* Does our bundle directory exist ? */ - strcpy(tmpbuf, jrepath); - strcat(tmpbuf, "\\lib\\bundles"); - if (stat(tmpbuf, &s) != 0) { - if (_launcher_debug) { - printf("EnsureJreInstallation:<%s>:not found\n", tmpbuf); - } - return; - } - /* Does our jkernel dll exist ? */ - strcpy(tmpbuf, jrepath); - strcat(tmpbuf, "\\bin\\jkernel.dll"); - if (stat(tmpbuf, &s) != 0) { - if (_launcher_debug) { - printf("EnsureJreInstallation:<%s>:not found\n", tmpbuf); - } - return; - } - /* The Microsoft C Runtime Library needs to be loaded first. */ - if (!LoadMSVCRT()) { - if (_launcher_debug) { - printf("EnsureJreInstallation:could not load C runtime DLL\n"); - } - return; - } - /* Load the jkernel.dll */ - if ((handle = LoadLibrary(tmpbuf)) == 0) { - if (_launcher_debug) { - printf("EnsureJreInstallation:%s:load failed\n", tmpbuf); - } - return; - } - /* Get the function address */ - PreJVMStart = (PREJVMSTART)GetProcAddress(handle, "preJVMStart"); - if (PreJVMStart == NULL) { - if (_launcher_debug) { - printf("EnsureJreInstallation:preJVMStart:function lookup failed\n"); - } - FreeLibrary(handle); - return; - } - PreJVMStart(); - if (_launcher_debug) { - printf("EnsureJreInstallation:preJVMStart:called\n"); - } - FreeLibrary(handle); - return; -} - -/* - * Find path to JRE based on .exe's location or registry settings. - */ -jboolean -GetJREPath(char *path, jint pathsize) -{ - char javadll[MAXPATHLEN]; - struct stat s; - - if (GetApplicationHome(path, pathsize)) { - /* Is JRE co-located with the application? */ - sprintf(javadll, "%s\\bin\\" JAVA_DLL, path); - if (stat(javadll, &s) == 0) { - goto found; - } - - /* Does this app ship a private JRE in \jre directory? */ - sprintf(javadll, "%s\\jre\\bin\\" JAVA_DLL, path); - if (stat(javadll, &s) == 0) { - strcat(path, "\\jre"); - goto found; - } - } - -#ifndef GAMMA - /* Look for a public JRE on this machine. */ - if (GetPublicJREHome(path, pathsize)) { - goto found; - } -#endif - - fprintf(stderr, "Error: could not find " JAVA_DLL "\n"); - return JNI_FALSE; - - found: - if (_launcher_debug) - printf("JRE path is %s\n", path); - return JNI_TRUE; -} - -/* - * Given a JRE location and a JVM type, construct what the name the - * JVM shared library will be. Return true, if such a library - * exists, false otherwise. - */ -static jboolean -GetJVMPath(const char *jrepath, const char *jvmtype, - char *jvmpath, jint jvmpathsize) -{ - struct stat s; - -#ifndef GAMMA - if (strchr(jvmtype, '/') || strchr(jvmtype, '\\')) { - sprintf(jvmpath, "%s\\" JVM_DLL, jvmtype); - } else { - sprintf(jvmpath, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype); - } -#else - /* - * For gamma launcher, JVM is either built-in or in the same directory. - * Either way we return "/jvm.dll" where is the - * directory where gamma launcher is located. - */ - - char *p; - GetModuleFileName(0, jvmpath, jvmpathsize); - - p = strrchr(jvmpath, '\\'); - if (p) { - /* replace executable name with libjvm.so */ - snprintf(p + 1, jvmpathsize - (p + 1 - jvmpath), "%s", JVM_DLL); - } else { - /* this case shouldn't happen */ - snprintf(jvmpath, jvmpathsize, "%s", JVM_DLL); - } -#endif /* ifndef GAMMA */ - - if (stat(jvmpath, &s) == 0) { - return JNI_TRUE; - } else { - return JNI_FALSE; - } -} - -/* - * Load a jvm from "jvmpath" and initialize the invocation functions. - */ -jboolean -LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn) -{ -#ifdef GAMMA - /* JVM is directly linked with gamma launcher; no Loadlibrary() */ - ifn->CreateJavaVM = JNI_CreateJavaVM; - ifn->GetDefaultJavaVMInitArgs = JNI_GetDefaultJavaVMInitArgs; - return JNI_TRUE; -#else - HINSTANCE handle; - - if (_launcher_debug) { - printf("JVM path is %s\n", jvmpath); - } - - /* The Microsoft C Runtime Library needs to be loaded first. */ - LoadMSVCRT(); - - /* Load the Java VM DLL */ - if ((handle = LoadLibrary(jvmpath)) == 0) { - ReportErrorMessage2("Error loading: %s", (char *)jvmpath, JNI_TRUE); - return JNI_FALSE; - } - - /* Now get the function addresses */ - ifn->CreateJavaVM = - (void *)GetProcAddress(handle, "JNI_CreateJavaVM"); - ifn->GetDefaultJavaVMInitArgs = - (void *)GetProcAddress(handle, "JNI_GetDefaultJavaVMInitArgs"); - if (ifn->CreateJavaVM == 0 || ifn->GetDefaultJavaVMInitArgs == 0) { - ReportErrorMessage2("Error: can't find JNI interfaces in: %s", - (char *)jvmpath, JNI_TRUE); - return JNI_FALSE; - } - - return JNI_TRUE; -#endif /* ifndef GAMMA */ -} - -/* - * If app is "c:\foo\bin\javac", then put "c:\foo" into buf. - */ -jboolean -GetApplicationHome(char *buf, jint bufsize) -{ -#ifndef GAMMA - char *cp; - GetModuleFileName(0, buf, bufsize); - *strrchr(buf, '\\') = '\0'; /* remove .exe file name */ - if ((cp = strrchr(buf, '\\')) == 0) { - /* This happens if the application is in a drive root, and - * there is no bin directory. */ - buf[0] = '\0'; - return JNI_FALSE; - } - *cp = '\0'; /* remove the bin\ part */ - return JNI_TRUE; - -#else /* ifndef GAMMA */ - - char env[MAXPATHLEN + 1]; - - /* gamma launcher uses ALT_JAVA_HOME environment variable or jdkpath.txt file to find JDK/JRE */ - - if (getenv("ALT_JAVA_HOME") != NULL) { - snprintf(buf, bufsize, "%s", getenv("ALT_JAVA_HOME")); - } - else { - char path[MAXPATHLEN + 1]; - char* p; - int len; - FILE* fp; - - // find the path to the currect executable - len = GetModuleFileName(NULL, path, MAXPATHLEN + 1); - if (len == 0 || len > MAXPATHLEN) { - printf("Could not get directory of current executable."); - return JNI_FALSE; - } - // remove last path component ("hotspot.exe") - p = strrchr(path, '\\'); - if (p == NULL) { - printf("Could not parse directory of current executable.\n"); - return JNI_FALSE; - } - *p = '\0'; - - // open jdkpath.txt and read JAVA_HOME from it - if (strlen(path) + strlen("\\jdkpath.txt") + 1 >= MAXPATHLEN) { - printf("Path too long: %s\n", path); - return JNI_FALSE; - } - strcat(path, "\\jdkpath.txt"); - fp = fopen(path, "r"); - if (fp == NULL) { - printf("Could not open file %s to get path to JDK.\n", path); - return JNI_FALSE; - } - - if (fgets(buf, bufsize, fp) == NULL) { - printf("Could not read from file %s to get path to JDK.\n", path); - fclose(fp); - return JNI_FALSE; - } - // trim the buffer - p = buf + strlen(buf) - 1; - while(isspace(*p)) { - *p = '\0'; - p--; - } - fclose(fp); - } - - _snprintf(env, MAXPATHLEN, "JAVA_HOME=%s", buf); - _putenv(env); - - return JNI_TRUE; -#endif /* ifndef GAMMA */ -} - -#ifdef JAVAW -__declspec(dllimport) char **__initenv; - -int WINAPI -WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow) -{ - int ret; - - __initenv = _environ; - ret = main(__argc, __argv); - - return ret; -} -#endif - -#ifndef GAMMA - -/* - * Helpers to look in the registry for a public JRE. - */ - /* Same for 1.5.0, 1.5.1, 1.5.2 etc. */ -#define DOTRELEASE JDK_MAJOR_VERSION "." JDK_MINOR_VERSION -#define JRE_KEY "Software\\JavaSoft\\Java Runtime Environment" - -static jboolean -GetStringFromRegistry(HKEY key, const char *name, char *buf, jint bufsize) -{ - DWORD type, size; - - if (RegQueryValueEx(key, name, 0, &type, 0, &size) == 0 - && type == REG_SZ - && (size < (unsigned int)bufsize)) { - if (RegQueryValueEx(key, name, 0, 0, buf, &size) == 0) { - return JNI_TRUE; - } - } - return JNI_FALSE; -} - -static jboolean -GetPublicJREHome(char *buf, jint bufsize) -{ - HKEY key, subkey; - char version[MAXPATHLEN]; - - /* - * Note: There is a very similar implementation of the following - * registry reading code in the Windows java control panel (javacp.cpl). - * If there are bugs here, a similar bug probably exists there. Hence, - * changes here require inspection there. - */ - - /* Find the current version of the JRE */ - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, JRE_KEY, 0, KEY_READ, &key) != 0) { - fprintf(stderr, "Error opening registry key '" JRE_KEY "'\n"); - return JNI_FALSE; - } - - if (!GetStringFromRegistry(key, "CurrentVersion", - version, sizeof(version))) { - fprintf(stderr, "Failed reading value of registry key:\n\t" - JRE_KEY "\\CurrentVersion\n"); - RegCloseKey(key); - return JNI_FALSE; - } - - if (strcmp(version, DOTRELEASE) != 0) { - fprintf(stderr, "Registry key '" JRE_KEY "\\CurrentVersion'\nhas " - "value '%s', but '" DOTRELEASE "' is required.\n", version); - RegCloseKey(key); - return JNI_FALSE; - } - - /* Find directory where the current version is installed. */ - if (RegOpenKeyEx(key, version, 0, KEY_READ, &subkey) != 0) { - fprintf(stderr, "Error opening registry key '" - JRE_KEY "\\%s'\n", version); - RegCloseKey(key); - return JNI_FALSE; - } - - if (!GetStringFromRegistry(subkey, "JavaHome", buf, bufsize)) { - fprintf(stderr, "Failed reading value of registry key:\n\t" - JRE_KEY "\\%s\\JavaHome\n", version); - RegCloseKey(key); - RegCloseKey(subkey); - return JNI_FALSE; - } - - if (_launcher_debug) { - char micro[MAXPATHLEN]; - if (!GetStringFromRegistry(subkey, "MicroVersion", micro, - sizeof(micro))) { - printf("Warning: Can't read MicroVersion\n"); - micro[0] = '\0'; - } - printf("Version major.minor.micro = %s.%s\n", version, micro); - } - - RegCloseKey(key); - RegCloseKey(subkey); - return JNI_TRUE; -} - -#endif /* ifndef GAMMA */ - -/* - * Support for doing cheap, accurate interval timing. - */ -static jboolean counterAvailable = JNI_FALSE; -static jboolean counterInitialized = JNI_FALSE; -static LARGE_INTEGER counterFrequency; - -jlong CounterGet() -{ - LARGE_INTEGER count; - - if (!counterInitialized) { - counterAvailable = QueryPerformanceFrequency(&counterFrequency); - counterInitialized = JNI_TRUE; - } - if (!counterAvailable) { - return 0; - } - QueryPerformanceCounter(&count); - return (jlong)(count.QuadPart); -} - -jlong Counter2Micros(jlong counts) -{ - if (!counterAvailable || !counterInitialized) { - return 0; - } - return (counts * 1000 * 1000)/counterFrequency.QuadPart; -} - -void ReportErrorMessage(char * message, jboolean always) { -#ifdef JAVAW - if (message != NULL) { - MessageBox(NULL, message, "Java Virtual Machine Launcher", - (MB_OK|MB_ICONSTOP|MB_APPLMODAL)); - } -#else - if (always) { - fprintf(stderr, "%s\n", message); - } -#endif -} - -void ReportErrorMessage2(char * format, char * string, jboolean always) { - /* - * The format argument must be a printf format string with one %s - * argument, which is passed the string argument. - */ -#ifdef JAVAW - size_t size; - char * message; - size = strlen(format) + strlen(string); - message = (char*)JLI_MemAlloc(size*sizeof(char)); - sprintf(message, (const char *)format, string); - - if (message != NULL) { - MessageBox(NULL, message, "Java Virtual Machine Launcher", - (MB_OK|MB_ICONSTOP|MB_APPLMODAL)); - JLI_MemFree(message); - } -#else - if (always) { - fprintf(stderr, (const char *)format, string); - fprintf(stderr, "\n"); - } -#endif -} - -/* - * As ReportErrorMessage2 (above) except the system message (if any) - * associated with this error is written to a second %s format specifier - * in the format argument. - */ -void ReportSysErrorMessage2(char * format, char * string, jboolean always) { - int save_errno = errno; - DWORD errval; - int freeit = 0; - char *errtext = NULL; - - if ((errval = GetLastError()) != 0) { /* Platform SDK / DOS Error */ - int n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM| - FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, errval, 0, (LPTSTR)&errtext, 0, NULL); - if (errtext == NULL || n == 0) { /* Paranoia check */ - errtext = ""; - n = 0; - } else { - freeit = 1; - if (n > 2) { /* Drop final CR, LF */ - if (errtext[n - 1] == '\n') n--; - if (errtext[n - 1] == '\r') n--; - errtext[n] = '\0'; - } - } - } else /* C runtime error that has no corresponding DOS error code */ - errtext = strerror(save_errno); - -#ifdef JAVAW - { - size_t size; - char * message; - size = strlen(format) + strlen(string) + strlen(errtext); - message = (char*)JLI_MemAlloc(size*sizeof(char)); - sprintf(message, (const char *)format, string, errtext); - - if (message != NULL) { - MessageBox(NULL, message, "Java Virtual Machine Launcher", - (MB_OK|MB_ICONSTOP|MB_APPLMODAL)); - JLI_MemFree(message); - } - } -#else - if (always) { - fprintf(stderr, (const char *)format, string, errtext); - fprintf(stderr, "\n"); - } -#endif - if (freeit) - (void)LocalFree((HLOCAL)errtext); -} - -void ReportExceptionDescription(JNIEnv * env) { -#ifdef JAVAW - /* - * This code should be replaced by code which opens a window with - * the exception detail message. - */ - (*env)->ExceptionDescribe(env); -#else - (*env)->ExceptionDescribe(env); -#endif -} - - -/* - * Return JNI_TRUE for an option string that has no effect but should - * _not_ be passed on to the vm; return JNI_FALSE otherwise. On - * windows, there are no options that should be screened in this - * manner. - */ -jboolean RemovableMachineDependentOption(char * option) { -#ifdef ENABLE_AWT_PRELOAD - if (awtPreloadD3D < 0) { - /* Tests the command line parameter only if not set yet. */ - if (GetBoolParamValue(PARAM_PRELOAD_D3D, option) == 1) { - awtPreloadD3D = 1; - } - } - if (awtPreloadD3D != 0) { - /* Don't test the command line parameters if already disabled. */ - if (GetBoolParamValue(PARAM_NODDRAW, option) == 1 - || GetBoolParamValue(PARAM_D3D, option) == 0 - || GetBoolParamValue(PARAM_OPENGL, option) == 1) - { - awtPreloadD3D = 0; - } - } -#endif /* ENABLE_AWT_PRELOAD */ - - return JNI_FALSE; -} - -void PrintMachineDependentOptions() { - return; -} - -#ifndef GAMMA - -jboolean -ServerClassMachine() { - jboolean result = JNI_FALSE; -#if defined(NEVER_ACT_AS_SERVER_CLASS_MACHINE) - result = JNI_FALSE; -#elif defined(ALWAYS_ACT_AS_SERVER_CLASS_MACHINE) - result = JNI_TRUE; -#endif - return result; -} - -/* - * Determine if there is an acceptable JRE in the registry directory top_key. - * Upon locating the "best" one, return a fully qualified path to it. - * "Best" is defined as the most advanced JRE meeting the constraints - * contained in the manifest_info. If no JRE in this directory meets the - * constraints, return NULL. - * - * It doesn't matter if we get an error reading the registry, or we just - * don't find anything interesting in the directory. We just return NULL - * in either case. - */ -static char * -ProcessDir(manifest_info* info, HKEY top_key) { - DWORD index = 0; - HKEY ver_key; - char name[MAXNAMELEN]; - int len; - char *best = NULL; - - /* - * Enumerate "/SOFTWARE/JavaSoft/Java Runtime Environment" - * searching for the best available version. - */ - while (RegEnumKey(top_key, index, name, MAXNAMELEN) == ERROR_SUCCESS) { - index++; - if (JLI_AcceptableRelease(name, info->jre_version)) - if ((best == NULL) || (JLI_ExactVersionId(name, best) > 0)) { - if (best != NULL) - JLI_MemFree(best); - best = JLI_StringDup(name); - } - } - - /* - * Extract "JavaHome" from the "best" registry directory and return - * that path. If no appropriate version was located, or there is an - * error in extracting the "JavaHome" string, return null. - */ - if (best == NULL) - return (NULL); - else { - if (RegOpenKeyEx(top_key, best, 0, KEY_READ, &ver_key) - != ERROR_SUCCESS) { - JLI_MemFree(best); - if (ver_key != NULL) - RegCloseKey(ver_key); - return (NULL); - } - JLI_MemFree(best); - len = MAXNAMELEN; - if (RegQueryValueEx(ver_key, "JavaHome", NULL, NULL, (LPBYTE)name, &len) - != ERROR_SUCCESS) { - if (ver_key != NULL) - RegCloseKey(ver_key); - return (NULL); - } - if (ver_key != NULL) - RegCloseKey(ver_key); - return (JLI_StringDup(name)); - } -} - -/* - * This is the global entry point. It examines the host for the optimal - * JRE to be used by scanning a set of registry entries. This set of entries - * is hardwired on Windows as "Software\JavaSoft\Java Runtime Environment" - * under the set of roots "{ HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }". - * - * This routine simply opens each of these registry directories before passing - * control onto ProcessDir(). - */ -char * -LocateJRE(manifest_info* info) { - HKEY key = NULL; - char *path; - int key_index; - HKEY root_keys[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }; - - for (key_index = 0; key_index <= 1; key_index++) { - if (RegOpenKeyEx(root_keys[key_index], JRE_KEY, 0, KEY_READ, &key) - == ERROR_SUCCESS) - if ((path = ProcessDir(info, key)) != NULL) { - if (key != NULL) - RegCloseKey(key); - return (path); - } - if (key != NULL) - RegCloseKey(key); - } - return NULL; -} - - -/* - * Local helper routine to isolate a single token (option or argument) - * from the command line. - * - * This routine accepts a pointer to a character pointer. The first - * token (as defined by MSDN command-line argument syntax) is isolated - * from that string. - * - * Upon return, the input character pointer pointed to by the parameter s - * is updated to point to the remainding, unscanned, portion of the string, - * or to a null character if the entire string has been consummed. - * - * This function returns a pointer to a null-terminated string which - * contains the isolated first token, or to the null character if no - * token could be isolated. - * - * Note the side effect of modifying the input string s by the insertion - * of a null character, making it two strings. - * - * See "Parsing C Command-Line Arguments" in the MSDN Library for the - * parsing rule details. The rule summary from that specification is: - * - * * Arguments are delimited by white space, which is either a space or a tab. - * - * * A string surrounded by double quotation marks is interpreted as a single - * argument, regardless of white space contained within. A quoted string can - * be embedded in an argument. Note that the caret (^) is not recognized as - * an escape character or delimiter. - * - * * A double quotation mark preceded by a backslash, \", is interpreted as a - * literal double quotation mark ("). - * - * * Backslashes are interpreted literally, unless they immediately precede a - * double quotation mark. - * - * * If an even number of backslashes is followed by a double quotation mark, - * then one backslash (\) is placed in the argv array for every pair of - * backslashes (\\), and the double quotation mark (") is interpreted as a - * string delimiter. - * - * * If an odd number of backslashes is followed by a double quotation mark, - * then one backslash (\) is placed in the argv array for every pair of - * backslashes (\\) and the double quotation mark is interpreted as an - * escape sequence by the remaining backslash, causing a literal double - * quotation mark (") to be placed in argv. - */ -static char* -nextarg(char** s) { - char *p = *s; - char *head; - int slashes = 0; - int inquote = 0; - - /* - * Strip leading whitespace, which MSDN defines as only space or tab. - * (Hence, no locale specific "isspace" here.) - */ - while (*p != (char)0 && (*p == ' ' || *p == '\t')) - p++; - head = p; /* Save the start of the token to return */ - - /* - * Isolate a token from the command line. - */ - while (*p != (char)0 && (inquote || !(*p == ' ' || *p == '\t'))) { - if (*p == '\\' && *(p+1) == '"' && slashes % 2 == 0) - p++; - else if (*p == '"') - inquote = !inquote; - slashes = (*p++ == '\\') ? slashes + 1 : 0; - } - - /* - * If the token isolated isn't already terminated in a "char zero", - * then replace the whitespace character with one and move to the - * next character. - */ - if (*p != (char)0) - *p++ = (char)0; - - /* - * Update the parameter to point to the head of the remaining string - * reflecting the command line and return a pointer to the leading - * token which was isolated from the command line. - */ - *s = p; - return (head); -} - -/* - * Local helper routine to return a string equivalent to the input string - * s, but with quotes removed so the result is a string as would be found - * in argv[]. The returned string should be freed by a call to JLI_MemFree(). - * - * The rules for quoting (and escaped quotes) are: - * - * 1 A double quotation mark preceded by a backslash, \", is interpreted as a - * literal double quotation mark ("). - * - * 2 Backslashes are interpreted literally, unless they immediately precede a - * double quotation mark. - * - * 3 If an even number of backslashes is followed by a double quotation mark, - * then one backslash (\) is placed in the argv array for every pair of - * backslashes (\\), and the double quotation mark (") is interpreted as a - * string delimiter. - * - * 4 If an odd number of backslashes is followed by a double quotation mark, - * then one backslash (\) is placed in the argv array for every pair of - * backslashes (\\) and the double quotation mark is interpreted as an - * escape sequence by the remaining backslash, causing a literal double - * quotation mark (") to be placed in argv. - */ -static char* -unquote(const char *s) { - const char *p = s; /* Pointer to the tail of the original string */ - char *un = (char*)JLI_MemAlloc(strlen(s) + 1); /* Ptr to unquoted string */ - char *pun = un; /* Pointer to the tail of the unquoted string */ - - while (*p != '\0') { - if (*p == '"') { - p++; - } else if (*p == '\\') { - const char *q = p + strspn(p,"\\"); - if (*q == '"') - do { - *pun++ = '\\'; - p += 2; - } while (*p == '\\' && p < q); - else - while (p < q) - *pun++ = *p++; - } else { - *pun++ = *p++; - } - } - *pun = '\0'; - return un; -} - -/* - * Given a path to a jre to execute, this routine checks if this process - * is indeed that jre. If not, it exec's that jre. - * - * We want to actually check the paths rather than just the version string - * built into the executable, so that given version specification will yield - * the exact same Java environment, regardless of the version of the arbitrary - * launcher we start with. - */ -void -ExecJRE(char *jre, char **argv) { - int len; - char *progname; - char path[MAXPATHLEN + 1]; - - /* - * Determine the executable we are building (or in the rare case, running). - */ -#ifdef JAVA_ARGS /* javac, jar and friends. */ - progname = "java"; -#else /* java, oldjava, javaw and friends */ -#ifdef PROGNAME - progname = PROGNAME; -#else - { - char *s; - progname = *argv; - if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) { - progname = s + 1; - } - } -#endif /* PROGNAME */ -#endif /* JAVA_ARGS */ - - /* - * Resolve the real path to the currently running launcher. - */ - len = GetModuleFileName(NULL, path, MAXPATHLEN + 1); - if (len == 0 || len > MAXPATHLEN) { - ReportSysErrorMessage2( - "Unable to resolve path to current %s executable: %s", - progname, JNI_TRUE); - exit(1); - } - - if (_launcher_debug) { - printf("ExecJRE: old: %s\n", path); - printf("ExecJRE: new: %s\n", jre); - } - - /* - * If the path to the selected JRE directory is a match to the initial - * portion of the path to the currently executing JRE, we have a winner! - * If so, just return. (strnicmp() is the Windows equiv. of strncasecmp().) - */ - if (strnicmp(jre, path, strlen(jre)) == 0) - return; /* I am the droid you were looking for */ - - /* - * If this isn't the selected version, exec the selected version. - */ - (void)strcat(strcat(strcpy(path, jre), "\\bin\\"), progname); - (void)strcat(path, ".exe"); - - /* - * Although Windows has an execv() entrypoint, it doesn't actually - * overlay a process: it can only create a new process and terminate - * the old process. Therefore, any processes waiting on the initial - * process wake up and they shouldn't. Hence, a chain of pseudo-zombie - * processes must be retained to maintain the proper wait semantics. - * Fortunately the image size of the launcher isn't too large at this - * time. - * - * If it weren't for this semantic flaw, the code below would be ... - * - * execv(path, argv); - * ReportErrorMessage2("Exec of %s failed\n", path, JNI_TRUE); - * exit(1); - * - * The incorrect exec semantics could be addressed by: - * - * exit((int)spawnv(_P_WAIT, path, argv)); - * - * Unfortunately, a bug in Windows spawn/exec impementation prevents - * this from completely working. All the Windows POSIX process creation - * interfaces are implemented as wrappers around the native Windows - * function CreateProcess(). CreateProcess() takes a single string - * to specify command line options and arguments, so the POSIX routine - * wrappers build a single string from the argv[] array and in the - * process, any quoting information is lost. - * - * The solution to this to get the original command line, to process it - * to remove the new multiple JRE options (if any) as was done for argv - * in the common SelectVersion() routine and finally to pass it directly - * to the native CreateProcess() Windows process control interface. - */ - { - char *cmdline; - char *p; - char *np; - char *ocl; - char *ccl; - char *unquoted; - DWORD exitCode; - STARTUPINFO si; - PROCESS_INFORMATION pi; - - /* - * The following code block gets and processes the original command - * line, replacing the argv[0] equivalent in the command line with - * the path to the new executable and removing the appropriate - * Multiple JRE support options. Note that similar logic exists - * in the platform independent SelectVersion routine, but is - * replicated here due to the syntax of CreateProcess(). - * - * The magic "+ 4" characters added to the command line length are - * 2 possible quotes around the path (argv[0]), a space after the - * path and a terminating null character. - */ - ocl = GetCommandLine(); - np = ccl = JLI_StringDup(ocl); - p = nextarg(&np); /* Discard argv[0] */ - cmdline = (char *)JLI_MemAlloc(strlen(path) + strlen(np) + 4); - if (strchr(path, (int)' ') == NULL && strchr(path, (int)'\t') == NULL) - cmdline = strcpy(cmdline, path); - else - cmdline = strcat(strcat(strcpy(cmdline, "\""), path), "\""); - - while (*np != (char)0) { /* While more command-line */ - p = nextarg(&np); - if (*p != (char)0) { /* If a token was isolated */ - unquoted = unquote(p); - if (*unquoted == '-') { /* Looks like an option */ - if (strcmp(unquoted, "-classpath") == 0 || - strcmp(unquoted, "-cp") == 0) { /* Unique cp syntax */ - cmdline = strcat(strcat(cmdline, " "), p); - p = nextarg(&np); - if (*p != (char)0) /* If a token was isolated */ - cmdline = strcat(strcat(cmdline, " "), p); - } else if (strncmp(unquoted, "-version:", 9) != 0 && - strcmp(unquoted, "-jre-restrict-search") != 0 && - strcmp(unquoted, "-no-jre-restrict-search") != 0) { - cmdline = strcat(strcat(cmdline, " "), p); - } - } else { /* End of options */ - cmdline = strcat(strcat(cmdline, " "), p); - cmdline = strcat(strcat(cmdline, " "), np); - JLI_MemFree((void *)unquoted); - break; - } - JLI_MemFree((void *)unquoted); - } - } - JLI_MemFree((void *)ccl); - - if (_launcher_debug) { - np = ccl = JLI_StringDup(cmdline); - p = nextarg(&np); - printf("ReExec Command: %s (%s)\n", path, p); - printf("ReExec Args: %s\n", np); - JLI_MemFree((void *)ccl); - } - (void)fflush(stdout); - (void)fflush(stderr); - - /* - * The following code is modeled after a model presented in the - * Microsoft Technical Article "Moving Unix Applications to - * Windows NT" (March 6, 1994) and "Creating Processes" on MSDN - * (Februrary 2005). It approximates UNIX spawn semantics with - * the parent waiting for termination of the child. - */ - memset(&si, 0, sizeof(si)); - si.cb =sizeof(STARTUPINFO); - memset(&pi, 0, sizeof(pi)); - - if (!CreateProcess((LPCTSTR)path, /* executable name */ - (LPTSTR)cmdline, /* command line */ - (LPSECURITY_ATTRIBUTES)NULL, /* process security attr. */ - (LPSECURITY_ATTRIBUTES)NULL, /* thread security attr. */ - (BOOL)TRUE, /* inherits system handles */ - (DWORD)0, /* creation flags */ - (LPVOID)NULL, /* environment block */ - (LPCTSTR)NULL, /* current directory */ - (LPSTARTUPINFO)&si, /* (in) startup information */ - (LPPROCESS_INFORMATION)&pi)) { /* (out) process information */ - ReportSysErrorMessage2("CreateProcess(%s, ...) failed: %s", - path, JNI_TRUE); - exit(1); - } - - if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED) { - if (GetExitCodeProcess(pi.hProcess, &exitCode) == FALSE) - exitCode = 1; - } else { - ReportErrorMessage("WaitForSingleObject() failed.", JNI_TRUE); - exitCode = 1; - } - - CloseHandle(pi.hThread); - CloseHandle(pi.hProcess); - - exit(exitCode); - } - -} - -#endif /* ifndef GAMMA */ - - -/* - * Wrapper for platform dependent unsetenv function. - */ -int -UnsetEnv(char *name) -{ - int ret; - char *buf = JLI_MemAlloc(strlen(name) + 2); - buf = strcat(strcpy(buf, name), "="); - ret = _putenv(buf); - JLI_MemFree(buf); - return (ret); -} - -/* --- Splash Screen shared library support --- */ - -static const char* SPLASHSCREEN_SO = "\\bin\\splashscreen.dll"; - -static HMODULE hSplashLib = NULL; - -void* SplashProcAddress(const char* name) { - char libraryPath[MAXPATHLEN]; /* some extra space for strcat'ing SPLASHSCREEN_SO */ - - if (!GetJREPath(libraryPath, MAXPATHLEN)) { - return NULL; - } - if (strlen(libraryPath)+strlen(SPLASHSCREEN_SO) >= MAXPATHLEN) { - return NULL; - } - strcat(libraryPath, SPLASHSCREEN_SO); - - if (!hSplashLib) { - hSplashLib = LoadLibrary(libraryPath); - } - if (hSplashLib) { - return GetProcAddress(hSplashLib, name); - } else { - return NULL; - } -} - -void SplashFreeLibrary() { - if (hSplashLib) { - FreeLibrary(hSplashLib); - hSplashLib = NULL; - } -} - -/* - * Block current thread and continue execution in a new thread - */ -int -ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void * args) { - int rslt = 0; - unsigned thread_id; - -#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION -#define STACK_SIZE_PARAM_IS_A_RESERVATION (0x10000) -#endif - - /* - * STACK_SIZE_PARAM_IS_A_RESERVATION is what we want, but it's not - * supported on older version of Windows. Try first with the flag; and - * if that fails try again without the flag. See MSDN document or HotSpot - * source (os_win32.cpp) for details. - */ - HANDLE thread_handle = - (HANDLE)_beginthreadex(NULL, - (unsigned)stack_size, - continuation, - args, - STACK_SIZE_PARAM_IS_A_RESERVATION, - &thread_id); - if (thread_handle == NULL) { - thread_handle = - (HANDLE)_beginthreadex(NULL, - (unsigned)stack_size, - continuation, - args, - 0, - &thread_id); - } - - /* AWT preloading (AFTER main thread start) */ -#ifdef ENABLE_AWT_PRELOAD - /* D3D preloading */ - if (awtPreloadD3D != 0) { - char *envValue; - /* D3D routines checks env.var J2D_D3D if no appropriate - * command line params was specified - */ - envValue = getenv("J2D_D3D"); - if (envValue != NULL && stricmp(envValue, "false") == 0) { - awtPreloadD3D = 0; - } - /* Test that AWT preloading isn't disabled by J2D_D3D_PRELOAD env.var */ - envValue = getenv("J2D_D3D_PRELOAD"); - if (envValue != NULL && stricmp(envValue, "false") == 0) { - awtPreloadD3D = 0; - } - if (awtPreloadD3D < 0) { - /* If awtPreloadD3D is still undefined (-1), test - * if it is turned on by J2D_D3D_PRELOAD env.var. - * By default it's turned OFF. - */ - awtPreloadD3D = 0; - if (envValue != NULL && stricmp(envValue, "true") == 0) { - awtPreloadD3D = 1; - } - } - } - if (awtPreloadD3D) { - AWTPreload(D3D_PRELOAD_FUNC); - } -#endif /* ENABLE_AWT_PRELOAD */ - - if (thread_handle) { - WaitForSingleObject(thread_handle, INFINITE); - GetExitCodeThread(thread_handle, &rslt); - CloseHandle(thread_handle); - } else { - rslt = continuation(args); - } - -#ifdef ENABLE_AWT_PRELOAD - if (awtPreloaded) { - AWTPreloadStop(); - } -#endif /* ENABLE_AWT_PRELOAD */ - - return rslt; -} - -/* Linux only, empty on windows. */ -void SetJavaLauncherPlatformProps() {} - - -//============================== -// AWT preloading -#ifdef ENABLE_AWT_PRELOAD - -typedef int FnPreloadStart(void); -typedef void FnPreloadStop(void); -static FnPreloadStop *fnPreloadStop = NULL; -static HMODULE hPreloadAwt = NULL; - -/* - * Starts AWT preloading - */ -int AWTPreload(const char *funcName) -{ - int result = -1; - - // load AWT library once (if several preload function should be called) - if (hPreloadAwt == NULL) { - // awt.dll is not loaded yet - char libraryPath[MAXPATHLEN]; - int jrePathLen = 0; - HMODULE hJava = NULL; - HMODULE hVerify = NULL; - - while (1) { - // awt.dll depends on jvm.dll & java.dll; - // jvm.dll is already loaded, so we need only java.dll; - // java.dll depends on MSVCRT lib & verify.dll. - if (!GetJREPath(libraryPath, MAXPATHLEN)) { - break; - } - - // save path length - jrePathLen = strlen(libraryPath); - - // load msvcrt 1st - LoadMSVCRT(); - - // load verify.dll - strcat(libraryPath, "\\bin\\verify.dll"); - hVerify = LoadLibrary(libraryPath); - if (hVerify == NULL) { - break; - } - - // restore jrePath - libraryPath[jrePathLen] = 0; - // load java.dll - strcat(libraryPath, "\\bin\\" JAVA_DLL); - hJava = LoadLibrary(libraryPath); - if (hJava == NULL) { - break; - } - - // restore jrePath - libraryPath[jrePathLen] = 0; - // load awt.dll - strcat(libraryPath, "\\bin\\awt.dll"); - hPreloadAwt = LoadLibrary(libraryPath); - if (hPreloadAwt == NULL) { - break; - } - - // get "preloadStop" func ptr - fnPreloadStop = (FnPreloadStop *)GetProcAddress(hPreloadAwt, "preloadStop"); - - break; - } - } - - if (hPreloadAwt != NULL) { - FnPreloadStart *fnInit = (FnPreloadStart *)GetProcAddress(hPreloadAwt, funcName); - if (fnInit != NULL) { - // don't forget to stop preloading - awtPreloaded = 1; - - result = fnInit(); - } - } - - return result; -} - -/* - * Terminates AWT preloading - */ -void AWTPreloadStop() { - if (fnPreloadStop != NULL) { - fnPreloadStop(); - } -} - -#endif /* ENABLE_AWT_PRELOAD */ diff --git a/hotspot/src/os/windows/launcher/java_md.h b/hotspot/src/os/windows/launcher/java_md.h deleted file mode 100644 index 763e2457644..00000000000 --- a/hotspot/src/os/windows/launcher/java_md.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef JAVA_MD_H -#define JAVA_MD_H - -#include -#include -#include -#ifndef GAMMA -#include "manifest_info.h" -#endif -#include "jli_util.h" - -#ifdef GAMMA -#define stricmp _stricmp -#define strnicmp _strnicmp -#define snprintf _snprintf -#define strdup _strdup -#endif - -#define PATH_SEPARATOR ';' -#define FILESEP "\\" -#define FILE_SEPARATOR '\\' -#define IS_FILE_SEPARATOR(c) ((c) == '\\' || (c) == '/') -#define MAXPATHLEN MAX_PATH -#define MAXNAMELEN MAX_PATH - -#ifdef JAVA_ARGS -/* - * ApplicationHome is prepended to each of these entries; the resulting - * strings are concatenated (separated by PATH_SEPARATOR) and used as the - * value of -cp option to the launcher. - */ -#ifndef APP_CLASSPATH -#define APP_CLASSPATH { "\\lib\\tools.jar", "\\classes" } -#endif -#endif - -/* - * Support for doing cheap, accurate interval timing. - */ -extern jlong CounterGet(void); -extern jlong Counter2Micros(jlong counts); - -#ifdef JAVAW -#define main _main -extern int _main(int argc, char **argv); -#endif - -#define JLONG_FORMAT "%I64d" - -/* - * Function prototypes. - */ -#ifndef GAMMA -char *LocateJRE(manifest_info *info); -void ExecJRE(char *jre, char **argv); -#endif -int UnsetEnv(char *name); - -#endif diff --git a/hotspot/src/share/tools/ProjectCreator/BuildConfig.java b/hotspot/src/share/tools/ProjectCreator/BuildConfig.java index 953967fccd4..f9283886a87 100644 --- a/hotspot/src/share/tools/ProjectCreator/BuildConfig.java +++ b/hotspot/src/share/tools/ProjectCreator/BuildConfig.java @@ -65,6 +65,7 @@ class BuildConfig { String sourceBase = getFieldString(null, "SourceBase"); String buildSpace = getFieldString(null, "BuildSpace"); String outDir = buildBase; + String jdkTargetRoot = getFieldString(null, "JdkTargetRoot"); put("Id", flavourBuild); put("OutputDir", outDir); @@ -72,6 +73,7 @@ class BuildConfig { put("BuildBase", buildBase); put("BuildSpace", buildSpace); put("OutputDll", outDir + Util.sep + outDll); + put("JdkTargetRoot", jdkTargetRoot); context = new String [] {flavourBuild, flavour, build, null}; } diff --git a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java index 137abdc30e9..8d094d30108 100644 --- a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java +++ b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java @@ -98,11 +98,6 @@ public class WinGammaPlatformVC10 extends WinGammaPlatformVC7 { tagV(cfg.getV("LinkerFlags")); endTag(); - startTag("PostBuildEvent"); - tagData("Message", BuildConfig.getFieldString(null, "PostbuildDescription")); - tagData("Command", cfg.expandFormat(BuildConfig.getFieldString(null, "PostbuildCommand").replace("\t", "\r\n"))); - endTag(); - startTag("PreLinkEvent"); tagData("Message", BuildConfig.getFieldString(null, "PrelinkDescription")); tagData("Command", cfg.expandFormat(BuildConfig.getFieldString(null, "PrelinkCommand").replace("\t", "\r\n"))); @@ -141,7 +136,9 @@ public class WinGammaPlatformVC10 extends WinGammaPlatformVC7 { for (BuildConfig cfg : allConfigs) { startTag(cfg, "PropertyGroup"); - tagData("LocalDebuggerCommand", "$(TargetDir)/hotspot.exe"); + tagData("LocalDebuggerCommand", cfg.get("JdkTargetRoot") + "\\bin\\java.exe"); + tagData("LocalDebuggerCommandArguments", "-XXaltjvm=$(TargetDir) -Dsun.java.launcher=gamma"); + tagData("LocalDebuggerEnvironment", "JAVA_HOME=" + cfg.get("JdkTargetRoot")); endTag(); } diff --git a/hotspot/src/share/tools/launcher/java.c b/hotspot/src/share/tools/launcher/java.c deleted file mode 100644 index 63f11d77c86..00000000000 --- a/hotspot/src/share/tools/launcher/java.c +++ /dev/null @@ -1,2080 +0,0 @@ -/* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - * - */ - -/* - * Gamma (Hotspot internal engineering test) launcher based on 6.0u22 JDK, - * search "GAMMA" for gamma specific changes. - * - * GAMMA: gamma launcher is much simpler than regular java launcher in that - * JVM is either statically linked in or it is installed in the - * same directory where the launcher exists, so we don't have to - * worry about choosing the right JVM based on command line flag, jar - * file and/or ergonomics. Intead of removing unused logic from source - * they are commented out with #ifndef GAMMA, hopefully it'll be easier - * to maintain this file in sync with regular JDK launcher. - */ - -/* - * Shared source for 'java' command line tool. - * - * If JAVA_ARGS is defined, then acts as a launcher for applications. For - * instance, the JDK command line tools such as javac and javadoc (see - * makefiles for more details) are built with this program. Any arguments - * prefixed with '-J' will be passed directly to the 'java' command. - */ - -#ifdef GAMMA -# ifdef JAVA_ARGS -# error Do NOT define JAVA_ARGS when building gamma launcher -# endif -# if !defined(LINK_INTO_AOUT) && !defined(LINK_INTO_LIBJVM) -# error Either LINK_INTO_AOUT or LINK_INTO_LIBJVM must be defined -# endif -#endif - -/* - * One job of the launcher is to remove command line options which the - * vm does not understand and will not process. These options include - * options which select which style of vm is run (e.g. -client and - * -server) as well as options which select the data model to use. - * Additionally, for tools which invoke an underlying vm "-J-foo" - * options are turned into "-foo" options to the vm. This option - * filtering is handled in a number of places in the launcher, some of - * it in machine-dependent code. In this file, the function - * CheckJVMType removes vm style options and TranslateApplicationArgs - * removes "-J" prefixes. On unix platforms, the - * CreateExecutionEnvironment function from the unix java_md.c file - * processes and removes -d options. However, in case - * CreateExecutionEnvironment does not need to exec because - * LD_LIBRARY_PATH is set acceptably and the data model does not need - * to be changed, ParseArguments will screen out the redundant -d - * options and prevent them from being passed to the vm; this is done - * by using the machine-dependent call - * RemovableMachineDependentOption. - */ - -#include -#include -#include - -#include -#include -#include "java.h" -#ifndef GAMMA -#include "manifest_info.h" -#include "version_comp.h" -#include "splashscreen.h" -#endif -#include "wildcard.h" - -#ifndef FULL_VERSION -#define FULL_VERSION JDK_MAJOR_VERSION "." JDK_MINOR_VERSION -#endif - -/* - * The following environment variable is used to influence the behavior - * of the jre exec'd through the SelectVersion routine. The command line - * options which specify the version are not passed to the exec'd version, - * because that jre may be an older version which wouldn't recognize them. - * This environment variable is known to this (and later) version and serves - * to suppress the version selection code. This is not only for efficiency, - * but also for correctness, since any command line options have been - * removed which would cause any value found in the manifest to be used. - * This would be incorrect because the command line options are defined - * to take precedence. - * - * The value associated with this environment variable is the MainClass - * name from within the executable jar file (if any). This is strictly a - * performance enhancement to avoid re-reading the jar file manifest. - * - * A NOTE TO DEVELOPERS: For performance reasons it is important that - * the program image remain relatively small until after SelectVersion - * CreateExecutionEnvironment have finished their possibly recursive - * processing. Watch everything, but resist all temptations to use Java - * interfaces. - */ -#define ENV_ENTRY "_JAVA_VERSION_SET" - -#ifndef GAMMA -#define SPLASH_FILE_ENV_ENTRY "_JAVA_SPLASH_FILE" -#define SPLASH_JAR_ENV_ENTRY "_JAVA_SPLASH_JAR" -#endif - -static jboolean printVersion = JNI_FALSE; /* print and exit */ -static jboolean showVersion = JNI_FALSE; /* print but continue */ -static char *progname; -jboolean _launcher_debug = JNI_FALSE; - -#ifndef GAMMA -/* - * Entries for splash screen environment variables. - * putenv is performed in SelectVersion. We need - * them in memory until UnsetEnv, so they are made static - * global instead of auto local. - */ -static char* splash_file_entry = NULL; -static char* splash_jar_entry = NULL; -#endif - -/* - * List of VM options to be specified when the VM is created. - */ -static JavaVMOption *options; -static int numOptions, maxOptions; - -/* - * Prototypes for functions internal to launcher. - */ -static void SetClassPath(const char *s); -static void SelectVersion(int argc, char **argv, char **main_class); -static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile, - char **pclassname, int *pret, const char *jvmpath); -static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv, - InvocationFunctions *ifn); -static jstring NewPlatformString(JNIEnv *env, char *s); -static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc); -static jclass LoadClass(JNIEnv *env, char *name); -static jstring GetMainClassName(JNIEnv *env, char *jarname); -static void SetJavaCommandLineProp(char* classname, char* jarfile, int argc, char** argv); -static void SetJavaLauncherProp(void); - -#ifdef JAVA_ARGS -static void TranslateApplicationArgs(int *pargc, char ***pargv); -static jboolean AddApplicationOptions(void); -#endif - -static void PrintJavaVersion(JNIEnv *env); -static void PrintUsage(void); -static jint PrintXUsage(const char *jvmpath); - -static void SetPaths(int argc, char **argv); - -#ifndef GAMMA - -/* Maximum supported entries from jvm.cfg. */ -#define INIT_MAX_KNOWN_VMS 10 -/* Values for vmdesc.flag */ -#define VM_UNKNOWN -1 -#define VM_KNOWN 0 -#define VM_ALIASED_TO 1 -#define VM_WARN 2 -#define VM_ERROR 3 -#define VM_IF_SERVER_CLASS 4 -#define VM_IGNORE 5 -struct vmdesc { - char *name; - int flag; - char *alias; - char *server_class; -}; -static struct vmdesc *knownVMs = NULL; -static int knownVMsCount = 0; -static int knownVMsLimit = 0; - -static void GrowKnownVMs(); -static int KnownVMIndex(const char* name); -static void FreeKnownVMs(); -static void ShowSplashScreen(); - -#endif /* ifndef GAMMA */ - -jboolean ServerClassMachine(); - -/* flag which if set suppresses error messages from the launcher */ -static int noExitErrorMessage = 0; - -/* - * Running Java code in primordial thread caused many problems. We will - * create a new thread to invoke JVM. See 6316197 for more information. - */ -static jlong threadStackSize = 0; /* stack size of the new thread */ - -int JNICALL JavaMain(void * args); /* entry point */ - -struct JavaMainArgs { - int argc; - char ** argv; - char * jarfile; - char * classname; - InvocationFunctions ifn; -}; - -/* - * Entry point. - */ -int -main(int argc, char ** argv) -{ - char *jarfile = 0; - char *classname = 0; - char *s = 0; - char *main_class = NULL; - int ret; - InvocationFunctions ifn; - jlong start, end; - char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN]; - char ** original_argv = argv; - - if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) { - _launcher_debug = JNI_TRUE; - printf("----_JAVA_LAUNCHER_DEBUG----\n"); - } - -#ifndef GAMMA - /* - * Make sure the specified version of the JRE is running. - * - * There are three things to note about the SelectVersion() routine: - * 1) If the version running isn't correct, this routine doesn't - * return (either the correct version has been exec'd or an error - * was issued). - * 2) Argc and Argv in this scope are *not* altered by this routine. - * It is the responsibility of subsequent code to ignore the - * arguments handled by this routine. - * 3) As a side-effect, the variable "main_class" is guaranteed to - * be set (if it should ever be set). This isn't exactly the - * poster child for structured programming, but it is a small - * price to pay for not processing a jar file operand twice. - * (Note: This side effect has been disabled. See comment on - * bugid 5030265 below.) - */ - SelectVersion(argc, argv, &main_class); -#endif /* ifndef GAMMA */ - - /* copy original argv */ - { - int i; - original_argv = (char**)JLI_MemAlloc(sizeof(char*)*(argc+1)); - for(i = 0; i < argc+1; i++) - original_argv[i] = argv[i]; - } - - CreateExecutionEnvironment(&argc, &argv, - jrepath, sizeof(jrepath), - jvmpath, sizeof(jvmpath), - original_argv); - - printf("Using java runtime at: %s\n", jrepath); - - ifn.CreateJavaVM = 0; - ifn.GetDefaultJavaVMInitArgs = 0; - - if (_launcher_debug) - start = CounterGet(); - if (!LoadJavaVM(jvmpath, &ifn)) { - exit(6); - } - if (_launcher_debug) { - end = CounterGet(); - printf("%ld micro seconds to LoadJavaVM\n", - (long)(jint)Counter2Micros(end-start)); - } - -#ifdef JAVA_ARGS /* javac, jar and friends. */ - progname = "java"; -#else /* java, oldjava, javaw and friends */ -#ifdef PROGNAME - progname = PROGNAME; -#else - progname = *argv; - if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) { - progname = s + 1; - } -#endif /* PROGNAME */ -#endif /* JAVA_ARGS */ - ++argv; - --argc; - -#ifdef JAVA_ARGS - /* Preprocess wrapper arguments */ - TranslateApplicationArgs(&argc, &argv); - if (!AddApplicationOptions()) { - exit(1); - } -#endif - - /* Set default CLASSPATH */ - if ((s = getenv("CLASSPATH")) == 0) { - s = "."; - } -#ifndef JAVA_ARGS - SetClassPath(s); -#endif - - /* - * Parse command line options; if the return value of - * ParseArguments is false, the program should exit. - */ - if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret, jvmpath)) { - exit(ret); - } - - /* Override class path if -jar flag was specified */ - if (jarfile != 0) { - SetClassPath(jarfile); - } - - /* set the -Dsun.java.command pseudo property */ - SetJavaCommandLineProp(classname, jarfile, argc, argv); - - /* Set the -Dsun.java.launcher pseudo property */ - SetJavaLauncherProp(); - - /* set the -Dsun.java.launcher.* platform properties */ - SetJavaLauncherPlatformProps(); - -#ifndef GAMMA - /* Show the splash screen if needed */ - ShowSplashScreen(); -#endif - - /* - * Done with all command line processing and potential re-execs so - * clean up the environment. - */ - (void)UnsetEnv(ENV_ENTRY); -#ifndef GAMMA - (void)UnsetEnv(SPLASH_FILE_ENV_ENTRY); - (void)UnsetEnv(SPLASH_JAR_ENV_ENTRY); - - JLI_MemFree(splash_jar_entry); - JLI_MemFree(splash_file_entry); -#endif - - /* - * If user doesn't specify stack size, check if VM has a preference. - * Note that HotSpot no longer supports JNI_VERSION_1_1 but it will - * return its default stack size through the init args structure. - */ - if (threadStackSize == 0) { - struct JDK1_1InitArgs args1_1; - memset((void*)&args1_1, 0, sizeof(args1_1)); - args1_1.version = JNI_VERSION_1_1; - ifn.GetDefaultJavaVMInitArgs(&args1_1); /* ignore return value */ - if (args1_1.javaStackSize > 0) { - threadStackSize = args1_1.javaStackSize; - } - } - - { /* Create a new thread to create JVM and invoke main method */ - struct JavaMainArgs args; - - args.argc = argc; - args.argv = argv; - args.jarfile = jarfile; - args.classname = classname; - args.ifn = ifn; - - return ContinueInNewThread(JavaMain, threadStackSize, (void*)&args); - } -} - -int JNICALL -JavaMain(void * _args) -{ - struct JavaMainArgs *args = (struct JavaMainArgs *)_args; - int argc = args->argc; - char **argv = args->argv; - char *jarfile = args->jarfile; - char *classname = args->classname; - InvocationFunctions ifn = args->ifn; - - JavaVM *vm = 0; - JNIEnv *env = 0; - jstring mainClassName; - jclass mainClass; - jmethodID mainID; - jobjectArray mainArgs; - int ret = 0; - jlong start, end; - - /* - * Error message to print or display; by default the message will - * only be displayed in a window. - */ - char * message = "Fatal exception occurred. Program will exit."; - jboolean messageDest = JNI_FALSE; - - /* Initialize the virtual machine */ - - if (_launcher_debug) - start = CounterGet(); - if (!InitializeJVM(&vm, &env, &ifn)) { - ReportErrorMessage("Could not create the Java virtual machine.", - JNI_TRUE); - exit(1); - } - - if (printVersion || showVersion) { - PrintJavaVersion(env); - if ((*env)->ExceptionOccurred(env)) { - ReportExceptionDescription(env); - goto leave; - } - if (printVersion) { - ret = 0; - message = NULL; - goto leave; - } - if (showVersion) { - fprintf(stderr, "\n"); - } - } - - /* If the user specified neither a class name nor a JAR file */ - if (jarfile == 0 && classname == 0) { - PrintUsage(); - message = NULL; - goto leave; - } - -#ifndef GAMMA - FreeKnownVMs(); /* after last possible PrintUsage() */ -#endif - - if (_launcher_debug) { - end = CounterGet(); - printf("%ld micro seconds to InitializeJVM\n", - (long)(jint)Counter2Micros(end-start)); - } - - /* At this stage, argc/argv have the applications' arguments */ - if (_launcher_debug) { - int i = 0; - printf("Main-Class is '%s'\n", classname ? classname : ""); - printf("Apps' argc is %d\n", argc); - for (; i < argc; i++) { - printf(" argv[%2d] = '%s'\n", i, argv[i]); - } - } - - ret = 1; - - /* - * Get the application's main class. - * - * See bugid 5030265. The Main-Class name has already been parsed - * from the manifest, but not parsed properly for UTF-8 support. - * Hence the code here ignores the value previously extracted and - * uses the pre-existing code to reextract the value. This is - * possibly an end of release cycle expedient. However, it has - * also been discovered that passing some character sets through - * the environment has "strange" behavior on some variants of - * Windows. Hence, maybe the manifest parsing code local to the - * launcher should never be enhanced. - * - * Hence, future work should either: - * 1) Correct the local parsing code and verify that the - * Main-Class attribute gets properly passed through - * all environments, - * 2) Remove the vestages of maintaining main_class through - * the environment (and remove these comments). - */ - if (jarfile != 0) { - mainClassName = GetMainClassName(env, jarfile); - if ((*env)->ExceptionOccurred(env)) { - ReportExceptionDescription(env); - goto leave; - } - if (mainClassName == NULL) { - const char * format = "Failed to load Main-Class manifest " - "attribute from\n%s"; - message = (char*)JLI_MemAlloc((strlen(format) + strlen(jarfile)) * - sizeof(char)); - sprintf(message, format, jarfile); - messageDest = JNI_TRUE; - goto leave; - } - classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0); - if (classname == NULL) { - ReportExceptionDescription(env); - goto leave; - } - mainClass = LoadClass(env, classname); - if(mainClass == NULL) { /* exception occured */ - const char * format = "Could not find the main class: %s. Program will exit."; - ReportExceptionDescription(env); - message = (char *)JLI_MemAlloc((strlen(format) + - strlen(classname)) * sizeof(char) ); - messageDest = JNI_TRUE; - sprintf(message, format, classname); - goto leave; - } - (*env)->ReleaseStringUTFChars(env, mainClassName, classname); - } else { - mainClassName = NewPlatformString(env, classname); - if (mainClassName == NULL) { - const char * format = "Failed to load Main Class: %s"; - message = (char *)JLI_MemAlloc((strlen(format) + strlen(classname)) * - sizeof(char) ); - sprintf(message, format, classname); - messageDest = JNI_TRUE; - goto leave; - } - classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0); - if (classname == NULL) { - ReportExceptionDescription(env); - goto leave; - } - mainClass = LoadClass(env, classname); - if(mainClass == NULL) { /* exception occured */ - const char * format = "Could not find the main class: %s. Program will exit."; - ReportExceptionDescription(env); - message = (char *)JLI_MemAlloc((strlen(format) + - strlen(classname)) * sizeof(char) ); - messageDest = JNI_TRUE; - sprintf(message, format, classname); - goto leave; - } - (*env)->ReleaseStringUTFChars(env, mainClassName, classname); - } - - /* Get the application's main method */ - mainID = (*env)->GetStaticMethodID(env, mainClass, "main", - "([Ljava/lang/String;)V"); - if (mainID == NULL) { - if ((*env)->ExceptionOccurred(env)) { - ReportExceptionDescription(env); - } else { - message = "No main method found in specified class."; - messageDest = JNI_TRUE; - } - goto leave; - } - - { /* Make sure the main method is public */ - jint mods; - jmethodID mid; - jobject obj = (*env)->ToReflectedMethod(env, mainClass, - mainID, JNI_TRUE); - - if( obj == NULL) { /* exception occurred */ - ReportExceptionDescription(env); - goto leave; - } - - mid = - (*env)->GetMethodID(env, - (*env)->GetObjectClass(env, obj), - "getModifiers", "()I"); - if ((*env)->ExceptionOccurred(env)) { - ReportExceptionDescription(env); - goto leave; - } - - mods = (*env)->CallIntMethod(env, obj, mid); - if ((mods & 1) == 0) { /* if (!Modifier.isPublic(mods)) ... */ - message = "Main method not public."; - messageDest = JNI_TRUE; - goto leave; - } - } - - /* Build argument array */ - mainArgs = NewPlatformStringArray(env, argv, argc); - if (mainArgs == NULL) { - ReportExceptionDescription(env); - goto leave; - } - - /* Invoke main method. */ - (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs); - - /* - * The launcher's exit code (in the absence of calls to - * System.exit) will be non-zero if main threw an exception. - */ - ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1; - - /* - * Detach the main thread so that it appears to have ended when - * the application's main method exits. This will invoke the - * uncaught exception handler machinery if main threw an - * exception. An uncaught exception handler cannot change the - * launcher's return code except by calling System.exit. - */ - if ((*vm)->DetachCurrentThread(vm) != 0) { - message = "Could not detach main thread."; - messageDest = JNI_TRUE; - ret = 1; - goto leave; - } - - message = NULL; - - leave: - /* - * Wait for all non-daemon threads to end, then destroy the VM. - * This will actually create a trivial new Java waiter thread - * named "DestroyJavaVM", but this will be seen as a different - * thread from the one that executed main, even though they are - * the same C thread. This allows mainThread.join() and - * mainThread.isAlive() to work as expected. - */ - (*vm)->DestroyJavaVM(vm); - - if(message != NULL && !noExitErrorMessage) - ReportErrorMessage(message, messageDest); - return ret; -} - -#ifndef GAMMA -/* - * Checks the command line options to find which JVM type was - * specified. If no command line option was given for the JVM type, - * the default type is used. The environment variable - * JDK_ALTERNATE_VM and the command line option -XXaltjvm= are also - * checked as ways of specifying which JVM type to invoke. - */ -char * -CheckJvmType(int *pargc, char ***argv, jboolean speculative) { - int i, argi; - int argc; - char **newArgv; - int newArgvIdx = 0; - int isVMType; - int jvmidx = -1; - char *jvmtype = getenv("JDK_ALTERNATE_VM"); - - argc = *pargc; - - /* To make things simpler we always copy the argv array */ - newArgv = JLI_MemAlloc((argc + 1) * sizeof(char *)); - - /* The program name is always present */ - newArgv[newArgvIdx++] = (*argv)[0]; - - for (argi = 1; argi < argc; argi++) { - char *arg = (*argv)[argi]; - isVMType = 0; - -#ifdef JAVA_ARGS - if (arg[0] != '-') { - newArgv[newArgvIdx++] = arg; - continue; - } -#else - if (strcmp(arg, "-classpath") == 0 || - strcmp(arg, "-cp") == 0) { - newArgv[newArgvIdx++] = arg; - argi++; - if (argi < argc) { - newArgv[newArgvIdx++] = (*argv)[argi]; - } - continue; - } - if (arg[0] != '-') break; -#endif - - /* Did the user pass an explicit VM type? */ - i = KnownVMIndex(arg); - if (i >= 0) { - jvmtype = knownVMs[jvmidx = i].name + 1; /* skip the - */ - isVMType = 1; - *pargc = *pargc - 1; - } - - /* Did the user specify an "alternate" VM? */ - else if (strncmp(arg, "-XXaltjvm=", 10) == 0 || strncmp(arg, "-J-XXaltjvm=", 12) == 0) { - isVMType = 1; - jvmtype = arg+((arg[1]=='X')? 10 : 12); - jvmidx = -1; - } - - if (!isVMType) { - newArgv[newArgvIdx++] = arg; - } - } - - /* - * Finish copying the arguments if we aborted the above loop. - * NOTE that if we aborted via "break" then we did NOT copy the - * last argument above, and in addition argi will be less than - * argc. - */ - while (argi < argc) { - newArgv[newArgvIdx++] = (*argv)[argi]; - argi++; - } - - /* argv is null-terminated */ - newArgv[newArgvIdx] = 0; - - /* Copy back argv */ - *argv = newArgv; - *pargc = newArgvIdx; - - /* use the default VM type if not specified (no alias processing) */ - if (jvmtype == NULL) { - char* result = knownVMs[0].name+1; - /* Use a different VM type if we are on a server class machine? */ - if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) && - (ServerClassMachine() == JNI_TRUE)) { - result = knownVMs[0].server_class+1; - } - if (_launcher_debug) { - printf("Default VM: %s\n", result); - } - return result; - } - - /* if using an alternate VM, no alias processing */ - if (jvmidx < 0) - return jvmtype; - - /* Resolve aliases first */ - { - int loopCount = 0; - while (knownVMs[jvmidx].flag == VM_ALIASED_TO) { - int nextIdx = KnownVMIndex(knownVMs[jvmidx].alias); - - if (loopCount > knownVMsCount) { - if (!speculative) { - ReportErrorMessage("Error: Corrupt jvm.cfg file; cycle in alias list.", - JNI_TRUE); - exit(1); - } else { - return "ERROR"; - /* break; */ - } - } - - if (nextIdx < 0) { - if (!speculative) { - ReportErrorMessage2("Error: Unable to resolve VM alias %s", - knownVMs[jvmidx].alias, JNI_TRUE); - exit(1); - } else { - return "ERROR"; - } - } - jvmidx = nextIdx; - jvmtype = knownVMs[jvmidx].name+1; - loopCount++; - } - } - - switch (knownVMs[jvmidx].flag) { - case VM_WARN: - if (!speculative) { - fprintf(stderr, "Warning: %s VM not supported; %s VM will be used\n", - jvmtype, knownVMs[0].name + 1); - } - /* fall through */ - case VM_IGNORE: - jvmtype = knownVMs[jvmidx=0].name + 1; - /* fall through */ - case VM_KNOWN: - break; - case VM_ERROR: - if (!speculative) { - ReportErrorMessage2("Error: %s VM not supported", jvmtype, JNI_TRUE); - exit(1); - } else { - return "ERROR"; - } - } - - return jvmtype; -} -#endif /* ifndef GAMMA */ - -# define KB (1024UL) -# define MB (1024UL * KB) -# define GB (1024UL * MB) - -/* copied from HotSpot function "atomll()" */ -static int -parse_stack_size(const char *s, jlong *result) { - jlong n = 0; - int args_read = sscanf(s, JLONG_FORMAT, &n); - if (args_read != 1) { - return 0; - } - while (*s != '\0' && *s >= '0' && *s <= '9') { - s++; - } - // 4705540: illegal if more characters are found after the first non-digit - if (strlen(s) > 1) { - return 0; - } - switch (*s) { - case 'T': case 't': - *result = n * GB * KB; - return 1; - case 'G': case 'g': - *result = n * GB; - return 1; - case 'M': case 'm': - *result = n * MB; - return 1; - case 'K': case 'k': - *result = n * KB; - return 1; - case '\0': - *result = n; - return 1; - default: - /* Create JVM with default stack and let VM handle malformed -Xss string*/ - return 0; - } -} - -/* - * Adds a new VM option with the given given name and value. - */ -void -AddOption(char *str, void *info) -{ - /* - * Expand options array if needed to accommodate at least one more - * VM option. - */ - if (numOptions >= maxOptions) { - if (options == 0) { - maxOptions = 4; - options = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption)); - } else { - JavaVMOption *tmp; - maxOptions *= 2; - tmp = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption)); - memcpy(tmp, options, numOptions * sizeof(JavaVMOption)); - JLI_MemFree(options); - options = tmp; - } - } - options[numOptions].optionString = str; - options[numOptions++].extraInfo = info; - - if (strncmp(str, "-Xss", 4) == 0) { - jlong tmp; - if (parse_stack_size(str + 4, &tmp)) { - threadStackSize = tmp; - } - } -} - -static void -SetClassPath(const char *s) -{ - char *def; - s = JLI_WildcardExpandClasspath(s); - def = JLI_MemAlloc(strlen(s) + 40); - sprintf(def, "-Djava.class.path=%s", s); - AddOption(def, NULL); -} - -#ifndef GAMMA -/* - * The SelectVersion() routine ensures that an appropriate version of - * the JRE is running. The specification for the appropriate version - * is obtained from either the manifest of a jar file (preferred) or - * from command line options. - * The routine also parses splash screen command line options and - * passes on their values in private environment variables. - */ -static void -SelectVersion(int argc, char **argv, char **main_class) -{ - char *arg; - char **new_argv; - char **new_argp; - char *operand; - char *version = NULL; - char *jre = NULL; - int jarflag = 0; - int headlessflag = 0; - int restrict_search = -1; /* -1 implies not known */ - manifest_info info; - char env_entry[MAXNAMELEN + 24] = ENV_ENTRY "="; - char *splash_file_name = NULL; - char *splash_jar_name = NULL; - char *env_in; - int res; - - /* - * If the version has already been selected, set *main_class - * with the value passed through the environment (if any) and - * simply return. - */ - if ((env_in = getenv(ENV_ENTRY)) != NULL) { - if (*env_in != '\0') - *main_class = JLI_StringDup(env_in); - return; - } - - /* - * Scan through the arguments for options relevant to multiple JRE - * support. For reference, the command line syntax is defined as: - * - * SYNOPSIS - * java [options] class [argument...] - * - * java [options] -jar file.jar [argument...] - * - * As the scan is performed, make a copy of the argument list with - * the version specification options (new to 1.5) removed, so that - * a version less than 1.5 can be exec'd. - * - * Note that due to the syntax of the native Windows interface - * CreateProcess(), processing similar to the following exists in - * the Windows platform specific routine ExecJRE (in java_md.c). - * Changes here should be reproduced there. - */ - new_argv = JLI_MemAlloc((argc + 1) * sizeof(char*)); - new_argv[0] = argv[0]; - new_argp = &new_argv[1]; - argc--; - argv++; - while ((arg = *argv) != 0 && *arg == '-') { - if (strncmp(arg, "-version:", 9) == 0) { - version = arg + 9; - } else if (strcmp(arg, "-jre-restrict-search") == 0) { - restrict_search = 1; - } else if (strcmp(arg, "-no-jre-restrict-search") == 0) { - restrict_search = 0; - } else { - if (strcmp(arg, "-jar") == 0) - jarflag = 1; - /* deal with "unfortunate" classpath syntax */ - if ((strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) && - (argc >= 2)) { - *new_argp++ = arg; - argc--; - argv++; - arg = *argv; - } - - /* - * Checking for headless toolkit option in the some way as AWT does: - * "true" means true and any other value means false - */ - if (strcmp(arg, "-Djava.awt.headless=true") == 0) { - headlessflag = 1; - } else if (strncmp(arg, "-Djava.awt.headless=", 20) == 0) { - headlessflag = 0; - } else if (strncmp(arg, "-splash:", 8) == 0) { - splash_file_name = arg+8; - } - *new_argp++ = arg; - } - argc--; - argv++; - } - if (argc <= 0) { /* No operand? Possibly legit with -[full]version */ - operand = NULL; - } else { - argc--; - *new_argp++ = operand = *argv++; - } - while (argc-- > 0) /* Copy over [argument...] */ - *new_argp++ = *argv++; - *new_argp = NULL; - - /* - * If there is a jar file, read the manifest. If the jarfile can't be - * read, the manifest can't be read from the jar file, or the manifest - * is corrupt, issue the appropriate error messages and exit. - * - * Even if there isn't a jar file, construct a manifest_info structure - * containing the command line information. It's a convenient way to carry - * this data around. - */ - if (jarflag && operand) { - if ((res = JLI_ParseManifest(operand, &info)) != 0) { - if (res == -1) - ReportErrorMessage2("Unable to access jarfile %s", - operand, JNI_TRUE); - else - ReportErrorMessage2("Invalid or corrupt jarfile %s", - operand, JNI_TRUE); - exit(1); - } - - /* - * Command line splash screen option should have precedence - * over the manifest, so the manifest data is used only if - * splash_file_name has not been initialized above during command - * line parsing - */ - if (!headlessflag && !splash_file_name && info.splashscreen_image_file_name) { - splash_file_name = info.splashscreen_image_file_name; - splash_jar_name = operand; - } - } else { - info.manifest_version = NULL; - info.main_class = NULL; - info.jre_version = NULL; - info.jre_restrict_search = 0; - } - - /* - * Passing on splash screen info in environment variables - */ - if (splash_file_name && !headlessflag) { - char* splash_file_entry = JLI_MemAlloc(strlen(SPLASH_FILE_ENV_ENTRY "=")+strlen(splash_file_name)+1); - strcpy(splash_file_entry, SPLASH_FILE_ENV_ENTRY "="); - strcat(splash_file_entry, splash_file_name); - putenv(splash_file_entry); - } - if (splash_jar_name && !headlessflag) { - char* splash_jar_entry = JLI_MemAlloc(strlen(SPLASH_JAR_ENV_ENTRY "=")+strlen(splash_jar_name)+1); - strcpy(splash_jar_entry, SPLASH_JAR_ENV_ENTRY "="); - strcat(splash_jar_entry, splash_jar_name); - putenv(splash_jar_entry); - } - - /* - * The JRE-Version and JRE-Restrict-Search values (if any) from the - * manifest are overwritten by any specified on the command line. - */ - if (version != NULL) - info.jre_version = version; - if (restrict_search != -1) - info.jre_restrict_search = restrict_search; - - /* - * "Valid" returns (other than unrecoverable errors) follow. Set - * main_class as a side-effect of this routine. - */ - if (info.main_class != NULL) - *main_class = JLI_StringDup(info.main_class); - - /* - * If no version selection information is found either on the command - * line or in the manifest, simply return. - */ - if (info.jre_version == NULL) { - JLI_FreeManifest(); - JLI_MemFree(new_argv); - return; - } - - /* - * Check for correct syntax of the version specification (JSR 56). - */ - if (!JLI_ValidVersionString(info.jre_version)) { - ReportErrorMessage2("Syntax error in version specification \"%s\"", - info.jre_version, JNI_TRUE); - exit(1); - } - - /* - * Find the appropriate JVM on the system. Just to be as forgiving as - * possible, if the standard algorithms don't locate an appropriate - * jre, check to see if the one running will satisfy the requirements. - * This can happen on systems which haven't been set-up for multiple - * JRE support. - */ - jre = LocateJRE(&info); - if (_launcher_debug) - printf("JRE-Version = %s, JRE-Restrict-Search = %s Selected = %s\n", - (info.jre_version?info.jre_version:"null"), - (info.jre_restrict_search?"true":"false"), (jre?jre:"null")); - if (jre == NULL) { - if (JLI_AcceptableRelease(FULL_VERSION, info.jre_version)) { - JLI_FreeManifest(); - JLI_MemFree(new_argv); - return; - } else { - ReportErrorMessage2( - "Unable to locate JRE meeting specification \"%s\"", - info.jre_version, JNI_TRUE); - exit(1); - } - } - - /* - * If I'm not the chosen one, exec the chosen one. Returning from - * ExecJRE indicates that I am indeed the chosen one. - * - * The private environment variable _JAVA_VERSION_SET is used to - * prevent the chosen one from re-reading the manifest file and - * using the values found within to override the (potential) command - * line flags stripped from argv (because the target may not - * understand them). Passing the MainClass value is an optimization - * to avoid locating, expanding and parsing the manifest extra - * times. - */ - if (info.main_class != NULL) { - if (strlen(info.main_class) <= MAXNAMELEN) { - (void)strcat(env_entry, info.main_class); - } else { - ReportErrorMessage("Error: main-class: attribute exceeds system limits\n", JNI_TRUE); - exit(1); - } - } - (void)putenv(env_entry); - ExecJRE(jre, new_argv); - JLI_FreeManifest(); - JLI_MemFree(new_argv); - return; -} -#endif /* ifndef GAMMA */ - -/* - * Parses command line arguments. Returns JNI_FALSE if launcher - * should exit without starting vm (e.g. certain version and usage - * options); returns JNI_TRUE if vm needs to be started to process - * given options. *pret (the launcher process return value) is set to - * 0 for a normal exit. - */ -static jboolean -ParseArguments(int *pargc, char ***pargv, char **pjarfile, - char **pclassname, int *pret, const char *jvmpath) -{ - int argc = *pargc; - char **argv = *pargv; - jboolean jarflag = JNI_FALSE; - char *arg; - - *pret = 1; - while ((arg = *argv) != 0 && *arg == '-') { - argv++; --argc; - if (strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) { - if (argc < 1) { - ReportErrorMessage2("%s requires class path specification", - arg, JNI_TRUE); - PrintUsage(); - return JNI_FALSE; - } - SetClassPath(*argv); - argv++; --argc; - } else if (strcmp(arg, "-jar") == 0) { - jarflag = JNI_TRUE; - } else if (strcmp(arg, "-help") == 0 || - strcmp(arg, "-h") == 0 || - strcmp(arg, "-?") == 0) { - PrintUsage(); - *pret = 0; - return JNI_FALSE; - } else if (strcmp(arg, "-version") == 0) { - printVersion = JNI_TRUE; - return JNI_TRUE; - } else if (strcmp(arg, "-showversion") == 0) { - showVersion = JNI_TRUE; - } else if (strcmp(arg, "-X") == 0) { - *pret = PrintXUsage(jvmpath); - return JNI_FALSE; -/* - * The following case provide backward compatibility with old-style - * command line options. - */ - } else if (strcmp(arg, "-fullversion") == 0) { - fprintf(stderr, "%s full version \"%s\"\n", progname, - FULL_VERSION); - *pret = 0; - return JNI_FALSE; - } else if (strcmp(arg, "-verbosegc") == 0) { - AddOption("-verbose:gc", NULL); - } else if (strcmp(arg, "-t") == 0) { - AddOption("-Xt", NULL); - } else if (strcmp(arg, "-tm") == 0) { - AddOption("-Xtm", NULL); - } else if (strcmp(arg, "-debug") == 0) { - AddOption("-Xdebug", NULL); - } else if (strcmp(arg, "-noclassgc") == 0) { - AddOption("-Xnoclassgc", NULL); - } else if (strcmp(arg, "-Xfuture") == 0) { - AddOption("-Xverify:all", NULL); - } else if (strcmp(arg, "-verify") == 0) { - AddOption("-Xverify:all", NULL); - } else if (strcmp(arg, "-verifyremote") == 0) { - AddOption("-Xverify:remote", NULL); - } else if (strcmp(arg, "-noverify") == 0) { - AddOption("-Xverify:none", NULL); - } else if (strcmp(arg, "-XXsuppressExitMessage") == 0) { - noExitErrorMessage = 1; - } else if (strncmp(arg, "-prof", 5) == 0) { - char *p = arg + 5; - char *tmp = JLI_MemAlloc(strlen(arg) + 50); - if (*p) { - sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1); - } else { - sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof"); - } - AddOption(tmp, NULL); - } else if (strncmp(arg, "-ss", 3) == 0 || - strncmp(arg, "-oss", 4) == 0 || - strncmp(arg, "-ms", 3) == 0 || - strncmp(arg, "-mx", 3) == 0) { - char *tmp = JLI_MemAlloc(strlen(arg) + 6); - sprintf(tmp, "-X%s", arg + 1); /* skip '-' */ - AddOption(tmp, NULL); - } else if (strcmp(arg, "-checksource") == 0 || - strcmp(arg, "-cs") == 0 || - strcmp(arg, "-noasyncgc") == 0) { - /* No longer supported */ - fprintf(stderr, - "Warning: %s option is no longer supported.\n", - arg); - } else if (strncmp(arg, "-version:", 9) == 0 || - strcmp(arg, "-no-jre-restrict-search") == 0 || - strcmp(arg, "-jre-restrict-search") == 0 || - strncmp(arg, "-splash:", 8) == 0) { - ; /* Ignore machine independent options already handled */ - } else if (RemovableMachineDependentOption(arg) ) { - ; /* Do not pass option to vm. */ - } - else { - AddOption(arg, NULL); - } - } - - if (--argc >= 0) { - if (jarflag) { - *pjarfile = *argv++; - *pclassname = 0; - } else { - *pjarfile = 0; - *pclassname = *argv++; - } - *pargc = argc; - *pargv = argv; - } - - return JNI_TRUE; -} - -/* - * Initializes the Java Virtual Machine. Also frees options array when - * finished. - */ -static jboolean -InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn) -{ - JavaVMInitArgs args; - jint r; - - memset(&args, 0, sizeof(args)); - args.version = JNI_VERSION_1_2; - args.nOptions = numOptions; - args.options = options; - args.ignoreUnrecognized = JNI_FALSE; - - if (_launcher_debug) { - int i = 0; - printf("JavaVM args:\n "); - printf("version 0x%08lx, ", (long)args.version); - printf("ignoreUnrecognized is %s, ", - args.ignoreUnrecognized ? "JNI_TRUE" : "JNI_FALSE"); - printf("nOptions is %ld\n", (long)args.nOptions); - for (i = 0; i < numOptions; i++) - printf(" option[%2d] = '%s'\n", - i, args.options[i].optionString); - } - - r = ifn->CreateJavaVM(pvm, (void **)penv, &args); - JLI_MemFree(options); - return r == JNI_OK; -} - - -#define NULL_CHECK0(e) if ((e) == 0) return 0 -#define NULL_CHECK(e) if ((e) == 0) return - -static jstring platformEncoding = NULL; -static jstring getPlatformEncoding(JNIEnv *env) { - if (platformEncoding == NULL) { - jstring propname = (*env)->NewStringUTF(env, "sun.jnu.encoding"); - if (propname) { - jclass cls; - jmethodID mid; - NULL_CHECK0 (cls = (*env)->FindClass(env, "java/lang/System")); - NULL_CHECK0 (mid = (*env)->GetStaticMethodID( - env, cls, - "getProperty", - "(Ljava/lang/String;)Ljava/lang/String;")); - platformEncoding = (*env)->CallStaticObjectMethod ( - env, cls, mid, propname); - } - } - return platformEncoding; -} - -static jboolean isEncodingSupported(JNIEnv *env, jstring enc) { - jclass cls; - jmethodID mid; - NULL_CHECK0 (cls = (*env)->FindClass(env, "java/nio/charset/Charset")); - NULL_CHECK0 (mid = (*env)->GetStaticMethodID( - env, cls, - "isSupported", - "(Ljava/lang/String;)Z")); - return (*env)->CallStaticBooleanMethod(env, cls, mid, enc); -} - -/* - * Returns a new Java string object for the specified platform string. - */ -static jstring -NewPlatformString(JNIEnv *env, char *s) -{ - int len = (int)strlen(s); - jclass cls; - jmethodID mid; - jbyteArray ary; - jstring enc; - - if (s == NULL) - return 0; - enc = getPlatformEncoding(env); - - ary = (*env)->NewByteArray(env, len); - if (ary != 0) { - jstring str = 0; - (*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s); - if (!(*env)->ExceptionOccurred(env)) { - if (isEncodingSupported(env, enc) == JNI_TRUE) { - NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); - NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "", - "([BLjava/lang/String;)V")); - str = (*env)->NewObject(env, cls, mid, ary, enc); - } else { - /*If the encoding specified in sun.jnu.encoding is not - endorsed by "Charset.isSupported" we have to fall back - to use String(byte[]) explicitly here without specifying - the encoding name, in which the StringCoding class will - pickup the iso-8859-1 as the fallback converter for us. - */ - NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); - NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "", - "([B)V")); - str = (*env)->NewObject(env, cls, mid, ary); - } - (*env)->DeleteLocalRef(env, ary); - return str; - } - } - return 0; -} - -/* - * Returns a new array of Java string objects for the specified - * array of platform strings. - */ -static jobjectArray -NewPlatformStringArray(JNIEnv *env, char **strv, int strc) -{ - jarray cls; - jarray ary; - int i; - - NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); - NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0)); - for (i = 0; i < strc; i++) { - jstring str = NewPlatformString(env, *strv++); - NULL_CHECK0(str); - (*env)->SetObjectArrayElement(env, ary, i, str); - (*env)->DeleteLocalRef(env, str); - } - return ary; -} - -/* - * Loads a class, convert the '.' to '/'. - */ -static jclass -LoadClass(JNIEnv *env, char *name) -{ - char *buf = JLI_MemAlloc(strlen(name) + 1); - char *s = buf, *t = name, c; - jclass cls; - jlong start, end; - - if (_launcher_debug) - start = CounterGet(); - - do { - c = *t++; - *s++ = (c == '.') ? '/' : c; - } while (c != '\0'); - cls = (*env)->FindClass(env, buf); - JLI_MemFree(buf); - - if (_launcher_debug) { - end = CounterGet(); - printf("%ld micro seconds to load main class\n", - (long)(jint)Counter2Micros(end-start)); - printf("----_JAVA_LAUNCHER_DEBUG----\n"); - } - - return cls; -} - - -/* - * Returns the main class name for the specified jar file. - */ -static jstring -GetMainClassName(JNIEnv *env, char *jarname) -{ -#define MAIN_CLASS "Main-Class" - jclass cls; - jmethodID mid; - jobject jar, man, attr; - jstring str, result = 0; - - NULL_CHECK0(cls = (*env)->FindClass(env, "java/util/jar/JarFile")); - NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "", - "(Ljava/lang/String;)V")); - NULL_CHECK0(str = NewPlatformString(env, jarname)); - NULL_CHECK0(jar = (*env)->NewObject(env, cls, mid, str)); - NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "getManifest", - "()Ljava/util/jar/Manifest;")); - man = (*env)->CallObjectMethod(env, jar, mid); - if (man != 0) { - NULL_CHECK0(mid = (*env)->GetMethodID(env, - (*env)->GetObjectClass(env, man), - "getMainAttributes", - "()Ljava/util/jar/Attributes;")); - attr = (*env)->CallObjectMethod(env, man, mid); - if (attr != 0) { - NULL_CHECK0(mid = (*env)->GetMethodID(env, - (*env)->GetObjectClass(env, attr), - "getValue", - "(Ljava/lang/String;)Ljava/lang/String;")); - NULL_CHECK0(str = NewPlatformString(env, MAIN_CLASS)); - result = (*env)->CallObjectMethod(env, attr, mid, str); - } - } - return result; -} - -#ifdef JAVA_ARGS -static char *java_args[] = JAVA_ARGS; -static char *app_classpath[] = APP_CLASSPATH; - -/* - * For tools, convert command line args thus: - * javac -cp foo:foo/"*" -J-ms32m ... - * java -ms32m -cp JLI_WildcardExpandClasspath(foo:foo/"*") ... - */ -static void -TranslateApplicationArgs(int *pargc, char ***pargv) -{ - const int NUM_ARGS = (sizeof(java_args) / sizeof(char *)); - int argc = *pargc; - char **argv = *pargv; - int nargc = argc + NUM_ARGS; - char **nargv = JLI_MemAlloc((nargc + 1) * sizeof(char *)); - int i; - - *pargc = nargc; - *pargv = nargv; - - /* Copy the VM arguments (i.e. prefixed with -J) */ - for (i = 0; i < NUM_ARGS; i++) { - char *arg = java_args[i]; - if (arg[0] == '-' && arg[1] == 'J') { - *nargv++ = arg + 2; - } - } - - for (i = 0; i < argc; i++) { - char *arg = argv[i]; - if (arg[0] == '-' && arg[1] == 'J') { - if (arg[2] == '\0') { - ReportErrorMessage("Error: the -J option should not be " - "followed by a space.", JNI_TRUE); - exit(1); - } - *nargv++ = arg + 2; - } - } - - /* Copy the rest of the arguments */ - for (i = 0; i < NUM_ARGS; i++) { - char *arg = java_args[i]; - if (arg[0] != '-' || arg[1] != 'J') { - *nargv++ = arg; - } - } - for (i = 0; i < argc; i++) { - char *arg = argv[i]; - if (arg[0] == '-') { - if (arg[1] == 'J') - continue; -#ifdef EXPAND_CLASSPATH_WILDCARDS - if (arg[1] == 'c' - && (strcmp(arg, "-cp") == 0 || - strcmp(arg, "-classpath") == 0) - && i < argc - 1) { - *nargv++ = arg; - *nargv++ = (char *) JLI_WildcardExpandClasspath(argv[i+1]); - i++; - continue; - } -#endif - } - *nargv++ = arg; - } - *nargv = 0; -} - -/* - * For our tools, we try to add 3 VM options: - * -Denv.class.path= - * -Dapplication.home= - * -Djava.class.path= - * is the user's setting of CLASSPATH -- for instance the user - * tells javac where to find binary classes through this environment - * variable. Notice that users will be able to compile against our - * tools classes (sun.tools.javac.Main) only if they explicitly add - * tools.jar to CLASSPATH. - * is the directory where the application is installed. - * is the classpath to where our apps' classfiles are. - */ -static jboolean -AddApplicationOptions() -{ - const int NUM_APP_CLASSPATH = (sizeof(app_classpath) / sizeof(char *)); - char *envcp, *appcp, *apphome; - char home[MAXPATHLEN]; /* application home */ - char separator[] = { PATH_SEPARATOR, '\0' }; - int size, i; - int strlenHome; - - { - const char *s = getenv("CLASSPATH"); - if (s) { - s = (char *) JLI_WildcardExpandClasspath(s); - /* 40 for -Denv.class.path= */ - envcp = (char *)JLI_MemAlloc(strlen(s) + 40); - sprintf(envcp, "-Denv.class.path=%s", s); - AddOption(envcp, NULL); - } - } - - if (!GetApplicationHome(home, sizeof(home))) { - ReportErrorMessage("Can't determine application home", JNI_TRUE); - return JNI_FALSE; - } - - /* 40 for '-Dapplication.home=' */ - apphome = (char *)JLI_MemAlloc(strlen(home) + 40); - sprintf(apphome, "-Dapplication.home=%s", home); - AddOption(apphome, NULL); - - /* How big is the application's classpath? */ - size = 40; /* 40: "-Djava.class.path=" */ - strlenHome = (int)strlen(home); - for (i = 0; i < NUM_APP_CLASSPATH; i++) { - size += strlenHome + (int)strlen(app_classpath[i]) + 1; /* 1: separator */ - } - appcp = (char *)JLI_MemAlloc(size + 1); - strcpy(appcp, "-Djava.class.path="); - for (i = 0; i < NUM_APP_CLASSPATH; i++) { - strcat(appcp, home); /* c:\program files\myapp */ - strcat(appcp, app_classpath[i]); /* \lib\myapp.jar */ - strcat(appcp, separator); /* ; */ - } - appcp[strlen(appcp)-1] = '\0'; /* remove trailing path separator */ - AddOption(appcp, NULL); - return JNI_TRUE; -} -#endif /* JAVA_ARGS */ - -/* - * inject the -Dsun.java.command pseudo property into the args structure - * this pseudo property is used in the HotSpot VM to expose the - * Java class name and arguments to the main method to the VM. The - * HotSpot VM uses this pseudo property to store the Java class name - * (or jar file name) and the arguments to the class's main method - * to the instrumentation memory region. The sun.java.command pseudo - * property is not exported by HotSpot to the Java layer. - */ -void -SetJavaCommandLineProp(char *classname, char *jarfile, - int argc, char **argv) -{ - - int i = 0; - size_t len = 0; - char* javaCommand = NULL; - char* dashDstr = "-Dsun.java.command="; - - if (classname == NULL && jarfile == NULL) { - /* unexpected, one of these should be set. just return without - * setting the property - */ - return; - } - - /* if the class name is not set, then use the jarfile name */ - if (classname == NULL) { - classname = jarfile; - } - - /* determine the amount of memory to allocate assuming - * the individual components will be space separated - */ - len = strlen(classname); - for (i = 0; i < argc; i++) { - len += strlen(argv[i]) + 1; - } - - /* allocate the memory */ - javaCommand = (char*) JLI_MemAlloc(len + strlen(dashDstr) + 1); - - /* build the -D string */ - *javaCommand = '\0'; - strcat(javaCommand, dashDstr); - strcat(javaCommand, classname); - - for (i = 0; i < argc; i++) { - /* the components of the string are space separated. In - * the case of embedded white space, the relationship of - * the white space separated components to their true - * positional arguments will be ambiguous. This issue may - * be addressed in a future release. - */ - strcat(javaCommand, " "); - strcat(javaCommand, argv[i]); - } - - AddOption(javaCommand, NULL); -} - -/* - * JVM would like to know if it's created by a standard Sun launcher, or by - * user native application, the following property indicates the former. - */ -void SetJavaLauncherProp() { - AddOption("-Dsun.java.launcher=" LAUNCHER_TYPE, NULL); -} - -/* - * Prints the version information from the java.version and other properties. - */ -static void -PrintJavaVersion(JNIEnv *env) -{ - jclass ver; - jmethodID print; - - NULL_CHECK(ver = (*env)->FindClass(env, "sun/misc/Version")); - NULL_CHECK(print = (*env)->GetStaticMethodID(env, ver, "print", "()V")); - - (*env)->CallStaticVoidMethod(env, ver, print); -} - -/* - * Prints default usage message. - */ -static void -PrintUsage(void) -{ -#ifndef GAMMA - int i; -#endif - - fprintf(stdout, - "Usage: %s [-options] class [args...]\n" - " (to execute a class)\n" - " or %s [-options] -jar jarfile [args...]\n" - " (to execute a jar file)\n" - "\n" - "where options include:\n", - progname, - progname); - -#ifndef GAMMA - PrintMachineDependentOptions(); - - if ((knownVMs[0].flag == VM_KNOWN) || - (knownVMs[0].flag == VM_IF_SERVER_CLASS)) { - fprintf(stdout, " %s\t to select the \"%s\" VM\n", - knownVMs[0].name, knownVMs[0].name+1); - } - for (i=1; i\n" -" -classpath \n" -" A %c separated list of directories, JAR archives,\n" -" and ZIP archives to search for class files.\n" -" -D=\n" -" set a system property\n" -" -verbose[:class|gc|jni]\n" -" enable verbose output\n" -" -version print product version and exit\n" -" -version:\n" -" require the specified version to run\n" -" -showversion print product version and continue\n" -" -jre-restrict-search | -jre-no-restrict-search\n" -" include/exclude user private JREs in the version search\n" -" -? -help print this help message\n" -" -X print help on non-standard options\n" -" -ea[:...|:]\n" -" -enableassertions[:...|:]\n" -" enable assertions\n" -" -da[:...|:]\n" -" -disableassertions[:...|:]\n" -" disable assertions\n" -" -esa | -enablesystemassertions\n" -" enable system assertions\n" -" -dsa | -disablesystemassertions\n" -" disable system assertions\n" -" -agentlib:[=]\n" -" load native agent library , e.g. -agentlib:hprof\n" -" see also, -agentlib:jdwp=help and -agentlib:hprof=help\n" -" -agentpath:[=]\n" -" load native agent library by full pathname\n" -" -javaagent:[=]\n" -" load Java programming language agent, see java.lang.instrument\n" -" -splash:\n" -" show splash screen with specified image\n" - - ,PATH_SEPARATOR); -} - -/* - * Print usage message for -X options. - */ -static jint -PrintXUsage(const char *jvmpath) -{ - /* - A 32 bit cushion to prevent buffer overrun, noting that - fopen(3C) may fail if the buffer exceeds MAXPATHLEN. - */ - char path[MAXPATHLEN+32]; - char buf[128]; - size_t n; - FILE *fp; - static const char Xusage_txt[] = "/Xusage.txt"; - - strcpy(path, jvmpath); - /* Note the FILE_SEPARATOR is platform dependent */ - strcpy(strrchr(path, FILE_SEPARATOR), Xusage_txt); - fp = fopen(path, "r"); - if (fp == 0) { - fprintf(stderr, "Can't open %s\n", path); - return 1; - } - while ((n = fread(buf, 1, sizeof(buf), fp)) != 0) { - fwrite(buf, 1, n, stdout); - } - fclose(fp); - return 0; -} - -#ifndef GAMMA -/* - * Read the jvm.cfg file and fill the knownJVMs[] array. - * - * The functionality of the jvm.cfg file is subject to change without - * notice and the mechanism will be removed in the future. - * - * The lexical structure of the jvm.cfg file is as follows: - * - * jvmcfg := { vmLine } - * vmLine := knownLine - * | aliasLine - * | warnLine - * | ignoreLine - * | errorLine - * | predicateLine - * | commentLine - * knownLine := flag "KNOWN" EOL - * warnLine := flag "WARN" EOL - * ignoreLine := flag "IGNORE" EOL - * errorLine := flag "ERROR" EOL - * aliasLine := flag "ALIASED_TO" flag EOL - * predicateLine := flag "IF_SERVER_CLASS" flag EOL - * commentLine := "#" text EOL - * flag := "-" identifier - * - * The semantics are that when someone specifies a flag on the command line: - * - if the flag appears on a knownLine, then the identifier is used as - * the name of the directory holding the JVM library (the name of the JVM). - * - if the flag appears as the first flag on an aliasLine, the identifier - * of the second flag is used as the name of the JVM. - * - if the flag appears on a warnLine, the identifier is used as the - * name of the JVM, but a warning is generated. - * - if the flag appears on an ignoreLine, the identifier is recognized as the - * name of a JVM, but the identifier is ignored and the default vm used - * - if the flag appears on an errorLine, an error is generated. - * - if the flag appears as the first flag on a predicateLine, and - * the machine on which you are running passes the predicate indicated, - * then the identifier of the second flag is used as the name of the JVM, - * otherwise the identifier of the first flag is used as the name of the JVM. - * If no flag is given on the command line, the first vmLine of the jvm.cfg - * file determines the name of the JVM. - * PredicateLines are only interpreted on first vmLine of a jvm.cfg file, - * since they only make sense if someone hasn't specified the name of the - * JVM on the command line. - * - * The intent of the jvm.cfg file is to allow several JVM libraries to - * be installed in different subdirectories of a single JRE installation, - * for space-savings and convenience in testing. - * The intent is explicitly not to provide a full aliasing or predicate - * mechanism. - */ -jint -ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative) -{ - FILE *jvmCfg; - char jvmCfgName[MAXPATHLEN+20]; - char line[MAXPATHLEN+20]; - int cnt = 0; - int lineno = 0; - jlong start, end; - int vmType; - char *tmpPtr; - char *altVMName = NULL; - char *serverClassVMName = NULL; - static char *whiteSpace = " \t"; - if (_launcher_debug) { - start = CounterGet(); - } - - strcpy(jvmCfgName, jrepath); - strcat(jvmCfgName, FILESEP "lib" FILESEP); - strcat(jvmCfgName, arch); - strcat(jvmCfgName, FILESEP "jvm.cfg"); - - jvmCfg = fopen(jvmCfgName, "r"); - if (jvmCfg == NULL) { - if (!speculative) { - ReportErrorMessage2("Error: could not open `%s'", jvmCfgName, - JNI_TRUE); - exit(1); - } else { - return -1; - } - } - while (fgets(line, sizeof(line), jvmCfg) != NULL) { - vmType = VM_UNKNOWN; - lineno++; - if (line[0] == '#') - continue; - if (line[0] != '-') { - fprintf(stderr, "Warning: no leading - on line %d of `%s'\n", - lineno, jvmCfgName); - } - if (cnt >= knownVMsLimit) { - GrowKnownVMs(cnt); - } - line[strlen(line)-1] = '\0'; /* remove trailing newline */ - tmpPtr = line + strcspn(line, whiteSpace); - if (*tmpPtr == 0) { - fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n", - lineno, jvmCfgName); - } else { - /* Null-terminate this string for JLI_StringDup below */ - *tmpPtr++ = 0; - tmpPtr += strspn(tmpPtr, whiteSpace); - if (*tmpPtr == 0) { - fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n", - lineno, jvmCfgName); - } else { - if (!strncmp(tmpPtr, "KNOWN", strlen("KNOWN"))) { - vmType = VM_KNOWN; - } else if (!strncmp(tmpPtr, "ALIASED_TO", strlen("ALIASED_TO"))) { - tmpPtr += strcspn(tmpPtr, whiteSpace); - if (*tmpPtr != 0) { - tmpPtr += strspn(tmpPtr, whiteSpace); - } - if (*tmpPtr == 0) { - fprintf(stderr, "Warning: missing VM alias on line %d of `%s'\n", - lineno, jvmCfgName); - } else { - /* Null terminate altVMName */ - altVMName = tmpPtr; - tmpPtr += strcspn(tmpPtr, whiteSpace); - *tmpPtr = 0; - vmType = VM_ALIASED_TO; - } - } else if (!strncmp(tmpPtr, "WARN", strlen("WARN"))) { - vmType = VM_WARN; - } else if (!strncmp(tmpPtr, "IGNORE", strlen("IGNORE"))) { - vmType = VM_IGNORE; - } else if (!strncmp(tmpPtr, "ERROR", strlen("ERROR"))) { - vmType = VM_ERROR; - } else if (!strncmp(tmpPtr, - "IF_SERVER_CLASS", - strlen("IF_SERVER_CLASS"))) { - tmpPtr += strcspn(tmpPtr, whiteSpace); - if (*tmpPtr != 0) { - tmpPtr += strspn(tmpPtr, whiteSpace); - } - if (*tmpPtr == 0) { - fprintf(stderr, "Warning: missing server class VM on line %d of `%s'\n", - lineno, jvmCfgName); - } else { - /* Null terminate server class VM name */ - serverClassVMName = tmpPtr; - tmpPtr += strcspn(tmpPtr, whiteSpace); - *tmpPtr = 0; - vmType = VM_IF_SERVER_CLASS; - } - } else { - fprintf(stderr, "Warning: unknown VM type on line %d of `%s'\n", - lineno, &jvmCfgName[0]); - vmType = VM_KNOWN; - } - } - } - - if (_launcher_debug) - printf("jvm.cfg[%d] = ->%s<-\n", cnt, line); - if (vmType != VM_UNKNOWN) { - knownVMs[cnt].name = JLI_StringDup(line); - knownVMs[cnt].flag = vmType; - switch (vmType) { - default: - break; - case VM_ALIASED_TO: - knownVMs[cnt].alias = JLI_StringDup(altVMName); - if (_launcher_debug) { - printf(" name: %s vmType: %s alias: %s\n", - knownVMs[cnt].name, "VM_ALIASED_TO", knownVMs[cnt].alias); - } - break; - case VM_IF_SERVER_CLASS: - knownVMs[cnt].server_class = JLI_StringDup(serverClassVMName); - if (_launcher_debug) { - printf(" name: %s vmType: %s server_class: %s\n", - knownVMs[cnt].name, "VM_IF_SERVER_CLASS", knownVMs[cnt].server_class); - } - break; - } - cnt++; - } - } - fclose(jvmCfg); - knownVMsCount = cnt; - - if (_launcher_debug) { - end = CounterGet(); - printf("%ld micro seconds to parse jvm.cfg\n", - (long)(jint)Counter2Micros(end-start)); - } - - return cnt; -} - - -static void -GrowKnownVMs(int minimum) -{ - struct vmdesc* newKnownVMs; - int newMax; - - newMax = (knownVMsLimit == 0 ? INIT_MAX_KNOWN_VMS : (2 * knownVMsLimit)); - if (newMax <= minimum) { - newMax = minimum; - } - newKnownVMs = (struct vmdesc*) JLI_MemAlloc(newMax * sizeof(struct vmdesc)); - if (knownVMs != NULL) { - memcpy(newKnownVMs, knownVMs, knownVMsLimit * sizeof(struct vmdesc)); - } - JLI_MemFree(knownVMs); - knownVMs = newKnownVMs; - knownVMsLimit = newMax; -} - - -/* Returns index of VM or -1 if not found */ -static int -KnownVMIndex(const char* name) -{ - int i; - if (strncmp(name, "-J", 2) == 0) name += 2; - for (i = 0; i < knownVMsCount; i++) { - if (!strcmp(name, knownVMs[i].name)) { - return i; - } - } - return -1; -} - -static void -FreeKnownVMs() -{ - int i; - for (i = 0; i < knownVMsCount; i++) { - JLI_MemFree(knownVMs[i].name); - knownVMs[i].name = NULL; - } - JLI_MemFree(knownVMs); -} - - -/* - * Displays the splash screen according to the jar file name - * and image file names stored in environment variables - */ -static void -ShowSplashScreen() -{ - const char *jar_name = getenv(SPLASH_JAR_ENV_ENTRY); - const char *file_name = getenv(SPLASH_FILE_ENV_ENTRY); - int data_size; - void *image_data; - if (jar_name) { - image_data = JLI_JarUnpackFile(jar_name, file_name, &data_size); - if (image_data) { - DoSplashInit(); - DoSplashLoadMemory(image_data, data_size); - JLI_MemFree(image_data); - } - } else if (file_name) { - DoSplashInit(); - DoSplashLoadFile(file_name); - } else { - return; - } - DoSplashSetFileJarName(file_name, jar_name); -} - -#endif /* ifndef GAMMA */ diff --git a/hotspot/src/share/tools/launcher/java.h b/hotspot/src/share/tools/launcher/java.h deleted file mode 100644 index 1dd79618c84..00000000000 --- a/hotspot/src/share/tools/launcher/java.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - - -#ifndef _JAVA_H_ -#define _JAVA_H_ - -/* - * Get system specific defines. - */ -#include "jni.h" -#include "java_md.h" -#include "jli_util.h" - -/* - * Pointers to the needed JNI invocation API, initialized by LoadJavaVM. - */ -typedef jint (JNICALL *CreateJavaVM_t)(JavaVM **pvm, void **env, void *args); -typedef jint (JNICALL *GetDefaultJavaVMInitArgs_t)(void *args); - -typedef struct { - CreateJavaVM_t CreateJavaVM; - GetDefaultJavaVMInitArgs_t GetDefaultJavaVMInitArgs; -} InvocationFunctions; - -/* - * Prototypes for launcher functions in the system specific java_md.c. - */ - -jboolean -LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn); - -void -GetXUsagePath(char *buf, jint bufsize); - -jboolean -GetApplicationHome(char *buf, jint bufsize); - -const char * -GetArch(); - -void CreateExecutionEnvironment(int *_argc, - char ***_argv, - char jrepath[], - jint so_jrepath, - char jvmpath[], - jint so_jvmpath, - char **original_argv); - -/* - * Report an error message to stderr or a window as appropriate. The - * flag always is set to JNI_TRUE if message is to be reported to both - * strerr and windows and set to JNI_FALSE if the message should only - * be sent to a window. - */ -void ReportErrorMessage(char * message, jboolean always); -void ReportErrorMessage2(char * format, char * string, jboolean always); - -/* - * Report an exception which terminates the vm to stderr or a window - * as appropriate. - */ -void ReportExceptionDescription(JNIEnv * env); - -jboolean RemovableMachineDependentOption(char * option); -void PrintMachineDependentOptions(); - -/* - * Block current thread and continue execution in new thread - */ -int ContinueInNewThread(int (JNICALL *continuation)(void *), - jlong stack_size, void * args); - -/* sun.java.launcher.* platform properties. */ -void SetJavaLauncherPlatformProps(void); - -/* - * Functions defined in java.c and used in java_md.c. - */ -jint ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative); -char *CheckJvmType(int *argc, char ***argv, jboolean speculative); -void AddOption(char *str, void *info); - -/* - * Make launcher spit debug output. - */ -extern jboolean _launcher_debug; - -#endif /* _JAVA_H_ */ diff --git a/hotspot/src/share/tools/launcher/jli_util.c b/hotspot/src/share/tools/launcher/jli_util.c deleted file mode 100644 index 36b164e3d37..00000000000 --- a/hotspot/src/share/tools/launcher/jli_util.c +++ /dev/null @@ -1,89 +0,0 @@ - -/* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include -#include -#include "jli_util.h" - -#ifdef GAMMA -#ifdef TARGET_OS_FAMILY_windows -#define strdup _strdup -#endif -#endif - -/* - * Returns a pointer to a block of at least 'size' bytes of memory. - * Prints error message and exits if the memory could not be allocated. - */ -void * -JLI_MemAlloc(size_t size) -{ - void *p = malloc(size); - if (p == 0) { - perror("malloc"); - exit(1); - } - return p; -} - -/* - * Equivalent to realloc(size). - * Prints error message and exits if the memory could not be reallocated. - */ -void * -JLI_MemRealloc(void *ptr, size_t size) -{ - void *p = realloc(ptr, size); - if (p == 0) { - perror("realloc"); - exit(1); - } - return p; -} - -/* - * Wrapper over strdup(3C) which prints an error message and exits if memory - * could not be allocated. - */ -char * -JLI_StringDup(const char *s1) -{ - char *s = strdup(s1); - if (s == NULL) { - perror("strdup"); - exit(1); - } - return s; -} - -/* - * Very equivalent to free(ptr). - * Here to maintain pairing with the above routines. - */ -void -JLI_MemFree(void *ptr) -{ - free(ptr); -} diff --git a/hotspot/src/share/tools/launcher/wildcard.c b/hotspot/src/share/tools/launcher/wildcard.c deleted file mode 100644 index 8b3cbcd69c4..00000000000 --- a/hotspot/src/share/tools/launcher/wildcard.c +++ /dev/null @@ -1,496 +0,0 @@ -/* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. - * 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. - * - */ - -/* - * Class-Path Wildcards - * - * The syntax for wildcards is a single asterisk. The class path - * foo/"*", e.g., loads all jar files in the directory named foo. - * (This requires careful quotation when used in shell scripts.) - * - * Only files whose names end in .jar or .JAR are matched. - * Files whose names end in .zip, or which have a particular - * magic number, regardless of filename extension, are not - * matched. - * - * Files are considered regardless of whether or not they are - * "hidden" in the UNIX sense, i.e., have names beginning with '.'. - * - * A wildcard only matches jar files, not class files in the same - * directory. If you want to load both class files and jar files from - * a single directory foo then you can say foo:foo/"*", or foo/"*":foo - * if you want the jar files to take precedence. - * - * Subdirectories are not searched recursively, i.e., foo/"*" only - * looks for jar files in foo, not in foo/bar, foo/baz, etc. - * - * Expansion of wildcards is done early, prior to the invocation of a - * program's main method, rather than late, during the class-loading - * process itself. Each element of the input class path containing a - * wildcard is replaced by the (possibly empty) sequence of elements - * generated by enumerating the jar files in the named directory. If - * the directory foo contains a.jar, b.jar, and c.jar, - * e.g., then the class path foo/"*" is expanded into - * foo/a.jar:foo/b.jar:foo/c.jar, and that string would be the value - * of the system property java.class.path. - * - * The order in which the jar files in a directory are enumerated in - * the expanded class path is not specified and may vary from platform - * to platform and even from moment to moment on the same machine. A - * well-constructed application should not depend upon any particular - * order. If a specific order is required then the jar files can be - * enumerated explicitly in the class path. - * - * The CLASSPATH environment variable is not treated any differently - * from the -classpath (equiv. -cp) command-line option, - * i.e. wildcards are honored in all these cases. - * - * Class-path wildcards are not honored in the Class-Path jar-manifest - * header. - * - * Class-path wildcards are honored not only by the Java launcher but - * also by most other command-line tools that accept class paths, and - * in particular by javac and javadoc. - * - * Class-path wildcards are not honored in any other kind of path, and - * especially not in the bootstrap class path, which is a mere - * artifact of our implementation and not something that developers - * should use. - * - * Classpath wildcards are only expanded in the Java launcher code, - * supporting the use of wildcards on the command line and in the - * CLASSPATH environment variable. We do not support the use of - * wildcards by applications that embed the JVM. - */ - -#include -#include -#include -#include -#include -#include "java.h" /* Strictly for PATH_SEPARATOR/FILE_SEPARATOR */ -#include "jli_util.h" - -#ifdef _WIN32 -#include -#else /* Unix */ -#include -#include -#endif /* Unix */ - -static int -exists(const char* filename) -{ -#ifdef _WIN32 - return _access(filename, 0) == 0; -#else - return access(filename, F_OK) == 0; -#endif -} - -#define NEW_(TYPE) ((TYPE) JLI_MemAlloc(sizeof(struct TYPE##_))) - -/* - * Wildcard directory iteration. - * WildcardIterator_for(wildcard) returns an iterator. - * Each call to that iterator's next() method returns the basename - * of an entry in the wildcard's directory. The basename's memory - * belongs to the iterator. The caller is responsible for prepending - * the directory name and file separator, if necessary. - * When done with the iterator, call the close method to clean up. - */ -typedef struct WildcardIterator_* WildcardIterator; - -#ifdef _WIN32 -struct WildcardIterator_ -{ - HANDLE handle; - char *firstFile; /* Stupid FindFirstFile...FindNextFile */ -}; - -static WildcardIterator -WildcardIterator_for(const char *wildcard) -{ - WIN32_FIND_DATA find_data; - WildcardIterator it = NEW_(WildcardIterator); - HANDLE handle = FindFirstFile(wildcard, &find_data); - if (handle == INVALID_HANDLE_VALUE) - return NULL; - it->handle = handle; - it->firstFile = find_data.cFileName; - return it; -} - -static char * -WildcardIterator_next(WildcardIterator it) -{ - WIN32_FIND_DATA find_data; - if (it->firstFile != NULL) { - char *firstFile = it->firstFile; - it->firstFile = NULL; - return firstFile; - } - return FindNextFile(it->handle, &find_data) - ? find_data.cFileName : NULL; -} - -static void -WildcardIterator_close(WildcardIterator it) -{ - if (it) { - FindClose(it->handle); - JLI_MemFree(it->firstFile); - JLI_MemFree(it); - } -} - -#else /* Unix */ -struct WildcardIterator_ -{ - DIR *dir; -}; - -static WildcardIterator -WildcardIterator_for(const char *wildcard) -{ - DIR *dir; - int wildlen = strlen(wildcard); - if (wildlen < 2) { - dir = opendir("."); - } else { - char *dirname = JLI_StringDup(wildcard); - dirname[wildlen - 1] = '\0'; - dir = opendir(dirname); - JLI_MemFree(dirname); - } - if (dir == NULL) - return NULL; - else { - WildcardIterator it = NEW_(WildcardIterator); - it->dir = dir; - return it; - } -} - -static char * -WildcardIterator_next(WildcardIterator it) -{ - struct dirent* dirp = readdir(it->dir); - return dirp ? dirp->d_name : NULL; -} - -static void -WildcardIterator_close(WildcardIterator it) -{ - if (it) { - closedir(it->dir); - JLI_MemFree(it); - } -} -#endif /* Unix */ - -static int -equal(const char *s1, const char *s2) -{ - return strcmp(s1, s2) == 0; -} - -/* - * FileList ADT - a dynamic list of C filenames - */ -struct FileList_ -{ - char **files; - int size; - int capacity; -}; -typedef struct FileList_ *FileList; - -static FileList -FileList_new(int capacity) -{ - FileList fl = NEW_(FileList); - fl->capacity = capacity; - fl->files = (char **) JLI_MemAlloc(capacity * sizeof(fl->files[0])); - fl->size = 0; - return fl; -} - -#ifdef DEBUG_WILDCARD -static void -FileList_print(FileList fl) -{ - int i; - putchar('['); - for (i = 0; i < fl->size; i++) { - if (i > 0) printf(", "); - printf("\"%s\"",fl->files[i]); - } - putchar(']'); -} -#endif - -static void -FileList_free(FileList fl) -{ - if (fl) { - if (fl->files) { - int i; - for (i = 0; i < fl->size; i++) - JLI_MemFree(fl->files[i]); - JLI_MemFree(fl->files); - } - JLI_MemFree(fl); - } -} - -static void -FileList_ensureCapacity(FileList fl, int capacity) -{ - if (fl->capacity < capacity) { - while (fl->capacity < capacity) - fl->capacity *= 2; - fl->files = JLI_MemRealloc(fl->files, - fl->capacity * sizeof(fl->files[0])); - } -} - -static void -FileList_add(FileList fl, char *file) -{ - FileList_ensureCapacity(fl, fl->size+1); - fl->files[fl->size++] = file; -} - -static void -FileList_addSubstring(FileList fl, const char *beg, int len) -{ - char *filename = (char *) JLI_MemAlloc(len+1); - memcpy(filename, beg, len); - filename[len] = '\0'; - FileList_ensureCapacity(fl, fl->size+1); - fl->files[fl->size++] = filename; -} - -static char * -FileList_join(FileList fl, char sep) -{ - int i; - int size; - char *path; - char *p; - for (i = 0, size = 1; i < fl->size; i++) - size += strlen(fl->files[i]) + 1; - - path = JLI_MemAlloc(size); - - for (i = 0, p = path; i < fl->size; i++) { - int len = strlen(fl->files[i]); - if (i > 0) *p++ = sep; - memcpy(p, fl->files[i], len); - p += len; - } - *p = '\0'; - - return path; -} - -static FileList -FileList_split(const char *path, char sep) -{ - const char *p, *q; - int len = strlen(path); - int count; - FileList fl; - for (count = 1, p = path; p < path + len; p++) - count += (*p == sep); - fl = FileList_new(count); - for (p = path;;) { - for (q = p; q <= path + len; q++) { - if (*q == sep || *q == '\0') { - FileList_addSubstring(fl, p, q - p); - if (*q == '\0') - return fl; - p = q + 1; - } - } - } -} - -static int -isJarFileName(const char *filename) -{ - int len = strlen(filename); - return (len >= 4) && - (filename[len - 4] == '.') && - (equal(filename + len - 3, "jar") || - equal(filename + len - 3, "JAR")) && - /* Paranoia: Maybe filename is "DIR:foo.jar" */ - (strchr(filename, PATH_SEPARATOR) == NULL); -} - -static char * -wildcardConcat(const char *wildcard, const char *basename) -{ - int wildlen = strlen(wildcard); - int baselen = strlen(basename); - char *filename = (char *) JLI_MemAlloc(wildlen + baselen); - /* Replace the trailing '*' with basename */ - memcpy(filename, wildcard, wildlen-1); - memcpy(filename+wildlen-1, basename, baselen+1); - return filename; -} - -static FileList -wildcardFileList(const char *wildcard) -{ - const char *basename; - FileList fl = FileList_new(16); - WildcardIterator it = WildcardIterator_for(wildcard); - if (it == NULL) { - FileList_free(fl); - return NULL; - } - while ((basename = WildcardIterator_next(it)) != NULL) - if (isJarFileName(basename)) - FileList_add(fl, wildcardConcat(wildcard, basename)); - WildcardIterator_close(it); - return fl; -} - -static int -isWildcard(const char *filename) -{ - int len = strlen(filename); - return (len > 0) && - (filename[len - 1] == '*') && - (len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) && - (! exists(filename)); -} - -static void -FileList_expandWildcards(FileList fl) -{ - int i, j; - for (i = 0; i < fl->size; i++) { - if (isWildcard(fl->files[i])) { - FileList expanded = wildcardFileList(fl->files[i]); - if (expanded != NULL && expanded->size > 0) { - JLI_MemFree(fl->files[i]); - FileList_ensureCapacity(fl, fl->size + expanded->size); - for (j = fl->size - 1; j >= i+1; j--) - fl->files[j+expanded->size-1] = fl->files[j]; - for (j = 0; j < expanded->size; j++) - fl->files[i+j] = expanded->files[j]; - i += expanded->size - 1; - fl->size += expanded->size - 1; - /* fl expropriates expanded's elements. */ - expanded->size = 0; - } - FileList_free(expanded); - } - } -} - -const char * -JLI_WildcardExpandClasspath(const char *classpath) -{ - char *expanded; - FileList fl; - - if (strchr(classpath, '*') == NULL) - return classpath; - fl = FileList_split(classpath, PATH_SEPARATOR); - FileList_expandWildcards(fl); - expanded = FileList_join(fl, PATH_SEPARATOR); - FileList_free(fl); - if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) - printf("Expanded wildcards:\n" - " before: \"%s\"\n" - " after : \"%s\"\n", - classpath, expanded); - return expanded; -} - -#ifdef DEBUG_WILDCARD -static void -wildcardExpandArgv(const char ***argv) -{ - int i; - for (i = 0; (*argv)[i]; i++) { - if (equal((*argv)[i], "-cp") || - equal((*argv)[i], "-classpath")) { - i++; - (*argv)[i] = wildcardExpandClasspath((*argv)[i]); - } - } -} - -static void -debugPrintArgv(char *argv[]) -{ - int i; - putchar('['); - for (i = 0; argv[i]; i++) { - if (i > 0) printf(", "); - printf("\"%s\"", argv[i]); - } - printf("]\n"); -} - -int -main(int argc, char *argv[]) -{ - argv[0] = "java"; - wildcardExpandArgv((const char***)&argv); - debugPrintArgv(argv); - /* execvp("java", argv); */ - return 0; -} -#endif /* DEBUG_WILDCARD */ - -/* Cute little perl prototype implementation.... - -my $sep = ($^O =~ /^(Windows|cygwin)/) ? ";" : ":"; - -sub expand($) { - opendir DIR, $_[0] or return $_[0]; - join $sep, map {"$_[0]/$_"} grep {/\.(jar|JAR)$/} readdir DIR; -} - -sub munge($) { - join $sep, - map {(! -r $_ and s/[\/\\]+\*$//) ? expand $_ : $_} split $sep, $_[0]; -} - -for (my $i = 0; $i < @ARGV - 1; $i++) { - $ARGV[$i+1] = munge $ARGV[$i+1] if $ARGV[$i] =~ /^-c(p|lasspath)$/; -} - -$ENV{CLASSPATH} = munge $ENV{CLASSPATH} if exists $ENV{CLASSPATH}; -@ARGV = ("java", @ARGV); -print "@ARGV\n"; -exec @ARGV; - -*/ diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp index d74e3693ae1..d74e484c66e 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp @@ -211,12 +211,41 @@ bool ciInstanceKlass::is_java_lang_Object() const { // ------------------------------------------------------------------ // ciInstanceKlass::uses_default_loader -bool ciInstanceKlass::uses_default_loader() { +bool ciInstanceKlass::uses_default_loader() const { // Note: We do not need to resolve the handle or enter the VM // in order to test null-ness. return _loader == NULL; } +// ------------------------------------------------------------------ + +/** + * Return basic type of boxed value for box klass or T_OBJECT if not. + */ +BasicType ciInstanceKlass::box_klass_type() const { + if (uses_default_loader() && is_loaded()) { + return SystemDictionary::box_klass_type(get_Klass()); + } else { + return T_OBJECT; + } +} + +/** + * Is this boxing klass? + */ +bool ciInstanceKlass::is_box_klass() const { + return is_java_primitive(box_klass_type()); +} + +/** + * Is this boxed value offset? + */ +bool ciInstanceKlass::is_boxed_value_offset(int offset) const { + BasicType bt = box_klass_type(); + return is_java_primitive(bt) && + (offset == java_lang_boxing_object::value_offset_in_bytes(bt)); +} + // ------------------------------------------------------------------ // ciInstanceKlass::is_in_package // diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp index f7aeba2df3b..0b244a2972c 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp @@ -217,10 +217,14 @@ public: ciInstanceKlass* implementor(); // Is the defining class loader of this class the default loader? - bool uses_default_loader(); + bool uses_default_loader() const; bool is_java_lang_Object() const; + BasicType box_klass_type() const; + bool is_box_klass() const; + bool is_boxed_value_offset(int offset) const; + // Is this klass in the given package? bool is_in_package(const char* packagename) { return is_in_package(packagename, (int) strlen(packagename)); diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index 780f4ad868f..d0363250ee6 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -1179,6 +1179,44 @@ bool ciMethod::has_jsrs () const { FETCH_FLAG_FROM_VM(has_jsrs); bool ciMethod::is_accessor () const { FETCH_FLAG_FROM_VM(is_accessor); } bool ciMethod::is_initializer () const { FETCH_FLAG_FROM_VM(is_initializer); } +bool ciMethod::is_boxing_method() const { + if (holder()->is_box_klass()) { + switch (intrinsic_id()) { + case vmIntrinsics::_Boolean_valueOf: + case vmIntrinsics::_Byte_valueOf: + case vmIntrinsics::_Character_valueOf: + case vmIntrinsics::_Short_valueOf: + case vmIntrinsics::_Integer_valueOf: + case vmIntrinsics::_Long_valueOf: + case vmIntrinsics::_Float_valueOf: + case vmIntrinsics::_Double_valueOf: + return true; + default: + return false; + } + } + return false; +} + +bool ciMethod::is_unboxing_method() const { + if (holder()->is_box_klass()) { + switch (intrinsic_id()) { + case vmIntrinsics::_booleanValue: + case vmIntrinsics::_byteValue: + case vmIntrinsics::_charValue: + case vmIntrinsics::_shortValue: + case vmIntrinsics::_intValue: + case vmIntrinsics::_longValue: + case vmIntrinsics::_floatValue: + case vmIntrinsics::_doubleValue: + return true; + default: + return false; + } + } + return false; +} + BCEscapeAnalyzer *ciMethod::get_bcea() { #ifdef COMPILER2 if (_bcea == NULL) { diff --git a/hotspot/src/share/vm/ci/ciMethod.hpp b/hotspot/src/share/vm/ci/ciMethod.hpp index 46ea500b551..8305547c56f 100644 --- a/hotspot/src/share/vm/ci/ciMethod.hpp +++ b/hotspot/src/share/vm/ci/ciMethod.hpp @@ -298,6 +298,8 @@ class ciMethod : public ciMetadata { bool is_initializer () const; bool can_be_statically_bound() const { return _can_be_statically_bound; } void dump_replay_data(outputStream* st); + bool is_boxing_method() const; + bool is_unboxing_method() const; // Print the bytecodes of this method. void print_codes_on(outputStream* st); diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index d9e9b9d032d..16d4023fb17 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -3041,7 +3041,7 @@ AnnotationArray* ClassFileParser::assemble_annotations(u1* runtime_visible_annot } -#ifndef PRODUCT +#ifdef ASSERT static void parseAndPrintGenericSignatures( instanceKlassHandle this_klass, TRAPS) { assert(ParseAllGenericSignatures == true, "Shouldn't call otherwise"); @@ -3066,7 +3066,7 @@ static void parseAndPrintGenericSignatures( } } } -#endif // ndef PRODUCT +#endif // def ASSERT instanceKlassHandle ClassFileParser::parse_super_class(int super_class_index, diff --git a/hotspot/src/share/vm/classfile/vmSymbols.cpp b/hotspot/src/share/vm/classfile/vmSymbols.cpp index 92939ea2487..cc38c6d2cd6 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.cpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp @@ -49,7 +49,7 @@ extern "C" { } } -#ifndef PRODUCT +#ifdef ASSERT #define VM_SYMBOL_ENUM_NAME_BODY(name, string) #name "\0" static const char* vm_symbol_enum_names = VM_SYMBOLS_DO(VM_SYMBOL_ENUM_NAME_BODY, VM_ALIAS_IGNORE) @@ -64,7 +64,7 @@ static const char* vm_symbol_enum_name(vmSymbols::SID sid) { } return string; } -#endif //PRODUCT +#endif //ASSERT // Put all the VM symbol strings in one place. // Makes for a more compact libjvm. diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index 428b2940f61..9fd9aff5e22 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -68,7 +68,7 @@ template(java_lang_Float, "java/lang/Float") \ template(java_lang_Double, "java/lang/Double") \ template(java_lang_Byte, "java/lang/Byte") \ - template(java_lang_Byte_Cache, "java/lang/Byte$ByteCache") \ + template(java_lang_Byte_ByteCache, "java/lang/Byte$ByteCache") \ template(java_lang_Short, "java/lang/Short") \ template(java_lang_Short_ShortCache, "java/lang/Short$ShortCache") \ template(java_lang_Integer, "java/lang/Integer") \ diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 086bff881cd..ad097d96a9b 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -1854,8 +1854,10 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) { tty->print("%7d ", (int) tty->time_stamp().milliseconds()); // print timestamp tty->print("%4d ", compile_id); // print compilation number tty->print("%s ", (is_osr ? "%" : " ")); - int code_size = (task->code() == NULL) ? 0 : task->code()->total_size(); - tty->print_cr("size: %d time: %d inlined: %d bytes", code_size, (int)time.milliseconds(), task->num_inlined_bytecodes()); + if (task->code() != NULL) { + tty->print("size: %d(%d) ", task->code()->total_size(), task->code()->insts_size()); + } + tty->print_cr("time: %d inlined: %d bytes", (int)time.milliseconds(), task->num_inlined_bytecodes()); } if (PrintCodeCacheOnCompilation) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 0f92b3602de..6da891572c4 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -692,8 +692,7 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, _cmsGen ->init_initiating_occupancy(CMSInitiatingOccupancyFraction, CMSTriggerRatio); // Clip CMSBootstrapOccupancy between 0 and 100. - _bootstrap_occupancy = ((double)MIN2((uintx)100, MAX2((uintx)0, CMSBootstrapOccupancy))) - /(double)100; + _bootstrap_occupancy = ((double)CMSBootstrapOccupancy)/(double)100; _full_gcs_since_conc_gc = 0; diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 39e5a2792b5..137f76c0974 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -4515,7 +4515,8 @@ G1PrintRegionLivenessInfoClosure(outputStream* out, const char* phase_name) _total_used_bytes(0), _total_capacity_bytes(0), _total_prev_live_bytes(0), _total_next_live_bytes(0), _hum_used_bytes(0), _hum_capacity_bytes(0), - _hum_prev_live_bytes(0), _hum_next_live_bytes(0) { + _hum_prev_live_bytes(0), _hum_next_live_bytes(0), + _total_remset_bytes(0) { G1CollectedHeap* g1h = G1CollectedHeap::heap(); MemRegion g1_committed = g1h->g1_committed(); MemRegion g1_reserved = g1h->g1_reserved(); @@ -4533,23 +4534,25 @@ G1PrintRegionLivenessInfoClosure(outputStream* out, const char* phase_name) HeapRegion::GrainBytes); _out->print_cr(G1PPRL_LINE_PREFIX); _out->print_cr(G1PPRL_LINE_PREFIX - G1PPRL_TYPE_H_FORMAT - G1PPRL_ADDR_BASE_H_FORMAT - G1PPRL_BYTE_H_FORMAT - G1PPRL_BYTE_H_FORMAT - G1PPRL_BYTE_H_FORMAT - G1PPRL_DOUBLE_H_FORMAT, - "type", "address-range", - "used", "prev-live", "next-live", "gc-eff"); + G1PPRL_TYPE_H_FORMAT + G1PPRL_ADDR_BASE_H_FORMAT + G1PPRL_BYTE_H_FORMAT + G1PPRL_BYTE_H_FORMAT + G1PPRL_BYTE_H_FORMAT + G1PPRL_DOUBLE_H_FORMAT + G1PPRL_BYTE_H_FORMAT, + "type", "address-range", + "used", "prev-live", "next-live", "gc-eff", "remset"); _out->print_cr(G1PPRL_LINE_PREFIX - G1PPRL_TYPE_H_FORMAT - G1PPRL_ADDR_BASE_H_FORMAT - G1PPRL_BYTE_H_FORMAT - G1PPRL_BYTE_H_FORMAT - G1PPRL_BYTE_H_FORMAT - G1PPRL_DOUBLE_H_FORMAT, - "", "", - "(bytes)", "(bytes)", "(bytes)", "(bytes/ms)"); + G1PPRL_TYPE_H_FORMAT + G1PPRL_ADDR_BASE_H_FORMAT + G1PPRL_BYTE_H_FORMAT + G1PPRL_BYTE_H_FORMAT + G1PPRL_BYTE_H_FORMAT + G1PPRL_DOUBLE_H_FORMAT + G1PPRL_BYTE_H_FORMAT, + "", "", + "(bytes)", "(bytes)", "(bytes)", "(bytes/ms)", "(bytes)"); } // It takes as a parameter a reference to one of the _hum_* fields, it @@ -4591,6 +4594,7 @@ bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) { size_t prev_live_bytes = r->live_bytes(); size_t next_live_bytes = r->next_live_bytes(); double gc_eff = r->gc_efficiency(); + size_t remset_bytes = r->rem_set()->mem_size(); if (r->used() == 0) { type = "FREE"; } else if (r->is_survivor()) { @@ -4624,6 +4628,7 @@ bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) { _total_capacity_bytes += capacity_bytes; _total_prev_live_bytes += prev_live_bytes; _total_next_live_bytes += next_live_bytes; + _total_remset_bytes += remset_bytes; // Print a line for this particular region. _out->print_cr(G1PPRL_LINE_PREFIX @@ -4632,14 +4637,17 @@ bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) { G1PPRL_BYTE_FORMAT G1PPRL_BYTE_FORMAT G1PPRL_BYTE_FORMAT - G1PPRL_DOUBLE_FORMAT, + G1PPRL_DOUBLE_FORMAT + G1PPRL_BYTE_FORMAT, type, bottom, end, - used_bytes, prev_live_bytes, next_live_bytes, gc_eff); + used_bytes, prev_live_bytes, next_live_bytes, gc_eff , remset_bytes); return false; } G1PrintRegionLivenessInfoClosure::~G1PrintRegionLivenessInfoClosure() { + // add static memory usages to remembered set sizes + _total_remset_bytes += HeapRegionRemSet::fl_mem_size() + HeapRegionRemSet::static_mem_size(); // Print the footer of the output. _out->print_cr(G1PPRL_LINE_PREFIX); _out->print_cr(G1PPRL_LINE_PREFIX @@ -4647,13 +4655,15 @@ G1PrintRegionLivenessInfoClosure::~G1PrintRegionLivenessInfoClosure() { G1PPRL_SUM_MB_FORMAT("capacity") G1PPRL_SUM_MB_PERC_FORMAT("used") G1PPRL_SUM_MB_PERC_FORMAT("prev-live") - G1PPRL_SUM_MB_PERC_FORMAT("next-live"), + G1PPRL_SUM_MB_PERC_FORMAT("next-live") + G1PPRL_SUM_MB_FORMAT("remset"), bytes_to_mb(_total_capacity_bytes), bytes_to_mb(_total_used_bytes), perc(_total_used_bytes, _total_capacity_bytes), bytes_to_mb(_total_prev_live_bytes), perc(_total_prev_live_bytes, _total_capacity_bytes), bytes_to_mb(_total_next_live_bytes), - perc(_total_next_live_bytes, _total_capacity_bytes)); + perc(_total_next_live_bytes, _total_capacity_bytes), + bytes_to_mb(_total_remset_bytes)); _out->cr(); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index 211a728e23e..58ef49e1f5b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -1257,6 +1257,9 @@ private: size_t _hum_prev_live_bytes; size_t _hum_next_live_bytes; + // Accumulator for the remembered set size + size_t _total_remset_bytes; + static double perc(size_t val, size_t total) { if (total == 0) { return 0.0; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp index a055d4f285b..00ea5b54850 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp @@ -101,20 +101,23 @@ void G1CardCounts::resize(size_t heap_capacity) { ReservedSpace::allocation_align_size_up(_committed_size), err_msg("Unaligned? committed_size: " SIZE_FORMAT, _committed_size)); - // Verify that the committed space for the card counts - // matches our committed max card num. + // Verify that the committed space for the card counts matches our + // committed max card num. Note for some allocation alignments, the + // amount of space actually committed for the counts table will be able + // to span more cards than the number spanned by the maximum heap. size_t prev_committed_size = _committed_size; - size_t prev_committed_card_num = prev_committed_size / sizeof(jbyte); + size_t prev_committed_card_num = committed_to_card_num(prev_committed_size); + assert(prev_committed_card_num == _committed_max_card_num, err_msg("Card mismatch: " "prev: " SIZE_FORMAT ", " - "committed: "SIZE_FORMAT, - prev_committed_card_num, _committed_max_card_num)); + "committed: "SIZE_FORMAT", " + "reserved: "SIZE_FORMAT, + prev_committed_card_num, _committed_max_card_num, _reserved_max_card_num)); size_t new_size = (heap_capacity >> CardTableModRefBS::card_shift) * sizeof(jbyte); size_t new_committed_size = ReservedSpace::allocation_align_size_up(new_size); - size_t new_committed_card_num = - MIN2(_reserved_max_card_num, new_committed_size / sizeof(jbyte)); + size_t new_committed_card_num = committed_to_card_num(new_committed_size); if (_committed_max_card_num < new_committed_card_num) { // we need to expand the backing store for the card counts diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp index cef297bd234..fd516c0b90e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp @@ -94,6 +94,14 @@ class G1CardCounts: public CHeapObj { return (jbyte*) (_ct_bot + card_num); } + // Helper routine. + // Returns the number of cards that can be counted by the given committed + // table size, with a maximum of the number of cards spanned by the max + // capacity of the heap. + size_t committed_to_card_num(size_t committed_size) { + return MIN2(_reserved_max_card_num, committed_size / sizeof(jbyte)); + } + // Clear the counts table for the given (exclusive) index range. void clear_range(size_t from_card_num, size_t to_card_num); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 49cde427238..11dcb0beb20 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1549,7 +1549,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, } if (G1Log::finer()) { - g1_policy()->print_detailed_heap_transition(); + g1_policy()->print_detailed_heap_transition(true /* full */); } print_heap_after_gc(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index a21290c835b..741c6b7130a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -124,9 +124,12 @@ G1CollectorPolicy::G1CollectorPolicy() : _last_young_gc(false), _last_gc_was_young(false), - _eden_bytes_before_gc(0), - _survivor_bytes_before_gc(0), - _capacity_before_gc(0), + _eden_used_bytes_before_gc(0), + _survivor_used_bytes_before_gc(0), + _heap_used_bytes_before_gc(0), + _metaspace_used_bytes_before_gc(0), + _eden_capacity_bytes_before_gc(0), + _heap_capacity_bytes_before_gc(0), _eden_cset_region_length(0), _survivor_cset_region_length(0), @@ -746,7 +749,7 @@ G1CollectorPolicy::verify_young_ages(HeapRegion* head, void G1CollectorPolicy::record_full_collection_start() { _full_collection_start_sec = os::elapsedTime(); - record_heap_size_info_at_start(); + record_heap_size_info_at_start(true /* full */); // Release the future to-space so that it is available for compaction into. _g1->set_full_collection(); } @@ -803,7 +806,7 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec) { _trace_gen0_time_data.record_start_collection(s_w_t_ms); _stop_world_start = 0.0; - record_heap_size_info_at_start(); + record_heap_size_info_at_start(false /* full */); phase_times()->record_cur_collection_start_sec(start_time_sec); _pending_cards = _g1->pending_card_num(); @@ -938,14 +941,6 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) { _mmu_tracker->add_pause(end_time_sec - pause_time_ms/1000.0, end_time_sec, false); - size_t freed_bytes = - _cur_collection_pause_used_at_start_bytes - cur_used_bytes; - size_t surviving_bytes = _collection_set_bytes_used_before - freed_bytes; - - double survival_fraction = - (double)surviving_bytes/ - (double)_collection_set_bytes_used_before; - if (update_stats) { _trace_gen0_time_data.record_end_collection(pause_time_ms, phase_times()); // this is where we update the allocation rate of the application @@ -998,6 +993,7 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) { } } } + bool new_in_marking_window = _in_marking_window; bool new_in_marking_window_im = false; if (during_initial_mark_pause()) { @@ -1083,8 +1079,10 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) { } _rs_length_diff_seq->add((double) rs_length_diff); - size_t copied_bytes = surviving_bytes; + size_t freed_bytes = _heap_used_bytes_before_gc - cur_used_bytes; + size_t copied_bytes = _collection_set_bytes_used_before - freed_bytes; double cost_per_byte_ms = 0.0; + if (copied_bytes > 0) { cost_per_byte_ms = phase_times()->average_last_obj_copy_time() / (double) copied_bytes; if (_in_marking_window) { @@ -1148,51 +1146,61 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) { byte_size_in_proper_unit((double)(bytes)), \ proper_unit_for_byte_size((bytes)) -void G1CollectorPolicy::record_heap_size_info_at_start() { +void G1CollectorPolicy::record_heap_size_info_at_start(bool full) { YoungList* young_list = _g1->young_list(); - _eden_bytes_before_gc = young_list->eden_used_bytes(); - _survivor_bytes_before_gc = young_list->survivor_used_bytes(); - _capacity_before_gc = _g1->capacity(); - - _cur_collection_pause_used_at_start_bytes = _g1->used(); + _eden_used_bytes_before_gc = young_list->eden_used_bytes(); + _survivor_used_bytes_before_gc = young_list->survivor_used_bytes(); + _heap_capacity_bytes_before_gc = _g1->capacity(); + _heap_used_bytes_before_gc = _g1->used(); _cur_collection_pause_used_regions_at_start = _g1->used_regions(); - size_t eden_capacity_before_gc = - (_young_list_target_length * HeapRegion::GrainBytes) - _survivor_bytes_before_gc; + _eden_capacity_bytes_before_gc = + (_young_list_target_length * HeapRegion::GrainBytes) - _survivor_used_bytes_before_gc; - _prev_eden_capacity = eden_capacity_before_gc; + if (full) { + _metaspace_used_bytes_before_gc = MetaspaceAux::allocated_used_bytes(); + } } void G1CollectorPolicy::print_heap_transition() { _g1->print_size_transition(gclog_or_tty, - _cur_collection_pause_used_at_start_bytes, _g1->used(), _g1->capacity()); + _heap_used_bytes_before_gc, + _g1->used(), + _g1->capacity()); } -void G1CollectorPolicy::print_detailed_heap_transition() { - YoungList* young_list = _g1->young_list(); - size_t eden_bytes = young_list->eden_used_bytes(); - size_t survivor_bytes = young_list->survivor_used_bytes(); - size_t used_before_gc = _cur_collection_pause_used_at_start_bytes; - size_t used = _g1->used(); - size_t capacity = _g1->capacity(); - size_t eden_capacity = - (_young_list_target_length * HeapRegion::GrainBytes) - survivor_bytes; +void G1CollectorPolicy::print_detailed_heap_transition(bool full) { + YoungList* young_list = _g1->young_list(); - gclog_or_tty->print_cr( - " [Eden: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT") " - "Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" " - "Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->" - EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]", - EXT_SIZE_PARAMS(_eden_bytes_before_gc), - EXT_SIZE_PARAMS(_prev_eden_capacity), - EXT_SIZE_PARAMS(eden_bytes), - EXT_SIZE_PARAMS(eden_capacity), - EXT_SIZE_PARAMS(_survivor_bytes_before_gc), - EXT_SIZE_PARAMS(survivor_bytes), - EXT_SIZE_PARAMS(used_before_gc), - EXT_SIZE_PARAMS(_capacity_before_gc), - EXT_SIZE_PARAMS(used), - EXT_SIZE_PARAMS(capacity)); + size_t eden_used_bytes_after_gc = young_list->eden_used_bytes(); + size_t survivor_used_bytes_after_gc = young_list->survivor_used_bytes(); + size_t heap_used_bytes_after_gc = _g1->used(); + + size_t heap_capacity_bytes_after_gc = _g1->capacity(); + size_t eden_capacity_bytes_after_gc = + (_young_list_target_length * HeapRegion::GrainBytes) - survivor_used_bytes_after_gc; + + gclog_or_tty->print( + " [Eden: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT") " + "Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" " + "Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->" + EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]", + EXT_SIZE_PARAMS(_eden_used_bytes_before_gc), + EXT_SIZE_PARAMS(_eden_capacity_bytes_before_gc), + EXT_SIZE_PARAMS(eden_used_bytes_after_gc), + EXT_SIZE_PARAMS(eden_capacity_bytes_after_gc), + EXT_SIZE_PARAMS(_survivor_used_bytes_before_gc), + EXT_SIZE_PARAMS(survivor_used_bytes_after_gc), + EXT_SIZE_PARAMS(_heap_used_bytes_before_gc), + EXT_SIZE_PARAMS(_heap_capacity_bytes_before_gc), + EXT_SIZE_PARAMS(heap_used_bytes_after_gc), + EXT_SIZE_PARAMS(heap_capacity_bytes_after_gc)); + + if (full) { + MetaspaceAux::print_metaspace_change(_metaspace_used_bytes_before_gc); + } + + gclog_or_tty->cr(); } void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time, diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index 08867850394..90106c00a34 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -175,7 +175,6 @@ private: CollectionSetChooser* _collectionSetChooser; double _full_collection_start_sec; - size_t _cur_collection_pause_used_at_start_bytes; uint _cur_collection_pause_used_regions_at_start; // These exclude marking times. @@ -194,7 +193,6 @@ private: uint _young_list_target_length; uint _young_list_fixed_length; - size_t _prev_eden_capacity; // used for logging // The max number of regions we can extend the eden by while the GC // locker is active. This should be >= _young_list_target_length; @@ -693,11 +691,11 @@ public: // Records the information about the heap size for reporting in // print_detailed_heap_transition - void record_heap_size_info_at_start(); + void record_heap_size_info_at_start(bool full); // Print heap sizing transition (with less and more detail). void print_heap_transition(); - void print_detailed_heap_transition(); + void print_detailed_heap_transition(bool full = false); void record_stop_world_start(); void record_concurrent_pause(); @@ -861,9 +859,16 @@ private: uint _max_survivor_regions; // For reporting purposes. - size_t _eden_bytes_before_gc; - size_t _survivor_bytes_before_gc; - size_t _capacity_before_gc; + // The value of _heap_bytes_before_gc is also used to calculate + // the cost of copying. + + size_t _eden_used_bytes_before_gc; // Eden occupancy before GC + size_t _survivor_used_bytes_before_gc; // Survivor occupancy before GC + size_t _heap_used_bytes_before_gc; // Heap occupancy before GC + size_t _metaspace_used_bytes_before_gc; // Metaspace occupancy before GC + + size_t _eden_capacity_bytes_before_gc; // Eden capacity before GC + size_t _heap_capacity_bytes_before_gc; // Heap capacity before GC // The amount of survivor regions after a collection. uint _recorded_survivor_regions; diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp index 34339b25e74..d148721df17 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp @@ -707,10 +707,11 @@ size_t OtherRegionsTable::mem_size() const { // Cast away const in this case. MutexLockerEx x((Mutex*)&_m, Mutex::_no_safepoint_check_flag); size_t sum = 0; - PerRegionTable * cur = _first_all_fine_prts; - while (cur != NULL) { - sum += cur->mem_size(); - cur = cur->next(); + // all PRTs are of the same size so it is sufficient to query only one of them. + if (_first_all_fine_prts != NULL) { + assert(_last_all_fine_prts != NULL && + _first_all_fine_prts->mem_size() == _last_all_fine_prts->mem_size(), "check that mem_size() is constant"); + sum += _first_all_fine_prts->mem_size() * _n_fine_entries; } sum += (sizeof(PerRegionTable*) * _max_fine_entries); sum += (_coarse_map.size_in_words() * HeapWordSize); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp index 3d4cbedd827..adf18645f8b 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp @@ -24,7 +24,6 @@ #include "precompiled.hpp" #include "gc_implementation/parallelScavenge/parMarkBitMap.hpp" -#include "gc_implementation/parallelScavenge/parMarkBitMap.inline.hpp" #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" #include "oops/oop.inline.hpp" #include "runtime/os.hpp" @@ -108,31 +107,6 @@ ParMarkBitMap::mark_obj(HeapWord* addr, size_t size) return false; } -size_t -ParMarkBitMap::live_words_in_range(HeapWord* beg_addr, HeapWord* end_addr) const -{ - assert(beg_addr <= end_addr, "bad range"); - - idx_t live_bits = 0; - - // The bitmap routines require the right boundary to be word-aligned. - const idx_t end_bit = addr_to_bit(end_addr); - const idx_t range_end = BitMap::word_align_up(end_bit); - - idx_t beg_bit = find_obj_beg(addr_to_bit(beg_addr), range_end); - while (beg_bit < end_bit) { - idx_t tmp_end = find_obj_end(beg_bit, range_end); - if (tmp_end < end_bit) { - live_bits += tmp_end - beg_bit + 1; - beg_bit = find_obj_beg(tmp_end + 1, range_end); - } else { - live_bits += end_bit - beg_bit; // No + 1 here; end_bit is not counted. - return bits_to_words(live_bits); - } - } - return bits_to_words(live_bits); -} - size_t ParMarkBitMap::live_words_in_range(HeapWord* beg_addr, oop end_obj) const { assert(beg_addr <= (HeapWord*)end_obj, "bad range"); @@ -244,13 +218,6 @@ ParMarkBitMap::iterate(ParMarkBitMapClosure* live_closure, return complete; } -#ifndef PRODUCT -void ParMarkBitMap::reset_counters() -{ - _cas_tries = _cas_retries = _cas_by_another = 0; -} -#endif // #ifndef PRODUCT - #ifdef ASSERT void ParMarkBitMap::verify_clear() const { diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp index fdc0febfa21..7c6cf515c73 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp @@ -26,11 +26,11 @@ #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_HPP #include "memory/memRegion.hpp" -#include "gc_implementation/parallelScavenge/psVirtualspace.hpp" -#include "utilities/bitMap.inline.hpp" +#include "oops/oop.hpp" +#include "utilities/bitMap.hpp" -class oopDesc; class ParMarkBitMapClosure; +class PSVirtualSpace; class ParMarkBitMap: public CHeapObj { @@ -41,13 +41,11 @@ public: enum IterationStatus { incomplete, complete, full, would_overflow }; inline ParMarkBitMap(); - inline ParMarkBitMap(MemRegion covered_region); bool initialize(MemRegion covered_region); // Atomically mark an object as live. bool mark_obj(HeapWord* addr, size_t size); inline bool mark_obj(oop obj, int size); - inline bool mark_obj(oop obj); // Return whether the specified begin or end bit is set. inline bool is_obj_beg(idx_t bit) const; @@ -77,11 +75,6 @@ public: // Return the size in words of the object (a search is done for the end bit). inline size_t obj_size(idx_t beg_bit) const; inline size_t obj_size(HeapWord* addr) const; - inline size_t obj_size(oop obj) const; - - // Synonyms for the above. - size_t obj_size_in_words(oop obj) const { return obj_size((HeapWord*)obj); } - size_t obj_size_in_words(HeapWord* addr) const { return obj_size(addr); } // Apply live_closure to each live object that lies completely within the // range [live_range_beg, live_range_end). This is used to iterate over the @@ -124,15 +117,12 @@ public: HeapWord* range_end, HeapWord* dead_range_end) const; - // Return the number of live words in the range [beg_addr, end_addr) due to + // Return the number of live words in the range [beg_addr, end_obj) due to // objects that start in the range. If a live object extends onto the range, // the caller must detect and account for any live words due to that object. // If a live object extends beyond the end of the range, only the words within - // the range are included in the result. - size_t live_words_in_range(HeapWord* beg_addr, HeapWord* end_addr) const; - - // Same as the above, except the end of the range must be a live object, which - // is the case when updating pointers. This allows a branch to be removed + // the range are included in the result. The end of the range must be a live object, + // which is the case when updating pointers. This allows a branch to be removed // from inside the loop. size_t live_words_in_range(HeapWord* beg_addr, oop end_obj) const; @@ -156,22 +146,11 @@ public: // Clear a range of bits or the entire bitmap (both begin and end bits are // cleared). inline void clear_range(idx_t beg, idx_t end); - inline void clear() { clear_range(0, size()); } // Return the number of bits required to represent the specified number of // HeapWords, or the specified region. static inline idx_t bits_required(size_t words); static inline idx_t bits_required(MemRegion covered_region); - static inline idx_t words_required(MemRegion covered_region); - -#ifndef PRODUCT - // CAS statistics. - size_t cas_tries() { return _cas_tries; } - size_t cas_retries() { return _cas_retries; } - size_t cas_by_another() { return _cas_by_another; } - - void reset_counters(); -#endif // #ifndef PRODUCT void print_on_error(outputStream* st) const { st->print_cr("Marking Bits: (ParMarkBitMap*) " PTR_FORMAT, this); @@ -197,28 +176,11 @@ private: BitMap _beg_bits; BitMap _end_bits; PSVirtualSpace* _virtual_space; - -#ifndef PRODUCT - size_t _cas_tries; - size_t _cas_retries; - size_t _cas_by_another; -#endif // #ifndef PRODUCT }; inline ParMarkBitMap::ParMarkBitMap(): - _beg_bits(), - _end_bits() -{ - _region_start = 0; - _virtual_space = 0; -} - -inline ParMarkBitMap::ParMarkBitMap(MemRegion covered_region): - _beg_bits(), - _end_bits() -{ - initialize(covered_region); -} + _beg_bits(), _end_bits(), _region_start(NULL), _region_size(0), _virtual_space(NULL) +{ } inline void ParMarkBitMap::clear_range(idx_t beg, idx_t end) { @@ -240,12 +202,6 @@ ParMarkBitMap::bits_required(MemRegion covered_region) return bits_required(covered_region.word_size()); } -inline ParMarkBitMap::idx_t -ParMarkBitMap::words_required(MemRegion covered_region) -{ - return bits_required(covered_region) / BitsPerWord; -} - inline HeapWord* ParMarkBitMap::region_start() const { @@ -350,11 +306,6 @@ inline size_t ParMarkBitMap::obj_size(HeapWord* addr) const return obj_size(addr_to_bit(addr)); } -inline size_t ParMarkBitMap::obj_size(oop obj) const -{ - return obj_size((HeapWord*)obj); -} - inline ParMarkBitMap::IterationStatus ParMarkBitMap::iterate(ParMarkBitMapClosure* live_closure, HeapWord* range_beg, @@ -435,8 +386,10 @@ inline void ParMarkBitMap::verify_bit(idx_t bit) const { inline void ParMarkBitMap::verify_addr(HeapWord* addr) const { // Allow one past the last valid address; useful for loop bounds. - assert(addr >= region_start(), "addr too small"); - assert(addr <= region_start() + region_size(), "addr too big"); + assert(addr >= region_start(), + err_msg("addr too small, addr: " PTR_FORMAT " region start: " PTR_FORMAT, addr, region_start())); + assert(addr <= region_end(), + err_msg("addr too big, addr: " PTR_FORMAT " region end: " PTR_FORMAT, addr, region_end())); } #endif // #ifdef ASSERT diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp index 3b24ed8866a..8b3ee26548d 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -201,15 +201,232 @@ void PSAdaptiveSizePolicy::compute_generation_free_space( size_t cur_eden, size_t max_old_gen_size, size_t max_eden_size, - bool is_full_gc, - GCCause::Cause gc_cause, - CollectorPolicy* collector_policy) { + bool is_full_gc) { + compute_eden_space_size(young_live, + eden_live, + cur_eden, + max_eden_size, + is_full_gc); + + compute_old_gen_free_space(old_live, + cur_eden, + max_old_gen_size, + is_full_gc); +} + +void PSAdaptiveSizePolicy::compute_eden_space_size( + size_t young_live, + size_t eden_live, + size_t cur_eden, + size_t max_eden_size, + bool is_full_gc) { // Update statistics // Time statistics are updated as we go, update footprint stats here _avg_base_footprint->sample(BaseFootPrintEstimate); avg_young_live()->sample(young_live); avg_eden_live()->sample(eden_live); + + // This code used to return if the policy was not ready , i.e., + // policy_is_ready() returning false. The intent was that + // decisions below needed major collection times and so could + // not be made before two major collections. A consequence was + // adjustments to the young generation were not done until after + // two major collections even if the minor collections times + // exceeded the requested goals. Now let the young generation + // adjust for the minor collection times. Major collection times + // will be zero for the first collection and will naturally be + // ignored. Tenured generation adjustments are only made at the + // full collections so until the second major collection has + // been reached, no tenured generation adjustments will be made. + + // Until we know better, desired promotion size uses the last calculation + size_t desired_promo_size = _promo_size; + + // Start eden at the current value. The desired value that is stored + // in _eden_size is not bounded by constraints of the heap and can + // run away. + // + // As expected setting desired_eden_size to the current + // value of desired_eden_size as a starting point + // caused desired_eden_size to grow way too large and caused + // an overflow down stream. It may have improved performance in + // some case but is dangerous. + size_t desired_eden_size = cur_eden; + + // Cache some values. There's a bit of work getting these, so + // we might save a little time. + const double major_cost = major_gc_cost(); + const double minor_cost = minor_gc_cost(); + + // This method sets the desired eden size. That plus the + // desired survivor space sizes sets the desired young generation + // size. This methods does not know what the desired survivor + // size is but expects that other policy will attempt to make + // the survivor sizes compatible with the live data in the + // young generation. This limit is an estimate of the space left + // in the young generation after the survivor spaces have been + // subtracted out. + size_t eden_limit = max_eden_size; + + const double gc_cost_limit = GCTimeLimit/100.0; + + // Which way should we go? + // if pause requirement is not met + // adjust size of any generation with average paus exceeding + // the pause limit. Adjust one pause at a time (the larger) + // and only make adjustments for the major pause at full collections. + // else if throughput requirement not met + // adjust the size of the generation with larger gc time. Only + // adjust one generation at a time. + // else + // adjust down the total heap size. Adjust down the larger of the + // generations. + + // Add some checks for a threshold for a change. For example, + // a change less than the necessary alignment is probably not worth + // attempting. + + + if ((_avg_minor_pause->padded_average() > gc_pause_goal_sec()) || + (_avg_major_pause->padded_average() > gc_pause_goal_sec())) { + // + // Check pauses + // + // Make changes only to affect one of the pauses (the larger) + // at a time. + adjust_eden_for_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size); + + } else if (_avg_minor_pause->padded_average() > gc_minor_pause_goal_sec()) { + // Adjust only for the minor pause time goal + adjust_eden_for_minor_pause_time(is_full_gc, &desired_eden_size); + + } else if(adjusted_mutator_cost() < _throughput_goal) { + // This branch used to require that (mutator_cost() > 0.0 in 1.4.2. + // This sometimes resulted in skipping to the minimize footprint + // code. Change this to try and reduce GC time if mutator time is + // negative for whatever reason. Or for future consideration, + // bail out of the code if mutator time is negative. + // + // Throughput + // + assert(major_cost >= 0.0, "major cost is < 0.0"); + assert(minor_cost >= 0.0, "minor cost is < 0.0"); + // Try to reduce the GC times. + adjust_eden_for_throughput(is_full_gc, &desired_eden_size); + + } else { + + // Be conservative about reducing the footprint. + // Do a minimum number of major collections first. + // Have reasonable averages for major and minor collections costs. + if (UseAdaptiveSizePolicyFootprintGoal && + young_gen_policy_is_ready() && + avg_major_gc_cost()->average() >= 0.0 && + avg_minor_gc_cost()->average() >= 0.0) { + size_t desired_sum = desired_eden_size + desired_promo_size; + desired_eden_size = adjust_eden_for_footprint(desired_eden_size, desired_sum); + } + } + + // Note we make the same tests as in the code block below; the code + // seems a little easier to read with the printing in another block. + if (PrintAdaptiveSizePolicy) { + if (desired_eden_size > eden_limit) { + gclog_or_tty->print_cr( + "PSAdaptiveSizePolicy::compute_eden_space_size limits:" + " desired_eden_size: " SIZE_FORMAT + " old_eden_size: " SIZE_FORMAT + " eden_limit: " SIZE_FORMAT + " cur_eden: " SIZE_FORMAT + " max_eden_size: " SIZE_FORMAT + " avg_young_live: " SIZE_FORMAT, + desired_eden_size, _eden_size, eden_limit, cur_eden, + max_eden_size, (size_t)avg_young_live()->average()); + } + if (gc_cost() > gc_cost_limit) { + gclog_or_tty->print_cr( + "PSAdaptiveSizePolicy::compute_eden_space_size: gc time limit" + " gc_cost: %f " + " GCTimeLimit: %d", + gc_cost(), GCTimeLimit); + } + } + + // Align everything and make a final limit check + const size_t alignment = _intra_generation_alignment; + desired_eden_size = align_size_up(desired_eden_size, alignment); + desired_eden_size = MAX2(desired_eden_size, alignment); + + eden_limit = align_size_down(eden_limit, alignment); + + // And one last limit check, now that we've aligned things. + if (desired_eden_size > eden_limit) { + // If the policy says to get a larger eden but + // is hitting the limit, don't decrease eden. + // This can lead to a general drifting down of the + // eden size. Let the tenuring calculation push more + // into the old gen. + desired_eden_size = MAX2(eden_limit, cur_eden); + } + + if (PrintAdaptiveSizePolicy) { + // Timing stats + gclog_or_tty->print( + "PSAdaptiveSizePolicy::compute_eden_space_size: costs" + " minor_time: %f" + " major_cost: %f" + " mutator_cost: %f" + " throughput_goal: %f", + minor_gc_cost(), major_gc_cost(), mutator_cost(), + _throughput_goal); + + // We give more details if Verbose is set + if (Verbose) { + gclog_or_tty->print( " minor_pause: %f" + " major_pause: %f" + " minor_interval: %f" + " major_interval: %f" + " pause_goal: %f", + _avg_minor_pause->padded_average(), + _avg_major_pause->padded_average(), + _avg_minor_interval->average(), + _avg_major_interval->average(), + gc_pause_goal_sec()); + } + + // Footprint stats + gclog_or_tty->print( " live_space: " SIZE_FORMAT + " free_space: " SIZE_FORMAT, + live_space(), free_space()); + // More detail + if (Verbose) { + gclog_or_tty->print( " base_footprint: " SIZE_FORMAT + " avg_young_live: " SIZE_FORMAT + " avg_old_live: " SIZE_FORMAT, + (size_t)_avg_base_footprint->average(), + (size_t)avg_young_live()->average(), + (size_t)avg_old_live()->average()); + } + + // And finally, our old and new sizes. + gclog_or_tty->print(" old_eden_size: " SIZE_FORMAT + " desired_eden_size: " SIZE_FORMAT, + _eden_size, desired_eden_size); + gclog_or_tty->cr(); + } + + set_eden_size(desired_eden_size); +} + +void PSAdaptiveSizePolicy::compute_old_gen_free_space( + size_t old_live, + size_t cur_eden, + size_t max_old_gen_size, + bool is_full_gc) { + + // Update statistics + // Time statistics are updated as we go, update footprint stats here if (is_full_gc) { // old_live is only accurate after a full gc avg_old_live()->sample(old_live); @@ -242,32 +459,14 @@ void PSAdaptiveSizePolicy::compute_generation_free_space( // some case but is dangerous. size_t desired_eden_size = cur_eden; -#ifdef ASSERT - size_t original_promo_size = desired_promo_size; - size_t original_eden_size = desired_eden_size; -#endif - // Cache some values. There's a bit of work getting these, so // we might save a little time. const double major_cost = major_gc_cost(); const double minor_cost = minor_gc_cost(); - // Used for diagnostics - clear_generation_free_space_flags(); - // Limits on our growth size_t promo_limit = (size_t)(max_old_gen_size - avg_old_live()->average()); - // This method sets the desired eden size. That plus the - // desired survivor space sizes sets the desired young generation - // size. This methods does not know what the desired survivor - // size is but expects that other policy will attempt to make - // the survivor sizes compatible with the live data in the - // young generation. This limit is an estimate of the space left - // in the young generation after the survivor spaces have been - // subtracted out. - size_t eden_limit = max_eden_size; - // But don't force a promo size below the current promo size. Otherwise, // the promo size will shrink for no good reason. promo_limit = MAX2(promo_limit, _promo_size); @@ -290,7 +489,6 @@ void PSAdaptiveSizePolicy::compute_generation_free_space( // a change less than the necessary alignment is probably not worth // attempting. - if ((_avg_minor_pause->padded_average() > gc_pause_goal_sec()) || (_avg_major_pause->padded_average() > gc_pause_goal_sec())) { // @@ -298,12 +496,13 @@ void PSAdaptiveSizePolicy::compute_generation_free_space( // // Make changes only to affect one of the pauses (the larger) // at a time. - adjust_for_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size); - + if (is_full_gc) { + set_decide_at_full_gc(decide_at_full_gc_true); + adjust_promo_for_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size); + } } else if (_avg_minor_pause->padded_average() > gc_minor_pause_goal_sec()) { // Adjust only for the minor pause time goal - adjust_for_minor_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size); - + adjust_promo_for_minor_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size); } else if(adjusted_mutator_cost() < _throughput_goal) { // This branch used to require that (mutator_cost() > 0.0 in 1.4.2. // This sometimes resulted in skipping to the minimize footprint @@ -316,8 +515,10 @@ void PSAdaptiveSizePolicy::compute_generation_free_space( assert(major_cost >= 0.0, "major cost is < 0.0"); assert(minor_cost >= 0.0, "minor cost is < 0.0"); // Try to reduce the GC times. - adjust_for_throughput(is_full_gc, &desired_promo_size, &desired_eden_size); - + if (is_full_gc) { + set_decide_at_full_gc(decide_at_full_gc_true); + adjust_promo_for_throughput(is_full_gc, &desired_promo_size); + } } else { // Be conservative about reducing the footprint. @@ -327,13 +528,10 @@ void PSAdaptiveSizePolicy::compute_generation_free_space( young_gen_policy_is_ready() && avg_major_gc_cost()->average() >= 0.0 && avg_minor_gc_cost()->average() >= 0.0) { - size_t desired_sum = desired_eden_size + desired_promo_size; - desired_eden_size = adjust_eden_for_footprint(desired_eden_size, - desired_sum); if (is_full_gc) { set_decide_at_full_gc(decide_at_full_gc_true); - desired_promo_size = adjust_promo_for_footprint(desired_promo_size, - desired_sum); + size_t desired_sum = desired_eden_size + desired_promo_size; + desired_promo_size = adjust_promo_for_footprint(desired_promo_size, desired_sum); } } } @@ -345,7 +543,7 @@ void PSAdaptiveSizePolicy::compute_generation_free_space( // "free_in_old_gen" was the original value for used for promo_limit size_t free_in_old_gen = (size_t)(max_old_gen_size - avg_old_live()->average()); gclog_or_tty->print_cr( - "PSAdaptiveSizePolicy::compute_generation_free_space limits:" + "PSAdaptiveSizePolicy::compute_old_gen_free_space limits:" " desired_promo_size: " SIZE_FORMAT " promo_limit: " SIZE_FORMAT " free_in_old_gen: " SIZE_FORMAT @@ -354,21 +552,9 @@ void PSAdaptiveSizePolicy::compute_generation_free_space( desired_promo_size, promo_limit, free_in_old_gen, max_old_gen_size, (size_t) avg_old_live()->average()); } - if (desired_eden_size > eden_limit) { - gclog_or_tty->print_cr( - "AdaptiveSizePolicy::compute_generation_free_space limits:" - " desired_eden_size: " SIZE_FORMAT - " old_eden_size: " SIZE_FORMAT - " eden_limit: " SIZE_FORMAT - " cur_eden: " SIZE_FORMAT - " max_eden_size: " SIZE_FORMAT - " avg_young_live: " SIZE_FORMAT, - desired_eden_size, _eden_size, eden_limit, cur_eden, - max_eden_size, (size_t)avg_young_live()->average()); - } if (gc_cost() > gc_cost_limit) { gclog_or_tty->print_cr( - "AdaptiveSizePolicy::compute_generation_free_space: gc time limit" + "PSAdaptiveSizePolicy::compute_old_gen_free_space: gc time limit" " gc_cost: %f " " GCTimeLimit: %d", gc_cost(), GCTimeLimit); @@ -377,46 +563,18 @@ void PSAdaptiveSizePolicy::compute_generation_free_space( // Align everything and make a final limit check const size_t alignment = _intra_generation_alignment; - desired_eden_size = align_size_up(desired_eden_size, alignment); - desired_eden_size = MAX2(desired_eden_size, alignment); desired_promo_size = align_size_up(desired_promo_size, alignment); desired_promo_size = MAX2(desired_promo_size, alignment); - eden_limit = align_size_down(eden_limit, alignment); promo_limit = align_size_down(promo_limit, alignment); - // Is too much time being spent in GC? - // Is the heap trying to grow beyond it's limits? - - const size_t free_in_old_gen = - (size_t)(max_old_gen_size - avg_old_live()->average()); - if (desired_promo_size > free_in_old_gen && desired_eden_size > eden_limit) { - check_gc_overhead_limit(young_live, - eden_live, - max_old_gen_size, - max_eden_size, - is_full_gc, - gc_cause, - collector_policy); - } - - // And one last limit check, now that we've aligned things. - if (desired_eden_size > eden_limit) { - // If the policy says to get a larger eden but - // is hitting the limit, don't decrease eden. - // This can lead to a general drifting down of the - // eden size. Let the tenuring calculation push more - // into the old gen. - desired_eden_size = MAX2(eden_limit, cur_eden); - } desired_promo_size = MIN2(desired_promo_size, promo_limit); - if (PrintAdaptiveSizePolicy) { // Timing stats gclog_or_tty->print( - "PSAdaptiveSizePolicy::compute_generation_free_space: costs" + "PSAdaptiveSizePolicy::compute_old_gen_free_space: costs" " minor_time: %f" " major_cost: %f" " mutator_cost: %f" @@ -454,19 +612,13 @@ void PSAdaptiveSizePolicy::compute_generation_free_space( // And finally, our old and new sizes. gclog_or_tty->print(" old_promo_size: " SIZE_FORMAT - " old_eden_size: " SIZE_FORMAT - " desired_promo_size: " SIZE_FORMAT - " desired_eden_size: " SIZE_FORMAT, - _promo_size, _eden_size, - desired_promo_size, desired_eden_size); + " desired_promo_size: " SIZE_FORMAT, + _promo_size, desired_promo_size); gclog_or_tty->cr(); } - decay_supplemental_growth(is_full_gc); - set_promo_size(desired_promo_size); - set_eden_size(desired_eden_size); -}; +} void PSAdaptiveSizePolicy::decay_supplemental_growth(bool is_full_gc) { // Decay the supplemental increment? Decay the supplement growth @@ -490,9 +642,39 @@ void PSAdaptiveSizePolicy::decay_supplemental_growth(bool is_full_gc) { } } -void PSAdaptiveSizePolicy::adjust_for_minor_pause_time(bool is_full_gc, +void PSAdaptiveSizePolicy::adjust_promo_for_minor_pause_time(bool is_full_gc, size_t* desired_promo_size_ptr, size_t* desired_eden_size_ptr) { + if (PSAdjustTenuredGenForMinorPause) { + if (is_full_gc) { + set_decide_at_full_gc(decide_at_full_gc_true); + } + // If the desired eden size is as small as it will get, + // try to adjust the old gen size. + if (*desired_eden_size_ptr <= _intra_generation_alignment) { + // Vary the old gen size to reduce the young gen pause. This + // may not be a good idea. This is just a test. + if (minor_pause_old_estimator()->decrement_will_decrease()) { + set_change_old_gen_for_min_pauses(decrease_old_gen_for_min_pauses_true); + *desired_promo_size_ptr = + _promo_size - promo_decrement_aligned_down(*desired_promo_size_ptr); + } else { + set_change_old_gen_for_min_pauses(increase_old_gen_for_min_pauses_true); + size_t promo_heap_delta = + promo_increment_with_supplement_aligned_up(*desired_promo_size_ptr); + if ((*desired_promo_size_ptr + promo_heap_delta) > + *desired_promo_size_ptr) { + *desired_promo_size_ptr = + _promo_size + promo_heap_delta; + } + } + } + } +} + +void PSAdaptiveSizePolicy::adjust_eden_for_minor_pause_time(bool is_full_gc, + size_t* desired_eden_size_ptr) { + // Adjust the young generation size to reduce pause time of // of collections. // @@ -512,49 +694,19 @@ void PSAdaptiveSizePolicy::adjust_for_minor_pause_time(bool is_full_gc, set_change_young_gen_for_min_pauses( increase_young_gen_for_min_pauses_true); } - if (PSAdjustTenuredGenForMinorPause) { - // If the desired eden size is as small as it will get, - // try to adjust the old gen size. - if (*desired_eden_size_ptr <= _intra_generation_alignment) { - // Vary the old gen size to reduce the young gen pause. This - // may not be a good idea. This is just a test. - if (minor_pause_old_estimator()->decrement_will_decrease()) { - set_change_old_gen_for_min_pauses( - decrease_old_gen_for_min_pauses_true); - *desired_promo_size_ptr = - _promo_size - promo_decrement_aligned_down(*desired_promo_size_ptr); - } else { - set_change_old_gen_for_min_pauses( - increase_old_gen_for_min_pauses_true); - size_t promo_heap_delta = - promo_increment_with_supplement_aligned_up(*desired_promo_size_ptr); - if ((*desired_promo_size_ptr + promo_heap_delta) > - *desired_promo_size_ptr) { - *desired_promo_size_ptr = - _promo_size + promo_heap_delta; - } - } - } - } } -void PSAdaptiveSizePolicy::adjust_for_pause_time(bool is_full_gc, +void PSAdaptiveSizePolicy::adjust_promo_for_pause_time(bool is_full_gc, size_t* desired_promo_size_ptr, size_t* desired_eden_size_ptr) { size_t promo_heap_delta = 0; - size_t eden_heap_delta = 0; - // Add some checks for a threshhold for a change. For example, + // Add some checks for a threshold for a change. For example, // a change less than the required alignment is probably not worth // attempting. - if (is_full_gc) { - set_decide_at_full_gc(decide_at_full_gc_true); - } if (_avg_minor_pause->padded_average() > _avg_major_pause->padded_average()) { - adjust_for_minor_pause_time(is_full_gc, - desired_promo_size_ptr, - desired_eden_size_ptr); + adjust_promo_for_minor_pause_time(is_full_gc, desired_promo_size_ptr, desired_eden_size_ptr); // major pause adjustments } else if (is_full_gc) { // Adjust for the major pause time only at full gc's because the @@ -573,6 +725,33 @@ void PSAdaptiveSizePolicy::adjust_for_pause_time(bool is_full_gc, // promo_increment_aligned_up(*desired_promo_size_ptr); set_change_old_gen_for_maj_pauses(increase_old_gen_for_maj_pauses_true); } + } + + if (PrintAdaptiveSizePolicy && Verbose) { + gclog_or_tty->print_cr( + "PSAdaptiveSizePolicy::compute_old_gen_free_space " + "adjusting gen sizes for major pause (avg %f goal %f). " + "desired_promo_size " SIZE_FORMAT " promo delta " SIZE_FORMAT, + _avg_major_pause->average(), gc_pause_goal_sec(), + *desired_promo_size_ptr, promo_heap_delta); + } +} + +void PSAdaptiveSizePolicy::adjust_eden_for_pause_time(bool is_full_gc, + size_t* desired_promo_size_ptr, + size_t* desired_eden_size_ptr) { + + size_t eden_heap_delta = 0; + // Add some checks for a threshold for a change. For example, + // a change less than the required alignment is probably not worth + // attempting. + if (_avg_minor_pause->padded_average() > _avg_major_pause->padded_average()) { + adjust_eden_for_minor_pause_time(is_full_gc, + desired_eden_size_ptr); + // major pause adjustments + } else if (is_full_gc) { + // Adjust for the major pause time only at full gc's because the + // affects of a change can only be seen at full gc's. if (PSAdjustYoungGenForMajorPause) { // If the promo size is at the minimum (i.e., the old gen // size will not actually decrease), consider changing the @@ -607,43 +786,35 @@ void PSAdaptiveSizePolicy::adjust_for_pause_time(bool is_full_gc, if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr( - "AdaptiveSizePolicy::compute_generation_free_space " + "PSAdaptiveSizePolicy::compute_eden_space_size " "adjusting gen sizes for major pause (avg %f goal %f). " - "desired_promo_size " SIZE_FORMAT "desired_eden_size " - SIZE_FORMAT - " promo delta " SIZE_FORMAT " eden delta " SIZE_FORMAT, + "desired_eden_size " SIZE_FORMAT " eden delta " SIZE_FORMAT, _avg_major_pause->average(), gc_pause_goal_sec(), - *desired_promo_size_ptr, *desired_eden_size_ptr, - promo_heap_delta, eden_heap_delta); + *desired_eden_size_ptr, eden_heap_delta); } } -void PSAdaptiveSizePolicy::adjust_for_throughput(bool is_full_gc, - size_t* desired_promo_size_ptr, - size_t* desired_eden_size_ptr) { +void PSAdaptiveSizePolicy::adjust_promo_for_throughput(bool is_full_gc, + size_t* desired_promo_size_ptr) { - // Add some checks for a threshhold for a change. For example, + // Add some checks for a threshold for a change. For example, // a change less than the required alignment is probably not worth // attempting. - if (is_full_gc) { - set_decide_at_full_gc(decide_at_full_gc_true); - } if ((gc_cost() + mutator_cost()) == 0.0) { return; } if (PrintAdaptiveSizePolicy && Verbose) { - gclog_or_tty->print("\nPSAdaptiveSizePolicy::adjust_for_throughput(" - "is_full: %d, promo: " SIZE_FORMAT ", cur_eden: " SIZE_FORMAT "): ", - is_full_gc, *desired_promo_size_ptr, *desired_eden_size_ptr); + gclog_or_tty->print("\nPSAdaptiveSizePolicy::adjust_promo_for_throughput(" + "is_full: %d, promo: " SIZE_FORMAT "): ", + is_full_gc, *desired_promo_size_ptr); gclog_or_tty->print_cr("mutator_cost %f major_gc_cost %f " "minor_gc_cost %f", mutator_cost(), major_gc_cost(), minor_gc_cost()); } // Tenured generation if (is_full_gc) { - // Calculate the change to use for the tenured gen. size_t scaled_promo_heap_delta = 0; // Can the increment to the generation be scaled? @@ -720,6 +891,26 @@ void PSAdaptiveSizePolicy::adjust_for_throughput(bool is_full_gc, *desired_promo_size_ptr, scaled_promo_heap_delta); } } +} + +void PSAdaptiveSizePolicy::adjust_eden_for_throughput(bool is_full_gc, + size_t* desired_eden_size_ptr) { + + // Add some checks for a threshold for a change. For example, + // a change less than the required alignment is probably not worth + // attempting. + + if ((gc_cost() + mutator_cost()) == 0.0) { + return; + } + + if (PrintAdaptiveSizePolicy && Verbose) { + gclog_or_tty->print("\nPSAdaptiveSizePolicy::adjust_eden_for_throughput(" + "is_full: %d, cur_eden: " SIZE_FORMAT "): ", + is_full_gc, *desired_eden_size_ptr); + gclog_or_tty->print_cr("mutator_cost %f major_gc_cost %f " + "minor_gc_cost %f", mutator_cost(), major_gc_cost(), minor_gc_cost()); + } // Young generation size_t scaled_eden_heap_delta = 0; diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp index 030cb9da167..683c6a991fe 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -136,18 +136,24 @@ class PSAdaptiveSizePolicy : public AdaptiveSizePolicy { double gc_minor_pause_goal_sec() const { return _gc_minor_pause_goal_sec; } // Change the young generation size to achieve a minor GC pause time goal - void adjust_for_minor_pause_time(bool is_full_gc, + void adjust_promo_for_minor_pause_time(bool is_full_gc, size_t* desired_promo_size_ptr, size_t* desired_eden_size_ptr); + void adjust_eden_for_minor_pause_time(bool is_full_gc, + size_t* desired_eden_size_ptr); // Change the generation sizes to achieve a GC pause time goal // Returned sizes are not necessarily aligned. - void adjust_for_pause_time(bool is_full_gc, + void adjust_promo_for_pause_time(bool is_full_gc, + size_t* desired_promo_size_ptr, + size_t* desired_eden_size_ptr); + void adjust_eden_for_pause_time(bool is_full_gc, size_t* desired_promo_size_ptr, size_t* desired_eden_size_ptr); // Change the generation sizes to achieve an application throughput goal // Returned sizes are not necessarily aligned. - void adjust_for_throughput(bool is_full_gc, - size_t* desired_promo_size_ptr, + void adjust_promo_for_throughput(bool is_full_gc, + size_t* desired_promo_size_ptr); + void adjust_eden_for_throughput(bool is_full_gc, size_t* desired_eden_size_ptr); // Change the generation sizes to achieve minimum footprint // Returned sizes are not aligned. @@ -168,9 +174,6 @@ class PSAdaptiveSizePolicy : public AdaptiveSizePolicy { size_t promo_decrement_aligned_down(size_t cur_promo); size_t promo_increment_with_supplement_aligned_up(size_t cur_promo); - // Decay the supplemental growth additive. - void decay_supplemental_growth(bool is_full_gc); - // Returns a change that has been scaled down. Result // is not aligned. (If useful, move to some shared // location.) @@ -336,7 +339,7 @@ class PSAdaptiveSizePolicy : public AdaptiveSizePolicy { // perform a Full GC? bool should_full_GC(size_t live_in_old_gen); - // Calculates optimial free space sizes for both the old and young + // Calculates optimal (free) space sizes for both the young and old // generations. Stores results in _eden_size and _promo_size. // Takes current used space in all generations as input, as well // as an indication if a full gc has just been performed, for use @@ -347,9 +350,18 @@ class PSAdaptiveSizePolicy : public AdaptiveSizePolicy { size_t cur_eden, // current eden in bytes size_t max_old_gen_size, size_t max_eden_size, - bool is_full_gc, - GCCause::Cause gc_cause, - CollectorPolicy* collector_policy); + bool is_full_gc); + + void compute_eden_space_size(size_t young_live, + size_t eden_live, + size_t cur_eden, // current eden in bytes + size_t max_eden_size, + bool is_full_gc); + + void compute_old_gen_free_space(size_t old_live, + size_t cur_eden, // current eden in bytes + size_t max_old_gen_size, + bool is_full_gc); // Calculates new survivor space size; returns a new tenuring threshold // value. Stores new survivor size in _survivor_size. @@ -390,6 +402,9 @@ class PSAdaptiveSizePolicy : public AdaptiveSizePolicy { // Printing support virtual bool print_adaptive_size_policy_on(outputStream* st) const; + + // Decay the supplemental growth additive. + void decay_supplemental_growth(bool is_full_gc); }; #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSADAPTIVESIZEPOLICY_HPP diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp index adbaee43fc3..90b0d091486 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,8 +92,8 @@ void PSMarkSweep::invoke(bool maximum_heap_compaction) { const bool clear_all_soft_refs = heap->collector_policy()->should_clear_all_soft_refs(); - int count = (maximum_heap_compaction)?1:MarkSweepAlwaysCompactCount; - IntFlagSetting flag_setting(MarkSweepAlwaysCompactCount, count); + uint count = maximum_heap_compaction ? 1 : MarkSweepAlwaysCompactCount; + UIntFlagSetting flag_setting(MarkSweepAlwaysCompactCount, count); PSMarkSweep::invoke_no_policy(clear_all_soft_refs || maximum_heap_compaction); } @@ -277,18 +277,36 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { young_gen->from_space()->capacity_in_bytes() + young_gen->to_space()->capacity_in_bytes(), "Sizes of space in young gen are out-of-bounds"); + + size_t young_live = young_gen->used_in_bytes(); + size_t eden_live = young_gen->eden_space()->used_in_bytes(); + size_t old_live = old_gen->used_in_bytes(); + size_t cur_eden = young_gen->eden_space()->capacity_in_bytes(); + size_t max_old_gen_size = old_gen->max_gen_size(); size_t max_eden_size = young_gen->max_size() - young_gen->from_space()->capacity_in_bytes() - young_gen->to_space()->capacity_in_bytes(); - size_policy->compute_generation_free_space(young_gen->used_in_bytes(), - young_gen->eden_space()->used_in_bytes(), - old_gen->used_in_bytes(), - young_gen->eden_space()->capacity_in_bytes(), - old_gen->max_gen_size(), - max_eden_size, - true /* full gc*/, - gc_cause, - heap->collector_policy()); + + // Used for diagnostics + size_policy->clear_generation_free_space_flags(); + + size_policy->compute_generation_free_space(young_live, + eden_live, + old_live, + cur_eden, + max_old_gen_size, + max_eden_size, + true /* full gc*/); + + size_policy->check_gc_overhead_limit(young_live, + eden_live, + max_old_gen_size, + max_eden_size, + true /* full gc*/, + gc_cause, + heap->collector_policy()); + + size_policy->decay_supplemental_growth(true /* full gc*/); heap->resize_old_gen(size_policy->calculated_old_free_size_in_bytes()); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp index 9844d1afdf8..820696af085 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp @@ -88,8 +88,7 @@ void PSMarkSweepDecorator::precompact() { * by the MarkSweepAlwaysCompactCount parameter. This is a significant * performance improvement! */ - bool skip_dead = (MarkSweepAlwaysCompactCount < 1) - || ((PSMarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0); + bool skip_dead = ((PSMarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0); size_t allowed_deadspace = 0; if (skip_dead) { diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp index b03107a97cd..72177e10619 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -948,7 +948,6 @@ void PSParallelCompact::pre_compact(PreGCValues* pre_gc_values) pre_gc_values->fill(heap); - NOT_PRODUCT(_mark_bitmap.reset_counters()); DEBUG_ONLY(add_obj_count = add_obj_size = 0;) DEBUG_ONLY(mark_bitmap_count = mark_bitmap_size = 0;) @@ -2042,15 +2041,6 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { marking_start.update(); marking_phase(vmthread_cm, maximum_heap_compaction); -#ifndef PRODUCT - if (TraceParallelOldGCMarkingPhase) { - gclog_or_tty->print_cr("marking_phase: cas_tries %d cas_retries %d " - "cas_by_another %d", - mark_bitmap()->cas_tries(), mark_bitmap()->cas_retries(), - mark_bitmap()->cas_by_another()); - } -#endif // #ifndef PRODUCT - bool max_on_system_gc = UseMaximumCompactionOnSystemGC && gc_cause == GCCause::_java_lang_system_gc; summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc); @@ -2094,19 +2084,36 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { young_gen->from_space()->capacity_in_bytes() + young_gen->to_space()->capacity_in_bytes(), "Sizes of space in young gen are out-of-bounds"); + + size_t young_live = young_gen->used_in_bytes(); + size_t eden_live = young_gen->eden_space()->used_in_bytes(); + size_t old_live = old_gen->used_in_bytes(); + size_t cur_eden = young_gen->eden_space()->capacity_in_bytes(); + size_t max_old_gen_size = old_gen->max_gen_size(); size_t max_eden_size = young_gen->max_size() - young_gen->from_space()->capacity_in_bytes() - young_gen->to_space()->capacity_in_bytes(); - size_policy->compute_generation_free_space( - young_gen->used_in_bytes(), - young_gen->eden_space()->used_in_bytes(), - old_gen->used_in_bytes(), - young_gen->eden_space()->capacity_in_bytes(), - old_gen->max_gen_size(), - max_eden_size, - true /* full gc*/, - gc_cause, - heap->collector_policy()); + + // Used for diagnostics + size_policy->clear_generation_free_space_flags(); + + size_policy->compute_generation_free_space(young_live, + eden_live, + old_live, + cur_eden, + max_old_gen_size, + max_eden_size, + true /* full gc*/); + + size_policy->check_gc_overhead_limit(young_live, + eden_live, + max_old_gen_size, + max_eden_size, + true /* full gc*/, + gc_cause, + heap->collector_policy()); + + size_policy->decay_supplemental_growth(true /* full gc*/); heap->resize_old_gen( size_policy->calculated_old_free_size_in_bytes()); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp index 4bc7870b98a..f427c3941c5 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp @@ -552,19 +552,33 @@ bool PSScavenge::invoke_no_policy() { young_gen->from_space()->capacity_in_bytes() + young_gen->to_space()->capacity_in_bytes(), "Sizes of space in young gen are out-of-bounds"); + + size_t young_live = young_gen->used_in_bytes(); + size_t eden_live = young_gen->eden_space()->used_in_bytes(); + size_t cur_eden = young_gen->eden_space()->capacity_in_bytes(); + size_t max_old_gen_size = old_gen->max_gen_size(); size_t max_eden_size = young_gen->max_size() - young_gen->from_space()->capacity_in_bytes() - young_gen->to_space()->capacity_in_bytes(); - size_policy->compute_generation_free_space(young_gen->used_in_bytes(), - young_gen->eden_space()->used_in_bytes(), - old_gen->used_in_bytes(), - young_gen->eden_space()->capacity_in_bytes(), - old_gen->max_gen_size(), - max_eden_size, - false /* full gc*/, - gc_cause, - heap->collector_policy()); + // Used for diagnostics + size_policy->clear_generation_free_space_flags(); + + size_policy->compute_eden_space_size(young_live, + eden_live, + cur_eden, + max_eden_size, + false /* not full gc*/); + + size_policy->check_gc_overhead_limit(young_live, + eden_live, + max_old_gen_size, + max_eden_size, + false /* not full gc*/, + gc_cause, + heap->collector_policy()); + + size_policy->decay_supplemental_growth(false /* not full gc*/); } // Resize the young generation at every collection // even if new sizes have not been calculated. This is diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp index 905869e72cf..817a1e62609 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp @@ -30,7 +30,7 @@ #include "oops/objArrayKlass.inline.hpp" #include "oops/oop.inline.hpp" -unsigned int MarkSweep::_total_invocations = 0; +uint MarkSweep::_total_invocations = 0; Stack MarkSweep::_marking_stack; Stack MarkSweep::_objarray_stack; diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp index ec724afa5ec..dc3af9aa6c0 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp @@ -113,7 +113,7 @@ class MarkSweep : AllStatic { // protected: // Total invocations of a MarkSweep collection - static unsigned int _total_invocations; + static uint _total_invocations; // Traversal stacks used during phase1 static Stack _marking_stack; @@ -147,7 +147,7 @@ class MarkSweep : AllStatic { static AdjustKlassClosure adjust_klass_closure; // Accessors - static unsigned int total_invocations() { return _total_invocations; } + static uint total_invocations() { return _total_invocations; } // Reference Processing static ReferenceProcessor* const ref_processor() { return _ref_processor; } diff --git a/hotspot/src/share/vm/memory/collectorPolicy.cpp b/hotspot/src/share/vm/memory/collectorPolicy.cpp index 0ac674a324a..cba14a01459 100644 --- a/hotspot/src/share/vm/memory/collectorPolicy.cpp +++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp @@ -264,6 +264,27 @@ void TwoGenerationCollectorPolicy::initialize_flags() { // need to do this again MaxHeapSize = align_size_up(MaxHeapSize, max_alignment()); + // adjust max heap size if necessary + if (NewSize + OldSize > MaxHeapSize) { + if (FLAG_IS_CMDLINE(MaxHeapSize)) { + // somebody set a maximum heap size with the intention that we should not + // exceed it. Adjust New/OldSize as necessary. + uintx calculated_size = NewSize + OldSize; + double shrink_factor = (double) MaxHeapSize / calculated_size; + // align + NewSize = align_size_down((uintx) (NewSize * shrink_factor), min_alignment()); + // OldSize is already aligned because above we aligned MaxHeapSize to + // max_alignment(), and we just made sure that NewSize is aligned to + // min_alignment(). In initialize_flags() we verified that max_alignment() + // is a multiple of min_alignment(). + OldSize = MaxHeapSize - NewSize; + } else { + MaxHeapSize = NewSize + OldSize; + } + } + // need to do this again + MaxHeapSize = align_size_up(MaxHeapSize, max_alignment()); + always_do_update_barrier = UseConcMarkSweepGC; // Check validity of heap flags @@ -731,7 +752,7 @@ HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size, // free memory should be here, especially if they are expensive. If this // attempt fails, an OOM exception will be thrown. { - IntFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted + UIntFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted gch->do_collection(true /* full */, true /* clear_all_soft_refs */, diff --git a/hotspot/src/share/vm/memory/space.hpp b/hotspot/src/share/vm/memory/space.hpp index a434b0a337a..eb1e209a850 100644 --- a/hotspot/src/share/vm/memory/space.hpp +++ b/hotspot/src/share/vm/memory/space.hpp @@ -537,9 +537,8 @@ protected: * Occasionally, we want to ensure a full compaction, which is determined \ * by the MarkSweepAlwaysCompactCount parameter. \ */ \ - int invocations = MarkSweep::total_invocations(); \ - bool skip_dead = (MarkSweepAlwaysCompactCount < 1) \ - ||((invocations % MarkSweepAlwaysCompactCount) != 0); \ + uint invocations = MarkSweep::total_invocations(); \ + bool skip_dead = ((invocations % MarkSweepAlwaysCompactCount) != 0); \ \ size_t allowed_deadspace = 0; \ if (skip_dead) { \ diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index c8a9a36df39..62b81ea4e93 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -832,7 +832,9 @@ void Method::link_method(methodHandle h_method, TRAPS) { assert(entry != NULL, "interpreter entry must be non-null"); // Sets both _i2i_entry and _from_interpreted_entry set_interpreter_entry(entry); - if (is_native() && !is_method_handle_intrinsic()) { + + // Don't overwrite already registered native entries. + if (is_native() && !has_native_function()) { set_native_function( SharedRuntime::native_method_throw_unsatisfied_link_error_entry(), !native_bind_event_is_interesting); diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index 6d8f1b3da91..9d2a36be28e 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -85,16 +85,35 @@ InlineTree::InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvm assert(!UseOldInlining, "do not use for old stuff"); } +/** + * Return true when EA is ON and a java constructor is called or + * a super constructor is called from an inlined java constructor. + * Also return true for boxing methods. + */ static bool is_init_with_ea(ciMethod* callee_method, ciMethod* caller_method, Compile* C) { - // True when EA is ON and a java constructor is called or - // a super constructor is called from an inlined java constructor. - return C->do_escape_analysis() && EliminateAllocations && - ( callee_method->is_initializer() || - (caller_method->is_initializer() && - caller_method != C->method() && - caller_method->holder()->is_subclass_of(callee_method->holder())) - ); + if (!C->do_escape_analysis() || !EliminateAllocations) { + return false; // EA is off + } + if (callee_method->is_initializer()) { + return true; // constuctor + } + if (caller_method->is_initializer() && + caller_method != C->method() && + caller_method->holder()->is_subclass_of(callee_method->holder())) { + return true; // super constructor is called from inlined constructor + } + if (C->eliminate_boxing() && callee_method->is_boxing_method()) { + return true; + } + return false; +} + +/** + * Force inlining unboxing accessor. + */ +static bool is_unboxing_method(ciMethod* callee_method, Compile* C) { + return C->eliminate_boxing() && callee_method->is_unboxing_method(); } // positive filter: should callee be inlined? @@ -144,6 +163,7 @@ bool InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method, // bump the max size if the call is frequent if ((freq >= InlineFrequencyRatio) || (call_site_count >= InlineFrequencyCount) || + is_unboxing_method(callee_method, C) || is_init_with_ea(callee_method, caller_method, C)) { max_inline_size = C->freq_inline_size(); @@ -237,8 +257,25 @@ bool InlineTree::should_not_inline(ciMethod *callee_method, return false; } + if (callee_method->should_not_inline()) { + set_msg("disallowed by CompilerOracle"); + return true; + } + +#ifndef PRODUCT + if (ciReplay::should_not_inline(callee_method)) { + set_msg("disallowed by ciReplay"); + return true; + } +#endif + // Now perform checks which are heuristic + if (is_unboxing_method(callee_method, C)) { + // Inline unboxing methods. + return false; + } + if (!callee_method->force_inline()) { if (callee_method->has_compiled_code() && callee_method->instructions_size() > InlineSmallCode) { @@ -260,18 +297,6 @@ bool InlineTree::should_not_inline(ciMethod *callee_method, } } - if (callee_method->should_not_inline()) { - set_msg("disallowed by CompilerOracle"); - return true; - } - -#ifndef PRODUCT - if (ciReplay::should_not_inline(callee_method)) { - set_msg("disallowed by ciReplay"); - return true; - } -#endif - if (UseStringCache) { // Do not inline StringCache::profile() method used only at the beginning. if (callee_method->name() == ciSymbol::profile_name() && @@ -296,9 +321,8 @@ bool InlineTree::should_not_inline(ciMethod *callee_method, } if (is_init_with_ea(callee_method, caller_method, C)) { - // Escape Analysis: inline all executed constructors - + return false; } else if (!callee_method->was_executed_more_than(MIN2(MinInliningThreshold, CompileThreshold >> 1))) { set_msg("executed < MinInliningThreshold times"); diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index f01101cd4bb..49ed1e8bcf0 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -442,12 +442,15 @@ notproduct(bool, PrintEliminateLocks, false, \ "Print out when locks are eliminated") \ \ - diagnostic(bool, EliminateAutoBox, false, \ - "Private flag to control optimizations for autobox elimination") \ + product(bool, EliminateAutoBox, true, \ + "Control optimizations for autobox elimination") \ \ product(intx, AutoBoxCacheMax, 128, \ "Sets max value cached by the java.lang.Integer autobox cache") \ \ + experimental(bool, AggressiveUnboxing, false, \ + "Control optimizations for aggressive boxing elimination") \ + \ product(bool, DoEscapeAnalysis, true, \ "Perform escape analysis") \ \ diff --git a/hotspot/src/share/vm/opto/c2compiler.cpp b/hotspot/src/share/vm/opto/c2compiler.cpp index 713e3f1d1a1..85f30a5ac1e 100644 --- a/hotspot/src/share/vm/opto/c2compiler.cpp +++ b/hotspot/src/share/vm/opto/c2compiler.cpp @@ -125,9 +125,10 @@ void C2Compiler::compile_method(ciEnv* env, bool subsume_loads = SubsumeLoads; bool do_escape_analysis = DoEscapeAnalysis && !env->jvmti_can_access_local_variables(); + bool eliminate_boxing = EliminateAutoBox; while (!env->failing()) { // Attempt to compile while subsuming loads into machine instructions. - Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis); + Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing); // Check result and retry if appropriate. @@ -142,6 +143,12 @@ void C2Compiler::compile_method(ciEnv* env, do_escape_analysis = false; continue; // retry } + if (C.has_boxed_value()) { + // Recompile without boxing elimination regardless failure reason. + assert(eliminate_boxing, "must make progress"); + eliminate_boxing = false; + continue; // retry + } // Pass any other failure reason up to the ciEnv. // Note that serious, irreversible failures are already logged // on the ciEnv via env->record_method_not_compilable(). diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index 8cac8ee769b..470a36e5c9f 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -134,7 +134,7 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) { kit.C->log()->elem("direct_call bci='%d'", jvms->bci()); } - CallStaticJavaNode *call = new (kit.C) CallStaticJavaNode(tf(), target, method(), kit.bci()); + CallStaticJavaNode *call = new (kit.C) CallStaticJavaNode(kit.C, tf(), target, method(), kit.bci()); _call_node = call; // Save the call node in case we need it later if (!is_static) { // Make an explicit receiver null_check as part of this call. @@ -304,29 +304,34 @@ class LateInlineCallGenerator : public DirectCallGenerator { void LateInlineCallGenerator::do_late_inline() { // Can't inline it - if (call_node() == NULL || call_node()->outcnt() == 0 || - call_node()->in(0) == NULL || call_node()->in(0)->is_top()) { + CallStaticJavaNode* call = call_node(); + if (call == NULL || call->outcnt() == 0 || + call->in(0) == NULL || call->in(0)->is_top()) { return; } - const TypeTuple *r = call_node()->tf()->domain(); + const TypeTuple *r = call->tf()->domain(); for (int i1 = 0; i1 < method()->arg_size(); i1++) { - if (call_node()->in(TypeFunc::Parms + i1)->is_top() && r->field_at(TypeFunc::Parms + i1) != Type::HALF) { + if (call->in(TypeFunc::Parms + i1)->is_top() && r->field_at(TypeFunc::Parms + i1) != Type::HALF) { assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing"); return; } } - if (call_node()->in(TypeFunc::Memory)->is_top()) { + if (call->in(TypeFunc::Memory)->is_top()) { assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing"); return; } - CallStaticJavaNode* call = call_node(); + Compile* C = Compile::current(); + // Remove inlined methods from Compiler's lists. + if (call->is_macro()) { + C->remove_macro_node(call); + } // Make a clone of the JVMState that appropriate to use for driving a parse - Compile* C = Compile::current(); - JVMState* jvms = call->jvms()->clone_shallow(C); + JVMState* old_jvms = call->jvms(); + JVMState* jvms = old_jvms->clone_shallow(C); uint size = call->req(); SafePointNode* map = new (C) SafePointNode(size, jvms); for (uint i1 = 0; i1 < size; i1++) { @@ -340,16 +345,23 @@ void LateInlineCallGenerator::do_late_inline() { map->set_req(TypeFunc::Memory, mem); } - // Make enough space for the expression stack and transfer the incoming arguments - int nargs = method()->arg_size(); + uint nargs = method()->arg_size(); + // blow away old call arguments + Node* top = C->top(); + for (uint i1 = 0; i1 < nargs; i1++) { + map->set_req(TypeFunc::Parms + i1, top); + } jvms->set_map(map); + + // Make enough space in the expression stack to transfer + // the incoming arguments and return value. map->ensure_stack(jvms, jvms->method()->max_stack()); - if (nargs > 0) { - for (int i1 = 0; i1 < nargs; i1++) { - map->set_req(i1 + jvms->argoff(), call->in(TypeFunc::Parms + i1)); - } + for (uint i1 = 0; i1 < nargs; i1++) { + map->set_argument(jvms, i1, call->in(TypeFunc::Parms + i1)); } + // This check is done here because for_method_handle_inline() method + // needs jvms for inlined state. if (!do_late_inline_check(jvms)) { map->disconnect_inputs(NULL, C); return; @@ -480,6 +492,26 @@ CallGenerator* CallGenerator::for_string_late_inline(ciMethod* method, CallGener return new LateInlineStringCallGenerator(method, inline_cg); } +class LateInlineBoxingCallGenerator : public LateInlineCallGenerator { + + public: + LateInlineBoxingCallGenerator(ciMethod* method, CallGenerator* inline_cg) : + LateInlineCallGenerator(method, inline_cg) {} + + virtual JVMState* generate(JVMState* jvms) { + Compile *C = Compile::current(); + C->print_inlining_skip(this); + + C->add_boxing_late_inline(this); + + JVMState* new_jvms = DirectCallGenerator::generate(jvms); + return new_jvms; + } +}; + +CallGenerator* CallGenerator::for_boxing_late_inline(ciMethod* method, CallGenerator* inline_cg) { + return new LateInlineBoxingCallGenerator(method, inline_cg); +} //---------------------------WarmCallGenerator-------------------------------- // Internal class which handles initial deferral of inlining decisions. diff --git a/hotspot/src/share/vm/opto/callGenerator.hpp b/hotspot/src/share/vm/opto/callGenerator.hpp index 7051dbe5c2e..8cdc4e827cd 100644 --- a/hotspot/src/share/vm/opto/callGenerator.hpp +++ b/hotspot/src/share/vm/opto/callGenerator.hpp @@ -125,6 +125,7 @@ class CallGenerator : public ResourceObj { static CallGenerator* for_late_inline(ciMethod* m, CallGenerator* inline_cg); static CallGenerator* for_mh_late_inline(ciMethod* caller, ciMethod* callee, bool input_not_const); static CallGenerator* for_string_late_inline(ciMethod* m, CallGenerator* inline_cg); + static CallGenerator* for_boxing_late_inline(ciMethod* m, CallGenerator* inline_cg); // How to make a call but defer the decision whether to inline or not. static CallGenerator* for_warm_call(WarmCallInfo* ci, diff --git a/hotspot/src/share/vm/opto/callnode.cpp b/hotspot/src/share/vm/opto/callnode.cpp index c90b76d4adb..cce6c5f29b4 100644 --- a/hotspot/src/share/vm/opto/callnode.cpp +++ b/hotspot/src/share/vm/opto/callnode.cpp @@ -523,7 +523,9 @@ void JVMState::dump_spec(outputStream *st) const { void JVMState::dump_on(outputStream* st) const { - if (_map && !((uintptr_t)_map & 1)) { + bool print_map = _map && !((uintptr_t)_map & 1) && + ((caller() == NULL) || (caller()->map() != _map)); + if (print_map) { if (_map->len() > _map->req()) { // _map->has_exceptions() Node* ex = _map->in(_map->req()); // _map->next_exception() // skip the first one; it's already being printed @@ -532,7 +534,10 @@ void JVMState::dump_on(outputStream* st) const { ex->dump(1); } } - _map->dump(2); + _map->dump(Verbose ? 2 : 1); + } + if (caller() != NULL) { + caller()->dump_on(st); } st->print("JVMS depth=%d loc=%d stk=%d arg=%d mon=%d scalar=%d end=%d mondepth=%d sp=%d bci=%d reexecute=%s method=", depth(), locoff(), stkoff(), argoff(), monoff(), scloff(), endoff(), monitor_depth(), sp(), bci(), should_reexecute()?"true":"false"); @@ -546,9 +551,6 @@ void JVMState::dump_on(outputStream* st) const { _method->print_codes_on(bci(), bci()+1, st); } } - if (caller() != NULL) { - caller()->dump_on(st); - } } // Extra way to dump a jvms from the debugger, @@ -584,6 +586,15 @@ JVMState* JVMState::clone_deep(Compile* C) const { return n; } +/** + * Reset map for all callers + */ +void JVMState::set_map_deep(SafePointNode* map) { + for (JVMState* p = this; p->_caller != NULL; p = p->_caller) { + p->set_map(map); + } +} + //============================================================================= uint CallNode::cmp( const Node &n ) const { return _tf == ((CallNode&)n)._tf && _jvms == ((CallNode&)n)._jvms; } @@ -663,17 +674,49 @@ uint CallNode::match_edge(uint idx) const { // Determine whether the call could modify the field of the specified // instance at the specified offset. // -bool CallNode::may_modify(const TypePtr *addr_t, PhaseTransform *phase) { - const TypeOopPtr *adrInst_t = addr_t->isa_oopptr(); - - // If not an OopPtr or not an instance type, assume the worst. - // Note: currently this method is called only for instance types. - if (adrInst_t == NULL || !adrInst_t->is_known_instance()) { - return true; +bool CallNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) { + assert((t_oop != NULL), "sanity"); + if (t_oop->is_known_instance()) { + // The instance_id is set only for scalar-replaceable allocations which + // are not passed as arguments according to Escape Analysis. + return false; } - // The instance_id is set only for scalar-replaceable allocations which - // are not passed as arguments according to Escape Analysis. - return false; + if (t_oop->is_ptr_to_boxed_value()) { + ciKlass* boxing_klass = t_oop->klass(); + if (is_CallStaticJava() && as_CallStaticJava()->is_boxing_method()) { + // Skip unrelated boxing methods. + Node* proj = proj_out(TypeFunc::Parms); + if ((proj == NULL) || (phase->type(proj)->is_instptr()->klass() != boxing_klass)) { + return false; + } + } + if (is_CallJava() && as_CallJava()->method() != NULL) { + ciMethod* meth = as_CallJava()->method(); + if (meth->is_accessor()) { + return false; + } + // May modify (by reflection) if an boxing object is passed + // as argument or returned. + if (returns_pointer() && (proj_out(TypeFunc::Parms) != NULL)) { + Node* proj = proj_out(TypeFunc::Parms); + const TypeInstPtr* inst_t = phase->type(proj)->isa_instptr(); + if ((inst_t != NULL) && (!inst_t->klass_is_exact() || + (inst_t->klass() == boxing_klass))) { + return true; + } + } + const TypeTuple* d = tf()->domain(); + for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { + const TypeInstPtr* inst_t = d->field_at(i)->isa_instptr(); + if ((inst_t != NULL) && (!inst_t->klass_is_exact() || + (inst_t->klass() == boxing_klass))) { + return true; + } + } + return false; + } + } + return true; } // Does this call have a direct reference to n other than debug information? @@ -1020,6 +1063,7 @@ void SafePointNode::grow_stack(JVMState* jvms, uint grow_by) { int scloff = jvms->scloff(); int endoff = jvms->endoff(); assert(endoff == (int)req(), "no other states or debug info after me"); + assert(jvms->scl_size() == 0, "parsed code should not have scalar objects"); Node* top = Compile::current()->top(); for (uint i = 0; i < grow_by; i++) { ins_req(monoff, top); @@ -1035,6 +1079,7 @@ void SafePointNode::push_monitor(const FastLockNode *lock) { const int MonitorEdges = 2; assert(JVMState::logMonitorEdges == exact_log2(MonitorEdges), "correct MonitorEdges"); assert(req() == jvms()->endoff(), "correct sizing"); + assert((jvms()->scl_size() == 0), "parsed code should not have scalar objects"); int nextmon = jvms()->scloff(); if (GenerateSynchronizationCode) { add_req(lock->box_node()); @@ -1050,6 +1095,7 @@ void SafePointNode::push_monitor(const FastLockNode *lock) { void SafePointNode::pop_monitor() { // Delete last monitor from debug info + assert((jvms()->scl_size() == 0), "parsed code should not have scalar objects"); debug_only(int num_before_pop = jvms()->nof_monitors()); const int MonitorEdges = (1<scloff(); @@ -1154,6 +1200,7 @@ AllocateNode::AllocateNode(Compile* C, const TypeFunc *atype, init_class_id(Class_Allocate); init_flags(Flag_is_macro); _is_scalar_replaceable = false; + _is_non_escaping = false; Node *topnode = C->top(); init_req( TypeFunc::Control , ctrl ); @@ -1169,8 +1216,6 @@ AllocateNode::AllocateNode(Compile* C, const TypeFunc *atype, } //============================================================================= -uint AllocateArrayNode::size_of() const { return sizeof(*this); } - Node* AllocateArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { if (remove_dead_region(phase, can_reshape)) return this; // Don't bother trying to transform a dead node @@ -1235,6 +1280,8 @@ Node *AllocateArrayNode::make_ideal_length(const TypeOopPtr* oop_type, PhaseTran // - the narrow_length is 0 // - the narrow_length is not wider than length assert(narrow_length_type == TypeInt::ZERO || + length_type->is_con() && narrow_length_type->is_con() && + (narrow_length_type->_hi <= length_type->_lo) || (narrow_length_type->_hi <= length_type->_hi && narrow_length_type->_lo >= length_type->_lo), "narrow type must be narrower than length type"); diff --git a/hotspot/src/share/vm/opto/callnode.hpp b/hotspot/src/share/vm/opto/callnode.hpp index 0aa35c214e5..ebcca023315 100644 --- a/hotspot/src/share/vm/opto/callnode.hpp +++ b/hotspot/src/share/vm/opto/callnode.hpp @@ -49,6 +49,7 @@ class CallLeafNode; class CallLeafNoFPNode; class AllocateNode; class AllocateArrayNode; +class BoxLockNode; class LockNode; class UnlockNode; class JVMState; @@ -235,7 +236,6 @@ public: int loc_size() const { return stkoff() - locoff(); } int stk_size() const { return monoff() - stkoff(); } - int arg_size() const { return monoff() - argoff(); } int mon_size() const { return scloff() - monoff(); } int scl_size() const { return endoff() - scloff(); } @@ -298,6 +298,7 @@ public: // Miscellaneous utility functions JVMState* clone_deep(Compile* C) const; // recursively clones caller chain JVMState* clone_shallow(Compile* C) const; // retains uncloned caller + void set_map_deep(SafePointNode *map);// reset map for all callers #ifndef PRODUCT void format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) const; @@ -439,7 +440,7 @@ public: static bool needs_polling_address_input(); #ifndef PRODUCT - virtual void dump_spec(outputStream *st) const; + virtual void dump_spec(outputStream *st) const; #endif }; @@ -554,10 +555,10 @@ public: virtual bool guaranteed_safepoint() { return true; } // For macro nodes, the JVMState gets modified during expansion, so when cloning // the node the JVMState must be cloned. - virtual void clone_jvms() { } // default is not to clone + virtual void clone_jvms(Compile* C) { } // default is not to clone // Returns true if the call may modify n - virtual bool may_modify(const TypePtr *addr_t, PhaseTransform *phase); + virtual bool may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase); // Does this node have a use of n other than in debug information? bool has_non_debug_use(Node *n); // Returns the unique CheckCastPP of a call @@ -630,9 +631,15 @@ class CallStaticJavaNode : public CallJavaNode { virtual uint cmp( const Node &n ) const; virtual uint size_of() const; // Size is bigger public: - CallStaticJavaNode(const TypeFunc* tf, address addr, ciMethod* method, int bci) + CallStaticJavaNode(Compile* C, const TypeFunc* tf, address addr, ciMethod* method, int bci) : CallJavaNode(tf, addr, method, bci), _name(NULL) { init_class_id(Class_CallStaticJava); + if (C->eliminate_boxing() && (method != NULL) && method->is_boxing_method()) { + init_flags(Flag_is_macro); + C->add_macro_node(this); + } + _is_scalar_replaceable = false; + _is_non_escaping = false; } CallStaticJavaNode(const TypeFunc* tf, address addr, const char* name, int bci, const TypePtr* adr_type) @@ -640,13 +647,31 @@ public: init_class_id(Class_CallStaticJava); // This node calls a runtime stub, which often has narrow memory effects. _adr_type = adr_type; + _is_scalar_replaceable = false; + _is_non_escaping = false; } - const char *_name; // Runtime wrapper name + const char *_name; // Runtime wrapper name + + // Result of Escape Analysis + bool _is_scalar_replaceable; + bool _is_non_escaping; // If this is an uncommon trap, return the request code, else zero. int uncommon_trap_request() const; static int extract_uncommon_trap_request(const Node* call); + bool is_boxing_method() const { + return is_macro() && (method() != NULL) && method()->is_boxing_method(); + } + // Later inlining modifies the JVMState, so we need to clone it + // when the call node is cloned (because it is macro node). + virtual void clone_jvms(Compile* C) { + if ((jvms() != NULL) && is_boxing_method()) { + set_jvms(jvms()->clone_deep(C)); + jvms()->set_map_deep(this); + } + } + virtual int Opcode() const; #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; @@ -748,12 +773,12 @@ public: ParmLimit }; - static const TypeFunc* alloc_type() { + static const TypeFunc* alloc_type(const Type* t) { const Type** fields = TypeTuple::fields(ParmLimit - TypeFunc::Parms); fields[AllocSize] = TypeInt::POS; fields[KlassNode] = TypeInstPtr::NOTNULL; fields[InitialTest] = TypeInt::BOOL; - fields[ALength] = TypeInt::INT; // length (can be a bad length) + fields[ALength] = t; // length (can be a bad length) const TypeTuple *domain = TypeTuple::make(ParmLimit, fields); @@ -766,21 +791,26 @@ public: return TypeFunc::make(domain, range); } - bool _is_scalar_replaceable; // Result of Escape Analysis + // Result of Escape Analysis + bool _is_scalar_replaceable; + bool _is_non_escaping; virtual uint size_of() const; // Size is bigger AllocateNode(Compile* C, const TypeFunc *atype, Node *ctrl, Node *mem, Node *abio, Node *size, Node *klass_node, Node *initial_test); // Expansion modifies the JVMState, so we need to clone it - virtual void clone_jvms() { - set_jvms(jvms()->clone_deep(Compile::current())); + virtual void clone_jvms(Compile* C) { + if (jvms() != NULL) { + set_jvms(jvms()->clone_deep(C)); + jvms()->set_map_deep(this); + } } virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegP; } virtual bool guaranteed_safepoint() { return false; } // allocations do not modify their arguments - virtual bool may_modify(const TypePtr *addr_t, PhaseTransform *phase) { return false;} + virtual bool may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) { return false;} // Pattern-match a possible usage of AllocateNode. // Return null if no allocation is recognized. @@ -815,10 +845,6 @@ public: // are defined in graphKit.cpp, which sets up the bidirectional relation.) InitializeNode* initialization(); - // Return the corresponding storestore barrier (or null if none). - // Walks out edges to find it... - MemBarStoreStoreNode* storestore(); - // Convenience for initialization->maybe_set_complete(phase) bool maybe_set_complete(PhaseGVN* phase); }; @@ -840,7 +866,6 @@ public: set_req(AllocateNode::ALength, count_val); } virtual int Opcode() const; - virtual uint size_of() const; // Size is bigger virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); // Dig the length operand out of a array allocation site. @@ -918,7 +943,7 @@ public: void set_nested() { _kind = Nested; set_eliminated_lock_counter(); } // locking does not modify its arguments - virtual bool may_modify(const TypePtr *addr_t, PhaseTransform *phase){ return false;} + virtual bool may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase){ return false;} #ifndef PRODUCT void create_lock_counter(JVMState* s); @@ -965,8 +990,11 @@ public: virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); // Expansion modifies the JVMState, so we need to clone it - virtual void clone_jvms() { - set_jvms(jvms()->clone_deep(Compile::current())); + virtual void clone_jvms(Compile* C) { + if (jvms() != NULL) { + set_jvms(jvms()->clone_deep(C)); + jvms()->set_map_deep(this); + } } bool is_nested_lock_region(); // Is this Lock nested? diff --git a/hotspot/src/share/vm/opto/cfgnode.cpp b/hotspot/src/share/vm/opto/cfgnode.cpp index 68fcc9cbb8e..4185ada5d1c 100644 --- a/hotspot/src/share/vm/opto/cfgnode.cpp +++ b/hotspot/src/share/vm/opto/cfgnode.cpp @@ -806,7 +806,7 @@ PhiNode* PhiNode::split_out_instance(const TypePtr* at, PhaseIterGVN *igvn) cons Node *in = ophi->in(i); if (in == NULL || igvn->type(in) == Type::TOP) continue; - Node *opt = MemNode::optimize_simple_memory_chain(in, at, igvn); + Node *opt = MemNode::optimize_simple_memory_chain(in, t_oop, NULL, igvn); PhiNode *optphi = opt->is_Phi() ? opt->as_Phi() : NULL; if (optphi != NULL && optphi->adr_type() == TypePtr::BOTTOM) { opt = node_map[optphi->_idx]; @@ -1921,7 +1921,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { const TypePtr* at = adr_type(); for( uint i=1; iprint_cr("** Bailout: Recompile without escape analysis **"); tty->print_cr("*********************************************************"); } + if (_eliminate_boxing != EliminateAutoBox && PrintOpto) { + // Recompiling without boxing elimination + tty->print_cr("*********************************************************"); + tty->print_cr("** Bailout: Recompile without boxing elimination **"); + tty->print_cr("*********************************************************"); + } if (env()->break_at_compile()) { // Open the debugger when compiling this method. tty->print("### Breaking when compiling: "); @@ -601,7 +608,8 @@ debug_only( int Compile::_debug_idx = 100000; ) // the continuation bci for on stack replacement. -Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr_bci, bool subsume_loads, bool do_escape_analysis ) +Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr_bci, + bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing ) : Phase(Compiler), _env(ci_env), _log(ci_env->log()), @@ -617,6 +625,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr _warm_calls(NULL), _subsume_loads(subsume_loads), _do_escape_analysis(do_escape_analysis), + _eliminate_boxing(eliminate_boxing), _failure_reason(NULL), _code_buffer("Compile::Fill_buffer"), _orig_pc_slot(0), @@ -638,6 +647,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr _congraph(NULL), _late_inlines(comp_arena(), 2, 0, NULL), _string_late_inlines(comp_arena(), 2, 0, NULL), + _boxing_late_inlines(comp_arena(), 2, 0, NULL), _late_inlines_pos(0), _number_of_mh_late_inlines(0), _inlining_progress(false), @@ -906,6 +916,7 @@ Compile::Compile( ciEnv* ci_env, _orig_pc_slot_offset_in_bytes(0), _subsume_loads(true), _do_escape_analysis(false), + _eliminate_boxing(false), _failure_reason(NULL), _code_buffer("Compile::Fill_buffer"), _has_method_handle_invokes(false), @@ -1016,6 +1027,7 @@ void Compile::Init(int aliaslevel) { set_has_split_ifs(false); set_has_loops(has_method() && method()->has_loops()); // first approximation set_has_stringbuilder(false); + set_has_boxed_value(false); _trap_can_recompile = false; // no traps emitted yet _major_progress = true; // start out assuming good things will happen set_has_unsafe_access(false); @@ -1807,6 +1819,38 @@ void Compile::inline_string_calls(bool parse_time) { _string_late_inlines.trunc_to(0); } +// Late inlining of boxing methods +void Compile::inline_boxing_calls(PhaseIterGVN& igvn) { + if (_boxing_late_inlines.length() > 0) { + assert(has_boxed_value(), "inconsistent"); + + PhaseGVN* gvn = initial_gvn(); + set_inlining_incrementally(true); + + assert( igvn._worklist.size() == 0, "should be done with igvn" ); + for_igvn()->clear(); + gvn->replace_with(&igvn); + + while (_boxing_late_inlines.length() > 0) { + CallGenerator* cg = _boxing_late_inlines.pop(); + cg->do_late_inline(); + if (failing()) return; + } + _boxing_late_inlines.trunc_to(0); + + { + ResourceMark rm; + PhaseRemoveUseless pru(gvn, for_igvn()); + } + + igvn = PhaseIterGVN(gvn); + igvn.optimize(); + + set_inlining_progress(false); + set_inlining_incrementally(false); + } +} + void Compile::inline_incrementally_one(PhaseIterGVN& igvn) { assert(IncrementalInline, "incremental inlining should be on"); PhaseGVN* gvn = initial_gvn(); @@ -1831,7 +1875,7 @@ void Compile::inline_incrementally_one(PhaseIterGVN& igvn) { { ResourceMark rm; - PhaseRemoveUseless pru(C->initial_gvn(), C->for_igvn()); + PhaseRemoveUseless pru(gvn, for_igvn()); } igvn = PhaseIterGVN(gvn); @@ -1929,12 +1973,25 @@ void Compile::Optimize() { if (failing()) return; - inline_incrementally(igvn); + { + NOT_PRODUCT( TracePhase t2("incrementalInline", &_t_incrInline, TimeCompiler); ) + inline_incrementally(igvn); + } print_method("Incremental Inline", 2); if (failing()) return; + if (eliminate_boxing()) { + NOT_PRODUCT( TracePhase t2("incrementalInline", &_t_incrInline, TimeCompiler); ) + // Inline valueOf() methods now. + inline_boxing_calls(igvn); + + print_method("Incremental Boxing Inline", 2); + + if (failing()) return; + } + // No more new expensive nodes will be added to the list from here // so keep only the actual candidates for optimizations. cleanup_expensive_nodes(igvn); @@ -2896,6 +2953,7 @@ void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) { } break; case Op_MemBarStoreStore: + case Op_MemBarRelease: // Break the link with AllocateNode: it is no longer useful and // confuses register allocation. if (n->req() > MemBarNode::Precedent) { diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index d951fbf5f94..e0f1cd23d16 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -262,6 +262,7 @@ class Compile : public Phase { const bool _save_argument_registers; // save/restore arg regs for trampolines const bool _subsume_loads; // Load can be matched as part of a larger op. const bool _do_escape_analysis; // Do escape analysis. + const bool _eliminate_boxing; // Do boxing elimination. ciMethod* _method; // The method being compiled. int _entry_bci; // entry bci for osr methods. const TypeFunc* _tf; // My kind of signature @@ -287,6 +288,7 @@ class Compile : public Phase { bool _has_split_ifs; // True if the method _may_ have some split-if bool _has_unsafe_access; // True if the method _may_ produce faults in unsafe loads or stores. bool _has_stringbuilder; // True StringBuffers or StringBuilders are allocated + bool _has_boxed_value; // True if a boxed object is allocated int _max_vector_size; // Maximum size of generated vectors uint _trap_hist[trapHistLength]; // Cumulative traps bool _trap_can_recompile; // Have we emitted a recompiling trap? @@ -375,6 +377,8 @@ class Compile : public Phase { // main parsing has finished. GrowableArray _string_late_inlines; // same but for string operations + GrowableArray _boxing_late_inlines; // same but for boxing operations + int _late_inlines_pos; // Where in the queue should the next late inlining candidate go (emulate depth first inlining) uint _number_of_mh_late_inlines; // number of method handle late inlining still pending @@ -486,8 +490,12 @@ class Compile : public Phase { // instructions that subsume a load may result in an unschedulable // instruction sequence. bool subsume_loads() const { return _subsume_loads; } - // Do escape analysis. + /** Do escape analysis. */ bool do_escape_analysis() const { return _do_escape_analysis; } + /** Do boxing elimination. */ + bool eliminate_boxing() const { return _eliminate_boxing; } + /** Do aggressive boxing elimination. */ + bool aggressive_unboxing() const { return _eliminate_boxing && AggressiveUnboxing; } bool save_argument_registers() const { return _save_argument_registers; } @@ -527,6 +535,8 @@ class Compile : public Phase { void set_has_unsafe_access(bool z) { _has_unsafe_access = z; } bool has_stringbuilder() const { return _has_stringbuilder; } void set_has_stringbuilder(bool z) { _has_stringbuilder = z; } + bool has_boxed_value() const { return _has_boxed_value; } + void set_has_boxed_value(bool z) { _has_boxed_value = z; } int max_vector_size() const { return _max_vector_size; } void set_max_vector_size(int s) { _max_vector_size = s; } void set_trap_count(uint r, uint c) { assert(r < trapHistLength, "oob"); _trap_hist[r] = c; } @@ -579,12 +589,12 @@ class Compile : public Phase { #endif } - int macro_count() { return _macro_nodes->length(); } - int predicate_count() { return _predicate_opaqs->length();} - int expensive_count() { return _expensive_nodes->length(); } - Node* macro_node(int idx) { return _macro_nodes->at(idx); } - Node* predicate_opaque1_node(int idx) { return _predicate_opaqs->at(idx);} - Node* expensive_node(int idx) { return _expensive_nodes->at(idx); } + int macro_count() const { return _macro_nodes->length(); } + int predicate_count() const { return _predicate_opaqs->length();} + int expensive_count() const { return _expensive_nodes->length(); } + Node* macro_node(int idx) const { return _macro_nodes->at(idx); } + Node* predicate_opaque1_node(int idx) const { return _predicate_opaqs->at(idx);} + Node* expensive_node(int idx) const { return _expensive_nodes->at(idx); } ConnectionGraph* congraph() { return _congraph;} void set_congraph(ConnectionGraph* congraph) { _congraph = congraph;} void add_macro_node(Node * n) { @@ -766,7 +776,12 @@ class Compile : public Phase { // Decide how to build a call. // The profile factor is a discount to apply to this site's interp. profile. CallGenerator* call_generator(ciMethod* call_method, int vtable_index, bool call_does_dispatch, JVMState* jvms, bool allow_inline, float profile_factor, bool allow_intrinsics = true, bool delayed_forbidden = false); - bool should_delay_inlining(ciMethod* call_method, JVMState* jvms); + bool should_delay_inlining(ciMethod* call_method, JVMState* jvms) { + return should_delay_string_inlining(call_method, jvms) || + should_delay_boxing_inlining(call_method, jvms); + } + bool should_delay_string_inlining(ciMethod* call_method, JVMState* jvms); + bool should_delay_boxing_inlining(ciMethod* call_method, JVMState* jvms); // Helper functions to identify inlining potential at call-site ciMethod* optimize_virtual_call(ciMethod* caller, int bci, ciInstanceKlass* klass, @@ -822,6 +837,10 @@ class Compile : public Phase { _string_late_inlines.push(cg); } + void add_boxing_late_inline(CallGenerator* cg) { + _boxing_late_inlines.push(cg); + } + void remove_useless_late_inlines(GrowableArray* inlines, Unique_Node_List &useful); void dump_inlining(); @@ -841,6 +860,7 @@ class Compile : public Phase { void inline_incrementally_one(PhaseIterGVN& igvn); void inline_incrementally(PhaseIterGVN& igvn); void inline_string_calls(bool parse_time); + void inline_boxing_calls(PhaseIterGVN& igvn); // Matching, CFG layout, allocation, code generation PhaseCFG* cfg() { return _cfg; } @@ -913,7 +933,8 @@ class Compile : public Phase { // replacement, entry_bci indicates the bytecode for which to compile a // continuation. Compile(ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, - int entry_bci, bool subsume_loads, bool do_escape_analysis); + int entry_bci, bool subsume_loads, bool do_escape_analysis, + bool eliminate_boxing); // Second major entry point. From the TypeFunc signature, generate code // to pass arguments from the Java calling convention to the C calling diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index 9a7562d01fb..e55a01ba638 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -176,9 +176,12 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool // Delay the inlining of this method to give us the // opportunity to perform some high level optimizations // first. - if (should_delay_inlining(callee, jvms)) { + if (should_delay_string_inlining(callee, jvms)) { assert(!delayed_forbidden, "strange"); return CallGenerator::for_string_late_inline(callee, cg); + } else if (should_delay_boxing_inlining(callee, jvms)) { + assert(!delayed_forbidden, "strange"); + return CallGenerator::for_boxing_late_inline(callee, cg); } else if ((should_delay || AlwaysIncrementalInline) && !delayed_forbidden) { return CallGenerator::for_late_inline(callee, cg); } @@ -276,7 +279,7 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool // Return true for methods that shouldn't be inlined early so that // they are easier to analyze and optimize as intrinsics. -bool Compile::should_delay_inlining(ciMethod* call_method, JVMState* jvms) { +bool Compile::should_delay_string_inlining(ciMethod* call_method, JVMState* jvms) { if (has_stringbuilder()) { if ((call_method->holder() == C->env()->StringBuilder_klass() || @@ -327,6 +330,13 @@ bool Compile::should_delay_inlining(ciMethod* call_method, JVMState* jvms) { return false; } +bool Compile::should_delay_boxing_inlining(ciMethod* call_method, JVMState* jvms) { + if (eliminate_boxing() && call_method->is_boxing_method()) { + set_has_boxed_value(true); + return true; + } + return false; +} // uncommon-trap call-sites where callee is unloaded, uninitialized or will not link bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* klass) { diff --git a/hotspot/src/share/vm/opto/escape.cpp b/hotspot/src/share/vm/opto/escape.cpp index c5a93dfa68f..f29f82b3539 100644 --- a/hotspot/src/share/vm/opto/escape.cpp +++ b/hotspot/src/share/vm/opto/escape.cpp @@ -63,15 +63,19 @@ 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++ ) { + for (int i = 0; i < cnt; i++) { Node *n = C->macro_node(i); - if ( n->is_Allocate() ) + if (n->is_Allocate()) return true; - if( n->is_Lock() ) { + if (n->is_Lock()) { Node* obj = n->as_Lock()->obj_node()->uncast(); - if( !(obj->is_Parm() || obj->is_Con()) ) + if (!(obj->is_Parm() || obj->is_Con())) return true; } + if (n->is_CallStaticJava() && + n->as_CallStaticJava()->is_boxing_method()) { + return true; + } } return false; } @@ -115,7 +119,7 @@ bool ConnectionGraph::compute_escape() { { Compile::TracePhase t3("connectionGraph", &Phase::_t_connectionGraph, true); // 1. Populate Connection Graph (CG) with PointsTo nodes. - ideal_nodes.map(C->unique(), NULL); // preallocate space + ideal_nodes.map(C->live_nodes(), NULL); // preallocate space // Initialize worklist if (C->root() != NULL) { ideal_nodes.push(C->root()); @@ -152,8 +156,11 @@ bool ConnectionGraph::compute_escape() { // escape status of the associated Allocate node some of them // may be eliminated. storestore_worklist.append(n); + } else if (n->is_MemBar() && (n->Opcode() == Op_MemBarRelease) && + (n->req() > MemBarNode::Precedent)) { + record_for_optimizer(n); #ifdef ASSERT - } else if(n->is_AddP()) { + } else if (n->is_AddP()) { // Collect address nodes for graph verification. addp_worklist.append(n); #endif @@ -206,8 +213,15 @@ bool ConnectionGraph::compute_escape() { 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()) { + bool noescape = (ptn->escape_state() == PointsToNode::NoEscape); + Node* n = ptn->ideal_node(); + if (n->is_Allocate()) { + n->as_Allocate()->_is_non_escaping = noescape; + } + if (n->is_CallStaticJava()) { + n->as_CallStaticJava()->_is_non_escaping = noescape; + } + if (noescape && ptn->scalar_replaceable()) { adjust_scalar_replaceable_state(ptn); if (ptn->scalar_replaceable()) { alloc_worklist.append(ptn->ideal_node()); @@ -330,8 +344,10 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de // 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) { + if ((n->as_Call()->returns_pointer() && + n->as_Call()->proj_out(TypeFunc::Parms) != NULL) || + (n->is_CallStaticJava() && + n->as_CallStaticJava()->is_boxing_method())) { add_call_node(n->as_Call()); } } @@ -387,8 +403,8 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de case Op_ConNKlass: { // 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) { + const Type* t = igvn->type(n); + if (t == TypePtr::NULL_PTR || t == TypeNarrowOop::NULL_PTR) { es = PointsToNode::NoEscape; } else { es = PointsToNode::GlobalEscape; @@ -468,6 +484,9 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de Node* adr = n->in(MemNode::Address); const Type *adr_type = igvn->type(adr); adr_type = adr_type->make_ptr(); + if (adr_type == NULL) { + break; // skip dead nodes + } if (adr_type->isa_oopptr() || (opcode == Op_StoreP || opcode == Op_StoreN || opcode == Op_StoreNKlass) && (adr_type == TypeRawPtr::NOTNULL && @@ -660,14 +679,18 @@ void ConnectionGraph::add_final_edges(Node *n) { case Op_GetAndSetP: case Op_GetAndSetN: { Node* adr = n->in(MemNode::Address); - if (opcode == Op_GetAndSetP || opcode == Op_GetAndSetN) { - const Type* t = _igvn->type(n); - if (t->make_ptr() != NULL) { - add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL); - } - } const Type *adr_type = _igvn->type(adr); adr_type = adr_type->make_ptr(); +#ifdef ASSERT + if (adr_type == NULL) { + n->dump(1); + assert(adr_type != NULL, "dead node should not be on list"); + break; + } +#endif + if (opcode == Op_GetAndSetP || opcode == Op_GetAndSetN) { + add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL); + } if (adr_type->isa_oopptr() || (opcode == Op_StoreP || opcode == Op_StoreN || opcode == Op_StoreNKlass) && (adr_type == TypeRawPtr::NOTNULL && @@ -797,6 +820,18 @@ void ConnectionGraph::add_call_node(CallNode* call) { // Returns a newly allocated unescaped object. add_java_object(call, PointsToNode::NoEscape); ptnode_adr(call_idx)->set_scalar_replaceable(false); + } else if (meth->is_boxing_method()) { + // Returns boxing object + PointsToNode::EscapeState es; + vmIntrinsics::ID intr = meth->intrinsic_id(); + if (intr == vmIntrinsics::_floatValue || intr == vmIntrinsics::_doubleValue) { + // It does not escape if object is always allocated. + es = PointsToNode::NoEscape; + } else { + // It escapes globally if object could be loaded from cache. + es = PointsToNode::GlobalEscape; + } + add_java_object(call, es); } else { BCEscapeAnalyzer* call_analyzer = meth->get_bcea(); call_analyzer->copy_dependencies(_compile->dependencies()); @@ -943,6 +978,9 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { assert((name == NULL || strcmp(name, "uncommon_trap") != 0), "normal calls only"); #endif ciMethod* meth = call->as_CallJava()->method(); + if ((meth != NULL) && meth->is_boxing_method()) { + break; // Boxing methods do not modify any oops. + } BCEscapeAnalyzer* call_analyzer = (meth !=NULL) ? meth->get_bcea() : NULL; // fall-through if not a Java method or no analyzer information if (call_analyzer != NULL) { @@ -1791,9 +1829,8 @@ Node* ConnectionGraph::optimize_ptr_compare(Node* n) { 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"); + const Type* t1 = jobj1->ideal_node()->get_ptr_type(); + const Type* t2 = jobj2->ideal_node()->get_ptr_type(); if (t1->make_ptr() == t2->make_ptr()) { return _pcmp_eq; } else { @@ -2744,6 +2781,11 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) // so it could be eliminated if it has no uses. alloc->as_Allocate()->_is_scalar_replaceable = true; } + if (alloc->is_CallStaticJava()) { + // Set the scalar_replaceable flag for boxing method + // so it could be eliminated if it has no uses. + alloc->as_CallStaticJava()->_is_scalar_replaceable = true; + } continue; } if (!n->is_CheckCastPP()) { // not unique CheckCastPP. @@ -2782,6 +2824,11 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) // so it could be eliminated. alloc->as_Allocate()->_is_scalar_replaceable = true; } + if (alloc->is_CallStaticJava()) { + // Set the scalar_replaceable flag for boxing method + // so it could be eliminated. + alloc->as_CallStaticJava()->_is_scalar_replaceable = true; + } 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) @@ -2911,7 +2958,9 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) // Load/store to instance's field memnode_worklist.append_if_missing(use); } else if (use->is_MemBar()) { - memnode_worklist.append_if_missing(use); + if (use->in(TypeFunc::Memory) == n) { // Ignore precedent edge + memnode_worklist.append_if_missing(use); + } } else if (use->is_AddP() && use->outcnt() > 0) { // No dead nodes Node* addp2 = find_second_addp(use, n); if (addp2 != NULL) { @@ -3028,7 +3077,9 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) continue; memnode_worklist.append_if_missing(use); } else if (use->is_MemBar()) { - memnode_worklist.append_if_missing(use); + if (use->in(TypeFunc::Memory) == n) { // Ignore precedent edge + memnode_worklist.append_if_missing(use); + } #ifdef ASSERT } else if(use->is_Mem()) { assert(use->in(MemNode::Memory) != n, "EA: missing memory path"); @@ -3264,7 +3315,12 @@ void ConnectionGraph::dump(GrowableArray& ptnodes_worklist) { if (ptn == NULL || !ptn->is_JavaObject()) continue; PointsToNode::EscapeState es = ptn->escape_state(); - if (ptn->ideal_node()->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) { + if ((es != PointsToNode::NoEscape) && !Verbose) { + continue; + } + Node* n = ptn->ideal_node(); + if (n->is_Allocate() || (n->is_CallStaticJava() && + n->as_CallStaticJava()->is_boxing_method())) { if (first) { tty->cr(); tty->print("======== Connection graph for "); diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index e2285916ce5..590770b7c72 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -333,6 +333,7 @@ void GraphKit::combine_exception_states(SafePointNode* ex_map, SafePointNode* ph assert(ex_jvms->stkoff() == phi_map->_jvms->stkoff(), "matching locals"); assert(ex_jvms->sp() == phi_map->_jvms->sp(), "matching stack sizes"); assert(ex_jvms->monoff() == phi_map->_jvms->monoff(), "matching JVMS"); + assert(ex_jvms->scloff() == phi_map->_jvms->scloff(), "matching scalar replaced objects"); assert(ex_map->req() == phi_map->req(), "matching maps"); uint tos = ex_jvms->stkoff() + ex_jvms->sp(); Node* hidden_merge_mark = root(); @@ -409,7 +410,7 @@ void GraphKit::combine_exception_states(SafePointNode* ex_map, SafePointNode* ph while (dst->req() > orig_width) dst->del_req(dst->req()-1); } else { assert(dst->is_Phi(), "nobody else uses a hidden region"); - phi = (PhiNode*)dst; + phi = dst->as_Phi(); } if (add_multiple && src->in(0) == ex_control) { // Both are phis. @@ -1438,7 +1439,12 @@ Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, } else { ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt); } - return _gvn.transform(ld); + ld = _gvn.transform(ld); + if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) { + // Improve graph before escape analysis and boxing elimination. + record_for_igvn(ld); + } + return ld; } Node* GraphKit::store_to_memory(Node* ctl, Node* adr, Node *val, BasicType bt, @@ -3144,7 +3150,7 @@ Node* GraphKit::new_instance(Node* klass_node, set_all_memory(mem); // Create new memory state AllocateNode* alloc - = new (C) AllocateNode(C, AllocateNode::alloc_type(), + = new (C) AllocateNode(C, AllocateNode::alloc_type(Type::TOP), control(), mem, i_o(), size, klass_node, initial_slow_test); @@ -3285,7 +3291,7 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable) // Create the AllocateArrayNode and its result projections AllocateArrayNode* alloc - = new (C) AllocateArrayNode(C, AllocateArrayNode::alloc_type(), + = new (C) AllocateArrayNode(C, AllocateArrayNode::alloc_type(TypeInt::INT), control(), mem, i_o(), size, klass_node, initial_slow_test, @@ -3326,10 +3332,9 @@ AllocateNode* AllocateNode::Ideal_allocation(Node* ptr, PhaseTransform* phase) { if (ptr == NULL) { // reduce dumb test in callers return NULL; } - if (ptr->is_CheckCastPP()) { // strip a raw-to-oop cast - ptr = ptr->in(1); - if (ptr == NULL) return NULL; - } + ptr = ptr->uncast(); // strip a raw-to-oop cast + if (ptr == NULL) return NULL; + if (ptr->is_Proj()) { Node* allo = ptr->in(0); if (allo != NULL && allo->is_Allocate()) { @@ -3374,19 +3379,6 @@ InitializeNode* AllocateNode::initialization() { return NULL; } -// Trace Allocate -> Proj[Parm] -> MemBarStoreStore -MemBarStoreStoreNode* AllocateNode::storestore() { - ProjNode* rawoop = proj_out(AllocateNode::RawAddress); - if (rawoop == NULL) return NULL; - for (DUIterator_Fast imax, i = rawoop->fast_outs(imax); i < imax; i++) { - Node* storestore = rawoop->fast_out(i); - if (storestore->is_MemBarStoreStore()) { - return storestore->as_MemBarStoreStore(); - } - } - return NULL; -} - //----------------------------- loop predicates --------------------------- //------------------------------add_predicate_impl---------------------------- diff --git a/hotspot/src/share/vm/opto/ifnode.cpp b/hotspot/src/share/vm/opto/ifnode.cpp index b506a03f587..3995446485b 100644 --- a/hotspot/src/share/vm/opto/ifnode.cpp +++ b/hotspot/src/share/vm/opto/ifnode.cpp @@ -673,7 +673,7 @@ const TypeInt* IfNode::filtered_int_type(PhaseGVN* gvn, Node *val, Node* if_proj // / Region // Node* IfNode::fold_compares(PhaseGVN* phase) { - if (!EliminateAutoBox || Opcode() != Op_If) return NULL; + if (!phase->C->eliminate_boxing() || Opcode() != Op_If) return NULL; Node* this_cmp = in(1)->in(1); if (this_cmp != NULL && this_cmp->Opcode() == Op_CmpI && diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index ddb55d30e62..2b3eca478d9 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -219,9 +219,10 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe // cannot reason about it; is probably not implicit null exception } else { const TypePtr* tptr; - if (UseCompressedOops && Universe::narrow_oop_shift() == 0) { + if (UseCompressedOops && (Universe::narrow_oop_shift() == 0 || + Universe::narrow_klass_shift() == 0)) { // 32-bits narrow oop can be the base of address expressions - tptr = base->bottom_type()->make_ptr(); + tptr = base->get_ptr_type(); } else { // only regular oops are expected here tptr = base->bottom_type()->is_ptr(); diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 1f4b58ebbbb..609b7022608 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -2783,7 +2783,7 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind #ifdef _LP64 if (type == T_OBJECT && adr->bottom_type()->is_ptr_to_narrowoop() && kind == LS_xchg) { - load_store = _gvn.transform(new (C) DecodeNNode(load_store, load_store->bottom_type()->make_ptr())); + load_store = _gvn.transform(new (C) DecodeNNode(load_store, load_store->get_ptr_type())); } #endif @@ -3703,7 +3703,7 @@ LibraryCallKit::generate_method_call(vmIntrinsics::ID method_id, bool is_virtual CallJavaNode* slow_call; if (is_static) { assert(!is_virtual, ""); - slow_call = new(C) CallStaticJavaNode(tf, + slow_call = new(C) CallStaticJavaNode(C, tf, SharedRuntime::get_resolve_static_call_stub(), method, bci()); } else if (is_virtual) { @@ -3722,7 +3722,7 @@ LibraryCallKit::generate_method_call(vmIntrinsics::ID method_id, bool is_virtual method, vtable_index, bci()); } else { // neither virtual nor static: opt_virtual null_check_receiver(); - slow_call = new(C) CallStaticJavaNode(tf, + slow_call = new(C) CallStaticJavaNode(C, tf, SharedRuntime::get_resolve_opt_virtual_call_stub(), method, bci()); slow_call->set_optimized_virtual(true); diff --git a/hotspot/src/share/vm/opto/loopPredicate.cpp b/hotspot/src/share/vm/opto/loopPredicate.cpp index a9867a5ee8a..f29d9daab55 100644 --- a/hotspot/src/share/vm/opto/loopPredicate.cpp +++ b/hotspot/src/share/vm/opto/loopPredicate.cpp @@ -821,8 +821,8 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { loop->dump_head(); } #endif - } else if (cl != NULL && loop->is_range_check_if(iff, this, invar)) { - assert(proj->_con == predicate_proj->_con, "must match"); + } else if ((cl != NULL) && (proj->_con == predicate_proj->_con) && + loop->is_range_check_if(iff, this, invar)) { // Range check for counted loops const Node* cmp = bol->in(1)->as_Cmp(); diff --git a/hotspot/src/share/vm/opto/machnode.cpp b/hotspot/src/share/vm/opto/machnode.cpp index b9b014e050b..0d6ddf9aeed 100644 --- a/hotspot/src/share/vm/opto/machnode.cpp +++ b/hotspot/src/share/vm/opto/machnode.cpp @@ -349,11 +349,11 @@ const class TypePtr *MachNode::adr_type() const { if (base == NodeSentinel) return TypePtr::BOTTOM; const Type* t = base->bottom_type(); - if (UseCompressedOops && Universe::narrow_oop_shift() == 0) { + if (t->isa_narrowoop() && Universe::narrow_oop_shift() == 0) { // 32-bit unscaled narrow oop can be the base of any address expression t = t->make_ptr(); } - if (UseCompressedKlassPointers && Universe::narrow_klass_shift() == 0) { + if (t->isa_narrowklass() && Universe::narrow_klass_shift() == 0) { // 32-bit unscaled narrow oop can be the base of any address expression t = t->make_ptr(); } diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index aeb1b6226be..56b9c939147 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -666,7 +666,7 @@ bool PhaseMacroExpand::can_eliminate_allocation(AllocateNode *alloc, GrowableArr alloc->dump(); else res->dump(); - } else { + } else if (alloc->_is_scalar_replaceable) { tty->print("NotScalar (%s)", fail_eliminate); if (res == NULL) alloc->dump(); @@ -834,7 +834,7 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray is_EncodeP()) { field_val = field_val->in(1); } else { - field_val = transform_later(new (C) DecodeNNode(field_val, field_val->bottom_type()->make_ptr())); + field_val = transform_later(new (C) DecodeNNode(field_val, field_val->get_ptr_type())); } } sfpt->add_req(field_val); @@ -845,18 +845,14 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray debug_start(); int end = jvms->debug_end(); - for (int i = start; i < end; i++) { - if (sfpt->in(i) == res) { - sfpt->set_req(i, sobj); - } - } + sfpt->replace_edges_in_range(res, sobj, start, end); safepoints_done.append_if_missing(sfpt); // keep it for rollback } return true; } // Process users of eliminated allocation. -void PhaseMacroExpand::process_users_of_allocation(AllocateNode *alloc) { +void PhaseMacroExpand::process_users_of_allocation(CallNode *alloc) { Node* res = alloc->result_cast(); if (res != NULL) { for (DUIterator_Last jmin, j = res->last_outs(jmin); j >= jmin; ) { @@ -899,6 +895,17 @@ void PhaseMacroExpand::process_users_of_allocation(AllocateNode *alloc) { // Process other users of allocation's projections // if (_resproj != NULL && _resproj->outcnt() != 0) { + // First disconnect stores captured by Initialize node. + // If Initialize node is eliminated first in the following code, + // it will kill such stores and DUIterator_Last will assert. + for (DUIterator_Fast jmax, j = _resproj->fast_outs(jmax); j < jmax; j++) { + Node *use = _resproj->fast_out(j); + if (use->is_AddP()) { + // raw memory addresses used only by the initialization + _igvn.replace_node(use, C->top()); + --j; --jmax; + } + } for (DUIterator_Last jmin, j = _resproj->last_outs(jmin); j >= jmin; ) { Node *use = _resproj->last_out(j); uint oc1 = _resproj->outcnt(); @@ -923,9 +930,6 @@ void PhaseMacroExpand::process_users_of_allocation(AllocateNode *alloc) { #endif _igvn.replace_node(mem_proj, mem); } - } else if (use->is_AddP()) { - // raw memory addresses used only by the initialization - _igvn.replace_node(use, C->top()); } else { assert(false, "only Initialize or AddP expected"); } @@ -953,8 +957,18 @@ void PhaseMacroExpand::process_users_of_allocation(AllocateNode *alloc) { } bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) { - - if (!EliminateAllocations || !alloc->_is_scalar_replaceable) { + if (!EliminateAllocations || !alloc->_is_non_escaping) { + return false; + } + Node* klass = alloc->in(AllocateNode::KlassNode); + const TypeKlassPtr* tklass = _igvn.type(klass)->is_klassptr(); + Node* res = alloc->result_cast(); + // Eliminate boxing allocations which are not used + // regardless scalar replacable status. + bool boxing_alloc = C->eliminate_boxing() && + tklass->klass()->is_instance_klass() && + tklass->klass()->as_instance_klass()->is_box_klass(); + if (!alloc->_is_scalar_replaceable && (!boxing_alloc || (res != NULL))) { return false; } @@ -965,14 +979,22 @@ bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) { return false; } + if (!alloc->_is_scalar_replaceable) { + assert(res == NULL, "sanity"); + // We can only eliminate allocation if all debug info references + // are already replaced with SafePointScalarObject because + // we can't search for a fields value without instance_id. + if (safepoints.length() > 0) { + return false; + } + } + if (!scalar_replacement(alloc, safepoints)) { return false; } CompileLog* log = C->log(); if (log != NULL) { - Node* klass = alloc->in(AllocateNode::KlassNode); - const TypeKlassPtr* tklass = _igvn.type(klass)->is_klassptr(); log->head("eliminate_allocation type='%d'", log->identify(tklass->klass())); JVMState* p = alloc->jvms(); @@ -997,6 +1019,43 @@ bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) { return true; } +bool PhaseMacroExpand::eliminate_boxing_node(CallStaticJavaNode *boxing) { + // EA should remove all uses of non-escaping boxing node. + if (!C->eliminate_boxing() || boxing->proj_out(TypeFunc::Parms) != NULL) { + return false; + } + + extract_call_projections(boxing); + + const TypeTuple* r = boxing->tf()->range(); + assert(r->cnt() > TypeFunc::Parms, "sanity"); + const TypeInstPtr* t = r->field_at(TypeFunc::Parms)->isa_instptr(); + assert(t != NULL, "sanity"); + + CompileLog* log = C->log(); + if (log != NULL) { + log->head("eliminate_boxing type='%d'", + log->identify(t->klass())); + JVMState* p = boxing->jvms(); + while (p != NULL) { + log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method())); + p = p->caller(); + } + log->tail("eliminate_boxing"); + } + + process_users_of_allocation(boxing); + +#ifndef PRODUCT + if (PrintEliminateAllocations) { + tty->print("++++ Eliminated: %d ", boxing->_idx); + boxing->method()->print_short_name(tty); + tty->cr(); + } +#endif + + return true; +} //---------------------------set_eden_pointers------------------------- void PhaseMacroExpand::set_eden_pointers(Node* &eden_top_adr, Node* &eden_end_adr) { @@ -2384,6 +2443,9 @@ void PhaseMacroExpand::eliminate_macro_nodes() { case Node::Class_AllocateArray: success = eliminate_allocate_node(n->as_Allocate()); break; + case Node::Class_CallStaticJava: + success = eliminate_boxing_node(n->as_CallStaticJava()); + break; case Node::Class_Lock: case Node::Class_Unlock: assert(!n->as_AbstractLock()->is_eliminated(), "sanity"); @@ -2424,6 +2486,11 @@ bool PhaseMacroExpand::expand_macro_nodes() { C->remove_macro_node(n); _igvn._worklist.push(n); success = true; + } else if (n->Opcode() == Op_CallStaticJava) { + // Remove it from macro list and put on IGVN worklist to optimize. + C->remove_macro_node(n); + _igvn._worklist.push(n); + success = true; } else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) { _igvn.replace_node(n, n->in(1)); success = true; diff --git a/hotspot/src/share/vm/opto/macro.hpp b/hotspot/src/share/vm/opto/macro.hpp index ba35c497f2b..7a72316dfc8 100644 --- a/hotspot/src/share/vm/opto/macro.hpp +++ b/hotspot/src/share/vm/opto/macro.hpp @@ -86,10 +86,11 @@ private: Node *value_from_mem(Node *mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc); Node *value_from_mem_phi(Node *mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc, Node_Stack *value_phis, int level); + bool eliminate_boxing_node(CallStaticJavaNode *boxing); bool eliminate_allocate_node(AllocateNode *alloc); bool can_eliminate_allocation(AllocateNode *alloc, GrowableArray & safepoints); bool scalar_replacement(AllocateNode *alloc, GrowableArray & safepoints_done); - void process_users_of_allocation(AllocateNode *alloc); + void process_users_of_allocation(CallNode *alloc); void eliminate_card_mark(Node *cm); void mark_eliminated_box(Node* box, Node* obj); diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index a4dcdb7c9a8..fc59cebdc55 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -103,11 +103,15 @@ extern void print_alias_types(); #endif -Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypePtr *t_adr, PhaseGVN *phase) { - const TypeOopPtr *tinst = t_adr->isa_oopptr(); - if (tinst == NULL || !tinst->is_known_instance_field()) +Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypeOopPtr *t_oop, Node *load, PhaseGVN *phase) { + assert((t_oop != NULL), "sanity"); + bool is_instance = t_oop->is_known_instance_field(); + bool is_boxed_value_load = t_oop->is_ptr_to_boxed_value() && + (load != NULL) && load->is_Load() && + (phase->is_IterGVN() != NULL); + if (!(is_instance || is_boxed_value_load)) return mchain; // don't try to optimize non-instance types - uint instance_id = tinst->instance_id(); + uint instance_id = t_oop->instance_id(); Node *start_mem = phase->C->start()->proj_out(TypeFunc::Memory); Node *prev = NULL; Node *result = mchain; @@ -122,15 +126,24 @@ Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypePtr *t_adr, break; // hit one of our sentinels } else if (proj_in->is_Call()) { CallNode *call = proj_in->as_Call(); - if (!call->may_modify(t_adr, phase)) { + if (!call->may_modify(t_oop, phase)) { // returns false for instances result = call->in(TypeFunc::Memory); } } else if (proj_in->is_Initialize()) { AllocateNode* alloc = proj_in->as_Initialize()->allocation(); // Stop if this is the initialization for the object instance which // which contains this memory slice, otherwise skip over it. - if (alloc != NULL && alloc->_idx != instance_id) { + if ((alloc == NULL) || (alloc->_idx == instance_id)) { + break; + } + if (is_instance) { result = proj_in->in(TypeFunc::Memory); + } else if (is_boxed_value_load) { + Node* klass = alloc->in(AllocateNode::KlassNode); + const TypeKlassPtr* tklass = phase->type(klass)->is_klassptr(); + if (tklass->klass_is_exact() && !tklass->klass()->equals(t_oop->klass())) { + result = proj_in->in(TypeFunc::Memory); // not related allocation + } } } else if (proj_in->is_MemBar()) { result = proj_in->in(TypeFunc::Memory); @@ -138,25 +151,26 @@ Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypePtr *t_adr, assert(false, "unexpected projection"); } } else if (result->is_ClearArray()) { - if (!ClearArrayNode::step_through(&result, instance_id, phase)) { + if (!is_instance || !ClearArrayNode::step_through(&result, instance_id, phase)) { // Can not bypass initialization of the instance // we are looking for. break; } // Otherwise skip it (the call updated 'result' value). } else if (result->is_MergeMem()) { - result = step_through_mergemem(phase, result->as_MergeMem(), t_adr, NULL, tty); + result = step_through_mergemem(phase, result->as_MergeMem(), t_oop, NULL, tty); } } return result; } -Node *MemNode::optimize_memory_chain(Node *mchain, const TypePtr *t_adr, PhaseGVN *phase) { - const TypeOopPtr *t_oop = t_adr->isa_oopptr(); - bool is_instance = (t_oop != NULL) && t_oop->is_known_instance_field(); +Node *MemNode::optimize_memory_chain(Node *mchain, const TypePtr *t_adr, Node *load, PhaseGVN *phase) { + const TypeOopPtr* t_oop = t_adr->isa_oopptr(); + if (t_oop == NULL) + return mchain; // don't try to optimize non-oop types + Node* result = optimize_simple_memory_chain(mchain, t_oop, load, phase); + bool is_instance = t_oop->is_known_instance_field(); PhaseIterGVN *igvn = phase->is_IterGVN(); - Node *result = mchain; - result = optimize_simple_memory_chain(result, t_adr, phase); if (is_instance && igvn != NULL && result->is_Phi()) { PhiNode *mphi = result->as_Phi(); assert(mphi->bottom_type() == Type::MEMORY, "memory phi required"); @@ -383,7 +397,7 @@ bool MemNode::all_controls_dominate(Node* dom, Node* sub) { // Or Region for the check in LoadNode::Ideal(); // 'sub' should have sub->in(0) != NULL. assert(sub->is_Allocate() || sub->is_Initialize() || sub->is_Start() || - sub->is_Region(), "expecting only these nodes"); + sub->is_Region() || sub->is_Call(), "expecting only these nodes"); // Get control edge of 'sub'. Node* orig_sub = sub; @@ -957,11 +971,14 @@ uint LoadNode::hash() const { // of aliasing. Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const { Node* ld_adr = in(MemNode::Address); - + intptr_t ld_off = 0; + AllocateNode* ld_alloc = AllocateNode::Ideal_allocation(ld_adr, phase, ld_off); const TypeInstPtr* tp = phase->type(ld_adr)->isa_instptr(); - Compile::AliasType* atp = tp != NULL ? phase->C->alias_type(tp) : NULL; - if (EliminateAutoBox && atp != NULL && atp->index() >= Compile::AliasIdxRaw && - atp->field() != NULL && !atp->field()->is_volatile()) { + Compile::AliasType* atp = (tp != NULL) ? phase->C->alias_type(tp) : NULL; + // This is more general than load from boxing objects. + if (phase->C->eliminate_boxing() && (atp != NULL) && + (atp->index() >= Compile::AliasIdxRaw) && + (atp->field() != NULL) && !atp->field()->is_volatile()) { uint alias_idx = atp->index(); bool final = atp->field()->is_final(); Node* result = NULL; @@ -983,7 +1000,7 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const { Node* new_st = merge->memory_at(alias_idx); if (new_st == merge->base_memory()) { // Keep searching - current = merge->base_memory(); + current = new_st; continue; } // Save the new memory state for the slice and fall through @@ -1010,9 +1027,7 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const { intptr_t st_off = 0; AllocateNode* alloc = AllocateNode::Ideal_allocation(st_adr, phase, st_off); if (alloc == NULL) return NULL; - intptr_t ld_off = 0; - AllocateNode* allo2 = AllocateNode::Ideal_allocation(ld_adr, phase, ld_off); - if (alloc != allo2) return NULL; + if (alloc != ld_alloc) return NULL; if (ld_off != st_off) return NULL; // At this point we have proven something like this setup: // A = Allocate(...) @@ -1029,14 +1044,12 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const { return st->in(MemNode::ValueIn); } - intptr_t offset = 0; // scratch - // A load from a freshly-created object always returns zero. // (This can happen after LoadNode::Ideal resets the load's memory input // to find_captured_store, which returned InitializeNode::zero_memory.) if (st->is_Proj() && st->in(0)->is_Allocate() && - st->in(0) == AllocateNode::Ideal_allocation(ld_adr, phase, offset) && - offset >= st->in(0)->as_Allocate()->minimum_header_size()) { + (st->in(0) == ld_alloc) && + (ld_off >= st->in(0)->as_Allocate()->minimum_header_size())) { // return a zero value for the load's basic type // (This is one of the few places where a generic PhaseTransform // can create new nodes. Think of it as lazily manifesting @@ -1048,15 +1061,27 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const { if (st->is_Proj() && st->in(0)->is_Initialize()) { InitializeNode* init = st->in(0)->as_Initialize(); AllocateNode* alloc = init->allocation(); - if (alloc != NULL && - alloc == AllocateNode::Ideal_allocation(ld_adr, phase, offset)) { + if ((alloc != NULL) && (alloc == ld_alloc)) { // examine a captured store value - st = init->find_captured_store(offset, memory_size(), phase); + st = init->find_captured_store(ld_off, memory_size(), phase); if (st != NULL) continue; // take one more trip around } } + // Load boxed value from result of valueOf() call is input parameter. + if (this->is_Load() && ld_adr->is_AddP() && + (tp != NULL) && tp->is_ptr_to_boxed_value()) { + intptr_t ignore = 0; + Node* base = AddPNode::Ideal_base_and_offset(ld_adr, phase, ignore); + if (base != NULL && base->is_Proj() && + base->as_Proj()->_con == TypeFunc::Parms && + base->in(0)->is_CallStaticJava() && + base->in(0)->as_CallStaticJava()->is_boxing_method()) { + return base->in(0)->in(TypeFunc::Parms); + } + } + break; } @@ -1065,11 +1090,13 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const { //----------------------is_instance_field_load_with_local_phi------------------ bool LoadNode::is_instance_field_load_with_local_phi(Node* ctrl) { - if( in(MemNode::Memory)->is_Phi() && in(MemNode::Memory)->in(0) == ctrl && - in(MemNode::Address)->is_AddP() ) { - const TypeOopPtr* t_oop = in(MemNode::Address)->bottom_type()->isa_oopptr(); - // Only instances. - if( t_oop != NULL && t_oop->is_known_instance_field() && + if( in(Memory)->is_Phi() && in(Memory)->in(0) == ctrl && + in(Address)->is_AddP() ) { + const TypeOopPtr* t_oop = in(Address)->bottom_type()->isa_oopptr(); + // Only instances and boxed values. + if( t_oop != NULL && + (t_oop->is_ptr_to_boxed_value() || + t_oop->is_known_instance_field()) && t_oop->offset() != Type::OffsetBot && t_oop->offset() != Type::OffsetTop) { return true; @@ -1083,7 +1110,7 @@ bool LoadNode::is_instance_field_load_with_local_phi(Node* ctrl) { Node *LoadNode::Identity( PhaseTransform *phase ) { // If the previous store-maker is the right kind of Store, and the store is // to the same address, then we are equal to the value stored. - Node* mem = in(MemNode::Memory); + Node* mem = in(Memory); Node* value = can_see_stored_value(mem, phase); if( value ) { // byte, short & char stores truncate naturally. @@ -1105,15 +1132,22 @@ Node *LoadNode::Identity( PhaseTransform *phase ) { // instance's field to avoid infinite generation of phis in a loop. Node *region = mem->in(0); if (is_instance_field_load_with_local_phi(region)) { - const TypePtr *addr_t = in(MemNode::Address)->bottom_type()->isa_ptr(); + const TypeOopPtr *addr_t = in(Address)->bottom_type()->isa_oopptr(); int this_index = phase->C->get_alias_index(addr_t); int this_offset = addr_t->offset(); - int this_id = addr_t->is_oopptr()->instance_id(); + int this_iid = addr_t->instance_id(); + if (!addr_t->is_known_instance() && + addr_t->is_ptr_to_boxed_value()) { + // Use _idx of address base (could be Phi node) for boxed values. + intptr_t ignore = 0; + Node* base = AddPNode::Ideal_base_and_offset(in(Address), phase, ignore); + this_iid = base->_idx; + } const Type* this_type = bottom_type(); for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { Node* phi = region->fast_out(i); if (phi->is_Phi() && phi != mem && - phi->as_Phi()->is_same_inst_field(this_type, this_id, this_index, this_offset)) { + phi->as_Phi()->is_same_inst_field(this_type, this_iid, this_index, this_offset)) { return phi; } } @@ -1122,170 +1156,106 @@ Node *LoadNode::Identity( PhaseTransform *phase ) { return this; } - -// Returns true if the AliasType refers to the field that holds the -// cached box array. Currently only handles the IntegerCache case. -static bool is_autobox_cache(Compile::AliasType* atp) { - if (atp != NULL && atp->field() != NULL) { - ciField* field = atp->field(); - ciSymbol* klass = field->holder()->name(); - if (field->name() == ciSymbol::cache_field_name() && - field->holder()->uses_default_loader() && - klass == ciSymbol::java_lang_Integer_IntegerCache()) { - return true; - } - } - return false; -} - -// Fetch the base value in the autobox array -static bool fetch_autobox_base(Compile::AliasType* atp, int& cache_offset) { - if (atp != NULL && atp->field() != NULL) { - ciField* field = atp->field(); - ciSymbol* klass = field->holder()->name(); - if (field->name() == ciSymbol::cache_field_name() && - field->holder()->uses_default_loader() && - klass == ciSymbol::java_lang_Integer_IntegerCache()) { - assert(field->is_constant(), "what?"); - ciObjArray* array = field->constant_value().as_object()->as_obj_array(); - // Fetch the box object at the base of the array and get its value - ciInstance* box = array->obj_at(0)->as_instance(); - ciInstanceKlass* ik = box->klass()->as_instance_klass(); - if (ik->nof_nonstatic_fields() == 1) { - // This should be true nonstatic_field_at requires calling - // nof_nonstatic_fields so check it anyway - ciConstant c = box->field_value(ik->nonstatic_field_at(0)); - cache_offset = c.as_int(); - } - return true; - } - } - return false; -} - -// Returns true if the AliasType refers to the value field of an -// autobox object. Currently only handles Integer. -static bool is_autobox_object(Compile::AliasType* atp) { - if (atp != NULL && atp->field() != NULL) { - ciField* field = atp->field(); - ciSymbol* klass = field->holder()->name(); - if (field->name() == ciSymbol::value_name() && - field->holder()->uses_default_loader() && - klass == ciSymbol::java_lang_Integer()) { - return true; - } - } - return false; -} - - // We're loading from an object which has autobox behaviour. // If this object is result of a valueOf call we'll have a phi // merging a newly allocated object and a load from the cache. // We want to replace this load with the original incoming // argument to the valueOf call. Node* LoadNode::eliminate_autobox(PhaseGVN* phase) { - Node* base = in(Address)->in(AddPNode::Base); - if (base->is_Phi() && base->req() == 3) { - AllocateNode* allocation = NULL; - int allocation_index = -1; - int load_index = -1; - for (uint i = 1; i < base->req(); i++) { - allocation = AllocateNode::Ideal_allocation(base->in(i), phase); - if (allocation != NULL) { - allocation_index = i; - load_index = 3 - allocation_index; - break; - } - } - bool has_load = ( allocation != NULL && - (base->in(load_index)->is_Load() || - base->in(load_index)->is_DecodeN() && - base->in(load_index)->in(1)->is_Load()) ); - if (has_load && in(Memory)->is_Phi() && in(Memory)->in(0) == base->in(0)) { - // Push the loads from the phi that comes from valueOf up - // through it to allow elimination of the loads and the recovery - // of the original value. - Node* mem_phi = in(Memory); - Node* offset = in(Address)->in(AddPNode::Offset); - Node* region = base->in(0); - - Node* in1 = clone(); - Node* in1_addr = in1->in(Address)->clone(); - in1_addr->set_req(AddPNode::Base, base->in(allocation_index)); - in1_addr->set_req(AddPNode::Address, base->in(allocation_index)); - in1_addr->set_req(AddPNode::Offset, offset); - in1->set_req(0, region->in(allocation_index)); - in1->set_req(Address, in1_addr); - in1->set_req(Memory, mem_phi->in(allocation_index)); - - Node* in2 = clone(); - Node* in2_addr = in2->in(Address)->clone(); - in2_addr->set_req(AddPNode::Base, base->in(load_index)); - in2_addr->set_req(AddPNode::Address, base->in(load_index)); - in2_addr->set_req(AddPNode::Offset, offset); - in2->set_req(0, region->in(load_index)); - in2->set_req(Address, in2_addr); - in2->set_req(Memory, mem_phi->in(load_index)); - - in1_addr = phase->transform(in1_addr); - in1 = phase->transform(in1); - in2_addr = phase->transform(in2_addr); - in2 = phase->transform(in2); - - PhiNode* result = PhiNode::make_blank(region, this); - result->set_req(allocation_index, in1); - result->set_req(load_index, in2); - return result; - } + assert(phase->C->eliminate_boxing(), "sanity"); + intptr_t ignore = 0; + Node* base = AddPNode::Ideal_base_and_offset(in(Address), phase, ignore); + if ((base == NULL) || base->is_Phi()) { + // Push the loads from the phi that comes from valueOf up + // through it to allow elimination of the loads and the recovery + // of the original value. It is done in split_through_phi(). + return NULL; } else if (base->is_Load() || base->is_DecodeN() && base->in(1)->is_Load()) { - if (base->is_DecodeN()) { - // Get LoadN node which loads cached Integer object - base = base->in(1); - } - // Eliminate the load of Integer.value for integers from the cache + // Eliminate the load of boxed value for integer types from the cache // array by deriving the value from the index into the array. // Capture the offset of the load and then reverse the computation. - Node* load_base = base->in(Address)->in(AddPNode::Base); - if (load_base->is_DecodeN()) { - // Get LoadN node which loads IntegerCache.cache field - load_base = load_base->in(1); + + // Get LoadN node which loads a boxing object from 'cache' array. + if (base->is_DecodeN()) { + base = base->in(1); } - if (load_base != NULL) { - Compile::AliasType* atp = phase->C->alias_type(load_base->adr_type()); - intptr_t cache_offset; - int shift = -1; - Node* cache = NULL; - if (is_autobox_cache(atp)) { - shift = exact_log2(type2aelembytes(T_OBJECT)); - cache = AddPNode::Ideal_base_and_offset(load_base->in(Address), phase, cache_offset); - } - if (cache != NULL && base->in(Address)->is_AddP()) { + if (!base->in(Address)->is_AddP()) { + return NULL; // Complex address + } + AddPNode* address = base->in(Address)->as_AddP(); + Node* cache_base = address->in(AddPNode::Base); + if ((cache_base != NULL) && cache_base->is_DecodeN()) { + // Get ConP node which is static 'cache' field. + cache_base = cache_base->in(1); + } + if ((cache_base != NULL) && cache_base->is_Con()) { + const TypeAryPtr* base_type = cache_base->bottom_type()->isa_aryptr(); + if ((base_type != NULL) && base_type->is_autobox_cache()) { Node* elements[4]; - int count = base->in(Address)->as_AddP()->unpack_offsets(elements, ARRAY_SIZE(elements)); - int cache_low; - if (count > 0 && fetch_autobox_base(atp, cache_low)) { - int offset = arrayOopDesc::base_offset_in_bytes(memory_type()) - (cache_low << shift); - // Add up all the offsets making of the address of the load - Node* result = elements[0]; - for (int i = 1; i < count; i++) { - result = phase->transform(new (phase->C) AddXNode(result, elements[i])); - } - // Remove the constant offset from the address and then - // remove the scaling of the offset to recover the original index. - result = phase->transform(new (phase->C) AddXNode(result, phase->MakeConX(-offset))); - if (result->Opcode() == Op_LShiftX && result->in(2) == phase->intcon(shift)) { - // Peel the shift off directly but wrap it in a dummy node - // since Ideal can't return existing nodes - result = new (phase->C) RShiftXNode(result->in(1), phase->intcon(0)); - } else { - result = new (phase->C) RShiftXNode(result, phase->intcon(shift)); - } + int shift = exact_log2(type2aelembytes(T_OBJECT)); + int count = address->unpack_offsets(elements, ARRAY_SIZE(elements)); + if ((count > 0) && elements[0]->is_Con() && + ((count == 1) || + (count == 2) && elements[1]->Opcode() == Op_LShiftX && + elements[1]->in(2) == phase->intcon(shift))) { + ciObjArray* array = base_type->const_oop()->as_obj_array(); + // Fetch the box object cache[0] at the base of the array and get its value + ciInstance* box = array->obj_at(0)->as_instance(); + ciInstanceKlass* ik = box->klass()->as_instance_klass(); + assert(ik->is_box_klass(), "sanity"); + assert(ik->nof_nonstatic_fields() == 1, "change following code"); + if (ik->nof_nonstatic_fields() == 1) { + // This should be true nonstatic_field_at requires calling + // nof_nonstatic_fields so check it anyway + ciConstant c = box->field_value(ik->nonstatic_field_at(0)); + BasicType bt = c.basic_type(); + // Only integer types have boxing cache. + assert(bt == T_BOOLEAN || bt == T_CHAR || + bt == T_BYTE || bt == T_SHORT || + bt == T_INT || bt == T_LONG, err_msg_res("wrong type = %s", type2name(bt))); + jlong cache_low = (bt == T_LONG) ? c.as_long() : c.as_int(); + if (cache_low != (int)cache_low) { + return NULL; // should not happen since cache is array indexed by value + } + jlong offset = arrayOopDesc::base_offset_in_bytes(T_OBJECT) - (cache_low << shift); + if (offset != (int)offset) { + return NULL; // should not happen since cache is array indexed by value + } + // Add up all the offsets making of the address of the load + Node* result = elements[0]; + for (int i = 1; i < count; i++) { + result = phase->transform(new (phase->C) AddXNode(result, elements[i])); + } + // Remove the constant offset from the address and then + result = phase->transform(new (phase->C) AddXNode(result, phase->MakeConX(-(int)offset))); + // remove the scaling of the offset to recover the original index. + if (result->Opcode() == Op_LShiftX && result->in(2) == phase->intcon(shift)) { + // Peel the shift off directly but wrap it in a dummy node + // since Ideal can't return existing nodes + result = new (phase->C) RShiftXNode(result->in(1), phase->intcon(0)); + } else if (result->is_Add() && result->in(2)->is_Con() && + result->in(1)->Opcode() == Op_LShiftX && + result->in(1)->in(2) == phase->intcon(shift)) { + // We can't do general optimization: ((X<> Z ==> X + (Y>>Z) + // but for boxing cache access we know that X<C) RShiftXNode(result->in(2), phase->intcon(shift)); + result = new (phase->C) AddXNode(result->in(1)->in(1), phase->transform(add_con)); + } else { + result = new (phase->C) RShiftXNode(result, phase->intcon(shift)); + } #ifdef _LP64 - result = new (phase->C) ConvL2INode(phase->transform(result)); + if (bt != T_LONG) { + result = new (phase->C) ConvL2INode(phase->transform(result)); + } +#else + if (bt == T_LONG) { + result = new (phase->C) ConvI2LNode(phase->transform(result)); + } #endif - return result; + return result; + } } } } @@ -1293,65 +1263,131 @@ Node* LoadNode::eliminate_autobox(PhaseGVN* phase) { return NULL; } -//------------------------------split_through_phi------------------------------ -// Split instance field load through Phi. -Node *LoadNode::split_through_phi(PhaseGVN *phase) { - Node* mem = in(MemNode::Memory); - Node* address = in(MemNode::Address); - const TypePtr *addr_t = phase->type(address)->isa_ptr(); - const TypeOopPtr *t_oop = addr_t->isa_oopptr(); - - assert(mem->is_Phi() && (t_oop != NULL) && - t_oop->is_known_instance_field(), "invalide conditions"); - - Node *region = mem->in(0); +static bool stable_phi(PhiNode* phi, PhaseGVN *phase) { + Node* region = phi->in(0); if (region == NULL) { - return NULL; // Wait stable graph + return false; // Wait stable graph } - uint cnt = mem->req(); + uint cnt = phi->req(); for (uint i = 1; i < cnt; i++) { Node* rc = region->in(i); if (rc == NULL || phase->type(rc) == Type::TOP) - return NULL; // Wait stable graph - Node *in = mem->in(i); - if (in == NULL) { + return false; // Wait stable graph + Node* in = phi->in(i); + if (in == NULL || phase->type(in) == Type::TOP) + return false; // Wait stable graph + } + return true; +} +//------------------------------split_through_phi------------------------------ +// Split instance or boxed field load through Phi. +Node *LoadNode::split_through_phi(PhaseGVN *phase) { + Node* mem = in(Memory); + Node* address = in(Address); + const TypeOopPtr *t_oop = phase->type(address)->isa_oopptr(); + + assert((t_oop != NULL) && + (t_oop->is_known_instance_field() || + t_oop->is_ptr_to_boxed_value()), "invalide conditions"); + + Compile* C = phase->C; + intptr_t ignore = 0; + Node* base = AddPNode::Ideal_base_and_offset(address, phase, ignore); + bool base_is_phi = (base != NULL) && base->is_Phi(); + bool load_boxed_values = t_oop->is_ptr_to_boxed_value() && C->aggressive_unboxing() && + (base != NULL) && (base == address->in(AddPNode::Base)) && + phase->type(base)->higher_equal(TypePtr::NOTNULL); + + if (!((mem->is_Phi() || base_is_phi) && + (load_boxed_values || t_oop->is_known_instance_field()))) { + return NULL; // memory is not Phi + } + + if (mem->is_Phi()) { + if (!stable_phi(mem->as_Phi(), phase)) { return NULL; // Wait stable graph } - } - // Check for loop invariant. - if (cnt == 3) { - for (uint i = 1; i < cnt; i++) { - Node *in = mem->in(i); - Node* m = MemNode::optimize_memory_chain(in, addr_t, phase); - if (m == mem) { - set_req(MemNode::Memory, mem->in(cnt - i)); // Skip this phi. - return this; + uint cnt = mem->req(); + // Check for loop invariant memory. + if (cnt == 3) { + for (uint i = 1; i < cnt; i++) { + Node* in = mem->in(i); + Node* m = optimize_memory_chain(in, t_oop, this, phase); + if (m == mem) { + set_req(Memory, mem->in(cnt - i)); + return this; // made change + } } } } + if (base_is_phi) { + if (!stable_phi(base->as_Phi(), phase)) { + return NULL; // Wait stable graph + } + uint cnt = base->req(); + // Check for loop invariant memory. + if (cnt == 3) { + for (uint i = 1; i < cnt; i++) { + if (base->in(i) == base) { + return NULL; // Wait stable graph + } + } + } + } + + bool load_boxed_phi = load_boxed_values && base_is_phi && (base->in(0) == mem->in(0)); + // Split through Phi (see original code in loopopts.cpp). - assert(phase->C->have_alias_type(addr_t), "instance should have alias type"); + assert(C->have_alias_type(t_oop), "instance should have alias type"); // Do nothing here if Identity will find a value // (to avoid infinite chain of value phis generation). if (!phase->eqv(this, this->Identity(phase))) return NULL; - // Skip the split if the region dominates some control edge of the address. - if (!MemNode::all_controls_dominate(address, region)) - return NULL; + // Select Region to split through. + Node* region; + if (!base_is_phi) { + assert(mem->is_Phi(), "sanity"); + region = mem->in(0); + // Skip if the region dominates some control edge of the address. + if (!MemNode::all_controls_dominate(address, region)) + return NULL; + } else if (!mem->is_Phi()) { + assert(base_is_phi, "sanity"); + region = base->in(0); + // Skip if the region dominates some control edge of the memory. + if (!MemNode::all_controls_dominate(mem, region)) + return NULL; + } else if (base->in(0) != mem->in(0)) { + assert(base_is_phi && mem->is_Phi(), "sanity"); + if (MemNode::all_controls_dominate(mem, base->in(0))) { + region = base->in(0); + } else if (MemNode::all_controls_dominate(address, mem->in(0))) { + region = mem->in(0); + } else { + return NULL; // complex graph + } + } else { + assert(base->in(0) == mem->in(0), "sanity"); + region = mem->in(0); + } const Type* this_type = this->bottom_type(); - int this_index = phase->C->get_alias_index(addr_t); - int this_offset = addr_t->offset(); - int this_iid = addr_t->is_oopptr()->instance_id(); - PhaseIterGVN *igvn = phase->is_IterGVN(); - Node *phi = new (igvn->C) PhiNode(region, this_type, NULL, this_iid, this_index, this_offset); + int this_index = C->get_alias_index(t_oop); + int this_offset = t_oop->offset(); + int this_iid = t_oop->instance_id(); + if (!t_oop->is_known_instance() && load_boxed_values) { + // Use _idx of address base for boxed values. + this_iid = base->_idx; + } + PhaseIterGVN* igvn = phase->is_IterGVN(); + Node* phi = new (C) PhiNode(region, this_type, NULL, this_iid, this_index, this_offset); for (uint i = 1; i < region->req(); i++) { - Node *x; + Node* x; Node* the_clone = NULL; - if (region->in(i) == phase->C->top()) { - x = phase->C->top(); // Dead path? Use a dead data op + if (region->in(i) == C->top()) { + x = C->top(); // Dead path? Use a dead data op } else { x = this->clone(); // Else clone up the data op the_clone = x; // Remember for possible deletion. @@ -1361,10 +1397,16 @@ Node *LoadNode::split_through_phi(PhaseGVN *phase) { } else { x->set_req(0, NULL); } - for (uint j = 1; j < this->req(); j++) { - Node *in = this->in(j); - if (in->is_Phi() && in->in(0) == region) - x->set_req(j, in->in(i)); // Use pre-Phi input for the clone + if (mem->is_Phi() && (mem->in(0) == region)) { + x->set_req(Memory, mem->in(i)); // Use pre-Phi input for the clone. + } + if (address->is_Phi() && address->in(0) == region) { + x->set_req(Address, address->in(i)); // Use pre-Phi input for the clone + } + if (base_is_phi && (base->in(0) == region)) { + Node* base_x = base->in(i); // Clone address for loads from boxed objects. + Node* adr_x = phase->transform(new (C) AddPNode(base_x,base_x,address->in(AddPNode::Offset))); + x->set_req(Address, adr_x); } } // Check for a 'win' on some paths @@ -1394,7 +1436,7 @@ Node *LoadNode::split_through_phi(PhaseGVN *phase) { if (y != x) { x = y; } else { - y = igvn->hash_find(x); + y = igvn->hash_find_insert(x); if (y) { x = y; } else { @@ -1405,8 +1447,9 @@ Node *LoadNode::split_through_phi(PhaseGVN *phase) { } } } - if (x != the_clone && the_clone != NULL) + if (x != the_clone && the_clone != NULL) { igvn->remove_dead_node(the_clone); + } phi->set_req(i, x); } // Record Phi @@ -1445,31 +1488,23 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) { // A method-invariant, non-null address (constant or 'this' argument). set_req(MemNode::Control, NULL); } - - if (EliminateAutoBox && can_reshape) { - assert(!phase->type(base)->higher_equal(TypePtr::NULL_PTR), "the autobox pointer should be non-null"); - Compile::AliasType* atp = phase->C->alias_type(adr_type()); - if (is_autobox_object(atp)) { - Node* result = eliminate_autobox(phase); - if (result != NULL) return result; - } - } } Node* mem = in(MemNode::Memory); const TypePtr *addr_t = phase->type(address)->isa_ptr(); - if (addr_t != NULL) { + if (can_reshape && (addr_t != NULL)) { // try to optimize our memory input - Node* opt_mem = MemNode::optimize_memory_chain(mem, addr_t, phase); + Node* opt_mem = MemNode::optimize_memory_chain(mem, addr_t, this, phase); if (opt_mem != mem) { set_req(MemNode::Memory, opt_mem); if (phase->type( opt_mem ) == Type::TOP) return NULL; return this; } const TypeOopPtr *t_oop = addr_t->isa_oopptr(); - if (can_reshape && opt_mem->is_Phi() && - (t_oop != NULL) && t_oop->is_known_instance_field()) { + if ((t_oop != NULL) && + (t_oop->is_known_instance_field() || + t_oop->is_ptr_to_boxed_value())) { PhaseIterGVN *igvn = phase->is_IterGVN(); if (igvn != NULL && igvn->_worklist.member(opt_mem)) { // Delay this transformation until memory Phi is processed. @@ -1479,6 +1514,11 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Split instance field load through Phi. Node* result = split_through_phi(phase); if (result != NULL) return result; + + if (t_oop->is_ptr_to_boxed_value()) { + Node* result = eliminate_autobox(phase); + if (result != NULL) return result; + } } } @@ -1587,18 +1627,23 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const { // This can happen if a interface-typed array narrows to a class type. jt = _type; } - - if (EliminateAutoBox && adr->is_AddP()) { +#ifdef ASSERT + if (phase->C->eliminate_boxing() && adr->is_AddP()) { // The pointers in the autobox arrays are always non-null Node* base = adr->in(AddPNode::Base); - if (base != NULL && - !phase->type(base)->higher_equal(TypePtr::NULL_PTR)) { - Compile::AliasType* atp = C->alias_type(base->adr_type()); - if (is_autobox_cache(atp)) { - return jt->join(TypePtr::NOTNULL)->is_ptr(); + if ((base != NULL) && base->is_DecodeN()) { + // Get LoadN node which loads IntegerCache.cache field + base = base->in(1); + } + if ((base != NULL) && base->is_Con()) { + const TypeAryPtr* base_type = base->bottom_type()->isa_aryptr(); + if ((base_type != NULL) && base_type->is_autobox_cache()) { + // It could be narrow oop + assert(jt->make_ptr()->ptr() == TypePtr::NotNull,"sanity"); } } } +#endif return jt; } } @@ -1638,6 +1683,10 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const { // Optimizations for constant objects ciObject* const_oop = tinst->const_oop(); if (const_oop != NULL) { + // For constant Boxed value treat the target field as a compile time constant. + if (tinst->is_ptr_to_boxed_value()) { + return tinst->get_const_boxed_value(); + } else // For constant CallSites treat the target field as a compile time constant. if (const_oop->is_call_site()) { ciCallSite* call_site = const_oop->as_call_site(); @@ -1759,7 +1808,8 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const { // (Also allow a variable load from a fresh array to produce zero.) const TypeOopPtr *tinst = tp->isa_oopptr(); bool is_instance = (tinst != NULL) && tinst->is_known_instance_field(); - if (ReduceFieldZeroing || is_instance) { + bool is_boxed_value = (tinst != NULL) && tinst->is_ptr_to_boxed_value(); + if (ReduceFieldZeroing || is_instance || is_boxed_value) { Node* value = can_see_stored_value(mem,phase); if (value != NULL && value->is_Con()) { assert(value->bottom_type()->higher_equal(_type),"sanity"); @@ -2883,24 +2933,38 @@ Node *MemBarNode::Ideal(PhaseGVN *phase, bool can_reshape) { if (in(0) && in(0)->is_top()) return NULL; // Eliminate volatile MemBars for scalar replaced objects. - if (can_reshape && req() == (Precedent+1) && - (Opcode() == Op_MemBarAcquire || Opcode() == Op_MemBarVolatile)) { - // Volatile field loads and stores. - Node* my_mem = in(MemBarNode::Precedent); - if (my_mem != NULL && my_mem->is_Mem()) { - const TypeOopPtr* t_oop = my_mem->in(MemNode::Address)->bottom_type()->isa_oopptr(); - // Check for scalar replaced object reference. - if( t_oop != NULL && t_oop->is_known_instance_field() && - t_oop->offset() != Type::OffsetBot && - t_oop->offset() != Type::OffsetTop) { - // Replace MemBar projections by its inputs. - PhaseIterGVN* igvn = phase->is_IterGVN(); - igvn->replace_node(proj_out(TypeFunc::Memory), in(TypeFunc::Memory)); - igvn->replace_node(proj_out(TypeFunc::Control), in(TypeFunc::Control)); - // Must return either the original node (now dead) or a new node - // (Do not return a top here, since that would break the uniqueness of top.) - return new (phase->C) ConINode(TypeInt::ZERO); + if (can_reshape && req() == (Precedent+1)) { + bool eliminate = false; + int opc = Opcode(); + if ((opc == Op_MemBarAcquire || opc == Op_MemBarVolatile)) { + // Volatile field loads and stores. + Node* my_mem = in(MemBarNode::Precedent); + if (my_mem != NULL && my_mem->is_Mem()) { + const TypeOopPtr* t_oop = my_mem->in(MemNode::Address)->bottom_type()->isa_oopptr(); + // Check for scalar replaced object reference. + if( t_oop != NULL && t_oop->is_known_instance_field() && + t_oop->offset() != Type::OffsetBot && + t_oop->offset() != Type::OffsetTop) { + eliminate = true; + } } + } else if (opc == Op_MemBarRelease) { + // Final field stores. + Node* alloc = AllocateNode::Ideal_allocation(in(MemBarNode::Precedent), phase); + if ((alloc != NULL) && alloc->is_Allocate() && + alloc->as_Allocate()->_is_non_escaping) { + // The allocated object does not escape. + eliminate = true; + } + } + if (eliminate) { + // Replace MemBar projections by its inputs. + PhaseIterGVN* igvn = phase->is_IterGVN(); + igvn->replace_node(proj_out(TypeFunc::Memory), in(TypeFunc::Memory)); + igvn->replace_node(proj_out(TypeFunc::Control), in(TypeFunc::Control)); + // Must return either the original node (now dead) or a new node + // (Do not return a top here, since that would break the uniqueness of top.) + return new (phase->C) ConINode(TypeInt::ZERO); } } return NULL; @@ -3113,9 +3177,7 @@ intptr_t InitializeNode::get_store_offset(Node* st, PhaseTransform* phase) { // within the initialization without creating a vicious cycle, such as: // { Foo p = new Foo(); p.next = p; } // True for constants and parameters and small combinations thereof. -bool InitializeNode::detect_init_independence(Node* n, - bool st_is_pinned, - int& count) { +bool InitializeNode::detect_init_independence(Node* n, int& count) { if (n == NULL) return true; // (can this really happen?) if (n->is_Proj()) n = n->in(0); if (n == this) return false; // found a cycle @@ -3135,7 +3197,6 @@ bool InitializeNode::detect_init_independence(Node* n, // a store is never pinned *before* the availability of its inputs. if (!MemNode::all_controls_dominate(n, this)) return false; // failed to prove a good control - } // Check data edges for possible dependencies on 'this'. @@ -3145,7 +3206,7 @@ bool InitializeNode::detect_init_independence(Node* n, if (m == NULL || m == n || m->is_top()) continue; uint first_i = n->find_edge(m); if (i != first_i) continue; // process duplicate edge just once - if (!detect_init_independence(m, st_is_pinned, count)) { + if (!detect_init_independence(m, count)) { return false; } } @@ -3176,7 +3237,7 @@ intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase, return FAIL; // wrong allocation! (store needs to float up) Node* val = st->in(MemNode::ValueIn); int complexity_count = 0; - if (!detect_init_independence(val, true, complexity_count)) + if (!detect_init_independence(val, complexity_count)) return FAIL; // stored value must be 'simple enough' // The Store can be captured only if nothing after the allocation diff --git a/hotspot/src/share/vm/opto/memnode.hpp b/hotspot/src/share/vm/opto/memnode.hpp index 73b3e34c705..9a009908453 100644 --- a/hotspot/src/share/vm/opto/memnode.hpp +++ b/hotspot/src/share/vm/opto/memnode.hpp @@ -75,8 +75,8 @@ public: PhaseTransform* phase); static bool adr_phi_is_loop_invariant(Node* adr_phi, Node* cast); - static Node *optimize_simple_memory_chain(Node *mchain, const TypePtr *t_adr, PhaseGVN *phase); - static Node *optimize_memory_chain(Node *mchain, const TypePtr *t_adr, PhaseGVN *phase); + static Node *optimize_simple_memory_chain(Node *mchain, const TypeOopPtr *t_oop, Node *load, PhaseGVN *phase); + static Node *optimize_memory_chain(Node *mchain, const TypePtr *t_adr, Node *load, PhaseGVN *phase); // This one should probably be a phase-specific function: static bool all_controls_dominate(Node* dom, Node* sub); @@ -1099,7 +1099,7 @@ public: Node* make_raw_address(intptr_t offset, PhaseTransform* phase); - bool detect_init_independence(Node* n, bool st_is_pinned, int& count); + bool detect_init_independence(Node* n, int& count); void coalesce_subword_stores(intptr_t header_size, Node* size_in_bytes, PhaseGVN* phase); diff --git a/hotspot/src/share/vm/opto/multnode.cpp b/hotspot/src/share/vm/opto/multnode.cpp index 28041410682..dca8dbe703c 100644 --- a/hotspot/src/share/vm/opto/multnode.cpp +++ b/hotspot/src/share/vm/opto/multnode.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "opto/callnode.hpp" #include "opto/matcher.hpp" #include "opto/multnode.hpp" #include "opto/opcodes.hpp" @@ -73,13 +74,26 @@ bool ProjNode::is_CFG() const { return (_con == TypeFunc::Control && def->is_CFG()); } +const Type* ProjNode::proj_type(const Type* t) const { + if (t == Type::TOP) { + return Type::TOP; + } + if (t == Type::BOTTOM) { + return Type::BOTTOM; + } + t = t->is_tuple()->field_at(_con); + Node* n = in(0); + if ((_con == TypeFunc::Parms) && + n->is_CallStaticJava() && n->as_CallStaticJava()->is_boxing_method()) { + // The result of autoboxing is always non-null on normal path. + t = t->join(TypePtr::NOTNULL); + } + return t; +} + const Type *ProjNode::bottom_type() const { - if (in(0) == NULL) return Type::TOP; - const Type *tb = in(0)->bottom_type(); - if( tb == Type::TOP ) return Type::TOP; - if( tb == Type::BOTTOM ) return Type::BOTTOM; - const TypeTuple *t = tb->is_tuple(); - return t->field_at(_con); + if (in(0) == NULL) return Type::TOP; + return proj_type(in(0)->bottom_type()); } const TypePtr *ProjNode::adr_type() const { @@ -115,11 +129,8 @@ void ProjNode::check_con() const { //------------------------------Value------------------------------------------ const Type *ProjNode::Value( PhaseTransform *phase ) const { - if( !in(0) ) return Type::TOP; - const Type *t = phase->type(in(0)); - if( t == Type::TOP ) return t; - if( t == Type::BOTTOM ) return t; - return t->is_tuple()->field_at(_con); + if (in(0) == NULL) return Type::TOP; + return proj_type(phase->type(in(0))); } //------------------------------out_RegMask------------------------------------ diff --git a/hotspot/src/share/vm/opto/multnode.hpp b/hotspot/src/share/vm/opto/multnode.hpp index fba94e5b431..242e58f4850 100644 --- a/hotspot/src/share/vm/opto/multnode.hpp +++ b/hotspot/src/share/vm/opto/multnode.hpp @@ -60,6 +60,7 @@ protected: virtual uint cmp( const Node &n ) const; virtual uint size_of() const; void check_con() const; // Called from constructor. + const Type* proj_type(const Type* t) const; public: ProjNode( Node *src, uint con, bool io_use = false ) @@ -83,6 +84,7 @@ public: virtual const Type *Value( PhaseTransform *phase ) const; virtual uint ideal_reg() const; virtual const RegMask &out_RegMask() const; + #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; #endif diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp index e1698b26be3..f2100040ffe 100644 --- a/hotspot/src/share/vm/opto/node.cpp +++ b/hotspot/src/share/vm/opto/node.cpp @@ -67,7 +67,8 @@ void Node::verify_construction() { } Compile::set_debug_idx(new_debug_idx); set_debug_idx( new_debug_idx ); - assert(Compile::current()->unique() < (UINT_MAX - 1), "Node limit exceeded UINT_MAX"); + assert(Compile::current()->unique() < (INT_MAX - 1), "Node limit exceeded INT_MAX"); + assert(Compile::current()->live_nodes() < (uint)MaxNodeLimit, "Live Node limit exceeded limit"); if (BreakAtNode != 0 && (_debug_idx == BreakAtNode || (int)_idx == BreakAtNode)) { tty->print_cr("BreakAtNode: _idx=%d _debug_idx=%d", _idx, _debug_idx); BREAKPOINT; @@ -471,9 +472,9 @@ Node::Node(Node *n0, Node *n1, Node *n2, Node *n3, //------------------------------clone------------------------------------------ // Clone a Node. Node *Node::clone() const { - Compile *compile = Compile::current(); + Compile* C = Compile::current(); uint s = size_of(); // Size of inherited Node - Node *n = (Node*)compile->node_arena()->Amalloc_D(size_of() + _max*sizeof(Node*)); + Node *n = (Node*)C->node_arena()->Amalloc_D(size_of() + _max*sizeof(Node*)); Copy::conjoint_words_to_lower((HeapWord*)this, (HeapWord*)n, s); // Set the new input pointer array n->_in = (Node**)(((char*)n)+s); @@ -492,18 +493,18 @@ Node *Node::clone() const { if (x != NULL) x->add_out(n); } if (is_macro()) - compile->add_macro_node(n); + C->add_macro_node(n); if (is_expensive()) - compile->add_expensive_node(n); + C->add_expensive_node(n); - n->set_idx(compile->next_unique()); // Get new unique index as well + n->set_idx(C->next_unique()); // Get new unique index as well debug_only( n->verify_construction() ); NOT_PRODUCT(nodes_created++); // Do not patch over the debug_idx of a clone, because it makes it // impossible to break on the clone's moment of creation. //debug_only( n->set_debug_idx( debug_idx() ) ); - compile->copy_node_notes_to(n, (Node*) this); + C->copy_node_notes_to(n, (Node*) this); // MachNode clone uint nopnds; @@ -518,13 +519,12 @@ Node *Node::clone() const { (const void*)(&mthis->_opnds), 1)); mach->_opnds = to; for ( uint i = 0; i < nopnds; ++i ) { - to[i] = from[i]->clone(compile); + to[i] = from[i]->clone(C); } } // cloning CallNode may need to clone JVMState if (n->is_Call()) { - CallNode *call = n->as_Call(); - call->clone_jvms(); + n->as_Call()->clone_jvms(C); } return n; // Return the clone } @@ -811,6 +811,21 @@ int Node::replace_edge(Node* old, Node* neww) { return nrep; } +/** + * Replace input edges in the range pointing to 'old' node. + */ +int Node::replace_edges_in_range(Node* old, Node* neww, int start, int end) { + if (old == neww) return 0; // nothing to do + uint nrep = 0; + for (int i = start; i < end; i++) { + if (in(i) == old) { + set_req(i, neww); + nrep++; + } + } + return nrep; +} + //-------------------------disconnect_inputs----------------------------------- // NULL out all inputs to eliminate incoming Def-Use edges. // Return the number of edges between 'n' and 'this' @@ -1383,6 +1398,21 @@ const TypeLong* Node::find_long_type() const { return NULL; } + +/** + * Return a ptr type for nodes which should have it. + */ +const TypePtr* Node::get_ptr_type() const { + const TypePtr* tp = this->bottom_type()->make_ptr(); +#ifdef ASSERT + if (tp == NULL) { + this->dump(1); + assert((tp != NULL), "unexpected node type"); + } +#endif + return tp; +} + // Get a double constant from a ConstNode. // Returns the constant if it is a double ConstNode jdouble Node::getd() const { diff --git a/hotspot/src/share/vm/opto/node.hpp b/hotspot/src/share/vm/opto/node.hpp index f8f2c24e860..bb5e8f200d0 100644 --- a/hotspot/src/share/vm/opto/node.hpp +++ b/hotspot/src/share/vm/opto/node.hpp @@ -410,6 +410,7 @@ protected: // Find first occurrence of n among my edges: int find_edge(Node* n); int replace_edge(Node* old, Node* neww); + int replace_edges_in_range(Node* old, Node* neww, int start, int end); // NULL out all inputs to eliminate incoming Def-Use edges. // Return the number of edges between 'n' and 'this' int disconnect_inputs(Node *n, Compile *c); @@ -964,6 +965,8 @@ public: } const TypeLong* find_long_type() const; + const TypePtr* get_ptr_type() const; + // These guys are called by code generated by ADLC: intptr_t get_ptr() const; intptr_t get_narrowcon() const; diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index f5a1e08e169..f04ab721b97 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -929,7 +929,7 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { scval = new_loc_value( _regalloc, obj_reg, Location::oop ); } } else { - const TypePtr *tp = obj_node->bottom_type()->make_ptr(); + const TypePtr *tp = obj_node->get_ptr_type(); scval = new ConstantOopWriteValue(tp->is_oopptr()->const_oop()->constant_encoding()); } diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp index c38f96b6be8..91025bf56fb 100644 --- a/hotspot/src/share/vm/opto/parse.hpp +++ b/hotspot/src/share/vm/opto/parse.hpp @@ -330,6 +330,7 @@ class Parse : public GraphKit { bool _wrote_final; // Did we write a final field? bool _count_invocations; // update and test invocation counter bool _method_data_update; // update method data oop + Node* _alloc_with_final; // An allocation node with final field // Variables which track Java semantics during bytecode parsing: @@ -370,6 +371,11 @@ class Parse : public GraphKit { void set_wrote_final(bool z) { _wrote_final = z; } bool count_invocations() const { return _count_invocations; } bool method_data_update() const { return _method_data_update; } + Node* alloc_with_final() const { return _alloc_with_final; } + void set_alloc_with_final(Node* n) { + assert((_alloc_with_final == NULL) || (_alloc_with_final == n), "different init objects?"); + _alloc_with_final = n; + } Block* block() const { return _block; } ciBytecodeStream& iter() { return _iter; } @@ -512,7 +518,7 @@ class Parse : public GraphKit { // loading from a constant field or the constant pool // returns false if push failed (non-perm field constants only, not ldcs) - bool push_constant(ciConstant con, bool require_constant = false); + bool push_constant(ciConstant con, bool require_constant = false, bool is_autobox_cache = false); // implementation of object creation bytecodes void emit_guard_for_new(ciInstanceKlass* klass); diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index f0f7c8b0a9c..10d98b92f08 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -390,6 +390,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) _expected_uses = expected_uses; _depth = 1 + (caller->has_method() ? caller->depth() : 0); _wrote_final = false; + _alloc_with_final = NULL; _entry_bci = InvocationEntryBci; _tf = NULL; _block = NULL; @@ -723,6 +724,8 @@ void Parse::build_exits() { // Note: iophi and memphi are not transformed until do_exits. Node* iophi = new (C) PhiNode(region, Type::ABIO); Node* memphi = new (C) PhiNode(region, Type::MEMORY, TypePtr::BOTTOM); + gvn().set_type_bottom(iophi); + gvn().set_type_bottom(memphi); _exits.set_i_o(iophi); _exits.set_all_memory(memphi); @@ -738,6 +741,7 @@ void Parse::build_exits() { } int ret_size = type2size[ret_type->basic_type()]; Node* ret_phi = new (C) PhiNode(region, ret_type); + gvn().set_type_bottom(ret_phi); _exits.ensure_stack(ret_size); assert((int)(tf()->range()->cnt() - TypeFunc::Parms) == ret_size, "good tf range"); assert(method()->return_type()->size() == ret_size, "tf agrees w/ method"); @@ -917,7 +921,7 @@ void Parse::do_exits() { // such unusual early publications. But no barrier is needed on // exceptional returns, since they cannot publish normally. // - _exits.insert_mem_bar(Op_MemBarRelease); + _exits.insert_mem_bar(Op_MemBarRelease, alloc_with_final()); #ifndef PRODUCT if (PrintOpto && (Verbose || WizardMode)) { method()->print_name(); diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index 73be6aae570..c41ca257e62 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -987,7 +987,7 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) { uncommon_trap(Deoptimization::Reason_unreached, Deoptimization::Action_reinterpret, NULL, "cold"); - if (EliminateAutoBox) { + if (C->eliminate_boxing()) { // Mark the successor blocks as parsed branch_block->next_path_num(); next_block->next_path_num(); @@ -1012,7 +1012,7 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) { if (stopped()) { // Path is dead? explicit_null_checks_elided++; - if (EliminateAutoBox) { + if (C->eliminate_boxing()) { // Mark the successor block as parsed branch_block->next_path_num(); } @@ -1032,7 +1032,7 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) { if (stopped()) { // Path is dead? explicit_null_checks_elided++; - if (EliminateAutoBox) { + if (C->eliminate_boxing()) { // Mark the successor block as parsed next_block->next_path_num(); } @@ -1069,7 +1069,7 @@ void Parse::do_if(BoolTest::mask btest, Node* c) { uncommon_trap(Deoptimization::Reason_unreached, Deoptimization::Action_reinterpret, NULL, "cold"); - if (EliminateAutoBox) { + if (C->eliminate_boxing()) { // Mark the successor blocks as parsed branch_block->next_path_num(); next_block->next_path_num(); @@ -1135,7 +1135,7 @@ void Parse::do_if(BoolTest::mask btest, Node* c) { set_control(taken_branch); if (stopped()) { - if (EliminateAutoBox) { + if (C->eliminate_boxing()) { // Mark the successor block as parsed branch_block->next_path_num(); } @@ -1154,7 +1154,7 @@ void Parse::do_if(BoolTest::mask btest, Node* c) { // Branch not taken. if (stopped()) { - if (EliminateAutoBox) { + if (C->eliminate_boxing()) { // Mark the successor block as parsed next_block->next_path_num(); } diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index 9de92a2ae54..acabf4985f5 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -150,6 +150,23 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) { // final field if (field->is_static()) { // final static field + if (C->eliminate_boxing()) { + // The pointers in the autobox arrays are always non-null. + ciSymbol* klass_name = field->holder()->name(); + if (field->name() == ciSymbol::cache_field_name() && + field->holder()->uses_default_loader() && + (klass_name == ciSymbol::java_lang_Character_CharacterCache() || + klass_name == ciSymbol::java_lang_Byte_ByteCache() || + klass_name == ciSymbol::java_lang_Short_ShortCache() || + klass_name == ciSymbol::java_lang_Integer_IntegerCache() || + klass_name == ciSymbol::java_lang_Long_LongCache())) { + bool require_const = true; + bool autobox_cache = true; + if (push_constant(field->constant_value(), require_const, autobox_cache)) { + return; + } + } + } if (push_constant(field->constant_value())) return; } @@ -304,11 +321,18 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) { // out of the constructor. if (is_field && field->is_final()) { set_wrote_final(true); + // Preserve allocation ptr to create precedent edge to it in membar + // generated on exit from constructor. + if (C->eliminate_boxing() && + adr_type->isa_oopptr() && adr_type->is_oopptr()->is_ptr_to_boxed_value() && + AllocateNode::Ideal_allocation(obj, &_gvn) != NULL) { + set_alloc_with_final(obj); + } } } -bool Parse::push_constant(ciConstant constant, bool require_constant) { +bool Parse::push_constant(ciConstant constant, bool require_constant, bool is_autobox_cache) { switch (constant.basic_type()) { case T_BOOLEAN: push( intcon(constant.as_boolean()) ); break; case T_INT: push( intcon(constant.as_int()) ); break; @@ -329,7 +353,7 @@ bool Parse::push_constant(ciConstant constant, bool require_constant) { push( zerocon(T_OBJECT) ); break; } else if (require_constant || oop_constant->should_be_constant()) { - push( makecon(TypeOopPtr::make_from_constant(oop_constant, require_constant)) ); + push( makecon(TypeOopPtr::make_from_constant(oop_constant, require_constant, is_autobox_cache)) ); break; } else { // we cannot inline the oop, but we can use it later to narrow a type diff --git a/hotspot/src/share/vm/opto/parseHelper.cpp b/hotspot/src/share/vm/opto/parseHelper.cpp index e9486088dc9..5d0c2f7befe 100644 --- a/hotspot/src/share/vm/opto/parseHelper.cpp +++ b/hotspot/src/share/vm/opto/parseHelper.cpp @@ -284,6 +284,11 @@ void Parse::do_new() { klass == C->env()->StringBuffer_klass())) { C->set_has_stringbuilder(true); } + + // Keep track of boxed values for EliminateAutoBox optimizations. + if (C->eliminate_boxing() && klass->is_box_klass()) { + C->set_has_boxed_value(true); + } } #ifndef PRODUCT diff --git a/hotspot/src/share/vm/opto/phase.cpp b/hotspot/src/share/vm/opto/phase.cpp index 0b88996d3cb..5359301575d 100644 --- a/hotspot/src/share/vm/opto/phase.cpp +++ b/hotspot/src/share/vm/opto/phase.cpp @@ -64,6 +64,7 @@ elapsedTimer Phase::_t_idealLoopVerify; // Subtimers for _t_optimizer elapsedTimer Phase::_t_iterGVN; elapsedTimer Phase::_t_iterGVN2; +elapsedTimer Phase::_t_incrInline; // Subtimers for _t_registerAllocation elapsedTimer Phase::_t_ctorChaitin; @@ -110,6 +111,7 @@ void Phase::print_timers() { 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 (" incrInline : %3.3f sec", Phase::_t_incrInline.seconds()); tty->print_cr (" idealLoop : %3.3f sec", Phase::_t_idealLoop.seconds()); tty->print_cr (" idealLoopVerify: %3.3f sec", Phase::_t_idealLoopVerify.seconds()); tty->print_cr (" ccp : %3.3f sec", Phase::_t_ccp.seconds()); diff --git a/hotspot/src/share/vm/opto/phase.hpp b/hotspot/src/share/vm/opto/phase.hpp index 9faabf5430c..582a126db36 100644 --- a/hotspot/src/share/vm/opto/phase.hpp +++ b/hotspot/src/share/vm/opto/phase.hpp @@ -100,6 +100,7 @@ protected: // Subtimers for _t_optimizer static elapsedTimer _t_iterGVN; static elapsedTimer _t_iterGVN2; + static elapsedTimer _t_incrInline; // Subtimers for _t_registerAllocation static elapsedTimer _t_ctorChaitin; diff --git a/hotspot/src/share/vm/opto/phaseX.cpp b/hotspot/src/share/vm/opto/phaseX.cpp index a8c979662d2..654c6f724b9 100644 --- a/hotspot/src/share/vm/opto/phaseX.cpp +++ b/hotspot/src/share/vm/opto/phaseX.cpp @@ -882,7 +882,7 @@ void PhaseIterGVN::optimize() { return; } Node *n = _worklist.pop(); - if (++loop_count >= K * C->unique()) { + if (++loop_count >= K * C->live_nodes()) { debug_only(n->dump(4);) assert(false, "infinite loop in PhaseIterGVN::optimize"); C->record_method_not_compilable("infinite loop in PhaseIterGVN::optimize"); diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index 7edb97e0bba..d0aefad66b7 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -126,17 +126,15 @@ ExceptionBlob* OptoRuntime::_exception_blob; // This should be called in an assertion at the start of OptoRuntime routines // which are entered from compiled code (all of them) -#ifndef PRODUCT +#ifdef ASSERT static bool check_compiled_frame(JavaThread* thread) { assert(thread->last_frame().is_runtime_frame(), "cannot call runtime directly from compiled code"); -#ifdef ASSERT RegisterMap map(thread, false); frame caller = thread->last_frame().sender(&map); assert(caller.is_compiled_frame(), "not being called from compiled like code"); -#endif /* ASSERT */ return true; } -#endif +#endif // ASSERT #define gen(env, var, type_func_gen, c_func, fancy_jump, pass_tls, save_arg_regs, return_pc) \ diff --git a/hotspot/src/share/vm/opto/subnode.cpp b/hotspot/src/share/vm/opto/subnode.cpp index 70a64ba70cd..275b4d80dd1 100644 --- a/hotspot/src/share/vm/opto/subnode.cpp +++ b/hotspot/src/share/vm/opto/subnode.cpp @@ -863,10 +863,11 @@ const Type *CmpNNode::sub( const Type *t1, const Type *t2 ) const { const TypePtr *r1 = t2->make_ptr(); // Undefined inputs makes for an undefined result - if( TypePtr::above_centerline(r0->_ptr) || - TypePtr::above_centerline(r1->_ptr) ) + if ((r0 == NULL) || (r1 == NULL) || + TypePtr::above_centerline(r0->_ptr) || + TypePtr::above_centerline(r1->_ptr)) { return Type::TOP; - + } if (r0 == r1 && r0->singleton()) { // Equal pointer constants (klasses, nulls, etc.) return TypeInt::CC_EQ; diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index 68f681342d9..fabcf1cad16 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -2372,7 +2372,12 @@ TypeOopPtr::TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int _klass_is_exact(xk), _is_ptr_to_narrowoop(false), _is_ptr_to_narrowklass(false), + _is_ptr_to_boxed_value(false), _instance_id(instance_id) { + if (Compile::current()->eliminate_boxing() && (t == InstPtr) && + (offset > 0) && xk && (k != 0) && k->is_instance_klass()) { + _is_ptr_to_boxed_value = k->as_instance_klass()->is_boxed_value_offset(offset); + } #ifdef _LP64 if (_offset != 0) { if (_offset == oopDesc::klass_offset_in_bytes()) { @@ -2613,44 +2618,50 @@ const TypeOopPtr* TypeOopPtr::make_from_klass_common(ciKlass *klass, bool klass_ //------------------------------make_from_constant----------------------------- // Make a java pointer from an oop constant -const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, bool require_constant) { - assert(!o->is_null_object(), "null object not yet handled here."); - ciKlass* klass = o->klass(); - if (klass->is_instance_klass()) { - // Element is an instance - if (require_constant) { - if (!o->can_be_constant()) return NULL; - } else if (!o->should_be_constant()) { - return TypeInstPtr::make(TypePtr::NotNull, klass, true, NULL, 0); - } - return TypeInstPtr::make(o); - } else if (klass->is_obj_array_klass()) { - // Element is an object array. Recursively call ourself. - const Type *etype = +const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, + bool require_constant, + bool is_autobox_cache) { + assert(!o->is_null_object(), "null object not yet handled here."); + ciKlass* klass = o->klass(); + if (klass->is_instance_klass()) { + // Element is an instance + if (require_constant) { + if (!o->can_be_constant()) return NULL; + } else if (!o->should_be_constant()) { + return TypeInstPtr::make(TypePtr::NotNull, klass, true, NULL, 0); + } + return TypeInstPtr::make(o); + } else if (klass->is_obj_array_klass()) { + // Element is an object array. Recursively call ourself. + const TypeOopPtr *etype = TypeOopPtr::make_from_klass_raw(klass->as_obj_array_klass()->element_klass()); - const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length())); - // We used to pass NotNull in here, asserting that the sub-arrays - // are all not-null. This is not true in generally, as code can - // slam NULLs down in the subarrays. - if (require_constant) { - if (!o->can_be_constant()) return NULL; - } else if (!o->should_be_constant()) { - return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0); - } - const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0); + if (is_autobox_cache) { + // The pointers in the autobox arrays are always non-null. + etype = etype->cast_to_ptr_type(TypePtr::NotNull)->is_oopptr(); + } + const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length())); + // We used to pass NotNull in here, asserting that the sub-arrays + // are all not-null. This is not true in generally, as code can + // slam NULLs down in the subarrays. + if (require_constant) { + if (!o->can_be_constant()) return NULL; + } else if (!o->should_be_constant()) { + return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0); + } + const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0, InstanceBot, is_autobox_cache); return arr; - } else if (klass->is_type_array_klass()) { - // Element is an typeArray + } else if (klass->is_type_array_klass()) { + // Element is an typeArray const Type* etype = (Type*)get_const_basic_type(klass->as_type_array_klass()->element_type()); - const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length())); - // We used to pass NotNull in here, asserting that the array pointer - // is not-null. That was not true in general. - if (require_constant) { - if (!o->can_be_constant()) return NULL; - } else if (!o->should_be_constant()) { - return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0); - } + const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length())); + // We used to pass NotNull in here, asserting that the array pointer + // is not-null. That was not true in general. + if (require_constant) { + if (!o->can_be_constant()) return NULL; + } else if (!o->should_be_constant()) { + return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0); + } const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0); return arr; } @@ -2856,6 +2867,28 @@ const TypeInstPtr *TypeInstPtr::make(PTR ptr, return result; } +/** + * Create constant type for a constant boxed value + */ +const Type* TypeInstPtr::get_const_boxed_value() const { + assert(is_ptr_to_boxed_value(), "should be called only for boxed value"); + assert((const_oop() != NULL), "should be called only for constant object"); + ciConstant constant = const_oop()->as_instance()->field_value_by_offset(offset()); + BasicType bt = constant.basic_type(); + switch (bt) { + case T_BOOLEAN: return TypeInt::make(constant.as_boolean()); + case T_INT: return TypeInt::make(constant.as_int()); + case T_CHAR: return TypeInt::make(constant.as_char()); + case T_BYTE: return TypeInt::make(constant.as_byte()); + case T_SHORT: return TypeInt::make(constant.as_short()); + case T_FLOAT: return TypeF::make(constant.as_float()); + case T_DOUBLE: return TypeD::make(constant.as_double()); + case T_LONG: return TypeLong::make(constant.as_long()); + default: break; + } + fatal(err_msg_res("Invalid boxed value type '%s'", type2name(bt))); + return NULL; +} //------------------------------cast_to_ptr_type------------------------------- const Type *TypeInstPtr::cast_to_ptr_type(PTR ptr) const { @@ -3330,18 +3363,18 @@ const TypeAryPtr *TypeAryPtr::make( PTR ptr, const TypeAry *ary, ciKlass* k, boo if (!xk) xk = ary->ary_must_be_exact(); assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed"); if (!UseExactTypes) xk = (ptr == Constant); - return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id))->hashcons(); + return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id, false))->hashcons(); } //------------------------------make------------------------------------------- -const TypeAryPtr *TypeAryPtr::make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id ) { +const TypeAryPtr *TypeAryPtr::make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, bool is_autobox_cache) { assert(!(k == NULL && ary->_elem->isa_int()), "integral arrays must be pre-equipped with a class"); assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" ); if (!xk) xk = (o != NULL) || ary->ary_must_be_exact(); assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed"); if (!UseExactTypes) xk = (ptr == Constant); - return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id))->hashcons(); + return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id, is_autobox_cache))->hashcons(); } //------------------------------cast_to_ptr_type------------------------------- @@ -3397,8 +3430,20 @@ const TypeInt* TypeAryPtr::narrow_size_type(const TypeInt* size) const { jint max_hi = max_array_length(elem()->basic_type()); //if (index_not_size) --max_hi; // type of a valid array index, FTR bool chg = false; - if (lo < min_lo) { lo = min_lo; chg = true; } - if (hi > max_hi) { hi = max_hi; chg = true; } + if (lo < min_lo) { + lo = min_lo; + if (size->is_con()) { + hi = lo; + } + chg = true; + } + if (hi > max_hi) { + hi = max_hi; + if (size->is_con()) { + lo = hi; + } + chg = true; + } // Negative length arrays will produce weird intermediate dead fast-path code if (lo > hi) return TypeInt::ZERO; @@ -3630,7 +3675,7 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const { //------------------------------xdual------------------------------------------ // Dual: compute field-by-field dual const Type *TypeAryPtr::xdual() const { - return new TypeAryPtr( dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id() ); + return new TypeAryPtr( dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id(), is_autobox_cache() ); } //----------------------interface_vs_oop--------------------------------------- diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index 7868b2f7856..0626cb53f52 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -234,6 +234,9 @@ public: bool is_ptr_to_narrowoop() const; bool is_ptr_to_narrowklass() const; + bool is_ptr_to_boxing_obj() const; + + // Convenience access float getf() const; double getd() const; @@ -794,6 +797,7 @@ protected: bool _klass_is_exact; bool _is_ptr_to_narrowoop; bool _is_ptr_to_narrowklass; + bool _is_ptr_to_boxed_value; // If not InstanceTop or InstanceBot, indicates that this is // a particular instance of this type which is distinct. @@ -826,7 +830,9 @@ public: // If the object cannot be rendered as a constant, // may return a non-singleton type. // If require_constant, produce a NULL if a singleton is not possible. - static const TypeOopPtr* make_from_constant(ciObject* o, bool require_constant = false); + static const TypeOopPtr* make_from_constant(ciObject* o, + bool require_constant = false, + bool not_null_elements = false); // Make a generic (unclassed) pointer to an oop. static const TypeOopPtr* make(PTR ptr, int offset, int instance_id); @@ -839,7 +845,7 @@ public: // compressed oop references. bool is_ptr_to_narrowoop_nv() const { return _is_ptr_to_narrowoop; } bool is_ptr_to_narrowklass_nv() const { return _is_ptr_to_narrowklass; } - + bool is_ptr_to_boxed_value() const { return _is_ptr_to_boxed_value; } bool is_known_instance() const { return _instance_id > 0; } int instance_id() const { return _instance_id; } bool is_known_instance_field() const { return is_known_instance() && _offset >= 0; } @@ -912,6 +918,9 @@ class TypeInstPtr : public TypeOopPtr { // Make a pointer to an oop. static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot ); + /** Create constant type for a constant boxed value */ + const Type* get_const_boxed_value() const; + // If this is a java.lang.Class constant, return the type for it or NULL. // Pass to Type::get_const_type to turn it to a type, which will usually // be a TypeInstPtr, but may also be a TypeInt::INT for int.class, etc. @@ -943,7 +952,12 @@ class TypeInstPtr : public TypeOopPtr { //------------------------------TypeAryPtr------------------------------------- // Class of Java array pointers class TypeAryPtr : public TypeOopPtr { - TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id ) : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id), _ary(ary) { + TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, + int offset, int instance_id, bool is_autobox_cache ) + : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id), + _ary(ary), + _is_autobox_cache(is_autobox_cache) + { #ifdef ASSERT if (k != NULL) { // Verify that specified klass and TypeAryPtr::klass() follow the same rules. @@ -964,6 +978,7 @@ class TypeAryPtr : public TypeOopPtr { virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing const TypeAry *_ary; // Array we point into + const bool _is_autobox_cache; ciKlass* compute_klass(DEBUG_ONLY(bool verify = false)) const; @@ -974,9 +989,11 @@ public: const Type* elem() const { return _ary->_elem; } const TypeInt* size() const { return _ary->_size; } + bool is_autobox_cache() const { return _is_autobox_cache; } + static const TypeAryPtr *make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot); // Constant pointer to array - static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot); + static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, bool is_autobox_cache = false); // Return a 'ptr' version of this type virtual const Type *cast_to_ptr_type(PTR ptr) const; @@ -1504,6 +1521,13 @@ inline bool Type::is_floatingpoint() const { return false; } +inline bool Type::is_ptr_to_boxing_obj() const { + const TypeInstPtr* tp = isa_instptr(); + return (tp != NULL) && (tp->offset() == 0) && + tp->klass()->is_instance_klass() && + tp->klass()->as_instance_klass()->is_box_klass(); +} + // =============================================================== // Things that need to be 64-bits in the 64-bit build but diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index a1dba8dc8bf..58957eed067 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -1306,6 +1306,28 @@ JVM_ENTRY(void, MHN_setCallSiteTargetVolatile(JNIEnv* env, jobject igcls, jobjec } JVM_END +/** + * Throws a java/lang/UnsupportedOperationException unconditionally. + * This is required by the specification of MethodHandle.invoke if + * invoked directly. + */ +JVM_ENTRY(jobject, MH_invoke_UOE(JNIEnv* env, jobject mh, jobjectArray args)) { + THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "MethodHandle.invoke cannot be invoked reflectively"); + return NULL; +} +JVM_END + +/** + * Throws a java/lang/UnsupportedOperationException unconditionally. + * This is required by the specification of MethodHandle.invokeExact if + * invoked directly. + */ +JVM_ENTRY(jobject, MH_invokeExact_UOE(JNIEnv* env, jobject mh, jobjectArray args)) { + THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "MethodHandle.invokeExact cannot be invoked reflectively"); + return NULL; +} +JVM_END + /// JVM_RegisterMethodHandleMethods #undef CS // Solaris builds complain @@ -1325,7 +1347,7 @@ JVM_END #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) // These are the native methods on java.lang.invoke.MethodHandleNatives. -static JNINativeMethod required_methods_JDK8[] = { +static JNINativeMethod MHN_methods[] = { {CC"init", CC"("MEM""OBJ")V", FN_PTR(MHN_init_Mem)}, {CC"expand", CC"("MEM")V", FN_PTR(MHN_expand_Mem)}, {CC"resolve", CC"("MEM""CLS")"MEM, FN_PTR(MHN_resolve_Mem)}, @@ -1343,8 +1365,28 @@ static JNINativeMethod required_methods_JDK8[] = { {CC"getMemberVMInfo", CC"("MEM")"OBJ, FN_PTR(MHN_getMemberVMInfo)} }; -// This one function is exported, used by NativeLookup. +static JNINativeMethod MH_methods[] = { + // UnsupportedOperationException throwers + {CC"invoke", CC"(["OBJ")"OBJ, FN_PTR(MH_invoke_UOE)}, + {CC"invokeExact", CC"(["OBJ")"OBJ, FN_PTR(MH_invokeExact_UOE)} +}; +/** + * Helper method to register native methods. + */ +static bool register_natives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint nMethods) { + int status = env->RegisterNatives(clazz, methods, nMethods); + if (status != JNI_OK || env->ExceptionOccurred()) { + warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); + env->ExceptionClear(); + return false; + } + return true; +} + +/** + * This one function is exported, used by NativeLookup. + */ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) { if (!EnableInvokeDynamic) { warning("JSR 292 is disabled in this JVM. Use -XX:+UnlockDiagnosticVMOptions -XX:+EnableInvokeDynamic to enable."); @@ -1362,16 +1404,14 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) MH_class = (jclass) JNIHandles::make_local(env, mirror); } - int status; - if (enable_MH) { ThreadToNativeFromVM ttnfv(thread); - status = env->RegisterNatives(MHN_class, required_methods_JDK8, sizeof(required_methods_JDK8)/sizeof(JNINativeMethod)); - if (status != JNI_OK || env->ExceptionOccurred()) { - warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); - enable_MH = false; - env->ExceptionClear(); + if (enable_MH) { + enable_MH = register_natives(env, MHN_class, MHN_methods, sizeof(MHN_methods)/sizeof(JNINativeMethod)); + } + if (enable_MH) { + enable_MH = register_natives(env, MH_class, MH_methods, sizeof(MH_methods)/sizeof(JNINativeMethod)); } } diff --git a/hotspot/src/share/vm/prims/nativeLookup.cpp b/hotspot/src/share/vm/prims/nativeLookup.cpp index 6162ae85032..990600eea27 100644 --- a/hotspot/src/share/vm/prims/nativeLookup.cpp +++ b/hotspot/src/share/vm/prims/nativeLookup.cpp @@ -383,10 +383,7 @@ address NativeLookup::lookup_base(methodHandle method, bool& in_base_library, TR address NativeLookup::lookup(methodHandle method, bool& in_base_library, TRAPS) { if (!method->has_native_function()) { - address entry = - method->intrinsic_id() == vmIntrinsics::_invokeGeneric ? - SharedRuntime::native_method_throw_unsupported_operation_exception_entry() : - lookup_base(method, in_base_library, CHECK_NULL); + address entry = lookup_base(method, in_base_library, CHECK_NULL); method->set_native_function(entry, Method::native_bind_event_is_interesting); // -verbose:jni printing diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 19ad81502dd..b1cfb3cc362 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1089,6 +1089,10 @@ void Arguments::set_tiered_flags() { if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) { FLAG_SET_DEFAULT(ReservedCodeCacheSize, ReservedCodeCacheSize * 5); } + if (!UseInterpreter) { // -Xcomp + Tier3InvokeNotifyFreqLog = 0; + Tier4InvocationThreshold = 0; + } } #if INCLUDE_ALL_GCS @@ -1669,6 +1673,20 @@ void Arguments::set_bytecode_flags() { // Aggressive optimization flags -XX:+AggressiveOpts void Arguments::set_aggressive_opts_flags() { #ifdef COMPILER2 + if (AggressiveUnboxing) { + if (FLAG_IS_DEFAULT(EliminateAutoBox)) { + FLAG_SET_DEFAULT(EliminateAutoBox, true); + } else if (!EliminateAutoBox) { + // warning("AggressiveUnboxing is disabled because EliminateAutoBox is disabled"); + AggressiveUnboxing = false; + } + if (FLAG_IS_DEFAULT(DoEscapeAnalysis)) { + FLAG_SET_DEFAULT(DoEscapeAnalysis, true); + } else if (!DoEscapeAnalysis) { + // warning("AggressiveUnboxing is disabled because DoEscapeAnalysis is disabled"); + AggressiveUnboxing = false; + } + } if (AggressiveOpts || !FLAG_IS_DEFAULT(AutoBoxCacheMax)) { if (FLAG_IS_DEFAULT(EliminateAutoBox)) { FLAG_SET_DEFAULT(EliminateAutoBox, true); @@ -1901,7 +1919,7 @@ bool Arguments::check_vm_args_consistency() { status = false; } - status = status && verify_percentage(AdaptiveSizePolicyWeight, + status = status && verify_interval(AdaptiveSizePolicyWeight, 0, 100, "AdaptiveSizePolicyWeight"); status = status && verify_percentage(ThresholdTolerance, "ThresholdTolerance"); status = status && verify_percentage(MinHeapFreeRatio, "MinHeapFreeRatio"); @@ -1961,8 +1979,6 @@ bool Arguments::check_vm_args_consistency() { FLAG_SET_DEFAULT(UseGCOverheadLimit, false); } - status = status && verify_percentage(GCHeapFreeLimit, "GCHeapFreeLimit"); - status = status && check_gc_consistency(); status = status && check_stack_pages(); @@ -2056,6 +2072,52 @@ bool Arguments::check_vm_args_consistency() { status = status && verify_interval(G1ConcRSLogCacheSize, 0, 31, "G1ConcRSLogCacheSize"); } + if (UseConcMarkSweepGC) { + status = status && verify_min_value(CMSOldPLABNumRefills, 1, "CMSOldPLABNumRefills"); + status = status && verify_min_value(CMSOldPLABToleranceFactor, 1, "CMSOldPLABToleranceFactor"); + status = status && verify_min_value(CMSOldPLABMax, 1, "CMSOldPLABMax"); + status = status && verify_interval(CMSOldPLABMin, 1, CMSOldPLABMax, "CMSOldPLABMin"); + + status = status && verify_min_value(CMSYoungGenPerWorker, 1, "CMSYoungGenPerWorker"); + + status = status && verify_min_value(CMSSamplingGrain, 1, "CMSSamplingGrain"); + status = status && verify_interval(CMS_SweepWeight, 0, 100, "CMS_SweepWeight"); + status = status && verify_interval(CMS_FLSWeight, 0, 100, "CMS_FLSWeight"); + + status = status && verify_interval(FLSCoalescePolicy, 0, 4, "FLSCoalescePolicy"); + + status = status && verify_min_value(CMSRescanMultiple, 1, "CMSRescanMultiple"); + status = status && verify_min_value(CMSConcMarkMultiple, 1, "CMSConcMarkMultiple"); + + status = status && verify_interval(CMSPrecleanIter, 0, 9, "CMSPrecleanIter"); + status = status && verify_min_value(CMSPrecleanDenominator, 1, "CMSPrecleanDenominator"); + status = status && verify_interval(CMSPrecleanNumerator, 0, CMSPrecleanDenominator - 1, "CMSPrecleanNumerator"); + + status = status && verify_percentage(CMSBootstrapOccupancy, "CMSBootstrapOccupancy"); + + status = status && verify_min_value(CMSPrecleanThreshold, 100, "CMSPrecleanThreshold"); + + status = status && verify_percentage(CMSScheduleRemarkEdenPenetration, "CMSScheduleRemarkEdenPenetration"); + status = status && verify_min_value(CMSScheduleRemarkSamplingRatio, 1, "CMSScheduleRemarkSamplingRatio"); + status = status && verify_min_value(CMSBitMapYieldQuantum, 1, "CMSBitMapYieldQuantum"); + status = status && verify_percentage(CMSTriggerRatio, "CMSTriggerRatio"); + status = status && verify_percentage(CMSIsTooFullPercentage, "CMSIsTooFullPercentage"); + } + + if (UseParallelGC || UseParallelOldGC) { + status = status && verify_interval(ParallelOldDeadWoodLimiterMean, 0, 100, "ParallelOldDeadWoodLimiterMean"); + status = status && verify_interval(ParallelOldDeadWoodLimiterStdDev, 0, 100, "ParallelOldDeadWoodLimiterStdDev"); + + status = status && verify_percentage(YoungGenerationSizeIncrement, "YoungGenerationSizeIncrement"); + status = status && verify_percentage(TenuredGenerationSizeIncrement, "TenuredGenerationSizeIncrement"); + + status = status && verify_min_value(YoungGenerationSizeSupplementDecay, 1, "YoungGenerationSizeSupplementDecay"); + status = status && verify_min_value(TenuredGenerationSizeSupplementDecay, 1, "TenuredGenerationSizeSupplementDecay"); + + status = status && verify_min_value(ParGCCardsPerStrideChunk, 1, "ParGCCardsPerStrideChunk"); + + status = status && verify_min_value(ParallelOldGCSplitInterval, 0, "ParallelOldGCSplitInterval"); + } #endif // INCLUDE_ALL_GCS status = status && verify_interval(RefDiscoveryPolicy, @@ -2075,7 +2137,42 @@ bool Arguments::check_vm_args_consistency() { status = status && verify_interval(MarkStackSizeMax, 1, (max_jint - 1), "MarkStackSizeMax"); + status = status && verify_interval(NUMAChunkResizeWeight, 0, 100, "NUMAChunkResizeWeight"); + status = status && verify_min_value(LogEventsBufferEntries, 1, "LogEventsBufferEntries"); + + status = status && verify_min_value(HeapSizePerGCThread, (uintx) os::vm_page_size(), "HeapSizePerGCThread"); + + status = status && verify_min_value(GCTaskTimeStampEntries, 1, "GCTaskTimeStampEntries"); + + status = status && verify_percentage(ParallelGCBufferWastePct, "ParallelGCBufferWastePct"); + status = status && verify_interval(TargetPLABWastePct, 1, 100, "TargetPLABWastePct"); + + status = status && verify_min_value(ParGCStridesPerThread, 1, "ParGCStridesPerThread"); + + status = status && verify_min_value(MinRAMFraction, 1, "MinRAMFraction"); + status = status && verify_min_value(InitialRAMFraction, 1, "InitialRAMFraction"); + status = status && verify_min_value(MaxRAMFraction, 1, "MaxRAMFraction"); + status = status && verify_min_value(DefaultMaxRAMFraction, 1, "DefaultMaxRAMFraction"); + + status = status && verify_interval(AdaptiveTimeWeight, 0, 100, "AdaptiveTimeWeight"); + status = status && verify_min_value(AdaptiveSizeDecrementScaleFactor, 1, "AdaptiveSizeDecrementScaleFactor"); + + status = status && verify_interval(TLABAllocationWeight, 0, 100, "TLABAllocationWeight"); + status = status && verify_min_value(MinTLABSize, 1, "MinTLABSize"); + status = status && verify_min_value(TLABRefillWasteFraction, 1, "TLABRefillWasteFraction"); + + status = status && verify_percentage(YoungGenerationSizeSupplement, "YoungGenerationSizeSupplement"); + status = status && verify_percentage(TenuredGenerationSizeSupplement, "TenuredGenerationSizeSupplement"); + + // the "age" field in the oop header is 4 bits; do not want to pull in markOop.hpp + // just for that, so hardcode here. + status = status && verify_interval(MaxTenuringThreshold, 0, 15, "MaxTenuringThreshold"); + status = status && verify_interval(InitialTenuringThreshold, 0, MaxTenuringThreshold, "MaxTenuringThreshold"); + status = status && verify_percentage(TargetSurvivorRatio, "TargetSurvivorRatio"); + status = status && verify_percentage(MarkSweepDeadRatio, "MarkSweepDeadRatio"); + + status = status && verify_min_value(MarkSweepAlwaysCompactCount, 1, "MarkSweepAlwaysCompactCount"); #ifdef SPARC if (UseConcMarkSweepGC || UseG1GC) { // Issue a stern warning if the user has explicitly set @@ -2985,6 +3082,11 @@ jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_req set_mode_flags(_int); } + // eventually fix up InitialTenuringThreshold if only MaxTenuringThreshold is set + if (FLAG_IS_DEFAULT(InitialTenuringThreshold) && (InitialTenuringThreshold > MaxTenuringThreshold)) { + FLAG_SET_ERGO(uintx, InitialTenuringThreshold, MaxTenuringThreshold); + } + #ifndef COMPILER2 // Don't degrade server performance for footprint if (FLAG_IS_DEFAULT(UseLargePages) && diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 6a0e4a403fb..1131c8e103b 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -286,12 +286,12 @@ class CounterSetting { }; -class IntFlagSetting { - intx val; - intx* flag; +class UIntFlagSetting { + uintx val; + uintx* flag; public: - IntFlagSetting(intx& fl, intx newValue) { flag = &fl; val = fl; fl = newValue; } - ~IntFlagSetting() { *flag = val; } + UIntFlagSetting(uintx& fl, uintx newValue) { flag = &fl; val = fl; fl = newValue; } + ~UIntFlagSetting() { *flag = val; } }; @@ -513,12 +513,12 @@ class CommandLineFlags { product(bool, ForceNUMA, false, \ "Force NUMA optimizations on single-node/UMA systems") \ \ - product(intx, NUMAChunkResizeWeight, 20, \ - "Percentage (0-100) used to weight the current sample when " \ + product(uintx, NUMAChunkResizeWeight, 20, \ + "Percentage (0-100) used to weigh the current sample when " \ "computing exponentially decaying average for " \ "AdaptiveNUMAChunkSizing") \ \ - product(intx, NUMASpaceResizeRate, 1*G, \ + product(uintx, NUMASpaceResizeRate, 1*G, \ "Do not reallocate more that this amount per collection") \ \ product(bool, UseAdaptiveNUMAChunkSizing, true, \ @@ -527,7 +527,7 @@ class CommandLineFlags { product(bool, NUMAStats, false, \ "Print NUMA stats in detailed heap information") \ \ - product(intx, NUMAPageScanRate, 256, \ + product(uintx, NUMAPageScanRate, 256, \ "Maximum number of pages to include in the page scan procedure") \ \ product_pd(bool, NeedsDeoptSuspend, \ @@ -715,7 +715,7 @@ class CommandLineFlags { diagnostic(bool, LogEvents, true, \ "Enable the various ring buffer event logs") \ \ - diagnostic(intx, LogEventsBufferEntries, 10, \ + diagnostic(uintx, LogEventsBufferEntries, 10, \ "Enable the various ring buffer event logs") \ \ product(bool, BytecodeVerificationRemote, true, \ @@ -1429,16 +1429,17 @@ class CommandLineFlags { product(bool, ParallelGCVerbose, false, \ "Verbose output for parallel GC.") \ \ - product(intx, ParallelGCBufferWastePct, 10, \ - "wasted fraction of parallel allocation buffer.") \ + product(uintx, ParallelGCBufferWastePct, 10, \ + "Wasted fraction of parallel allocation buffer.") \ \ diagnostic(bool, ParallelGCRetainPLAB, false, \ "Retain parallel allocation buffers across scavenges; " \ " -- disabled because this currently conflicts with " \ " parallel card scanning under certain conditions ") \ \ - product(intx, TargetPLABWastePct, 10, \ - "target wasted space in last buffer as pct of overall allocation")\ + product(uintx, TargetPLABWastePct, 10, \ + "Target wasted space in last buffer as percent of overall " \ + "allocation") \ \ product(uintx, PLABWeight, 75, \ "Percentage (0-100) used to weight the current sample when" \ @@ -1516,7 +1517,7 @@ class CommandLineFlags { product(bool, AlwaysPreTouch, false, \ "It forces all freshly committed pages to be pre-touched.") \ \ - product_pd(intx, CMSYoungGenPerWorker, \ + product_pd(uintx, CMSYoungGenPerWorker, \ "The maximum size of young gen chosen by default per GC worker " \ "thread available") \ \ @@ -1834,7 +1835,7 @@ class CommandLineFlags { product(bool, UseCMSInitiatingOccupancyOnly, false, \ "Only use occupancy as a crierion for starting a CMS collection") \ \ - product(intx, CMSIsTooFullPercentage, 98, \ + product(uintx, CMSIsTooFullPercentage, 98, \ "An absolute ceiling above which CMS will always consider the " \ "unloading of classes when class unloading is enabled") \ \ @@ -1873,7 +1874,7 @@ class CommandLineFlags { develop(uintx, PromotionFailureALotInterval, 5, \ "Total collections between promotion failures alot") \ \ - experimental(intx, WorkStealingSleepMillis, 1, \ + experimental(uintx, WorkStealingSleepMillis, 1, \ "Sleep time when sleep is used for yields") \ \ experimental(uintx, WorkStealingYieldsBeforeSleep, 5000, \ @@ -2017,7 +2018,7 @@ class CommandLineFlags { "Number of collections before the adaptive sizing is started") \ \ product(uintx, AdaptiveSizePolicyOutputInterval, 0, \ - "Collecton interval for printing information; zero => never") \ + "Collection interval for printing information; zero means never") \ \ product(bool, UseAdaptiveSizePolicyFootprintGoal, true, \ "Use adaptive minimum footprint as a goal") \ @@ -3046,7 +3047,7 @@ class CommandLineFlags { product(uintx, MaxMetaspaceExpansion, ScaleForWordSize(4*M), \ "Max expansion of Metaspace without full GC (in bytes)") \ \ - product(intx, QueuedAllocationWarningCount, 0, \ + product(uintx, QueuedAllocationWarningCount, 0, \ "Number of times an allocation that queues behind a GC " \ "will retry before printing a warning") \ \ @@ -3074,7 +3075,7 @@ class CommandLineFlags { "either completely full or completely empty. Par compact also" \ "has a smaller default value; see arguments.cpp.") \ \ - product(intx, MarkSweepAlwaysCompactCount, 4, \ + product(uintx, MarkSweepAlwaysCompactCount, 4, \ "How often should we fully compact the heap (ignoring the dead " \ "space parameters)") \ \ diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 57af1f3bda7..114f27d20a8 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -883,15 +883,23 @@ address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread, } -JNI_ENTRY(void, throw_unsatisfied_link_error(JNIEnv* env, ...)) +/** + * Throws an java/lang/UnsatisfiedLinkError. The address of this method is + * installed in the native function entry of all native Java methods before + * they get linked to their actual native methods. + * + * \note + * This method actually never gets called! The reason is because + * the interpreter's native entries call NativeLookup::lookup() which + * throws the exception when the lookup fails. The exception is then + * caught and forwarded on the return from NativeLookup::lookup() call + * before the call to the native function. This might change in the future. + */ +JNI_ENTRY(void*, throw_unsatisfied_link_error(JNIEnv* env, ...)) { - THROW(vmSymbols::java_lang_UnsatisfiedLinkError()); -} -JNI_END - -JNI_ENTRY(void, throw_unsupported_operation_exception(JNIEnv* env, ...)) -{ - THROW(vmSymbols::java_lang_UnsupportedOperationException()); + // We return a bad value here to make sure that the exception is + // forwarded before we look at the return value. + THROW_(vmSymbols::java_lang_UnsatisfiedLinkError(), (void*)badJNIHandle); } JNI_END @@ -899,10 +907,6 @@ address SharedRuntime::native_method_throw_unsatisfied_link_error_entry() { return CAST_FROM_FN_PTR(address, &throw_unsatisfied_link_error); } -address SharedRuntime::native_method_throw_unsupported_operation_exception_entry() { - return CAST_FROM_FN_PTR(address, &throw_unsupported_operation_exception); -} - #ifndef PRODUCT JRT_ENTRY(intptr_t, SharedRuntime::trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2)) diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index aacc63b5e41..b3fdd1e7097 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -1057,6 +1057,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; c2_nonstatic_field(Compile, _save_argument_registers, const bool) \ c2_nonstatic_field(Compile, _subsume_loads, const bool) \ c2_nonstatic_field(Compile, _do_escape_analysis, const bool) \ + c2_nonstatic_field(Compile, _eliminate_boxing, const bool) \ c2_nonstatic_field(Compile, _ilt, InlineTree*) \ \ c2_nonstatic_field(InlineTree, _caller_jvms, JVMState*) \ diff --git a/hotspot/src/share/vm/utilities/quickSort.cpp b/hotspot/src/share/vm/utilities/quickSort.cpp index 86c33a208a2..0cb7f6ef833 100644 --- a/hotspot/src/share/vm/utilities/quickSort.cpp +++ b/hotspot/src/share/vm/utilities/quickSort.cpp @@ -34,6 +34,7 @@ #include "memory/allocation.inline.hpp" #include +#ifdef ASSERT static int test_comparator(int a, int b) { if (a == b) { return 0; @@ -43,6 +44,7 @@ static int test_comparator(int a, int b) { } return 1; } +#endif // ASSERT static int test_even_odd_comparator(int a, int b) { bool a_is_odd = (a % 2) == 1; diff --git a/hotspot/test/compiler/6934604/TestByteBoxing.java b/hotspot/test/compiler/6934604/TestByteBoxing.java new file mode 100644 index 00000000000..ee5511a9818 --- /dev/null +++ b/hotspot/test/compiler/6934604/TestByteBoxing.java @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 6934604 + * @summary enable parts of EliminateAutoBox by default + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox TestByteBoxing + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox + * -XX:CompileCommand=exclude,TestByteBoxing.dummy -XX:CompileCommand=exclude,TestByteBoxing.foo -XX:CompileCommand=exclude,TestByteBoxing.foob TestByteBoxing + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-EliminateAutoBox + * -XX:CompileCommand=exclude,TestByteBoxing.dummy -XX:CompileCommand=exclude,TestByteBoxing.foo -XX:CompileCommand=exclude,TestByteBoxing.foob TestByteBoxing + * + */ + +public class TestByteBoxing { + + static final Byte ibc = new Byte((byte)1); + + //=============================================== + // Non-inlined methods to test deoptimization info + static void dummy() { } + static byte foo(byte i) { return i; } + static Byte foob(byte i) { return Byte.valueOf(i); } + + + static byte simple(byte i) { + Byte ib = new Byte(i); + return ib; + } + + static byte simpleb(byte i) { + Byte ib = Byte.valueOf(i); + return ib; + } + + static byte simplec() { + Byte ib = ibc; + return ib; + } + + static byte simplef(byte i) { + Byte ib = foob(i); + return ib; + } + + static byte simplep(Byte ib) { + return ib; + } + + static byte simple2(byte i) { + Byte ib1 = new Byte(i); + Byte ib2 = new Byte((byte)(i+1)); + return (byte)(ib1 + ib2); + } + + static byte simpleb2(byte i) { + Byte ib1 = Byte.valueOf(i); + Byte ib2 = Byte.valueOf((byte)(i+1)); + return (byte)(ib1 + ib2); + } + + static byte simplem2(byte i) { + Byte ib1 = new Byte(i); + Byte ib2 = Byte.valueOf((byte)(i+1)); + return (byte)(ib1 + ib2); + } + + static byte simplep2(byte i, Byte ib1) { + Byte ib2 = Byte.valueOf((byte)(i+1)); + return (byte)(ib1 + ib2); + } + + static byte simplec2(byte i) { + Byte ib1 = ibc; + Byte ib2 = Byte.valueOf((byte)(i+1)); + return (byte)(ib1 + ib2); + } + + //=============================================== + static byte test(byte i) { + Byte ib = new Byte(i); + if ((i&1) == 0) + ib = (byte)(i+1); + return ib; + } + + static byte testb(byte i) { + Byte ib = i; + if ((i&1) == 0) + ib = (byte)(i+1); + return ib; + } + + static byte testm(byte i) { + Byte ib = i; + if ((i&1) == 0) + ib = new Byte((byte)(i+1)); + return ib; + } + + static byte testp(byte i, Byte ib) { + if ((i&1) == 0) + ib = new Byte((byte)(i+1)); + return ib; + } + + static byte testc(byte i) { + Byte ib = ibc; + if ((i&1) == 0) + ib = new Byte((byte)(i+1)); + return ib; + } + + static byte test2(byte i) { + Byte ib1 = new Byte(i); + Byte ib2 = new Byte((byte)(i+1)); + if ((i&1) == 0) { + ib1 = new Byte((byte)(i+1)); + ib2 = new Byte((byte)(i+2)); + } + return (byte)(ib1+ib2); + } + + static byte testb2(byte i) { + Byte ib1 = i; + Byte ib2 = (byte)(i+1); + if ((i&1) == 0) { + ib1 = (byte)(i+1); + ib2 = (byte)(i+2); + } + return (byte)(ib1 + ib2); + } + + static byte testm2(byte i) { + Byte ib1 = new Byte(i); + Byte ib2 = (byte)(i+1); + if ((i&1) == 0) { + ib1 = new Byte((byte)(i+1)); + ib2 = (byte)(i+2); + } + return (byte)(ib1 + ib2); + } + + static byte testp2(byte i, Byte ib1) { + Byte ib2 = (byte)(i+1); + if ((i&1) == 0) { + ib1 = new Byte((byte)(i+1)); + ib2 = (byte)(i+2); + } + return (byte)(ib1 + ib2); + } + + static byte testc2(byte i) { + Byte ib1 = ibc; + Byte ib2 = (byte)(i+1); + if ((i&1) == 0) { + ib1 = (byte)(ibc+1); + ib2 = (byte)(i+2); + } + return (byte)(ib1 + ib2); + } + + //=============================================== + static byte sum(byte[] a) { + byte result = 1; + for (Byte i : a) + result += i; + return result; + } + + static byte sumb(byte[] a) { + Byte result = 1; + for (Byte i : a) + result = (byte)(result + i); + return result; + } + + static byte sumc(byte[] a) { + Byte result = ibc; + for (Byte i : a) + result = (byte)(result + i); + return result; + } + + static byte sumf(byte[] a) { + Byte result = foob((byte)1); + for (Byte i : a) + result = (byte)(result + i); + return result; + } + + static byte sump(byte[] a, Byte result) { + for (Byte i : a) + result = (byte)(result + i); + return result; + } + + static byte sum2(byte[] a) { + byte result1 = 1; + byte result2 = 1; + for (Byte i : a) { + result1 += i; + result2 += i + 1; + } + return (byte)(result1 + result2); + } + + static byte sumb2(byte[] a) { + Byte result1 = 1; + Byte result2 = 1; + for (Byte i : a) { + result1 = (byte)(result1 + i); + result2 = (byte)(result2 + i + 1); + } + return (byte)(result1 + result2); + } + + static byte summ2(byte[] a) { + Byte result1 = 1; + Byte result2 = new Byte((byte)1); + for (Byte i : a) { + result1 = (byte)(result1 + i); + result2 = (byte)(result2 + new Byte((byte)(i + 1))); + } + return (byte)(result1 + result2); + } + + static byte sump2(byte[] a, Byte result2) { + Byte result1 = 1; + for (Byte i : a) { + result1 = (byte)(result1 + i); + result2 = (byte)(result2 + i + 1); + } + return (byte)(result1 + result2); + } + + static byte sumc2(byte[] a) { + Byte result1 = 1; + Byte result2 = ibc; + for (Byte i : a) { + result1 = (byte)(result1 + i); + result2 = (byte)(result2 + i + ibc); + } + return (byte)(result1 + result2); + } + + //=============================================== + static byte remi_sum() { + Byte j = new Byte((byte)1); + for (int i = 0; i< 1000; i++) { + j = new Byte((byte)(j + 1)); + } + return j; + } + + static byte remi_sumb() { + Byte j = Byte.valueOf((byte)1); + for (int i = 0; i< 1000; i++) { + j = (byte)(j + 1); + } + return j; + } + + static byte remi_sumf() { + Byte j = foob((byte)1); + for (int i = 0; i< 1000; i++) { + j = (byte)(j + 1); + } + return j; + } + + static byte remi_sump(Byte j) { + for (int i = 0; i< 1000; i++) { + j = new Byte((byte)(j + 1)); + } + return j; + } + + static byte remi_sumc() { + Byte j = ibc; + for (int i = 0; i< 1000; i++) { + j = (byte)(j + ibc); + } + return j; + } + + static byte remi_sum2() { + Byte j1 = new Byte((byte)1); + Byte j2 = new Byte((byte)1); + for (int i = 0; i< 1000; i++) { + j1 = new Byte((byte)(j1 + 1)); + j2 = new Byte((byte)(j2 + 2)); + } + return (byte)(j1 + j2); + } + + static byte remi_sumb2() { + Byte j1 = Byte.valueOf((byte)1); + Byte j2 = Byte.valueOf((byte)1); + for (int i = 0; i< 1000; i++) { + j1 = (byte)(j1 + 1); + j2 = (byte)(j2 + 2); + } + return (byte)(j1 + j2); + } + + static byte remi_summ2() { + Byte j1 = new Byte((byte)1); + Byte j2 = Byte.valueOf((byte)1); + for (int i = 0; i< 1000; i++) { + j1 = new Byte((byte)(j1 + 1)); + j2 = (byte)(j2 + 2); + } + return (byte)(j1 + j2); + } + + static byte remi_sump2(Byte j1) { + Byte j2 = Byte.valueOf((byte)1); + for (int i = 0; i< 1000; i++) { + j1 = new Byte((byte)(j1 + 1)); + j2 = (byte)(j2 + 2); + } + return (byte)(j1 + j2); + } + + static byte remi_sumc2() { + Byte j1 = ibc; + Byte j2 = Byte.valueOf((byte)1); + for (int i = 0; i< 1000; i++) { + j1 = (byte)(j1 + ibc); + j2 = (byte)(j2 + 2); + } + return (byte)(j1 + j2); + } + + + //=============================================== + // Safepointa and debug info for deoptimization + static byte simple_deop(byte i) { + Byte ib = new Byte(foo(i)); + dummy(); + return ib; + } + + static byte simpleb_deop(byte i) { + Byte ib = Byte.valueOf(foo(i)); + dummy(); + return ib; + } + + static byte simplef_deop(byte i) { + Byte ib = foob(i); + dummy(); + return ib; + } + + static byte simplep_deop(Byte ib) { + dummy(); + return ib; + } + + static byte simplec_deop(byte i) { + Byte ib = ibc; + dummy(); + return ib; + } + + static byte test_deop(byte i) { + Byte ib = new Byte(foo(i)); + if ((i&1) == 0) + ib = foo((byte)(i+1)); + dummy(); + return ib; + } + + static byte testb_deop(byte i) { + Byte ib = foo(i); + if ((i&1) == 0) + ib = foo((byte)(i+1)); + dummy(); + return ib; + } + + static byte testf_deop(byte i) { + Byte ib = foob(i); + if ((i&1) == 0) + ib = foo((byte)(i+1)); + dummy(); + return ib; + } + + static byte testp_deop(byte i, Byte ib) { + if ((i&1) == 0) + ib = foo((byte)(i+1)); + dummy(); + return ib; + } + + static byte testc_deop(byte i) { + Byte ib = ibc; + if ((i&1) == 0) + ib = foo((byte)(i+1)); + dummy(); + return ib; + } + + static byte sum_deop(byte[] a) { + byte result = 1; + for (Byte i : a) + result += foo(i); + dummy(); + return result; + } + + static byte sumb_deop(byte[] a) { + Byte result = 1; + for (Byte i : a) + result = (byte)(result + foo(i)); + dummy(); + return result; + } + + static byte sumf_deop(byte[] a) { + Byte result = 1; + for (Byte i : a) + result = (byte)(result + foob(i)); + dummy(); + return result; + } + + static byte sump_deop(byte[] a, Byte result) { + for (Byte i : a) + result = (byte)(result + foob(i)); + dummy(); + return result; + } + + static byte sumc_deop(byte[] a) { + Byte result = ibc; + for (Byte i : a) + result = (byte)(result + foo(i)); + dummy(); + return result; + } + + static byte remi_sum_deop() { + Byte j = new Byte(foo((byte)1)); + for (int i = 0; i< 1000; i++) { + j = new Byte(foo((byte)(j + 1))); + } + dummy(); + return j; + } + + static byte remi_sumb_deop() { + Byte j = Byte.valueOf(foo((byte)1)); + for (int i = 0; i< 1000; i++) { + j = foo((byte)(j + 1)); + } + dummy(); + return j; + } + + static byte remi_sumf_deop() { + Byte j = foob((byte)1); + for (int i = 0; i< 1000; i++) { + j = foo((byte)(j + 1)); + } + dummy(); + return j; + } + + static byte remi_sump_deop(Byte j) { + for (int i = 0; i< 1000; i++) { + j = foo((byte)(j + 1)); + } + dummy(); + return j; + } + + static byte remi_sumc_deop() { + Byte j = ibc; + for (int i = 0; i< 1000; i++) { + j = foo((byte)(j + 1)); + } + dummy(); + return j; + } + + //=============================================== + // Conditional increment + static byte remi_sum_cond() { + Byte j = new Byte((byte)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = new Byte((byte)(j + 1)); + } + } + return j; + } + + static byte remi_sumb_cond() { + Byte j = Byte.valueOf((byte)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = (byte)(j + 1); + } + } + return j; + } + + static byte remi_sumf_cond() { + Byte j = foob((byte)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = (byte)(j + 1); + } + } + return j; + } + + static byte remi_sump_cond(Byte j) { + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = (byte)(j + 1); + } + } + return j; + } + + static byte remi_sumc_cond() { + Byte j = ibc; + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = (byte)(j + ibc); + } + } + return j; + } + + static byte remi_sum2_cond() { + Byte j1 = new Byte((byte)1); + Byte j2 = new Byte((byte)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Byte((byte)(j1 + 1)); + } else { + j2 = new Byte((byte)(j2 + 2)); + } + } + return (byte)(j1 + j2); + } + + static byte remi_sumb2_cond() { + Byte j1 = Byte.valueOf((byte)1); + Byte j2 = Byte.valueOf((byte)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = (byte)(j1 + 1); + } else { + j2 = (byte)(j2 + 2); + } + } + return (byte)(j1 + j2); + } + + static byte remi_summ2_cond() { + Byte j1 = new Byte((byte)1); + Byte j2 = Byte.valueOf((byte)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Byte((byte)(j1 + 1)); + } else { + j2 = (byte)(j2 + 2); + } + } + return (byte)(j1 + j2); + } + + static byte remi_sump2_cond(Byte j1) { + Byte j2 = Byte.valueOf((byte)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Byte((byte)(j1 + 1)); + } else { + j2 = (byte)(j2 + 2); + } + } + return (byte)(j1 + j2); + } + + static byte remi_sumc2_cond() { + Byte j1 = ibc; + Byte j2 = Byte.valueOf((byte)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = (byte)(j1 + ibc); + } else { + j2 = (byte)(j2 + 2); + } + } + return (byte)(j1 + j2); + } + + + public static void main(String[] args) { + final int ntests = 70; + + String[] test_name = new String[] { + "simple", "simpleb", "simplec", "simplef", "simplep", + "simple2", "simpleb2", "simplec2", "simplem2", "simplep2", + "simple_deop", "simpleb_deop", "simplec_deop", "simplef_deop", "simplep_deop", + "test", "testb", "testc", "testm", "testp", + "test2", "testb2", "testc2", "testm2", "testp2", + "test_deop", "testb_deop", "testc_deop", "testf_deop", "testp_deop", + "sum", "sumb", "sumc", "sumf", "sump", + "sum2", "sumb2", "sumc2", "summ2", "sump2", + "sum_deop", "sumb_deop", "sumc_deop", "sumf_deop", "sump_deop", + "remi_sum", "remi_sumb", "remi_sumc", "remi_sumf", "remi_sump", + "remi_sum2", "remi_sumb2", "remi_sumc2", "remi_summ2", "remi_sump2", + "remi_sum_deop", "remi_sumb_deop", "remi_sumc_deop", "remi_sumf_deop", "remi_sump_deop", + "remi_sum_cond", "remi_sumb_cond", "remi_sumc_cond", "remi_sumf_cond", "remi_sump_cond", + "remi_sum2_cond", "remi_sumb2_cond", "remi_sumc2_cond", "remi_summ2_cond", "remi_sump2_cond" + }; + + final int[] val = new int[] { + -5488, -5488, 12000, -5488, -5488, + 1024, 1024, -5552, 1024, 1024, + -5488, -5488, 12000, -5488, -5488, + 512, 512, 6256, 512, 512, + 13024, 13024, -5584, 13024, 13024, + 512, 512, 6256, 512, 512, + 45, 45, 45, 45, 45, + 66, 66, 66, 66, 66, + 45, 45, 45, 45, 45, + -23, -23, -23, -23, -23, + -70, -70, -70, -70, -70, + -23, -23, -23, -23, -23, + -11, -11, -11, -11, -11, + -34, -34, -34, -34, -34 + }; + + int[] res = new int[ntests]; + for (int i = 0; i < ntests; i++) { + res[i] = 0; + } + + + for (int i = 0; i < 12000; i++) { + res[0] += simple((byte)i); + res[1] += simpleb((byte)i); + res[2] += simplec(); + res[3] += simplef((byte)i); + res[4] += simplep((byte)i); + + res[5] += simple2((byte)i); + res[6] += simpleb2((byte)i); + res[7] += simplec2((byte)i); + res[8] += simplem2((byte)i); + res[9] += simplep2((byte)i, (byte)i); + + res[10] += simple_deop((byte)i); + res[11] += simpleb_deop((byte)i); + res[12] += simplec_deop((byte)i); + res[13] += simplef_deop((byte)i); + res[14] += simplep_deop((byte)i); + + res[15] += test((byte)i); + res[16] += testb((byte)i); + res[17] += testc((byte)i); + res[18] += testm((byte)i); + res[19] += testp((byte)i, (byte)i); + + res[20] += test2((byte)i); + res[21] += testb2((byte)i); + res[22] += testc2((byte)i); + res[23] += testm2((byte)i); + res[24] += testp2((byte)i, (byte)i); + + res[25] += test_deop((byte)i); + res[26] += testb_deop((byte)i); + res[27] += testc_deop((byte)i); + res[28] += testf_deop((byte)i); + res[29] += testp_deop((byte)i, (byte)i); + } + + byte[] ia = new byte[1000]; + for (int i = 0; i < 1000; i++) { + ia[i] = (byte)i; + } + + for (int i = 0; i < 100; i++) { + res[30] = sum(ia); + res[31] = sumb(ia); + res[32] = sumc(ia); + res[33] = sumf(ia); + res[34] = sump(ia, (byte)1); + + res[35] = sum2(ia); + res[36] = sumb2(ia); + res[37] = sumc2(ia); + res[38] = summ2(ia); + res[39] = sump2(ia, (byte)1); + + res[40] = sum_deop(ia); + res[41] = sumb_deop(ia); + res[42] = sumc_deop(ia); + res[43] = sumf_deop(ia); + res[44] = sump_deop(ia, (byte)1); + + res[45] = remi_sum(); + res[46] = remi_sumb(); + res[47] = remi_sumc(); + res[48] = remi_sumf(); + res[49] = remi_sump((byte)1); + + res[50] = remi_sum2(); + res[51] = remi_sumb2(); + res[52] = remi_sumc2(); + res[53] = remi_summ2(); + res[54] = remi_sump2((byte)1); + + res[55] = remi_sum_deop(); + res[56] = remi_sumb_deop(); + res[57] = remi_sumc_deop(); + res[58] = remi_sumf_deop(); + res[59] = remi_sump_deop((byte)1); + + res[60] = remi_sum_cond(); + res[61] = remi_sumb_cond(); + res[62] = remi_sumc_cond(); + res[63] = remi_sumf_cond(); + res[64] = remi_sump_cond((byte)1); + + res[65] = remi_sum2_cond(); + res[66] = remi_sumb2_cond(); + res[67] = remi_sumc2_cond(); + res[68] = remi_summ2_cond(); + res[69] = remi_sump2_cond((byte)1); + } + + int failed = 0; + for (int i = 0; i < ntests; i++) { + if (res[i] != val[i]) { + System.err.println(test_name[i] + ": " + res[i] + " != " + val[i]); + failed++; + } + } + if (failed > 0) { + System.err.println("Failed " + failed + " tests."); + throw new InternalError(); + } else { + System.out.println("Passed."); + } + } +} diff --git a/hotspot/test/compiler/6934604/TestDoubleBoxing.java b/hotspot/test/compiler/6934604/TestDoubleBoxing.java new file mode 100644 index 00000000000..7b76ac95655 --- /dev/null +++ b/hotspot/test/compiler/6934604/TestDoubleBoxing.java @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 6934604 + * @summary enable parts of EliminateAutoBox by default + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox TestDoubleBoxing + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox + * -XX:CompileCommand=exclude,TestDoubleBoxing.dummy -XX:CompileCommand=exclude,TestDoubleBoxing.foo -XX:CompileCommand=exclude,TestDoubleBoxing.foob TestDoubleBoxing + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-EliminateAutoBox + * -XX:CompileCommand=exclude,TestDoubleBoxing.dummy -XX:CompileCommand=exclude,TestDoubleBoxing.foo -XX:CompileCommand=exclude,TestDoubleBoxing.foob TestDoubleBoxing + * + */ + +public class TestDoubleBoxing { + + static final Double ibc = new Double(1.); + + //=============================================== + // Non-inlined methods to test deoptimization info + static void dummy() { } + static double foo(double i) { return i; } + static Double foob(double i) { return Double.valueOf(i); } + + + static double simple(double i) { + Double ib = new Double(i); + return ib; + } + + static double simpleb(double i) { + Double ib = Double.valueOf(i); + return ib; + } + + static double simplec() { + Double ib = ibc; + return ib; + } + + static double simplef(double i) { + Double ib = foob(i); + return ib; + } + + static double simplep(Double ib) { + return ib; + } + + static double simple2(double i) { + Double ib1 = new Double(i); + Double ib2 = new Double(i+1.); + return ib1 + ib2; + } + + static double simpleb2(double i) { + Double ib1 = Double.valueOf(i); + Double ib2 = Double.valueOf(i+1.); + return ib1 + ib2; + } + + static double simplem2(double i) { + Double ib1 = new Double(i); + Double ib2 = Double.valueOf(i+1.); + return ib1 + ib2; + } + + static double simplep2(double i, Double ib1) { + Double ib2 = Double.valueOf(i+1.); + return ib1 + ib2; + } + + static double simplec2(double i) { + Double ib1 = ibc; + Double ib2 = Double.valueOf(i+1.); + return ib1 + ib2; + } + + //=============================================== + static double test(double f, int i) { + Double ib = new Double(f); + if ((i&1) == 0) + ib = f+1.; + return ib; + } + + static double testb(double f, int i) { + Double ib = f; + if ((i&1) == 0) + ib = (f+1.); + return ib; + } + + static double testm(double f, int i) { + Double ib = f; + if ((i&1) == 0) + ib = new Double(f+1.); + return ib; + } + + static double testp(double f, int i, Double ib) { + if ((i&1) == 0) + ib = new Double(f+1.); + return ib; + } + + static double testc(double f, int i) { + Double ib = ibc; + if ((i&1) == 0) + ib = new Double(f+1.); + return ib; + } + + static double test2(double f, int i) { + Double ib1 = new Double(f); + Double ib2 = new Double(f+1.); + if ((i&1) == 0) { + ib1 = new Double(f+1.); + ib2 = new Double(f+2.); + } + return ib1+ib2; + } + + static double testb2(double f, int i) { + Double ib1 = f; + Double ib2 = f+1.; + if ((i&1) == 0) { + ib1 = (f+1.); + ib2 = (f+2.); + } + return ib1+ib2; + } + + static double testm2(double f, int i) { + Double ib1 = new Double(f); + Double ib2 = f+1.; + if ((i&1) == 0) { + ib1 = new Double(f+1.); + ib2 = (f+2.); + } + return ib1+ib2; + } + + static double testp2(double f, int i, Double ib1) { + Double ib2 = f+1.; + if ((i&1) == 0) { + ib1 = new Double(f+1.); + ib2 = (f+2.); + } + return ib1+ib2; + } + + static double testc2(double f, int i) { + Double ib1 = ibc; + Double ib2 = f+1.; + if ((i&1) == 0) { + ib1 = (ibc+1.); + ib2 = (f+2.); + } + return ib1+ib2; + } + + //=============================================== + static double sum(double[] a) { + double result = 1.; + for (Double i : a) + result += i; + return result; + } + + static double sumb(double[] a) { + Double result = 1.; + for (Double i : a) + result += i; + return result; + } + + static double sumc(double[] a) { + Double result = ibc; + for (Double i : a) + result += i; + return result; + } + + static double sumf(double[] a) { + Double result = foob(1.); + for (Double i : a) + result += i; + return result; + } + + static double sump(double[] a, Double result) { + for (Double i : a) + result += i; + return result; + } + + static double sum2(double[] a) { + double result1 = 1.; + double result2 = 1.; + for (Double i : a) { + result1 += i; + result2 += i + 1.; + } + return result1 + result2; + } + + static double sumb2(double[] a) { + Double result1 = 1.; + Double result2 = 1.; + for (Double i : a) { + result1 += i; + result2 += i + 1.; + } + return result1 + result2; + } + + static double summ2(double[] a) { + Double result1 = 1.; + Double result2 = new Double(1.); + for (Double i : a) { + result1 += i; + result2 += new Double(i + 1.); + } + return result1 + result2; + } + + static double sump2(double[] a, Double result2) { + Double result1 = 1.; + for (Double i : a) { + result1 += i; + result2 += i + 1.; + } + return result1 + result2; + } + + static double sumc2(double[] a) { + Double result1 = 1.; + Double result2 = ibc; + for (Double i : a) { + result1 += i; + result2 += i + ibc; + } + return result1 + result2; + } + + //=============================================== + static double remi_sum() { + Double j = new Double(1.); + for (int i = 0; i< 1000; i++) { + j = new Double(j + 1.); + } + return j; + } + + static double remi_sumb() { + Double j = Double.valueOf(1.); + for (int i = 0; i< 1000; i++) { + j = j + 1.; + } + return j; + } + + static double remi_sumf() { + Double j = foob(1.); + for (int i = 0; i< 1000; i++) { + j = j + 1.; + } + return j; + } + + static double remi_sump(Double j) { + for (int i = 0; i< 1000; i++) { + j = new Double(j + 1.); + } + return j; + } + + static double remi_sumc() { + Double j = ibc; + for (int i = 0; i< 1000; i++) { + j = j + ibc; + } + return j; + } + + static double remi_sum2() { + Double j1 = new Double(1.); + Double j2 = new Double(1.); + for (int i = 0; i< 1000; i++) { + j1 = new Double(j1 + 1.); + j2 = new Double(j2 + 2.); + } + return j1 + j2; + } + + static double remi_sumb2() { + Double j1 = Double.valueOf(1.); + Double j2 = Double.valueOf(1.); + for (int i = 0; i< 1000; i++) { + j1 = j1 + 1.; + j2 = j2 + 2.; + } + return j1 + j2; + } + + static double remi_summ2() { + Double j1 = new Double(1.); + Double j2 = Double.valueOf(1.); + for (int i = 0; i< 1000; i++) { + j1 = new Double(j1 + 1.); + j2 = j2 + 2.; + } + return j1 + j2; + } + + static double remi_sump2(Double j1) { + Double j2 = Double.valueOf(1.); + for (int i = 0; i< 1000; i++) { + j1 = new Double(j1 + 1.); + j2 = j2 + 2.; + } + return j1 + j2; + } + + static double remi_sumc2() { + Double j1 = ibc; + Double j2 = Double.valueOf(1.); + for (int i = 0; i< 1000; i++) { + j1 = j1 + ibc; + j2 = j2 + 2.; + } + return j1 + j2; + } + + + //=============================================== + // Safepointa and debug info for deoptimization + static double simple_deop(double i) { + Double ib = new Double(foo(i)); + dummy(); + return ib; + } + + static double simpleb_deop(double i) { + Double ib = Double.valueOf(foo(i)); + dummy(); + return ib; + } + + static double simplef_deop(double i) { + Double ib = foob(i); + dummy(); + return ib; + } + + static double simplep_deop(Double ib) { + dummy(); + return ib; + } + + static double simplec_deop(double i) { + Double ib = ibc; + dummy(); + return ib; + } + + static double test_deop(double f, int i) { + Double ib = new Double(foo(f)); + if ((i&1) == 0) + ib = foo(f+1.); + dummy(); + return ib; + } + + static double testb_deop(double f, int i) { + Double ib = foo(f); + if ((i&1) == 0) + ib = foo(f+1.); + dummy(); + return ib; + } + + static double testf_deop(double f, int i) { + Double ib = foob(f); + if ((i&1) == 0) + ib = foo(f+1.); + dummy(); + return ib; + } + + static double testp_deop(double f, int i, Double ib) { + if ((i&1) == 0) + ib = foo(f+1.); + dummy(); + return ib; + } + + static double testc_deop(double f, int i) { + Double ib = ibc; + if ((i&1) == 0) + ib = foo(f+1.); + dummy(); + return ib; + } + + static double sum_deop(double[] a) { + double result = 1.; + for (Double i : a) + result += foo(i); + dummy(); + return result; + } + + static double sumb_deop(double[] a) { + Double result = 1.; + for (Double i : a) + result += foo(i); + dummy(); + return result; + } + + static double sumf_deop(double[] a) { + Double result = 1.; + for (Double i : a) + result += foob(i); + dummy(); + return result; + } + + static double sump_deop(double[] a, Double result) { + for (Double i : a) + result += foob(i); + dummy(); + return result; + } + + static double sumc_deop(double[] a) { + Double result = ibc; + for (Double i : a) + result += foo(i); + dummy(); + return result; + } + + static double remi_sum_deop() { + Double j = new Double(foo(1.)); + for (int i = 0; i< 1000; i++) { + j = new Double(foo(j + 1.)); + } + dummy(); + return j; + } + + static double remi_sumb_deop() { + Double j = Double.valueOf(foo(1.)); + for (int i = 0; i< 1000; i++) { + j = foo(j + 1.); + } + dummy(); + return j; + } + + static double remi_sumf_deop() { + Double j = foob(1.); + for (int i = 0; i< 1000; i++) { + j = foo(j + 1.); + } + dummy(); + return j; + } + + static double remi_sump_deop(Double j) { + for (int i = 0; i< 1000; i++) { + j = foo(j + 1.); + } + dummy(); + return j; + } + + static double remi_sumc_deop() { + Double j = ibc; + for (int i = 0; i< 1000; i++) { + j = foo(j + 1.); + } + dummy(); + return j; + } + + //=============================================== + // Conditional increment + static double remi_sum_cond() { + Double j = new Double(1.); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = new Double(j + 1.); + } + } + return j; + } + + static double remi_sumb_cond() { + Double j = Double.valueOf(1.); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + 1.; + } + } + return j; + } + + static double remi_sumf_cond() { + Double j = foob(1.); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + 1.; + } + } + return j; + } + + static double remi_sump_cond(Double j) { + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + 1.; + } + } + return j; + } + + static double remi_sumc_cond() { + Double j = ibc; + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + ibc; + } + } + return j; + } + + static double remi_sum2_cond() { + Double j1 = new Double(1.); + Double j2 = new Double(1.); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Double(j1 + 1.); + } else { + j2 = new Double(j2 + 2.); + } + } + return j1 + j2; + } + + static double remi_sumb2_cond() { + Double j1 = Double.valueOf(1.); + Double j2 = Double.valueOf(1.); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = j1 + 1.; + } else { + j2 = j2 + 2.; + } + } + return j1 + j2; + } + + static double remi_summ2_cond() { + Double j1 = new Double(1.); + Double j2 = Double.valueOf(1.); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Double(j1 + 1.); + } else { + j2 = j2 + 2.; + } + } + return j1 + j2; + } + + static double remi_sump2_cond(Double j1) { + Double j2 = Double.valueOf(1.); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Double(j1 + 1.); + } else { + j2 = j2 + 2.; + } + } + return j1 + j2; + } + + static double remi_sumc2_cond() { + Double j1 = ibc; + Double j2 = Double.valueOf(1.); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = j1 + ibc; + } else { + j2 = j2 + 2; + } + } + return j1 + j2; + } + + + public static void main(String[] args) { + final int ntests = 70; + + String[] test_name = new String[] { + "simple", "simpleb", "simplec", "simplef", "simplep", + "simple2", "simpleb2", "simplec2", "simplem2", "simplep2", + "simple_deop", "simpleb_deop", "simplec_deop", "simplef_deop", "simplep_deop", + "test", "testb", "testc", "testm", "testp", + "test2", "testb2", "testc2", "testm2", "testp2", + "test_deop", "testb_deop", "testc_deop", "testf_deop", "testp_deop", + "sum", "sumb", "sumc", "sumf", "sump", + "sum2", "sumb2", "sumc2", "summ2", "sump2", + "sum_deop", "sumb_deop", "sumc_deop", "sumf_deop", "sump_deop", + "remi_sum", "remi_sumb", "remi_sumc", "remi_sumf", "remi_sump", + "remi_sum2", "remi_sumb2", "remi_sumc2", "remi_summ2", "remi_sump2", + "remi_sum_deop", "remi_sumb_deop", "remi_sumc_deop", "remi_sumf_deop", "remi_sump_deop", + "remi_sum_cond", "remi_sumb_cond", "remi_sumc_cond", "remi_sumf_cond", "remi_sump_cond", + "remi_sum2_cond", "remi_sumb2_cond", "remi_sumc2_cond", "remi_summ2_cond", "remi_sump2_cond" + }; + + final double[] val = new double[] { + 71994000., 71994000., 12000., 71994000., 71994000., + 144000000., 144000000., 72018000., 144000000., 144000000., + 71994000., 71994000., 12000., 71994000., 71994000., + 72000000., 72000000., 36006000., 72000000., 72000000., + 144012000., 144012000., 72030000., 144012000., 144012000., + 72000000., 72000000., 36006000., 72000000., 72000000., + 499501., 499501., 499501., 499501., 499501., + 1000002., 1000002., 1000002., 1000002., 1000002., + 499501., 499501., 499501., 499501., 499501., + 1001., 1001., 1001., 1001., 1001., + 3002., 3002., 3002., 3002., 3002., + 1001., 1001., 1001., 1001., 1001., + 501., 501., 501., 501., 501., + 1502., 1502., 1502., 1502., 1502. + }; + + double[] res = new double[ntests]; + for (int i = 0; i < ntests; i++) { + res[i] = 0.; + } + + + for (int i = 0; i < 12000; i++) { + res[0] += simple(i); + res[1] += simpleb(i); + res[2] += simplec(); + res[3] += simplef(i); + res[4] += simplep((double)i); + + res[5] += simple2((double)i); + res[6] += simpleb2((double)i); + res[7] += simplec2((double)i); + res[8] += simplem2((double)i); + res[9] += simplep2((double)i, (double)i); + + res[10] += simple_deop((double)i); + res[11] += simpleb_deop((double)i); + res[12] += simplec_deop((double)i); + res[13] += simplef_deop((double)i); + res[14] += simplep_deop((double)i); + + res[15] += test((double)i, i); + res[16] += testb((double)i, i); + res[17] += testc((double)i, i); + res[18] += testm((double)i, i); + res[19] += testp((double)i, i, (double)i); + + res[20] += test2((double)i, i); + res[21] += testb2((double)i, i); + res[22] += testc2((double)i, i); + res[23] += testm2((double)i, i); + res[24] += testp2((double)i, i, (double)i); + + res[25] += test_deop((double)i, i); + res[26] += testb_deop((double)i, i); + res[27] += testc_deop((double)i, i); + res[28] += testf_deop((double)i, i); + res[29] += testp_deop((double)i, i, (double)i); + } + + double[] ia = new double[1000]; + for (int i = 0; i < 1000; i++) { + ia[i] = i; + } + + for (int i = 0; i < 100; i++) { + res[30] = sum(ia); + res[31] = sumb(ia); + res[32] = sumc(ia); + res[33] = sumf(ia); + res[34] = sump(ia, 1.); + + res[35] = sum2(ia); + res[36] = sumb2(ia); + res[37] = sumc2(ia); + res[38] = summ2(ia); + res[39] = sump2(ia, 1.); + + res[40] = sum_deop(ia); + res[41] = sumb_deop(ia); + res[42] = sumc_deop(ia); + res[43] = sumf_deop(ia); + res[44] = sump_deop(ia, 1.); + + res[45] = remi_sum(); + res[46] = remi_sumb(); + res[47] = remi_sumc(); + res[48] = remi_sumf(); + res[49] = remi_sump(1.); + + res[50] = remi_sum2(); + res[51] = remi_sumb2(); + res[52] = remi_sumc2(); + res[53] = remi_summ2(); + res[54] = remi_sump2(1.); + + res[55] = remi_sum_deop(); + res[56] = remi_sumb_deop(); + res[57] = remi_sumc_deop(); + res[58] = remi_sumf_deop(); + res[59] = remi_sump_deop(1.); + + res[60] = remi_sum_cond(); + res[61] = remi_sumb_cond(); + res[62] = remi_sumc_cond(); + res[63] = remi_sumf_cond(); + res[64] = remi_sump_cond(1.); + + res[65] = remi_sum2_cond(); + res[66] = remi_sumb2_cond(); + res[67] = remi_sumc2_cond(); + res[68] = remi_summ2_cond(); + res[69] = remi_sump2_cond(1.); + } + + int failed = 0; + for (int i = 0; i < ntests; i++) { + if (res[i] != val[i]) { + System.err.println(test_name[i] + ": " + res[i] + " != " + val[i]); + failed++; + } + } + if (failed > 0) { + System.err.println("Failed " + failed + " tests."); + throw new InternalError(); + } else { + System.out.println("Passed."); + } + } +} diff --git a/hotspot/test/compiler/6934604/TestFloatBoxing.java b/hotspot/test/compiler/6934604/TestFloatBoxing.java new file mode 100644 index 00000000000..45716730109 --- /dev/null +++ b/hotspot/test/compiler/6934604/TestFloatBoxing.java @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 6934604 + * @summary enable parts of EliminateAutoBox by default + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox TestFloatBoxing + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox + * -XX:CompileCommand=exclude,TestFloatBoxing.dummy -XX:CompileCommand=exclude,TestFloatBoxing.foo -XX:CompileCommand=exclude,TestFloatBoxing.foob TestFloatBoxing + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-EliminateAutoBox + * -XX:CompileCommand=exclude,TestFloatBoxing.dummy -XX:CompileCommand=exclude,TestFloatBoxing.foo -XX:CompileCommand=exclude,TestFloatBoxing.foob TestFloatBoxing + * + */ + +public class TestFloatBoxing { + + static final Float ibc = new Float(1.f); + + //=============================================== + // Non-inlined methods to test deoptimization info + static void dummy() { } + static float foo(float i) { return i; } + static Float foob(float i) { return Float.valueOf(i); } + + + static float simple(float i) { + Float ib = new Float(i); + return ib; + } + + static float simpleb(float i) { + Float ib = Float.valueOf(i); + return ib; + } + + static float simplec() { + Float ib = ibc; + return ib; + } + + static float simplef(float i) { + Float ib = foob(i); + return ib; + } + + static float simplep(Float ib) { + return ib; + } + + static float simple2(float i) { + Float ib1 = new Float(i); + Float ib2 = new Float(i+1.f); + return ib1 + ib2; + } + + static float simpleb2(float i) { + Float ib1 = Float.valueOf(i); + Float ib2 = Float.valueOf(i+1.f); + return ib1 + ib2; + } + + static float simplem2(float i) { + Float ib1 = new Float(i); + Float ib2 = Float.valueOf(i+1.f); + return ib1 + ib2; + } + + static float simplep2(float i, Float ib1) { + Float ib2 = Float.valueOf(i+1.f); + return ib1 + ib2; + } + + static float simplec2(float i) { + Float ib1 = ibc; + Float ib2 = Float.valueOf(i+1.f); + return ib1 + ib2; + } + + //=============================================== + static float test(float f, int i) { + Float ib = new Float(f); + if ((i&1) == 0) + ib = f+1.f; + return ib; + } + + static float testb(float f, int i) { + Float ib = f; + if ((i&1) == 0) + ib = (f+1.f); + return ib; + } + + static float testm(float f, int i) { + Float ib = f; + if ((i&1) == 0) + ib = new Float(f+1.f); + return ib; + } + + static float testp(float f, int i, Float ib) { + if ((i&1) == 0) + ib = new Float(f+1.f); + return ib; + } + + static float testc(float f, int i) { + Float ib = ibc; + if ((i&1) == 0) + ib = new Float(f+1.f); + return ib; + } + + static float test2(float f, int i) { + Float ib1 = new Float(f); + Float ib2 = new Float(f+1.f); + if ((i&1) == 0) { + ib1 = new Float(f+1.f); + ib2 = new Float(f+2.f); + } + return ib1+ib2; + } + + static float testb2(float f, int i) { + Float ib1 = f; + Float ib2 = f+1.f; + if ((i&1) == 0) { + ib1 = (f+1.f); + ib2 = (f+2.f); + } + return ib1+ib2; + } + + static float testm2(float f, int i) { + Float ib1 = new Float(f); + Float ib2 = f+1.f; + if ((i&1) == 0) { + ib1 = new Float(f+1.f); + ib2 = (f+2.f); + } + return ib1+ib2; + } + + static float testp2(float f, int i, Float ib1) { + Float ib2 = f+1.f; + if ((i&1) == 0) { + ib1 = new Float(f+1.f); + ib2 = (f+2.f); + } + return ib1+ib2; + } + + static float testc2(float f, int i) { + Float ib1 = ibc; + Float ib2 = f+1.f; + if ((i&1) == 0) { + ib1 = (ibc+1.f); + ib2 = (f+2.f); + } + return ib1+ib2; + } + + //=============================================== + static float sum(float[] a) { + float result = 1.f; + for (Float i : a) + result += i; + return result; + } + + static float sumb(float[] a) { + Float result = 1.f; + for (Float i : a) + result += i; + return result; + } + + static float sumc(float[] a) { + Float result = ibc; + for (Float i : a) + result += i; + return result; + } + + static float sumf(float[] a) { + Float result = foob(1.f); + for (Float i : a) + result += i; + return result; + } + + static float sump(float[] a, Float result) { + for (Float i : a) + result += i; + return result; + } + + static float sum2(float[] a) { + float result1 = 1.f; + float result2 = 1.f; + for (Float i : a) { + result1 += i; + result2 += i + 1.f; + } + return result1 + result2; + } + + static float sumb2(float[] a) { + Float result1 = 1.f; + Float result2 = 1.f; + for (Float i : a) { + result1 += i; + result2 += i + 1.f; + } + return result1 + result2; + } + + static float summ2(float[] a) { + Float result1 = 1.f; + Float result2 = new Float(1.f); + for (Float i : a) { + result1 += i; + result2 += new Float(i + 1.f); + } + return result1 + result2; + } + + static float sump2(float[] a, Float result2) { + Float result1 = 1.f; + for (Float i : a) { + result1 += i; + result2 += i + 1.f; + } + return result1 + result2; + } + + static float sumc2(float[] a) { + Float result1 = 1.f; + Float result2 = ibc; + for (Float i : a) { + result1 += i; + result2 += i + ibc; + } + return result1 + result2; + } + + //=============================================== + static float remi_sum() { + Float j = new Float(1.f); + for (int i = 0; i< 1000; i++) { + j = new Float(j + 1.f); + } + return j; + } + + static float remi_sumb() { + Float j = Float.valueOf(1.f); + for (int i = 0; i< 1000; i++) { + j = j + 1.f; + } + return j; + } + + static float remi_sumf() { + Float j = foob(1.f); + for (int i = 0; i< 1000; i++) { + j = j + 1.f; + } + return j; + } + + static float remi_sump(Float j) { + for (int i = 0; i< 1000; i++) { + j = new Float(j + 1.f); + } + return j; + } + + static float remi_sumc() { + Float j = ibc; + for (int i = 0; i< 1000; i++) { + j = j + ibc; + } + return j; + } + + static float remi_sum2() { + Float j1 = new Float(1.f); + Float j2 = new Float(1.f); + for (int i = 0; i< 1000; i++) { + j1 = new Float(j1 + 1.f); + j2 = new Float(j2 + 2.f); + } + return j1 + j2; + } + + static float remi_sumb2() { + Float j1 = Float.valueOf(1.f); + Float j2 = Float.valueOf(1.f); + for (int i = 0; i< 1000; i++) { + j1 = j1 + 1.f; + j2 = j2 + 2.f; + } + return j1 + j2; + } + + static float remi_summ2() { + Float j1 = new Float(1.f); + Float j2 = Float.valueOf(1.f); + for (int i = 0; i< 1000; i++) { + j1 = new Float(j1 + 1.f); + j2 = j2 + 2.f; + } + return j1 + j2; + } + + static float remi_sump2(Float j1) { + Float j2 = Float.valueOf(1.f); + for (int i = 0; i< 1000; i++) { + j1 = new Float(j1 + 1.f); + j2 = j2 + 2.f; + } + return j1 + j2; + } + + static float remi_sumc2() { + Float j1 = ibc; + Float j2 = Float.valueOf(1.f); + for (int i = 0; i< 1000; i++) { + j1 = j1 + ibc; + j2 = j2 + 2.f; + } + return j1 + j2; + } + + + //=============================================== + // Safepointa and debug info for deoptimization + static float simple_deop(float i) { + Float ib = new Float(foo(i)); + dummy(); + return ib; + } + + static float simpleb_deop(float i) { + Float ib = Float.valueOf(foo(i)); + dummy(); + return ib; + } + + static float simplef_deop(float i) { + Float ib = foob(i); + dummy(); + return ib; + } + + static float simplep_deop(Float ib) { + dummy(); + return ib; + } + + static float simplec_deop(float i) { + Float ib = ibc; + dummy(); + return ib; + } + + static float test_deop(float f, int i) { + Float ib = new Float(foo(f)); + if ((i&1) == 0) + ib = foo(f+1.f); + dummy(); + return ib; + } + + static float testb_deop(float f, int i) { + Float ib = foo(f); + if ((i&1) == 0) + ib = foo(f+1.f); + dummy(); + return ib; + } + + static float testf_deop(float f, int i) { + Float ib = foob(f); + if ((i&1) == 0) + ib = foo(f+1.f); + dummy(); + return ib; + } + + static float testp_deop(float f, int i, Float ib) { + if ((i&1) == 0) + ib = foo(f+1.f); + dummy(); + return ib; + } + + static float testc_deop(float f, int i) { + Float ib = ibc; + if ((i&1) == 0) + ib = foo(f+1.f); + dummy(); + return ib; + } + + static float sum_deop(float[] a) { + float result = 1.f; + for (Float i : a) + result += foo(i); + dummy(); + return result; + } + + static float sumb_deop(float[] a) { + Float result = 1.f; + for (Float i : a) + result += foo(i); + dummy(); + return result; + } + + static float sumf_deop(float[] a) { + Float result = 1.f; + for (Float i : a) + result += foob(i); + dummy(); + return result; + } + + static float sump_deop(float[] a, Float result) { + for (Float i : a) + result += foob(i); + dummy(); + return result; + } + + static float sumc_deop(float[] a) { + Float result = ibc; + for (Float i : a) + result += foo(i); + dummy(); + return result; + } + + static float remi_sum_deop() { + Float j = new Float(foo(1.f)); + for (int i = 0; i< 1000; i++) { + j = new Float(foo(j + 1.f)); + } + dummy(); + return j; + } + + static float remi_sumb_deop() { + Float j = Float.valueOf(foo(1.f)); + for (int i = 0; i< 1000; i++) { + j = foo(j + 1.f); + } + dummy(); + return j; + } + + static float remi_sumf_deop() { + Float j = foob(1.f); + for (int i = 0; i< 1000; i++) { + j = foo(j + 1.f); + } + dummy(); + return j; + } + + static float remi_sump_deop(Float j) { + for (int i = 0; i< 1000; i++) { + j = foo(j + 1.f); + } + dummy(); + return j; + } + + static float remi_sumc_deop() { + Float j = ibc; + for (int i = 0; i< 1000; i++) { + j = foo(j + 1.f); + } + dummy(); + return j; + } + + //=============================================== + // Conditional increment + static float remi_sum_cond() { + Float j = new Float(1.f); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = new Float(j + 1.f); + } + } + return j; + } + + static float remi_sumb_cond() { + Float j = Float.valueOf(1.f); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + 1.f; + } + } + return j; + } + + static float remi_sumf_cond() { + Float j = foob(1.f); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + 1.f; + } + } + return j; + } + + static float remi_sump_cond(Float j) { + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + 1.f; + } + } + return j; + } + + static float remi_sumc_cond() { + Float j = ibc; + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + ibc; + } + } + return j; + } + + static float remi_sum2_cond() { + Float j1 = new Float(1.f); + Float j2 = new Float(1.f); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Float(j1 + 1.f); + } else { + j2 = new Float(j2 + 2.f); + } + } + return j1 + j2; + } + + static float remi_sumb2_cond() { + Float j1 = Float.valueOf(1.f); + Float j2 = Float.valueOf(1.f); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = j1 + 1.f; + } else { + j2 = j2 + 2.f; + } + } + return j1 + j2; + } + + static float remi_summ2_cond() { + Float j1 = new Float(1.f); + Float j2 = Float.valueOf(1.f); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Float(j1 + 1.f); + } else { + j2 = j2 + 2.f; + } + } + return j1 + j2; + } + + static float remi_sump2_cond(Float j1) { + Float j2 = Float.valueOf(1.f); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Float(j1 + 1.f); + } else { + j2 = j2 + 2.f; + } + } + return j1 + j2; + } + + static float remi_sumc2_cond() { + Float j1 = ibc; + Float j2 = Float.valueOf(1.f); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = j1 + ibc; + } else { + j2 = j2 + 2; + } + } + return j1 + j2; + } + + + public static void main(String[] args) { + final int ntests = 70; + + String[] test_name = new String[] { + "simple", "simpleb", "simplec", "simplef", "simplep", + "simple2", "simpleb2", "simplec2", "simplem2", "simplep2", + "simple_deop", "simpleb_deop", "simplec_deop", "simplef_deop", "simplep_deop", + "test", "testb", "testc", "testm", "testp", + "test2", "testb2", "testc2", "testm2", "testp2", + "test_deop", "testb_deop", "testc_deop", "testf_deop", "testp_deop", + "sum", "sumb", "sumc", "sumf", "sump", + "sum2", "sumb2", "sumc2", "summ2", "sump2", + "sum_deop", "sumb_deop", "sumc_deop", "sumf_deop", "sump_deop", + "remi_sum", "remi_sumb", "remi_sumc", "remi_sumf", "remi_sump", + "remi_sum2", "remi_sumb2", "remi_sumc2", "remi_summ2", "remi_sump2", + "remi_sum_deop", "remi_sumb_deop", "remi_sumc_deop", "remi_sumf_deop", "remi_sump_deop", + "remi_sum_cond", "remi_sumb_cond", "remi_sumc_cond", "remi_sumf_cond", "remi_sump_cond", + "remi_sum2_cond", "remi_sumb2_cond", "remi_sumc2_cond", "remi_summ2_cond", "remi_sump2_cond" + }; + + final float[] val = new float[] { + 71990896.f, 71990896.f, 12000.f, 71990896.f, 71990896.f, + 144000000.f, 144000000.f, 72014896.f, 144000000.f, 144000000.f, + 71990896.f, 71990896.f, 12000.f, 71990896.f, 71990896.f, + 72000000.f, 72000000.f, 36004096.f, 72000000.f, 72000000.f, + 144012288.f, 144012288.f, 72033096.f, 144012288.f, 144012288.f, + 72000000.f, 72000000.f, 36004096.f, 72000000.f, 72000000.f, + 499501.f, 499501.f, 499501.f, 499501.f, 499501.f, + 1000002.f, 1000002.f, 1000002.f, 1000002.f, 1000002.f, + 499501.f, 499501.f, 499501.f, 499501.f, 499501.f, + 1001.f, 1001.f, 1001.f, 1001.f, 1001.f, + 3002.f, 3002.f, 3002.f, 3002.f, 3002.f, + 1001.f, 1001.f, 1001.f, 1001.f, 1001.f, + 501.f, 501.f, 501.f, 501.f, 501.f, + 1502.f, 1502.f, 1502.f, 1502.f, 1502.f + }; + + float[] res = new float[ntests]; + for (int i = 0; i < ntests; i++) { + res[i] = 0.f; + } + + + for (int i = 0; i < 12000; i++) { + res[0] += simple(i); + res[1] += simpleb(i); + res[2] += simplec(); + res[3] += simplef(i); + res[4] += simplep((float)i); + + res[5] += simple2((float)i); + res[6] += simpleb2((float)i); + res[7] += simplec2((float)i); + res[8] += simplem2((float)i); + res[9] += simplep2((float)i, (float)i); + + res[10] += simple_deop((float)i); + res[11] += simpleb_deop((float)i); + res[12] += simplec_deop((float)i); + res[13] += simplef_deop((float)i); + res[14] += simplep_deop((float)i); + + res[15] += test((float)i, i); + res[16] += testb((float)i, i); + res[17] += testc((float)i, i); + res[18] += testm((float)i, i); + res[19] += testp((float)i, i, (float)i); + + res[20] += test2((float)i, i); + res[21] += testb2((float)i, i); + res[22] += testc2((float)i, i); + res[23] += testm2((float)i, i); + res[24] += testp2((float)i, i, (float)i); + + res[25] += test_deop((float)i, i); + res[26] += testb_deop((float)i, i); + res[27] += testc_deop((float)i, i); + res[28] += testf_deop((float)i, i); + res[29] += testp_deop((float)i, i, (float)i); + } + + float[] ia = new float[1000]; + for (int i = 0; i < 1000; i++) { + ia[i] = i; + } + + for (int i = 0; i < 100; i++) { + res[30] = sum(ia); + res[31] = sumb(ia); + res[32] = sumc(ia); + res[33] = sumf(ia); + res[34] = sump(ia, 1.f); + + res[35] = sum2(ia); + res[36] = sumb2(ia); + res[37] = sumc2(ia); + res[38] = summ2(ia); + res[39] = sump2(ia, 1.f); + + res[40] = sum_deop(ia); + res[41] = sumb_deop(ia); + res[42] = sumc_deop(ia); + res[43] = sumf_deop(ia); + res[44] = sump_deop(ia, 1.f); + + res[45] = remi_sum(); + res[46] = remi_sumb(); + res[47] = remi_sumc(); + res[48] = remi_sumf(); + res[49] = remi_sump(1.f); + + res[50] = remi_sum2(); + res[51] = remi_sumb2(); + res[52] = remi_sumc2(); + res[53] = remi_summ2(); + res[54] = remi_sump2(1.f); + + res[55] = remi_sum_deop(); + res[56] = remi_sumb_deop(); + res[57] = remi_sumc_deop(); + res[58] = remi_sumf_deop(); + res[59] = remi_sump_deop(1.f); + + res[60] = remi_sum_cond(); + res[61] = remi_sumb_cond(); + res[62] = remi_sumc_cond(); + res[63] = remi_sumf_cond(); + res[64] = remi_sump_cond(1.f); + + res[65] = remi_sum2_cond(); + res[66] = remi_sumb2_cond(); + res[67] = remi_sumc2_cond(); + res[68] = remi_summ2_cond(); + res[69] = remi_sump2_cond(1.f); + } + + int failed = 0; + for (int i = 0; i < ntests; i++) { + if (res[i] != val[i]) { + System.err.println(test_name[i] + ": " + res[i] + " != " + val[i]); + failed++; + } + } + if (failed > 0) { + System.err.println("Failed " + failed + " tests."); + throw new InternalError(); + } else { + System.out.println("Passed."); + } + } +} diff --git a/hotspot/test/compiler/6934604/TestIntBoxing.java b/hotspot/test/compiler/6934604/TestIntBoxing.java new file mode 100644 index 00000000000..d1ad10b070c --- /dev/null +++ b/hotspot/test/compiler/6934604/TestIntBoxing.java @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 6934604 + * @summary enable parts of EliminateAutoBox by default + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox TestIntBoxing + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox + * -XX:CompileCommand=exclude,TestIntBoxing.dummy -XX:CompileCommand=exclude,TestIntBoxing.foo -XX:CompileCommand=exclude,TestIntBoxing.foob TestIntBoxing + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-EliminateAutoBox + * -XX:CompileCommand=exclude,TestIntBoxing.dummy -XX:CompileCommand=exclude,TestIntBoxing.foo -XX:CompileCommand=exclude,TestIntBoxing.foob TestIntBoxing + * + */ + +public class TestIntBoxing { + + static final Integer ibc = new Integer(1); + + //=============================================== + // Non-inlined methods to test deoptimization info + static void dummy() { } + static int foo(int i) { return i; } + static Integer foob(int i) { return Integer.valueOf(i); } + + + static int simple(int i) { + Integer ib = new Integer(i); + return ib; + } + + static int simpleb(int i) { + Integer ib = Integer.valueOf(i); + return ib; + } + + static int simplec() { + Integer ib = ibc; + return ib; + } + + static int simplef(int i) { + Integer ib = foob(i); + return ib; + } + + static int simplep(Integer ib) { + return ib; + } + + static int simple2(int i) { + Integer ib1 = new Integer(i); + Integer ib2 = new Integer(i+1); + return ib1 + ib2; + } + + static int simpleb2(int i) { + Integer ib1 = Integer.valueOf(i); + Integer ib2 = Integer.valueOf(i+1); + return ib1 + ib2; + } + + static int simplem2(int i) { + Integer ib1 = new Integer(i); + Integer ib2 = Integer.valueOf(i+1); + return ib1 + ib2; + } + + static int simplep2(int i, Integer ib1) { + Integer ib2 = Integer.valueOf(i+1); + return ib1 + ib2; + } + + static int simplec2(int i) { + Integer ib1 = ibc; + Integer ib2 = Integer.valueOf(i+1); + return ib1 + ib2; + } + + //=============================================== + static int test(int i) { + Integer ib = new Integer(i); + if ((i&1) == 0) + ib = i+1; + return ib; + } + + static int testb(int i) { + Integer ib = i; + if ((i&1) == 0) + ib = (i+1); + return ib; + } + + static int testm(int i) { + Integer ib = i; + if ((i&1) == 0) + ib = new Integer(i+1); + return ib; + } + + static int testp(int i, Integer ib) { + if ((i&1) == 0) + ib = new Integer(i+1); + return ib; + } + + static int testc(int i) { + Integer ib = ibc; + if ((i&1) == 0) + ib = new Integer(i+1); + return ib; + } + + static int test2(int i) { + Integer ib1 = new Integer(i); + Integer ib2 = new Integer(i+1); + if ((i&1) == 0) { + ib1 = new Integer(i+1); + ib2 = new Integer(i+2); + } + return ib1+ib2; + } + + static int testb2(int i) { + Integer ib1 = i; + Integer ib2 = i+1; + if ((i&1) == 0) { + ib1 = (i+1); + ib2 = (i+2); + } + return ib1+ib2; + } + + static int testm2(int i) { + Integer ib1 = new Integer(i); + Integer ib2 = i+1; + if ((i&1) == 0) { + ib1 = new Integer(i+1); + ib2 = (i+2); + } + return ib1+ib2; + } + + static int testp2(int i, Integer ib1) { + Integer ib2 = i+1; + if ((i&1) == 0) { + ib1 = new Integer(i+1); + ib2 = (i+2); + } + return ib1+ib2; + } + + static int testc2(int i) { + Integer ib1 = ibc; + Integer ib2 = i+1; + if ((i&1) == 0) { + ib1 = (ibc+1); + ib2 = (i+2); + } + return ib1+ib2; + } + + //=============================================== + static int sum(int[] a) { + int result = 1; + for (Integer i : a) + result += i; + return result; + } + + static int sumb(int[] a) { + Integer result = 1; + for (Integer i : a) + result += i; + return result; + } + + static int sumc(int[] a) { + Integer result = ibc; + for (Integer i : a) + result += i; + return result; + } + + static int sumf(int[] a) { + Integer result = foob(1); + for (Integer i : a) + result += i; + return result; + } + + static int sump(int[] a, Integer result) { + for (Integer i : a) + result += i; + return result; + } + + static int sum2(int[] a) { + int result1 = 1; + int result2 = 1; + for (Integer i : a) { + result1 += i; + result2 += i + 1; + } + return result1 + result2; + } + + static int sumb2(int[] a) { + Integer result1 = 1; + Integer result2 = 1; + for (Integer i : a) { + result1 += i; + result2 += i + 1; + } + return result1 + result2; + } + + static int summ2(int[] a) { + Integer result1 = 1; + Integer result2 = new Integer(1); + for (Integer i : a) { + result1 += i; + result2 += new Integer(i + 1); + } + return result1 + result2; + } + + static int sump2(int[] a, Integer result2) { + Integer result1 = 1; + for (Integer i : a) { + result1 += i; + result2 += i + 1; + } + return result1 + result2; + } + + static int sumc2(int[] a) { + Integer result1 = 1; + Integer result2 = ibc; + for (Integer i : a) { + result1 += i; + result2 += i + ibc; + } + return result1 + result2; + } + + //=============================================== + static int remi_sum() { + Integer j = new Integer(1); + for (int i = 0; i< 1000; i++) { + j = new Integer(j + 1); + } + return j; + } + + static int remi_sumb() { + Integer j = Integer.valueOf(1); + for (int i = 0; i< 1000; i++) { + j = j + 1; + } + return j; + } + + static int remi_sumf() { + Integer j = foob(1); + for (int i = 0; i< 1000; i++) { + j = j + 1; + } + return j; + } + + static int remi_sump(Integer j) { + for (int i = 0; i< 1000; i++) { + j = new Integer(j + 1); + } + return j; + } + + static int remi_sumc() { + Integer j = ibc; + for (int i = 0; i< 1000; i++) { + j = j + ibc; + } + return j; + } + + static int remi_sum2() { + Integer j1 = new Integer(1); + Integer j2 = new Integer(1); + for (int i = 0; i< 1000; i++) { + j1 = new Integer(j1 + 1); + j2 = new Integer(j2 + 2); + } + return j1 + j2; + } + + static int remi_sumb2() { + Integer j1 = Integer.valueOf(1); + Integer j2 = Integer.valueOf(1); + for (int i = 0; i< 1000; i++) { + j1 = j1 + 1; + j2 = j2 + 2; + } + return j1 + j2; + } + + static int remi_summ2() { + Integer j1 = new Integer(1); + Integer j2 = Integer.valueOf(1); + for (int i = 0; i< 1000; i++) { + j1 = new Integer(j1 + 1); + j2 = j2 + 2; + } + return j1 + j2; + } + + static int remi_sump2(Integer j1) { + Integer j2 = Integer.valueOf(1); + for (int i = 0; i< 1000; i++) { + j1 = new Integer(j1 + 1); + j2 = j2 + 2; + } + return j1 + j2; + } + + static int remi_sumc2() { + Integer j1 = ibc; + Integer j2 = Integer.valueOf(1); + for (int i = 0; i< 1000; i++) { + j1 = j1 + ibc; + j2 = j2 + 2; + } + return j1 + j2; + } + + + //=============================================== + // Safepointa and debug info for deoptimization + static int simple_deop(int i) { + Integer ib = new Integer(foo(i)); + dummy(); + return ib; + } + + static int simpleb_deop(int i) { + Integer ib = Integer.valueOf(foo(i)); + dummy(); + return ib; + } + + static int simplef_deop(int i) { + Integer ib = foob(i); + dummy(); + return ib; + } + + static int simplep_deop(Integer ib) { + dummy(); + return ib; + } + + static int simplec_deop(int i) { + Integer ib = ibc; + dummy(); + return ib; + } + + static int test_deop(int i) { + Integer ib = new Integer(foo(i)); + if ((i&1) == 0) + ib = foo(i+1); + dummy(); + return ib; + } + + static int testb_deop(int i) { + Integer ib = foo(i); + if ((i&1) == 0) + ib = foo(i+1); + dummy(); + return ib; + } + + static int testf_deop(int i) { + Integer ib = foob(i); + if ((i&1) == 0) + ib = foo(i+1); + dummy(); + return ib; + } + + static int testp_deop(int i, Integer ib) { + if ((i&1) == 0) + ib = foo(i+1); + dummy(); + return ib; + } + + static int testc_deop(int i) { + Integer ib = ibc; + if ((i&1) == 0) + ib = foo(i+1); + dummy(); + return ib; + } + + static int sum_deop(int[] a) { + int result = 1; + for (Integer i : a) + result += foo(i); + dummy(); + return result; + } + + static int sumb_deop(int[] a) { + Integer result = 1; + for (Integer i : a) + result += foo(i); + dummy(); + return result; + } + + static int sumf_deop(int[] a) { + Integer result = 1; + for (Integer i : a) + result += foob(i); + dummy(); + return result; + } + + static int sump_deop(int[] a, Integer result) { + for (Integer i : a) + result += foob(i); + dummy(); + return result; + } + + static int sumc_deop(int[] a) { + Integer result = ibc; + for (Integer i : a) + result += foo(i); + dummy(); + return result; + } + + static int remi_sum_deop() { + Integer j = new Integer(foo(1)); + for (int i = 0; i< 1000; i++) { + j = new Integer(foo(j + 1)); + } + dummy(); + return j; + } + + static int remi_sumb_deop() { + Integer j = Integer.valueOf(foo(1)); + for (int i = 0; i< 1000; i++) { + j = foo(j + 1); + } + dummy(); + return j; + } + + static int remi_sumf_deop() { + Integer j = foob(1); + for (int i = 0; i< 1000; i++) { + j = foo(j + 1); + } + dummy(); + return j; + } + + static int remi_sump_deop(Integer j) { + for (int i = 0; i< 1000; i++) { + j = foo(j + 1); + } + dummy(); + return j; + } + + static int remi_sumc_deop() { + Integer j = ibc; + for (int i = 0; i< 1000; i++) { + j = foo(j + 1); + } + dummy(); + return j; + } + + //=============================================== + // Conditional increment + static int remi_sum_cond() { + Integer j = new Integer(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = new Integer(j + 1); + } + } + return j; + } + + static int remi_sumb_cond() { + Integer j = Integer.valueOf(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + 1; + } + } + return j; + } + + static int remi_sumf_cond() { + Integer j = foob(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + 1; + } + } + return j; + } + + static int remi_sump_cond(Integer j) { + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + 1; + } + } + return j; + } + + static int remi_sumc_cond() { + Integer j = ibc; + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + ibc; + } + } + return j; + } + + static int remi_sum2_cond() { + Integer j1 = new Integer(1); + Integer j2 = new Integer(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Integer(j1 + 1); + } else { + j2 = new Integer(j2 + 2); + } + } + return j1 + j2; + } + + static int remi_sumb2_cond() { + Integer j1 = Integer.valueOf(1); + Integer j2 = Integer.valueOf(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = j1 + 1; + } else { + j2 = j2 + 2; + } + } + return j1 + j2; + } + + static int remi_summ2_cond() { + Integer j1 = new Integer(1); + Integer j2 = Integer.valueOf(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Integer(j1 + 1); + } else { + j2 = j2 + 2; + } + } + return j1 + j2; + } + + static int remi_sump2_cond(Integer j1) { + Integer j2 = Integer.valueOf(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Integer(j1 + 1); + } else { + j2 = j2 + 2; + } + } + return j1 + j2; + } + + static int remi_sumc2_cond() { + Integer j1 = ibc; + Integer j2 = Integer.valueOf(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = j1 + ibc; + } else { + j2 = j2 + 2; + } + } + return j1 + j2; + } + + + public static void main(String[] args) { + final int ntests = 70; + + String[] test_name = new String[] { + "simple", "simpleb", "simplec", "simplef", "simplep", + "simple2", "simpleb2", "simplec2", "simplem2", "simplep2", + "simple_deop", "simpleb_deop", "simplec_deop", "simplef_deop", "simplep_deop", + "test", "testb", "testc", "testm", "testp", + "test2", "testb2", "testc2", "testm2", "testp2", + "test_deop", "testb_deop", "testc_deop", "testf_deop", "testp_deop", + "sum", "sumb", "sumc", "sumf", "sump", + "sum2", "sumb2", "sumc2", "summ2", "sump2", + "sum_deop", "sumb_deop", "sumc_deop", "sumf_deop", "sump_deop", + "remi_sum", "remi_sumb", "remi_sumc", "remi_sumf", "remi_sump", + "remi_sum2", "remi_sumb2", "remi_sumc2", "remi_summ2", "remi_sump2", + "remi_sum_deop", "remi_sumb_deop", "remi_sumc_deop", "remi_sumf_deop", "remi_sump_deop", + "remi_sum_cond", "remi_sumb_cond", "remi_sumc_cond", "remi_sumf_cond", "remi_sump_cond", + "remi_sum2_cond", "remi_sumb2_cond", "remi_sumc2_cond", "remi_summ2_cond", "remi_sump2_cond" + }; + + final int[] val = new int[] { + 71994000, 71994000, 12000, 71994000, 71994000, + 144000000, 144000000, 72018000, 144000000, 144000000, + 71994000, 71994000, 12000, 71994000, 71994000, + 72000000, 72000000, 36006000, 72000000, 72000000, + 144012000, 144012000, 72030000, 144012000, 144012000, + 72000000, 72000000, 36006000, 72000000, 72000000, + 499501, 499501, 499501, 499501, 499501, + 1000002, 1000002, 1000002, 1000002, 1000002, + 499501, 499501, 499501, 499501, 499501, + 1001, 1001, 1001, 1001, 1001, + 3002, 3002, 3002, 3002, 3002, + 1001, 1001, 1001, 1001, 1001, + 501, 501, 501, 501, 501, + 1502, 1502, 1502, 1502, 1502 + }; + + int[] res = new int[ntests]; + for (int i = 0; i < ntests; i++) { + res[i] = 0; + } + + + for (int i = 0; i < 12000; i++) { + res[0] += simple(i); + res[1] += simpleb(i); + res[2] += simplec(); + res[3] += simplef(i); + res[4] += simplep(i); + + res[5] += simple2(i); + res[6] += simpleb2(i); + res[7] += simplec2(i); + res[8] += simplem2(i); + res[9] += simplep2(i, i); + + res[10] += simple_deop(i); + res[11] += simpleb_deop(i); + res[12] += simplec_deop(i); + res[13] += simplef_deop(i); + res[14] += simplep_deop(i); + + res[15] += test(i); + res[16] += testb(i); + res[17] += testc(i); + res[18] += testm(i); + res[19] += testp(i, i); + + res[20] += test2(i); + res[21] += testb2(i); + res[22] += testc2(i); + res[23] += testm2(i); + res[24] += testp2(i, i); + + res[25] += test_deop(i); + res[26] += testb_deop(i); + res[27] += testc_deop(i); + res[28] += testf_deop(i); + res[29] += testp_deop(i, i); + } + + int[] ia = new int[1000]; + for (int i = 0; i < 1000; i++) { + ia[i] = i; + } + + for (int i = 0; i < 100; i++) { + res[30] = sum(ia); + res[31] = sumb(ia); + res[32] = sumc(ia); + res[33] = sumf(ia); + res[34] = sump(ia, 1); + + res[35] = sum2(ia); + res[36] = sumb2(ia); + res[37] = sumc2(ia); + res[38] = summ2(ia); + res[39] = sump2(ia, 1); + + res[40] = sum_deop(ia); + res[41] = sumb_deop(ia); + res[42] = sumc_deop(ia); + res[43] = sumf_deop(ia); + res[44] = sump_deop(ia, 1); + + res[45] = remi_sum(); + res[46] = remi_sumb(); + res[47] = remi_sumc(); + res[48] = remi_sumf(); + res[49] = remi_sump(1); + + res[50] = remi_sum2(); + res[51] = remi_sumb2(); + res[52] = remi_sumc2(); + res[53] = remi_summ2(); + res[54] = remi_sump2(1); + + res[55] = remi_sum_deop(); + res[56] = remi_sumb_deop(); + res[57] = remi_sumc_deop(); + res[58] = remi_sumf_deop(); + res[59] = remi_sump_deop(1); + + res[60] = remi_sum_cond(); + res[61] = remi_sumb_cond(); + res[62] = remi_sumc_cond(); + res[63] = remi_sumf_cond(); + res[64] = remi_sump_cond(1); + + res[65] = remi_sum2_cond(); + res[66] = remi_sumb2_cond(); + res[67] = remi_sumc2_cond(); + res[68] = remi_summ2_cond(); + res[69] = remi_sump2_cond(1); + } + + int failed = 0; + for (int i = 0; i < ntests; i++) { + if (res[i] != val[i]) { + System.err.println(test_name[i] + ": " + res[i] + " != " + val[i]); + failed++; + } + } + if (failed > 0) { + System.err.println("Failed " + failed + " tests."); + throw new InternalError(); + } else { + System.out.println("Passed."); + } + } +} diff --git a/hotspot/test/compiler/6934604/TestLongBoxing.java b/hotspot/test/compiler/6934604/TestLongBoxing.java new file mode 100644 index 00000000000..b92a01c962b --- /dev/null +++ b/hotspot/test/compiler/6934604/TestLongBoxing.java @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 6934604 + * @summary enable parts of EliminateAutoBox by default + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox TestLongBoxing + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox + * -XX:CompileCommand=exclude,TestLongBoxing.dummy -XX:CompileCommand=exclude,TestLongBoxing.foo -XX:CompileCommand=exclude,TestLongBoxing.foob TestLongBoxing + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-EliminateAutoBox + * -XX:CompileCommand=exclude,TestLongBoxing.dummy -XX:CompileCommand=exclude,TestLongBoxing.foo -XX:CompileCommand=exclude,TestLongBoxing.foob TestLongBoxing + * + */ + +public class TestLongBoxing { + + static final Long ibc = new Long(1); + + //=============================================== + // Non-inlined methods to test deoptimization info + static void dummy() { } + static long foo(long i) { return i; } + static Long foob(long i) { return Long.valueOf(i); } + + + static long simple(long i) { + Long ib = new Long(i); + return ib; + } + + static long simpleb(long i) { + Long ib = Long.valueOf(i); + return ib; + } + + static long simplec() { + Long ib = ibc; + return ib; + } + + static long simplef(long i) { + Long ib = foob(i); + return ib; + } + + static long simplep(Long ib) { + return ib; + } + + static long simple2(long i) { + Long ib1 = new Long(i); + Long ib2 = new Long(i+1); + return ib1 + ib2; + } + + static long simpleb2(long i) { + Long ib1 = Long.valueOf(i); + Long ib2 = Long.valueOf(i+1); + return ib1 + ib2; + } + + static long simplem2(long i) { + Long ib1 = new Long(i); + Long ib2 = Long.valueOf(i+1); + return ib1 + ib2; + } + + static long simplep2(long i, Long ib1) { + Long ib2 = Long.valueOf(i+1); + return ib1 + ib2; + } + + static long simplec2(long i) { + Long ib1 = ibc; + Long ib2 = Long.valueOf(i+1); + return ib1 + ib2; + } + + //=============================================== + static long test(long i) { + Long ib = new Long(i); + if ((i&1) == 0) + ib = i+1; + return ib; + } + + static long testb(long i) { + Long ib = i; + if ((i&1) == 0) + ib = (i+1); + return ib; + } + + static long testm(long i) { + Long ib = i; + if ((i&1) == 0) + ib = new Long(i+1); + return ib; + } + + static long testp(long i, Long ib) { + if ((i&1) == 0) + ib = new Long(i+1); + return ib; + } + + static long testc(long i) { + Long ib = ibc; + if ((i&1) == 0) + ib = new Long(i+1); + return ib; + } + + static long test2(long i) { + Long ib1 = new Long(i); + Long ib2 = new Long(i+1); + if ((i&1) == 0) { + ib1 = new Long(i+1); + ib2 = new Long(i+2); + } + return ib1+ib2; + } + + static long testb2(long i) { + Long ib1 = i; + Long ib2 = i+1; + if ((i&1) == 0) { + ib1 = (i+1); + ib2 = (i+2); + } + return ib1+ib2; + } + + static long testm2(long i) { + Long ib1 = new Long(i); + Long ib2 = i+1; + if ((i&1) == 0) { + ib1 = new Long(i+1); + ib2 = (i+2); + } + return ib1+ib2; + } + + static long testp2(long i, Long ib1) { + Long ib2 = i+1; + if ((i&1) == 0) { + ib1 = new Long(i+1); + ib2 = (i+2); + } + return ib1+ib2; + } + + static long testc2(long i) { + Long ib1 = ibc; + Long ib2 = i+1; + if ((i&1) == 0) { + ib1 = (ibc+1); + ib2 = (i+2); + } + return ib1+ib2; + } + + //=============================================== + static long sum(long[] a) { + long result = 1; + for (Long i : a) + result += i; + return result; + } + + static long sumb(long[] a) { + Long result = 1l; + for (Long i : a) + result += i; + return result; + } + + static long sumc(long[] a) { + Long result = ibc; + for (Long i : a) + result += i; + return result; + } + + static long sumf(long[] a) { + Long result = foob(1); + for (Long i : a) + result += i; + return result; + } + + static long sump(long[] a, Long result) { + for (Long i : a) + result += i; + return result; + } + + static long sum2(long[] a) { + long result1 = 1; + long result2 = 1; + for (Long i : a) { + result1 += i; + result2 += i + 1; + } + return result1 + result2; + } + + static long sumb2(long[] a) { + Long result1 = 1l; + Long result2 = 1l; + for (Long i : a) { + result1 += i; + result2 += i + 1; + } + return result1 + result2; + } + + static long summ2(long[] a) { + Long result1 = 1l; + Long result2 = new Long(1); + for (Long i : a) { + result1 += i; + result2 += new Long(i + 1); + } + return result1 + result2; + } + + static long sump2(long[] a, Long result2) { + Long result1 = 1l; + for (Long i : a) { + result1 += i; + result2 += i + 1; + } + return result1 + result2; + } + + static long sumc2(long[] a) { + Long result1 = 1l; + Long result2 = ibc; + for (Long i : a) { + result1 += i; + result2 += i + ibc; + } + return result1 + result2; + } + + //=============================================== + static long remi_sum() { + Long j = new Long(1); + for (int i = 0; i< 1000; i++) { + j = new Long(j + 1); + } + return j; + } + + static long remi_sumb() { + Long j = Long.valueOf(1); + for (int i = 0; i< 1000; i++) { + j = j + 1; + } + return j; + } + + static long remi_sumf() { + Long j = foob(1); + for (int i = 0; i< 1000; i++) { + j = j + 1; + } + return j; + } + + static long remi_sump(Long j) { + for (int i = 0; i< 1000; i++) { + j = new Long(j + 1); + } + return j; + } + + static long remi_sumc() { + Long j = ibc; + for (int i = 0; i< 1000; i++) { + j = j + ibc; + } + return j; + } + + static long remi_sum2() { + Long j1 = new Long(1); + Long j2 = new Long(1); + for (int i = 0; i< 1000; i++) { + j1 = new Long(j1 + 1); + j2 = new Long(j2 + 2); + } + return j1 + j2; + } + + static long remi_sumb2() { + Long j1 = Long.valueOf(1); + Long j2 = Long.valueOf(1); + for (int i = 0; i< 1000; i++) { + j1 = j1 + 1; + j2 = j2 + 2; + } + return j1 + j2; + } + + static long remi_summ2() { + Long j1 = new Long(1); + Long j2 = Long.valueOf(1); + for (int i = 0; i< 1000; i++) { + j1 = new Long(j1 + 1); + j2 = j2 + 2; + } + return j1 + j2; + } + + static long remi_sump2(Long j1) { + Long j2 = Long.valueOf(1); + for (int i = 0; i< 1000; i++) { + j1 = new Long(j1 + 1); + j2 = j2 + 2; + } + return j1 + j2; + } + + static long remi_sumc2() { + Long j1 = ibc; + Long j2 = Long.valueOf(1); + for (int i = 0; i< 1000; i++) { + j1 = j1 + ibc; + j2 = j2 + 2; + } + return j1 + j2; + } + + + //=============================================== + // Safepointa and debug info for deoptimization + static long simple_deop(long i) { + Long ib = new Long(foo(i)); + dummy(); + return ib; + } + + static long simpleb_deop(long i) { + Long ib = Long.valueOf(foo(i)); + dummy(); + return ib; + } + + static long simplef_deop(long i) { + Long ib = foob(i); + dummy(); + return ib; + } + + static long simplep_deop(Long ib) { + dummy(); + return ib; + } + + static long simplec_deop(long i) { + Long ib = ibc; + dummy(); + return ib; + } + + static long test_deop(long i) { + Long ib = new Long(foo(i)); + if ((i&1) == 0) + ib = foo(i+1); + dummy(); + return ib; + } + + static long testb_deop(long i) { + Long ib = foo(i); + if ((i&1) == 0) + ib = foo(i+1); + dummy(); + return ib; + } + + static long testf_deop(long i) { + Long ib = foob(i); + if ((i&1) == 0) + ib = foo(i+1); + dummy(); + return ib; + } + + static long testp_deop(long i, Long ib) { + if ((i&1) == 0) + ib = foo(i+1); + dummy(); + return ib; + } + + static long testc_deop(long i) { + Long ib = ibc; + if ((i&1) == 0) + ib = foo(i+1); + dummy(); + return ib; + } + + static long sum_deop(long[] a) { + long result = 1; + for (Long i : a) + result += foo(i); + dummy(); + return result; + } + + static long sumb_deop(long[] a) { + Long result = 1l; + for (Long i : a) + result += foo(i); + dummy(); + return result; + } + + static long sumf_deop(long[] a) { + Long result = 1l; + for (Long i : a) + result += foob(i); + dummy(); + return result; + } + + static long sump_deop(long[] a, Long result) { + for (Long i : a) + result += foob(i); + dummy(); + return result; + } + + static long sumc_deop(long[] a) { + Long result = ibc; + for (Long i : a) + result += foo(i); + dummy(); + return result; + } + + static long remi_sum_deop() { + Long j = new Long(foo(1)); + for (int i = 0; i< 1000; i++) { + j = new Long(foo(j + 1)); + } + dummy(); + return j; + } + + static long remi_sumb_deop() { + Long j = Long.valueOf(foo(1)); + for (int i = 0; i< 1000; i++) { + j = foo(j + 1); + } + dummy(); + return j; + } + + static long remi_sumf_deop() { + Long j = foob(1); + for (int i = 0; i< 1000; i++) { + j = foo(j + 1); + } + dummy(); + return j; + } + + static long remi_sump_deop(Long j) { + for (int i = 0; i< 1000; i++) { + j = foo(j + 1); + } + dummy(); + return j; + } + + static long remi_sumc_deop() { + Long j = ibc; + for (int i = 0; i< 1000; i++) { + j = foo(j + 1); + } + dummy(); + return j; + } + + //=============================================== + // Conditional increment + static long remi_sum_cond() { + Long j = new Long(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = new Long(j + 1); + } + } + return j; + } + + static long remi_sumb_cond() { + Long j = Long.valueOf(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + 1; + } + } + return j; + } + + static long remi_sumf_cond() { + Long j = foob(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + 1; + } + } + return j; + } + + static long remi_sump_cond(Long j) { + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + 1; + } + } + return j; + } + + static long remi_sumc_cond() { + Long j = ibc; + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = j + ibc; + } + } + return j; + } + + static long remi_sum2_cond() { + Long j1 = new Long(1); + Long j2 = new Long(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Long(j1 + 1); + } else { + j2 = new Long(j2 + 2); + } + } + return j1 + j2; + } + + static long remi_sumb2_cond() { + Long j1 = Long.valueOf(1); + Long j2 = Long.valueOf(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = j1 + 1; + } else { + j2 = j2 + 2; + } + } + return j1 + j2; + } + + static long remi_summ2_cond() { + Long j1 = new Long(1); + Long j2 = Long.valueOf(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Long(j1 + 1); + } else { + j2 = j2 + 2; + } + } + return j1 + j2; + } + + static long remi_sump2_cond(Long j1) { + Long j2 = Long.valueOf(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Long(j1 + 1); + } else { + j2 = j2 + 2; + } + } + return j1 + j2; + } + + static long remi_sumc2_cond() { + Long j1 = ibc; + Long j2 = Long.valueOf(1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = j1 + ibc; + } else { + j2 = j2 + 2; + } + } + return j1 + j2; + } + + + public static void main(String[] args) { + final int ntests = 70; + + String[] test_name = new String[] { + "simple", "simpleb", "simplec", "simplef", "simplep", + "simple2", "simpleb2", "simplec2", "simplem2", "simplep2", + "simple_deop", "simpleb_deop", "simplec_deop", "simplef_deop", "simplep_deop", + "test", "testb", "testc", "testm", "testp", + "test2", "testb2", "testc2", "testm2", "testp2", + "test_deop", "testb_deop", "testc_deop", "testf_deop", "testp_deop", + "sum", "sumb", "sumc", "sumf", "sump", + "sum2", "sumb2", "sumc2", "summ2", "sump2", + "sum_deop", "sumb_deop", "sumc_deop", "sumf_deop", "sump_deop", + "remi_sum", "remi_sumb", "remi_sumc", "remi_sumf", "remi_sump", + "remi_sum2", "remi_sumb2", "remi_sumc2", "remi_summ2", "remi_sump2", + "remi_sum_deop", "remi_sumb_deop", "remi_sumc_deop", "remi_sumf_deop", "remi_sump_deop", + "remi_sum_cond", "remi_sumb_cond", "remi_sumc_cond", "remi_sumf_cond", "remi_sump_cond", + "remi_sum2_cond", "remi_sumb2_cond", "remi_sumc2_cond", "remi_summ2_cond", "remi_sump2_cond" + }; + + final long[] val = new long[] { + 71994000, 71994000, 12000, 71994000, 71994000, + 144000000, 144000000, 72018000, 144000000, 144000000, + 71994000, 71994000, 12000, 71994000, 71994000, + 72000000, 72000000, 36006000, 72000000, 72000000, + 144012000, 144012000, 72030000, 144012000, 144012000, + 72000000, 72000000, 36006000, 72000000, 72000000, + 499501, 499501, 499501, 499501, 499501, + 1000002, 1000002, 1000002, 1000002, 1000002, + 499501, 499501, 499501, 499501, 499501, + 1001, 1001, 1001, 1001, 1001, + 3002, 3002, 3002, 3002, 3002, + 1001, 1001, 1001, 1001, 1001, + 501, 501, 501, 501, 501, + 1502, 1502, 1502, 1502, 1502 + }; + + long[] res = new long[ntests]; + for (int i = 0; i < ntests; i++) { + res[i] = 0; + } + + + for (long i = 0; i < 12000; i++) { + res[0] += simple(i); + res[1] += simpleb(i); + res[2] += simplec(); + res[3] += simplef(i); + res[4] += simplep(i); + + res[5] += simple2(i); + res[6] += simpleb2(i); + res[7] += simplec2(i); + res[8] += simplem2(i); + res[9] += simplep2(i, i); + + res[10] += simple_deop(i); + res[11] += simpleb_deop(i); + res[12] += simplec_deop(i); + res[13] += simplef_deop(i); + res[14] += simplep_deop(i); + + res[15] += test(i); + res[16] += testb(i); + res[17] += testc(i); + res[18] += testm(i); + res[19] += testp(i, i); + + res[20] += test2(i); + res[21] += testb2(i); + res[22] += testc2(i); + res[23] += testm2(i); + res[24] += testp2(i, i); + + res[25] += test_deop(i); + res[26] += testb_deop(i); + res[27] += testc_deop(i); + res[28] += testf_deop(i); + res[29] += testp_deop(i, i); + } + + long[] ia = new long[1000]; + for (int i = 0; i < 1000; i++) { + ia[i] = i; + } + + for (int i = 0; i < 100; i++) { + res[30] = sum(ia); + res[31] = sumb(ia); + res[32] = sumc(ia); + res[33] = sumf(ia); + res[34] = sump(ia, (long)1); + + res[35] = sum2(ia); + res[36] = sumb2(ia); + res[37] = sumc2(ia); + res[38] = summ2(ia); + res[39] = sump2(ia, (long)1); + + res[40] = sum_deop(ia); + res[41] = sumb_deop(ia); + res[42] = sumc_deop(ia); + res[43] = sumf_deop(ia); + res[44] = sump_deop(ia, (long)1); + + res[45] = remi_sum(); + res[46] = remi_sumb(); + res[47] = remi_sumc(); + res[48] = remi_sumf(); + res[49] = remi_sump((long)1); + + res[50] = remi_sum2(); + res[51] = remi_sumb2(); + res[52] = remi_sumc2(); + res[53] = remi_summ2(); + res[54] = remi_sump2((long)1); + + res[55] = remi_sum_deop(); + res[56] = remi_sumb_deop(); + res[57] = remi_sumc_deop(); + res[58] = remi_sumf_deop(); + res[59] = remi_sump_deop((long)1); + + res[60] = remi_sum_cond(); + res[61] = remi_sumb_cond(); + res[62] = remi_sumc_cond(); + res[63] = remi_sumf_cond(); + res[64] = remi_sump_cond((long)1); + + res[65] = remi_sum2_cond(); + res[66] = remi_sumb2_cond(); + res[67] = remi_sumc2_cond(); + res[68] = remi_summ2_cond(); + res[69] = remi_sump2_cond((long)1); + } + + int failed = 0; + for (int i = 0; i < ntests; i++) { + if (res[i] != val[i]) { + System.err.println(test_name[i] + ": " + res[i] + " != " + val[i]); + failed++; + } + } + if (failed > 0) { + System.err.println("Failed " + failed + " tests."); + throw new InternalError(); + } else { + System.out.println("Passed."); + } + } +} diff --git a/hotspot/test/compiler/6934604/TestShortBoxing.java b/hotspot/test/compiler/6934604/TestShortBoxing.java new file mode 100644 index 00000000000..0f065af3c63 --- /dev/null +++ b/hotspot/test/compiler/6934604/TestShortBoxing.java @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 6934604 + * @summary enable parts of EliminateAutoBox by default + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox TestShortBoxing + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox + * -XX:CompileCommand=exclude,TestShortBoxing.dummy -XX:CompileCommand=exclude,TestShortBoxing.foo -XX:CompileCommand=exclude,TestShortBoxing.foob TestShortBoxing + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-EliminateAutoBox + * -XX:CompileCommand=exclude,TestShortBoxing.dummy -XX:CompileCommand=exclude,TestShortBoxing.foo -XX:CompileCommand=exclude,TestShortBoxing.foob TestShortBoxing + * + */ + +public class TestShortBoxing { + + static final Short ibc = new Short((short)1); + + //=============================================== + // Non-inlined methods to test deoptimization info + static void dummy() { } + static short foo(short i) { return i; } + static Short foob(short i) { return Short.valueOf(i); } + + + static short simple(short i) { + Short ib = new Short(i); + return ib; + } + + static short simpleb(short i) { + Short ib = Short.valueOf(i); + return ib; + } + + static short simplec() { + Short ib = ibc; + return ib; + } + + static short simplef(short i) { + Short ib = foob(i); + return ib; + } + + static short simplep(Short ib) { + return ib; + } + + static short simple2(short i) { + Short ib1 = new Short(i); + Short ib2 = new Short((short)(i+1)); + return (short)(ib1 + ib2); + } + + static short simpleb2(short i) { + Short ib1 = Short.valueOf(i); + Short ib2 = Short.valueOf((short)(i+1)); + return (short)(ib1 + ib2); + } + + static short simplem2(short i) { + Short ib1 = new Short(i); + Short ib2 = Short.valueOf((short)(i+1)); + return (short)(ib1 + ib2); + } + + static short simplep2(short i, Short ib1) { + Short ib2 = Short.valueOf((short)(i+1)); + return (short)(ib1 + ib2); + } + + static short simplec2(short i) { + Short ib1 = ibc; + Short ib2 = Short.valueOf((short)(i+1)); + return (short)(ib1 + ib2); + } + + //=============================================== + static short test(short i) { + Short ib = new Short(i); + if ((i&1) == 0) + ib = (short)(i+1); + return ib; + } + + static short testb(short i) { + Short ib = i; + if ((i&1) == 0) + ib = (short)(i+1); + return ib; + } + + static short testm(short i) { + Short ib = i; + if ((i&1) == 0) + ib = new Short((short)(i+1)); + return ib; + } + + static short testp(short i, Short ib) { + if ((i&1) == 0) + ib = new Short((short)(i+1)); + return ib; + } + + static short testc(short i) { + Short ib = ibc; + if ((i&1) == 0) + ib = new Short((short)(i+1)); + return ib; + } + + static short test2(short i) { + Short ib1 = new Short(i); + Short ib2 = new Short((short)(i+1)); + if ((i&1) == 0) { + ib1 = new Short((short)(i+1)); + ib2 = new Short((short)(i+2)); + } + return (short)(ib1+ib2); + } + + static short testb2(short i) { + Short ib1 = i; + Short ib2 = (short)(i+1); + if ((i&1) == 0) { + ib1 = (short)(i+1); + ib2 = (short)(i+2); + } + return (short)(ib1 + ib2); + } + + static short testm2(short i) { + Short ib1 = new Short(i); + Short ib2 = (short)(i+1); + if ((i&1) == 0) { + ib1 = new Short((short)(i+1)); + ib2 = (short)(i+2); + } + return (short)(ib1 + ib2); + } + + static short testp2(short i, Short ib1) { + Short ib2 = (short)(i+1); + if ((i&1) == 0) { + ib1 = new Short((short)(i+1)); + ib2 = (short)(i+2); + } + return (short)(ib1 + ib2); + } + + static short testc2(short i) { + Short ib1 = ibc; + Short ib2 = (short)(i+1); + if ((i&1) == 0) { + ib1 = (short)(ibc+1); + ib2 = (short)(i+2); + } + return (short)(ib1 + ib2); + } + + //=============================================== + static short sum(short[] a) { + short result = 1; + for (Short i : a) + result += i; + return result; + } + + static short sumb(short[] a) { + Short result = 1; + for (Short i : a) + result = (short)(result + i); + return result; + } + + static short sumc(short[] a) { + Short result = ibc; + for (Short i : a) + result = (short)(result + i); + return result; + } + + static short sumf(short[] a) { + Short result = foob((short)1); + for (Short i : a) + result = (short)(result + i); + return result; + } + + static short sump(short[] a, Short result) { + for (Short i : a) + result = (short)(result + i); + return result; + } + + static short sum2(short[] a) { + short result1 = 1; + short result2 = 1; + for (Short i : a) { + result1 += i; + result2 += i + 1; + } + return (short)(result1 + result2); + } + + static short sumb2(short[] a) { + Short result1 = 1; + Short result2 = 1; + for (Short i : a) { + result1 = (short)(result1 + i); + result2 = (short)(result2 + i + 1); + } + return (short)(result1 + result2); + } + + static short summ2(short[] a) { + Short result1 = 1; + Short result2 = new Short((short)1); + for (Short i : a) { + result1 = (short)(result1 + i); + result2 = (short)(result2 + new Short((short)(i + 1))); + } + return (short)(result1 + result2); + } + + static short sump2(short[] a, Short result2) { + Short result1 = 1; + for (Short i : a) { + result1 = (short)(result1 + i); + result2 = (short)(result2 + i + 1); + } + return (short)(result1 + result2); + } + + static short sumc2(short[] a) { + Short result1 = 1; + Short result2 = ibc; + for (Short i : a) { + result1 = (short)(result1 + i); + result2 = (short)(result2 + i + ibc); + } + return (short)(result1 + result2); + } + + //=============================================== + static short remi_sum() { + Short j = new Short((short)1); + for (int i = 0; i< 1000; i++) { + j = new Short((short)(j + 1)); + } + return j; + } + + static short remi_sumb() { + Short j = Short.valueOf((short)1); + for (int i = 0; i< 1000; i++) { + j = (short)(j + 1); + } + return j; + } + + static short remi_sumf() { + Short j = foob((short)1); + for (int i = 0; i< 1000; i++) { + j = (short)(j + 1); + } + return j; + } + + static short remi_sump(Short j) { + for (int i = 0; i< 1000; i++) { + j = new Short((short)(j + 1)); + } + return j; + } + + static short remi_sumc() { + Short j = ibc; + for (int i = 0; i< 1000; i++) { + j = (short)(j + ibc); + } + return j; + } + + static short remi_sum2() { + Short j1 = new Short((short)1); + Short j2 = new Short((short)1); + for (int i = 0; i< 1000; i++) { + j1 = new Short((short)(j1 + 1)); + j2 = new Short((short)(j2 + 2)); + } + return (short)(j1 + j2); + } + + static short remi_sumb2() { + Short j1 = Short.valueOf((short)1); + Short j2 = Short.valueOf((short)1); + for (int i = 0; i< 1000; i++) { + j1 = (short)(j1 + 1); + j2 = (short)(j2 + 2); + } + return (short)(j1 + j2); + } + + static short remi_summ2() { + Short j1 = new Short((short)1); + Short j2 = Short.valueOf((short)1); + for (int i = 0; i< 1000; i++) { + j1 = new Short((short)(j1 + 1)); + j2 = (short)(j2 + 2); + } + return (short)(j1 + j2); + } + + static short remi_sump2(Short j1) { + Short j2 = Short.valueOf((short)1); + for (int i = 0; i< 1000; i++) { + j1 = new Short((short)(j1 + 1)); + j2 = (short)(j2 + 2); + } + return (short)(j1 + j2); + } + + static short remi_sumc2() { + Short j1 = ibc; + Short j2 = Short.valueOf((short)1); + for (int i = 0; i< 1000; i++) { + j1 = (short)(j1 + ibc); + j2 = (short)(j2 + 2); + } + return (short)(j1 + j2); + } + + + //=============================================== + // Safepointa and debug info for deoptimization + static short simple_deop(short i) { + Short ib = new Short(foo(i)); + dummy(); + return ib; + } + + static short simpleb_deop(short i) { + Short ib = Short.valueOf(foo(i)); + dummy(); + return ib; + } + + static short simplef_deop(short i) { + Short ib = foob(i); + dummy(); + return ib; + } + + static short simplep_deop(Short ib) { + dummy(); + return ib; + } + + static short simplec_deop(short i) { + Short ib = ibc; + dummy(); + return ib; + } + + static short test_deop(short i) { + Short ib = new Short(foo(i)); + if ((i&1) == 0) + ib = foo((short)(i+1)); + dummy(); + return ib; + } + + static short testb_deop(short i) { + Short ib = foo(i); + if ((i&1) == 0) + ib = foo((short)(i+1)); + dummy(); + return ib; + } + + static short testf_deop(short i) { + Short ib = foob(i); + if ((i&1) == 0) + ib = foo((short)(i+1)); + dummy(); + return ib; + } + + static short testp_deop(short i, Short ib) { + if ((i&1) == 0) + ib = foo((short)(i+1)); + dummy(); + return ib; + } + + static short testc_deop(short i) { + Short ib = ibc; + if ((i&1) == 0) + ib = foo((short)(i+1)); + dummy(); + return ib; + } + + static short sum_deop(short[] a) { + short result = 1; + for (Short i : a) + result += foo(i); + dummy(); + return result; + } + + static short sumb_deop(short[] a) { + Short result = 1; + for (Short i : a) + result = (short)(result + foo(i)); + dummy(); + return result; + } + + static short sumf_deop(short[] a) { + Short result = 1; + for (Short i : a) + result = (short)(result + foob(i)); + dummy(); + return result; + } + + static short sump_deop(short[] a, Short result) { + for (Short i : a) + result = (short)(result + foob(i)); + dummy(); + return result; + } + + static short sumc_deop(short[] a) { + Short result = ibc; + for (Short i : a) + result = (short)(result + foo(i)); + dummy(); + return result; + } + + static short remi_sum_deop() { + Short j = new Short(foo((short)1)); + for (int i = 0; i< 1000; i++) { + j = new Short(foo((short)(j + 1))); + } + dummy(); + return j; + } + + static short remi_sumb_deop() { + Short j = Short.valueOf(foo((short)1)); + for (int i = 0; i< 1000; i++) { + j = foo((short)(j + 1)); + } + dummy(); + return j; + } + + static short remi_sumf_deop() { + Short j = foob((short)1); + for (int i = 0; i< 1000; i++) { + j = foo((short)(j + 1)); + } + dummy(); + return j; + } + + static short remi_sump_deop(Short j) { + for (int i = 0; i< 1000; i++) { + j = foo((short)(j + 1)); + } + dummy(); + return j; + } + + static short remi_sumc_deop() { + Short j = ibc; + for (int i = 0; i< 1000; i++) { + j = foo((short)(j + 1)); + } + dummy(); + return j; + } + + //=============================================== + // Conditional increment + static short remi_sum_cond() { + Short j = new Short((short)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = new Short((short)(j + 1)); + } + } + return j; + } + + static short remi_sumb_cond() { + Short j = Short.valueOf((short)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = (short)(j + 1); + } + } + return j; + } + + static short remi_sumf_cond() { + Short j = foob((short)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = (short)(j + 1); + } + } + return j; + } + + static short remi_sump_cond(Short j) { + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = (short)(j + 1); + } + } + return j; + } + + static short remi_sumc_cond() { + Short j = ibc; + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j = (short)(j + ibc); + } + } + return j; + } + + static short remi_sum2_cond() { + Short j1 = new Short((short)1); + Short j2 = new Short((short)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Short((short)(j1 + 1)); + } else { + j2 = new Short((short)(j2 + 2)); + } + } + return (short)(j1 + j2); + } + + static short remi_sumb2_cond() { + Short j1 = Short.valueOf((short)1); + Short j2 = Short.valueOf((short)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = (short)(j1 + 1); + } else { + j2 = (short)(j2 + 2); + } + } + return (short)(j1 + j2); + } + + static short remi_summ2_cond() { + Short j1 = new Short((short)1); + Short j2 = Short.valueOf((short)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Short((short)(j1 + 1)); + } else { + j2 = (short)(j2 + 2); + } + } + return (short)(j1 + j2); + } + + static short remi_sump2_cond(Short j1) { + Short j2 = Short.valueOf((short)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = new Short((short)(j1 + 1)); + } else { + j2 = (short)(j2 + 2); + } + } + return (short)(j1 + j2); + } + + static short remi_sumc2_cond() { + Short j1 = ibc; + Short j2 = Short.valueOf((short)1); + for (int i = 0; i< 1000; i++) { + if ((i&1) == 0) { + j1 = (short)(j1 + ibc); + } else { + j2 = (short)(j2 + 2); + } + } + return (short)(j1 + j2); + } + + + public static void main(String[] args) { + final int ntests = 70; + + String[] test_name = new String[] { + "simple", "simpleb", "simplec", "simplef", "simplep", + "simple2", "simpleb2", "simplec2", "simplem2", "simplep2", + "simple_deop", "simpleb_deop", "simplec_deop", "simplef_deop", "simplep_deop", + "test", "testb", "testc", "testm", "testp", + "test2", "testb2", "testc2", "testm2", "testp2", + "test_deop", "testb_deop", "testc_deop", "testf_deop", "testp_deop", + "sum", "sumb", "sumc", "sumf", "sump", + "sum2", "sumb2", "sumc2", "summ2", "sump2", + "sum_deop", "sumb_deop", "sumc_deop", "sumf_deop", "sump_deop", + "remi_sum", "remi_sumb", "remi_sumc", "remi_sumf", "remi_sump", + "remi_sum2", "remi_sumb2", "remi_sumc2", "remi_summ2", "remi_sump2", + "remi_sum_deop", "remi_sumb_deop", "remi_sumc_deop", "remi_sumf_deop", "remi_sump_deop", + "remi_sum_cond", "remi_sumb_cond", "remi_sumc_cond", "remi_sumf_cond", "remi_sump_cond", + "remi_sum2_cond", "remi_sumb2_cond", "remi_sumc2_cond", "remi_summ2_cond", "remi_sump2_cond" + }; + + final int[] val = new int[] { + 71994000, 71994000, 12000, 71994000, 71994000, + 144000000, 144000000, 72018000, 144000000, 144000000, + 71994000, 71994000, 12000, 71994000, 71994000, + 72000000, 72000000, 36006000, 72000000, 72000000, + 144012000, 144012000, 72030000, 144012000, 144012000, + 72000000, 72000000, 36006000, 72000000, 72000000, + -24787, -24787, -24787, -24787, -24787, + 16962, 16962, 16962, 16962, 16962, + -24787, -24787, -24787, -24787, -24787, + 1001, 1001, 1001, 1001, 1001, + 3002, 3002, 3002, 3002, 3002, + 1001, 1001, 1001, 1001, 1001, + 501, 501, 501, 501, 501, + 1502, 1502, 1502, 1502, 1502 + }; + + int[] res = new int[ntests]; + for (int i = 0; i < ntests; i++) { + res[i] = 0; + } + + + for (int i = 0; i < 12000; i++) { + res[0] += simple((short)i); + res[1] += simpleb((short)i); + res[2] += simplec(); + res[3] += simplef((short)i); + res[4] += simplep((short)i); + + res[5] += simple2((short)i); + res[6] += simpleb2((short)i); + res[7] += simplec2((short)i); + res[8] += simplem2((short)i); + res[9] += simplep2((short)i, (short)i); + + res[10] += simple_deop((short)i); + res[11] += simpleb_deop((short)i); + res[12] += simplec_deop((short)i); + res[13] += simplef_deop((short)i); + res[14] += simplep_deop((short)i); + + res[15] += test((short)i); + res[16] += testb((short)i); + res[17] += testc((short)i); + res[18] += testm((short)i); + res[19] += testp((short)i, (short)i); + + res[20] += test2((short)i); + res[21] += testb2((short)i); + res[22] += testc2((short)i); + res[23] += testm2((short)i); + res[24] += testp2((short)i, (short)i); + + res[25] += test_deop((short)i); + res[26] += testb_deop((short)i); + res[27] += testc_deop((short)i); + res[28] += testf_deop((short)i); + res[29] += testp_deop((short)i, (short)i); + } + + short[] ia = new short[1000]; + for (int i = 0; i < 1000; i++) { + ia[i] = (short)i; + } + + for (int i = 0; i < 100; i++) { + res[30] = sum(ia); + res[31] = sumb(ia); + res[32] = sumc(ia); + res[33] = sumf(ia); + res[34] = sump(ia, (short)1); + + res[35] = sum2(ia); + res[36] = sumb2(ia); + res[37] = sumc2(ia); + res[38] = summ2(ia); + res[39] = sump2(ia, (short)1); + + res[40] = sum_deop(ia); + res[41] = sumb_deop(ia); + res[42] = sumc_deop(ia); + res[43] = sumf_deop(ia); + res[44] = sump_deop(ia, (short)1); + + res[45] = remi_sum(); + res[46] = remi_sumb(); + res[47] = remi_sumc(); + res[48] = remi_sumf(); + res[49] = remi_sump((short)1); + + res[50] = remi_sum2(); + res[51] = remi_sumb2(); + res[52] = remi_sumc2(); + res[53] = remi_summ2(); + res[54] = remi_sump2((short)1); + + res[55] = remi_sum_deop(); + res[56] = remi_sumb_deop(); + res[57] = remi_sumc_deop(); + res[58] = remi_sumf_deop(); + res[59] = remi_sump_deop((short)1); + + res[60] = remi_sum_cond(); + res[61] = remi_sumb_cond(); + res[62] = remi_sumc_cond(); + res[63] = remi_sumf_cond(); + res[64] = remi_sump_cond((short)1); + + res[65] = remi_sum2_cond(); + res[66] = remi_sumb2_cond(); + res[67] = remi_sumc2_cond(); + res[68] = remi_summ2_cond(); + res[69] = remi_sump2_cond((short)1); + } + + int failed = 0; + for (int i = 0; i < ntests; i++) { + if (res[i] != val[i]) { + System.err.println(test_name[i] + ": " + res[i] + " != " + val[i]); + failed++; + } + } + if (failed > 0) { + System.err.println("Failed " + failed + " tests."); + throw new InternalError(); + } else { + System.out.println("Passed."); + } + } +} diff --git a/hotspot/test/compiler/8009761/Test8009761.java b/hotspot/test/compiler/8009761/Test8009761.java index f588b82cd23..401458b6b92 100644 --- a/hotspot/test/compiler/8009761/Test8009761.java +++ b/hotspot/test/compiler/8009761/Test8009761.java @@ -25,7 +25,7 @@ * @test * @bug 8009761 * @summary Deoptimization on sparc doesn't set Llast_SP correctly in the interpreter frames it creates - * @run main/othervm -Xmixed -XX:-UseOnStackReplacement -XX:-BackgroundCompilation Test8009761 + * @run main/othervm -XX:CompileCommand=exclude,Test8009761::m2 -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -Xss256K Test8009761 * */ @@ -249,7 +249,7 @@ public class Test8009761 { System.out.println("Failed: init recursive calls: " + c1 + ". After deopt " + count); System.exit(97); } else { - System.out.println("PASSED"); + System.out.println("PASSED " + c1); } } } diff --git a/hotspot/test/compiler/ciReplay/TestSA.sh b/hotspot/test/compiler/ciReplay/TestSA.sh index daaec61d05a..6ea2c53a6ce 100644 --- a/hotspot/test/compiler/ciReplay/TestSA.sh +++ b/hotspot/test/compiler/ciReplay/TestSA.sh @@ -77,10 +77,11 @@ then "replay data wasn't generated by SA" fi -diff --brief ${replay_data} replay_vm.txt -if [ $? -ne 0 ] +diff ${replay_data} replay_vm.txt > replay.diff 2>&1 +if [ -s replay.diff ] then - echo WARNING: replay.txt from SA != replay.txt from VM + echo WARNING: replay.txt from SA != replay.txt from VM: + cat replay.diff fi common_tests 10 diff --git a/hotspot/test/compiler/ciReplay/common.sh b/hotspot/test/compiler/ciReplay/common.sh index 6b6ccd09b16..ec3b7fe33cf 100644 --- a/hotspot/test/compiler/ciReplay/common.sh +++ b/hotspot/test/compiler/ciReplay/common.sh @@ -182,8 +182,11 @@ echo "is_tiered=$is_tiered" # crash vm in compiler thread with generation replay data and 'small' dump-file # $@ - additional vm opts generate_replay() { - # enable core dump - ulimit -c unlimited + if [ $VM_OS != "windows" ] + then + # enable core dump + ulimit -c unlimited + fi cmd="${JAVA} ${TESTVMOPTS} $@ \ -Xms8m \ @@ -206,29 +209,24 @@ generate_replay() { echo GENERATION OF REPLAY.TXT: echo $cmd - ${cmd} 2>&1 > crash.out + ${cmd} > crash.out 2>&1 core_locations=`grep -i core crash.out | grep "location:" | \ sed -e 's/.*location: //'` rm crash.out # processing core locations for *nix - if [ $OS != "windows" ] + if [ $VM_OS != "windows" ] then # remove 'or' between '/core.' and 'core' core_locations=`echo $core_locations | \ sed -e 's/\([^ ]*\) or \([^ ]*\)/\1 \2/'` # add /core. core. - core=`echo $core_locations | awk '{print $1}'` - dir=`dirname $core` - core=`basename $core` - if [ -n ${core} ] + core_with_dir=`echo $core_locations | awk '{print $1}'` + dir=`dirname $core_with_dir` + core_with_pid=`echo $core_locations | awk '{print $2}'` + if [ -n ${core_with_pid} ] then - core_locations="$core_locations $dir${FS}$core" - fi - core=`echo $core_locations | awk '{print $2}'` - if [ -n ${core} ] - then - core_locations="$core_locations $dir${FS}$core" + core_locations="$core_locations $dir${FS}$core_with_pid $core_with_pid" fi fi diff --git a/hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java b/hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java new file mode 100644 index 00000000000..3dc688ce8ab --- /dev/null +++ b/hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* 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 TestCMSHeapSizeFlags + * @key gc + * @bug 8006088 + * @summary Tests argument processing for initial and maximum heap size for the CMS collector + * @library /testlibrary /testlibrary/whitebox + * @build TestCMSHeapSizeFlags TestMaxHeapSizeTools + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm TestCMSHeapSizeFlags + * @author thomas.schatzl@oracle.com + */ + +public class TestCMSHeapSizeFlags { + + public static void main(String args[]) throws Exception { + final String gcName = "-XX:+UseConcMarkSweepGC"; + + TestMaxHeapSizeTools.checkMinInitialMaxHeapFlags(gcName); + + TestMaxHeapSizeTools.checkGenMaxHeapErgo(gcName); + } +} + diff --git a/hotspot/test/gc/arguments/TestG1HeapSizeFlags.java b/hotspot/test/gc/arguments/TestG1HeapSizeFlags.java new file mode 100644 index 00000000000..31ab5e333c0 --- /dev/null +++ b/hotspot/test/gc/arguments/TestG1HeapSizeFlags.java @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* 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 TestG1HeapSizeFlags + * @key gc + * @bug 8006088 + * @summary Tests argument processing for initial and maximum heap size for the G1 collector + * @library /testlibrary /testlibrary/whitebox + * @build TestG1HeapSizeFlags TestMaxHeapSizeTools + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm TestG1HeapSizeFlags + * @author thomas.schatzl@oracle.com + */ + +public class TestG1HeapSizeFlags { + + public static void main(String args[]) throws Exception { + final String gcName = "-XX:+UseG1GC"; + + TestMaxHeapSizeTools.checkMinInitialMaxHeapFlags(gcName); + + TestMaxHeapSizeTools.checkGenMaxHeapErgo(gcName); + } +} + diff --git a/hotspot/test/gc/arguments/TestInitialTenuringThreshold.java b/hotspot/test/gc/arguments/TestInitialTenuringThreshold.java new file mode 100644 index 00000000000..2c97ccd8fff --- /dev/null +++ b/hotspot/test/gc/arguments/TestInitialTenuringThreshold.java @@ -0,0 +1,75 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* 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 TestInitialTenuringThreshold + * @key gc + * @bug 8014765 + * @summary Tests argument processing for initial tenuring threshold + * @library /testlibrary + * @run main/othervm TestInitialTenuringThreshold + * @author thomas.schatzl@oracle.com + */ + +import com.oracle.java.testlibrary.*; + +public class TestInitialTenuringThreshold { + + public static void runWithThresholds(int initial, int max, boolean shouldfail) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:InitialTenuringThreshold=" + String.valueOf(initial), + "-XX:MaxTenuringThreshold=" + String.valueOf(max), + "-version" + ); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + if (shouldfail) { + output.shouldHaveExitValue(1); + } else { + output.shouldHaveExitValue(0); + } + } + + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + // some value below the default value of InitialTenuringThreshold of 7 + "-XX:MaxTenuringThreshold=1", + "-version" + ); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + // successful tests + runWithThresholds(0, 10, false); + runWithThresholds(5, 5, false); + // failing tests + runWithThresholds(10, 0, true); + runWithThresholds(9, 8, true); + runWithThresholds(-1, 8, true); + runWithThresholds(8, -1, true); + runWithThresholds(8, 16, true); + runWithThresholds(16, 8, true); + } +} + diff --git a/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java b/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java new file mode 100644 index 00000000000..cb7d841355e --- /dev/null +++ b/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java @@ -0,0 +1,295 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* 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.regex.Matcher; +import java.util.regex.Pattern; +import java.util.ArrayList; +import java.util.Arrays; + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +class ErgoArgsPrinter { + public static void main(String[] args) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + wb.printHeapSizes(); + } +} + +final class MinInitialMaxValues { + public long minHeapSize; + public long initialHeapSize; + public long maxHeapSize; + + public long minAlignment; + public long maxAlignment; +} + +class TestMaxHeapSizeTools { + + public static void checkMinInitialMaxHeapFlags(String gcflag) throws Exception { + checkInvalidMinInitialHeapCombinations(gcflag); + checkValidMinInitialHeapCombinations(gcflag); + checkInvalidInitialMaxHeapCombinations(gcflag); + checkValidInitialMaxHeapCombinations(gcflag); + } + + public static void checkMinInitialErgonomics(String gcflag) throws Exception { + // heap sizing ergonomics use the value NewSize + OldSize as default values + // for ergonomics calculation. Retrieve these values. + long[] values = new long[2]; + getNewOldSize(gcflag, values); + + // we check cases with values smaller and larger than this default value. + long newPlusOldSize = values[0] + values[1]; + long smallValue = newPlusOldSize / 2; + long largeValue = newPlusOldSize * 2; + + // -Xms is not set + checkErgonomics(new String[] { gcflag, "-Xmx16M" }, values, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=0" }, values, -1, -1); + + // -Xms is set to zero + checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0" }, values, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=0" }, values, -1, -1); + + // -Xms is set to small value + checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue }, values, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=0" }, values, smallValue, -1); + + // -Xms is set to large value + checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue }, values, largeValue, largeValue); + // the next case has already been checked elsewhere and gives an error + // checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue); + // the next case has already been checked elsewhere too + // checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=" + largeValue }, values, values[0], largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=0" }, values, largeValue, -1); + } + + private static long align_up(long value, long alignment) { + long alignmentMinusOne = alignment - 1; + return (value + alignmentMinusOne) & ~alignmentMinusOne; + } + + private static void getNewOldSize(String gcflag, long[] values) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(gcflag, + "-XX:+PrintFlagsFinal", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + + String stdout = output.getStdout(); + values[0] = getFlagValue(" NewSize", stdout); + values[1] = getFlagValue(" OldSize", stdout); + } + + public static void checkGenMaxHeapErgo(String gcflag) throws Exception { + TestMaxHeapSizeTools.checkGenMaxHeapSize(gcflag, 3); + TestMaxHeapSizeTools.checkGenMaxHeapSize(gcflag, 4); + TestMaxHeapSizeTools.checkGenMaxHeapSize(gcflag, 5); + } + + private static void checkInvalidMinInitialHeapCombinations(String gcflag) throws Exception { + expectError(new String[] { gcflag, "-Xms8M", "-XX:InitialHeapSize=4M", "-version" }); + } + + private static void checkValidMinInitialHeapCombinations(String gcflag) throws Exception { + expectValid(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-Xms4M", "-version" }); + expectValid(new String[] { gcflag, "-Xms4M", "-XX:InitialHeapSize=8M", "-version" }); + expectValid(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-Xms8M", "-version" }); + // the following is not an error as -Xms sets both minimal and initial heap size + expectValid(new String[] { gcflag, "-XX:InitialHeapSize=4M", "-Xms8M", "-version" }); + } + + private static void checkInvalidInitialMaxHeapCombinations(String gcflag) throws Exception { + expectError(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:InitialHeapSize=8M", "-version" }); + expectError(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-XX:MaxHeapSize=4M", "-version" }); + } + + private static void checkValidInitialMaxHeapCombinations(String gcflag) throws Exception { + expectValid(new String[] { gcflag, "-XX:InitialHeapSize=4M", "-XX:MaxHeapSize=8M", "-version" }); + expectValid(new String[] { gcflag, "-XX:MaxHeapSize=8M", "-XX:InitialHeapSize=4M", "-version" }); + expectValid(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:InitialHeapSize=4M", "-version" }); + // a value of "0" for initial heap size means auto-detect + expectValid(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:InitialHeapSize=0M", "-version" }); + } + + private static long valueAfter(String source, String match) { + int start = source.indexOf(match) + match.length(); + String tail = source.substring(start).split(" ")[0]; + return Long.parseLong(tail); + } + + /** + * Executes a new VM process with the given class and parameters. + * @param vmargs Arguments to the VM to run + * @param classname Name of the class to run + * @param arguments Arguments to the class + * @param useTestDotJavaDotOpts Use test.java.opts as part of the VM argument string + * @return The OutputAnalyzer with the results for the invocation. + */ + public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, String[] arguments, boolean useTestDotJavaDotOpts) throws Exception { + ArrayList finalargs = new ArrayList(); + + String[] whiteboxOpts = new String[] { + "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", + "-cp", System.getProperty("java.class.path"), + }; + + if (useTestDotJavaDotOpts) { + // System.getProperty("test.java.opts") is '' if no options is set, + // we need to skip such a result + String[] externalVMOpts = new String[0]; + if (System.getProperty("test.java.opts") != null && System.getProperty("test.java.opts").length() != 0) { + externalVMOpts = System.getProperty("test.java.opts").split(" "); + } + finalargs.addAll(Arrays.asList(externalVMOpts)); + } + + finalargs.addAll(Arrays.asList(vmargs)); + finalargs.addAll(Arrays.asList(whiteboxOpts)); + finalargs.add(classname); + finalargs.addAll(Arrays.asList(arguments)); + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0])); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + + return output; + } + + private static void getMinInitialMaxHeap(String[] args, MinInitialMaxValues val) throws Exception { + OutputAnalyzer output = runWhiteBoxTest(args, ErgoArgsPrinter.class.getName(), new String[] {}, false); + + // the output we watch for has the following format: + // + // "Minimum heap X Initial heap Y Maximum heap Z Min alignment A Max Alignment B" + // + // where A, B, X, Y and Z are sizes in bytes. + // Unfortunately there is no other way to retrieve the minimum heap size and + // the alignments. + + Matcher m = Pattern.compile("Minimum heap \\d+ Initial heap \\d+ Maximum heap \\d+ Min alignment \\d+ Max alignment \\d+"). + matcher(output.getStdout()); + if (!m.find()) { + throw new RuntimeException("Could not find heap size string."); + } + + String match = m.group(); + + // actual values + val.minHeapSize = valueAfter(match, "Minimum heap "); + val.initialHeapSize = valueAfter(match, "Initial heap "); + val.maxHeapSize = valueAfter(match, "Maximum heap "); + val.minAlignment = valueAfter(match, "Min alignment "); + val.maxAlignment = valueAfter(match, "Max alignment "); + } + + /** + * Verify whether the VM automatically synchronizes minimum and initial heap size if only + * one is given for the GC specified. + */ + public static void checkErgonomics(String[] args, long[] newoldsize, + long expectedMin, long expectedInitial) throws Exception { + + MinInitialMaxValues v = new MinInitialMaxValues(); + getMinInitialMaxHeap(args, v); + + if ((expectedMin != -1) && (align_up(expectedMin, v.minAlignment) != v.minHeapSize)) { + throw new RuntimeException("Actual minimum heap size of " + v.minHeapSize + + " differs from expected minimum heap size of " + expectedMin); + } + + if ((expectedInitial != -1) && (align_up(expectedInitial, v.minAlignment) != v.initialHeapSize)) { + throw new RuntimeException("Actual initial heap size of " + v.initialHeapSize + + " differs from expected initial heap size of " + expectedInitial); + } + + // always check the invariant min <= initial <= max heap size + if (!(v.minHeapSize <= v.initialHeapSize && v.initialHeapSize <= v.maxHeapSize)) { + throw new RuntimeException("Inconsistent min/initial/max heap sizes, they are " + + v.minHeapSize + "/" + v.initialHeapSize + "/" + v.maxHeapSize); + } + } + + /** + * Verify whether the VM respects the given maximum heap size in MB for the + * GC specified. + * @param gcflag The garbage collector to test as command line flag. E.g. -XX:+UseG1GC + * @param maxHeapSize the maximum heap size to verify, in MB. + */ + public static void checkGenMaxHeapSize(String gcflag, long maxHeapsize) throws Exception { + final long K = 1024; + + MinInitialMaxValues v = new MinInitialMaxValues(); + getMinInitialMaxHeap(new String[] { gcflag, "-XX:MaxHeapSize=" + maxHeapsize + "M" }, v); + + long expectedHeapSize = align_up(maxHeapsize * K * K, v.maxAlignment); + long actualHeapSize = v.maxHeapSize; + + if (actualHeapSize > expectedHeapSize) { + throw new RuntimeException("Heap has " + actualHeapSize + + " bytes, expected to be less than " + expectedHeapSize); + } + } + + private static long getFlagValue(String flag, String where) { + Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where); + if (!m.find()) { + throw new RuntimeException("Could not find value for flag " + flag + " in output string"); + } + String match = m.group(); + return Long.parseLong(match.substring(match.lastIndexOf(" ") + 1, match.length())); + } + + private static void shouldContainOrNot(OutputAnalyzer output, boolean contains, String message) throws Exception { + if (contains) { + output.shouldContain(message); + } else { + output.shouldNotContain(message); + } + } + + private static void expect(String[] flags, boolean hasWarning, boolean hasError, int errorcode) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(flags); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + shouldContainOrNot(output, hasWarning, "Warning"); + shouldContainOrNot(output, hasError, "Error"); + output.shouldHaveExitValue(errorcode); + } + + private static void expectError(String[] flags) throws Exception { + expect(flags, false, true, 1); + } + + private static void expectValid(String[] flags) throws Exception { + expect(flags, false, false, 0); + } +} + diff --git a/hotspot/test/gc/arguments/TestMinInitialErgonomics.java b/hotspot/test/gc/arguments/TestMinInitialErgonomics.java new file mode 100644 index 00000000000..8352d92c8b0 --- /dev/null +++ b/hotspot/test/gc/arguments/TestMinInitialErgonomics.java @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* 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 TestMinInitialErgonomics + * @key gc + * @bug 8006088 + * @summary Test ergonomics decisions related to minimum and initial heap size. + * @library /testlibrary /testlibrary/whitebox + * @build TestMinInitialErgonomics TestMaxHeapSizeTools + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm TestMinInitialErgonomics + * @author thomas.schatzl@oracle.com + */ + +public class TestMinInitialErgonomics { + + public static void main(String args[]) throws Exception { + final String gcName = "-XX:+UseParallelGC"; + // check ergonomic decisions about minimum and initial heap size in + // a single gc only as ergonomics are the same everywhere. + TestMaxHeapSizeTools.checkMinInitialErgonomics(gcName); + } +} + diff --git a/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java new file mode 100644 index 00000000000..2de2826ed5b --- /dev/null +++ b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* 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 TestParallelHeapSizeFlags + * @key gc + * @bug 8006088 + * @summary Tests argument processing for initial and maximum heap size for the + * parallel collectors. + * @library /testlibrary /testlibrary/whitebox + * @build TestParallelHeapSizeFlags TestMaxHeapSizeTools + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm TestParallelHeapSizeFlags + * @author thomas.schatzl@oracle.com + */ + +public class TestParallelHeapSizeFlags { + + public static void main(String args[]) throws Exception { + // just pick one of the parallel generational collectors. Sizing logic is the + // same. + final String gcName = "-XX:+UseParallelOldGC"; + + TestMaxHeapSizeTools.checkMinInitialMaxHeapFlags(gcName); + + TestMaxHeapSizeTools.checkGenMaxHeapErgo(gcName); + } +} + diff --git a/hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java b/hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java new file mode 100644 index 00000000000..967adf64147 --- /dev/null +++ b/hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* 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 TestSerialHeapSizeFlags + * @key gc + * @bug 8006088 + * @summary Tests argument processing for initial and maximum heap size for the Serial collector + * @library /testlibrary /testlibrary/whitebox + * @build TestSerialHeapSizeFlags TestMaxHeapSizeTools + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm TestSerialHeapSizeFlags + * @author thomas.schatzl@oracle.com + */ + +public class TestSerialHeapSizeFlags { + + public static void main(String args[]) throws Exception { + final String gcName = "-XX:+UseSerialGC"; + + TestMaxHeapSizeTools.checkMinInitialMaxHeapFlags(gcName); + + TestMaxHeapSizeTools.checkGenMaxHeapErgo(gcName); + } +} + diff --git a/hotspot/test/gc/g1/TestPrintGCDetails.java b/hotspot/test/gc/g1/TestPrintGCDetails.java new file mode 100644 index 00000000000..4280a19cd25 --- /dev/null +++ b/hotspot/test/gc/g1/TestPrintGCDetails.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 TestPrintGCDetails + * @bug 8010738 + * @summary Ensure that the PrintGCDetails for a full GC with G1 includes Metaspace. + * @key gc + * @key regression + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.ProcessTools; +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class TestPrintGCDetails { + public static void main(String[] args) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", + "-XX:+PrintGCDetails", + SystemGCTest.class.getName()); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + System.out.println("Output:\n" + output.getOutput()); + + output.shouldContain("Metaspace"); + output.shouldHaveExitValue(0); + } + + static class SystemGCTest { + public static void main(String [] args) { + System.out.println("Calling System.gc()"); + System.gc(); + } + } +} diff --git a/hotspot/test/gc/g1/TestPrintRegionRememberedSetInfo.java b/hotspot/test/gc/g1/TestPrintRegionRememberedSetInfo.java new file mode 100644 index 00000000000..417b2cc1a39 --- /dev/null +++ b/hotspot/test/gc/g1/TestPrintRegionRememberedSetInfo.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 TestPrintRegionRememberedSetInfo + * @key gc + * @bug 8014240 + * @summary Test output of G1PrintRegionRememberedSetInfo + * @library /testlibrary + * @build TestPrintRegionRememberedSetInfo + * @author thomas.schatzl@oracle.com + */ + +import com.oracle.java.testlibrary.*; +import java.lang.Thread; +import java.util.ArrayList; +import java.util.Arrays; + +class RunAndWaitForMarking { + public static void main(String[] args) { + System.gc(); + try { + Thread.sleep(200); + } catch (InterruptedException e) { + } + } +} + +public class TestPrintRegionRememberedSetInfo { + + public static String runTest(String arg) throws Exception { + ArrayList finalargs = new ArrayList(); + String[] defaultArgs = new String[] { + "-XX:+UseG1GC", + "-Xmx10m", + "-XX:+ExplicitGCInvokesConcurrent", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+G1PrintRegionLivenessInfo", + "-XX:G1HeapRegionSize=1M", + "-XX:InitiatingHeapOccupancyPercent=0", + }; + + finalargs.addAll(Arrays.asList(defaultArgs)); + finalargs.add(arg); + + finalargs.add(RunAndWaitForMarking.class.getName()); + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + finalargs.toArray(new String[0])); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + + String result = output.getStdout(); + return result; + } + + public static void main(String[] args) throws Exception { + String result; + + result = runTest("-XX:+G1PrintRegionLivenessInfo"); + // check that we got region statistics output + if (result.indexOf("PHASE") == -1) { + throw new RuntimeException("Unexpected output from -XX:+PrintRegionLivenessInfo found."); + } + + result = runTest("-XX:-G1PrintRegionLivenessInfo"); + if (result.indexOf("remset") != -1) { + throw new RuntimeException("Should find remembered set information in output."); + } + } +} + diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 62e9fbe5fe0..7ba815339e0 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -211,3 +211,4 @@ ca71ec37b2efc9c3f0971ebabb3a6eb1213d76de jdk8-b86 eddbc8ad2435a89f64729512337c9f2669e4dd85 jdk8-b87 7122f7bb0fcc8a39e5254402119b2ee3fa0ad313 jdk8-b88 893d2ba8bbea3a8d090e51d8eaea285b390789ea jdk8-b89 +668acc0e1034bc1bec6d02be92e0dd4a63d0667e jdk8-b90 diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/generic/BasicType.java b/jaxp/src/com/sun/org/apache/bcel/internal/generic/BasicType.java index 978478476b6..c7340a62b15 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/generic/BasicType.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/generic/BasicType.java @@ -97,8 +97,14 @@ public final class BasicType extends Type { /** @return true if both type objects refer to the same type */ + @Override public boolean equals(Object type) { return (type instanceof BasicType)? ((BasicType)type).type == this.type : false; } + + @Override + public int hashCode() { + return type; + } } diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java b/jaxp/src/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java index d9a76251201..36960f8438f 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java @@ -93,6 +93,7 @@ public abstract class BranchInstruction extends Instruction implements Instructi * Dump instruction as byte code to stream out. * @param out Output stream */ + @Override public void dump(DataOutputStream out) throws IOException { out.writeByte(opcode); @@ -153,6 +154,7 @@ public abstract class BranchInstruction extends Instruction implements Instructi * @param verbose long/short format switch * @return mnemonic for instruction */ + @Override public String toString(boolean verbose) { String s = super.toString(verbose); String t = "null"; @@ -184,6 +186,7 @@ public abstract class BranchInstruction extends Instruction implements Instructi * @param wide wide prefix? * @see InstructionList */ + @Override protected void initFromFile(ByteSequence bytes, boolean wide) throws IOException { length = 3; @@ -204,26 +207,41 @@ public abstract class BranchInstruction extends Instruction implements Instructi * Set branch target * @param target branch target */ - public void setTarget(InstructionHandle target) { - notifyTarget(this.target, target, this); + public final void setTarget(InstructionHandle target) { + notifyTargetChanging(this.target, this); this.target = target; + notifyTargetChanged(this.target, this); } /** - * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen + * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen. + * Must be called before the target is actually changed in the + * InstructionTargeter. */ - static final void notifyTarget(InstructionHandle old_ih, InstructionHandle new_ih, + static void notifyTargetChanging(InstructionHandle old_ih, InstructionTargeter t) { - if(old_ih != null) + if(old_ih != null) { old_ih.removeTargeter(t); - if(new_ih != null) + } + } + + /** + * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen. + * Must be called after the target is actually changed in the + * InstructionTargeter. + */ + static void notifyTargetChanged(InstructionHandle new_ih, + InstructionTargeter t) { + if(new_ih != null) { new_ih.addTargeter(t); + } } /** * @param old_ih old target * @param new_ih new target */ + @Override public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) { if(target == old_ih) setTarget(new_ih); @@ -234,6 +252,7 @@ public abstract class BranchInstruction extends Instruction implements Instructi /** * @return true, if ih is target of this instruction */ + @Override public boolean containsTarget(InstructionHandle ih) { return (target == ih); } @@ -241,6 +260,7 @@ public abstract class BranchInstruction extends Instruction implements Instructi /** * Inform target that it's not targeted anymore. */ + @Override void dispose() { setTarget(null); index=-1; diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java b/jaxp/src/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java index 96c32fafdc2..0fb252ba576 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java @@ -58,7 +58,6 @@ package com.sun.org.apache.bcel.internal.generic; * . */ -import com.sun.org.apache.bcel.internal.Constants; import com.sun.org.apache.bcel.internal.classfile.*; /** @@ -118,31 +117,35 @@ public final class CodeExceptionGen /* Set start of handler * @param start_pc Start of handled region (inclusive) */ - public void setStartPC(InstructionHandle start_pc) { - BranchInstruction.notifyTarget(this.start_pc, start_pc, this); + public final void setStartPC(InstructionHandle start_pc) { + BranchInstruction.notifyTargetChanging(this.start_pc, this); this.start_pc = start_pc; + BranchInstruction.notifyTargetChanged(this.start_pc, this); } /* Set end of handler * @param end_pc End of handled region (inclusive) */ - public void setEndPC(InstructionHandle end_pc) { - BranchInstruction.notifyTarget(this.end_pc, end_pc, this); + public final void setEndPC(InstructionHandle end_pc) { + BranchInstruction.notifyTargetChanging(this.end_pc, this); this.end_pc = end_pc; + BranchInstruction.notifyTargetChanged(this.end_pc, this); } /* Set handler code * @param handler_pc Start of handler */ - public void setHandlerPC(InstructionHandle handler_pc) { - BranchInstruction.notifyTarget(this.handler_pc, handler_pc, this); + public final void setHandlerPC(InstructionHandle handler_pc) { + BranchInstruction.notifyTargetChanging(this.handler_pc, this); this.handler_pc = handler_pc; + BranchInstruction.notifyTargetChanged(this.handler_pc, this); } /** * @param old_ih old target, either start or end * @param new_ih new target */ + @Override public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) { boolean targeted = false; @@ -169,6 +172,7 @@ public final class CodeExceptionGen /** * @return true, if ih is target of this handler */ + @Override public boolean containsTarget(InstructionHandle ih) { return (start_pc == ih) || (end_pc == ih) || (handler_pc == ih); } @@ -190,10 +194,12 @@ public final class CodeExceptionGen */ public InstructionHandle getHandlerPC() { return handler_pc; } + @Override public String toString() { return "CodeExceptionGen(" + start_pc + ", " + end_pc + ", " + handler_pc + ")"; } + @Override public Object clone() { try { return super.clone(); diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java b/jaxp/src/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java index e191e01a056..a8427a8c812 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java @@ -58,7 +58,6 @@ package com.sun.org.apache.bcel.internal.generic; * . */ -import com.sun.org.apache.bcel.internal.Constants; import com.sun.org.apache.bcel.internal.classfile.*; /** @@ -88,6 +87,7 @@ public class LineNumberGen /** * @return true, if ih is target of this line number */ + @Override public boolean containsTarget(InstructionHandle ih) { return this.ih == ih; } @@ -96,6 +96,7 @@ public class LineNumberGen * @param old_ih old target * @param new_ih new target */ + @Override public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) { if(old_ih != ih) throw new ClassGenException("Not targeting " + old_ih + ", but " + ih + "}"); @@ -113,12 +114,13 @@ public class LineNumberGen return new LineNumber(ih.getPosition(), src_line); } - public void setInstruction(InstructionHandle ih) { - BranchInstruction.notifyTarget(this.ih, ih, this); - + public final void setInstruction(InstructionHandle ih) { + BranchInstruction.notifyTargetChanging(this.ih, this); this.ih = ih; + BranchInstruction.notifyTargetChanged(this.ih, this); } + @Override public Object clone() { try { return super.clone(); diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java b/jaxp/src/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java index d9a7130133a..1f2fd868e40 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java @@ -60,6 +60,7 @@ package com.sun.org.apache.bcel.internal.generic; import com.sun.org.apache.bcel.internal.Constants; import com.sun.org.apache.bcel.internal.classfile.*; +import java.util.Objects; /** * This class represents a local variable within a method. It contains its @@ -75,7 +76,7 @@ public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Cloneable, java.io.Serializable { - private int index; + private final int index; private String name; private Type type; private InstructionHandle start, end; @@ -131,30 +132,96 @@ public class LocalVariableGen signature_index, index, cp.getConstantPool()); } - public void setIndex(int index) { this.index = index; } - public int getIndex() { return index; } + public int getIndex() { return index; } + @Override public void setName(String name) { this.name = name; } + @Override public String getName() { return name; } + @Override public void setType(Type type) { this.type = type; } + @Override public Type getType() { return type; } public InstructionHandle getStart() { return start; } public InstructionHandle getEnd() { return end; } - public void setStart(InstructionHandle start) { - BranchInstruction.notifyTarget(this.start, start, this); - this.start = start; + /** + * Remove this from any known HashSet in which it might be registered. + */ + void notifyTargetChanging() { + // hashCode depends on 'index', 'start', and 'end'. + // Therefore before changing any of these values we + // need to unregister 'this' from any HashSet where + // this is registered, and then we need to add it + // back... + + // Unregister 'this' from the HashSet held by 'start'. + BranchInstruction.notifyTargetChanging(this.start, this); + if (this.end != this.start) { + // Since hashCode() is going to change we need to unregister + // 'this' both form 'start' and 'end'. + // Unregister 'this' from the HashSet held by 'end'. + BranchInstruction.notifyTargetChanging(this.end, this); + } } - public void setEnd(InstructionHandle end) { - BranchInstruction.notifyTarget(this.end, end, this); + /** + * Add back 'this' in all HashSet in which it should be registered. + **/ + void notifyTargetChanged() { + // hashCode depends on 'index', 'start', and 'end'. + // Therefore before changing any of these values we + // need to unregister 'this' from any HashSet where + // this is registered, and then we need to add it + // back... + + // Register 'this' in the HashSet held by start. + BranchInstruction.notifyTargetChanged(this.start, this); + if (this.end != this.start) { + // Since hashCode() has changed we need to register + // 'this' again in 'end'. + // Add back 'this' in the HashSet held by 'end'. + BranchInstruction.notifyTargetChanged(this.end, this); + } + } + + public final void setStart(InstructionHandle start) { + + // Call notifyTargetChanging *before* modifying this, + // as the code triggered by notifyTargetChanging + // depends on this pointing to the 'old' start. + notifyTargetChanging(); + + this.start = start; + + // call notifyTargetChanged *after* modifying this, + // as the code triggered by notifyTargetChanged + // depends on this pointing to the 'new' start. + notifyTargetChanged(); + } + + public final void setEnd(InstructionHandle end) { + // call notifyTargetChanging *before* modifying this, + // as the code triggered by notifyTargetChanging + // depends on this pointing to the 'old' end. + // Unregister 'this' from the HashSet held by the 'old' end. + notifyTargetChanging(); + this.end = end; + + // call notifyTargetChanged *after* modifying this, + // as the code triggered by notifyTargetChanged + // depends on this pointing to the 'new' end. + // Register 'this' in the HashSet held by the 'new' end. + notifyTargetChanged(); + } /** * @param old_ih old target, either start or end * @param new_ih new target */ + @Override public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) { boolean targeted = false; @@ -176,15 +243,20 @@ public class LocalVariableGen /** * @return true, if ih is target of this variable */ + @Override public boolean containsTarget(InstructionHandle ih) { return (start == ih) || (end == ih); } /** - * We consider to local variables to be equal, if the use the same index and + * We consider two local variables to be equal, if they use the same index and * are valid in the same range. */ + @Override public boolean equals(Object o) { + if (o==this) + return true; + if(!(o instanceof LocalVariableGen)) return false; @@ -192,10 +264,21 @@ public class LocalVariableGen return (l.index == index) && (l.start == start) && (l.end == end); } + @Override + public int hashCode() { + int hash = 7; + hash = 59 * hash + this.index; + hash = 59 * hash + Objects.hashCode(this.start); + hash = 59 * hash + Objects.hashCode(this.end); + return hash; + } + + @Override public String toString() { return "LocalVariableGen(" + name + ", " + type + ", " + start + ", " + end + ")"; } + @Override public Object clone() { try { return super.clone(); diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/generic/ReturnaddressType.java b/jaxp/src/com/sun/org/apache/bcel/internal/generic/ReturnaddressType.java index 659d7247ef8..501efdd09ec 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/generic/ReturnaddressType.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/generic/ReturnaddressType.java @@ -58,7 +58,7 @@ package com.sun.org.apache.bcel.internal.generic; * . */ import com.sun.org.apache.bcel.internal.Constants; -import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import java.util.Objects; /** * Returnaddress, the type JSR or JSR_W instructions push upon the stack. @@ -86,9 +86,15 @@ public class ReturnaddressType extends Type { this.returnTarget = returnTarget; } + @Override + public int hashCode() { + return Objects.hashCode(this.returnTarget); + } + /** * Returns if the two Returnaddresses refer to the same target. */ + @Override public boolean equals(Object rat){ if(!(rat instanceof ReturnaddressType)) return false; diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/generic/Select.java b/jaxp/src/com/sun/org/apache/bcel/internal/generic/Select.java index dfdf8a7a250..0cf47f634ca 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/generic/Select.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/generic/Select.java @@ -97,8 +97,9 @@ public abstract class Select extends BranchInstruction super(opcode, target); this.targets = targets; - for(int i=0; i < targets.length; i++) - notifyTarget(null, targets[i], this); + for(int i=0; i < targets.length; i++) { + BranchInstruction.notifyTargetChanged(targets[i], this); + } this.match = match; @@ -121,6 +122,7 @@ public abstract class Select extends BranchInstruction * @param max_offset the maximum offset that may be caused by these instructions * @return additional offset caused by possible change of this instruction's length */ + @Override protected int updatePosition(int offset, int max_offset) { position += offset; // Additional offset caused by preceding SWITCHs, GOTOs, etc. @@ -138,6 +140,7 @@ public abstract class Select extends BranchInstruction * Dump instruction as byte code to stream out. * @param out Output stream */ + @Override public void dump(DataOutputStream out) throws IOException { out.writeByte(opcode); @@ -151,6 +154,7 @@ public abstract class Select extends BranchInstruction /** * Read needed data (e.g. index) from file. */ + @Override protected void initFromFile(ByteSequence bytes, boolean wide) throws IOException { padding = (4 - (bytes.getIndex() % 4)) % 4; // Compute number of pad bytes @@ -166,8 +170,9 @@ public abstract class Select extends BranchInstruction /** * @return mnemonic for instruction */ + @Override public String toString(boolean verbose) { - StringBuffer buf = new StringBuffer(super.toString(verbose)); + final StringBuilder buf = new StringBuilder(super.toString(verbose)); if(verbose) { for(int i=0; i < match_length; i++) { @@ -176,7 +181,8 @@ public abstract class Select extends BranchInstruction if(targets[i] != null) s = targets[i].getInstruction().toString(); - buf.append("(" + match[i] + ", " + s + " = {" + indices[i] + "})"); + buf.append("(").append(match[i]).append(", ") + .append(s).append(" = {").append(indices[i]).append("})"); } } else @@ -188,15 +194,17 @@ public abstract class Select extends BranchInstruction /** * Set branch target for `i'th case */ - public void setTarget(int i, InstructionHandle target) { - notifyTarget(targets[i], target, this); + public final void setTarget(int i, InstructionHandle target) { + notifyTargetChanging(targets[i], this); targets[i] = target; + notifyTargetChanged(targets[i], this); } /** * @param old_ih old target * @param new_ih new target */ + @Override public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) { boolean targeted = false; @@ -219,6 +227,7 @@ public abstract class Select extends BranchInstruction /** * @return true, if ih is target of this instruction */ + @Override public boolean containsTarget(InstructionHandle ih) { if(target == ih) return true; @@ -233,6 +242,7 @@ public abstract class Select extends BranchInstruction /** * Inform targets that they're not targeted anymore. */ + @Override void dispose() { super.dispose(); diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/XalanConstants.java b/jaxp/src/com/sun/org/apache/xalan/internal/XalanConstants.java index 6fdccc023c7..82756c198ea 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/XalanConstants.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/XalanConstants.java @@ -25,9 +25,7 @@ package com.sun.org.apache.xalan.internal; -import com.sun.org.apache.xerces.internal.impl.*; -import java.util.Enumeration; -import java.util.NoSuchElementException; +import com.sun.org.apache.xalan.internal.utils.SecuritySupport; /** * Commonly used constants. @@ -42,19 +40,99 @@ public final class XalanConstants { // Constants // // Oracle Feature: - /** - *

Use Service Mechanism

- * - *
    - *
  • - * true instructs the implementation to use service mechanism to find implementation. - * This is the default behavior. + /** + *

    Use Service Mechanism

    + * + *
      + *
    • + * {@code true} instruct an object to use service mechanism to + * find a service implementation. This is the default behavior. *
    • *
    • - * false instructs the implementation to skip service mechanism and use the default implementation. - *
    • - *
    - */ + * {@code false} instruct an object to skip service mechanism and + * use the default implementation for that service. + *
  • + *
+ */ + public static final String ORACLE_FEATURE_SERVICE_MECHANISM = "http://www.oracle.com/feature/use-service-mechanism"; + /** Oracle JAXP property prefix ("http://www.oracle.com/xml/jaxp/properties/"). */ + public static final String ORACLE_JAXP_PROPERTY_PREFIX = + "http://www.oracle.com/xml/jaxp/properties/"; + + //System Properties corresponding to ACCESS_EXTERNAL_* properties + public static final String SP_ACCESS_EXTERNAL_STYLESHEET = "javax.xml.accessExternalStylesheet"; + public static final String SP_ACCESS_EXTERNAL_DTD = "javax.xml.accessExternalDTD"; + + + //all access keyword + public static final String ACCESS_EXTERNAL_ALL = "all"; + + /** + * Default value when FEATURE_SECURE_PROCESSING (FSP) is set to true + */ + public static final String EXTERNAL_ACCESS_DEFAULT_FSP = ""; + /** + * JDK version by which the default is to restrict external connection + */ + public static final int RESTRICT_BY_DEFAULT_JDK_VERSION = 8; + /** + * FEATURE_SECURE_PROCESSING (FSP) is false by default + */ + public static final String EXTERNAL_ACCESS_DEFAULT = getExternalAccessDefault(false); + + /** + * Determine the default value of the external access properties + * + * jaxp 1.5 does not require implementations to restrict by default + * + * For JDK8: + * The default value is 'file' (including jar:file); The keyword "all" grants permission + * to all protocols. When {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} is on, + * the default value is an empty string indicating no access is allowed. + * + * For JDK7: + * The default value is 'all' granting permission to all protocols. If by default, + * {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} is true, it should + * not change the default value. However, if {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} + * is set explicitly, the values of the properties shall be set to an empty string + * indicating no access is allowed. + * + * @param isSecureProcessing indicating if Secure Processing is set + * @return default value + */ + public static String getExternalAccessDefault(boolean isSecureProcessing) { + String defaultValue = "all"; + if (isJDKandAbove(RESTRICT_BY_DEFAULT_JDK_VERSION)) { + defaultValue = "file"; + if (isSecureProcessing) { + defaultValue = EXTERNAL_ACCESS_DEFAULT_FSP; + } + } + return defaultValue; + } + + /* + * Check the version of the current JDK against that specified in the + * parameter + * + * There is a proposal to change the java version string to: + * MAJOR.MINOR.FU.CPU.PSU-BUILDNUMBER_BUGIDNUMBER_OPTIONAL + * This method would work with both the current format and that proposed + * + * @param compareTo a JDK version to be compared to + * @return true if the current version is the same or above that represented + * by the parameter + */ + public static boolean isJDKandAbove(int compareTo) { + String javaVersion = SecuritySupport.getSystemProperty("java.version"); + String versions[] = javaVersion.split("\\.", 3); + if (Integer.parseInt(versions[0]) >= compareTo || + Integer.parseInt(versions[1]) >= compareTo) { + return true; + } + return false; + } + } // class Constants diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/utils/SecuritySupport.java b/jaxp/src/com/sun/org/apache/xalan/internal/utils/SecuritySupport.java index b813b4c0d28..e418fd55275 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/utils/SecuritySupport.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/utils/SecuritySupport.java @@ -26,7 +26,9 @@ package com.sun.org.apache.xalan.internal.utils; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.IOException; import java.io.InputStream; +import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; @@ -36,6 +38,7 @@ import java.util.ListResourceBundle; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; +import java.util.Properties; /** * This class is duplicated for each subpackage so keep it in sync. It is @@ -200,7 +203,141 @@ public final class SecuritySupport { })).longValue(); } - - private SecuritySupport() { + /** + * Strip off path from an URI + * + * @param uri an URI with full path + * @return the file name only + */ + public static String sanitizePath(String uri) { + if (uri == null) { + return ""; + } + int i = uri.lastIndexOf("/"); + if (i > 0) { + return uri.substring(i+1, uri.length()); + } + return ""; } + + /** + * Check the protocol used in the systemId against allowed protocols + * + * @param systemId the Id of the URI + * @param allowedProtocols a list of allowed protocols separated by comma + * @param accessAny keyword to indicate allowing any protocol + * @return the name of the protocol if rejected, null otherwise + */ + public static String checkAccess(String systemId, String allowedProtocols, String accessAny) throws IOException { + if (systemId == null || allowedProtocols.equalsIgnoreCase(accessAny)) { + return null; + } + + String protocol; + if (systemId.indexOf(":")==-1) { + protocol = "file"; + } else { + URL url = new URL(systemId); + protocol = url.getProtocol(); + if (protocol.equalsIgnoreCase("jar")) { + String path = url.getPath(); + protocol = path.substring(0, path.indexOf(":")); + } + } + + if (isProtocolAllowed(protocol, allowedProtocols)) { + //access allowed + return null; + } else { + return protocol; + } + } + + /** + * Check if the protocol is in the allowed list of protocols. The check + * is case-insensitive while ignoring whitespaces. + * + * @param protocol a protocol + * @param allowedProtocols a list of allowed protocols + * @return true if the protocol is in the list + */ + private static boolean isProtocolAllowed(String protocol, String allowedProtocols) { + String temp[] = allowedProtocols.split(","); + for (String t : temp) { + t = t.trim(); + if (t.equalsIgnoreCase(protocol)) { + return true; + } + } + return false; + } + + /** + * Read from $java.home/lib/jaxp.properties for the specified property + * + * @param propertyId the Id of the property + * @return the value of the property + */ + public static String getDefaultAccessProperty(String sysPropertyId, String defaultVal) { + String accessExternal = SecuritySupport.getSystemProperty(sysPropertyId); + if (accessExternal == null) { + accessExternal = readJAXPProperty(sysPropertyId); + if (accessExternal == null) { + accessExternal = defaultVal; + } + } + return accessExternal; + } + + /** + * Read from $java.home/lib/jaxp.properties for the specified property + * The program + * + * @param propertyId the Id of the property + * @return the value of the property + */ + static String readJAXPProperty(String propertyId) { + String value = null; + InputStream is = null; + try { + if (firstTime) { + synchronized (cacheProps) { + if (firstTime) { + String configFile = getSystemProperty("java.home") + File.separator + + "lib" + File.separator + "jaxp.properties"; + File f = new File(configFile); + if (getFileExists(f)) { + is = getFileInputStream(f); + cacheProps.load(is); + } + firstTime = false; + } + } + } + value = cacheProps.getProperty(propertyId); + + } + catch (Exception ex) {} + finally { + if (is != null) { + try { + is.close(); + } catch (IOException ex) {} + } + } + + return value; + } + + /** + * Cache for properties in java.home/lib/jaxp.properties + */ + static final Properties cacheProps = new Properties(); + + /** + * Flag indicating if the program has tried reading java.home/lib/jaxp.properties + */ + static volatile boolean firstTime = true; + + private SecuritySupport () {} } diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java index f4f903b2be9..76c4643f21b 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java @@ -54,6 +54,7 @@ import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ReferenceType; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; import com.sun.org.apache.xalan.internal.utils.ObjectFactory; +import java.util.Objects; /** * @author Jacek Ambroziak @@ -156,8 +157,15 @@ class FunctionCall extends Expression { this.type = type; this.distance = distance; } + + @Override + public int hashCode() { + return Objects.hashCode(this.type); + } + + @Override public boolean equals(Object query){ - return query.equals(type); + return query != null && query.equals(type); } } @@ -277,6 +285,7 @@ class FunctionCall extends Expression { return(_fname.toString()); } + @Override public void setParser(Parser parser) { super.setParser(parser); if (_arguments != null) { @@ -319,6 +328,7 @@ class FunctionCall extends Expression { * Type check a function call. Since different type conversions apply, * type checking is different for standard and external (Java) functions. */ + @Override public Type typeCheck(SymbolTable stable) throws TypeCheckError { @@ -680,6 +690,7 @@ class FunctionCall extends Expression { * Compile the function call and treat as an expression * Update true/false-lists. */ + @Override public void translateDesynthesized(ClassGenerator classGen, MethodGenerator methodGen) { @@ -700,6 +711,7 @@ class FunctionCall extends Expression { * Translate a function call. The compiled code will leave the function's * return value on the JVM's stack. */ + @Override public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final int n = argumentCount(); final ConstantPoolGen cpg = classGen.getConstantPool(); @@ -857,6 +869,7 @@ class FunctionCall extends Expression { } } + @Override public String toString() { return "funcall(" + _fname + ", " + _arguments + ')'; } @@ -1069,7 +1082,7 @@ class FunctionCall extends Expression { protected static String replaceDash(String name) { char dash = '-'; - StringBuffer buff = new StringBuffer(""); + final StringBuilder buff = new StringBuilder(""); for (int i = 0; i < name.length(); i++) { if (i > 0 && name.charAt(i-1) == dash) buff.append(Character.toUpperCase(name.charAt(i))); diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Import.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Import.java index b2d33e940f2..fdfbe178d1d 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Import.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Import.java @@ -23,18 +23,19 @@ package com.sun.org.apache.xalan.internal.xsltc.compiler; -import java.io.File; -import java.net.URL; -import java.net.MalformedURLException; -import java.util.Enumeration; - -import com.sun.org.apache.xml.internal.utils.SystemIDResolver; +import com.sun.org.apache.xalan.internal.XalanConstants; +import com.sun.org.apache.xalan.internal.utils.SecuritySupport; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; - +import com.sun.org.apache.xml.internal.utils.SystemIDResolver; +import java.io.File; +import java.net.URL; +import java.net.MalformedURLException; +import java.util.Enumeration; +import javax.xml.XMLConstants; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; @@ -84,6 +85,17 @@ final class Import extends TopLevelElement { // No SourceLoader or not resolved by SourceLoader if (input == null) { docToLoad = SystemIDResolver.getAbsoluteURI(docToLoad, currLoadedDoc); + String accessError = SecuritySupport.checkAccess(docToLoad, + xsltc.getProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET), + XalanConstants.ACCESS_EXTERNAL_ALL); + + if (accessError != null) { + final ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + SecuritySupport.sanitizePath(docToLoad), accessError, + this); + parser.reportError(Constants.FATAL, msg); + return; + } input = new InputSource(docToLoad); } diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Include.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Include.java index 3d549f47402..71c129f7cca 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Include.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Include.java @@ -23,19 +23,20 @@ package com.sun.org.apache.xalan.internal.xsltc.compiler; -import java.io.File; -import java.io.FileNotFoundException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Enumeration; - -import com.sun.org.apache.xml.internal.utils.SystemIDResolver; +import com.sun.org.apache.xalan.internal.XalanConstants; +import com.sun.org.apache.xalan.internal.utils.SecuritySupport; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; - +import com.sun.org.apache.xml.internal.utils.SystemIDResolver; +import java.io.File; +import java.io.FileNotFoundException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; +import javax.xml.XMLConstants; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; @@ -85,6 +86,17 @@ final class Include extends TopLevelElement { // No SourceLoader or not resolved by SourceLoader if (input == null) { docToLoad = SystemIDResolver.getAbsoluteURI(docToLoad, currLoadedDoc); + String accessError = SecuritySupport.checkAccess(docToLoad, + xsltc.getProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET), + XalanConstants.ACCESS_EXTERNAL_ALL); + + if (accessError != null) { + final ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + SecuritySupport.sanitizePath(docToLoad), accessError, + this); + parser.reportError(Constants.FATAL, msg); + return; + } input = new InputSource(docToLoad); } diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java index 80ce77bb8b8..9669bf734ad 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java @@ -23,6 +23,16 @@ package com.sun.org.apache.xalan.internal.xsltc.compiler; +import com.sun.java_cup.internal.runtime.Symbol; +import com.sun.org.apache.xalan.internal.XalanConstants; +import com.sun.org.apache.xalan.internal.utils.FactoryImpl; +import com.sun.org.apache.xalan.internal.utils.ObjectFactory; +import com.sun.org.apache.xalan.internal.utils.SecuritySupport; +import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; +import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodType; +import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; +import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; +import com.sun.org.apache.xml.internal.serializer.utils.SystemIDResolver; import java.io.File; import java.io.IOException; import java.io.StringReader; @@ -33,27 +43,18 @@ import java.util.Properties; import java.util.Stack; import java.util.StringTokenizer; import java.util.Vector; - -import com.sun.java_cup.internal.runtime.Symbol; import javax.xml.XMLConstants; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; - -import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; -import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodType; -import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; -import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; -import com.sun.org.apache.xalan.internal.utils.FactoryImpl; -import com.sun.org.apache.xalan.internal.utils.ObjectFactory; import org.xml.sax.Attributes; -import org.xml.sax.helpers.AttributesImpl; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; +import org.xml.sax.helpers.AttributesImpl; /** * @author Jacek Ambroziak @@ -475,6 +476,8 @@ public class Parser implements Constants, ContentHandler { factory.setNamespaceAware(true); } final SAXParser parser = factory.newSAXParser(); + parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, + _xsltc.getProperty(XMLConstants.ACCESS_EXTERNAL_DTD)); final XMLReader reader = parser.getXMLReader(); return(parse(reader, input)); } @@ -547,6 +550,25 @@ public class Parser implements Constants, ContentHandler { return(element); } else { + try { + String path = _target; + if (path.indexOf(":")==-1) { + path = "file:" + path; + } + path = SystemIDResolver.getAbsoluteURI(path); + String accessError = SecuritySupport.checkAccess(path, + _xsltc.getProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET), + XalanConstants.ACCESS_EXTERNAL_ALL); + if (accessError != null) { + ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + SecuritySupport.sanitizePath(_target), accessError, + root); + throw new CompilerException(msg.toString()); + } + } catch (IOException ex) { + throw new CompilerException(ex); + } + return(loadExternalStylesheet(_target)); } } diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableRefBase.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableRefBase.java index 100c0e761b3..76cee04a87a 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableRefBase.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableRefBase.java @@ -25,6 +25,7 @@ package com.sun.org.apache.xalan.internal.xsltc.compiler; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; +import java.util.Objects; /** * @author Morten Jorgensen @@ -97,13 +98,15 @@ class VariableRefBase extends Expression { * Two variable references are deemed equal if they refer to the * same variable. */ + @Override public boolean equals(Object obj) { - try { - return (_variable == ((VariableRefBase) obj)._variable); - } - catch (ClassCastException e) { - return false; - } + return obj == this || (obj instanceof VariableRefBase) + && (_variable == ((VariableRefBase) obj)._variable); + } + + @Override + public int hashCode() { + return Objects.hashCode(this._variable); } /** @@ -111,10 +114,12 @@ class VariableRefBase extends Expression { * format 'variable-ref()'. * @return Variable reference description */ + @Override public String toString() { return "variable-ref("+_variable.getName()+'/'+_variable.getType()+')'; } + @Override public Type typeCheck(SymbolTable stable) throws TypeCheckError { diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java index 454027819b8..97fff3bf2e0 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java @@ -39,8 +39,10 @@ import java.util.Vector; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; +import javax.xml.XMLConstants; import com.sun.org.apache.bcel.internal.classfile.JavaClass; +import com.sun.org.apache.xalan.internal.XalanConstants; import com.sun.org.apache.xalan.internal.utils.SecuritySupport; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; @@ -135,6 +137,16 @@ public final class XSLTC { private boolean _useServicesMechanism = true; + /** + * protocols allowed for external references set by the stylesheet processing instruction, Import and Include element. + */ + private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT; + /** + * protocols allowed for external DTD references in source file and/or stylesheet. + */ + private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT; + + /** * XSLTC compiler constructor */ @@ -169,6 +181,31 @@ public final class XSLTC { _useServicesMechanism = flag; } + /** + * Return allowed protocols for accessing external stylesheet. + */ + public String getProperty(String name) { + if (name.equals(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)) { + return _accessExternalStylesheet; + } + else if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { + return _accessExternalDTD; + } + return null; + } + + /** + * Set allowed protocols for accessing external stylesheet. + */ + public void setProperty(String name, String value) { + if (name.equals(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)) { + _accessExternalStylesheet = (String)value; + } + else if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { + _accessExternalDTD = (String)value; + } + } + /** * Only for user by the internal TrAX implementation. */ diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java index de3783997e2..90655c6fe45 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java @@ -445,6 +445,12 @@ public class ErrorMessages extends ListResourceBundle { {ErrorMsg.MISSING_XSLT_TARGET_ERR, "Could not find stylesheet target ''{0}''."}, + /* + * Note to translators: access to the stylesheet target is denied + */ + {ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + "Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed."}, + /* * Note to translators: This message represents an internal error in * condition in XSLTC. The substitution text is the class name in XSLTC diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ca.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ca.java index 1d615bf5b17..fa28ddc2d2f 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ca.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ca.java @@ -443,6 +443,12 @@ public class ErrorMessages_ca extends ListResourceBundle { {ErrorMsg.MISSING_XSLT_TARGET_ERR, "No s''ha trobat la destinaci\u00f3 ''{0}'' del full d''estils."}, + /* + * Note to translators: access to the stylesheet target is denied + */ + {ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + "Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed."}, + /* * Note to translators: This message represents an internal error in * condition in XSLTC. The substitution text is the class name in XSLTC diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_cs.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_cs.java index 739b6703dea..4220efd8f04 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_cs.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_cs.java @@ -443,6 +443,12 @@ public class ErrorMessages_cs extends ListResourceBundle { {ErrorMsg.MISSING_XSLT_TARGET_ERR, "Nelze naj\u00edt c\u00edlovou p\u0159edlohu se stylem ''{0}''."}, + /* + * Note to translators: access to the stylesheet target is denied + */ + {ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + "Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed."}, + /* * Note to translators: This message represents an internal error in * condition in XSLTC. The substitution text is the class name in XSLTC diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java index e0473d45f97..1ae98c19170 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java @@ -443,6 +443,12 @@ public class ErrorMessages_de extends ListResourceBundle { {ErrorMsg.MISSING_XSLT_TARGET_ERR, "Stylesheet-Ziel \"{0}\" konnte nicht gefunden werden."}, + /* + * Note to translators: access to the stylesheet target is denied + */ + {ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + "Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed."}, + /* * Note to translators: This message represents an internal error in * condition in XSLTC. The substitution text is the class name in XSLTC diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_es.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_es.java index ffb9bcc588d..7aa0deb8c0a 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_es.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_es.java @@ -443,6 +443,12 @@ public class ErrorMessages_es extends ListResourceBundle { {ErrorMsg.MISSING_XSLT_TARGET_ERR, "No se ha encontrado el destino de hoja de estilo ''{0}''."}, + /* + * Note to translators: access to the stylesheet target is denied + */ + {ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + "Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed."}, + /* * Note to translators: This message represents an internal error in * condition in XSLTC. The substitution text is the class name in XSLTC diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_fr.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_fr.java index 4c7087e1367..39151c785b9 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_fr.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_fr.java @@ -443,6 +443,12 @@ public class ErrorMessages_fr extends ListResourceBundle { {ErrorMsg.MISSING_XSLT_TARGET_ERR, "Cible de feuille de style ''{0}'' introuvable."}, + /* + * Note to translators: access to the stylesheet target is denied + */ + {ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + "Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed."}, + /* * Note to translators: This message represents an internal error in * condition in XSLTC. The substitution text is the class name in XSLTC diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_it.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_it.java index 4c33c19a1d2..b8f68b95aac 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_it.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_it.java @@ -443,6 +443,12 @@ public class ErrorMessages_it extends ListResourceBundle { {ErrorMsg.MISSING_XSLT_TARGET_ERR, "Impossibile trovare la destinazione ''{0}'' del foglio di stile."}, + /* + * Note to translators: access to the stylesheet target is denied + */ + {ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + "Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed."}, + /* * Note to translators: This message represents an internal error in * condition in XSLTC. The substitution text is the class name in XSLTC diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ja.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ja.java index eec29e921ca..28c15eaf02b 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ja.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ja.java @@ -443,6 +443,12 @@ public class ErrorMessages_ja extends ListResourceBundle { {ErrorMsg.MISSING_XSLT_TARGET_ERR, "\u30B9\u30BF\u30A4\u30EB\u30B7\u30FC\u30C8\u30FB\u30BF\u30FC\u30B2\u30C3\u30C8''{0}''\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002"}, + /* + * Note to translators: access to the stylesheet target is denied + */ + {ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + "Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed."}, + /* * Note to translators: This message represents an internal error in * condition in XSLTC. The substitution text is the class name in XSLTC diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ko.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ko.java index 9a2c5b47ce5..33853810638 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ko.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ko.java @@ -443,6 +443,12 @@ public class ErrorMessages_ko extends ListResourceBundle { {ErrorMsg.MISSING_XSLT_TARGET_ERR, "\uC2A4\uD0C0\uC77C\uC2DC\uD2B8 \uB300\uC0C1 ''{0}''\uC744(\uB97C) \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."}, + /* + * Note to translators: access to the stylesheet target is denied + */ + {ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + "Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed."}, + /* * Note to translators: This message represents an internal error in * condition in XSLTC. The substitution text is the class name in XSLTC diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_pt_BR.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_pt_BR.java index a0c31428854..c6b369edc1b 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_pt_BR.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_pt_BR.java @@ -443,6 +443,12 @@ public class ErrorMessages_pt_BR extends ListResourceBundle { {ErrorMsg.MISSING_XSLT_TARGET_ERR, "N\u00E3o foi poss\u00EDvel localizar o alvo da folha de estilos ''{0}''."}, + /* + * Note to translators: access to the stylesheet target is denied + */ + {ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + "Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed."}, + /* * Note to translators: This message represents an internal error in * condition in XSLTC. The substitution text is the class name in XSLTC diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_sk.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_sk.java index cc0ba4bb88c..1a76afc2403 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_sk.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_sk.java @@ -443,6 +443,12 @@ public class ErrorMessages_sk extends ListResourceBundle { {ErrorMsg.MISSING_XSLT_TARGET_ERR, "Nebolo mo\u017en\u00e9 n\u00e1js\u0165 cie\u013e \u0161t\u00fdlu dokumentu ''{0}''."}, + /* + * Note to translators: access to the stylesheet target is denied + */ + {ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + "Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed."}, + /* * Note to translators: This message represents an internal error in * condition in XSLTC. The substitution text is the class name in XSLTC diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_sv.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_sv.java index 62d2f7a6ae5..07aa76cb122 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_sv.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_sv.java @@ -443,6 +443,12 @@ public class ErrorMessages_sv extends ListResourceBundle { {ErrorMsg.MISSING_XSLT_TARGET_ERR, "Hittade inte formatmallen ''{0}''."}, + /* + * Note to translators: access to the stylesheet target is denied + */ + {ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + "Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed."}, + /* * Note to translators: This message represents an internal error in * condition in XSLTC. The substitution text is the class name in XSLTC diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_CN.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_CN.java index 683ea33991e..1b12156b326 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_CN.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_CN.java @@ -443,6 +443,12 @@ public class ErrorMessages_zh_CN extends ListResourceBundle { {ErrorMsg.MISSING_XSLT_TARGET_ERR, "\u627E\u4E0D\u5230\u6837\u5F0F\u8868\u76EE\u6807 ''{0}''\u3002"}, + /* + * Note to translators: access to the stylesheet target is denied + */ + {ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + "Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed."}, + /* * Note to translators: This message represents an internal error in * condition in XSLTC. The substitution text is the class name in XSLTC diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_TW.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_TW.java index 892a2e8f353..f813e667d1c 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_TW.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_TW.java @@ -443,6 +443,12 @@ public class ErrorMessages_zh_TW extends ListResourceBundle { {ErrorMsg.MISSING_XSLT_TARGET_ERR, "\u627E\u4E0D\u5230\u6A23\u5F0F\u8868\u76EE\u6A19 ''{0}''\u3002"}, + /* + * Note to translators: access to the stylesheet target is denied + */ + {ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + "Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed."}, + /* * Note to translators: This message represents an internal error in * condition in XSLTC. The substitution text is the class name in XSLTC diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java index faa7e99c26a..102f354593e 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java @@ -95,6 +95,7 @@ public final class ErrorMsg { public static final String UNSUPPORTED_EXT_ERR = "UNSUPPORTED_EXT_ERR"; public static final String MISSING_XSLT_URI_ERR = "MISSING_XSLT_URI_ERR"; public static final String MISSING_XSLT_TARGET_ERR = "MISSING_XSLT_TARGET_ERR"; + public static final String ACCESSING_XSLT_TARGET_ERR = "ACCESSING_XSLT_TARGET_ERR"; public static final String NOT_IMPLEMENTED_ERR = "NOT_IMPLEMENTED_ERR"; public static final String NOT_STYLESHEET_ERR = "NOT_STYLESHEET_ERR"; public static final String ELEMENT_PARSE_ERR = "ELEMENT_PARSE_ERR"; diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/LoadDocument.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/LoadDocument.java index de87c5622dc..f3e28791a2f 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/LoadDocument.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/dom/LoadDocument.java @@ -23,6 +23,7 @@ package com.sun.org.apache.xalan.internal.xsltc.dom; +import com.sun.org.apache.xalan.internal.XalanConstants; import java.io.FileNotFoundException; import javax.xml.transform.stream.StreamSource; @@ -31,8 +32,10 @@ import com.sun.org.apache.xalan.internal.xsltc.DOM; import com.sun.org.apache.xalan.internal.xsltc.DOMCache; import com.sun.org.apache.xalan.internal.xsltc.DOMEnhancedForDTM; import com.sun.org.apache.xalan.internal.xsltc.TransletException; +import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; +import com.sun.org.apache.xalan.internal.utils.SecuritySupport; import com.sun.org.apache.xml.internal.dtm.DTM; import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; import com.sun.org.apache.xml.internal.dtm.DTMManager; @@ -199,6 +202,13 @@ public final class LoadDocument { throw new TransletException(e); } } else { + String accessError = SecuritySupport.checkAccess(uri, translet.getAllowedProtocols(), XalanConstants.ACCESS_EXTERNAL_ALL); + if (accessError != null) { + ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR, + SecuritySupport.sanitizePath(uri), accessError); + throw new Exception(msg.toString()); + } + // Parse the input document and construct DOM object // Trust the DTMManager to pick the right parser and // set up the DOM correctly. diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet.java index 71e1e4abf7a..9eddf5ce423 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet.java @@ -23,6 +23,7 @@ package com.sun.org.apache.xalan.internal.xsltc.runtime; +import com.sun.org.apache.xalan.internal.XalanConstants; import com.sun.org.apache.xalan.internal.utils.FactoryImpl; import java.io.File; import java.io.FileOutputStream; @@ -110,6 +111,11 @@ public abstract class AbstractTranslet implements Translet { private boolean _useServicesMechanism; + /** + * protocols allowed for external references set by the stylesheet processing instruction, Document() function, Import and Include element. + */ + private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT; + /************************************************************************ * Debugging ************************************************************************/ @@ -758,6 +764,20 @@ public abstract class AbstractTranslet implements Translet { _useServicesMechanism = flag; } + /** + * Return allowed protocols for accessing external stylesheet. + */ + public String getAllowedProtocols() { + return _accessExternalStylesheet; + } + + /** + * Set allowed protocols for accessing external stylesheet. + */ + public void setAllowedProtocols(String protocols) { + _accessExternalStylesheet = protocols; + } + /************************************************************************ * DOMImplementation caching for basis library ************************************************************************/ diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesHandlerImpl.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesHandlerImpl.java index 2eb161dafee..879c1cb4de0 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesHandlerImpl.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesHandlerImpl.java @@ -99,6 +99,12 @@ public class TemplatesHandlerImpl if (tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)) xsltc.setSecureProcessing(true); + xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, + (String)tfactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)); + xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, + (String)tfactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_DTD)); + + if ("true".equals(tfactory.getAttribute(TransformerFactoryImpl.ENABLE_INLINING))) xsltc.setTemplateInlining(true); else diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java index a3bd7f6d1ab..e6d9cc3cf95 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java @@ -23,6 +23,7 @@ package com.sun.org.apache.xalan.internal.xsltc.trax; +import com.sun.org.apache.xalan.internal.XalanConstants; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -124,6 +125,11 @@ public final class TemplatesImpl implements Templates, Serializable { private boolean _useServicesMechanism; + /** + * protocols allowed for external references set by the stylesheet processing instruction, Import and Include element. + */ + private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT; + static final class TransletClassLoader extends ClassLoader { TransletClassLoader(ClassLoader parent) { super(parent); @@ -171,6 +177,7 @@ public final class TemplatesImpl implements Templates, Serializable { _indentNumber = indentNumber; _tfactory = tfactory; _useServicesMechanism = tfactory.useServicesMechnism(); + _accessExternalStylesheet = (String) tfactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET); } /** * Need for de-serialization, see readObject(). @@ -381,6 +388,7 @@ public final class TemplatesImpl implements Templates, Serializable { translet.postInitialization(); translet.setTemplates(this); translet.setServicesMechnism(_useServicesMechanism); + translet.setAllowedProtocols(_accessExternalStylesheet); if (_auxClasses != null) { translet.setAuxiliaryClasses(_auxClasses); } diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java index 78d96aa0479..2675268d555 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java @@ -224,6 +224,16 @@ public class TransformerFactoryImpl */ private boolean _useServicesMechanism; + /** + * protocols allowed for external references set by the stylesheet processing instruction, Import and Include element. + */ + private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT; + /** + * protocols allowed for external DTD references in source file and/or stylesheet. + */ + private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT; + + /** * javax.xml.transform.sax.TransformerFactory implementation. */ @@ -238,10 +248,17 @@ public class TransformerFactoryImpl private TransformerFactoryImpl(boolean useServicesMechanism) { this.m_DTMManagerClass = XSLTCDTMManager.getDTMManagerClass(useServicesMechanism); this._useServicesMechanism = useServicesMechanism; + + String defaultAccess = XalanConstants.EXTERNAL_ACCESS_DEFAULT; if (System.getSecurityManager() != null) { _isSecureMode = true; _isNotSecureProcessing = false; + defaultAccess = XalanConstants.getExternalAccessDefault(true); } + _accessExternalStylesheet = SecuritySupport.getDefaultAccessProperty( + XalanConstants.SP_ACCESS_EXTERNAL_STYLESHEET, defaultAccess); + _accessExternalDTD = SecuritySupport.getDefaultAccessProperty( + XalanConstants.SP_ACCESS_EXTERNAL_DTD, defaultAccess); } /** @@ -301,6 +318,12 @@ public class TransformerFactoryImpl else return Boolean.FALSE; } + else if (name.equals(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)) { + return _accessExternalStylesheet; + } + else if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { + return _accessExternalDTD; + } // Throw an exception for all other attributes ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_INVALID_ATTR_ERR, name); @@ -401,6 +424,14 @@ public class TransformerFactoryImpl return; } } + else if (name.equals(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)) { + _accessExternalStylesheet = (String)value; + return; + } + else if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { + _accessExternalDTD = (String)value; + return; + } // Throw an exception for all other attributes final ErrorMsg err @@ -444,7 +475,12 @@ public class TransformerFactoryImpl throw new TransformerConfigurationException(err.toString()); } _isNotSecureProcessing = !value; - // all done processing feature + + // set restriction, allowing no access to external stylesheet + if (value) { + _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT_FSP; + _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT_FSP; + } return; } else if (name.equals(XalanConstants.ORACLE_FEATURE_SERVICE_MECHANISM)) { @@ -799,6 +835,8 @@ public class TransformerFactoryImpl xsltc.setTemplateInlining(false); if (!_isNotSecureProcessing) xsltc.setSecureProcessing(true); + xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, _accessExternalStylesheet); + xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD); xsltc.init(); // Set a document loader (for xsl:include/import) if defined @@ -880,15 +918,20 @@ public class TransformerFactoryImpl // Check that the transformation went well before returning if (bytecodes == null) { - Vector errs = xsltc.getErrors(); ErrorMsg err = null; if (errs != null) { - err = (ErrorMsg)errs.get(errs.size()-1); + err = (ErrorMsg)errs.elementAt(errs.size()-1); } else { err = new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR); } - TransformerConfigurationException exc = new TransformerConfigurationException(err.toString(), err.getCause()); + Throwable cause = err.getCause(); + TransformerConfigurationException exc; + if (cause != null) { + exc = new TransformerConfigurationException(cause.getMessage(), cause); + } else { + exc = new TransformerConfigurationException(err.toString()); + } // Pass compiler errors to the error listener if (_errorListener != null) { diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java index 16e178eba9a..a32ab8267f8 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java @@ -23,6 +23,7 @@ package com.sun.org.apache.xalan.internal.xsltc.trax; +import com.sun.org.apache.xalan.internal.XalanConstants; import com.sun.org.apache.xalan.internal.utils.FactoryImpl; import java.io.File; import java.io.FileOutputStream; @@ -61,6 +62,7 @@ import javax.xml.transform.stax.StAXResult; import javax.xml.transform.stax.StAXSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import javax.xml.XMLConstants; import com.sun.org.apache.xml.internal.utils.SystemIDResolver; @@ -207,6 +209,14 @@ public final class TransformerImpl extends Transformer * Note the default value (false) is the safe option.. */ private boolean _useServicesMechanism; + /** + * protocols allowed for external references set by the stylesheet processing instruction, Import and Include element. + */ + private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT; + /** + * protocols allowed for external DTD references in source file and/or stylesheet. + */ + private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT; /** * A hashtable to store parameters for the identity transform. These @@ -260,7 +270,10 @@ public final class TransformerImpl extends Transformer _indentNumber = indentNumber; _tfactory = tfactory; _useServicesMechanism = _tfactory.useServicesMechnism(); + _accessExternalStylesheet = (String)_tfactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET); + _accessExternalDTD = (String)_tfactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_DTD); _readerManager = XMLReaderManager.getInstance(_useServicesMechanism); + _readerManager.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD); //_isIncremental = tfactory._incremental; } diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java index f5e1c85b98c..bef160df947 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java @@ -105,6 +105,8 @@ public final class Util { if (reader == null) { try { reader= XMLReaderFactory.createXMLReader(); + reader.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, + xsltc.getProperty(XMLConstants.ACCESS_EXTERNAL_DTD)); } catch (Exception e ) { try { diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMConfigurationImpl.java b/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMConfigurationImpl.java index ad11c0416ee..23be56b5b58 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMConfigurationImpl.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/dom/DOMConfigurationImpl.java @@ -20,18 +20,6 @@ package com.sun.org.apache.xerces.internal.dom; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Locale; -import java.util.Vector; - -import com.sun.org.apache.xerces.internal.util.PropertyState; -import com.sun.org.apache.xerces.internal.util.Status; -import org.w3c.dom.DOMConfiguration; -import org.w3c.dom.DOMErrorHandler; -import org.w3c.dom.DOMStringList; - import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.XMLEntityManager; import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; @@ -42,7 +30,10 @@ import com.sun.org.apache.xerces.internal.util.DOMEntityResolverWrapper; import com.sun.org.apache.xerces.internal.util.DOMErrorHandlerWrapper; import com.sun.org.apache.xerces.internal.util.MessageFormatter; import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings; +import com.sun.org.apache.xerces.internal.util.PropertyState; import com.sun.org.apache.xerces.internal.util.SymbolTable; +import com.sun.org.apache.xerces.internal.utils.ObjectFactory; +import com.sun.org.apache.xerces.internal.utils.SecuritySupport; import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler; import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler; import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; @@ -55,12 +46,19 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver; import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler; import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration; -import com.sun.org.apache.xerces.internal.utils.ObjectFactory; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Locale; +import java.util.Vector; +import javax.xml.XMLConstants; +import org.w3c.dom.DOMConfiguration; +import org.w3c.dom.DOMErrorHandler; import org.w3c.dom.DOMException; +import org.w3c.dom.DOMStringList; import org.w3c.dom.ls.LSResourceResolver; - /** * Xerces implementation of DOMConfiguration that maintains a table of recognized parameters. * @@ -158,6 +156,14 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings protected static final String SCHEMA_DV_FACTORY = Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY; + /** Property identifier: access to external dtd */ + protected static final String ACCESS_EXTERNAL_DTD = + XMLConstants.ACCESS_EXTERNAL_DTD; + + /** Property identifier: access to external schema */ + protected static final String ACCESS_EXTERNAL_SCHEMA = + XMLConstants.ACCESS_EXTERNAL_SCHEMA; + // // Data // @@ -276,7 +282,9 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings JAXP_SCHEMA_SOURCE, JAXP_SCHEMA_LANGUAGE, DTD_VALIDATOR_FACTORY_PROPERTY, - SCHEMA_DV_FACTORY + SCHEMA_DV_FACTORY, + ACCESS_EXTERNAL_DTD, + ACCESS_EXTERNAL_SCHEMA }; addRecognizedProperties(recognizedProperties); @@ -310,6 +318,14 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings fValidationManager = createValidationManager(); setProperty(VALIDATION_MANAGER, fValidationManager); + //For DOM, the secure feature is set to true by default + String accessExternal = SecuritySupport.getDefaultAccessProperty( + Constants.SP_ACCESS_EXTERNAL_DTD, Constants.EXTERNAL_ACCESS_DEFAULT); + setProperty(ACCESS_EXTERNAL_DTD, accessExternal); + + accessExternal = SecuritySupport.getDefaultAccessProperty( + Constants.SP_ACCESS_EXTERNAL_SCHEMA, Constants.EXTERNAL_ACCESS_DEFAULT); + setProperty(ACCESS_EXTERNAL_SCHEMA, accessExternal); // add message formatters if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) { diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/Constants.java b/jaxp/src/com/sun/org/apache/xerces/internal/impl/Constants.java index d6f457db839..ec8a1117ebc 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/Constants.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/Constants.java @@ -20,6 +20,7 @@ package com.sun.org.apache.xerces.internal.impl; +import com.sun.org.apache.xerces.internal.utils.SecuritySupport; import java.util.Enumeration; import java.util.NoSuchElementException; @@ -138,6 +139,21 @@ public final class Constants { public static final String FEATURE_SECURE_PROCESSING = "http://javax.xml.XMLConstants/feature/secure-processing"; + // Oracle Feature: + /** + *

Use Service Mechanism

+ * + *
    + *
  • + * {@code true} instruct an object to use service mechanism to + * find a service implementation. This is the default behavior. + *
  • + *
  • + * {@code false} instruct an object to skip service mechanism and + * use the default implementation for that service. + *
  • + *
+ */ public static final String ORACLE_FEATURE_SERVICE_MECHANISM = "http://www.oracle.com/feature/use-service-mechanism"; /** Document XML version property ("document-xml-version"). */ @@ -160,6 +176,34 @@ public final class Constants { public static final String SYSTEM_PROPERTY_ELEMENT_ATTRIBUTE_LIMIT = "elementAttributeLimit" ; + /** JAXP Standard property prefix ("http://javax.xml.XMLConstants/property/"). */ + public static final String JAXPAPI_PROPERTY_PREFIX = + "http://javax.xml.XMLConstants/property/"; + + /** Oracle JAXP property prefix ("http://www.oracle.com/xml/jaxp/properties/"). */ + public static final String ORACLE_JAXP_PROPERTY_PREFIX = + "http://www.oracle.com/xml/jaxp/properties/"; + + //System Properties corresponding to ACCESS_EXTERNAL_* properties + public static final String SP_ACCESS_EXTERNAL_DTD = "javax.xml.accessExternalDTD"; + public static final String SP_ACCESS_EXTERNAL_SCHEMA = "javax.xml.accessExternalSchema"; + //all access keyword + public static final String ACCESS_EXTERNAL_ALL = "all"; + + /** + * Default value when FEATURE_SECURE_PROCESSING (FSP) is set to true + */ + public static final String EXTERNAL_ACCESS_DEFAULT_FSP = ""; + /** + * JDK version by which the default is to restrict external connection + */ + public static final int RESTRICT_BY_DEFAULT_JDK_VERSION = 8; + + /** + * FEATURE_SECURE_PROCESSING (FSP) is true by default + */ + public static final String EXTERNAL_ACCESS_DEFAULT = getExternalAccessDefault(true); + // // DOM features // @@ -653,6 +697,59 @@ public final class Constants { ? new ArrayEnumeration(fgXercesProperties) : fgEmptyEnumeration; } // getXercesProperties():Enumeration + /** + * Determine the default value of the external access properties + * + * jaxp 1.5 does not require implementations to restrict by default + * + * For JDK8: + * The default value is 'file' (including jar:file); The keyword "all" grants permission + * to all protocols. When {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} is on, + * the default value is an empty string indicating no access is allowed. + * + * For JDK7: + * The default value is 'all' granting permission to all protocols. If by default, + * {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} is true, it should + * not change the default value. However, if {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} + * is set explicitly, the values of the properties shall be set to an empty string + * indicating no access is allowed. + * + * @param isSecureProcessing indicating if Secure Processing is set + * @return default value + */ + public static String getExternalAccessDefault(boolean isSecureProcessing) { + String defaultValue = "all"; + if (isJDKandAbove(RESTRICT_BY_DEFAULT_JDK_VERSION)) { + defaultValue = "file"; + if (isSecureProcessing) { + defaultValue = EXTERNAL_ACCESS_DEFAULT_FSP; + } + } + return defaultValue; + } + + /* + * Check the version of the current JDK against that specified in the + * parameter + * + * There is a proposal to change the java version string to: + * MAJOR.MINOR.FU.CPU.PSU-BUILDNUMBER_BUGIDNUMBER_OPTIONAL + * This method would work with both the current format and that proposed + * + * @param compareTo a JDK version to be compared to + * @return true if the current version is the same or above that represented + * by the parameter + */ + public static boolean isJDKandAbove(int compareTo) { + String javaVersion = SecuritySupport.getSystemProperty("java.version"); + String versions[] = javaVersion.split("\\.", 3); + if (Integer.parseInt(versions[0]) >= compareTo || + Integer.parseInt(versions[1]) >= compareTo) { + return true; + } + return false; + } + // // Classes // diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/PropertyManager.java b/jaxp/src/com/sun/org/apache/xerces/internal/impl/PropertyManager.java index ead08fe0393..b85ea503fa3 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/PropertyManager.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/PropertyManager.java @@ -25,13 +25,14 @@ package com.sun.org.apache.xerces.internal.impl; +import com.sun.org.apache.xerces.internal.utils.SecuritySupport; +import com.sun.xml.internal.stream.StaxEntityResolverWrapper; import java.util.HashMap; +import javax.xml.XMLConstants; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLResolver; -import com.sun.xml.internal.stream.StaxEntityResolverWrapper; - /** * This class manages different properties related to Stax specification and its implementation. * This class constructor also takes itself (PropertyManager object) as parameter and initializes the @@ -51,6 +52,12 @@ public class PropertyManager { private static final String STRING_INTERNING = "http://xml.org/sax/features/string-interning"; + /** Property identifier: access to external dtd */ + protected static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD; + + /** Property identifier: access to external schema */ + protected static final String ACCESS_EXTERNAL_SCHEMA = XMLConstants.ACCESS_EXTERNAL_SCHEMA; + HashMap supportedProps = new HashMap(); public static final int CONTEXT_READER = 1; @@ -117,6 +124,15 @@ public class PropertyManager { supportedProps.put(Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE, new Boolean(false)); supportedProps.put(Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ENTITYDEF_FEATURE, new Boolean(false)); supportedProps.put(Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_UNDECLARED_ELEMDEF_FEATURE, new Boolean(false)); + + //For DOM/SAX, the secure feature is set to true by default + String accessExternal = SecuritySupport.getDefaultAccessProperty( + Constants.SP_ACCESS_EXTERNAL_DTD, Constants.EXTERNAL_ACCESS_DEFAULT); + supportedProps.put(ACCESS_EXTERNAL_DTD, accessExternal); + + accessExternal = SecuritySupport.getDefaultAccessProperty( + Constants.SP_ACCESS_EXTERNAL_SCHEMA, Constants.EXTERNAL_ACCESS_DEFAULT); + supportedProps.put(ACCESS_EXTERNAL_SCHEMA, accessExternal); } private void initWriterProps(){ diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java b/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java index abbd696bb03..82c009bbdd3 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java @@ -52,7 +52,10 @@ import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; import com.sun.org.apache.xerces.internal.util.SecurityManager; import com.sun.org.apache.xerces.internal.util.NamespaceSupport; +import com.sun.org.apache.xerces.internal.utils.SecuritySupport; import com.sun.org.apache.xerces.internal.xni.NamespaceContext; +import com.sun.xml.internal.stream.Entity; +import javax.xml.XMLConstants; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.events.XMLEvent; @@ -159,6 +162,18 @@ public class XMLDocumentFragmentScannerImpl protected static final String ENTITY_RESOLVER = Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY; + /** Feature identifier: standard uri conformant */ + protected static final String STANDARD_URI_CONFORMANT = + Constants.XERCES_FEATURE_PREFIX +Constants.STANDARD_URI_CONFORMANT_FEATURE; + + /** property identifier: access external dtd. */ + protected static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD; + + /** access external dtd: file protocol + * For DOM/SAX, the secure feature is set to true by default + */ + final static String EXTERNAL_ACCESS_DEFAULT = Constants.EXTERNAL_ACCESS_DEFAULT; + // recognized features and properties /** Recognized features. */ @@ -184,6 +199,7 @@ public class XMLDocumentFragmentScannerImpl SYMBOL_TABLE, ERROR_REPORTER, ENTITY_MANAGER, + ACCESS_EXTERNAL_DTD }; /** Property defaults. */ @@ -191,6 +207,7 @@ public class XMLDocumentFragmentScannerImpl null, null, null, + EXTERNAL_ACCESS_DEFAULT }; private static final char [] cdata = {'[','C','D','A','T','A','['}; @@ -297,6 +314,17 @@ public class XMLDocumentFragmentScannerImpl protected String fDeclaredEncoding = null; /** Xerces Feature: Disallow doctype declaration. */ protected boolean fDisallowDoctype = false; + /** + * comma-delimited list of protocols that are allowed for the purpose + * of accessing external dtd or entity references + */ + protected String fAccessExternalDTD = EXTERNAL_ACCESS_DEFAULT; + + /** + * standard uri conformant (strict uri). + * http://apache.org/xml/features/standard-uri-conformant + */ + protected boolean fStrictURI; // drivers @@ -413,17 +441,6 @@ public class XMLDocumentFragmentScannerImpl * * @return True if there is more to scan, false otherwise. */ - /* public boolean scanDocument(boolean complete) - throws IOException, XNIException { - - // keep dispatching "events" - fEntityManager.setEntityHandler(this); - - return true; - - } // scanDocument(boolean):boolean - */ - public boolean scanDocument(boolean complete) throws IOException, XNIException { @@ -579,6 +596,9 @@ public class XMLDocumentFragmentScannerImpl //xxx: external entities are supported in Xerces // it would be good to define feature for this case fSupportExternalEntities = true; + fSupportExternalEntities = true; + fSupportExternalEntities = true; + fSupportExternalEntities = true; fReplaceEntityReferences = true; fIsCoalesce = false; @@ -589,6 +609,9 @@ public class XMLDocumentFragmentScannerImpl dtdGrammarUtil = null; + // JAXP 1.5 features and properties + fAccessExternalDTD = (String) componentManager.getProperty(ACCESS_EXTERNAL_DTD, EXTERNAL_ACCESS_DEFAULT); + fStrictURI = componentManager.getFeature(STANDARD_URI_CONFORMANT, false); //fEntityManager.test(); } // reset(XMLComponentManager) @@ -639,6 +662,9 @@ public class XMLDocumentFragmentScannerImpl dtdGrammarUtil = null; + // Oracle jdk feature + fAccessExternalDTD = (String) propertyManager.getProperty(ACCESS_EXTERNAL_DTD); + } // reset(XMLComponentManager) /** @@ -735,6 +761,14 @@ public class XMLDocumentFragmentScannerImpl return; } + //JAXP 1.5 properties + if (propertyId.startsWith(Constants.JAXPAPI_PROPERTY_PREFIX)) { + if (propertyId.equals(ACCESS_EXTERNAL_DTD)) + { + fAccessExternalDTD = (String)value; + } + } + } // setProperty(String,Object) /** @@ -1846,7 +1880,8 @@ public class XMLDocumentFragmentScannerImpl //1. if the entity is external and support to external entities is not required // 2. or entities should not be replaced //3. or if it is built in entity reference. - if((fEntityStore.isExternalEntity(name) && !fSupportExternalEntities) || (!fEntityStore.isExternalEntity(name) && !fReplaceEntityReferences) || foundBuiltInRefs){ + boolean isEE = fEntityStore.isExternalEntity(name); + if((isEE && !fSupportExternalEntities) || (!isEE && !fReplaceEntityReferences) || foundBuiltInRefs){ fScannerState = SCANNER_STATE_REFERENCE; return ; } @@ -1996,6 +2031,12 @@ public class XMLDocumentFragmentScannerImpl } // getDriverName():String + String checkAccess(String systemId, String allowedProtocols) throws IOException { + String baseSystemId = fEntityScanner.getBaseSystemId(); + String expandedSystemId = fEntityManager.expandSystemId(systemId, baseSystemId,fStrictURI); + return SecuritySupport.checkAccess(expandedSystemId, allowedProtocols, Constants.ACCESS_EXTERNAL_ALL); + } + // // Classes // diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java b/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java index b6ef755a473..b043c9d3be1 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java @@ -21,6 +21,22 @@ package com.sun.org.apache.xerces.internal.impl; +import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDDescription; +import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; +import com.sun.org.apache.xerces.internal.util.NamespaceSupport; +import com.sun.org.apache.xerces.internal.util.XMLChar; +import com.sun.org.apache.xerces.internal.util.XMLResourceIdentifierImpl; +import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; +import com.sun.org.apache.xerces.internal.utils.SecuritySupport; +import com.sun.org.apache.xerces.internal.xni.Augmentations; +import com.sun.org.apache.xerces.internal.xni.NamespaceContext; +import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; +import com.sun.org.apache.xerces.internal.xni.XMLString; +import com.sun.org.apache.xerces.internal.xni.XNIException; +import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; +import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; +import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDScanner; +import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; import com.sun.xml.internal.stream.Entity; import com.sun.xml.internal.stream.StaxXMLInputSource; import com.sun.xml.internal.stream.dtd.DTDGrammarUtil; @@ -29,23 +45,6 @@ import java.io.IOException; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.events.XMLEvent; -import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; -import com.sun.org.apache.xerces.internal.util.NamespaceSupport; -import com.sun.org.apache.xerces.internal.util.XMLChar; -import com.sun.org.apache.xerces.internal.util.XMLResourceIdentifierImpl; -import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; -import com.sun.org.apache.xerces.internal.xni.NamespaceContext; -import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; -import com.sun.org.apache.xerces.internal.xni.XMLString; -import com.sun.org.apache.xerces.internal.xni.XNIException; -import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; -import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; -import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; -import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDScanner; -import com.sun.org.apache.xerces.internal.xni.Augmentations; -import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDDescription; -import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentScanner; - /** * This class is responsible for scanning XML document structure @@ -148,7 +147,7 @@ public class XMLDocumentScannerImpl /** Property defaults. */ private static final Object[] PROPERTY_DEFAULTS = { - null, + null, null }; @@ -920,7 +919,6 @@ public class XMLDocumentScannerImpl reportFatalError("DoctypeNotAllowed", null); } - if (fSeenDoctypeDecl) { reportFatalError("AlreadySeenDoctype", null); } @@ -952,15 +950,18 @@ public class XMLDocumentScannerImpl if (fDoctypeSystemId != null) { if (((fValidation || fLoadExternalDTD) && (fValidationManager == null || !fValidationManager.isCachedDTD()))) { - if (fSupportDTD) - setScannerState(SCANNER_STATE_DTD_EXTERNAL); - else - setScannerState(SCANNER_STATE_PROLOG); - setDriver(fContentDriver); - if(fDTDDriver == null) - fDTDDriver = new DTDDriver(); - return fDTDDriver.next(); + if (fSupportDTD) { + setScannerState(SCANNER_STATE_DTD_EXTERNAL); + } else { + setScannerState(SCANNER_STATE_PROLOG); + } + setDriver(fContentDriver); + if(fDTDDriver == null) { + fDTDDriver = new DTDDriver(); + } + + return fDTDDriver.next(); } } else if (fExternalSubsetSource != null) { @@ -1149,9 +1150,21 @@ public class XMLDocumentScannerImpl resourceIdentifier.setValues(fDoctypePublicId, fDoctypeSystemId, null, null); XMLInputSource xmlInputSource = null ; StaxXMLInputSource staxInputSource = fEntityManager.resolveEntityAsPerStax(resourceIdentifier); + + // Check access permission. If the source is resolved by a resolver, the check is skipped. + if (!staxInputSource.hasResolver()) { + String accessError = checkAccess(fDoctypeSystemId, fAccessExternalDTD); + if (accessError != null) { + reportFatalError("AccessExternalDTD", new Object[]{ SecuritySupport.sanitizePath(fDoctypeSystemId), accessError }); + } + } xmlInputSource = staxInputSource.getXMLInputSource(); fDTDScanner.setInputSource(xmlInputSource); - setScannerState(SCANNER_STATE_DTD_EXTERNAL_DECLS); + if (fEntityScanner.fCurrentEntity != null) { + setScannerState(SCANNER_STATE_DTD_EXTERNAL_DECLS); + } else { + setScannerState(SCANNER_STATE_PROLOG); + } again = true; break; } diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java b/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java index b761fc41974..547a3a5bcd5 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2006, 2013 Oracle and/or its affiliates. All rights reserved. */ /* @@ -20,51 +20,37 @@ package com.sun.org.apache.xerces.internal.impl ; +import com.sun.org.apache.xerces.internal.impl.Constants; +import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader; +import com.sun.org.apache.xerces.internal.impl.io.UCSReader; +import com.sun.org.apache.xerces.internal.impl.io.UTF8Reader; +import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; +import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; +import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; +import com.sun.org.apache.xerces.internal.util.*; +import com.sun.org.apache.xerces.internal.util.SecurityManager; +import com.sun.org.apache.xerces.internal.util.URI; +import com.sun.org.apache.xerces.internal.utils.SecuritySupport; +import com.sun.org.apache.xerces.internal.xni.Augmentations; +import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; +import com.sun.org.apache.xerces.internal.xni.XNIException; +import com.sun.org.apache.xerces.internal.xni.parser.*; +import com.sun.xml.internal.stream.Entity; import com.sun.xml.internal.stream.StaxEntityResolverWrapper; import com.sun.xml.internal.stream.StaxXMLInputSource; import com.sun.xml.internal.stream.XMLEntityStorage; import java.io.*; -import java.io.BufferedReader; -import java.util.*; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; import java.lang.reflect.Method; import java.net.HttpURLConnection; +import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; -import java.net.URISyntaxException; import java.util.Hashtable; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.Stack; - - -import com.sun.org.apache.xerces.internal.impl.io.*; -import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; -import com.sun.org.apache.xerces.internal.util.*; -import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; -import com.sun.org.apache.xerces.internal.xni.XNIException; -import com.sun.org.apache.xerces.internal.xni.parser.*; -import com.sun.org.apache.xerces.internal.impl.Constants; -import com.sun.org.apache.xerces.internal.utils.SecuritySupport; -import com.sun.xml.internal.stream.Entity; -import com.sun.org.apache.xerces.internal.xni.Augmentations; - -import com.sun.org.apache.xerces.internal.impl.io.UTF8Reader; -import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader; -import com.sun.org.apache.xerces.internal.impl.io.UCSReader; -import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; -import com.sun.org.apache.xerces.internal.util.HTTPInputSource; -import com.sun.org.apache.xerces.internal.xinclude.XIncludeHandler; - -import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; -import com.sun.org.apache.xerces.internal.util.SecurityManager; -import com.sun.org.apache.xerces.internal.util.URI; +import javax.xml.XMLConstants; /** @@ -140,6 +126,10 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { protected static final String WARN_ON_DUPLICATE_ENTITYDEF = Constants.XERCES_FEATURE_PREFIX +Constants.WARN_ON_DUPLICATE_ENTITYDEF_FEATURE; + /** Feature identifier: load external DTD. */ + protected static final String LOAD_EXTERNAL_DTD = + Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE; + // property identifiers /** Property identifier: symbol table. */ @@ -173,8 +163,16 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { protected static final String SECURITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; -protected static final String PARSER_SETTINGS = + protected static final String PARSER_SETTINGS = Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS; + + /** property identifier: access external dtd. */ + protected static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD; + + /** access external dtd: file protocol */ + static final String EXTERNAL_ACCESS_DEFAULT = Constants.EXTERNAL_ACCESS_DEFAULT; + + // recognized features and properties /** Recognized features. */ @@ -205,7 +203,7 @@ protected static final String PARSER_SETTINGS = VALIDATION_MANAGER, BUFFER_SIZE, SECURITY_MANAGER, - + ACCESS_EXTERNAL_DTD }; /** Property defaults. */ @@ -215,7 +213,8 @@ protected static final String PARSER_SETTINGS = null, null, new Integer(DEFAULT_BUFFER_SIZE), - null + null, + EXTERNAL_ACCESS_DEFAULT }; private static final String XMLEntity = "[xml]".intern(); @@ -274,6 +273,8 @@ protected static final String PARSER_SETTINGS = */ protected boolean fAllowJavaEncodings = true ; + /** Load external DTD. */ + protected boolean fLoadExternalDTD = true; // properties @@ -302,7 +303,8 @@ protected static final String PARSER_SETTINGS = /** Property Manager. This is used from Stax */ protected PropertyManager fPropertyManager ; - + /** used to restrict external access */ + protected String fAccessExternalDTD = EXTERNAL_ACCESS_DEFAULT; // settings /** @@ -366,6 +368,9 @@ protected static final String PARSER_SETTINGS = /** Current entity. */ protected Entity.ScannedEntity fCurrentEntity = null; + /** identify if the InputSource is created by a resolver */ + boolean fISCreatedByResolver = false; + // shared context protected XMLEntityStorage fEntityStorage ; @@ -965,18 +970,25 @@ protected static final String PARSER_SETTINGS = System.out.println("BEFORE Calling resolveEntity") ; } + fISCreatedByResolver = false; //either of Stax or Xerces would be null if(fStaxEntityResolver != null){ staxInputSource = fStaxEntityResolver.resolveEntity(ri); + if(staxInputSource != null) { + fISCreatedByResolver = true; + } } if(fEntityResolver != null){ xmlInputSource = fEntityResolver.resolveEntity(ri); + if(xmlInputSource != null) { + fISCreatedByResolver = true; + } } if(xmlInputSource != null){ //wrap this XMLInputSource to StaxInputSource - staxInputSource = new StaxXMLInputSource(xmlInputSource); + staxInputSource = new StaxXMLInputSource(xmlInputSource, fISCreatedByResolver); } // do default resolution @@ -1108,7 +1120,13 @@ protected static final String PARSER_SETTINGS = // should we skip external entities? boolean external = entity.isExternal(); + Entity.ExternalEntity externalEntity = null; + String extLitSysId = null, extBaseSysId = null, expandedSystemId = null; if (external) { + externalEntity = (Entity.ExternalEntity)entity; + extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getLiteralSystemId() : null); + extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getBaseSystemId() : null); + expandedSystemId = expandSystemId(extLitSysId, extBaseSysId); boolean unparsed = entity.isUnparsed(); boolean parameter = entityName.startsWith("%"); boolean general = !parameter; @@ -1118,13 +1136,6 @@ protected static final String PARSER_SETTINGS = if (fEntityHandler != null) { fResourceIdentifier.clear(); final String encoding = null; - Entity.ExternalEntity externalEntity = (Entity.ExternalEntity)entity; - //REVISIT: since we're storing expandedSystemId in the - // externalEntity, how could this have got here if it wasn't already - // expanded??? - neilg - String extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getLiteralSystemId() : null); - String extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getBaseSystemId() : null); - String expandedSystemId = expandSystemId(extLitSysId, extBaseSysId); fResourceIdentifier.setValues( (externalEntity.entityLocation != null ? externalEntity.entityLocation.getPublicId() : null), extLitSysId, extBaseSysId, expandedSystemId); @@ -1162,11 +1173,6 @@ protected static final String PARSER_SETTINGS = fResourceIdentifier.clear(); final String encoding = null; if (external) { - Entity.ExternalEntity externalEntity = (Entity.ExternalEntity)entity; - // REVISIT: for the same reason above... - String extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getLiteralSystemId() : null); - String extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getBaseSystemId() : null); - String expandedSystemId = expandSystemId(extLitSysId, extBaseSysId); fResourceIdentifier.setValues( (externalEntity.entityLocation != null ? externalEntity.entityLocation.getPublicId() : null), extLitSysId, extBaseSysId, expandedSystemId); @@ -1188,7 +1194,6 @@ protected static final String PARSER_SETTINGS = XMLInputSource xmlInputSource = null ; if (external) { - Entity.ExternalEntity externalEntity = (Entity.ExternalEntity)entity; staxInputSource = resolveEntityAsPerStax(externalEntity.entityLocation); /** xxx: Waiting from the EG * //simply return if there was entity resolver registered and application @@ -1196,6 +1201,18 @@ protected static final String PARSER_SETTINGS = * if(staxInputSource.hasXMLStreamOrXMLEventReader()) return ; */ xmlInputSource = staxInputSource.getXMLInputSource() ; + if (!fISCreatedByResolver) { + //let the not-LoadExternalDTD or not-SupportDTD process to handle the situation + if (fLoadExternalDTD) { + String accessError = SecuritySupport.checkAccess(expandedSystemId, fAccessExternalDTD, Constants.ACCESS_EXTERNAL_ALL); + if (accessError != null) { + fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN, + "AccessExternalEntity", + new Object[] { SecuritySupport.sanitizePath(expandedSystemId), accessError }, + XMLErrorReporter.SEVERITY_FATAL_ERROR); + } + } + } } // wrap internal entity else { @@ -1400,6 +1417,12 @@ protected static final String PARSER_SETTINGS = fStaxEntityResolver = null; } + // Zephyr feature ignore-external-dtd is the opposite of Xerces' load-external-dtd + fLoadExternalDTD = !((Boolean)propertyManager.getProperty(Constants.ZEPHYR_PROPERTY_PREFIX + Constants.IGNORE_EXTERNAL_DTD)).booleanValue(); + + // JAXP 1.5 feature + fAccessExternalDTD = (String) propertyManager.getProperty(ACCESS_EXTERNAL_DTD); + // initialize state //fStandalone = false; fEntities.clear(); @@ -1409,8 +1432,6 @@ protected static final String PARSER_SETTINGS = fExternalGeneralEntities = true; fExternalParameterEntities = true; fAllowJavaEncodings = true ; - - //test(); } /** @@ -1453,6 +1474,7 @@ protected static final String PARSER_SETTINGS = fAllowJavaEncodings = componentManager.getFeature(ALLOW_JAVA_ENCODINGS, false); fWarnDuplicateEntityDef = componentManager.getFeature(WARN_ON_DUPLICATE_ENTITYDEF, false); fStrictURI = componentManager.getFeature(STANDARD_URI_CONFORMANT, false); + fLoadExternalDTD = componentManager.getFeature(LOAD_EXTERNAL_DTD, true); // xerces properties fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE); @@ -1462,6 +1484,9 @@ protected static final String PARSER_SETTINGS = fValidationManager = (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER, null); fSecurityManager = (SecurityManager)componentManager.getProperty(SECURITY_MANAGER, null); + // JAXP 1.5 feature + fAccessExternalDTD = (String) componentManager.getProperty(ACCESS_EXTERNAL_DTD, EXTERNAL_ACCESS_DEFAULT); + //reset general state reset(); @@ -1554,6 +1579,11 @@ protected static final String PARSER_SETTINGS = featureId.endsWith(Constants.ALLOW_JAVA_ENCODINGS_FEATURE)) { fAllowJavaEncodings = state; } + if (suffixLength == Constants.LOAD_EXTERNAL_DTD_FEATURE.length() && + featureId.endsWith(Constants.LOAD_EXTERNAL_DTD_FEATURE)) { + fLoadExternalDTD = state; + return; + } } } // setFeature(String,boolean) @@ -1610,7 +1640,15 @@ protected static final String PARSER_SETTINGS = } } + //JAXP 1.5 properties + if (propertyId.startsWith(Constants.JAXPAPI_PROPERTY_PREFIX)) { + if (propertyId.equals(ACCESS_EXTERNAL_DTD)) + { + fAccessExternalDTD = (String)value; + } + } } + /** * Returns a list of property identifiers that are recognized by * this component. This method may return null if no properties diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/AbstractDateTimeDV.java b/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/AbstractDateTimeDV.java index e69c9e56a8a..d9d6587379b 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/AbstractDateTimeDV.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/AbstractDateTimeDV.java @@ -51,456 +51,471 @@ import com.sun.org.apache.xerces.internal.xs.datatypes.XSDateTime; */ public abstract class AbstractDateTimeDV extends TypeValidator { - //debugging - private static final boolean DEBUG=false; - - //define shared variables for date/time - - - //define constants to be used in assigning default values for - //all date/time excluding duration - protected final static int YEAR=2000; - protected final static int MONTH=01; - protected final static int DAY = 01; - + //debugging + private static final boolean DEBUG = false; + //define shared variables for date/time + //define constants to be used in assigning default values for + //all date/time excluding duration + protected final static int YEAR = 2000; + protected final static int MONTH = 01; + protected final static int DAY = 01; protected static final DatatypeFactory datatypeFactory = new DatatypeFactoryImpl(); - public short getAllowedFacets(){ - return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE ); - }//getAllowedFacets() - - - // distinguishes between identity and equality for date/time values - // ie: two values representing the same "moment in time" but with different - // remembered timezones are now equal but not identical. - public boolean isIdentical (Object value1, Object value2) { - if (!(value1 instanceof DateTimeData) || !(value2 instanceof DateTimeData)) { - return false; - } - - DateTimeData v1 = (DateTimeData)value1; - DateTimeData v2 = (DateTimeData)value2; - - // original timezones must be the same in addition to date/time values - // being 'equal' - if ((v1.timezoneHr == v2.timezoneHr) && (v1.timezoneMin == v2.timezoneMin)) { - return v1.equals(v2); - } - - return false; - }//isIdentical() - - // the parameters are in compiled form (from getActualValue) - public int compare (Object value1, Object value2) { - return compareDates(((DateTimeData)value1), - ((DateTimeData)value2), true); - }//compare() - - /** - * Compare algorithm described in dateDime (3.2.7). - * Duration datatype overwrites this method - * - * @param date1 normalized date representation of the first value - * @param date2 normalized date representation of the second value - * @param strict - * @return less, greater, less_equal, greater_equal, equal - */ - protected short compareDates(DateTimeData date1, DateTimeData date2, boolean strict) { - if (date1.utc == date2.utc) { - return compareOrder(date1, date2); - } - short c1, c2; - - DateTimeData tempDate = new DateTimeData(null, this); - - if ( date1.utc=='Z' ) { - - //compare date1<=date1<=(date2 with time zone -14) - // - cloneDate(date2, tempDate); //clones date1 value to global temporary storage: fTempDate - tempDate.timezoneHr=14; - tempDate.timezoneMin = 0; - tempDate.utc='+'; - normalize(tempDate); - c1 = compareOrder(date1, tempDate); - if (c1 == LESS_THAN) - return c1; - - //compare date1>=(date2 with time zone +14) - // - cloneDate(date2, tempDate); //clones date1 value to global temporary storage: tempDate - tempDate.timezoneHr = -14; - tempDate.timezoneMin = 0; - tempDate.utc='-'; - normalize(tempDate); - c2 = compareOrder(date1, tempDate); - if (c2 == GREATER_THAN) - return c2; - - return INDETERMINATE; - } - else if ( date2.utc=='Z' ) { - - //compare (date1 with time zone -14)<=date2 - // - cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate - tempDate.timezoneHr = -14; - tempDate.timezoneMin = 0; - tempDate.utc='-'; - if (DEBUG) { - System.out.println("tempDate=" + dateToString(tempDate)); - } - normalize(tempDate); - c1 = compareOrder(tempDate, date2); - if (DEBUG) { - System.out.println("date=" + dateToString(date2)); - System.out.println("tempDate=" + dateToString(tempDate)); - } - if (c1 == LESS_THAN) - return c1; - - //compare (date1 with time zone +14)<=date2 - // - cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate - tempDate.timezoneHr = 14; - tempDate.timezoneMin = 0; - tempDate.utc='+'; - normalize(tempDate); - c2 = compareOrder(tempDate, date2); - if (DEBUG) { - System.out.println("tempDate=" + dateToString(tempDate)); - } - if (c2 == GREATER_THAN) - return c2; - - return INDETERMINATE; - } - return INDETERMINATE; + @Override + public short getAllowedFacets() { + return (XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION | XSSimpleTypeDecl.FACET_MAXINCLUSIVE | XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE); + }//getAllowedFacets() + // distinguishes between identity and equality for date/time values + // ie: two values representing the same "moment in time" but with different + // remembered timezones are now equal but not identical. + @Override + public boolean isIdentical(Object value1, Object value2) { + if (!(value1 instanceof DateTimeData) || !(value2 instanceof DateTimeData)) { + return false; } - /** - * Given normalized values, determines order-relation - * between give date/time objects. - * - * @param date1 date/time object - * @param date2 date/time object - * @return 0 if date1 and date2 are equal, a value less than 0 if date1 is less than date2, a value greater than 0 if date1 is greater than date2 - */ - protected short compareOrder(DateTimeData date1, DateTimeData date2) { - if(date1.position < 1) { - if (date1.year < date2.year) - return -1; - if (date1.year > date2.year) - return 1; - } - if(date1.position < 2) { - if (date1.month < date2.month) - return -1; - if (date1.month > date2.month) - return 1; - } - if (date1.day < date2.day) - return -1; - if (date1.day > date2.day) - return 1; - if (date1.hour < date2.hour) - return -1; - if (date1.hour > date2.hour) - return 1; - if (date1.minute < date2.minute) - return -1; - if (date1.minute > date2.minute) - return 1; - if (date1.second < date2.second) - return -1; - if (date1.second > date2.second) - return 1; - if (date1.utc < date2.utc) - return -1; - if (date1.utc > date2.utc) - return 1; - return 0; + DateTimeData v1 = (DateTimeData) value1; + DateTimeData v2 = (DateTimeData) value2; + + // original timezones must be the same in addition to date/time values + // being 'equal' + if ((v1.timezoneHr == v2.timezoneHr) && (v1.timezoneMin == v2.timezoneMin)) { + return v1.equals(v2); } - /** - * Parses time hh:mm:ss.sss and time zone if any - * - * @param start - * @param end - * @param data - * @exception RuntimeException - */ - protected void getTime (String buffer, int start, int end, DateTimeData data) throws RuntimeException{ + return false; + }//isIdentical() - int stop = start+2; - - //get hours (hh) - data.hour=parseInt(buffer, start,stop); - - //get minutes (mm) - - if (buffer.charAt(stop++)!=':') { - throw new RuntimeException("Error in parsing time zone" ); - } - start = stop; - stop = stop+2; - data.minute=parseInt(buffer, start,stop); - - //get seconds (ss) - if (buffer.charAt(stop++)!=':') { - throw new RuntimeException("Error in parsing time zone" ); - } - - //find UTC sign if any - int sign = findUTCSign(buffer, start, end); - - //get seconds (ms) - start = stop; - stop = sign < 0 ? end : sign; - data.second = parseSecond(buffer, start, stop); - - //parse UTC time zone (hh:mm) - if (sign > 0) { - getTimeZone(buffer, data, sign, end); - } - } - - /** - * Parses date CCYY-MM-DD - * - * @param buffer - * @param start start position - * @param end end position - * @param date - * @exception RuntimeException - */ - protected int getDate (String buffer, int start, int end, DateTimeData date) throws RuntimeException{ - - start = getYearMonth(buffer, start, end, date); - - if (buffer.charAt(start++) !='-') { - throw new RuntimeException("CCYY-MM must be followed by '-' sign"); - } - int stop = start + 2; - date.day=parseInt(buffer, start, stop); - return stop; - } - - /** - * Parses date CCYY-MM - * - * @param buffer - * @param start start position - * @param end end position - * @param date - * @exception RuntimeException - */ - protected int getYearMonth (String buffer, int start, int end, DateTimeData date) throws RuntimeException{ - - if ( buffer.charAt(0)=='-' ) { - // REVISIT: date starts with preceding '-' sign - // do we have to do anything with it? - // - start++; - } - int i = indexOf(buffer, start, end, '-'); - if ( i==-1 ) throw new RuntimeException("Year separator is missing or misplaced"); - int length = i-start; - if (length<4) { - throw new RuntimeException("Year must have 'CCYY' format"); - } - else if (length > 4 && buffer.charAt(start)=='0'){ - throw new RuntimeException("Leading zeros are required if the year value would otherwise have fewer than four digits; otherwise they are forbidden"); - } - date.year= parseIntYear(buffer, i); - if (buffer.charAt(i)!='-') { - throw new RuntimeException("CCYY must be followed by '-' sign"); - } - start = ++i; - i = start +2; - date.month=parseInt(buffer, start, i); - return i; //fStart points right after the MONTH - } - - /** - * Shared code from Date and YearMonth datatypes. - * Finds if time zone sign is present - * - * @param end - * @param date - * @exception RuntimeException - */ - protected void parseTimeZone (String buffer, int start, int end, DateTimeData date) throws RuntimeException{ - - //fStart points right after the date - - if ( start < end ) { - if (!isNextCharUTCSign(buffer, start, end)) { - throw new RuntimeException ("Error in month parsing"); - } - else { - getTimeZone(buffer, date, start, end); - } - } - } - - /** - * Parses time zone: 'Z' or {+,-} followed by hh:mm - * - * @param data - * @param sign - * @exception RuntimeException - */ - protected void getTimeZone (String buffer, DateTimeData data, int sign, int end) throws RuntimeException{ - data.utc=buffer.charAt(sign); - - if ( buffer.charAt(sign) == 'Z' ) { - if (end>(++sign)) { - throw new RuntimeException("Error in parsing time zone"); - } - return; - } - if ( sign<=(end-6) ) { - - int negate = buffer.charAt(sign) == '-'?-1:1; - //parse hr - int stop = ++sign+2; - data.timezoneHr = negate*parseInt(buffer, sign, stop); - if (buffer.charAt(stop++)!=':') { - throw new RuntimeException("Error in parsing time zone" ); - } - - //parse min - data.timezoneMin = negate*parseInt(buffer, stop, stop+2); - - if ( stop+2!=end ) { - throw new RuntimeException("Error in parsing time zone"); - } - if(data.timezoneHr != 0 || data.timezoneMin != 0) - data.normalized = false; - } - else { - throw new RuntimeException("Error in parsing time zone"); - } - if ( DEBUG ) { - System.out.println("time[hh]="+data.timezoneHr + " time[mm]=" +data.timezoneMin); - } - } - - /** - * Computes index of given char within StringBuffer - * - * @param start - * @param end - * @param ch character to look for in StringBuffer - * @return index of ch within StringBuffer - */ - protected int indexOf (String buffer, int start, int end, char ch) { - for ( int i=start;i12 ) { - throw new RuntimeException("The month must have values 1 to 12"); - - } - - //validate days - if ( data.day>maxDayInMonthFor(data.year, data.month) || data.day<1 ) { - throw new RuntimeException("The day must have values 1 to 31"); - } - - //validate hours - if ( data.hour>23 || data.hour<0 ) { - if (data.hour == 24 && data.minute == 0 && data.second == 0) { - data.hour = 0; - if (++data.day > maxDayInMonthFor(data.year, data.month)) { - data.day = 1; - if (++data.month > 12) { - data.month = 1; - if (Constants.SCHEMA_1_1_SUPPORT) { - ++data.year; - } - else if (++data.year == 0) { - data.year = 1; - } - } - } - } - else { - throw new RuntimeException("Hour must have values 0-23, unless 24:00:00"); - } - } - - //validate - if ( data.minute>59 || data.minute<0 ) { - throw new RuntimeException("Minute must have values 0-59"); - } - - //validate - if ( data.second>=60 || data.second<0 ) { - throw new RuntimeException("Second must have values 0-59"); - - } - - //validate - if ( data.timezoneHr>14 || data.timezoneHr<-14 ) { - throw new RuntimeException("Time zone should have range -14:00 to +14:00"); - } - else { - if((data.timezoneHr == 14 || data.timezoneHr == -14) && data.timezoneMin != 0) - throw new RuntimeException("Time zone should have range -14:00 to +14:00"); - else if(data.timezoneMin > 59 || data.timezoneMin < -59) - throw new RuntimeException("Minute must have values 0-59"); - } - - } - - /** - * Return index of UTC char: 'Z', '+', '-' - * - * @param start - * @param end - * @return index of the UTC character that was found - */ - protected int findUTCSign (String buffer, int start, int end) { - int c; - for ( int i=start;itrue if the character at start is 'Z', '+' or '-'. + * Compare algorithm described in dateDime (3.2.7). Duration datatype + * overwrites this method + * + * @param date1 normalized date representation of the first value + * @param date2 normalized date representation of the second value + * @param strict + * @return less, greater, less_equal, greater_equal, equal + */ + protected short compareDates(DateTimeData date1, DateTimeData date2, boolean strict) { + if (date1.utc == date2.utc) { + return compareOrder(date1, date2); + } + short c1, c2; + + DateTimeData tempDate = new DateTimeData(null, this); + + if (date1.utc == 'Z') { + + //compare date1<=date1<=(date2 with time zone -14) + // + cloneDate(date2, tempDate); //clones date1 value to global temporary storage: fTempDate + tempDate.timezoneHr = 14; + tempDate.timezoneMin = 0; + tempDate.utc = '+'; + normalize(tempDate); + c1 = compareOrder(date1, tempDate); + if (c1 == LESS_THAN) { + return c1; + } + + //compare date1>=(date2 with time zone +14) + // + cloneDate(date2, tempDate); //clones date1 value to global temporary storage: tempDate + tempDate.timezoneHr = -14; + tempDate.timezoneMin = 0; + tempDate.utc = '-'; + normalize(tempDate); + c2 = compareOrder(date1, tempDate); + if (c2 == GREATER_THAN) { + return c2; + } + + return INDETERMINATE; + } else if (date2.utc == 'Z') { + + //compare (date1 with time zone -14)<=date2 + // + cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate + tempDate.timezoneHr = -14; + tempDate.timezoneMin = 0; + tempDate.utc = '-'; + if (DEBUG) { + System.out.println("tempDate=" + dateToString(tempDate)); + } + normalize(tempDate); + c1 = compareOrder(tempDate, date2); + if (DEBUG) { + System.out.println("date=" + dateToString(date2)); + System.out.println("tempDate=" + dateToString(tempDate)); + } + if (c1 == LESS_THAN) { + return c1; + } + + //compare (date1 with time zone +14)<=date2 + // + cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate + tempDate.timezoneHr = 14; + tempDate.timezoneMin = 0; + tempDate.utc = '+'; + normalize(tempDate); + c2 = compareOrder(tempDate, date2); + if (DEBUG) { + System.out.println("tempDate=" + dateToString(tempDate)); + } + if (c2 == GREATER_THAN) { + return c2; + } + + return INDETERMINATE; + } + return INDETERMINATE; + + } + + /** + * Given normalized values, determines order-relation between give date/time + * objects. + * + * @param date1 date/time object + * @param date2 date/time object + * @return 0 if date1 and date2 are equal, a value less than 0 if date1 is + * less than date2, a value greater than 0 if date1 is greater than date2 + */ + protected short compareOrder(DateTimeData date1, DateTimeData date2) { + if (date1.position < 1) { + if (date1.year < date2.year) { + return -1; + } + if (date1.year > date2.year) { + return 1; + } + } + if (date1.position < 2) { + if (date1.month < date2.month) { + return -1; + } + if (date1.month > date2.month) { + return 1; + } + } + if (date1.day < date2.day) { + return -1; + } + if (date1.day > date2.day) { + return 1; + } + if (date1.hour < date2.hour) { + return -1; + } + if (date1.hour > date2.hour) { + return 1; + } + if (date1.minute < date2.minute) { + return -1; + } + if (date1.minute > date2.minute) { + return 1; + } + if (date1.second < date2.second) { + return -1; + } + if (date1.second > date2.second) { + return 1; + } + if (date1.utc < date2.utc) { + return -1; + } + if (date1.utc > date2.utc) { + return 1; + } + return 0; + } + + /** + * Parses time hh:mm:ss.sss and time zone if any + * + * @param start + * @param end + * @param data + * @exception RuntimeException + */ + protected void getTime(String buffer, int start, int end, DateTimeData data) throws RuntimeException { + + int stop = start + 2; + + //get hours (hh) + data.hour = parseInt(buffer, start, stop); + + //get minutes (mm) + + if (buffer.charAt(stop++) != ':') { + throw new RuntimeException("Error in parsing time zone"); + } + start = stop; + stop = stop + 2; + data.minute = parseInt(buffer, start, stop); + + //get seconds (ss) + if (buffer.charAt(stop++) != ':') { + throw new RuntimeException("Error in parsing time zone"); + } + + //find UTC sign if any + int sign = findUTCSign(buffer, start, end); + + //get seconds (ms) + start = stop; + stop = sign < 0 ? end : sign; + data.second = parseSecond(buffer, start, stop); + + //parse UTC time zone (hh:mm) + if (sign > 0) { + getTimeZone(buffer, data, sign, end); + } + } + + /** + * Parses date CCYY-MM-DD + * + * @param buffer + * @param start start position + * @param end end position + * @param date + * @exception RuntimeException + */ + protected int getDate(String buffer, int start, int end, DateTimeData date) throws RuntimeException { + + start = getYearMonth(buffer, start, end, date); + + if (buffer.charAt(start++) != '-') { + throw new RuntimeException("CCYY-MM must be followed by '-' sign"); + } + int stop = start + 2; + date.day = parseInt(buffer, start, stop); + return stop; + } + + /** + * Parses date CCYY-MM + * + * @param buffer + * @param start start position + * @param end end position + * @param date + * @exception RuntimeException + */ + protected int getYearMonth(String buffer, int start, int end, DateTimeData date) throws RuntimeException { + + if (buffer.charAt(0) == '-') { + // REVISIT: date starts with preceding '-' sign + // do we have to do anything with it? + // + start++; + } + int i = indexOf(buffer, start, end, '-'); + if (i == -1) { + throw new RuntimeException("Year separator is missing or misplaced"); + } + int length = i - start; + if (length < 4) { + throw new RuntimeException("Year must have 'CCYY' format"); + } else if (length > 4 && buffer.charAt(start) == '0') { + throw new RuntimeException("Leading zeros are required if the year value would otherwise have fewer than four digits; otherwise they are forbidden"); + } + date.year = parseIntYear(buffer, i); + if (buffer.charAt(i) != '-') { + throw new RuntimeException("CCYY must be followed by '-' sign"); + } + start = ++i; + i = start + 2; + date.month = parseInt(buffer, start, i); + return i; //fStart points right after the MONTH + } + + /** + * Shared code from Date and YearMonth datatypes. Finds if time zone sign is + * present + * + * @param end + * @param date + * @exception RuntimeException + */ + protected void parseTimeZone(String buffer, int start, int end, DateTimeData date) throws RuntimeException { + + //fStart points right after the date + + if (start < end) { + if (!isNextCharUTCSign(buffer, start, end)) { + throw new RuntimeException("Error in month parsing"); + } else { + getTimeZone(buffer, date, start, end); + } + } + } + + /** + * Parses time zone: 'Z' or {+,-} followed by hh:mm + * + * @param data + * @param sign + * @exception RuntimeException + */ + protected void getTimeZone(String buffer, DateTimeData data, int sign, int end) throws RuntimeException { + data.utc = buffer.charAt(sign); + + if (buffer.charAt(sign) == 'Z') { + if (end > (++sign)) { + throw new RuntimeException("Error in parsing time zone"); + } + return; + } + if (sign <= (end - 6)) { + + int negate = buffer.charAt(sign) == '-' ? -1 : 1; + //parse hr + int stop = ++sign + 2; + data.timezoneHr = negate * parseInt(buffer, sign, stop); + if (buffer.charAt(stop++) != ':') { + throw new RuntimeException("Error in parsing time zone"); + } + + //parse min + data.timezoneMin = negate * parseInt(buffer, stop, stop + 2); + + if (stop + 2 != end) { + throw new RuntimeException("Error in parsing time zone"); + } + if (data.timezoneHr != 0 || data.timezoneMin != 0) { + data.normalized = false; + } + } else { + throw new RuntimeException("Error in parsing time zone"); + } + if (DEBUG) { + System.out.println("time[hh]=" + data.timezoneHr + " time[mm]=" + data.timezoneMin); + } + } + + /** + * Computes index of given char within StringBuffer + * + * @param start + * @param end + * @param ch character to look for in StringBuffer + * @return index of ch within StringBuffer + */ + protected int indexOf(String buffer, int start, int end, char ch) { + for (int i = start; i < end; i++) { + if (buffer.charAt(i) == ch) { + return i; + } + } + return -1; + } + + /** + * Validates given date/time object accoring to W3C PR Schema [D.1 ISO 8601 + * Conventions] + * + * @param data + */ + protected void validateDateTime(DateTimeData data) { + + //REVISIT: should we throw an exception for not valid dates + // or reporting an error message should be sufficient? + + /** + * XML Schema 1.1 - RQ-123: Allow year 0000 in date related types. + */ + if (!Constants.SCHEMA_1_1_SUPPORT && data.year == 0) { + throw new RuntimeException("The year \"0000\" is an illegal year value"); + + } + + if (data.month < 1 || data.month > 12) { + throw new RuntimeException("The month must have values 1 to 12"); + + } + + //validate days + if (data.day > maxDayInMonthFor(data.year, data.month) || data.day < 1) { + throw new RuntimeException("The day must have values 1 to 31"); + } + + //validate hours + if (data.hour > 23 || data.hour < 0) { + if (data.hour == 24 && data.minute == 0 && data.second == 0) { + data.hour = 0; + if (++data.day > maxDayInMonthFor(data.year, data.month)) { + data.day = 1; + if (++data.month > 12) { + data.month = 1; + if (Constants.SCHEMA_1_1_SUPPORT) { + ++data.year; + } else if (++data.year == 0) { + data.year = 1; + } + } + } + } else { + throw new RuntimeException("Hour must have values 0-23, unless 24:00:00"); + } + } + + //validate + if (data.minute > 59 || data.minute < 0) { + throw new RuntimeException("Minute must have values 0-59"); + } + + //validate + if (data.second >= 60 || data.second < 0) { + throw new RuntimeException("Second must have values 0-59"); + + } + + //validate + if (data.timezoneHr > 14 || data.timezoneHr < -14) { + throw new RuntimeException("Time zone should have range -14:00 to +14:00"); + } else { + if ((data.timezoneHr == 14 || data.timezoneHr == -14) && data.timezoneMin != 0) { + throw new RuntimeException("Time zone should have range -14:00 to +14:00"); + } else if (data.timezoneMin > 59 || data.timezoneMin < -59) { + throw new RuntimeException("Minute must have values 0-59"); + } + } + + } + + /** + * Return index of UTC char: 'Z', '+', '-' + * + * @param start + * @param end + * @return index of the UTC character that was found + */ + protected int findUTCSign(String buffer, int start, int end) { + int c; + for (int i = start; i < end; i++) { + c = buffer.charAt(i); + if (c == 'Z' || c == '+' || c == '-') { + return i; + } + + } + return -1; + } + + /** + * Returns + * true if the character at start is 'Z', '+' or '-'. */ protected final boolean isNextCharUTCSign(String buffer, int start, int end) { if (start < end) { @@ -510,135 +525,145 @@ public abstract class AbstractDateTimeDV extends TypeValidator { return false; } - /** - * Given start and end position, parses string value - * - * @param buffer string to parse - * @param start start position - * @param end end position - * @return return integer representation of characters - */ - protected int parseInt (String buffer, int start, int end) - throws NumberFormatException{ - //REVISIT: more testing on this parsing needs to be done. - int radix=10; - int result = 0; - int digit=0; - int limit = -Integer.MAX_VALUE; - int multmin = limit / radix; - int i = start; - do { - digit = getDigit(buffer.charAt(i)); - if ( digit < 0 ) throw new NumberFormatException("'" + buffer + "' has wrong format"); - if ( result < multmin ) throw new NumberFormatException("'" + buffer + "' has wrong format"); - result *= radix; - if ( result < limit + digit ) throw new NumberFormatException("'" + buffer + "' has wrong format"); - result -= digit; - - }while ( ++i < end ); - return -result; - } - - // parse Year differently to support negative value. - protected int parseIntYear (String buffer, int end){ - int radix=10; - int result = 0; - boolean negative = false; - int i=0; - int limit; - int multmin; - int digit=0; - - if (buffer.charAt(0) == '-'){ - negative = true; - limit = Integer.MIN_VALUE; - i++; - - } - else{ - limit = -Integer.MAX_VALUE; - } - multmin = limit / radix; - while (i < end) - { - digit = getDigit(buffer.charAt(i++)); - if (digit < 0) throw new NumberFormatException("'" + buffer + "' has wrong format"); - if (result < multmin) throw new NumberFormatException("'" + buffer + "' has wrong format"); - result *= radix; - if (result < limit + digit) throw new NumberFormatException("'" + buffer + "' has wrong format"); - result -= digit; - } - - if (negative) - { - if (i > 1) return result; - else throw new NumberFormatException("'" + buffer + "' has wrong format"); - } - return -result; - - } - - /** - * If timezone present - normalize dateTime [E Adding durations to dateTimes] - * - * @param date CCYY-MM-DDThh:mm:ss+03 - */ - protected void normalize(DateTimeData date) { - - // REVISIT: we have common code in addDuration() for durations - // should consider reorganizing it. - // - - //add minutes (from time zone) - int negate = -1; - - if ( DEBUG ) { - System.out.println("==>date.minute"+date.minute); - System.out.println("==>date.timezoneMin" +date.timezoneMin); - } - int temp = date.minute + negate * date.timezoneMin; - int carry = fQuotient (temp, 60); - date.minute= mod(temp, 60, carry); - - if ( DEBUG ) { - System.out.println("==>carry: " + carry); - } - //add hours - temp = date.hour + negate * date.timezoneHr + carry; - carry = fQuotient(temp, 24); - date.hour=mod(temp, 24, carry); - if ( DEBUG ) { - System.out.println("==>date.hour"+date.hour); - System.out.println("==>carry: " + carry); - } - - date.day=date.day+carry; - - while ( true ) { - temp=maxDayInMonthFor(date.year, date.month); - if (date.day<1) { - date.day = date.day + maxDayInMonthFor(date.year, date.month-1); - carry=-1; - } - else if ( date.day>temp ) { - date.day=date.day-temp; - carry=1; - } - else { - break; - } - temp=date.month+carry; - date.month=modulo(temp, 1, 13); - date.year=date.year+fQuotient(temp, 1, 13); - if(date.year == 0 && !Constants.SCHEMA_1_1_SUPPORT) { - date.year = (date.timezoneHr < 0 || date.timezoneMin < 0)?1:-1; + /** + * Given start and end position, parses string value + * + * @param buffer string to parse + * @param start start position + * @param end end position + * @return return integer representation of characters + */ + protected int parseInt(String buffer, int start, int end) + throws NumberFormatException { + //REVISIT: more testing on this parsing needs to be done. + int radix = 10; + int result = 0; + int digit = 0; + int limit = -Integer.MAX_VALUE; + int multmin = limit / radix; + int i = start; + do { + digit = getDigit(buffer.charAt(i)); + if (digit < 0) { + throw new NumberFormatException("'" + buffer + "' has wrong format"); } - } - date.utc='Z'; + if (result < multmin) { + throw new NumberFormatException("'" + buffer + "' has wrong format"); + } + result *= radix; + if (result < limit + digit) { + throw new NumberFormatException("'" + buffer + "' has wrong format"); + } + result -= digit; + + } while (++i < end); + return -result; + } + + // parse Year differently to support negative value. + protected int parseIntYear(String buffer, int end) { + int radix = 10; + int result = 0; + boolean negative = false; + int i = 0; + int limit; + int multmin; + int digit = 0; + + if (buffer.charAt(0) == '-') { + negative = true; + limit = Integer.MIN_VALUE; + i++; + + } else { + limit = -Integer.MAX_VALUE; + } + multmin = limit / radix; + while (i < end) { + digit = getDigit(buffer.charAt(i++)); + if (digit < 0) { + throw new NumberFormatException("'" + buffer + "' has wrong format"); + } + if (result < multmin) { + throw new NumberFormatException("'" + buffer + "' has wrong format"); + } + result *= radix; + if (result < limit + digit) { + throw new NumberFormatException("'" + buffer + "' has wrong format"); + } + result -= digit; } + if (negative) { + if (i > 1) { + return result; + } else { + throw new NumberFormatException("'" + buffer + "' has wrong format"); + } + } + return -result; - /** + } + + /** + * If timezone present - normalize dateTime [E Adding durations to + * dateTimes] + * + * @param date CCYY-MM-DDThh:mm:ss+03 + */ + protected void normalize(DateTimeData date) { + + // REVISIT: we have common code in addDuration() for durations + // should consider reorganizing it. + // + + //add minutes (from time zone) + int negate = -1; + + if (DEBUG) { + System.out.println("==>date.minute" + date.minute); + System.out.println("==>date.timezoneMin" + date.timezoneMin); + } + int temp = date.minute + negate * date.timezoneMin; + int carry = fQuotient(temp, 60); + date.minute = mod(temp, 60, carry); + + if (DEBUG) { + System.out.println("==>carry: " + carry); + } + //add hours + temp = date.hour + negate * date.timezoneHr + carry; + carry = fQuotient(temp, 24); + date.hour = mod(temp, 24, carry); + if (DEBUG) { + System.out.println("==>date.hour" + date.hour); + System.out.println("==>carry: " + carry); + } + + date.day = date.day + carry; + + while (true) { + temp = maxDayInMonthFor(date.year, date.month); + if (date.day < 1) { + date.day = date.day + maxDayInMonthFor(date.year, date.month - 1); + carry = -1; + } else if (date.day > temp) { + date.day = date.day - temp; + carry = 1; + } else { + break; + } + temp = date.month + carry; + date.month = modulo(temp, 1, 13); + date.year = date.year + fQuotient(temp, 1, 13); + if (date.year == 0 && !Constants.SCHEMA_1_1_SUPPORT) { + date.year = (date.timezoneHr < 0 || date.timezoneMin < 0) ? 1 : -1; + } + } + date.utc = 'Z'; + } + + /** * @param date */ protected void saveUnnormalized(DateTimeData date) { @@ -651,154 +676,149 @@ public abstract class AbstractDateTimeDV extends TypeValidator { } /** - * Resets object representation of date/time - * - * @param data date/time object - */ - protected void resetDateObj(DateTimeData data) { - data.year = 0; - data.month = 0; - data.day = 0; - data.hour = 0; - data.minute = 0; - data.second = 0; - data.utc = 0; - data.timezoneHr = 0; - data.timezoneMin = 0; + * Resets object representation of date/time + * + * @param data date/time object + */ + protected void resetDateObj(DateTimeData data) { + data.year = 0; + data.month = 0; + data.day = 0; + data.hour = 0; + data.minute = 0; + data.second = 0; + data.utc = 0; + data.timezoneHr = 0; + data.timezoneMin = 0; + } + + /** + * Given {year,month} computes maximum number of days for given month + * + * @param year + * @param month + * @return integer containg the number of days in a given month + */ + protected int maxDayInMonthFor(int year, int month) { + //validate days + if (month == 4 || month == 6 || month == 9 || month == 11) { + return 30; + } else if (month == 2) { + if (isLeapYear(year)) { + return 29; + } else { + return 28; + } + } else { + return 31; } + } - /** - * Given {year,month} computes maximum - * number of days for given month - * - * @param year - * @param month - * @return integer containg the number of days in a given month - */ - protected int maxDayInMonthFor(int year, int month) { - //validate days - if ( month==4 || month==6 || month==9 || month==11 ) { - return 30; - } - else if ( month==2 ) { - if ( isLeapYear(year) ) { - return 29; - } - else { - return 28; - } - } - else { - return 31; - } - } + private boolean isLeapYear(int year) { - private boolean isLeapYear(int year) { + //REVISIT: should we take care about Julian calendar? + return ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))); + } - //REVISIT: should we take care about Julian calendar? - return((year%4 == 0) && ((year%100 != 0) || (year%400 == 0))); - } + // + // help function described in W3C PR Schema [E Adding durations to dateTimes] + // + protected int mod(int a, int b, int quotient) { + //modulo(a, b) = a - fQuotient(a,b)*b + return (a - quotient * b); + } - // - // help function described in W3C PR Schema [E Adding durations to dateTimes] - // - protected int mod (int a, int b, int quotient) { - //modulo(a, b) = a - fQuotient(a,b)*b - return (a - quotient*b) ; - } + // + // help function described in W3C PR Schema [E Adding durations to dateTimes] + // + protected int fQuotient(int a, int b) { - // - // help function described in W3C PR Schema [E Adding durations to dateTimes] - // - protected int fQuotient (int a, int b) { + //fQuotient(a, b) = the greatest integer less than or equal to a/b + return (int) Math.floor((float) a / b); + } - //fQuotient(a, b) = the greatest integer less than or equal to a/b - return (int)Math.floor((float)a/b); - } + // + // help function described in W3C PR Schema [E Adding durations to dateTimes] + // + protected int modulo(int temp, int low, int high) { + //modulo(a - low, high - low) + low + int a = temp - low; + int b = high - low; + return (mod(a, b, fQuotient(a, b)) + low); + } - // - // help function described in W3C PR Schema [E Adding durations to dateTimes] - // - protected int modulo (int temp, int low, int high) { - //modulo(a - low, high - low) + low - int a = temp - low; - int b = high - low; - return (mod (a, b, fQuotient(a, b)) + low) ; - } + // + // help function described in W3C PR Schema [E Adding durations to dateTimes] + // + protected int fQuotient(int temp, int low, int high) { + //fQuotient(a - low, high - low) - // - // help function described in W3C PR Schema [E Adding durations to dateTimes] - // - protected int fQuotient (int temp, int low, int high) { - //fQuotient(a - low, high - low) + return fQuotient(temp - low, high - low); + } - return fQuotient(temp - low, high - low); - } + protected String dateToString(DateTimeData date) { + StringBuffer message = new StringBuffer(25); + append(message, date.year, 4); + message.append('-'); + append(message, date.month, 2); + message.append('-'); + append(message, date.day, 2); + message.append('T'); + append(message, date.hour, 2); + message.append(':'); + append(message, date.minute, 2); + message.append(':'); + append(message, date.second); + append(message, (char) date.utc, 0); + return message.toString(); + } - - protected String dateToString(DateTimeData date) { - StringBuffer message = new StringBuffer(25); - append(message, date.year, 4); - message.append('-'); - append(message, date.month, 2); - message.append('-'); - append(message, date.day, 2); - message.append('T'); - append(message, date.hour, 2); - message.append(':'); - append(message, date.minute, 2); - message.append(':'); - append(message, date.second); - append(message, (char)date.utc, 0); - return message.toString(); - } - - protected final void append(StringBuffer message, int value, int nch) { + protected final void append(StringBuffer message, int value, int nch) { if (value == Integer.MIN_VALUE) { message.append(value); return; } - if (value < 0) { - message.append('-'); - value = -value; - } - if (nch == 4) { - if (value < 10) - message.append("000"); - else if (value < 100) - message.append("00"); - else if (value < 1000) - message.append('0'); - message.append(value); - } - else if (nch == 2) { - if (value < 10) - message.append('0'); - message.append(value); - } - else { - if (value != 0) - message.append((char)value); - } + if (value < 0) { + message.append('-'); + value = -value; } - - protected final void append(StringBuffer message, double value) { - if (value < 0) { - message.append('-'); - value = -value; + if (nch == 4) { + if (value < 10) { + message.append("000"); + } else if (value < 100) { + message.append("00"); + } else if (value < 1000) { + message.append('0'); } + message.append(value); + } else if (nch == 2) { if (value < 10) { message.append('0'); } - append2(message, value); + message.append(value); + } else { + if (value != 0) { + message.append((char) value); + } } + } + + protected final void append(StringBuffer message, double value) { + if (value < 0) { + message.append('-'); + value = -value; + } + if (value < 10) { + message.append('0'); + } + append2(message, value); + } protected final void append2(StringBuffer message, double value) { final int intValue = (int) value; if (value == intValue) { message.append(intValue); - } - else { + } else { append3(message, value); } } @@ -815,9 +835,8 @@ public abstract class AbstractDateTimeDV extends TypeValidator { // Need to convert from scientific notation of the form // n.nnn...E-N (N >= 4) to a normal decimal value. try { - exp = parseInt(d, eIndex+2, d.length()); - } - // This should never happen. + exp = parseInt(d, eIndex + 2, d.length()); + } // This should never happen. // It's only possible if String.valueOf(double) is broken. catch (Exception e) { message.append(d); @@ -843,14 +862,12 @@ public abstract class AbstractDateTimeDV extends TypeValidator { message.append(c); } } - } - else { + } else { // Need to convert from scientific notation of the form // n.nnn...EN (N >= 7) to a normal decimal value. try { - exp = parseInt(d, eIndex+1, d.length()); - } - // This should never happen. + exp = parseInt(d, eIndex + 1, d.length()); + } // This should never happen. // It's only possible if String.valueOf(double) is broken. catch (Exception e) { message.append(d); @@ -873,174 +890,220 @@ public abstract class AbstractDateTimeDV extends TypeValidator { } } - protected double parseSecond(String buffer, int start, int end) - throws NumberFormatException { - int dot = -1; - for (int i = start; i < end; i++) { - char ch = buffer.charAt(i); - if (ch == '.') - dot = i; - else if (ch > '9' || ch < '0') - throw new NumberFormatException("'" + buffer + "' has wrong format"); - } - if (dot == -1) { - if (start+2 != end) - throw new NumberFormatException("'" + buffer + "' has wrong format"); - } - else if (start+2 != dot || dot+1 == end) { - throw new NumberFormatException("'" + buffer + "' has wrong format"); - } - return Double.parseDouble(buffer.substring(start, end)); + protected double parseSecond(String buffer, int start, int end) + throws NumberFormatException { + int dot = -1; + for (int i = start; i < end; i++) { + char ch = buffer.charAt(i); + if (ch == '.') { + dot = i; + } else if (ch > '9' || ch < '0') { + throw new NumberFormatException("'" + buffer + "' has wrong format"); + } } - - // - //Private help functions - // - - private void cloneDate (DateTimeData finalValue, DateTimeData tempDate) { - tempDate.year = finalValue.year; - tempDate.month = finalValue.month; - tempDate.day = finalValue.day; - tempDate.hour = finalValue.hour; - tempDate.minute = finalValue.minute; - tempDate.second = finalValue.second; - tempDate.utc = finalValue.utc; - tempDate.timezoneHr = finalValue.timezoneHr; - tempDate.timezoneMin = finalValue.timezoneMin; + if (dot == -1) { + if (start + 2 != end) { + throw new NumberFormatException("'" + buffer + "' has wrong format"); + } + } else if (start + 2 != dot || dot + 1 == end) { + throw new NumberFormatException("'" + buffer + "' has wrong format"); } + return Double.parseDouble(buffer.substring(start, end)); + } - /** - * Represents date time data - */ - static final class DateTimeData implements XSDateTime { - int year, month, day, hour, minute, utc; - double second; - int timezoneHr, timezoneMin; + // + //Private help functions + // + private void cloneDate(DateTimeData finalValue, DateTimeData tempDate) { + tempDate.year = finalValue.year; + tempDate.month = finalValue.month; + tempDate.day = finalValue.day; + tempDate.hour = finalValue.hour; + tempDate.minute = finalValue.minute; + tempDate.second = finalValue.second; + tempDate.utc = finalValue.utc; + tempDate.timezoneHr = finalValue.timezoneHr; + tempDate.timezoneMin = finalValue.timezoneMin; + } + + /** + * Represents date time data + */ + static final class DateTimeData implements XSDateTime { + + int year, month, day, hour, minute, utc; + double second; + int timezoneHr, timezoneMin; private String originalValue; boolean normalized = true; - int unNormYear; int unNormMonth; int unNormDay; int unNormHour; int unNormMinute; double unNormSecond; + // used for comparisons - to decide the 'interesting' portions of + // a date/time based data type. + int position; + // a pointer to the type that was used go generate this data + // note that this is not the actual simple type, but one of the + // statically created XXXDV objects, so this won't cause any GC problem. + final AbstractDateTimeDV type; + private volatile String canonical; - // used for comparisons - to decide the 'interesting' portions of - // a date/time based data type. - int position; - // a pointer to the type that was used go generate this data - // note that this is not the actual simple type, but one of the - // statically created XXXDV objects, so this won't cause any GC problem. - final AbstractDateTimeDV type; - private String canonical; - public DateTimeData(String originalValue, AbstractDateTimeDV type) { + public DateTimeData(String originalValue, AbstractDateTimeDV type) { this.originalValue = originalValue; - this.type = type; - } - public DateTimeData(int year, int month, int day, int hour, int minute, - double second, int utc, String originalValue, boolean normalized, AbstractDateTimeDV type) { - this.year = year; - this.month = month; - this.day = day; - this.hour = hour; - this.minute = minute; - this.second = second; - this.utc = utc; - this.type = type; + this.type = type; + } + + public DateTimeData(int year, int month, int day, int hour, int minute, + double second, int utc, String originalValue, boolean normalized, AbstractDateTimeDV type) { + this.year = year; + this.month = month; + this.day = day; + this.hour = hour; + this.minute = minute; + this.second = second; + this.utc = utc; + this.type = type; this.originalValue = originalValue; - } - public boolean equals(Object obj) { - if (!(obj instanceof DateTimeData)) - return false; - return type.compareDates(this, (DateTimeData)obj, true)==0; - } - public synchronized String toString() { - if (canonical == null) { - canonical = type.dateToString(this); - } - return canonical; - } - /* (non-Javadoc) - * @see org.apache.xerces.xs.datatypes.XSDateTime#getYear() - */ - public int getYears() { - if(type instanceof DurationDV) - return 0; - return normalized?year:unNormYear; - } - /* (non-Javadoc) - * @see org.apache.xerces.xs.datatypes.XSDateTime#getMonth() - */ - public int getMonths() { - if(type instanceof DurationDV) { - return year*12 + month; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof DateTimeData)) { + return false; } - return normalized?month:unNormMonth; - } - /* (non-Javadoc) - * @see org.apache.xerces.xs.datatypes.XSDateTime#getDay() - */ - public int getDays() { - if(type instanceof DurationDV) - return 0; - return normalized?day:unNormDay; - } - /* (non-Javadoc) - * @see org.apache.xerces.xs.datatypes.XSDateTime#getHour() - */ - public int getHours() { - if(type instanceof DurationDV) - return 0; - return normalized?hour:unNormHour; - } - /* (non-Javadoc) - * @see org.apache.xerces.xs.datatypes.XSDateTime#getMinutes() - */ - public int getMinutes() { - if(type instanceof DurationDV) - return 0; - return normalized?minute:unNormMinute; - } - /* (non-Javadoc) - * @see org.apache.xerces.xs.datatypes.XSDateTime#getSeconds() - */ - public double getSeconds() { - if(type instanceof DurationDV) { - return day*24*60*60 + hour*60*60 + minute*60 + second; + return type.compareDates(this, (DateTimeData) obj, true) == 0; + } + + // If two DateTimeData are equals - then they should have the same + // hashcode. This means we need to convert the date to UTC before + // we return its hashcode. + // The DateTimeData is unfortunately mutable - so we cannot + // cache the result of the conversion... + // + @Override + public int hashCode() { + final DateTimeData tempDate = new DateTimeData(null, type); + type.cloneDate(this, tempDate); + type.normalize(tempDate); + return type.dateToString(tempDate).hashCode(); + } + + @Override + public String toString() { + if (canonical == null) { + canonical = type.dateToString(this); } - return normalized?second:unNormSecond; - } - /* (non-Javadoc) - * @see org.apache.xerces.xs.datatypes.XSDateTime#hasTimeZone() - */ - public boolean hasTimeZone() { - return utc != 0; - } - /* (non-Javadoc) - * @see org.apache.xerces.xs.datatypes.XSDateTime#getTimeZoneHours() - */ - public int getTimeZoneHours() { - return timezoneHr; - } - /* (non-Javadoc) - * @see org.apache.xerces.xs.datatypes.XSDateTime#getTimeZoneMinutes() - */ - public int getTimeZoneMinutes() { - return timezoneMin; - } + return canonical; + } + /* (non-Javadoc) + * @see org.apache.xerces.xs.datatypes.XSDateTime#getYear() + */ + + @Override + public int getYears() { + if (type instanceof DurationDV) { + return 0; + } + return normalized ? year : unNormYear; + } + /* (non-Javadoc) + * @see org.apache.xerces.xs.datatypes.XSDateTime#getMonth() + */ + + @Override + public int getMonths() { + if (type instanceof DurationDV) { + return year * 12 + month; + } + return normalized ? month : unNormMonth; + } + /* (non-Javadoc) + * @see org.apache.xerces.xs.datatypes.XSDateTime#getDay() + */ + + @Override + public int getDays() { + if (type instanceof DurationDV) { + return 0; + } + return normalized ? day : unNormDay; + } + /* (non-Javadoc) + * @see org.apache.xerces.xs.datatypes.XSDateTime#getHour() + */ + + @Override + public int getHours() { + if (type instanceof DurationDV) { + return 0; + } + return normalized ? hour : unNormHour; + } + /* (non-Javadoc) + * @see org.apache.xerces.xs.datatypes.XSDateTime#getMinutes() + */ + + @Override + public int getMinutes() { + if (type instanceof DurationDV) { + return 0; + } + return normalized ? minute : unNormMinute; + } + /* (non-Javadoc) + * @see org.apache.xerces.xs.datatypes.XSDateTime#getSeconds() + */ + + @Override + public double getSeconds() { + if (type instanceof DurationDV) { + return day * 24 * 60 * 60 + hour * 60 * 60 + minute * 60 + second; + } + return normalized ? second : unNormSecond; + } + /* (non-Javadoc) + * @see org.apache.xerces.xs.datatypes.XSDateTime#hasTimeZone() + */ + + @Override + public boolean hasTimeZone() { + return utc != 0; + } + /* (non-Javadoc) + * @see org.apache.xerces.xs.datatypes.XSDateTime#getTimeZoneHours() + */ + + @Override + public int getTimeZoneHours() { + return timezoneHr; + } + /* (non-Javadoc) + * @see org.apache.xerces.xs.datatypes.XSDateTime#getTimeZoneMinutes() + */ + + @Override + public int getTimeZoneMinutes() { + return timezoneMin; + } /* (non-Javadoc) * @see org.apache.xerces.xs.datatypes.XSDateTime#getLexicalValue() */ + + @Override public String getLexicalValue() { return originalValue; } /* (non-Javadoc) * @see org.apache.xerces.xs.datatypes.XSDateTime#normalize() */ + + @Override public XSDateTime normalize() { - if(!normalized) { - DateTimeData dt = (DateTimeData)this.clone(); + if (!normalized) { + DateTimeData dt = (DateTimeData) this.clone(); dt.normalized = true; return dt; } @@ -1049,13 +1112,16 @@ public abstract class AbstractDateTimeDV extends TypeValidator { /* (non-Javadoc) * @see org.apache.xerces.xs.datatypes.XSDateTime#isNormalized() */ + + @Override public boolean isNormalized() { return normalized; } + @Override public Object clone() { DateTimeData dt = new DateTimeData(this.year, this.month, this.day, this.hour, - this.minute, this.second, this.utc, this.originalValue, this.normalized, this.type); + this.minute, this.second, this.utc, this.originalValue, this.normalized, this.type); dt.canonical = this.canonical; dt.position = position; dt.timezoneHr = this.timezoneHr; @@ -1072,16 +1138,19 @@ public abstract class AbstractDateTimeDV extends TypeValidator { /* (non-Javadoc) * @see org.apache.xerces.xs.datatypes.XSDateTime#getXMLGregorianCalendar() */ + @Override public XMLGregorianCalendar getXMLGregorianCalendar() { return type.getXMLGregorianCalendar(this); } /* (non-Javadoc) * @see org.apache.xerces.xs.datatypes.XSDateTime#getDuration() */ + + @Override public Duration getDuration() { return type.getDuration(this); } - } + } protected XMLGregorianCalendar getXMLGregorianCalendar(DateTimeData data) { return null; diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/DecimalDV.java b/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/DecimalDV.java index ce616113c04..622042b37cf 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/DecimalDV.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/DecimalDV.java @@ -26,6 +26,7 @@ import java.math.BigInteger; import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException; import com.sun.org.apache.xerces.internal.impl.dv.ValidationContext; import com.sun.org.apache.xerces.internal.xs.datatypes.XSDecimal; +import java.util.Objects; /** * Represent the schema type "decimal" @@ -38,10 +39,12 @@ import com.sun.org.apache.xerces.internal.xs.datatypes.XSDecimal; */ public class DecimalDV extends TypeValidator { + @Override public final short getAllowedFacets(){ return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE | XSSimpleTypeDecl.FACET_TOTALDIGITS | XSSimpleTypeDecl.FACET_FRACTIONDIGITS); } + @Override public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException { try { return new XDecimal(content); @@ -50,20 +53,23 @@ public class DecimalDV extends TypeValidator { } } + @Override public final int compare(Object value1, Object value2){ return ((XDecimal)value1).compareTo((XDecimal)value2); } + @Override public final int getTotalDigits(Object value){ return ((XDecimal)value).totalDigits; } + @Override public final int getFractionDigits(Object value){ return ((XDecimal)value).fracDigits; } // Avoid using the heavy-weight java.math.BigDecimal - static class XDecimal implements XSDecimal { + static final class XDecimal implements XSDecimal { // sign: 0 for vlaue 0; 1 for positive values; -1 for negative values int sign = 1; // total digits. >= 1 @@ -216,6 +222,8 @@ public class DecimalDV extends TypeValidator { integer = true; } + + @Override public boolean equals(Object val) { if (val == this) return true; @@ -232,6 +240,19 @@ public class DecimalDV extends TypeValidator { return intDigits == oval.intDigits && fracDigits == oval.fracDigits && ivalue.equals(oval.ivalue) && fvalue.equals(oval.fvalue); } + + @Override + public int hashCode() { + int hash = 7; + hash = 17 * hash + this.sign; + if (this.sign == 0) return hash; + hash = 17 * hash + this.intDigits; + hash = 17 * hash + this.fracDigits; + hash = 17 * hash + Objects.hashCode(this.ivalue); + hash = 17 * hash + Objects.hashCode(this.fvalue); + return hash; + } + public int compareTo(XDecimal val) { if (sign != val.sign) return sign > val.sign ? 1 : -1; @@ -248,7 +269,9 @@ public class DecimalDV extends TypeValidator { ret = fvalue.compareTo(val.fvalue); return ret == 0 ? 0 : (ret > 0 ? 1 : -1); } + private String canonical; + @Override public synchronized String toString() { if (canonical == null) { makeCanonical(); @@ -269,7 +292,7 @@ public class DecimalDV extends TypeValidator { return; } // for -0.1, total digits is 1, so we need 3 extra spots - StringBuffer buffer = new StringBuffer(totalDigits+3); + final StringBuilder buffer = new StringBuilder(totalDigits+3); if (sign == -1) buffer.append('-'); if (intDigits != 0) @@ -288,6 +311,7 @@ public class DecimalDV extends TypeValidator { canonical = buffer.toString(); } + @Override public BigDecimal getBigDecimal() { if (sign == 0) { return new BigDecimal(BigInteger.ZERO); @@ -295,6 +319,7 @@ public class DecimalDV extends TypeValidator { return new BigDecimal(toString()); } + @Override public BigInteger getBigInteger() throws NumberFormatException { if (fracDigits != 0) { throw new NumberFormatException(); @@ -308,6 +333,7 @@ public class DecimalDV extends TypeValidator { return new BigInteger("-" + ivalue); } + @Override public long getLong() throws NumberFormatException { if (fracDigits != 0) { throw new NumberFormatException(); @@ -321,6 +347,7 @@ public class DecimalDV extends TypeValidator { return Long.parseLong("-" + ivalue); } + @Override public int getInt() throws NumberFormatException { if (fracDigits != 0) { throw new NumberFormatException(); @@ -334,6 +361,7 @@ public class DecimalDV extends TypeValidator { return Integer.parseInt("-" + ivalue); } + @Override public short getShort() throws NumberFormatException { if (fracDigits != 0) { throw new NumberFormatException(); @@ -347,6 +375,7 @@ public class DecimalDV extends TypeValidator { return Short.parseShort("-" + ivalue); } + @Override public byte getByte() throws NumberFormatException { if (fracDigits != 0) { throw new NumberFormatException(); diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/PrecisionDecimalDV.java b/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/PrecisionDecimalDV.java index af8d8d499dc..a75f03a03ea 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/PrecisionDecimalDV.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/PrecisionDecimalDV.java @@ -32,7 +32,7 @@ import com.sun.org.apache.xerces.internal.impl.dv.ValidationContext; */ class PrecisionDecimalDV extends TypeValidator { - static class XPrecisionDecimal { + static final class XPrecisionDecimal { // sign: 0 for absent; 1 for positive values; -1 for negative values (except in case of INF, -INF) int sign = 1; @@ -144,7 +144,71 @@ class PrecisionDecimalDV extends TypeValidator { totalDigits = intDigits + fracDigits; } + // Construct a canonical String representation of this number + // for the purpose of deriving a hashCode value compliant with + // equals. + // The toString representation will be: + // NaN for NaN, INF for +infinity, -INF for -infinity, 0 for zero, + // and [1-9].[0-9]*[1-9]?(E[1-9][0-9]*)? for other numbers. + private static String canonicalToStringForHashCode(String ivalue, String fvalue, int sign, int pvalue) { + if ("NaN".equals(ivalue)) { + return "NaN"; + } + if ("INF".equals(ivalue)) { + return sign < 0 ? "-INF" : "INF"; + } + final StringBuilder builder = new StringBuilder(); + final int ilen = ivalue.length(); + final int flen0 = fvalue.length(); + int lastNonZero; + for (lastNonZero = flen0; lastNonZero > 0 ; lastNonZero--) { + if (fvalue.charAt(lastNonZero -1 ) != '0') break; + } + final int flen = lastNonZero; + int iStart; + int exponent = pvalue; + for (iStart = 0; iStart < ilen; iStart++) { + if (ivalue.charAt(iStart) != '0') break; + } + int fStart = 0; + if (iStart < ivalue.length()) { + builder.append(sign == -1 ? "-" : ""); + builder.append(ivalue.charAt(iStart)); + iStart++; + } else { + if (flen > 0) { + for (fStart = 0; fStart < flen; fStart++) { + if (fvalue.charAt(fStart) != '0') break; + } + if (fStart < flen) { + builder.append(sign == -1 ? "-" : ""); + builder.append(fvalue.charAt(fStart)); + exponent -= ++fStart; + } else { + return "0"; + } + } else { + return "0"; + } + } + if (iStart < ilen || fStart < flen) { + builder.append('.'); + } + while (iStart < ilen) { + builder.append(ivalue.charAt(iStart++)); + exponent++; + } + while (fStart < flen) { + builder.append(fvalue.charAt(fStart++)); + } + if (exponent != 0) { + builder.append("E").append(exponent); + } + return builder.toString(); + } + + @Override public boolean equals(Object val) { if (val == this) return true; @@ -156,6 +220,20 @@ class PrecisionDecimalDV extends TypeValidator { return this.compareTo(oval) == EQUAL; } + @Override + public int hashCode() { + // There's nothing else we can use easily, because equals could + // return true for widely different representation of the + // same number - and we don't have any canonical representation. + // The problem here is that we must ensure that if two numbers + // are equals then their hash code must also be equals. + // hashCode for 1.01E1 should be the same as hashCode for 0.101E2 + // So we call cannonicalToStringForHashCode - which implements an + // algorithm that invents a normalized string representation + // for this number, and we return a hash for that. + return canonicalToStringForHashCode(ivalue, fvalue, sign, pvalue).hashCode(); + } + /** * @return */ @@ -295,6 +373,7 @@ class PrecisionDecimalDV extends TypeValidator { private String canonical; + @Override public synchronized String toString() { if (canonical == null) { makeCanonical(); @@ -325,6 +404,7 @@ class PrecisionDecimalDV extends TypeValidator { /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.impl.dv.xs.TypeValidator#getAllowedFacets() */ + @Override public short getAllowedFacets() { return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE | XSSimpleTypeDecl.FACET_TOTALDIGITS | XSSimpleTypeDecl.FACET_FRACTIONDIGITS); } @@ -332,6 +412,7 @@ class PrecisionDecimalDV extends TypeValidator { /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.impl.dv.xs.TypeValidator#getActualValue(java.lang.String, com.sun.org.apache.xerces.internal.impl.dv.ValidationContext) */ + @Override public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException { try { @@ -341,18 +422,22 @@ class PrecisionDecimalDV extends TypeValidator { } } + @Override public int compare(Object value1, Object value2) { return ((XPrecisionDecimal)value1).compareTo((XPrecisionDecimal)value2); } + @Override public int getFractionDigits(Object value) { return ((XPrecisionDecimal)value).fracDigits; } + @Override public int getTotalDigits(Object value) { return ((XPrecisionDecimal)value).totalDigits; } + @Override public boolean isIdentical(Object value1, Object value2) { if(!(value2 instanceof XPrecisionDecimal) || !(value1 instanceof XPrecisionDecimal)) return false; diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages.properties index 5a06fa07fed..ea35c9e8377 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages.properties @@ -11,7 +11,7 @@ FallbackChild = Elements from namespace ''http://www.w3.org/2001/XInclude'', oth HrefMissing = The 'href' attribute of an 'include' element is missing. RecursiveInclude = Recursive include detected. Document ''{0}'' was already processed. InvalidParseValue = Invalid value for ''parse'' attribute on ''include'' element: ''{0}''. -XMLParseError = Error attempting to parse XML file (href=''{0}''). +XMLParseError = Error attempting to parse XML file (href=''{0}''). Reason: {1} XMLResourceError = Include operation failed, reverting to fallback. Resource error reading file as XML (href=''{0}''). Reason: {1} TextResourceError = Include operation failed, reverting to fallback. Resource error reading file as text (href=''{0}''). Reason: {1} NO_XPointerSchema = Schema for \"{0}\" is not supported by default. Define your own schema for {0}.See http://apache.org/xml/properties/xpointer-schema diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties index 5a05972a6d9..58c045b8d32 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties @@ -39,7 +39,7 @@ FallbackChild = Andere Elemente aus Namespace "http://www.w3.org/2001/XInclude" HrefMissing = "href"-Attribut eines "include"-Elements fehlt. RecursiveInclude = Rekursives "include" ermittelt. Dokument "{0}" wurde bereits verarbeitet. InvalidParseValue = Ung\u00FCltiger Wert f\u00FCr "parse"-Attribut bei "include"-Element: "{0}". -XMLParseError = Fehler beim Versuch, XML-Datei zu parsen (href="{0}"). +XMLParseError = Fehler beim Versuch, XML-Datei zu parsen (href="{0}"). Grund: {1} XMLResourceError = Include-Vorgang nicht erfolgreich. Zur\u00FCck zu Fallback. Ressourcenfehler beim Lesen der Datei als XML (href="{0}"). Grund: {1} TextResourceError = Include-Vorgang nicht erfolgreich. Zur\u00FCck zu Fallback. Ressourcenfehler beim Lesen der Datei als Text (href="{0}"). Grund: {1} NO_XPointerSchema = Schema f\u00FCr \"{0}\" wird standardm\u00E4\u00DFig nicht unterst\u00FCtzt. Definieren Sie Ihr eigenes Schema f\u00FCr {0}. Siehe http://apache.org/xml/properties/xpointer-schema diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_es.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_es.properties index 59b669f997f..2bf1f2b47b0 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_es.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_es.properties @@ -39,7 +39,7 @@ FallbackChild = No se permite que los elementos del espacio de nombres ''http:// HrefMissing = Falta el atributo 'href' de un elemento 'include'. RecursiveInclude = Se ha detectado un elemento include recursivo. El documento ''{0}'' ya se ha procesado. InvalidParseValue = Valor no v\u00E1lido para el atributo ''parse'' en el elemento ''include'': ''{0}''. -XMLParseError = Error al intentar analizar el archivo XML (href=''{0}''). +XMLParseError = Error al intentar analizar el archivo XML (href=''{0}''). Motivo: {1} XMLResourceError = Fallo de la operaci\u00F3n include, conversi\u00F3n a fallback. Error del recurso al leer el archivo como XML (href=''{0}''). Motivo: {1} TextResourceError = Fallo de la operaci\u00F3n include, conversi\u00F3n a fallback. Error del recurso al leer el archivo como texto (href=''{0}''). Motivo: {1} NO_XPointerSchema = El esquema para \"{0}\" no est\u00E1 soportado por defecto. Defina su propio esquema para {0}. Consulte http://apache.org/xml/properties/xpointer-schema diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_fr.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_fr.properties index c5f36660a2a..9a22cb4e2f2 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_fr.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_fr.properties @@ -39,7 +39,7 @@ FallbackChild = Les \u00E9l\u00E9ments de l''espace de noms ''http://www.w3.org/ HrefMissing = L'attribut 'href' d'un \u00E9l\u00E9ment 'include' est manquant. RecursiveInclude = El\u00E9ment "include" r\u00E9cursif d\u00E9tect\u00E9. Le document ''{0}'' a d\u00E9j\u00E0 \u00E9t\u00E9 trait\u00E9. InvalidParseValue = Valeur non valide pour l''attribut ''parse'' sur l''\u00E9l\u00E9ment ''include'' : ''{0}''. -XMLParseError = Erreur lors de la tentative d''analyse du fichier XML (href=''{0}''). +XMLParseError = Erreur lors de la tentative d''analyse du fichier XML (href=''{0}''). Raison : {1} XMLResourceError = Echec de l''op\u00E9ration Include, r\u00E9tablissement de l''\u00E9l\u00E9ment fallback. Erreur de ressource lors de la lecture du fichier en tant que XML (href=''{0}''). Raison : {1} TextResourceError = Echec de l''op\u00E9ration Include, r\u00E9tablissement de l''\u00E9l\u00E9ment fallback. Erreur de ressource lors de la lecture du fichier en tant que texte (href=''{0}''). Raison : {1} NO_XPointerSchema = Par d\u00E9faut, le sch\u00E9ma pour \"{0}\" n''est pas pris en charge. D\u00E9finissez votre propre sch\u00E9ma pour {0}. Reportez-vous \u00E0 l''adresse http://apache.org/xml/properties/xpointer-schema diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_it.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_it.properties index d0ca4e0414f..1cdc5442130 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_it.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_it.properties @@ -39,7 +39,7 @@ FallbackChild = Gli elementi dello spazio di nomi ''http://www.w3.org/2001/XIncl HrefMissing = Manca l'attributo 'href' di un elemento 'include'. RecursiveInclude = Inclusione ricorsiva rilevata. Il documento ''{0}'' \u00E8 gi\u00E0 stato elaborato. InvalidParseValue = Valore non valido per l''attributo ''parse'' nell''elemento ''include'': ''{0}''. -XMLParseError = Errore nel tentativo di analizzare il file XML (href=''{0}''). +XMLParseError = Errore nel tentativo di analizzare il file XML (href=''{0}''). Motivo: {1} XMLResourceError = Operazione di inclusione non riuscita. Verr\u00E0 ripristinato il fallback. Errore di risorsa durante la lettura del file come XML (href=''{0}''). Motivo: {1} TextResourceError = Operazione di inclusione non riuscita. Verr\u00E0 ripristinato il fallback. Errore di risorsa durante la lettura del file come testo (href=''{0}''). Motivo: {1} NO_XPointerSchema = Lo schema per \"{0}\" non \u00E8 supportato per impostazione predefinita. Definire il proprio schema per {0}. Vedere http://apache.org/xml/properties/xpointer-schema. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties index d17b8dbbefd..6b88fe82e05 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties @@ -39,7 +39,7 @@ FallbackChild = \u30CD\u30FC\u30E0\u30B9\u30DA\u30FC\u30B9''http://www.w3.org/20 HrefMissing = 'include'\u8981\u7D20\u306E'href'\u5C5E\u6027\u304C\u3042\u308A\u307E\u305B\u3093\u3002 RecursiveInclude = \u518D\u5E30\u7684\u306Ainclude\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F\u3002\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8''{0}''\u306F\u3059\u3067\u306B\u51E6\u7406\u3055\u308C\u3066\u3044\u307E\u3059\u3002 InvalidParseValue = ''include''\u8981\u7D20\u306E''parse''\u5C5E\u6027\u306E\u5024\u304C\u7121\u52B9\u3067\u3059: ''{0}''\u3002 -XMLParseError = XML\u30D5\u30A1\u30A4\u30EB\u306E\u89E3\u6790\u8A66\u884C\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F(href=''{0}'')\u3002 +XMLParseError = XML\u30D5\u30A1\u30A4\u30EB\u306E\u89E3\u6790\u8A66\u884C\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F(href=''{0}'')\u3002\u7406\u7531: {1} XMLResourceError = \u30A4\u30F3\u30AF\u30EB\u30FC\u30C9\u64CD\u4F5C\u304C\u5931\u6557\u3057\u3001\u30D5\u30A9\u30FC\u30EB\u30D0\u30C3\u30AF\u306B\u623B\u308A\u307E\u3059\u3002\u30D5\u30A1\u30A4\u30EB\u3092XML\u3068\u3057\u3066\u8AAD\u53D6\u308A\u4E2D\u306B\u30EA\u30BD\u30FC\u30B9\u30FB\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F(href=''{0}'')\u3002\u7406\u7531: {1} TextResourceError = \u30A4\u30F3\u30AF\u30EB\u30FC\u30C9\u64CD\u4F5C\u304C\u5931\u6557\u3057\u3001\u30D5\u30A9\u30FC\u30EB\u30D0\u30C3\u30AF\u306B\u623B\u308A\u307E\u3059\u3002\u30D5\u30A1\u30A4\u30EB\u3092\u30C6\u30AD\u30B9\u30C8\u3068\u3057\u3066\u8AAD\u53D6\u308A\u4E2D\u306B\u30EA\u30BD\u30FC\u30B9\u30FB\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F(href=''{0}'')\u3002\u7406\u7531: {1} NO_XPointerSchema = \u30C7\u30D5\u30A9\u30EB\u30C8\u3067\u306F\u3001\"{0}\"\u306E\u30B9\u30AD\u30FC\u30DE\u306F\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002{0}\u306B\u5BFE\u3057\u3066\u72EC\u81EA\u306E\u30B9\u30AD\u30FC\u30DE\u3092\u5B9A\u7FA9\u3057\u3066\u304F\u3060\u3055\u3044\u3002http://apache.org/xml/properties/xpointer-schema\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044 diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ko.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ko.properties index 430d6603d4a..570b7a7d583 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ko.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ko.properties @@ -39,7 +39,7 @@ FallbackChild = ''include'' \uC678\uC5D0 \uB2E4\uB978 ''http://www.w3.org/2001/X HrefMissing = 'include' \uC694\uC18C\uC758 'href' \uC18D\uC131\uC774 \uB204\uB77D\uB418\uC5C8\uC2B5\uB2C8\uB2E4. RecursiveInclude = \uC21C\uD658 include\uAC00 \uAC10\uC9C0\uB418\uC5C8\uC2B5\uB2C8\uB2E4. ''{0}'' \uBB38\uC11C\uAC00 \uC774\uBBF8 \uCC98\uB9AC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. InvalidParseValue = ''include'' \uC694\uC18C\uC5D0 ''parse'' \uC18D\uC131\uC5D0 \uB300\uD574 \uBD80\uC801\uD569\uD55C \uAC12\uC774 \uC788\uC74C: ''{0}''. -XMLParseError = XML \uD30C\uC77C(href=''{0}'')\uC758 \uAD6C\uBB38\uC744 \uBD84\uC11D\uD558\uB824\uACE0 \uC2DC\uB3C4\uD558\uB294 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. +XMLParseError = XML \uD30C\uC77C(href=''{0}'')\uC758 \uAD6C\uBB38\uC744 \uBD84\uC11D\uD558\uB824\uACE0 \uC2DC\uB3C4\uD558\uB294 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.\uC6D0\uC778: {1} XMLResourceError = Include \uC791\uC5C5\uC744 \uC2E4\uD328\uD558\uC5EC fallback\uC73C\uB85C \uBCF5\uC6D0\uD558\uB294 \uC911\uC785\uB2C8\uB2E4. \uD30C\uC77C\uC744 XML(href=''{0}'')\uB85C \uC77D\uB294 \uC911 \uB9AC\uC18C\uC2A4 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. \uC6D0\uC778: {1} TextResourceError = Include \uC791\uC5C5\uC744 \uC2E4\uD328\uD558\uC5EC fallback\uC73C\uB85C \uBCF5\uC6D0\uD558\uB294 \uC911\uC785\uB2C8\uB2E4. \uD30C\uC77C\uC744 \uD14D\uC2A4\uD2B8(href=''{0}'')\uB85C \uC77D\uB294 \uC911 \uB9AC\uC18C\uC2A4 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. \uC6D0\uC778: {1} NO_XPointerSchema = \uAE30\uBCF8\uC801\uC73C\uB85C \"{0}\"\uC5D0 \uB300\uD55C \uC2A4\uD0A4\uB9C8\uB294 \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. {0}\uC5D0 \uB300\uD574 \uACE0\uC720\uD55C \uC2A4\uD0A4\uB9C8\uB97C \uC815\uC758\uD558\uC2ED\uC2DC\uC624. http://apache.org/xml/properties/xpointer-schema\uB97C \uCC38\uC870\uD558\uC2ED\uC2DC\uC624. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_pt_BR.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_pt_BR.properties index 8d5b021af0b..5abd8266549 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_pt_BR.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_pt_BR.properties @@ -39,7 +39,7 @@ FallbackChild = Elementos do namespace ''http://www.w3.org/2001/XInclude'', dife HrefMissing = O atributo 'href' de um elemento 'include' n\u00E3o foi encontrado. RecursiveInclude = Inclus\u00E3o recursiva detectada. O documento ''{0}'' j\u00E1 foi processado. InvalidParseValue = Valor inv\u00E1lido para o atributo ''parse'' no elemento ''include'': ''{0}''. -XMLParseError = Erro ao tentar fazer parse do arquivo XML (href=''{0}''). +XMLParseError = Erro ao tentar fazer parse do arquivo XML (href=''{0}''). Motivo: {1} XMLResourceError = Falha na opera\u00E7\u00E3o de inclus\u00E3o; revertendo para fallback. Erro do recurso ao ler o arquivo como XML (href=''{0}''). Motivo: {1} TextResourceError = Falha na opera\u00E7\u00E3o de inclus\u00E3o; revertendo para fallback. Erro do recurso ao ler o arquivo como texto (href=''{0}''). Motivo: {1} NO_XPointerSchema = Por default, o esquema para \"{0}\" n\u00E3o \u00E9 suportado. Defina seu pr\u00F3prio esquema para {0}. Consulte http://apache.org/xml/properties/xpointer-schema diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_sv.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_sv.properties index 6f0d1f39054..426a5fa82bd 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_sv.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_sv.properties @@ -39,7 +39,7 @@ FallbackChild = Element fr\u00E5n namnrymd ''http://www.w3.org/2001/XInclude'', HrefMissing = Ett 'href'-attribut i ett 'include'-element saknas. RecursiveInclude = Rekursiv inkludering uppt\u00E4cktes. Dokumentet ''{0}'' har redan bearbetats. InvalidParseValue = Ogiltigt v\u00E4rde f\u00F6r ''parse''-attribut i ''include''-element: ''{0}''. -XMLParseError = Fel vid f\u00F6rs\u00F6k att tolka XML-fil (href=''{0}''). +XMLParseError = Fel vid f\u00F6rs\u00F6k att tolka XML-fil (href=''{0}''). Orsak: {1} XMLResourceError = Inkluderings\u00E5tg\u00E4rden utf\u00F6rdes inte, \u00E5terst\u00E4ller genom att \u00E5terskapa. Resursfel vid l\u00E4sning av fil som XML (href=''{0}''). Orsak: {1} TextResourceError = Inkluderings\u00E5tg\u00E4rden utf\u00F6rdes inte, \u00E5terst\u00E4ller genom att \u00E5terskapa. Resursfel vid l\u00E4sning av fil som text (href=''{0}''). Orsak: {1} NO_XPointerSchema = Schema f\u00F6r \"{0}\" st\u00F6ds inte som standard. Definiera ett eget schema f\u00F6r {0}.Se http://apache.org/xml/properties/xpointer-schema diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties index 3a36b4b243f..bcbb3aa3f70 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties @@ -39,7 +39,7 @@ FallbackChild = \u4E0D\u5141\u8BB8\u5C06\u540D\u79F0\u7A7A\u95F4 ''http://www.w3 HrefMissing = \u7F3A\u5C11 'include' \u5143\u7D20\u7684 'href' \u5C5E\u6027\u3002 RecursiveInclude = \u68C0\u6D4B\u5230\u9012\u5F52 include\u3002\u5DF2\u5904\u7406\u6587\u6863 ''{0}''\u3002 InvalidParseValue = ''include'' \u5143\u7D20\u7684 ''parse'' \u5C5E\u6027\u7684\u503C\u65E0\u6548: ''{0}''\u3002 -XMLParseError = \u5C1D\u8BD5\u5BF9 XML \u6587\u4EF6 (href=''{0}'') \u8FDB\u884C\u8BED\u6CD5\u5206\u6790\u65F6\u51FA\u9519\u3002 +XMLParseError = \u5C1D\u8BD5\u5BF9 XML \u6587\u4EF6 (href=''{0}'') \u8FDB\u884C\u8BED\u6CD5\u5206\u6790\u65F6\u51FA\u9519\u3002\u539F\u56E0: {1} XMLResourceError = Include \u64CD\u4F5C\u5931\u8D25, \u5E76\u8FD8\u539F\u4E3A fallback\u3002\u4EE5 XML (href=''{0}'') \u683C\u5F0F\u8BFB\u53D6\u6587\u4EF6\u65F6\u51FA\u73B0\u8D44\u6E90\u9519\u8BEF\u3002\u539F\u56E0: {1} TextResourceError = Include \u64CD\u4F5C\u5931\u8D25, \u5E76\u8FD8\u539F\u4E3A fallback\u3002\u4EE5\u6587\u672C (href=''{0}'') \u683C\u5F0F\u8BFB\u53D6\u6587\u4EF6\u65F6\u51FA\u73B0\u8D44\u6E90\u9519\u8BEF\u3002\u539F\u56E0: {1} NO_XPointerSchema = \u9ED8\u8BA4\u60C5\u51B5\u4E0B, \u4E0D\u652F\u6301 \"{0}\" \u7684\u65B9\u6848\u3002\u8BF7\u4E3A{0}\u5B9A\u4E49\u60A8\u81EA\u5DF1\u7684\u65B9\u6848\u3002\u8BF7\u8BBF\u95EE http://apache.org/xml/properties/xpointer-schema diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_TW.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_TW.properties index 33948e31c01..11cff31525e 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_TW.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_TW.properties @@ -39,7 +39,7 @@ FallbackChild = \u4F86\u81EA\u547D\u540D\u7A7A\u9593 ''http://www.w3.org/2001/XI HrefMissing = \u907A\u6F0F 'include' \u5143\u7D20\u7684 'href' \u5C6C\u6027\u3002 RecursiveInclude = \u5075\u6E2C\u5230\u905E\u8FF4\u5305\u542B\u3002\u5DF2\u7D93\u8655\u7406\u6587\u4EF6 ''{0}''\u3002 InvalidParseValue = ''include'' \u5143\u7D20\u4E0A ''parse'' \u5C6C\u6027\u7684\u7121\u6548\u503C: ''{0}''\u3002 -XMLParseError = \u5617\u8A66\u5256\u6790 XML \u6A94\u6848\u6642\u767C\u751F\u932F\u8AA4 (href=''{0}'')\u3002 +XMLParseError = \u5617\u8A66\u5256\u6790 XML \u6A94\u6848\u6642\u767C\u751F\u932F\u8AA4 (href=''{0}'')\u3002\u539F\u56E0: {1} XMLResourceError = \u5305\u542B\u4F5C\u696D\u5931\u6557\uFF0C\u56DE\u5FA9\u81F3\u5F8C\u63F4\u3002\u4EE5 XML (href=''{0}'') \u65B9\u5F0F\u8B80\u53D6\u6A94\u6848\u6642\u767C\u751F\u8CC7\u6E90\u932F\u8AA4\u3002\u539F\u56E0: {1} TextResourceError = \u5305\u542B\u4F5C\u696D\u5931\u6557\uFF0C\u56DE\u5FA9\u81F3\u5F8C\u63F4\u3002\u4EE5\u6587\u5B57 (href=''{0}'') \u65B9\u5F0F\u8B80\u53D6\u6A94\u6848\u6642\u767C\u751F\u8CC7\u6E90\u932F\u8AA4\u3002\u539F\u56E0: {1} NO_XPointerSchema = \u9810\u8A2D\u4E0D\u652F\u63F4 \"{0}\" \u7684\u7DB1\u8981\u3002\u8ACB\u70BA {0} \u5B9A\u7FA9\u60A8\u81EA\u5DF1\u7684\u7DB1\u8981\u3002\u8ACB\u53C3\u95B1 http://apache.org/xml/properties/xpointer-schema diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties index 133f4282020..3bf9ebdc987 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties @@ -261,6 +261,9 @@ # Entity related messages # 3.1 Start-Tags, End-Tags, and Empty-Element Tags ReferenceToExternalEntity = The external entity reference \"&{0};\" is not permitted in an attribute value. + AccessExternalDTD = External DTD: Failed to read external DTD ''{0}'', because ''{1}'' access is not allowed. + AccessExternalEntity = External Entity: Failed to read external document ''{0}'', because ''{1}'' access is not allowed. + # 4.1 Character and Entity References EntityNotDeclared = The entity \"{0}\" was referenced, but not declared. ReferenceToUnparsedEntity = The unparsed entity reference \"&{0};\" is not permitted. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties index 29bbccfb142..3cf21e56482 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties @@ -289,6 +289,9 @@ # Entity related messages # 3.1 Start-Tags, End-Tags, and Empty-Element Tags ReferenceToExternalEntity = Externe Entit\u00E4tsreferenz \"&{0};\" ist in einem Attributwert nicht zul\u00E4ssig. + AccessExternalDTD = External DTD: Failed to read external DTD ''{0}'', because ''{1}'' access is not allowed. + AccessExternalEntity = External Entity: Failed to read external document ''{0}'', because ''{1}'' access is not allowed. + # 4.1 Character and Entity References EntityNotDeclared = Entit\u00E4t \"{0}\" wurde referenziert aber nicht deklariert. ReferenceToUnparsedEntity = Nicht geparste Entit\u00E4tsreferenz \"&{0};\" ist nicht zul\u00E4ssig. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties index f8227e2ce47..5ebfaf0eb2a 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties @@ -289,6 +289,9 @@ # Entity related messages # 3.1 Start-Tags, End-Tags, and Empty-Element Tags ReferenceToExternalEntity = La referencia de entidad externa \"&{0};\" no est\u00E1 permitida en un valor de atributo. + AccessExternalDTD = External DTD: Failed to read external DTD ''{0}'', because ''{1}'' access is not allowed. + AccessExternalEntity = External Entity: Failed to read external document ''{0}'', because ''{1}'' access is not allowed. + # 4.1 Character and Entity References EntityNotDeclared = Se hizo referencia a la entidad \"{0}\", pero no se declar\u00F3. ReferenceToUnparsedEntity = La referencia de entidad no analizada \"&{0};\" no est\u00E1 permitida. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties index cc0c6bfff75..f60b07301ee 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties @@ -289,6 +289,9 @@ # Entity related messages # 3.1 Start-Tags, End-Tags, and Empty-Element Tags ReferenceToExternalEntity = La r\u00E9f\u00E9rence d''entit\u00E9 externe \"&{0};\" n''est pas autoris\u00E9e dans une valeur d''attribut. + AccessExternalDTD = External DTD: Failed to read external DTD ''{0}'', because ''{1}'' access is not allowed. + AccessExternalEntity = External Entity: Failed to read external document ''{0}'', because ''{1}'' access is not allowed. + # 4.1 Character and Entity References EntityNotDeclared = L''entit\u00E9 \"{0}\" \u00E9tait r\u00E9f\u00E9renc\u00E9e, mais pas d\u00E9clar\u00E9e. ReferenceToUnparsedEntity = La r\u00E9f\u00E9rence d''entit\u00E9 non analys\u00E9e \"&{0};\" n''est pas autoris\u00E9e. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties index 03f8ce2fa42..e525777850b 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties @@ -289,6 +289,9 @@ # Entity related messages # 3.1 Start-Tags, End-Tags, and Empty-Element Tags ReferenceToExternalEntity = Il riferimento di entit\u00E0 esterna \"&{0};\" non \u00E8 consentito in un valore di attributo. + AccessExternalDTD = External DTD: Failed to read external DTD ''{0}'', because ''{1}'' access is not allowed. + AccessExternalEntity = External Entity: Failed to read external document ''{0}'', because ''{1}'' access is not allowed. + # 4.1 Character and Entity References EntityNotDeclared = L''entit\u00E0 \"{0}\" \u00E8 indicata da un riferimento, ma non \u00E8 dichiarata. ReferenceToUnparsedEntity = Il riferimento di entit\u00E0 non analizzata \"&{0};\" non \u00E8 consentito. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties index e837075d8a1..ed548694ec4 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties @@ -289,6 +289,9 @@ # Entity related messages # 3.1 Start-Tags, End-Tags, and Empty-Element Tags ReferenceToExternalEntity = \u5916\u90E8\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3\u53C2\u7167\"&{0};\"\u306F\u3001\u5C5E\u6027\u5024\u3067\u306F\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002 + AccessExternalDTD = External DTD: Failed to read external DTD ''{0}'', because ''{1}'' access is not allowed. + AccessExternalEntity = External Entity: Failed to read external document ''{0}'', because ''{1}'' access is not allowed. + # 4.1 Character and Entity References EntityNotDeclared = \u30A8\u30F3\u30C6\u30A3\u30C6\u30A3\"{0}\"\u304C\u53C2\u7167\u3055\u308C\u3066\u3044\u307E\u3059\u304C\u3001\u5BA3\u8A00\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002 ReferenceToUnparsedEntity = \u672A\u89E3\u6790\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3\u53C2\u7167\"&{0};\"\u306F\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002 diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ko.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ko.properties index 8262f88a9e4..882f8085758 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ko.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ko.properties @@ -289,6 +289,9 @@ # Entity related messages # 3.1 Start-Tags, End-Tags, and Empty-Element Tags ReferenceToExternalEntity = \uC18D\uC131\uAC12\uC5D0\uC11C\uB294 \uC678\uBD80 \uC5D4\uD2F0\uD2F0 \uCC38\uC870 \"&{0};\"\uC774 \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. + AccessExternalDTD = External DTD: Failed to read external DTD ''{0}'', because ''{1}'' access is not allowed. + AccessExternalEntity = External Entity: Failed to read external document ''{0}'', because ''{1}'' access is not allowed. + # 4.1 Character and Entity References EntityNotDeclared = \"{0}\" \uC5D4\uD2F0\uD2F0\uAC00 \uCC38\uC870\uB418\uC5C8\uC9C0\uB9CC \uC120\uC5B8\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. ReferenceToUnparsedEntity = \uAD6C\uBB38\uC774 \uBD84\uC11D\uB418\uC9C0 \uC54A\uC740 \uC5D4\uD2F0\uD2F0 \uCC38\uC870 \"&{0};\"\uC740(\uB294) \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_pt_BR.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_pt_BR.properties index 94eebc6d80a..57770dcde09 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_pt_BR.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_pt_BR.properties @@ -289,6 +289,9 @@ # Entity related messages # 3.1 Start-Tags, End-Tags, and Empty-Element Tags ReferenceToExternalEntity = A refer\u00EAncia da entidade externa \"&{0};\" n\u00E3o \u00E9 permitida em um valor do atributo. + AccessExternalDTD = External DTD: Failed to read external DTD ''{0}'', because ''{1}'' access is not allowed. + AccessExternalEntity = External Entity: Failed to read external document ''{0}'', because ''{1}'' access is not allowed. + # 4.1 Character and Entity References EntityNotDeclared = A entidade \"{0}\" foi referenciada, mas n\u00E3o declarada. ReferenceToUnparsedEntity = A refer\u00EAncia da entidade n\u00E3o submetida a parse \"&{0};\" n\u00E3o \u00E9 permitida. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_sv.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_sv.properties index 6777adb5ed6..8c0bb0f0f8d 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_sv.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_sv.properties @@ -289,6 +289,9 @@ # Entity related messages # 3.1 Start-Tags, End-Tags, and Empty-Element Tags ReferenceToExternalEntity = Den externa enhetsreferensen \"&{0};\" till\u00E5ts inte i ett attributv\u00E4rde. + AccessExternalDTD = External DTD: Failed to read external DTD ''{0}'', because ''{1}'' access is not allowed. + AccessExternalEntity = External Entity: Failed to read external document ''{0}'', because ''{1}'' access is not allowed. + # 4.1 Character and Entity References EntityNotDeclared = Enheten \"{0}\" har refererats, men \u00E4r inte deklarerad. ReferenceToUnparsedEntity = Den otolkade enhetsreferensen \"&{0};\" \u00E4r inte till\u00E5ten. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties index 959f147b130..74a7a061c2b 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties @@ -289,6 +289,9 @@ # Entity related messages # 3.1 Start-Tags, End-Tags, and Empty-Element Tags ReferenceToExternalEntity = \u5C5E\u6027\u503C\u4E2D\u4E0D\u5141\u8BB8\u91C7\u7528\u5916\u90E8\u5B9E\u4F53\u5F15\u7528 \"&{0};\"\u3002 + AccessExternalDTD = External DTD: Failed to read external DTD ''{0}'', because ''{1}'' access is not allowed. + AccessExternalEntity = External Entity: Failed to read external document ''{0}'', because ''{1}'' access is not allowed. + # 4.1 Character and Entity References EntityNotDeclared = \u5F15\u7528\u4E86\u5B9E\u4F53 \"{0}\", \u4F46\u672A\u58F0\u660E\u5B83\u3002 ReferenceToUnparsedEntity = \u4E0D\u5141\u8BB8\u4F7F\u7528\u672A\u8FDB\u884C\u8BED\u6CD5\u5206\u6790\u7684\u5B9E\u4F53\u5F15\u7528 \"&{0};\"\u3002 diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_TW.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_TW.properties index 7495d31bfb4..1a953819503 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_TW.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_TW.properties @@ -289,6 +289,9 @@ # Entity related messages # 3.1 Start-Tags, End-Tags, and Empty-Element Tags ReferenceToExternalEntity = \u5C6C\u6027\u503C\u4E0D\u5141\u8A31\u53C3\u7167\u5916\u90E8\u500B\u9AD4 \"&{0};\"\u3002 + AccessExternalDTD = External DTD: Failed to read external DTD ''{0}'', because ''{1}'' access is not allowed. + AccessExternalEntity = External Entity: Failed to read external document ''{0}'', because ''{1}'' access is not allowed. + # 4.1 Character and Entity References EntityNotDeclared = \u53C3\u7167\u4E86\u500B\u9AD4 \"{0}\"\uFF0C\u4F46\u662F\u672A\u5BA3\u544A\u3002 ReferenceToUnparsedEntity = \u4E0D\u5141\u8A31\u672A\u5256\u6790\u7684\u500B\u9AD4\u53C3\u7167 \"&{0};\"\u3002 diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties index d2e847199ec..23234a4bf61 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties @@ -86,6 +86,7 @@ #schema valid (3.X.3) + schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed. schema_reference.4 = schema_reference.4: Failed to read schema document ''{0}'', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not . src-annotation = src-annotation: elements can only contain and elements, but ''{0}'' was found. src-attribute.1 = src-attribute.1: The properties ''default'' and ''fixed'' cannot both be present in attribute declaration ''{0}''. Use only one of them. @@ -289,6 +290,3 @@ TargetNamespace.2 = TargetNamespace.2: Expecting no namespace, but the schema document has a target namespace of ''{1}''. UndeclaredEntity = UndeclaredEntity: Entity ''{0}'' is not declared. UndeclaredPrefix = UndeclaredPrefix: Cannot resolve ''{0}'' as a QName: the prefix ''{1}'' is not declared. -null -null -null diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties index 755985e04c0..eed78fb7577 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties @@ -114,6 +114,7 @@ #schema valid (3.X.3) + schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed. schema_reference.4 = schema_reference.4: Schemadokument "{0}" konnte nicht gelesen werden, da 1) das Dokument nicht gefunden werden konnte; 2) das Dokument nicht gelesen werden konnte; 3) das Root-Element des Dokuments nicht ist. src-annotation = src-annotation: -Elemente k\u00F6nnen nur - und -Elemente enthalten, aber es wurde "{0}" gefunden. src-attribute.1 = src-attribute.1: Die Eigenschaften "default" und "fixed" k\u00F6nnen nicht beide in der Attributdeklaration "{0}" vorhanden sein. Verwenden Sie nur eine dieser Eigenschaften. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_es.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_es.properties index 3a4e15cfd97..b5e6560e957 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_es.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_es.properties @@ -114,6 +114,7 @@ #schema valid (3.X.3) + schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed. schema_reference.4 = schema_reference.4: Fallo al leer el documento de esquema ''{0}'', porque 1) no se ha encontrado el documento; 2) no se ha podido leer el documento; 3) el elemento ra\u00EDz del documento no es . src-annotation = src-annotation: Los elementos de s\u00F3lo pueden contener elementos de y , pero se ha encontrado ''{0}''. src-attribute.1 = src-attribute.1: Las propiedades ''default'' y ''fixed'' no pueden estar presentes de forma simult\u00E1nea en la declaraci\u00F3n de atributo ''{0}''. Utilice s\u00F3lo una de ellas. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_fr.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_fr.properties index 24e910cbe83..f3c3156d7c3 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_fr.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_fr.properties @@ -114,6 +114,7 @@ #schema valid (3.X.3) + schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed. schema_reference.4 = schema_reference.4 : Echec de la lecture du document de sch\u00E9ma ''{0}'' pour les raisons suivantes : 1) Le document est introuvable ; 2) Le document n''a pas pu \u00EAtre lu ; 3) L''\u00E9l\u00E9ment racine du document n''est pas . src-annotation = src-annotation : Les \u00E9l\u00E9ments ne peuvent contenir que des \u00E9l\u00E9ments et , mais ''{0}'' a \u00E9t\u00E9 trouv\u00E9. src-attribute.1 = src-attribute.1 : Les propri\u00E9t\u00E9s ''default'' et ''fixed'' ne peuvent pas figurer simultan\u00E9ment dans la d\u00E9claration d''attribut ''{0}''. Utilisez uniquement l''une d''entre elles. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_it.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_it.properties index 638d40001e2..4153c6d2219 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_it.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_it.properties @@ -114,6 +114,7 @@ #schema valid (3.X.3) + schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed. schema_reference.4 = schema_reference.4: lettura del documento di schema "{0}" non riuscita perch\u00E9 1) non \u00E8 stato possibile trovare il documento; 2) non \u00E8 stato possibile leggere il documento; 3) l''elemento radice del documento non \u00E8 . src-annotation = src-annotation: possono essere contenuti soltanto elementi e , ma \u00E8 stato trovato ''{0}''. src-attribute.1 = src-attribute.1: le propriet\u00E0 ''default'' e ''fixed'' non possono essere entrambi presenti nella dichiarazione di attributo ''{0}''. Utilizzarne solo una. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties index 536f78c9693..9fe30e2e67d 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties @@ -114,6 +114,7 @@ #schema valid (3.X.3) + schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed. schema_reference.4 = schema_reference.4: 1)\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u304C\u898B\u3064\u304B\u3089\u306A\u304B\u3063\u305F\u30012)\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u3092\u8AAD\u307F\u53D6\u308C\u306A\u304B\u3063\u305F\u30013)\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u30EB\u30FC\u30C8\u8981\u7D20\u304C\u3067\u306F\u306A\u304B\u3063\u305F\u305F\u3081\u3001\u30B9\u30AD\u30FC\u30DE\u30FB\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8''{0}''\u306E\u8AAD\u53D6\u308A\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 src-annotation = src-annotation: \u8981\u7D20\u306B\u542B\u3081\u308B\u3053\u3068\u304C\u3067\u304D\u308B\u306E\u306F\u8981\u7D20\u304A\u3088\u3073\u8981\u7D20\u306E\u307F\u3067\u3059\u304C\u3001''{0}''\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\u3002 src-attribute.1 = src-attribute.1: ''default''\u3068''fixed''\u306E\u4E21\u65B9\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u3092\u5C5E\u6027\u5BA3\u8A00''{0}''\u306B\u542B\u3081\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002\u3044\u305A\u308C\u304B\u4E00\u65B9\u306E\u307F\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002 diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ko.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ko.properties index 102466bd5af..a6a77f32186 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ko.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ko.properties @@ -114,6 +114,7 @@ #schema valid (3.X.3) + schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed. schema_reference.4 = schema_reference.4: \uC2A4\uD0A4\uB9C8 \uBB38\uC11C ''{0}'' \uC77D\uAE30\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uC6D0\uC778: 1) \uBB38\uC11C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. 2) \uBB38\uC11C\uB97C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. 3) \uBB38\uC11C\uC758 \uB8E8\uD2B8 \uC694\uC18C\uAC00 \uAC00 \uC544\uB2D9\uB2C8\uB2E4. src-annotation = src-annotation: \uC694\uC18C\uC5D0\uB294 \uBC0F \uC694\uC18C\uB9CC \uD3EC\uD568\uB420 \uC218 \uC788\uC9C0\uB9CC ''{0}''\uC774(\uAC00) \uBC1C\uACAC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. src-attribute.1 = src-attribute.1: ''default'' \uBC0F ''fixed'' \uC18D\uC131\uC740 \uC18D\uC131 \uC120\uC5B8 ''{0}''\uC5D0 \uD568\uAED8 \uC874\uC7AC\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uD558\uB098\uB9CC \uC0AC\uC6A9\uD558\uC2ED\uC2DC\uC624. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_pt_BR.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_pt_BR.properties index e3bee291978..163fc6d2b4a 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_pt_BR.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_pt_BR.properties @@ -114,6 +114,7 @@ #schema valid (3.X.3) + schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed. schema_reference.4 = schema_reference.4: Falha ao ler o documento do esquema ''{0}'' porque 1) n\u00E3o foi poss\u00EDvel encontrar o documento; 2) n\u00E3o foi poss\u00EDvel ler o documento; 3) o elemento-raiz do documento n\u00E3o \u00E9 . src-annotation = src-annotation: os elementos de podem conter somente os elementos e , mas foi encontrado ''{0}''. src-attribute.1 = src-attribute.1: As propriedades ''default'' e ''fixed'' n\u00E3o podem estar presentes na declara\u00E7\u00E3o do atributo ''{0}''. Use somente uma delas. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_sv.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_sv.properties index 0332f512fee..4cc42ca5eb5 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_sv.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_sv.properties @@ -114,6 +114,7 @@ #schema valid (3.X.3) + schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed. schema_reference.4 = schema_reference.4: L\u00E4sning av schemadokument ''{0}'' utf\u00F6rdes inte p\u00E5 grund av 1) det g\u00E5r inte att hitta dokumentet; 2) det g\u00E5r inte att l\u00E4sa dokumentet; 3) dokumentets rotelement \u00E4r inte . src-annotation = src-annotation: element f\u00F6r f\u00E5r endast inneh\u00E5lla element f\u00F6r och , men ''{0}'' hittades. src-attribute.1 = src-attribute.1: B\u00E5da egenskaperna ''default'' och ''fixed'' kan inte samtidigt ing\u00E5 i attributdeklarationen ''{0}''. Anv\u00E4nd en av dem. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties index ef0338ab8e7..f517a72a2cd 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties @@ -114,6 +114,7 @@ #schema valid (3.X.3) + schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed. schema_reference.4 = schema_reference.4: \u65E0\u6CD5\u8BFB\u53D6\u65B9\u6848\u6587\u6863 ''{0}'', \u539F\u56E0\u4E3A 1) \u65E0\u6CD5\u627E\u5230\u6587\u6863; 2) \u65E0\u6CD5\u8BFB\u53D6\u6587\u6863; 3) \u6587\u6863\u7684\u6839\u5143\u7D20\u4E0D\u662F \u3002 src-annotation = src-annotation: \u5143\u7D20\u53EA\u80FD\u5305\u542B \u548C \u5143\u7D20, \u4F46\u53D1\u73B0\u4E86 ''{0}''\u3002 src-attribute.1 = src-attribute.1: \u5C5E\u6027\u58F0\u660E ''{0}'' \u4E2D\u4E0D\u80FD\u540C\u65F6\u5B58\u5728\u7279\u6027 ''default'' \u548C ''fixed''\u3002\u5E94\u53EA\u4F7F\u7528\u5176\u4E2D\u4E00\u4E2A\u3002 diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_TW.properties b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_TW.properties index a61dc7cecb1..8661de47c74 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_TW.properties +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_TW.properties @@ -114,6 +114,7 @@ #schema valid (3.X.3) + schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed. schema_reference.4 = schema_reference.4: \u7121\u6CD5\u8B80\u53D6\u7DB1\u8981\u6587\u4EF6 ''{0}''\uFF0C\u56E0\u70BA 1) \u627E\u4E0D\u5230\u6587\u4EF6; 2) \u7121\u6CD5\u8B80\u53D6\u6587\u4EF6; 3) \u6587\u4EF6\u7684\u6839\u5143\u7D20\u4E0D\u662F \u3002 src-annotation = src-annotation: \u5143\u7D20\u50C5\u80FD\u5305\u542B \u8207 \u5143\u7D20\uFF0C\u4F46\u627E\u5230 ''{0}''\u3002 src-attribute.1 = src-attribute.1: \u5C6C\u6027 ''default'' \u8207 ''fixed'' \u4E0D\u53EF\u540C\u6642\u51FA\u73FE\u5728\u5C6C\u6027\u5BA3\u544A ''{0}'' \u4E2D\u3002\u8ACB\u53EA\u4F7F\u7528\u5176\u4E2D\u4E00\u500B\u3002 diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaLoader.java b/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaLoader.java index 4b7ba136685..3fbe23475d7 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaLoader.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaLoader.java @@ -53,6 +53,7 @@ import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings; import com.sun.org.apache.xerces.internal.util.Status; import com.sun.org.apache.xerces.internal.util.SymbolTable; import com.sun.org.apache.xerces.internal.util.XMLSymbols; +import com.sun.org.apache.xerces.internal.utils.SecuritySupport; import com.sun.org.apache.xerces.internal.xni.XNIException; import com.sun.org.apache.xerces.internal.xni.grammars.Grammar; import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; @@ -71,6 +72,7 @@ import com.sun.org.apache.xerces.internal.xs.XSLoader; import com.sun.org.apache.xerces.internal.xs.XSModel; import java.util.HashMap; import java.util.Map; +import javax.xml.XMLConstants; import org.w3c.dom.DOMConfiguration; import org.w3c.dom.DOMError; import org.w3c.dom.DOMErrorHandler; @@ -216,6 +218,12 @@ XSLoader, DOMConfiguration { protected static final String ENTITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY; + /** Property identifier: access to external dtd */ + public static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD; + + /** Property identifier: access to external schema */ + public static final String ACCESS_EXTERNAL_SCHEMA = XMLConstants.ACCESS_EXTERNAL_SCHEMA; + // recognized properties private static final String [] RECOGNIZED_PROPERTIES = { ENTITY_MANAGER, @@ -229,7 +237,9 @@ XSLoader, DOMConfiguration { JAXP_SCHEMA_SOURCE, SECURITY_MANAGER, LOCALE, - SCHEMA_DV_FACTORY + SCHEMA_DV_FACTORY, + ACCESS_EXTERNAL_DTD, + ACCESS_EXTERNAL_SCHEMA }; // Data @@ -260,6 +270,8 @@ XSLoader, DOMConfiguration { private final CMNodeFactory fNodeFactory = new CMNodeFactory(); //component mgr will be set later private CMBuilder fCMBuilder; private XSDDescription fXSDDescription = new XSDDescription(); + private String faccessExternalDTD = Constants.EXTERNAL_ACCESS_DEFAULT; + private String faccessExternalSchema = Constants.EXTERNAL_ACCESS_DEFAULT; private Map fJAXPCache; private Locale fLocale = Locale.getDefault(); @@ -454,6 +466,12 @@ XSLoader, DOMConfiguration { fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, new XSMessageFormatter()); } } + else if (propertyId.equals(ACCESS_EXTERNAL_DTD)) { + faccessExternalDTD = (String) state; + } + else if (propertyId.equals(ACCESS_EXTERNAL_SCHEMA)) { + faccessExternalSchema = (String) state; + } } // setProperty(String, Object) /** @@ -585,6 +603,15 @@ XSLoader, DOMConfiguration { if(!fJAXPProcessed) { processJAXPSchemaSource(locationPairs); } + + if (desc.isExternal()) { + String accessError = SecuritySupport.checkAccess(desc.getExpandedSystemId(), faccessExternalSchema, Constants.ACCESS_EXTERNAL_ALL); + if (accessError != null) { + throw new XNIException(fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN, + "schema_reference.access", + new Object[] { SecuritySupport.sanitizePath(desc.getExpandedSystemId()), accessError }, XMLErrorReporter.SEVERITY_ERROR)); + } + } SchemaGrammar grammar = fSchemaHandler.parseSchema(source, desc, locationPairs); return grammar; @@ -1038,6 +1065,9 @@ XSLoader, DOMConfiguration { // get generate-synthetic-annotations feature fSchemaHandler.setGenerateSyntheticAnnotations(componentManager.getFeature(GENERATE_SYNTHETIC_ANNOTATIONS, false)); fSchemaHandler.reset(componentManager); + + faccessExternalDTD = (String) componentManager.getProperty(ACCESS_EXTERNAL_DTD); + faccessExternalSchema = (String) componentManager.getProperty(ACCESS_EXTERNAL_SCHEMA); } private void initGrammarBucket(){ diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java b/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java index c14673ec26a..170601cb46a 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java @@ -29,7 +29,7 @@ import java.util.Map; import java.util.Stack; import java.util.Vector; import java.util.ArrayList; - +import javax.xml.XMLConstants; import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.RevalidationHandler; import com.sun.org.apache.xerces.internal.impl.XMLEntityManager; @@ -233,6 +233,12 @@ public class XMLSchemaValidator protected static final String SCHEMA_DV_FACTORY = Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY; + /** property identifier: access external dtd. */ + private static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD; + + /** Property identifier: access to external schema */ + private static final String ACCESS_EXTERNAL_SCHEMA = XMLConstants.ACCESS_EXTERNAL_SCHEMA; + protected static final String USE_SERVICE_MECHANISM = Constants.ORACLE_FEATURE_SERVICE_MECHANISM; // recognized features and properties @@ -291,11 +297,13 @@ public class XMLSchemaValidator JAXP_SCHEMA_SOURCE, JAXP_SCHEMA_LANGUAGE, SCHEMA_DV_FACTORY, + ACCESS_EXTERNAL_DTD, + ACCESS_EXTERNAL_SCHEMA }; /** Property defaults. */ private static final Object[] PROPERTY_DEFAULTS = - { null, null, null, null, null, null, null, null, null, null, null}; + { null, null, null, null, null, null, null, null, null, null, null, null, null}; // this is the number of valuestores of each kind // we expect an element to have. It's almost diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSDDescription.java b/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSDDescription.java index 8e09b9f80d8..c35baa8667a 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSDDescription.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XSDDescription.java @@ -34,6 +34,7 @@ import com.sun.org.apache.xerces.internal.xni.grammars.XMLSchemaDescription; * @author Neil Graham, IBM * @author Neeraj Bajaj, SUN Microsystems. * + * @version $Id: XSDDescription.java,v 1.6 2010-11-01 04:39:55 joehw Exp $ */ public class XSDDescription extends XMLResourceIdentifierImpl implements XMLSchemaDescription { @@ -180,6 +181,17 @@ public class XSDDescription extends XMLResourceIdentifierImpl fContextType == CONTEXT_XSITYPE; } + /** + * @return true is the schema is external + */ + public boolean isExternal() { + return fContextType == CONTEXT_INCLUDE || + fContextType == CONTEXT_REDEFINE || + fContextType == CONTEXT_IMPORT || + fContextType == CONTEXT_ELEMENT || + fContextType == CONTEXT_ATTRIBUTE || + fContextType == CONTEXT_XSITYPE; + } /** * Compares this grammar with the given grammar. Currently, we compare * the target namespaces. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java b/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java index 7c9974e4a17..eba1ac0de20 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java @@ -77,6 +77,7 @@ import com.sun.org.apache.xerces.internal.util.SymbolHash; import com.sun.org.apache.xerces.internal.util.SymbolTable; import com.sun.org.apache.xerces.internal.util.XMLSymbols; import com.sun.org.apache.xerces.internal.util.URI.MalformedURIException; +import com.sun.org.apache.xerces.internal.utils.SecuritySupport; import com.sun.org.apache.xerces.internal.xni.QName; import com.sun.org.apache.xerces.internal.xni.XNIException; import com.sun.org.apache.xerces.internal.xni.grammars.Grammar; @@ -105,6 +106,7 @@ import com.sun.org.apache.xerces.internal.xs.XSSimpleTypeDefinition; import com.sun.org.apache.xerces.internal.xs.XSTerm; import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; import com.sun.org.apache.xerces.internal.xs.datatypes.ObjectList; +import javax.xml.XMLConstants; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -221,6 +223,12 @@ public class XSDHandler { protected static final String LOCALE = Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY; + /** property identifier: access external dtd. */ + public static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD; + + /** Property identifier: access to external schema */ + public static final String ACCESS_EXTERNAL_SCHEMA = XMLConstants.ACCESS_EXTERNAL_SCHEMA; + protected static final boolean DEBUG_NODE_POOL = false; // Data @@ -251,6 +259,8 @@ public class XSDHandler { */ protected SecurityManager fSecureProcessing = null; + private String fAccessExternalSchema; + // These tables correspond to the symbol spaces defined in the // spec. // They are keyed with a QName (that is, String("URI,localpart) and @@ -2150,6 +2160,15 @@ public class XSDHandler { fLastSchemaWasDuplicate = true; return schemaElement; } + if (referType == XSDDescription.CONTEXT_IMPORT || referType == XSDDescription.CONTEXT_INCLUDE + || referType == XSDDescription.CONTEXT_REDEFINE) { + String accessError = SecuritySupport.checkAccess(schemaId, fAccessExternalSchema, Constants.ACCESS_EXTERNAL_ALL); + if (accessError != null) { + reportSchemaFatalError("schema_reference.access", + new Object[] { SecuritySupport.sanitizePath(schemaId), accessError }, + referElement); + } + } } fSchemaParser.parse(schemaSource); @@ -3561,6 +3580,11 @@ public class XSDHandler { } catch (XMLConfigurationException e) { } + //For Schema validation, the secure feature is set to true by default + fSchemaParser.setProperty(ACCESS_EXTERNAL_DTD, + componentManager.getProperty(ACCESS_EXTERNAL_DTD, Constants.EXTERNAL_ACCESS_DEFAULT)); + fAccessExternalSchema = (String) componentManager.getProperty( + ACCESS_EXTERNAL_SCHEMA, Constants.EXTERNAL_ACCESS_DEFAULT); } // reset(XMLComponentManager) diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java index af14049cf50..aea63c2eb16 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java @@ -37,7 +37,7 @@ import org.xml.sax.SAXNotSupportedException; /** * @author Rajiv Mordani * @author Edwin Goei - * @version $Id: DocumentBuilderFactoryImpl.java,v 1.6 2009/07/28 23:48:32 joehw Exp $ + * @version $Id: DocumentBuilderFactoryImpl.java,v 1.8 2010-11-01 04:40:06 joehw Exp $ */ public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory { /** These are DocumentBuilderFactory attributes not DOM attributes */ @@ -191,6 +191,9 @@ public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory { public void setFeature(String name, boolean value) throws ParserConfigurationException { + if (features == null) { + features = new Hashtable(); + } // If this is the secure processing feature, save it then return. if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { if (System.getSecurityManager() != null && (!value)) { @@ -199,11 +202,10 @@ public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory { "jaxp-secureprocessing-feature", null)); } fSecureProcess = value; + features.put(name, value ? Boolean.TRUE : Boolean.FALSE); return; } - if (features == null) { - features = new Hashtable(); - } + features.put(name, value ? Boolean.TRUE : Boolean.FALSE); // Test the feature by possibly throwing SAX exceptions try { diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java index 84bab42cbc5..39112a61f64 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java @@ -27,6 +27,7 @@ import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.validation.Schema; +import javax.xml.XMLConstants; import com.sun.org.apache.xerces.internal.dom.DOMImplementationImpl; import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter; @@ -42,6 +43,7 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource; import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration; +import javax.xml.XMLConstants; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.xml.sax.EntityResolver; @@ -95,6 +97,12 @@ public class DocumentBuilderImpl extends DocumentBuilder private static final String SECURITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; + /** property identifier: access external dtd. */ + public static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD; + + /** Property identifier: access to external schema */ + public static final String ACCESS_EXTERNAL_SCHEMA = XMLConstants.ACCESS_EXTERNAL_SCHEMA; + private final DOMParser domParser; private final Schema grammar; @@ -155,6 +163,23 @@ public class DocumentBuilderImpl extends DocumentBuilder // If the secure processing feature is on set a security manager. if (secureProcessing) { domParser.setProperty(SECURITY_MANAGER, new SecurityManager()); + + /** + * By default, secure processing is set, no external access is allowed. + * However, we need to check if it is actively set on the factory since we + * allow the use of the System Property or jaxp.properties to override + * the default value + */ + if (features != null) { + Object temp = features.get(XMLConstants.FEATURE_SECURE_PROCESSING); + if (temp != null) { + boolean value = ((Boolean) temp).booleanValue(); + if (value) { + domParser.setProperty(ACCESS_EXTERNAL_DTD, Constants.EXTERNAL_ACCESS_DEFAULT_FSP); + domParser.setProperty(ACCESS_EXTERNAL_SCHEMA, Constants.EXTERNAL_ACCESS_DEFAULT_FSP); + } + } + } } this.grammar = dbf.getSchema(); @@ -211,6 +236,10 @@ public class DocumentBuilderImpl extends DocumentBuilder String feature = (String) entry.getKey(); boolean value = ((Boolean) entry.getValue()).booleanValue(); domParser.setFeature(feature, value); + if (feature.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { + domParser.setProperty(ACCESS_EXTERNAL_DTD, ""); + domParser.setProperty(ACCESS_EXTERNAL_SCHEMA, ""); + } } } } diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserFactoryImpl.java b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserFactoryImpl.java index eecdc100344..ae9d99509d9 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserFactoryImpl.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserFactoryImpl.java @@ -43,7 +43,7 @@ import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter; * @author Rajiv Mordani * @author Edwin Goei * - * @version $Id: SAXParserFactoryImpl.java,v 1.7 2009/07/28 23:48:32 joehw Exp $ + * @version $Id: SAXParserFactoryImpl.java,v 1.9 2010-11-01 04:40:06 joehw Exp $ */ public class SAXParserFactoryImpl extends SAXParserFactory { @@ -124,6 +124,7 @@ public class SAXParserFactoryImpl extends SAXParserFactory { "jaxp-secureprocessing-feature", null)); } fSecureProcess = value; + putInFeatures(name, value); return; } diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java index 58d7d165d88..bbb609e9e28 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java @@ -92,6 +92,12 @@ public class SAXParserImpl extends javax.xml.parsers.SAXParser private static final String SECURITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; + /** property identifier: access external dtd. */ + public static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD; + + /** Property identifier: access to external schema */ + public static final String ACCESS_EXTERNAL_SCHEMA = XMLConstants.ACCESS_EXTERNAL_SCHEMA; + private final JAXPSAXParser xmlReader; private String schemaLanguage = null; // null means DTD private final Schema grammar; @@ -146,6 +152,22 @@ public class SAXParserImpl extends javax.xml.parsers.SAXParser // If the secure processing feature is on set a security manager. if (secureProcessing) { xmlReader.setProperty0(SECURITY_MANAGER, new SecurityManager()); + /** + * By default, secure processing is set, no external access is allowed. + * However, we need to check if it is actively set on the factory since we + * allow the use of the System Property or jaxp.properties to override + * the default value + */ + if (features != null) { + Object temp = features.get(XMLConstants.FEATURE_SECURE_PROCESSING); + if (temp != null) { + boolean value = ((Boolean) temp).booleanValue(); + if (value) { + xmlReader.setProperty0(ACCESS_EXTERNAL_DTD, Constants.EXTERNAL_ACCESS_DEFAULT_FSP); + xmlReader.setProperty0(ACCESS_EXTERNAL_SCHEMA, Constants.EXTERNAL_ACCESS_DEFAULT_FSP); + } + } + } } // Set application's features, followed by validation features. @@ -220,6 +242,10 @@ public class SAXParserImpl extends javax.xml.parsers.SAXParser String feature = (String) entry.getKey(); boolean value = ((Boolean) entry.getValue()).booleanValue(); xmlReader.setFeature0(feature, value); + if (feature.equals(XMLConstants.FEATURE_SECURE_PROCESSING) && value) { + xmlReader.setProperty0(ACCESS_EXTERNAL_DTD, ""); + xmlReader.setProperty0(ACCESS_EXTERNAL_SCHEMA, ""); + } } } } diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/AbstractXMLSchema.java b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/AbstractXMLSchema.java index 696dd9e1bf6..25e13a7a5ce 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/AbstractXMLSchema.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/AbstractXMLSchema.java @@ -41,8 +41,15 @@ abstract class AbstractXMLSchema extends Schema implements */ private final HashMap fFeatures; + /** + * Map containing the initial values of properties for + * validators created using this grammar pool container. + */ + private final HashMap fProperties; + public AbstractXMLSchema() { fFeatures = new HashMap(); + fProperties = new HashMap(); } /* @@ -77,11 +84,26 @@ abstract class AbstractXMLSchema extends Schema implements } /* - * Other methods + * Set a feature on the schema */ - - final void setFeature(String featureId, boolean state) { + public final void setFeature(String featureId, boolean state) { fFeatures.put(featureId, state ? Boolean.TRUE : Boolean.FALSE); } + /** + * Returns the initial value of a property for validators created + * using this grammar pool container or null if the validators + * should use the default value. + */ + public final Object getProperty(String propertyId) { + return fProperties.get(propertyId); + } + + /* + * Set a property on the schema + */ + public final void setProperty(String propertyId, Object state) { + fProperties.put(propertyId, state); + } + } // AbstractXMLSchema diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/StreamValidatorHelper.java b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/StreamValidatorHelper.java index 3919c0ca80f..1b4f6875611 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/StreamValidatorHelper.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/StreamValidatorHelper.java @@ -32,6 +32,7 @@ import javax.xml.transform.stream.StreamResult; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.XMLConstants; import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; @@ -176,6 +177,8 @@ final class StreamValidatorHelper implements ValidatorHelper { } config.setProperty(SYMBOL_TABLE, fComponentManager.getProperty(SYMBOL_TABLE)); config.setProperty(VALIDATION_MANAGER, fComponentManager.getProperty(VALIDATION_MANAGER)); + config.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, + fComponentManager.getProperty(XMLConstants.ACCESS_EXTERNAL_DTD)); config.setDocumentHandler(fSchemaValidator); config.setDTDHandler(null); config.setDTDContentModelHandler(null); diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/ValidatorHandlerImpl.java b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/ValidatorHandlerImpl.java index 2d9f2807910..e53118b2d4f 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/ValidatorHandlerImpl.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/ValidatorHandlerImpl.java @@ -675,6 +675,8 @@ final class ValidatorHandlerImpl extends ValidatorHandler implements spf.setNamespaceAware(true); try { reader = spf.newSAXParser().getXMLReader(); + reader.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, + fComponentManager.getProperty(XMLConstants.ACCESS_EXTERNAL_DTD)); // If this is a Xerces SAX parser, set the security manager if there is one if (reader instanceof com.sun.org.apache.xerces.internal.parsers.SAXParser) { SecurityManager securityManager = (SecurityManager) fComponentManager.getProperty(SECURITY_MANAGER); @@ -685,6 +687,8 @@ final class ValidatorHandlerImpl extends ValidatorHandler implements // Ignore the exception if the security manager cannot be set. catch (SAXException exc) {} } + reader.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, + fComponentManager.getProperty(XMLConstants.ACCESS_EXTERNAL_DTD)); } } catch( Exception e ) { // this is impossible, but better safe than sorry diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java index fece15d7697..4cac487362f 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java @@ -45,6 +45,7 @@ import com.sun.org.apache.xerces.internal.util.SecurityManager; import com.sun.org.apache.xerces.internal.util.StAXInputSource; import com.sun.org.apache.xerces.internal.util.Status; import com.sun.org.apache.xerces.internal.util.XMLGrammarPoolImpl; +import com.sun.org.apache.xerces.internal.utils.SecuritySupport; import com.sun.org.apache.xerces.internal.xni.XNIException; import com.sun.org.apache.xerces.internal.xni.grammars.Grammar; import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; @@ -82,6 +83,12 @@ public final class XMLSchemaFactory extends SchemaFactory { private static final String SECURITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; + /** property identifier: access external dtd. */ + public static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD; + + /** Property identifier: access to external schema */ + public static final String ACCESS_EXTERNAL_SCHEMA = XMLConstants.ACCESS_EXTERNAL_SCHEMA; + // // Data // @@ -132,6 +139,14 @@ public final class XMLSchemaFactory extends SchemaFactory { // Enable secure processing feature by default fSecurityManager = new SecurityManager(); fXMLSchemaLoader.setProperty(SECURITY_MANAGER, fSecurityManager); + + //by default, the secure feature is set to true, otherwise the default would have been 'file' + String accessExternal = SecuritySupport.getDefaultAccessProperty( + Constants.SP_ACCESS_EXTERNAL_DTD, Constants.EXTERNAL_ACCESS_DEFAULT); + fXMLSchemaLoader.setProperty(ACCESS_EXTERNAL_DTD, accessExternal); + accessExternal = SecuritySupport.getDefaultAccessProperty( + Constants.SP_ACCESS_EXTERNAL_SCHEMA, Constants.EXTERNAL_ACCESS_DEFAULT); + fXMLSchemaLoader.setProperty(ACCESS_EXTERNAL_SCHEMA, accessExternal); } /** @@ -274,6 +289,7 @@ public final class XMLSchemaFactory extends SchemaFactory { // Use a Schema that uses the system id as the equality source. AbstractXMLSchema schema = new WeakReferenceXMLSchema(); propagateFeatures(schema); + propagateProperties(schema); return schema; } @@ -350,6 +366,8 @@ public final class XMLSchemaFactory extends SchemaFactory { } fSecurityManager = value ? new SecurityManager() : null; fXMLSchemaLoader.setProperty(SECURITY_MANAGER, fSecurityManager); + fXMLSchemaLoader.setProperty(ACCESS_EXTERNAL_DTD, Constants.EXTERNAL_ACCESS_DEFAULT_FSP); + fXMLSchemaLoader.setProperty(ACCESS_EXTERNAL_SCHEMA, Constants.EXTERNAL_ACCESS_DEFAULT_FSP); return; } else if (name.equals(Constants.ORACLE_FEATURE_SERVICE_MECHANISM)) { //in secure mode, let _useServicesMechanism be determined by the constructor @@ -418,6 +436,15 @@ public final class XMLSchemaFactory extends SchemaFactory { } } + private void propagateProperties(AbstractXMLSchema schema) { + String[] properties = fXMLSchemaLoader.getRecognizedProperties(); + for (int i = 0; i < properties.length; ++i) { + Object state = fXMLSchemaLoader.getProperty(properties[i]); + schema.setProperty(properties[i], state); + } + } + + /** * Extension of XMLGrammarPoolImpl which exposes the number of * grammars stored in the grammar pool. diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java index bc4bdefb413..241d02cbf85 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java @@ -123,6 +123,12 @@ final class XMLSchemaValidatorComponentManager extends ParserConfigurationSettin private static final String LOCALE = Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY; + /** property identifier: access external dtd. */ + private static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD; + + /** Property identifier: access to external schema */ + private static final String ACCESS_EXTERNAL_SCHEMA = XMLConstants.ACCESS_EXTERNAL_SCHEMA; + // // Data // @@ -243,6 +249,9 @@ final class XMLSchemaValidatorComponentManager extends ParserConfigurationSettin } fComponents.put(SECURITY_MANAGER, fInitSecurityManager); + //pass on properties set on SchemaFactory + setProperty(ACCESS_EXTERNAL_DTD, grammarContainer.getProperty(ACCESS_EXTERNAL_DTD)); + setProperty(ACCESS_EXTERNAL_SCHEMA, grammarContainer.getProperty(ACCESS_EXTERNAL_SCHEMA)); } /** diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XSGrammarPoolContainer.java b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XSGrammarPoolContainer.java index 0246f37380c..79ef5593b06 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XSGrammarPoolContainer.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XSGrammarPoolContainer.java @@ -55,4 +55,21 @@ public interface XSGrammarPoolContainer { */ public Boolean getFeature(String featureId); + /* + * Set a feature on the schema + */ + public void setFeature(String featureId, boolean state); + + /** + * Returns the initial value of a property for validators created + * using this grammar pool container or null if the validators + * should use the default value. + */ + public Object getProperty(String propertyId); + + /* + * Set a property on the schema + */ + public void setProperty(String propertyId, Object state); + } diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java b/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java index 72acd0a20f8..32ac6a86d78 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java @@ -20,10 +20,13 @@ package com.sun.org.apache.xerces.internal.parsers; +import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; +import java.util.Properties; +import javax.xml.XMLConstants; import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.XML11DTDScannerImpl; @@ -52,6 +55,7 @@ import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings; import com.sun.org.apache.xerces.internal.util.PropertyState; import com.sun.org.apache.xerces.internal.util.Status; import com.sun.org.apache.xerces.internal.util.SymbolTable; +import com.sun.org.apache.xerces.internal.utils.SecuritySupport; import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler; import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler; import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; @@ -274,6 +278,12 @@ public class XML11Configuration extends ParserConfigurationSettings protected static final String SCHEMA_DV_FACTORY = Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY; + /** Property identifier: access to external dtd */ + protected static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD; + + /** Property identifier: access to external schema */ + protected static final String ACCESS_EXTERNAL_SCHEMA = XMLConstants.ACCESS_EXTERNAL_SCHEMA; + // debugging /** Set to true and recompile to print exception stack trace. */ @@ -475,7 +485,8 @@ public class XML11Configuration extends ParserConfigurationSettings XMLSCHEMA_VALIDATION, XMLSCHEMA_FULL_CHECKING, EXTERNAL_GENERAL_ENTITIES, EXTERNAL_PARAMETER_ENTITIES, - PARSER_SETTINGS + PARSER_SETTINGS, + XMLConstants.FEATURE_SECURE_PROCESSING }; addRecognizedFeatures(recognizedFeatures); // set state for default features @@ -488,30 +499,31 @@ public class XML11Configuration extends ParserConfigurationSettings fFeatures.put(SCHEMA_ELEMENT_DEFAULT, Boolean.TRUE); fFeatures.put(NORMALIZE_DATA, Boolean.TRUE); fFeatures.put(SCHEMA_AUGMENT_PSVI, Boolean.TRUE); - fFeatures.put(GENERATE_SYNTHETIC_ANNOTATIONS, Boolean.FALSE); - fFeatures.put(VALIDATE_ANNOTATIONS, Boolean.FALSE); - fFeatures.put(HONOUR_ALL_SCHEMALOCATIONS, Boolean.FALSE); - fFeatures.put(NAMESPACE_GROWTH, Boolean.FALSE); - fFeatures.put(TOLERATE_DUPLICATES, Boolean.FALSE); - fFeatures.put(USE_GRAMMAR_POOL_ONLY, Boolean.FALSE); + fFeatures.put(GENERATE_SYNTHETIC_ANNOTATIONS, Boolean.FALSE); + fFeatures.put(VALIDATE_ANNOTATIONS, Boolean.FALSE); + fFeatures.put(HONOUR_ALL_SCHEMALOCATIONS, Boolean.FALSE); + fFeatures.put(NAMESPACE_GROWTH, Boolean.FALSE); + fFeatures.put(TOLERATE_DUPLICATES, Boolean.FALSE); + fFeatures.put(USE_GRAMMAR_POOL_ONLY, Boolean.FALSE); fFeatures.put(PARSER_SETTINGS, Boolean.TRUE); + fFeatures.put(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); // add default recognized properties final String[] recognizedProperties = { - SYMBOL_TABLE, - ERROR_HANDLER, - ENTITY_RESOLVER, + SYMBOL_TABLE, + ERROR_HANDLER, + ENTITY_RESOLVER, ERROR_REPORTER, ENTITY_MANAGER, DOCUMENT_SCANNER, DTD_SCANNER, DTD_PROCESSOR, DTD_VALIDATOR, - DATATYPE_VALIDATOR_FACTORY, - VALIDATION_MANAGER, - SCHEMA_VALIDATOR, - XML_STRING, + DATATYPE_VALIDATOR_FACTORY, + VALIDATION_MANAGER, + SCHEMA_VALIDATOR, + XML_STRING, XMLGRAMMAR_POOL, JAXP_SCHEMA_SOURCE, JAXP_SCHEMA_LANGUAGE, @@ -523,18 +535,20 @@ public class XML11Configuration extends ParserConfigurationSettings SCHEMA_NONS_LOCATION, LOCALE, SCHEMA_DV_FACTORY, + ACCESS_EXTERNAL_DTD, + ACCESS_EXTERNAL_SCHEMA }; addRecognizedProperties(recognizedProperties); - if (symbolTable == null) { - symbolTable = new SymbolTable(); - } - fSymbolTable = symbolTable; - fProperties.put(SYMBOL_TABLE, fSymbolTable); + if (symbolTable == null) { + symbolTable = new SymbolTable(); + } + fSymbolTable = symbolTable; + fProperties.put(SYMBOL_TABLE, fSymbolTable); fGrammarPool = grammarPool; if (fGrammarPool != null) { - fProperties.put(XMLGRAMMAR_POOL, fGrammarPool); + fProperties.put(XMLGRAMMAR_POOL, fGrammarPool); } fEntityManager = new XMLEntityManager(); @@ -570,6 +584,15 @@ public class XML11Configuration extends ParserConfigurationSettings fVersionDetector = new XMLVersionDetector(); + //FEATURE_SECURE_PROCESSING is true, see the feature above + String accessExternal = SecuritySupport.getDefaultAccessProperty( + Constants.SP_ACCESS_EXTERNAL_DTD, Constants.EXTERNAL_ACCESS_DEFAULT); + fProperties.put(ACCESS_EXTERNAL_DTD, accessExternal); + + accessExternal = SecuritySupport.getDefaultAccessProperty( + Constants.SP_ACCESS_EXTERNAL_SCHEMA, Constants.EXTERNAL_ACCESS_DEFAULT); + fProperties.put(ACCESS_EXTERNAL_SCHEMA, accessExternal); + // add message formatters if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) { XMLMessageFormatter xmft = new XMLMessageFormatter(); diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/util/URI.java b/jaxp/src/com/sun/org/apache/xerces/internal/util/URI.java index 0f35b8ec665..e420f2616b6 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/util/URI.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/util/URI.java @@ -22,6 +22,7 @@ package com.sun.org.apache.xerces.internal.util; import java.io.IOException; import java.io.Serializable; +import java.util.Objects; /********************************************************************** * A class to represent a Uniform Resource Identifier (URI). This class @@ -1212,7 +1213,7 @@ import java.io.Serializable; * @return the scheme-specific part for this URI */ public String getSchemeSpecificPart() { - StringBuffer schemespec = new StringBuffer(); + final StringBuilder schemespec = new StringBuilder(); if (m_host != null || m_regAuthority != null) { schemespec.append("//"); @@ -1297,7 +1298,7 @@ import java.io.Serializable; * @return the authority */ public String getAuthority() { - StringBuffer authority = new StringBuffer(); + final StringBuilder authority = new StringBuilder(); if (m_host != null || m_regAuthority != null) { authority.append("//"); @@ -1340,7 +1341,7 @@ import java.io.Serializable; */ public String getPath(boolean p_includeQueryString, boolean p_includeFragment) { - StringBuffer pathString = new StringBuffer(m_path); + final StringBuilder pathString = new StringBuilder(m_path); if (p_includeQueryString && m_queryString != null) { pathString.append('?'); @@ -1683,6 +1684,7 @@ import java.io.Serializable; * @return true if p_test is a URI with all values equal to this * URI, false otherwise */ + @Override public boolean equals(Object p_test) { if (p_test instanceof URI) { URI testURI = (URI) p_test; @@ -1711,13 +1713,27 @@ import java.io.Serializable; return false; } + @Override + public int hashCode() { + int hash = 5; + hash = 47 * hash + Objects.hashCode(this.m_scheme); + hash = 47 * hash + Objects.hashCode(this.m_userinfo); + hash = 47 * hash + Objects.hashCode(this.m_host); + hash = 47 * hash + this.m_port; + hash = 47 * hash + Objects.hashCode(this.m_path); + hash = 47 * hash + Objects.hashCode(this.m_queryString); + hash = 47 * hash + Objects.hashCode(this.m_fragment); + return hash; + } + /** * Get the URI as a string specification. See RFC 2396 Section 5.2. * * @return the URI string specification */ + @Override public String toString() { - StringBuffer uriSpecString = new StringBuffer(); + final StringBuilder uriSpecString = new StringBuilder(); if (m_scheme != null) { uriSpecString.append(m_scheme); diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/utils/SecuritySupport.java b/jaxp/src/com/sun/org/apache/xerces/internal/utils/SecuritySupport.java index b1d9d870412..7b6d1d553d8 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/utils/SecuritySupport.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/utils/SecuritySupport.java @@ -23,14 +23,16 @@ package com.sun.org.apache.xerces.internal.utils; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.IOException; import java.io.InputStream; - +import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.Locale; import java.util.MissingResourceException; +import java.util.Properties; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; @@ -195,5 +197,141 @@ public final class SecuritySupport { })).longValue(); } + /** + * Strip off path from an URI + * + * @param uri an URI with full path + * @return the file name only + */ + public static String sanitizePath(String uri) { + if (uri == null) { + return ""; + } + int i = uri.lastIndexOf("/"); + if (i > 0) { + return uri.substring(i+1, uri.length()); + } + return ""; + } + + /** + * Check the protocol used in the systemId against allowed protocols + * + * @param systemId the Id of the URI + * @param allowedProtocols a list of allowed protocols separated by comma + * @param accessAny keyword to indicate allowing any protocol + * @return the name of the protocol if rejected, null otherwise + */ + public static String checkAccess(String systemId, String allowedProtocols, String accessAny) throws IOException { + if (systemId == null || allowedProtocols.equalsIgnoreCase(accessAny)) { + return null; + } + + String protocol; + if (systemId.indexOf(":")==-1) { + protocol = "file"; + } else { + URL url = new URL(systemId); + protocol = url.getProtocol(); + if (protocol.equalsIgnoreCase("jar")) { + String path = url.getPath(); + protocol = path.substring(0, path.indexOf(":")); + } + } + + if (isProtocolAllowed(protocol, allowedProtocols)) { + //access allowed + return null; + } else { + return protocol; + } + } + + /** + * Check if the protocol is in the allowed list of protocols. The check + * is case-insensitive while ignoring whitespaces. + * + * @param protocol a protocol + * @param allowedProtocols a list of allowed protocols + * @return true if the protocol is in the list + */ + private static boolean isProtocolAllowed(String protocol, String allowedProtocols) { + String temp[] = allowedProtocols.split(","); + for (String t : temp) { + t = t.trim(); + if (t.equalsIgnoreCase(protocol)) { + return true; + } + } + return false; + } + + /** + * Read from $java.home/lib/jaxp.properties for the specified property + * + * @param propertyId the Id of the property + * @return the value of the property + */ + public static String getDefaultAccessProperty(String sysPropertyId, String defaultVal) { + String accessExternal = SecuritySupport.getSystemProperty(sysPropertyId); + if (accessExternal == null) { + accessExternal = readJAXPProperty(sysPropertyId); + if (accessExternal == null) { + accessExternal = defaultVal; + } + } + return accessExternal; + } + + /** + * Read from $java.home/lib/jaxp.properties for the specified property + * The program + * + * @param propertyId the Id of the property + * @return the value of the property + */ + static String readJAXPProperty(String propertyId) { + String value = null; + InputStream is = null; + try { + if (firstTime) { + synchronized (cacheProps) { + if (firstTime) { + String configFile = getSystemProperty("java.home") + File.separator + + "lib" + File.separator + "jaxp.properties"; + File f = new File(configFile); + if (getFileExists(f)) { + is = getFileInputStream(f); + cacheProps.load(is); + } + firstTime = false; + } + } + } + value = cacheProps.getProperty(propertyId); + + } + catch (Exception ex) {} + finally { + if (is != null) { + try { + is.close(); + } catch (IOException ex) {} + } + } + + return value; + } + + /** + * Cache for properties in java.home/lib/jaxp.properties + */ + static final Properties cacheProps = new Properties(); + + /** + * Flag indicating if the program has tried reading java.home/lib/jaxp.properties + */ + static volatile boolean firstTime = true; + private SecuritySupport () {} } diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/XIncludeHandler.java b/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/XIncludeHandler.java index 347ae24e446..ba7284609e1 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/XIncludeHandler.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/xinclude/XIncludeHandler.java @@ -26,6 +26,7 @@ import java.util.Enumeration; import java.util.Locale; import java.util.Stack; import java.util.StringTokenizer; +import javax.xml.XMLConstants; import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.XMLEntityManager; @@ -67,6 +68,7 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration; import com.sun.org.apache.xerces.internal.xpointer.XPointerHandler; import com.sun.org.apache.xerces.internal.xpointer.XPointerProcessor; import com.sun.org.apache.xerces.internal.utils.ObjectFactory; +import java.util.Objects; /** *

@@ -229,6 +231,14 @@ public class XIncludeHandler protected static final String PARSER_SETTINGS = Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS; + /** property identifier: access external dtd. */ + protected static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD; + + /** access external dtd: file protocol + * For DOM/SAX, the secure feature is set to true by default + */ + final static String EXTERNAL_ACCESS_DEFAULT = Constants.EXTERNAL_ACCESS_DEFAULT; + /** Recognized features. */ private static final String[] RECOGNIZED_FEATURES = { ALLOW_UE_AND_NOTATION_EVENTS, XINCLUDE_FIXUP_BASE_URIS, XINCLUDE_FIXUP_LANGUAGE }; @@ -283,6 +293,12 @@ public class XIncludeHandler protected XMLErrorReporter fErrorReporter; protected XMLEntityResolver fEntityResolver; protected SecurityManager fSecurityManager; + /** + * comma-delimited list of protocols that are allowed for the purpose + * of accessing external dtd or entity references + */ + protected String fAccessExternalDTD = EXTERNAL_ACCESS_DEFAULT; + // these are needed for text include processing protected XIncludeTextReader fXInclude10TextReader; @@ -375,6 +391,7 @@ public class XIncludeHandler // XMLComponent methods + @Override public void reset(XMLComponentManager componentManager) throws XNIException { fNamespaceContext = null; @@ -523,6 +540,8 @@ public class XIncludeHandler fSecurityManager = null; } + fAccessExternalDTD = (String)componentManager.getProperty(ACCESS_EXTERNAL_DTD); + // Get buffer size. try { Integer value = @@ -580,6 +599,7 @@ public class XIncludeHandler * this component. This method may return null if no features * are recognized by this component. */ + @Override public String[] getRecognizedFeatures() { return (String[])(RECOGNIZED_FEATURES.clone()); } // getRecognizedFeatures():String[] @@ -599,6 +619,7 @@ public class XIncludeHandler * @throws SAXNotSupportedException The component should not throw * this exception. */ + @Override public void setFeature(String featureId, boolean state) throws XMLConfigurationException { if (featureId.equals(ALLOW_UE_AND_NOTATION_EVENTS)) { @@ -615,6 +636,7 @@ public class XIncludeHandler * this component. This method may return null if no properties * are recognized by this component. */ + @Override public String[] getRecognizedProperties() { return (String[])(RECOGNIZED_PROPERTIES.clone()); } // getRecognizedProperties():String[] @@ -634,6 +656,7 @@ public class XIncludeHandler * @throws SAXNotSupportedException The component should not throw * this exception. */ + @Override public void setProperty(String propertyId, Object value) throws XMLConfigurationException { if (propertyId.equals(SYMBOL_TABLE)) { @@ -664,6 +687,14 @@ public class XIncludeHandler } return; } + if (propertyId.equals(ACCESS_EXTERNAL_DTD)) { + fAccessExternalDTD = (String)value; + if (fChildConfig != null) { + fChildConfig.setProperty(propertyId, value); + } + return; + } + if (propertyId.equals(BUFFER_SIZE)) { Integer bufferSize = (Integer) value; if (fChildConfig != null) { @@ -694,6 +725,7 @@ public class XIncludeHandler * * @since Xerces 2.2.0 */ + @Override public Boolean getFeatureDefault(String featureId) { for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) { if (RECOGNIZED_FEATURES[i].equals(featureId)) { @@ -712,6 +744,7 @@ public class XIncludeHandler * * @since Xerces 2.2.0 */ + @Override public Object getPropertyDefault(String propertyId) { for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) { if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) { @@ -721,10 +754,12 @@ public class XIncludeHandler return null; } // getPropertyDefault(String):Object + @Override public void setDocumentHandler(XMLDocumentHandler handler) { fDocumentHandler = handler; } + @Override public XMLDocumentHandler getDocumentHandler() { return fDocumentHandler; } @@ -739,6 +774,7 @@ public class XIncludeHandler * * This event is only passed on to the document handler if this is the root document. */ + @Override public void startDocument( XMLLocator locator, String encoding, @@ -786,6 +822,7 @@ public class XIncludeHandler } } + @Override public void xmlDecl( String version, String encoding, @@ -798,6 +835,7 @@ public class XIncludeHandler } } + @Override public void doctypeDecl( String rootElement, String publicId, @@ -809,6 +847,7 @@ public class XIncludeHandler } } + @Override public void comment(XMLString text, Augmentations augs) throws XNIException { if (!fInDTD) { @@ -825,6 +864,7 @@ public class XIncludeHandler } } + @Override public void processingInstruction( String target, XMLString data, @@ -845,6 +885,7 @@ public class XIncludeHandler } } + @Override public void startElement( QName element, XMLAttributes attributes, @@ -915,6 +956,7 @@ public class XIncludeHandler } } + @Override public void emptyElement( QName element, XMLAttributes attributes, @@ -996,6 +1038,7 @@ public class XIncludeHandler fDepth--; } + @Override public void endElement(QName element, Augmentations augs) throws XNIException { @@ -1041,6 +1084,7 @@ public class XIncludeHandler fDepth--; } + @Override public void startGeneralEntity( String name, XMLResourceIdentifier resId, @@ -1059,6 +1103,7 @@ public class XIncludeHandler } } + @Override public void textDecl(String version, String encoding, Augmentations augs) throws XNIException { if (fDocumentHandler != null @@ -1067,6 +1112,7 @@ public class XIncludeHandler } } + @Override public void endGeneralEntity(String name, Augmentations augs) throws XNIException { if (fDocumentHandler != null @@ -1076,6 +1122,7 @@ public class XIncludeHandler } } + @Override public void characters(XMLString text, Augmentations augs) throws XNIException { if (getState() == STATE_NORMAL_PROCESSING) { @@ -1092,6 +1139,7 @@ public class XIncludeHandler } } + @Override public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException { if (fDocumentHandler != null @@ -1101,6 +1149,7 @@ public class XIncludeHandler } } + @Override public void startCDATA(Augmentations augs) throws XNIException { if (fDocumentHandler != null && getState() == STATE_NORMAL_PROCESSING @@ -1109,6 +1158,7 @@ public class XIncludeHandler } } + @Override public void endCDATA(Augmentations augs) throws XNIException { if (fDocumentHandler != null && getState() == STATE_NORMAL_PROCESSING @@ -1117,6 +1167,7 @@ public class XIncludeHandler } } + @Override public void endDocument(Augmentations augs) throws XNIException { if (isRootDocument()) { if (!fSeenRootElement) { @@ -1128,10 +1179,12 @@ public class XIncludeHandler } } + @Override public void setDocumentSource(XMLDocumentSource source) { fDocumentSource = source; } + @Override public XMLDocumentSource getDocumentSource() { return fDocumentSource; } @@ -1143,6 +1196,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#attributeDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, com.sun.org.apache.xerces.internal.xni.XMLString, com.sun.org.apache.xerces.internal.xni.XMLString, com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void attributeDecl( String elementName, String attributeName, @@ -1169,6 +1223,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#elementDecl(java.lang.String, java.lang.String, com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void elementDecl( String name, String contentModel, @@ -1182,6 +1237,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#endAttlist(com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void endAttlist(Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.endAttlist(augmentations); @@ -1191,6 +1247,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#endConditional(com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void endConditional(Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { @@ -1201,6 +1258,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#endDTD(com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void endDTD(Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.endDTD(augmentations); @@ -1211,6 +1269,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#endExternalSubset(com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void endExternalSubset(Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { @@ -1221,6 +1280,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#endParameterEntity(java.lang.String, com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void endParameterEntity(String name, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { @@ -1231,6 +1291,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#externalEntityDecl(java.lang.String, com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier, com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void externalEntityDecl( String name, XMLResourceIdentifier identifier, @@ -1244,6 +1305,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#getDTDSource() */ + @Override public XMLDTDSource getDTDSource() { return fDTDSource; } @@ -1251,6 +1313,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#ignoredCharacters(com.sun.org.apache.xerces.internal.xni.XMLString, com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void ignoredCharacters(XMLString text, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { @@ -1261,6 +1324,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#internalEntityDecl(java.lang.String, com.sun.org.apache.xerces.internal.xni.XMLString, com.sun.org.apache.xerces.internal.xni.XMLString, com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void internalEntityDecl( String name, XMLString text, @@ -1279,6 +1343,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#notationDecl(java.lang.String, com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier, com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void notationDecl( String name, XMLResourceIdentifier identifier, @@ -1293,6 +1358,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#setDTDSource(com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource) */ + @Override public void setDTDSource(XMLDTDSource source) { fDTDSource = source; } @@ -1300,6 +1366,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#startAttlist(java.lang.String, com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void startAttlist(String elementName, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { @@ -1310,6 +1377,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#startConditional(short, com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void startConditional(short type, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { @@ -1320,6 +1388,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#startDTD(com.sun.org.apache.xerces.internal.xni.XMLLocator, com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void startDTD(XMLLocator locator, Augmentations augmentations) throws XNIException { fInDTD = true; @@ -1331,6 +1400,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#startExternalSubset(com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier, com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void startExternalSubset( XMLResourceIdentifier identifier, Augmentations augmentations) @@ -1343,6 +1413,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#startParameterEntity(java.lang.String, com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier, java.lang.String, com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void startParameterEntity( String name, XMLResourceIdentifier identifier, @@ -1361,6 +1432,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#unparsedEntityDecl(java.lang.String, com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier, java.lang.String, com.sun.org.apache.xerces.internal.xni.Augmentations) */ + @Override public void unparsedEntityDecl( String name, XMLResourceIdentifier identifier, @@ -1380,6 +1452,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource#getDTDHandler() */ + @Override public XMLDTDHandler getDTDHandler() { return fDTDHandler; } @@ -1387,6 +1460,7 @@ public class XIncludeHandler /* (non-Javadoc) * @see com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource#setDTDHandler(com.sun.org.apache.xerces.internal.xni.XMLDTDHandler) */ + @Override public void setDTDHandler(XMLDTDHandler handler) { fDTDHandler = handler; } @@ -1578,6 +1652,7 @@ public class XIncludeHandler if (fErrorReporter != null) fChildConfig.setProperty(ERROR_REPORTER, fErrorReporter); if (fEntityResolver != null) fChildConfig.setProperty(ENTITY_RESOLVER, fEntityResolver); fChildConfig.setProperty(SECURITY_MANAGER, fSecurityManager); + fChildConfig.setProperty(ACCESS_EXTERNAL_DTD, fAccessExternalDTD); fChildConfig.setProperty(BUFFER_SIZE, new Integer(fBufferSize)); // features must be copied to child configuration @@ -1615,11 +1690,10 @@ public class XIncludeHandler fNamespaceContext); ((XPointerHandler)fXPtrProcessor).setProperty(XINCLUDE_FIXUP_BASE_URIS, - new Boolean(fFixupBaseURIs)); + fFixupBaseURIs); ((XPointerHandler)fXPtrProcessor).setProperty( - XINCLUDE_FIXUP_LANGUAGE, - new Boolean (fFixupLanguage)); + XINCLUDE_FIXUP_LANGUAGE, fFixupLanguage); if (fErrorReporter != null) ((XPointerHandler)fXPtrProcessor).setProperty(ERROR_REPORTER, fErrorReporter); @@ -1691,7 +1765,7 @@ public class XIncludeHandler if (fErrorReporter != null) { fErrorReporter.setDocumentLocator(fDocLocation); } - reportFatalError("XMLParseError", new Object[] { href }); + reportFatalError("XMLParseError", new Object[] { href, e.getMessage() }); } catch (IOException e) { // necessary to make sure proper location is reported in errors @@ -2093,14 +2167,14 @@ public class XIncludeHandler /** Check whether the scheme components are equal. */ final String baseScheme = base.getScheme(); final String literalScheme = uri.getScheme(); - if (!isEqual(baseScheme, literalScheme)) { + if (!Objects.equals(baseScheme, literalScheme)) { return relativeURI; } /** Check whether the authority components are equal. */ final String baseAuthority = base.getAuthority(); final String literalAuthority = uri.getAuthority(); - if (!isEqual(baseAuthority, literalAuthority)) { + if (!Objects.equals(baseAuthority, literalAuthority)) { return uri.getSchemeSpecificPart(); } @@ -2113,7 +2187,7 @@ public class XIncludeHandler final String literalQuery = uri.getQueryString(); final String literalFragment = uri.getFragment(); if (literalQuery != null || literalFragment != null) { - StringBuffer buffer = new StringBuffer(); + final StringBuilder buffer = new StringBuilder(); if (literalPath != null) { buffer.append(literalPath); } @@ -2624,15 +2698,15 @@ public class XIncludeHandler // equals() returns true if two Notations have the same name. // Useful for searching Vectors for notations with the same name + @Override public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (obj instanceof Notation) { - Notation other = (Notation)obj; - return name.equals(other.name); - } - return false; + return obj == this || obj instanceof Notation + && Objects.equals(name, ((Notation)obj).name); + } + + @Override + public int hashCode() { + return Objects.hashCode(name); } // from 4.5.2 @@ -2645,16 +2719,12 @@ public class XIncludeHandler public boolean isDuplicate(Object obj) { if (obj != null && obj instanceof Notation) { Notation other = (Notation)obj; - return name.equals(other.name) - && isEqual(publicId, other.publicId) - && isEqual(expandedSystemId, other.expandedSystemId); + return Objects.equals(name, other.name) + && Objects.equals(publicId, other.publicId) + && Objects.equals(expandedSystemId, other.expandedSystemId); } return false; } - - private boolean isEqual(String one, String two) { - return (one == two || (one != null && one.equals(two))); - } } // This is a storage class to hold information about the unparsed entities. @@ -2670,15 +2740,15 @@ public class XIncludeHandler // equals() returns true if two UnparsedEntities have the same name. // Useful for searching Vectors for entities with the same name + @Override public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (obj instanceof UnparsedEntity) { - UnparsedEntity other = (UnparsedEntity)obj; - return name.equals(other.name); - } - return false; + return obj == this || obj instanceof UnparsedEntity + && Objects.equals(name, ((UnparsedEntity)obj).name); + } + + @Override + public int hashCode() { + return Objects.hashCode(name); } // from 4.5.1: @@ -2691,17 +2761,13 @@ public class XIncludeHandler public boolean isDuplicate(Object obj) { if (obj != null && obj instanceof UnparsedEntity) { UnparsedEntity other = (UnparsedEntity)obj; - return name.equals(other.name) - && isEqual(publicId, other.publicId) - && isEqual(expandedSystemId, other.expandedSystemId) - && isEqual(notation, other.notation); + return Objects.equals(name, other.name) + && Objects.equals(publicId, other.publicId) + && Objects.equals(expandedSystemId, other.expandedSystemId) + && Objects.equals(notation, other.notation); } return false; } - - private boolean isEqual(String one, String two) { - return (one == two || (one != null && one.equals(two))); - } } // The following methods are used for XML Base processing @@ -2891,17 +2957,13 @@ public class XIncludeHandler return httpSource; } - private boolean isEqual(String one, String two) { - return (one == two || (one != null && one.equals(two))); - } - // which ASCII characters need to be escaped - private static boolean gNeedEscaping[] = new boolean[128]; + private static final boolean gNeedEscaping[] = new boolean[128]; // the first hex character if a character needs to be escaped - private static char gAfterEscaping1[] = new char[128]; + private static final char gAfterEscaping1[] = new char[128]; // the second hex character if a character needs to be escaped - private static char gAfterEscaping2[] = new char[128]; - private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7', + private static final char gAfterEscaping2[] = new char[128]; + private static final char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; // initialize the above 3 arrays static { @@ -2931,7 +2993,7 @@ public class XIncludeHandler private String escapeHref(String href) { int len = href.length(); int ch; - StringBuffer buffer = new StringBuffer(len*3); + final StringBuilder buffer = new StringBuilder(len*3); // for each character in the href int i = 0; diff --git a/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMNodeProxy.java b/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMNodeProxy.java index fa86b06fc3e..d9ca5b010f5 100644 --- a/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMNodeProxy.java +++ b/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMNodeProxy.java @@ -27,6 +27,7 @@ import java.util.Vector; import com.sun.org.apache.xml.internal.dtm.DTM; import com.sun.org.apache.xml.internal.dtm.DTMDOMException; import com.sun.org.apache.xpath.internal.NodeSet; +import java.util.Objects; import org.w3c.dom.Attr; import org.w3c.dom.CDATASection; @@ -141,21 +142,21 @@ public class DTMNodeProxy * * @return true if the given node has the same handle as this node. */ + @Override public final boolean equals(Object node) { - - try - { - // DTMNodeProxy dtmp = (DTMNodeProxy)node; // return (dtmp.node == this.node); // Patch attributed to Gary L Peskin - return equals((Node) node); - } - catch (ClassCastException cce) - { - return false; - } + return node instanceof Node && equals((Node) node); + } + + @Override + public int hashCode() { + int hash = 7; + hash = 29 * hash + Objects.hashCode(this.dtm); + hash = 29 * hash + this.node; + return hash; } /** @@ -181,6 +182,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Node */ + @Override public final String getNodeName() { return dtm.getNodeName(node); @@ -199,6 +201,7 @@ public class DTMNodeProxy * * */ + @Override public final String getTarget() { return dtm.getNodeName(node); @@ -209,6 +212,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Node as of DOM Level 2 */ + @Override public final String getLocalName() { return dtm.getLocalName(node); @@ -218,6 +222,7 @@ public class DTMNodeProxy * @return The prefix for this node. * @see org.w3c.dom.Node as of DOM Level 2 */ + @Override public final String getPrefix() { return dtm.getPrefix(node); @@ -230,6 +235,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Node as of DOM Level 2 -- DTMNodeProxy is read-only */ + @Override public final void setPrefix(String prefix) throws DOMException { throw new DTMDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR); @@ -240,6 +246,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Node as of DOM Level 2 */ + @Override public final String getNamespaceURI() { return dtm.getNamespaceURI(node); @@ -277,6 +284,7 @@ public class DTMNodeProxy * @return false * @see org.w3c.dom.Node as of DOM Level 2 */ + @Override public final boolean isSupported(String feature, String version) { return implementation.hasFeature(feature,version); @@ -290,6 +298,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Node */ + @Override public final String getNodeValue() throws DOMException { return dtm.getNodeValue(node); @@ -312,6 +321,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Node -- DTMNodeProxy is read-only */ + @Override public final void setNodeValue(String nodeValue) throws DOMException { throw new DTMDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR); @@ -322,6 +332,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Node */ + @Override public final short getNodeType() { return (short) dtm.getNodeType(node); @@ -332,6 +343,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Node */ + @Override public final Node getParentNode() { @@ -361,6 +373,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Node */ + @Override public final NodeList getChildNodes() { @@ -377,6 +390,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Node */ + @Override public final Node getFirstChild() { @@ -390,6 +404,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Node */ + @Override public final Node getLastChild() { @@ -403,6 +418,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Node */ + @Override public final Node getPreviousSibling() { @@ -416,6 +432,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Node */ + @Override public final Node getNextSibling() { @@ -435,6 +452,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Node */ + @Override public final NamedNodeMap getAttributes() { @@ -448,6 +466,7 @@ public class DTMNodeProxy * @param name * */ + @Override public boolean hasAttribute(String name) { return DTM.NULL != dtm.getAttributeNode(node,null,name); @@ -462,6 +481,7 @@ public class DTMNodeProxy * * */ + @Override public boolean hasAttributeNS(String namespaceURI, String localName) { return DTM.NULL != dtm.getAttributeNode(node,namespaceURI,localName); @@ -472,6 +492,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Node */ + @Override public final Document getOwnerDocument() { // Note that this uses the DOM-compatable version of the call @@ -488,6 +509,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Node -- DTMNodeProxy is read-only */ + @Override public final Node insertBefore(Node newChild, Node refChild) throws DOMException { @@ -504,6 +526,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Node -- DTMNodeProxy is read-only */ + @Override public final Node replaceChild(Node newChild, Node oldChild) throws DOMException { @@ -519,6 +542,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Node -- DTMNodeProxy is read-only */ + @Override public final Node removeChild(Node oldChild) throws DOMException { throw new DTMDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR); @@ -533,6 +557,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Node -- DTMNodeProxy is read-only */ + @Override public final Node appendChild(Node newChild) throws DOMException { throw new DTMDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR); @@ -543,6 +568,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Node */ + @Override public final boolean hasChildNodes() { return (DTM.NULL != dtm.getFirstChild(node)); @@ -555,6 +581,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Node -- DTMNodeProxy is read-only */ + @Override public final Node cloneNode(boolean deep) { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -565,6 +592,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Document */ + @Override public final DocumentType getDoctype() { return null; @@ -575,6 +603,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Document */ + @Override public final DOMImplementation getImplementation() { return implementation; @@ -587,6 +616,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Document */ + @Override public final Element getDocumentElement() { int dochandle=dtm.getDocument(); @@ -634,6 +664,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Document */ + @Override public final Element createElement(String tagName) throws DOMException { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -644,6 +675,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Document */ + @Override public final DocumentFragment createDocumentFragment() { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -656,6 +688,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Document */ + @Override public final Text createTextNode(String data) { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -668,6 +701,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Document */ + @Override public final Comment createComment(String data) { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -682,6 +716,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Document */ + @Override public final CDATASection createCDATASection(String data) throws DOMException { @@ -698,8 +733,9 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Document */ + @Override public final ProcessingInstruction createProcessingInstruction( - String target, String data) throws DOMException + String target, String data) throws DOMException { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); } @@ -713,6 +749,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Document */ + @Override public final Attr createAttribute(String name) throws DOMException { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -727,6 +764,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Document */ + @Override public final EntityReference createEntityReference(String name) throws DOMException { @@ -739,6 +777,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Document */ + @Override public final NodeList getElementsByTagName(String tagname) { Vector listVector = new Vector(); @@ -819,6 +858,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Document as of DOM Level 2 -- DTMNodeProxy is read-only */ + @Override public final Node importNode(Node importedNode, boolean deep) throws DOMException { @@ -835,8 +875,9 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Document as of DOM Level 2 */ + @Override public final Element createElementNS( - String namespaceURI, String qualifiedName) throws DOMException + String namespaceURI, String qualifiedName) throws DOMException { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); } @@ -851,8 +892,9 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Document as of DOM Level 2 */ + @Override public final Attr createAttributeNS( - String namespaceURI, String qualifiedName) throws DOMException + String namespaceURI, String qualifiedName) throws DOMException { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); } @@ -865,6 +907,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Document as of DOM Level 2 */ + @Override public final NodeList getElementsByTagNameNS(String namespaceURI, String localName) { @@ -952,6 +995,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Document as of DOM Level 2 */ + @Override public final Element getElementById(String elementId) { return (Element) dtm.getNode(dtm.getElementById(elementId)); @@ -966,6 +1010,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Text */ + @Override public final Text splitText(int offset) throws DOMException { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -978,6 +1023,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.CharacterData */ + @Override public final String getData() throws DOMException { return dtm.getNodeValue(node); @@ -990,6 +1036,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.CharacterData */ + @Override public final void setData(String data) throws DOMException { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -1000,6 +1047,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.CharacterData */ + @Override public final int getLength() { // %OPT% This should do something smarter? @@ -1016,6 +1064,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.CharacterData */ + @Override public final String substringData(int offset, int count) throws DOMException { return getData().substring(offset,offset+count); @@ -1028,6 +1077,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.CharacterData */ + @Override public final void appendData(String arg) throws DOMException { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -1041,6 +1091,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.CharacterData */ + @Override public final void insertData(int offset, String arg) throws DOMException { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -1054,6 +1105,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.CharacterData */ + @Override public final void deleteData(int offset, int count) throws DOMException { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -1068,6 +1120,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.CharacterData */ + @Override public final void replaceData(int offset, int count, String arg) throws DOMException { @@ -1079,6 +1132,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Element */ + @Override public final String getTagName() { return dtm.getNodeName(node); @@ -1091,12 +1145,13 @@ public class DTMNodeProxy * * @see org.w3c.dom.Element */ + @Override public final String getAttribute(String name) { - DTMNamedNodeMap map = new DTMNamedNodeMap(dtm, node); - Node node = map.getNamedItem(name); - return (null == node) ? EMPTYSTRING : node.getNodeValue(); } + Node n = map.getNamedItem(name); + return (null == n) ? EMPTYSTRING : n.getNodeValue(); + } /** * @@ -1106,6 +1161,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Element */ + @Override public final void setAttribute(String name, String value) throws DOMException { @@ -1119,6 +1175,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Element */ + @Override public final void removeAttribute(String name) throws DOMException { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -1131,9 +1188,9 @@ public class DTMNodeProxy * * @see org.w3c.dom.Element */ + @Override public final Attr getAttributeNode(String name) { - DTMNamedNodeMap map = new DTMNamedNodeMap(dtm, node); return (Attr)map.getNamedItem(name); } @@ -1147,6 +1204,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Element */ + @Override public final Attr setAttributeNode(Attr newAttr) throws DOMException { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -1161,6 +1219,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Element */ + @Override public final Attr removeAttributeNode(Attr oldAttr) throws DOMException { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -1171,12 +1230,14 @@ public class DTMNodeProxy * * */ + @Override public boolean hasAttributes() { return DTM.NULL != dtm.getFirstAttribute(node); } /** @see org.w3c.dom.Element */ + @Override public final void normalize() { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -1190,6 +1251,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Element */ + @Override public final String getAttributeNS(String namespaceURI, String localName) { Node retNode = null; @@ -1208,6 +1270,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Element */ + @Override public final void setAttributeNS( String namespaceURI, String qualifiedName, String value) throws DOMException @@ -1223,6 +1286,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Element */ + @Override public final void removeAttributeNS(String namespaceURI, String localName) throws DOMException { @@ -1237,6 +1301,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Element */ + @Override public final Attr getAttributeNodeNS(String namespaceURI, String localName) { Attr retAttr = null; @@ -1256,6 +1321,7 @@ public class DTMNodeProxy * @throws DOMException * @see org.w3c.dom.Element */ + @Override public final Attr setAttributeNodeNS(Attr newAttr) throws DOMException { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -1266,6 +1332,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Attr */ + @Override public final String getName() { return dtm.getNodeName(node); @@ -1276,6 +1343,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Attr */ + @Override public final boolean getSpecified() { // We really don't know which attributes might have come from the @@ -1290,6 +1358,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Attr */ + @Override public final String getValue() { return dtm.getNodeValue(node); @@ -1300,6 +1369,7 @@ public class DTMNodeProxy * @param value * @see org.w3c.dom.Attr */ + @Override public final void setValue(String value) { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -1311,6 +1381,7 @@ public class DTMNodeProxy * * @see org.w3c.dom.Attr as of DOM Level 2 */ + @Override public final Element getOwnerElement() { if (getNodeType() != Node.ATTRIBUTE_NODE) @@ -1331,9 +1402,9 @@ public class DTMNodeProxy * * @throws DOMException */ + @Override public Node adoptNode(Node source) throws DOMException { - throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); } @@ -1348,9 +1419,9 @@ public class DTMNodeProxy * * NEEDSDOC ($objectName$) @return */ + @Override public String getInputEncoding() { - throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); } @@ -1383,7 +1454,6 @@ public class DTMNodeProxy */ public boolean getStandalone() { - throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); } @@ -1418,9 +1488,9 @@ public class DTMNodeProxy * * NEEDSDOC ($objectName$) @return */ + @Override public boolean getStrictErrorChecking() { - throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); } @@ -1439,6 +1509,7 @@ public class DTMNodeProxy * * NEEDSDOC @param strictErrorChecking */ + @Override public void setStrictErrorChecking(boolean strictErrorChecking) { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); @@ -1457,7 +1528,6 @@ public class DTMNodeProxy */ public String getVersion() { - throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); } @@ -1482,10 +1552,12 @@ public class DTMNodeProxy */ static class DTMNodeProxyImplementation implements DOMImplementation { + @Override public DocumentType createDocumentType(String qualifiedName,String publicId, String systemId) { throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR); } + @Override public Document createDocument(String namespaceURI,String qualfiedName,DocumentType doctype) { // Could create a DTM... but why, when it'd have to be permanantly empty? @@ -1500,6 +1572,7 @@ public class DTMNodeProxy * methods we can't support. I'm not sure which would be more useful * to the caller. */ + @Override public boolean hasFeature(String feature,String version) { if( ("CORE".equals(feature.toUpperCase()) || "XML".equals(feature.toUpperCase())) @@ -1530,6 +1603,7 @@ public class DTMNodeProxy * childNodes, etc. * @since DOM Level 3 */ + @Override public Object getFeature(String feature, String version) { // we don't have any alternate node, either this node does the job // or we don't have anything that does @@ -1542,6 +1616,7 @@ public class DTMNodeProxy //RAMESH : Pending proper implementation of DOM Level 3 + @Override public Object setUserData(String key, Object data, UserDataHandler handler) { @@ -1557,6 +1632,7 @@ public class DTMNodeProxy * on this node, or null if there was none. * @since DOM Level 3 */ + @Override public Object getUserData(String key) { return getOwnerDocument().getUserData( key); } @@ -1581,6 +1657,7 @@ public class DTMNodeProxy * childNodes, etc. * @since DOM Level 3 */ + @Override public Object getFeature(String feature, String version) { // we don't have any alternate node, either this node does the job // or we don't have anything that does @@ -1629,6 +1706,7 @@ public class DTMNodeProxy * true otherwise false. * @since DOM Level 3 */ + @Override public boolean isEqualNode(Node arg) { if (arg == this) { return true; @@ -1705,6 +1783,7 @@ public class DTMNodeProxy * @return th URI for the namespace * @since DOM Level 3 */ + @Override public String lookupNamespaceURI(String specifiedPrefix) { short type = this.getNodeType(); switch (type) { @@ -1797,6 +1876,7 @@ public class DTMNodeProxy * is the default namespace, false otherwise. * @since DOM Level 3 */ + @Override public boolean isDefaultNamespace(String namespaceURI){ /* // REVISIT: remove casts when DOM L3 becomes REC. @@ -1871,6 +1951,7 @@ public class DTMNodeProxy * @param namespaceURI * @return the prefix for the namespace */ + @Override public String lookupPrefix(String namespaceURI){ // REVISIT: When Namespaces 1.1 comes out this may not be true @@ -1932,6 +2013,7 @@ public class DTMNodeProxy * false otherwise. * @since DOM Level 3 */ + @Override public boolean isSameNode(Node other) { // we do not use any wrapper so the answer is obvious return this == other; @@ -1980,8 +2062,9 @@ public class DTMNodeProxy * DOMSTRING_SIZE_ERR: Raised when it would return more characters than * fit in a DOMString variable on the implementation * platform. - * @since DOM Level 3 + * @since DOM Level 3 */ + @Override public void setTextContent(String textContent) throws DOMException { setNodeValue(textContent); @@ -2031,6 +2114,7 @@ public class DTMNodeProxy * platform. * @since DOM Level 3 */ + @Override public String getTextContent() throws DOMException { return getNodeValue(); // overriden in some subclasses } @@ -2043,6 +2127,7 @@ public class DTMNodeProxy * node. * @since DOM Level 3 */ + @Override public short compareDocumentPosition(Node other) throws DOMException { return 0; } @@ -2071,14 +2156,16 @@ public class DTMNodeProxy * Yes. (F2F 26 Sep 2001) * @since DOM Level 3 */ + @Override public String getBaseURI() { return null; } - /** + /** * DOM Level 3 * Renaming node */ + @Override public Node renameNode(Node n, String namespaceURI, String name) @@ -2091,14 +2178,16 @@ public class DTMNodeProxy * DOM Level 3 * Normalize document. */ + @Override public void normalizeDocument(){ } /** - * The configuration used when Document.normalizeDocument is + * The configuration used when Document.normalizeDocument is * invoked. * @since DOM Level 3 */ + @Override public DOMConfiguration getDomConfig(){ return null; } @@ -2110,8 +2199,8 @@ public class DTMNodeProxy /** * DOM Level 3 */ + @Override public void setDocumentURI(String documentURI){ - fDocumentURI= documentURI; } @@ -2123,6 +2212,7 @@ public class DTMNodeProxy * over this attribute. * @since DOM Level 3 */ + @Override public String getDocumentURI(){ return fDocumentURI; } @@ -2154,9 +2244,10 @@ public class DTMNodeProxy actualEncoding = value; } - /** + /** * DOM Level 3 */ + @Override public Text replaceWholeText(String content) throws DOMException{ /* @@ -2210,6 +2301,7 @@ public class DTMNodeProxy * nodes to this node, concatenated in document order. * @since DOM Level 3 */ + @Override public String getWholeText(){ /* @@ -2235,13 +2327,11 @@ public class DTMNodeProxy * Returns whether this text node contains whitespace in element content, * often abusively called "ignorable whitespace". */ + @Override public boolean isElementContentWhitespace(){ return false; } - - - /** * NON-DOM: set the type of this attribute to be ID type. * @@ -2254,6 +2344,7 @@ public class DTMNodeProxy /** * DOM Level 3: register the given attribute node as an ID attribute */ + @Override public void setIdAttribute(String name, boolean makeId) { //PENDING } @@ -2262,6 +2353,7 @@ public class DTMNodeProxy /** * DOM Level 3: register the given attribute node as an ID attribute */ + @Override public void setIdAttributeNode(Attr at, boolean makeId) { //PENDING } @@ -2269,6 +2361,7 @@ public class DTMNodeProxy /** * DOM Level 3: register the given attribute node as an ID attribute */ + @Override public void setIdAttributeNS(String namespaceURI, String localName, boolean makeId) { //PENDING @@ -2277,16 +2370,19 @@ public class DTMNodeProxy * Method getSchemaTypeInfo. * @return TypeInfo */ + @Override public TypeInfo getSchemaTypeInfo(){ return null; //PENDING } + @Override public boolean isId() { return false; //PENDING } private String xmlEncoding; + @Override public String getXmlEncoding( ) { return xmlEncoding; } @@ -2295,23 +2391,25 @@ public class DTMNodeProxy } private boolean xmlStandalone; + @Override public boolean getXmlStandalone() { return xmlStandalone; } + @Override public void setXmlStandalone(boolean xmlStandalone) throws DOMException { this.xmlStandalone = xmlStandalone; } private String xmlVersion; + @Override public String getXmlVersion() { return xmlVersion; } + @Override public void setXmlVersion(String xmlVersion) throws DOMException { this.xmlVersion = xmlVersion; } - - } diff --git a/jaxp/src/com/sun/org/apache/xml/internal/serializer/Encodings.java b/jaxp/src/com/sun/org/apache/xml/internal/serializer/Encodings.java index 35845697a32..d4d95ff8cf2 100644 --- a/jaxp/src/com/sun/org/apache/xml/internal/serializer/Encodings.java +++ b/jaxp/src/com/sun/org/apache/xml/internal/serializer/Encodings.java @@ -33,6 +33,14 @@ import java.util.Enumeration; import java.util.HashMap; import java.util.Properties; import java.util.StringTokenizer; +import java.io.IOException; +import java.net.MalformedURLException; +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; import com.sun.org.apache.xalan.internal.utils.SecuritySupport; @@ -79,36 +87,17 @@ public final class Encodings extends Object throws UnsupportedEncodingException { - for (int i = 0; i < _encodings.length; ++i) - { - if (_encodings[i].name.equalsIgnoreCase(encoding)) - { - try - { - return new BufferedWriter(new OutputStreamWriter( - output, - _encodings[i].javaName)); - } - catch (java.lang.IllegalArgumentException iae) // java 1.1.8 - { - // keep trying - } - catch (UnsupportedEncodingException usee) - { - - // keep trying - } + final EncodingInfo ei = _encodingInfos.findEncoding(toUpperCaseFast(encoding)); + if (ei != null) { + try { + return new BufferedWriter(new OutputStreamWriter( + output, ei.javaName)); + } catch (UnsupportedEncodingException usee) { + // keep trying } } - try - { - return new BufferedWriter(new OutputStreamWriter(output, encoding)); - } - catch (java.lang.IllegalArgumentException iae) // java 1.1.8 - { - throw new UnsupportedEncodingException(encoding); - } + return new BufferedWriter(new OutputStreamWriter(output, encoding)); } @@ -141,12 +130,24 @@ public final class Encodings extends Object EncodingInfo ei; String normalizedEncoding = toUpperCaseFast(encoding); - ei = (EncodingInfo) _encodingTableKeyJava.get(normalizedEncoding); - if (ei == null) - ei = (EncodingInfo) _encodingTableKeyMime.get(normalizedEncoding); + ei = _encodingInfos.findEncoding(normalizedEncoding); if (ei == null) { // We shouldn't have to do this, but just in case. - ei = new EncodingInfo(null,null); + try { + // This may happen if the caller tries to use + // an encoding that wasn't registered in the + // (java name)->(preferred mime name) mapping file. + // In that case we attempt to load the charset for the + // given encoding, and if that succeeds - we create a new + // EncodingInfo instance - assuming the canonical name + // of the charset can be used as the mime name. + final Charset c = Charset.forName(encoding); + final String name = c.name(); + ei = new EncodingInfo(name, name); + _encodingInfos.putEncoding(normalizedEncoding, ei); + } catch (IllegalCharsetNameException | UnsupportedCharsetException x) { + ei = new EncodingInfo(null,null); + } } return ei; @@ -269,8 +270,8 @@ public final class Encodings extends Object */ private static String convertJava2MimeEncoding(String encoding) { - EncodingInfo enc = - (EncodingInfo) _encodingTableKeyJava.get(encoding.toUpperCase()); + final EncodingInfo enc = + _encodingInfos.getEncodingFromJavaKey(toUpperCaseFast(encoding)); if (null != enc) return enc.name; return encoding; @@ -285,38 +286,37 @@ public final class Encodings extends Object */ public static String convertMime2JavaEncoding(String encoding) { - - for (int i = 0; i < _encodings.length; ++i) - { - if (_encodings[i].name.equalsIgnoreCase(encoding)) - { - return _encodings[i].javaName; - } - } - - return encoding; + final EncodingInfo info = _encodingInfos.findEncoding(toUpperCaseFast(encoding)); + return info != null ? info.javaName : encoding; } - /** - * Load a list of all the supported encodings. - * - * System property "encodings" formatted using URL syntax may define an - * external encodings list. Thanks to Sergey Ushakov for the code - * contribution! - */ - private static EncodingInfo[] loadEncodingInfo() - { - try - { + // Using an inner static class here prevent initialization races + // where the hash maps could be used before they were populated. + // + private final static class EncodingInfos { + // These maps are final and not modified after initialization. + private final Map _encodingTableKeyJava = new HashMap<>(); + private final Map _encodingTableKeyMime = new HashMap<>(); + // This map will be added to after initialization: make sure it's + // thread-safe. This map should not be used frequently - only in cases + // where the mapping requested was not declared in the Encodings.properties + // file. + private final Map _encodingDynamicTable = + Collections.synchronizedMap(new HashMap()); + + private EncodingInfos() { + loadEncodingInfo(); + } + + // Opens the file/resource containing java charset name -> preferred mime + // name mapping and returns it as an InputStream. + private InputStream openEncodingsFileStream() throws MalformedURLException, IOException { String urlString = null; InputStream is = null; - try - { + try { urlString = SecuritySupport.getSystemProperty(ENCODINGS_PROP, ""); - } - catch (SecurityException e) - { + } catch (SecurityException e) { } if (urlString != null && urlString.length() > 0) { @@ -327,84 +327,188 @@ public final class Encodings extends Object if (is == null) { is = SecuritySupport.getResourceAsStream(ENCODINGS_FILE); } + return is; + } + // Loads the Properties resource containing the mapping: + // java charset name -> preferred mime name + // and returns it. + private Properties loadProperties() throws MalformedURLException, IOException { Properties props = new Properties(); - if (is != null) { - props.load(is); - is.close(); - } else { - // Seems to be no real need to force failure here, let the - // system do its best... The issue is not really very critical, - // and the output will be in any case _correct_ though maybe not - // always human-friendly... :) - // But maybe report/log the resource problem? - // Any standard ways to report/log errors (in static context)? - } - - int totalEntries = props.size(); - int totalMimeNames = 0; - Enumeration keys = props.keys(); - for (int i = 0; i < totalEntries; ++i) - { - String javaName = (String) keys.nextElement(); - String val = props.getProperty(javaName); - totalMimeNames++; - int pos = val.indexOf(' '); - for (int j = 0; j < pos; ++j) - if (val.charAt(j) == ',') - totalMimeNames++; - } - EncodingInfo[] ret = new EncodingInfo[totalMimeNames]; - int j = 0; - keys = props.keys(); - for (int i = 0; i < totalEntries; ++i) - { - String javaName = (String) keys.nextElement(); - String val = props.getProperty(javaName); - int pos = val.indexOf(' '); - String mimeName; - //int lastPrintable; - if (pos < 0) - { - // Maybe report/log this problem? - // "Last printable character not defined for encoding " + - // mimeName + " (" + val + ")" ... - mimeName = val; - //lastPrintable = 0x00FF; + try (InputStream is = openEncodingsFileStream()) { + if (is != null) { + props.load(is); + } else { + // Seems to be no real need to force failure here, let the + // system do its best... The issue is not really very critical, + // and the output will be in any case _correct_ though maybe not + // always human-friendly... :) + // But maybe report/log the resource problem? + // Any standard ways to report/log errors (in static context)? } - else - { - //lastPrintable = - // Integer.decode(val.substring(pos).trim()).intValue(); - StringTokenizer st = - new StringTokenizer(val.substring(0, pos), ","); - for (boolean first = true; - st.hasMoreTokens(); - first = false) - { - mimeName = st.nextToken(); - ret[j] = - new EncodingInfo(mimeName, javaName); - _encodingTableKeyMime.put( - mimeName.toUpperCase(), - ret[j]); - if (first) - _encodingTableKeyJava.put( - javaName.toUpperCase(), - ret[j]); - j++; + } + return props; + } + + // Parses the mime list associated to a java charset name. + // The first mime name in the list is supposed to be the preferred + // mime name. + private String[] parseMimeTypes(String val) { + int pos = val.indexOf(' '); + //int lastPrintable; + if (pos < 0) { + // Maybe report/log this problem? + // "Last printable character not defined for encoding " + + // mimeName + " (" + val + ")" ... + return new String[] { val }; + //lastPrintable = 0x00FF; + } + //lastPrintable = + // Integer.decode(val.substring(pos).trim()).intValue(); + StringTokenizer st = + new StringTokenizer(val.substring(0, pos), ","); + String[] values = new String[st.countTokens()]; + for (int i=0; st.hasMoreTokens(); i++) { + values[i] = st.nextToken(); + } + return values; + } + + // This method here attempts to find the canonical charset name for the + // the given name - which is supposed to be either a java name or a mime + // name. + // For that, it attempts to load the charset using the given name, and + // then returns the charset's canonical name. + // If the charset could not be loaded from the given name, + // the method returns null. + private String findCharsetNameFor(String name) { + try { + return Charset.forName(name).name(); + } catch (Exception x) { + return null; + } + } + + // This method here attempts to find the canonical charset name for the + // the set javaName+mimeNames - which are supposed to all refer to the + // same charset. + // For that it attempts to load the charset using the javaName, and if + // not found, attempts again using each of the mime names in turn. + // If the charset could be loaded from the javaName, then the javaName + // itself is returned as charset name. Otherwise, each of the mime names + // is tried in turn, until a charset can be loaded from one of the names, + // and the loaded charset's canonical name is returned. + // If no charset can be loaded from either the javaName or one of the + // mime names, then null is returned. + // + // Note that the returned name is the 'java' name that will be used in + // instances of EncodingInfo. + // This is important because EncodingInfo uses that 'java name' later on + // in calls to String.getBytes(javaName). + // As it happens, sometimes only one element of the set mime names/javaName + // is known by Charset: sometimes only one of the mime names is known, + // sometime only the javaName is known, sometimes all are known. + // + // By using this method here, we fix the problem where one of the mime + // names is known but the javaName is unknown, by associating the charset + // loaded from one of the mime names with the unrecognized javaName. + // + // When none of the mime names or javaName are known - there's not much we can + // do... It can mean that this encoding is not supported for this + // OS. If such a charset is ever use it will result in having all characters + // escaped. + // + private String findCharsetNameFor(String javaName, String[] mimes) { + String cs = findCharsetNameFor(javaName); + if (cs != null) return javaName; + for (String m : mimes) { + cs = findCharsetNameFor(m); + if (cs != null) break; + } + return cs; + } + + /** + * Loads a list of all the supported encodings. + * + * System property "encodings" formatted using URL syntax may define an + * external encodings list. Thanks to Sergey Ushakov for the code + * contribution! + */ + private void loadEncodingInfo() { + try { + // load (java name)->(preferred mime name) mapping. + final Properties props = loadProperties(); + + // create instances of EncodingInfo from the loaded mapping + Enumeration keys = props.keys(); + Map canonicals = new HashMap<>(); + while (keys.hasMoreElements()) { + final String javaName = (String) keys.nextElement(); + final String[] mimes = parseMimeTypes(props.getProperty(javaName)); + + final String charsetName = findCharsetNameFor(javaName, mimes); + if (charsetName != null) { + final String kj = toUpperCaseFast(javaName); + final String kc = toUpperCaseFast(charsetName); + for (int i = 0; i < mimes.length; ++i) { + final String mimeName = mimes[i]; + final String km = toUpperCaseFast(mimeName); + EncodingInfo info = new EncodingInfo(mimeName, charsetName); + _encodingTableKeyMime.put(km, info); + if (!canonicals.containsKey(kc)) { + // canonicals will map the charset name to + // the info containing the prefered mime name + // (the preferred mime name is the first mime + // name in the list). + canonicals.put(kc, info); + _encodingTableKeyJava.put(kc, info); + } + _encodingTableKeyJava.put(kj, info); + } + } else { + // None of the java or mime names on the line were + // recognized => this charset is not supported? } } + + // Fix up the _encodingTableKeyJava so that the info mapped to + // the java name contains the preferred mime name. + // (a given java name can correspond to several mime name, + // but we want the _encodingTableKeyJava to point to the + // preferred mime name). + for (Entry e : _encodingTableKeyJava.entrySet()) { + e.setValue(canonicals.get(toUpperCaseFast(e.getValue().javaName))); + } + + } catch (java.net.MalformedURLException mue) { + throw new com.sun.org.apache.xml.internal.serializer.utils.WrappedRuntimeException(mue); + } catch (java.io.IOException ioe) { + throw new com.sun.org.apache.xml.internal.serializer.utils.WrappedRuntimeException(ioe); } - return ret; } - catch (java.net.MalformedURLException mue) - { - throw new com.sun.org.apache.xml.internal.serializer.utils.WrappedRuntimeException(mue); + + EncodingInfo findEncoding(String normalizedEncoding) { + EncodingInfo info = _encodingTableKeyJava.get(normalizedEncoding); + if (info == null) { + info = _encodingTableKeyMime.get(normalizedEncoding); + } + if (info == null) { + info = _encodingDynamicTable.get(normalizedEncoding); + } + return info; } - catch (java.io.IOException ioe) - { - throw new com.sun.org.apache.xml.internal.serializer.utils.WrappedRuntimeException(ioe); + + EncodingInfo getEncodingFromMimeKey(String normalizedMimeName) { + return _encodingTableKeyMime.get(normalizedMimeName); + } + + EncodingInfo getEncodingFromJavaKey(String normalizedJavaName) { + return _encodingTableKeyJava.get(normalizedJavaName); + } + + void putEncoding(String key, EncodingInfo info) { + _encodingDynamicTable.put(key, info); } } @@ -457,7 +561,6 @@ public final class Encodings extends Object return codePoint; } - private static final HashMap _encodingTableKeyJava = new HashMap(); - private static final HashMap _encodingTableKeyMime = new HashMap(); - private static final EncodingInfo[] _encodings = loadEncodingInfo(); + private final static EncodingInfos _encodingInfos = new EncodingInfos(); + } diff --git a/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/URI.java b/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/URI.java index 8af2fd8a1b4..4d5375a59c8 100644 --- a/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/URI.java +++ b/jaxp/src/com/sun/org/apache/xml/internal/serializer/utils/URI.java @@ -23,7 +23,7 @@ package com.sun.org.apache.xml.internal.serializer.utils; import java.io.IOException; -import java.io.Serializable; +import java.util.Objects; /** @@ -863,7 +863,7 @@ final class URI public String getSchemeSpecificPart() { - StringBuffer schemespec = new StringBuffer(); + final StringBuilder schemespec = new StringBuilder(); if (m_userinfo != null || m_host != null || m_port != -1) { @@ -955,7 +955,7 @@ final class URI boolean p_includeFragment) { - StringBuffer pathString = new StringBuffer(m_path); + final StringBuilder pathString = new StringBuilder(m_path); if (p_includeQueryString && m_queryString != null) { @@ -1321,6 +1321,7 @@ final class URI * @return true if p_test is a URI with all values equal to this * URI, false otherwise */ + @Override public boolean equals(Object p_test) { @@ -1343,15 +1344,29 @@ final class URI return false; } + @Override + public int hashCode() { + int hash = 5; + hash = 41 * hash + Objects.hashCode(this.m_scheme); + hash = 41 * hash + Objects.hashCode(this.m_userinfo); + hash = 41 * hash + Objects.hashCode(this.m_host); + hash = 41 * hash + this.m_port; + hash = 41 * hash + Objects.hashCode(this.m_path); + hash = 41 * hash + Objects.hashCode(this.m_queryString); + hash = 41 * hash + Objects.hashCode(this.m_fragment); + return hash; + } + /** * Get the URI as a string specification. See RFC 2396 Section 5.2. * * @return the URI string specification */ + @Override public String toString() { - StringBuffer uriSpecString = new StringBuffer(); + final StringBuilder uriSpecString = new StringBuilder(); if (m_scheme != null) { @@ -1543,7 +1558,7 @@ final class URI * * * @param p_char the character to check - * @return true if the char is betweeen '0' and '9', 'a' and 'f' + * @return true if the char is between '0' and '9', 'a' and 'f' * or 'A' and 'F', false otherwise */ private static boolean isHex(char p_char) diff --git a/jaxp/src/com/sun/org/apache/xml/internal/utils/URI.java b/jaxp/src/com/sun/org/apache/xml/internal/utils/URI.java index b2606a7134e..f9e67ab663c 100644 --- a/jaxp/src/com/sun/org/apache/xml/internal/utils/URI.java +++ b/jaxp/src/com/sun/org/apache/xml/internal/utils/URI.java @@ -27,6 +27,7 @@ import java.io.Serializable; import com.sun.org.apache.xml.internal.res.XMLErrorResources; import com.sun.org.apache.xml.internal.res.XMLMessages; +import java.util.Objects; /** * A class to represent a Uniform Resource Identifier (URI). This class @@ -883,7 +884,7 @@ public class URI implements Serializable public String getSchemeSpecificPart() { - StringBuffer schemespec = new StringBuffer(); + final StringBuilder schemespec = new StringBuilder(); if (m_userinfo != null || m_host != null || m_port != -1) { @@ -975,7 +976,7 @@ public class URI implements Serializable boolean p_includeFragment) { - StringBuffer pathString = new StringBuffer(m_path); + final StringBuilder pathString = new StringBuilder(m_path); if (p_includeQueryString && m_queryString != null) { @@ -1341,6 +1342,7 @@ public class URI implements Serializable * @return true if p_test is a URI with all values equal to this * URI, false otherwise */ + @Override public boolean equals(Object p_test) { @@ -1363,15 +1365,29 @@ public class URI implements Serializable return false; } + @Override + public int hashCode() { + int hash = 7; + hash = 59 * hash + Objects.hashCode(this.m_scheme); + hash = 59 * hash + Objects.hashCode(this.m_userinfo); + hash = 59 * hash + Objects.hashCode(this.m_host); + hash = 59 * hash + this.m_port; + hash = 59 * hash + Objects.hashCode(this.m_path); + hash = 59 * hash + Objects.hashCode(this.m_queryString); + hash = 59 * hash + Objects.hashCode(this.m_fragment); + return hash; + } + /** * Get the URI as a string specification. See RFC 2396 Section 5.2. * * @return the URI string specification */ + @Override public String toString() { - StringBuffer uriSpecString = new StringBuffer(); + final StringBuilder uriSpecString = new StringBuilder(); if (m_scheme != null) { diff --git a/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java b/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java index 20ed918f909..8f79f869cb2 100644 --- a/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java +++ b/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java @@ -22,17 +22,17 @@ */ package com.sun.org.apache.xml.internal.utils; -import com.sun.org.apache.xalan.internal.utils.SecuritySupport; +import com.sun.org.apache.xalan.internal.XalanConstants; import com.sun.org.apache.xalan.internal.utils.FactoryImpl; +import com.sun.org.apache.xalan.internal.utils.SecuritySupport; import java.util.HashMap; - +import javax.xml.XMLConstants; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; - +import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderFactory; -import org.xml.sax.SAXException; /** * Creates XMLReader objects and caches them for re-use. @@ -63,6 +63,11 @@ public class XMLReaderManager { private HashMap m_inUse; private boolean m_useServicesMechanism = true; + /** + * protocols allowed for external DTD references in source file and/or stylesheet. + */ + private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT; + /** * Hidden constructor */ @@ -131,6 +136,7 @@ public class XMLReaderManager { try { reader.setFeature(NAMESPACES_FEATURE, true); reader.setFeature(NAMESPACE_PREFIXES_FEATURE, false); + reader.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD); } catch (SAXException se) { // Try to carry on if we've got a parser that // doesn't know about namespace prefixes. @@ -181,4 +187,22 @@ public class XMLReaderManager { m_useServicesMechanism = flag; } + /** + * Get property value + */ + public String getProperty(String name) { + if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { + return _accessExternalDTD; + } + return null; + } + + /** + * Set property. + */ + public void setProperty(String name, String value) { + if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { + _accessExternalDTD = (String)value; + } + } } diff --git a/jaxp/src/com/sun/org/apache/xpath/internal/Arg.java b/jaxp/src/com/sun/org/apache/xpath/internal/Arg.java index bc3d13a3d58..311d07efca2 100644 --- a/jaxp/src/com/sun/org/apache/xpath/internal/Arg.java +++ b/jaxp/src/com/sun/org/apache/xpath/internal/Arg.java @@ -24,6 +24,7 @@ package com.sun.org.apache.xpath.internal; import com.sun.org.apache.xml.internal.utils.QName; import com.sun.org.apache.xpath.internal.objects.XObject; +import java.util.Objects; /** * This class holds an instance of an argument on @@ -182,7 +183,7 @@ public class Arg { m_qname = new QName(""); - ; // so that string compares can be done. + // so that string compares can be done. m_val = null; m_expression = null; m_isVisible = true; @@ -223,6 +224,11 @@ public class Arg m_expression = null; } + @Override + public int hashCode() { + return Objects.hashCode(this.m_qname); + } + /** * Equality function specialized for the variable name. If the argument * is not a qname, it will deligate to the super class. @@ -231,6 +237,7 @@ public class Arg * @return true if this object is the same as the obj * argument; false otherwise. */ + @Override public boolean equals(Object obj) { if(obj instanceof QName) diff --git a/jaxp/src/com/sun/xml/internal/stream/StaxXMLInputSource.java b/jaxp/src/com/sun/xml/internal/stream/StaxXMLInputSource.java index 351693f1472..106f9f9d227 100644 --- a/jaxp/src/com/sun/xml/internal/stream/StaxXMLInputSource.java +++ b/jaxp/src/com/sun/xml/internal/stream/StaxXMLInputSource.java @@ -43,6 +43,9 @@ public class StaxXMLInputSource { XMLEventReader fEventReader ; XMLInputSource fInputSource ; + //indicate if the source is resolved by a resolver + boolean fHasResolver = false; + /** Creates a new instance of StaxXMLInputSource */ public StaxXMLInputSource(XMLStreamReader streamReader) { fStreamReader = streamReader ; @@ -57,6 +60,12 @@ public class StaxXMLInputSource { fInputSource = inputSource ; } + + public StaxXMLInputSource(XMLInputSource inputSource, boolean hasResolver){ + fInputSource = inputSource ; + fHasResolver = hasResolver; + } + public XMLStreamReader getXMLStreamReader(){ return fStreamReader ; } @@ -72,4 +81,8 @@ public class StaxXMLInputSource { public boolean hasXMLStreamOrXMLEventReader(){ return (fStreamReader == null) && (fEventReader == null) ? false : true ; } + + public boolean hasResolver() { + return fHasResolver; + } } diff --git a/jaxp/src/javax/xml/XMLConstants.java b/jaxp/src/javax/xml/XMLConstants.java index 2e570f1de7b..b923a6cbf02 100644 --- a/jaxp/src/javax/xml/XMLConstants.java +++ b/jaxp/src/javax/xml/XMLConstants.java @@ -73,7 +73,7 @@ public final class XMLConstants { *

The official XML Namespace name URI.

* *

Defined by the XML specification to be - * "http://www.w3.org/XML/1998/namespace".

+ * "{@code http://www.w3.org/XML/1998/namespace}".

* * @see @@ -85,7 +85,7 @@ public final class XMLConstants { /** *

The official XML Namespace prefix.

* - *

Defined by the XML specification to be "xml".

+ *

Defined by the XML specification to be "{@code xml}".

* * @see
@@ -99,7 +99,7 @@ public final class XMLConstants { * XMLConstants.XMLNS_ATTRIBUTE}, Namespace name URI.

* *

Defined by the XML specification to be - * "http://www.w3.org/2000/xmlns/".

+ * "{@code http://www.w3.org/2000/xmlns/}".

* * @see
@@ -117,7 +117,7 @@ public final class XMLConstants { * *

It is NOT valid to use as a * prefix. Defined by the XML specification to be - * "xmlns".

+ * "{@code xmlns}".

* * @see
@@ -128,7 +128,7 @@ public final class XMLConstants { /** *

W3C XML Schema Namespace URI.

* - *

Defined to be "http://www.w3.org/2001/XMLSchema". + *

Defined to be "{@code http://www.w3.org/2001/XMLSchema}". * * @see @@ -141,7 +141,7 @@ public final class XMLConstants { /** *

W3C XML Schema Instance Namespace URI.

* - *

Defined to be "http://www.w3.org/2001/XMLSchema-instance".

+ *

Defined to be "{@code http://www.w3.org/2001/XMLSchema-instance}".

* * @see
@@ -154,7 +154,7 @@ public final class XMLConstants { /** *

W3C XPath Datatype Namespace URI.

* - *

Defined to be "http://www.w3.org/2003/11/xpath-datatypes".

+ *

Defined to be "{@code http://www.w3.org/2003/11/xpath-datatypes}".

* * @see
XQuery 1.0 and XPath 2.0 Data Model */ @@ -163,14 +163,14 @@ public final class XMLConstants { /** *

XML Document Type Declaration Namespace URI as an arbitrary value.

* - *

Since not formally defined by any existing standard, arbitrarily define to be "http://www.w3.org/TR/REC-xml". + *

Since not formally defined by any existing standard, arbitrarily define to be "{@code http://www.w3.org/TR/REC-xml}". */ public static final String XML_DTD_NS_URI = "http://www.w3.org/TR/REC-xml"; /** *

RELAX NG Namespace URI.

* - *

Defined to be "http://relaxng.org/ns/structure/1.0".

+ *

Defined to be "{@code http://relaxng.org/ns/structure/1.0}".

* * @see RELAX NG Specification */ @@ -181,14 +181,212 @@ public final class XMLConstants { * *
    *
  • - * true instructs the implementation to process XML securely. + * {@code true} instructs the implementation to process XML securely. * This may set limits on XML constructs to avoid conditions such as denial of service attacks. *
  • *
  • - * false instructs the implementation to process XML acording the letter of the XML specifications - * ingoring security issues such as limits on XML constructs to avoid conditions such as denial of service attacks. + * {@code false} instructs the implementation to process XML in accordance with the XML specifications + * ignoring security issues such as limits on XML constructs to avoid conditions such as denial of service attacks. *
  • *
*/ public static final String FEATURE_SECURE_PROCESSING = "http://javax.xml.XMLConstants/feature/secure-processing"; + + + /** + *

Property: accessExternalDTD

+ * + *

+ * Restrict access to external DTDs and external Entity References to the protocols specified. + * If access is denied due to the restriction of this property, a runtime exception that + * is specific to the context is thrown. In the case of {@link javax.xml.parsers.SAXParser} + * for example, {@link org.xml.sax.SAXException} is thrown. + *

+ * + *

+ * Value: a list of protocols separated by comma. A protocol is the scheme portion of a + * {@link java.net.URI}, or in the case of the JAR protocol, "jar" plus the scheme portion + * separated by colon. + * A scheme is defined as: + * + *

+ * scheme = alpha *( alpha | digit | "+" | "-" | "." )
+ * where alpha = a-z and A-Z.

+ * + * And the JAR protocol:
+ * + * jar[:scheme]

+ * + * Protocols including the keyword "jar" are case-insensitive. Any whitespaces as defined by + * {@link java.lang.Character#isSpaceChar } in the value will be ignored. + * Examples of protocols are file, http, jar:file. + * + *
+ *

+ * + *

+ * Default value: The default value is implementation specific and therefore not specified. + * The following options are provided for consideration: + *

+ *
    + *
  • an empty string to deny all access to external references;
  • + *
  • a specific protocol, such as file, to give permission to only the protocol;
  • + *
  • the keyword "all" to grant permission to all protocols.
  • + *

+ * When FEATURE_SECURE_PROCESSING is enabled, it is recommended that implementations + * restrict external connections by default, though this may cause problems for applications + * that process XML/XSD/XSL with external references. + *
+ *

+ * + *

+ * Granting all access: the keyword "all" grants permission to all protocols. + *

+ *

+ * System Property: The value of this property can be set or overridden by + * system property {@code javax.xml.accessExternalDTD}. + *

+ * + *

+ * ${JAVA_HOME}/lib/jaxp.properties: This configuration file is in standard + * {@link java.util.Properties} format. If the file exists and the system property is specified, + * its value will be used to override the default of the property. + *

+ * + *

+ * + *

+ * @since 1.7 + */ + public static final String ACCESS_EXTERNAL_DTD = "http://javax.xml.XMLConstants/property/accessExternalDTD"; + + /** + *

Property: accessExternalSchema

+ * + *

+ * Restrict access to the protocols specified for external reference set by the + * schemaLocation attribute, Import and Include element. If access is denied + * due to the restriction of this property, a runtime exception that is specific + * to the context is thrown. In the case of {@link javax.xml.validation.SchemaFactory} + * for example, org.xml.sax.SAXException is thrown. + *

+ *

+ * Value: a list of protocols separated by comma. A protocol is the scheme portion of a + * {@link java.net.URI}, or in the case of the JAR protocol, "jar" plus the scheme portion + * separated by colon. + * A scheme is defined as: + * + *

+ * scheme = alpha *( alpha | digit | "+" | "-" | "." )
+ * where alpha = a-z and A-Z.

+ * + * And the JAR protocol:
+ * + * jar[:scheme]

+ * + * Protocols including the keyword "jar" are case-insensitive. Any whitespaces as defined by + * {@link java.lang.Character#isSpaceChar } in the value will be ignored. + * Examples of protocols are file, http, jar:file. + * + *
+ *

+ * + *

+ * Default value: The default value is implementation specific and therefore not specified. + * The following options are provided for consideration: + *

+ *
    + *
  • an empty string to deny all access to external references;
  • + *
  • a specific protocol, such as file, to give permission to only the protocol;
  • + *
  • the keyword "all" to grant permission to all protocols.
  • + *

+ * When FEATURE_SECURE_PROCESSING is enabled, it is recommended that implementations + * restrict external connections by default, though this may cause problems for applications + * that process XML/XSD/XSL with external references. + *
+ *

+ *

+ * Granting all access: the keyword "all" grants permission to all protocols. + *

+ * + *

+ * System Property: The value of this property can be set or overridden by + * system property {@code javax.xml.accessExternalSchema} + *

+ * + *

+ * ${JAVA_HOME}/lib/jaxp.properties: This configuration file is in standard + * java.util.Properties format. If the file exists and the system property is specified, + * its value will be used to override the default of the property. + * + * @since 1.7 + *

+ */ + public static final String ACCESS_EXTERNAL_SCHEMA = "http://javax.xml.XMLConstants/property/accessExternalSchema"; + + /** + *

Property: accessExternalStylesheet

+ * + *

+ * Restrict access to the protocols specified for external references set by the + * stylesheet processing instruction, Import and Include element, and document function. + * If access is denied due to the restriction of this property, a runtime exception + * that is specific to the context is thrown. In the case of constructing new + * {@link javax.xml.transform.Transformer} for example, + * {@link javax.xml.transform.TransformerConfigurationException} + * will be thrown by the {@link javax.xml.transform.TransformerFactory}. + *

+ *

+ * Value: a list of protocols separated by comma. A protocol is the scheme portion of a + * {@link java.net.URI}, or in the case of the JAR protocol, "jar" plus the scheme portion + * separated by colon. + * A scheme is defined as: + * + *

+ * scheme = alpha *( alpha | digit | "+" | "-" | "." )
+ * where alpha = a-z and A-Z.

+ * + * And the JAR protocol:
+ * + * jar[:scheme]

+ * + * Protocols including the keyword "jar" are case-insensitive. Any whitespaces as defined by + * {@link java.lang.Character#isSpaceChar } in the value will be ignored. + * Examples of protocols are file, http, jar:file. + * + *
+ *

+ * + *

+ * Default value: The default value is implementation specific and therefore not specified. + * The following options are provided for consideration: + *

+ *
    + *
  • an empty string to deny all access to external references;
  • + *
  • a specific protocol, such as file, to give permission to only the protocol;
  • + *
  • the keyword "all" to grant permission to all protocols.
  • + *

+ * When FEATURE_SECURE_PROCESSING is enabled, it is recommended that implementations + * restrict external connections by default, though this may cause problems for applications + * that process XML/XSD/XSL with external references. + *
+ *

+ *

+ * Granting all access: the keyword "all" grants permission to all protocols. + *

+ * + *

+ * System Property: The value of this property can be set or overridden by + * system property {@code javax.xml.accessExternalStylesheet} + *

+ * + *

+ * ${JAVA_HOME}/lib/jaxp.properties: This configuration file is in standard + * java.util.Properties format. If the file exists and the system property is specified, + * its value will be used to override the default of the property. + * + * @since 1.7 + */ + public static final String ACCESS_EXTERNAL_STYLESHEET = "http://javax.xml.XMLConstants/property/accessExternalStylesheet"; + } diff --git a/jaxp/src/javax/xml/parsers/DocumentBuilderFactory.java b/jaxp/src/javax/xml/parsers/DocumentBuilderFactory.java index 0ef1c13cecb..748a1636f0a 100644 --- a/jaxp/src/javax/xml/parsers/DocumentBuilderFactory.java +++ b/jaxp/src/javax/xml/parsers/DocumentBuilderFactory.java @@ -351,6 +351,31 @@ public abstract class DocumentBuilderFactory { /** * Allows the user to set specific attributes on the underlying * implementation. + *

+ * All implementations that implement JAXP 1.5 or newer are required to + * support the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} and + * {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} properties. + *

+ *
    + *
  • + *

    + * Setting the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} property + * restricts the access to external DTDs, external Entity References to the + * protocols specified by the property. + * If access is denied during parsing due to the restriction of this property, + * {@link org.xml.sax.SAXException} will be thrown by the parse methods defined by + * {@link javax.xml.parsers.DocumentBuilder}. + *

    + *

    + * Setting the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} property + * restricts the access to external Schema set by the schemaLocation attribute to + * the protocols specified by the property. If access is denied during parsing + * due to the restriction of this property, {@link org.xml.sax.SAXException} + * will be thrown by the parse methods defined by + * {@link javax.xml.parsers.DocumentBuilder}. + *

    + *
  • + *
* * @param name The name of the attribute. * @param value The value of the attribute. diff --git a/jaxp/src/javax/xml/parsers/SAXParser.java b/jaxp/src/javax/xml/parsers/SAXParser.java index ef7b2e942c3..5461413eb41 100644 --- a/jaxp/src/javax/xml/parsers/SAXParser.java +++ b/jaxp/src/javax/xml/parsers/SAXParser.java @@ -441,6 +441,29 @@ public abstract class SAXParser { * A list of the core features and properties can be found at * * http://sax.sourceforge.net/?selected=get-set.

+ *

+ * All implementations that implement JAXP 1.5 or newer are required to + * support the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} and + * {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} properties. + *

+ *
    + *
  • + *

    + * Setting the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} property + * restricts the access to external DTDs, external Entity References to + * the protocols specified by the property. If access is denied during parsing + * due to the restriction of this property, {@link org.xml.sax.SAXException} + * will be thrown by the parse methods defined by {@link javax.xml.parsers.SAXParser}. + *

    + *

    + * Setting the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} property + * restricts the access to external Schema set by the schemaLocation attribute to + * the protocols specified by the property. If access is denied during parsing + * due to the restriction of this property, {@link org.xml.sax.SAXException} + * will be thrown by the parse methods defined by the {@link javax.xml.parsers.SAXParser}. + *

    + *
  • + *
* * @param name The name of the property to be set. * @param value The value of the property to be set. diff --git a/jaxp/src/javax/xml/stream/XMLInputFactory.java b/jaxp/src/javax/xml/stream/XMLInputFactory.java index 2bfbad5d461..d894893eb6d 100644 --- a/jaxp/src/javax/xml/stream/XMLInputFactory.java +++ b/jaxp/src/javax/xml/stream/XMLInputFactory.java @@ -433,9 +433,26 @@ public abstract class XMLInputFactory { public abstract void setXMLReporter(XMLReporter reporter); /** - * Allows the user to set specific feature/property on the underlying implementation. The underlying implementation - * is not required to support every setting of every property in the specification and may use IllegalArgumentException - * to signal that an unsupported property may not be set with the specified value. + * Allows the user to set specific feature/property on the underlying + * implementation. The underlying implementation is not required to support + * every setting of every property in the specification and may use + * IllegalArgumentException to signal that an unsupported property may not be + * set with the specified value. + *

+ * All implementations that implement JAXP 1.5 or newer are required to + * support the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} property. + *

+ *
    + *
  • + *

    + * Access to external DTDs, external Entity References is restricted to the + * protocols specified by the property. If access is denied during parsing + * due to the restriction of this property, {@link javax.xml.stream.XMLStreamException} + * will be thrown by the {@link javax.xml.stream.XMLStreamReader#next()} or + * {@link javax.xml.stream.XMLEventReader#nextEvent()} method. + *

    + *
  • + *
* @param name The name of the property (may not be null) * @param value The value of the property * @throws java.lang.IllegalArgumentException if the property is not supported diff --git a/jaxp/src/javax/xml/transform/TransformerFactory.java b/jaxp/src/javax/xml/transform/TransformerFactory.java index 61528855be6..9c4a076549d 100644 --- a/jaxp/src/javax/xml/transform/TransformerFactory.java +++ b/jaxp/src/javax/xml/transform/TransformerFactory.java @@ -325,6 +325,46 @@ public abstract class TransformerFactory { * be an option that the implementation provides. * An IllegalArgumentException is thrown if the underlying * implementation doesn't recognize the attribute. + *

+ * All implementations that implement JAXP 1.5 or newer are required to + * support the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} and + * {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_STYLESHEET} properties. + *

+ *
    + *
  • + *

    + * Access to external DTDs in the source file is restricted to the protocols + * specified by the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} property. + * If access is denied during transformation due to the restriction of this property, + * {@link javax.xml.transform.TransformerException} will be thrown by + * {@link javax.xml.transform.Transformer#transform(Source, Result)}. + *

    + *

    + * Access to external DTDs in the stylesheet is restricted to the protocols + * specified by the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} property. + * If access is denied during the creation of a new transformer due to the + * restriction of this property, + * {@link javax.xml.transform.TransformerConfigurationException} will be thrown + * by the {@link #newTransformer(Source)} method. + *

    + *

    + * Access to external reference set by the stylesheet processing instruction, + * Import and Include element is restricted to the protocols specified by the + * {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_STYLESHEET} property. + * If access is denied during the creation of a new transformer due to the + * restriction of this property, + * {@link javax.xml.transform.TransformerConfigurationException} will be thrown + * by the {@link #newTransformer(Source)} method. + *

    + *

    + * Access to external document through XSLT document function is restricted + * to the protocols specified by the property. If access is denied during + * the transformation due to the restriction of this property, + * {@link javax.xml.transform.TransformerException} will be thrown by the + * {@link javax.xml.transform.Transformer#transform(Source, Result)} method. + *

    + *
  • + *
* * @param name The name of the attribute. * @param value The value of the attribute. diff --git a/jaxp/src/javax/xml/validation/SchemaFactory.java b/jaxp/src/javax/xml/validation/SchemaFactory.java index 6f156af0ff5..d99f45011f7 100644 --- a/jaxp/src/javax/xml/validation/SchemaFactory.java +++ b/jaxp/src/javax/xml/validation/SchemaFactory.java @@ -390,8 +390,44 @@ public abstract class SchemaFactory { * possible for a {@link SchemaFactory} to recognize a property name but * to be unable to change the current value.

* - *

{@link SchemaFactory}s are not required to recognize setting - * any specific property names.

+ *

+ * All implementations that implement JAXP 1.5 or newer are required to + * support the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} and + * {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} properties. + *

+ *
    + *
  • + *

    Access to external DTDs in Schema files is restricted to the protocols + * specified by the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} property. + * If access is denied during the creation of new Schema due to the restriction + * of this property, {@link org.xml.sax.SAXException} will be thrown by the + * {@link #newSchema(Source)} or {@link #newSchema(File)} + * or {@link #newSchema(URL)} or or {@link #newSchema(Source[])} method.

    + * + *

    Access to external DTDs in xml source files is restricted to the protocols + * specified by the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} property. + * If access is denied during validation due to the restriction + * of this property, {@link org.xml.sax.SAXException} will be thrown by the + * {@link javax.xml.validation.Validator#validate(Source)} or + * {@link javax.xml.validation.Validator#validate(Source, Result)} method.

    + * + *

    Access to external reference set by the schemaLocation attribute is + * restricted to the protocols specified by the + * {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} property. + * If access is denied during validation due to the restriction of this property, + * {@link org.xml.sax.SAXException} will be thrown by the + * {@link javax.xml.validation.Validator#validate(Source)} or + * {@link javax.xml.validation.Validator#validate(Source, Result)} method.

    + * + *

    Access to external reference set by the Import + * and Include element is restricted to the protocols specified by the + * {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} property. + * If access is denied during the creation of new Schema due to the restriction + * of this property, {@link org.xml.sax.SAXException} will be thrown by the + * {@link #newSchema(Source)} or {@link #newSchema(File)} + * or {@link #newSchema(URL)} or {@link #newSchema(Source[])} method.

    + *
  • + *
* * @param name The property name, which is a non-null fully-qualified URI. * @param object The requested value for the property. diff --git a/jaxp/src/javax/xml/validation/Validator.java b/jaxp/src/javax/xml/validation/Validator.java index ee66a6d1f45..fad7c5ac4f0 100644 --- a/jaxp/src/javax/xml/validation/Validator.java +++ b/jaxp/src/javax/xml/validation/Validator.java @@ -440,8 +440,27 @@ public abstract class Validator { * in specific contexts, such as before, during, or after * a validation.

* - *

{@link Validator}s are not required to recognize setting - * any specific property names.

+ *

+ * All implementations that implement JAXP 1.5 or newer are required to + * support the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} and + * {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} properties. + *

+ *
    + *
  • + *

    Access to external DTDs in source or Schema file is restricted to + * the protocols specified by the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} + * property. If access is denied during validation due to the restriction + * of this property, {@link org.xml.sax.SAXException} will be thrown by the + * {@link #validate(Source)} method.

    + * + *

    Access to external reference set by the schemaLocation attribute is + * restricted to the protocols specified by the + * {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} property. + * If access is denied during validation due to the restriction of this property, + * {@link org.xml.sax.SAXException} will be thrown by the + * {@link #validate(Source)} method.

    + *
  • + *
* * @param name The property name, which is a non-null fully-qualified URI. * @param object The requested value for the property. diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 6ba47546a48..b60c92ca352 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -211,3 +211,4 @@ a5e7c2f093c9996ab3419db1565094a07b059e9c jdk8-b86 72e03566f0a61282cc48ebc869803b256cccd66c jdk8-b87 24fa5452e5d4e9df8b85196283275a6ca4b4adb4 jdk8-b88 88838e08e4ef6a254867c8126070a1975683108d jdk8-b89 +3e5b9ea5ac35ea7096da484e24a863cf4552179f jdk8-b90 diff --git a/jdk/.hgtags b/jdk/.hgtags index 303bb6739f7..7be0eb3751c 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -211,3 +211,4 @@ ac519af51769e92c51b597a730974e8607357709 jdk8-b83 d5228e624826a10ccc5b05f30ad8d839b58fe48d jdk8-b87 8dbb4b159e04de3c447c9242c70505e71f8624c7 jdk8-b88 845025546e35519fbb8970e79fc2a834063a5e19 jdk8-b89 +c63eda8f63008a4398d2c22ac8d72f7fef6f9238 jdk8-b90 diff --git a/jdk/make/com/sun/Makefile b/jdk/make/com/sun/Makefile index 052cd541032..e33b27f8c18 100644 --- a/jdk/make/com/sun/Makefile +++ b/jdk/make/com/sun/Makefile @@ -31,13 +31,6 @@ BUILDDIR = ../.. PRODUCT = sun include $(BUILDDIR)/common/Defs.gmk -ifndef OPENJDK - ORG_EXISTS := $(call DirExists,$(CLOSED_SRC)/share/classes/sun/org,,) - ifneq ("$(ORG_EXISTS)", "") - SCRIPT_SUBDIR = script - endif -endif - # jarsigner is part of JRE SUBDIRS = java security net/ssl jarsigner diff --git a/jdk/make/com/sun/script/Makefile b/jdk/make/com/sun/script/Makefile deleted file mode 100644 index 58e134fad53..00000000000 --- a/jdk/make/com/sun/script/Makefile +++ /dev/null @@ -1,62 +0,0 @@ -# -# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - - -BUILDDIR = ../../.. -PACKAGE = com.sun.script -PRODUCT = sun -include $(BUILDDIR)/common/Defs.gmk - -AUTO_FILES_JAVA_DIRS = com/sun/script - -# -# Files that need to be copied -# -SERVICEDIR = $(CLASSBINDIR)/META-INF/services - -FILES_copy = \ - $(SERVICEDIR)/javax.script.ScriptEngineFactory - -include $(BUILDDIR)/common/Classes.gmk - -all: classes copy-files - -# -# Copy the service provider configuration file into the resource -# directory. -# - -copy-files: $(FILES_copy) - -$(SERVICEDIR)/%: $(SHARE_SRC)/classes/com/sun/script/javascript/META-INF/services/% - $(install-file) - -.PHONY: copy-files - - -clean:: - $(RM) -r $(CLASSDESTDIR)/com/sun/script/javascript - $(RM) $(FILES_copy) - diff --git a/jdk/make/common/Release.gmk b/jdk/make/common/Release.gmk index 2cdfc0ef6ba..ce2dda53d1d 100644 --- a/jdk/make/common/Release.gmk +++ b/jdk/make/common/Release.gmk @@ -969,26 +969,35 @@ else # Create the list of db *.zip files to bundle with jdk ABS_DB_PATH :=$(call FullPath,$(CLOSED_SHARE_SRC)/db) -DB_ZIP_LIST = $(shell $(LS) $(ABS_DB_PATH)/*.zip 2>/dev/null) +DB_BINARY_BUNDLE = $(shell $(LS) $(ABS_DB_PATH)/db-derby-*-bin.zip 2>/dev/null) # Java DB image. Move the Java DB demo directory into the JDK's demo # dir and in the process, rename it to db. Also remove index.html, -# since it presumes docs are co-located. Also remove register.html (no -# longer relevant). -initial-image-jdk-db: $(DB_ZIP_LIST) +# since it presumes docs are co-located, javadoc, docs and tests and +# update the copyright year of the JDK READMEs to that of the release. +initial-image-jdk-db: $(DB_BINARY_BUNDLE) $(MKDIR) -p $(JDK_IMAGE_DIR)/db - for d in $(DB_ZIP_LIST); do \ - ($(CD) $(JDK_IMAGE_DIR)/db && $(UNZIP) -o $$d); \ - done - $(CP) $(ABS_DB_PATH)/README-JDK.html $(JDK_IMAGE_DIR)/db + $(CD) $(JDK_IMAGE_DIR)/db && $(UNZIP) -o $(DB_BINARY_BUNDLE) + $(CD) $(JDK_IMAGE_DIR)/db && $(MV) db-derby-*-bin/* . + $(CD) $(JDK_IMAGE_DIR)/db && $(RM) -r db-derby-*-bin + $(CAT) $(ABS_DB_PATH)/README-JDK.html | \ + $(SED) "s/XXXX/$(shell cat $(JDK_TOPDIR)/src/closed/share/db/COPYRIGHTYEAR)/" > \ + $(JDK_IMAGE_DIR)/db/README-JDK.html + $(CAT) $(ABS_DB_PATH)/3RDPARTY | \ + $(SED) "s/XXXX/$(shell cat $(JDK_TOPDIR)/src/closed/share/db/COPYRIGHTYEAR)/" > \ + $(JDK_IMAGE_DIR)/db/3RDPARTY ifndef NO_DEMOS - $(RM) -rf $(DEMODIR)/db + $(RM) -r $(DEMODIR)/db $(MV) $(JDK_IMAGE_DIR)/db/demo $(DEMODIR)/db - $(CP) $(ABS_DB_PATH)/README-JDK-DEMOS.html $(DEMODIR)/db/ + $(CAT) $(ABS_DB_PATH)/README-JDK-DEMOS.html | \ + $(SED) "s/XXXX/$(shell cat $(JDK_TOPDIR)/src/closed/share/db/COPYRIGHTYEAR)/" > \ + $(DEMODIR)/db/README-JDK-DEMOS.html else - $(RM) -rf $(JDK_IMAGE_DIR)/db/demo + $(RM) -r $(JDK_IMAGE_DIR)/db/demo endif - $(RM) $(JDK_IMAGE_DIR)/db/index.html $(JDK_IMAGE_DIR)/db/register.html + @# remove stuff from original distro we don't want + $(RM) $(JDK_IMAGE_DIR)/db/index.html $(JDK_IMAGE_DIR)/db/KEYS + $(RM) -r $(JDK_IMAGE_DIR)/db/{docs,javadoc,test} endif # The launcher source files we need for src.zip diff --git a/jdk/make/sun/Makefile b/jdk/make/sun/Makefile index 35fb554a81a..c9d6f9cc663 100644 --- a/jdk/make/sun/Makefile +++ b/jdk/make/sun/Makefile @@ -31,12 +31,6 @@ BUILDDIR = .. PRODUCT = sun include $(BUILDDIR)/common/Defs.gmk -# Rhino/Mozilla java sources -ORG_EXISTS := $(call DirExists,$(CLOSED_SRC)/share/classes/sun/org,,) -ifneq ("$(ORG_EXISTS)", "") - ORG_SUBDIR = org -endif - # Non windows subdirs ifneq ($(PLATFORM), windows) ifndef OPENJDK @@ -83,7 +77,7 @@ SUBDIRS_desktop = audio $(RENDER_SUBDIR) image \ $(LWAWT_PRE_SUBDIR) $(DISPLAY_LIBS) $(DGA_SUBDIR) $(LWAWT_SUBDIR) \ jawt font jpeg cmm $(DISPLAY_TOOLS) SUBDIRS_management = management -SUBDIRS_misc = $(ORG_SUBDIR) rmi tracing +SUBDIRS_misc = rmi tracing SUBDIRS_tools = native2ascii serialver tools jconsole ifndef OPENJDK diff --git a/jdk/make/sun/awt/mapfile-vers b/jdk/make/sun/awt/mapfile-vers index 5c6cfea808b..f68ef5cfb9d 100644 --- a/jdk/make/sun/awt/mapfile-vers +++ b/jdk/make/sun/awt/mapfile-vers @@ -87,6 +87,7 @@ SUNWprivate_1.1 { Java_sun_java2d_pipe_ShapeSpanIterator_skipDownTo; Java_java_awt_Dimension_initIDs; + Java_java_awt_Choice_initIDs; Java_java_awt_event_MouseEvent_initIDs; Java_java_awt_image_DataBufferInt_initIDs; Java_java_awt_image_SinglePixelPackedSampleModel_initIDs; diff --git a/jdk/make/sun/awt/mapfile-vers-bsd b/jdk/make/sun/awt/mapfile-vers-bsd index f606b3fbbb0..dcc59f09e0e 100644 --- a/jdk/make/sun/awt/mapfile-vers-bsd +++ b/jdk/make/sun/awt/mapfile-vers-bsd @@ -87,6 +87,7 @@ SUNWprivate_1.1 { Java_sun_java2d_pipe_ShapeSpanIterator_skipDownTo; Java_java_awt_Dimension_initIDs; + Java_java_awt_Choice_initIDs; Java_java_awt_event_MouseEvent_initIDs; Java_java_awt_image_DataBufferInt_initIDs; Java_java_awt_image_SinglePixelPackedSampleModel_initIDs; diff --git a/jdk/make/sun/awt/mapfile-vers-linux b/jdk/make/sun/awt/mapfile-vers-linux index b7033b89fa8..03f0cc07e47 100644 --- a/jdk/make/sun/awt/mapfile-vers-linux +++ b/jdk/make/sun/awt/mapfile-vers-linux @@ -87,6 +87,7 @@ SUNWprivate_1.1 { Java_sun_java2d_pipe_ShapeSpanIterator_skipDownTo; Java_java_awt_Dimension_initIDs; + Java_java_awt_Choice_initIDs; Java_java_awt_event_MouseEvent_initIDs; Java_java_awt_image_DataBufferInt_initIDs; Java_java_awt_image_SinglePixelPackedSampleModel_initIDs; diff --git a/jdk/make/sun/javazic/tzdata/VERSION b/jdk/make/sun/javazic/tzdata/VERSION index 85db871ccf3..8ad1064e058 100644 --- a/jdk/make/sun/javazic/tzdata/VERSION +++ b/jdk/make/sun/javazic/tzdata/VERSION @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2012i +tzdata2013c diff --git a/jdk/make/sun/javazic/tzdata/africa b/jdk/make/sun/javazic/tzdata/africa index 7db9b3d269d..2f5d3c5e3fc 100644 --- a/jdk/make/sun/javazic/tzdata/africa +++ b/jdk/make/sun/javazic/tzdata/africa @@ -27,9 +27,9 @@ # This data is by no means authoritative; if you think you know better, # go ahead and edit the file (and please send any changes to -# tz@elsie.nci.nih.gov for general use in the future). +# tz@iana.org for general use in the future). -# From Paul Eggert (2006-03-22): +# From Paul Eggert (2013-02-21): # # A good source for time zone historical data outside the U.S. is # Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition), @@ -48,6 +48,10 @@ # Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which # I found in the UCLA library. # +# For data circa 1899, a common source is: +# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94 +# . +# # A reliable and entertaining source about time zones is # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997). # @@ -139,8 +143,12 @@ Zone Africa/Porto-Novo 0:10:28 - LMT 1912 1:00 - WAT # Botswana +# From Paul Eggert (2013-02-21): +# Milne says they were regulated by the Cape Town Signal in 1899; +# assume they switched to 2:00 when Cape Town did. # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Gaborone 1:43:40 - LMT 1885 + 1:30 - SAST 1903 Mar 2:00 - CAT 1943 Sep 19 2:00 2:00 1:00 CAST 1944 Mar 19 2:00 2:00 - CAT @@ -212,6 +220,11 @@ Zone Africa/Djibouti 2:52:36 - LMT 1911 Jul # Egypt +# Milne says Cairo used 2:05:08.9, the local mean time of the Abbasizeh +# observatory; round to nearest. Milne also says that the official time for +# Egypt was mean noon at the Great Pyramid, 2:04:30.5, but apparently this +# did not apply to Cairo, Alexandria, or Port Said. + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Egypt 1940 only - Jul 15 0:00 1:00 S Rule Egypt 1940 only - Oct 1 0:00 0 - @@ -352,7 +365,7 @@ Rule Egypt 2010 only - Sep 10 0:00 1:00 S Rule Egypt 2010 only - Sep lastThu 23:00s 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Cairo 2:05:00 - LMT 1900 Oct +Zone Africa/Cairo 2:05:09 - LMT 1900 Oct 2:00 Egypt EE%sT # Equatorial Guinea @@ -447,6 +460,20 @@ Zone Africa/Monrovia -0:43:08 - LMT 1882 # Libya +# From Even Scharning (2012-11-10): +# Libya set their time one hour back at 02:00 on Saturday November 10. +# http://www.libyaherald.com/2012/11/04/clocks-to-go-back-an-hour-on-saturday/ +# Here is an official source [in Arabic]: http://ls.ly/fb6Yc +# +# Steffen Thorsen forwarded a translation (2012-11-10) in +# http://mm.icann.org/pipermail/tz/2012-November/018451.html +# +# From Tim Parenti (2012-11-11): +# Treat the 2012-11-10 change as a zone change from UTC+2 to UTC+1. +# The DST rules planned for 2013 and onward roughly mirror those of Europe +# (either two days before them or five days after them, so as to fall on +# lastFri instead of lastSun). + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Libya 1951 only - Oct 14 2:00 1:00 S Rule Libya 1952 only - Jan 1 0:00 0 - @@ -461,17 +488,21 @@ Rule Libya 1986 only - Apr 4 0:00 1:00 S Rule Libya 1986 only - Oct 3 0:00 0 - Rule Libya 1987 1989 - Apr 1 0:00 1:00 S Rule Libya 1987 1989 - Oct 1 0:00 0 - +Rule Libya 1997 only - Apr 4 0:00 1:00 S +Rule Libya 1997 only - Oct 4 0:00 0 - +Rule Libya 2013 max - Mar lastFri 1:00 1:00 S +Rule Libya 2013 max - Oct lastFri 2:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Tripoli 0:52:44 - LMT 1920 1:00 Libya CE%sT 1959 2:00 - EET 1982 1:00 Libya CE%sT 1990 May 4 -# The following entries are from Shanks & Pottenger; +# The 1996 and 1997 entries are from Shanks & Pottenger; # the IATA SSIM data contain some obvious errors. 2:00 - EET 1996 Sep 30 - 1:00 - CET 1997 Apr 4 - 1:00 1:00 CEST 1997 Oct 4 - 2:00 - EET + 1:00 Libya CE%sT 1997 Oct 4 + 2:00 - EET 2012 Nov 10 2:00 + 1:00 Libya CE%sT # Madagascar # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -838,6 +869,41 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou # 3:00 am Friday, July 20, 2012 and will again be advanced by 60 minutes # August 20, 2012 from 2:00 am. +# From Paul Eggert (2013-03-06): +# Morocco's daylight-saving transitions due to Ramadan seem to be +# announced a bit in advance. On 2012-07-11 the Moroccan government +# announced that year's Ramadan daylight-saving transitions would be +# 2012-07-20 and 2012-08-20; see +# . +# +# To estimate what the Moroccan government will do in future years, +# transition dates for 2013 through 2021 were determined by running +# the following program under GNU Emacs 24.3: +# +# (let ((islamic-year 1434)) +# (while (< islamic-year 1444) +# (let ((a +# (calendar-gregorian-from-absolute +# (calendar-islamic-to-absolute (list 9 1 islamic-year)))) +# (b +# (calendar-gregorian-from-absolute +# (calendar-islamic-to-absolute (list 10 1 islamic-year))))) +# (insert +# (format +# (concat "Rule\tMorocco\t%d\tonly\t-\t%s\t %2d\t 3:00\t0\t-\n" +# "Rule\tMorocco\t%d\tonly\t-\t%s\t %2d\t 2:00\t1:00\tS\n") +# (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a)) +# (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b))))) +# (setq islamic-year (+ 1 islamic-year)))) +# +# with the results hand-edited for 2020-2022, when the normal spring-forward +# date falls during the estimated Ramadan. +# +# From 2023 through 2038 Ramadan is not predicted to overlap with +# daylight saving time. Starting in 2039 there will be overlap again, +# but 32-bit time_t values roll around in 2038 so for now do not worry +# about dates after 2038. + # RULE NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Morocco 1939 only - Sep 12 0:00 1:00 S @@ -863,10 +929,28 @@ Rule Morocco 2010 only - May 2 0:00 1:00 S Rule Morocco 2010 only - Aug 8 0:00 0 - Rule Morocco 2011 only - Apr 3 0:00 1:00 S Rule Morocco 2011 only - Jul 31 0 0 - -Rule Morocco 2012 max - Apr lastSun 2:00 1:00 S +Rule Morocco 2012 2019 - Apr lastSun 2:00 1:00 S Rule Morocco 2012 max - Sep lastSun 3:00 0 - Rule Morocco 2012 only - Jul 20 3:00 0 - Rule Morocco 2012 only - Aug 20 2:00 1:00 S +Rule Morocco 2013 only - Jul 9 3:00 0 - +Rule Morocco 2013 only - Aug 8 2:00 1:00 S +Rule Morocco 2014 only - Jun 29 3:00 0 - +Rule Morocco 2014 only - Jul 29 2:00 1:00 S +Rule Morocco 2015 only - Jun 18 3:00 0 - +Rule Morocco 2015 only - Jul 18 2:00 1:00 S +Rule Morocco 2016 only - Jun 7 3:00 0 - +Rule Morocco 2016 only - Jul 7 2:00 1:00 S +Rule Morocco 2017 only - May 27 3:00 0 - +Rule Morocco 2017 only - Jun 26 2:00 1:00 S +Rule Morocco 2018 only - May 16 3:00 0 - +Rule Morocco 2018 only - Jun 15 2:00 1:00 S +Rule Morocco 2019 only - May 6 3:00 0 - +Rule Morocco 2019 only - Jun 5 2:00 1:00 S +Rule Morocco 2020 only - May 24 2:00 1:00 S +Rule Morocco 2021 only - May 13 2:00 1:00 S +Rule Morocco 2022 only - May 3 2:00 1:00 S +Rule Morocco 2023 max - Apr lastSun 2:00 1:00 S # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26 diff --git a/jdk/make/sun/javazic/tzdata/antarctica b/jdk/make/sun/javazic/tzdata/antarctica index 64b71d5c052..daa03ea830c 100644 --- a/jdk/make/sun/javazic/tzdata/antarctica +++ b/jdk/make/sun/javazic/tzdata/antarctica @@ -73,38 +73,8 @@ Rule ChileAQ 2009 only - Mar Sun>=9 3:00u 0 - Rule ChileAQ 2010 only - Apr Sun>=1 3:00u 0 - Rule ChileAQ 2011 only - May Sun>=2 3:00u 0 - Rule ChileAQ 2011 only - Aug Sun>=16 4:00u 1:00 S -Rule ChileAQ 2012 only - Apr Sun>=23 3:00u 0 - -Rule ChileAQ 2012 only - Sep Sun>=2 4:00u 1:00 S -Rule ChileAQ 2013 max - Mar Sun>=9 3:00u 0 - -Rule ChileAQ 2013 max - Oct Sun>=9 4:00u 1:00 S - -# These rules are stolen from the `australasia' file. -Rule AusAQ 1917 only - Jan 1 0:01 1:00 - -Rule AusAQ 1917 only - Mar 25 2:00 0 - -Rule AusAQ 1942 only - Jan 1 2:00 1:00 - -Rule AusAQ 1942 only - Mar 29 2:00 0 - -Rule AusAQ 1942 only - Sep 27 2:00 1:00 - -Rule AusAQ 1943 1944 - Mar lastSun 2:00 0 - -Rule AusAQ 1943 only - Oct 3 2:00 1:00 - -Rule ATAQ 1967 only - Oct Sun>=1 2:00s 1:00 - -Rule ATAQ 1968 only - Mar lastSun 2:00s 0 - -Rule ATAQ 1968 1985 - Oct lastSun 2:00s 1:00 - -Rule ATAQ 1969 1971 - Mar Sun>=8 2:00s 0 - -Rule ATAQ 1972 only - Feb lastSun 2:00s 0 - -Rule ATAQ 1973 1981 - Mar Sun>=1 2:00s 0 - -Rule ATAQ 1982 1983 - Mar lastSun 2:00s 0 - -Rule ATAQ 1984 1986 - Mar Sun>=1 2:00s 0 - -Rule ATAQ 1986 only - Oct Sun>=15 2:00s 1:00 - -Rule ATAQ 1987 1990 - Mar Sun>=15 2:00s 0 - -Rule ATAQ 1987 only - Oct Sun>=22 2:00s 1:00 - -Rule ATAQ 1988 1990 - Oct lastSun 2:00s 1:00 - -Rule ATAQ 1991 1999 - Oct Sun>=1 2:00s 1:00 - -Rule ATAQ 1991 2005 - Mar lastSun 2:00s 0 - -Rule ATAQ 2000 only - Aug lastSun 2:00s 1:00 - -Rule ATAQ 2001 max - Oct Sun>=1 2:00s 1:00 - -Rule ATAQ 2006 only - Apr Sun>=1 2:00s 0 - -Rule ATAQ 2007 only - Mar lastSun 2:00s 0 - -Rule ATAQ 2008 max - Apr Sun>=1 2:00s 0 - +Rule ChileAQ 2012 max - Apr Sun>=23 3:00u 0 - +Rule ChileAQ 2012 max - Sep Sun>=2 4:00u 1:00 S # Argentina - year-round bases # Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05 @@ -147,10 +117,7 @@ Rule ATAQ 2008 max - Apr Sun>=1 2:00s 0 - # # From Steffen Thorsen (2010-03-10): -# We got these changes from the Australian Antarctic Division: -# - Macquarie Island will stay on UTC+11 for winter and therefore not -# switch back from daylight savings time when other parts of Australia do -# on 4 April. +# We got these changes from the Australian Antarctic Division: ... # # - Casey station reverted to its normal time of UTC+8 on 5 March 2010. # The change to UTC+11 is being considered as a regular summer thing but @@ -161,9 +128,6 @@ Rule ATAQ 2008 max - Apr Sun>=1 2:00s 0 - # # - Mawson station stays on UTC+5. # -# In addition to the Rule changes for Casey/Davis, it means that Macquarie -# will no longer be like Hobart and will have to have its own Zone created. -# # Background: # # http://www.timeanddate.com/news/time/antartica-time-changes-2010.html @@ -190,12 +154,6 @@ Zone Antarctica/Mawson 0 - zzz 1954 Feb 13 6:00 - MAWT 2009 Oct 18 2:00 # Mawson Time 5:00 - MAWT -Zone Antarctica/Macquarie 0 - zzz 1911 - 10:00 - EST 1916 Oct 1 2:00 - 10:00 1:00 EST 1917 Feb - 10:00 AusAQ EST 1967 - 10:00 ATAQ EST 2010 Apr 4 3:00 - 11:00 - MIST # Macquarie Island Time # References: # # Casey Weather (1998-02-26) diff --git a/jdk/make/sun/javazic/tzdata/asia b/jdk/make/sun/javazic/tzdata/asia index 9ef3ef8df54..7818c029a60 100644 --- a/jdk/make/sun/javazic/tzdata/asia +++ b/jdk/make/sun/javazic/tzdata/asia @@ -27,9 +27,9 @@ # This data is by no means authoritative; if you think you know better, # go ahead and edit the file (and please send any changes to -# tz@elsie.nci.nih.gov for general use in the future). +# tz@iana.org for general use in the future). -# From Paul Eggert (2006-03-22): +# From Paul Eggert (2013-02-21): # # A good source for time zone historical data outside the U.S. is # Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition), @@ -48,6 +48,10 @@ # Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which # I found in the UCLA library. # +# For data circa 1899, a common source is: +# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94 +# . +# # A reliable and entertaining source about time zones is # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997). # @@ -302,9 +306,12 @@ Zone Asia/Brunei 7:39:40 - LMT 1926 Mar # Bandar Seri Begawan 8:00 - BNT # Burma / Myanmar + +# Milne says 6:24:40 was the meridian of the time ball observatory at Rangoon. + # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Rangoon 6:24:40 - LMT 1880 # or Yangon - 6:24:36 - RMT 1920 # Rangoon Mean Time? + 6:24:40 - RMT 1920 # Rangoon Mean Time? 6:30 - BURT 1942 May # Burma Time 9:00 - JST 1945 May 3 6:30 - MMT # Myanmar Time @@ -407,7 +414,8 @@ Zone Asia/Harbin 8:26:44 - LMT 1928 # or Haerbin 8:00 PRC C%sT # Zhongyuan Time ("Central plain Time") # most of China -Zone Asia/Shanghai 8:05:52 - LMT 1928 +# Milne gives 8:05:56.7; round to nearest. +Zone Asia/Shanghai 8:05:57 - LMT 1928 8:00 Shang C%sT 1949 8:00 PRC C%sT # Long-shu Time (probably due to Long and Shu being two names of that area) @@ -504,6 +512,10 @@ Zone Asia/Kashgar 5:03:56 - LMT 1928 # or Kashi or Kaxgar 8:00 PRC C%sT +# Hong Kong (Xianggang) + +# Milne gives 7:36:41.7; round this. + # From Lee Yiu Chung (2009-10-24): # I found there are some mistakes for the...DST rule for Hong # Kong. [According] to the DST record from Hong Kong Observatory (actually, @@ -570,7 +582,6 @@ Zone Asia/Kashgar 5:03:56 - LMT 1928 # or Kashi or Kaxgar # The Japanese surrender of Hong Kong was signed 1945-09-15. # For lack of anything better, use start of those days as the transition times. -# Hong Kong (Xianggang) # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule HK 1941 only - Apr 1 3:30 1:00 S Rule HK 1941 only - Sep 30 3:30 0 - @@ -592,7 +603,7 @@ Rule HK 1973 only - Dec 30 3:30 1:00 S Rule HK 1979 only - May Sun>=8 3:30 1:00 S Rule HK 1979 only - Oct Sun>=16 3:30 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Asia/Hong_Kong 7:36:36 - LMT 1904 Oct 30 +Zone Asia/Hong_Kong 7:36:42 - LMT 1904 Oct 30 8:00 HK HK%sT 1941 Dec 25 9:00 - JST 1945 Sep 15 8:00 HK HK%sT @@ -669,6 +680,9 @@ Zone Asia/Macau 7:34:20 - LMT 1912 ############################################################################### # Cyprus +# +# Milne says the Eastern Telegraph Company used 2:14:00. Stick with LMT. +# # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Cyprus 1975 only - Apr 13 0:00 1:00 S Rule Cyprus 1975 only - Oct 12 0:00 0 - @@ -1222,7 +1236,6 @@ Rule Zion 2012 only - Mar Fri>=26 2:00 1:00 D Rule Zion 2012 only - Sep 23 2:00 0 S # From Ephraim Silverberg (2012-10-18): - # Yesterday, the Interior Ministry Committee, after more than a year # past, approved sending the proposed June 2011 changes to the Time # Decree Law back to the Knesset for second and third (final) votes @@ -1235,6 +1248,10 @@ Rule Zion 2012 only - Sep 23 2:00 0 S # later (i.e. at 02:00 the first Monday after October 2). # [Rosh Hashana holidays are factored in until 2100.] +# From Ephraim Silverberg (2012-11-05): +# The Knesset passed today (in second and final readings) the amendment to the +# Time Decree Law making the changes ... law. + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Zion 2013 max - Mar Fri>=23 2:00 1:00 D Rule Zion 2013 2026 - Oct Sun>=2 2:00 0 S @@ -1824,8 +1841,11 @@ Zone Asia/Kathmandu 5:41:16 - LMT 1920 5:45 - NPT # Nepal Time # Oman + +# Milne says 3:54:24 was the meridian of the Muscat Tidal Observatory. + # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Asia/Muscat 3:54:20 - LMT 1920 +Zone Asia/Muscat 3:54:24 - LMT 1920 4:00 - GST # Pakistan @@ -2072,8 +2092,7 @@ Zone Asia/Karachi 4:28:12 - LMT 1907 # occurred before our cutoff date of 1970. # However, as we get more information, we may need to add entries # for parts of the West Bank as they transitioned from Israel's rules -# to Palestine's rules. If you have more info about this, please -# send it to tz@elsie.nci.nih.gov for incorporation into future editions. +# to Palestine's rules. # From IINS News Service - Israel - 1998-03-23 10:38:07 Israel time, # forwarded by Ephraim Silverberg: @@ -2295,11 +2314,20 @@ Zone Asia/Karachi 4:28:12 - LMT 1907 # http://www.timeanddate.com/news/time/gaza-west-bank-dst-2012.html # -# From Arthur David Olson (2012-03-27): -# The timeanddate article for 2012 says that "the end date has not yet been -# announced" and that "Last year, both...paused daylight saving time during... -# Ramadan. It is not yet known [for] 2012." -# For now, assume both switch back on the last Friday in September. XXX +# From Steffen Thorsen (2013-03-26): +# The following news sources tells that Palestine will "start daylight saving +# time from midnight on Friday, March 29, 2013" (translated). +# [These are in Arabic and are for Gaza and for Ramallah, respectively.] +# http://www.samanews.com/index.php?act=Show&id=154120 +# http://safa.ps/details/news/99844/%D8%B1%D8%A7%D9%85-%D8%A7%D9%84%D9%84%D9%87-%D8%A8%D8%AF%D8%A1-%D8%A7%D9%84%D8%AA%D9%88%D9%82%D9%8A%D8%AA-%D8%A7%D9%84%D8%B5%D9%8A%D9%81%D9%8A-29-%D8%A7%D9%84%D8%AC%D8%A7%D8%B1%D9%8A.html + +# From Paul Eggert (2013-04-15): +# For future dates, guess the last Thursday in March at 24:00 through +# the first Friday on or after September 21 at 01:00. This is consistent with +# the predictions in today's editions of the following URLs, +# which are for Gaza and Hebron respectively: +# http://www.timeanddate.com/worldclock/timezone.html?n=702 +# http://www.timeanddate.com/worldclock/timezone.html?n=2364 # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule EgyptAsia 1957 only - May 10 0:00 1:00 S @@ -2313,19 +2341,20 @@ Rule Palestine 1999 2005 - Apr Fri>=15 0:00 1:00 S Rule Palestine 1999 2003 - Oct Fri>=15 0:00 0 - Rule Palestine 2004 only - Oct 1 1:00 0 - Rule Palestine 2005 only - Oct 4 2:00 0 - -Rule Palestine 2006 2008 - Apr 1 0:00 1:00 S +Rule Palestine 2006 2007 - Apr 1 0:00 1:00 S Rule Palestine 2006 only - Sep 22 0:00 0 - Rule Palestine 2007 only - Sep Thu>=8 2:00 0 - -Rule Palestine 2008 only - Aug lastFri 0:00 0 - -Rule Palestine 2009 only - Mar lastFri 0:00 1:00 S -Rule Palestine 2009 only - Sep Fri>=1 2:00 0 - -Rule Palestine 2010 only - Mar lastSat 0:01 1:00 S +Rule Palestine 2008 2009 - Mar lastFri 0:00 1:00 S +Rule Palestine 2008 only - Sep 1 0:00 0 - +Rule Palestine 2009 only - Sep Fri>=1 1:00 0 - +Rule Palestine 2010 only - Mar 26 0:00 1:00 S Rule Palestine 2010 only - Aug 11 0:00 0 - - -# From Arthur David Olson (2011-09-20): -# 2011 transitions per http://www.timeanddate.com as of 2011-09-20. -# From Paul Eggert (2012-10-12): -# 2012 transitions per http://www.timeanddate.com as of 2012-10-12. +Rule Palestine 2011 only - Apr 1 0:01 1:00 S +Rule Palestine 2011 only - Aug 1 0:00 0 - +Rule Palestine 2011 only - Aug 30 0:00 1:00 S +Rule Palestine 2011 only - Sep 30 0:00 0 - +Rule Palestine 2012 max - Mar lastThu 24:00 1:00 S +Rule Palestine 2012 max - Sep Fri>=21 1:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Gaza 2:17:52 - LMT 1900 Oct @@ -2333,26 +2362,20 @@ Zone Asia/Gaza 2:17:52 - LMT 1900 Oct 2:00 EgyptAsia EE%sT 1967 Jun 5 2:00 Zion I%sT 1996 2:00 Jordan EE%sT 1999 - 2:00 Palestine EE%sT 2011 Apr 2 12:01 - 2:00 1:00 EEST 2011 Aug 1 - 2:00 - EET 2012 Mar 30 - 2:00 1:00 EEST 2012 Sep 21 1:00 - 2:00 - EET + 2:00 Palestine EE%sT 2008 Aug 29 0:00 + 2:00 - EET 2008 Sep + 2:00 Palestine EE%sT 2010 + 2:00 - EET 2010 Mar 27 0:01 + 2:00 Palestine EE%sT 2011 Aug 1 + 2:00 - EET 2012 + 2:00 Palestine EE%sT Zone Asia/Hebron 2:20:23 - LMT 1900 Oct 2:00 Zion EET 1948 May 15 2:00 EgyptAsia EE%sT 1967 Jun 5 2:00 Zion I%sT 1996 2:00 Jordan EE%sT 1999 - 2:00 Palestine EE%sT 2008 Aug - 2:00 1:00 EEST 2008 Sep - 2:00 Palestine EE%sT 2011 Apr 1 12:01 - 2:00 1:00 EEST 2011 Aug 1 - 2:00 - EET 2011 Aug 30 - 2:00 1:00 EEST 2011 Sep 30 3:00 - 2:00 - EET 2012 Mar 30 - 2:00 1:00 EEST 2012 Sep 21 1:00 - 2:00 - EET + 2:00 Palestine EE%sT # Paracel Is # no information @@ -2421,6 +2444,13 @@ Zone Asia/Singapore 6:55:25 - LMT 1901 Jan 1 # no information # Sri Lanka + +# From Paul Eggert (2013-02-21): +# Milne says "Madras mean time use from May 1, 1898. Prior to this Colombo +# mean time, 5h. 4m. 21.9s. F., was used." But 5:04:21.9 differs considerably +# from Colombo's meridian 5:19:24, so for now ignore Milne and stick with +# Shanks and Pottenger. + # From Paul Eggert (1996-09-03): # "Sri Lanka advances clock by an hour to avoid blackout" # (www.virtual-pc.com/lankaweb/news/items/240596-2.html, 1996-05-24, @@ -2720,6 +2750,12 @@ Zone Asia/Tashkent 4:37:12 - LMT 1924 May 2 # Vietnam +# From Paul Eggert (2013-02-21): +# Milne gives 7:16:56 for the meridian of Saigon in 1899, as being +# used in Lower Laos, Cambodia, and Annam. But this is quite a ways +# from Saigon's location. For now, ignore this and stick with Shanks +# and Pottenger. + # From Arthur David Olson (2008-03-18): # The English-language name of Vietnam's most populous city is "Ho Chi Min City"; # we use Ho_Chi_Minh below to avoid a name of more than 14 characters. @@ -2733,6 +2769,10 @@ Zone Asia/Ho_Chi_Minh 7:06:40 - LMT 1906 Jun 9 7:00 - ICT # Yemen + +# Milne says 2:59:54 was the meridian of the saluting battery at Aden, +# and that Yemen was at 1:55:56, the meridian of the Hagia Sophia. + # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Asia/Aden 3:00:48 - LMT 1950 +Zone Asia/Aden 2:59:54 - LMT 1950 3:00 - AST diff --git a/jdk/make/sun/javazic/tzdata/australasia b/jdk/make/sun/javazic/tzdata/australasia index 7f83448f3fb..db954a81dcd 100644 --- a/jdk/make/sun/javazic/tzdata/australasia +++ b/jdk/make/sun/javazic/tzdata/australasia @@ -241,9 +241,26 @@ Zone Australia/Lord_Howe 10:36:20 - LMT 1895 Feb # no times are set # # Macquarie -# permanent occupation (scientific station) since 1948; -# sealing and penguin oil station operated 1888/1917 -# like Australia/Hobart +# Permanent occupation (scientific station) 1911-1915 and since 25 March 1948; +# sealing and penguin oil station operated Nov 1899 to Apr 1919. See the +# Tasmania Parks & Wildlife Service history of sealing at Macquarie Island +# +# . +# Guess that it was like Australia/Hobart while inhabited before 2010. +# +# From Steffen Thorsen (2010-03-10): +# We got these changes from the Australian Antarctic Division: +# - Macquarie Island will stay on UTC+11 for winter and therefore not +# switch back from daylight savings time when other parts of Australia do +# on 4 April. +Zone Antarctica/Macquarie 0 - zzz 1899 Nov + 10:00 - EST 1916 Oct 1 2:00 + 10:00 1:00 EST 1917 Feb + 10:00 Aus EST 1919 Apr + 0 - zzz 1948 Mar 25 + 10:00 Aus EST 1967 + 10:00 AT EST 2010 Apr 4 3:00 + 11:00 - MIST # Macquarie I Standard Time # Christmas # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -269,6 +286,9 @@ Zone Indian/Cocos 6:27:40 - LMT 1900 6:30 - CCT # Cocos Islands Time # Fiji + +# Milne gives 11:55:44 for Suva. + # From Alexander Krivenyshev (2009-11-10): # According to Fiji Broadcasting Corporation, Fiji plans to re-introduce DST # from November 29th 2009 to April 25th 2010. @@ -362,7 +382,7 @@ Rule Fiji 2010 max - Oct Sun>=18 2:00 1:00 S Rule Fiji 2011 only - Mar Sun>=1 3:00 0 - Rule Fiji 2012 max - Jan Sun>=18 3:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Pacific/Fiji 11:53:40 - LMT 1915 Oct 26 # Suva +Zone Pacific/Fiji 11:55:44 - LMT 1915 Oct 26 # Suva 12:00 Fiji FJ%sT # Fiji Time # French Polynesia @@ -803,9 +823,9 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901 # This data is by no means authoritative; if you think you know better, # go ahead and edit the file (and please send any changes to -# tz@elsie.nci.nih.gov for general use in the future). +# tz@iana.org for general use in the future). -# From Paul Eggert (2006-03-22): +# From Paul Eggert (2013-02-21): # A good source for time zone historical data outside the U.S. is # Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition), # San Diego: ACS Publications, Inc. (2003). @@ -823,6 +843,10 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901 # Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which # I found in the UCLA library. # +# For data circa 1899, a common source is: +# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94 +# . +# # A reliable and entertaining source about time zones is # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997). # diff --git a/jdk/make/sun/javazic/tzdata/europe b/jdk/make/sun/javazic/tzdata/europe index 9a0d0b9db94..268504d0983 100644 --- a/jdk/make/sun/javazic/tzdata/europe +++ b/jdk/make/sun/javazic/tzdata/europe @@ -27,7 +27,7 @@ # This data is by no means authoritative; if you think you know better, # go ahead and edit the file (and please send any changes to -# tz@elsie.nci.nih.gov for general use in the future). +# tz@iana.org for general use in the future). # From Paul Eggert (2006-03-22): # A good source for time zone historical data outside the U.S. is @@ -53,6 +53,12 @@ # William Willett, The Waste of Daylight, 19th edition # (1914-03) # +# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94 +# . He writes: +# "It is requested that corrections and additions to these tables +# may be sent to Mr. John Milne, Royal Geographical Society, +# Savile Row, London." Nowadays please email them to tz@iana.org. +# # Brazil's Departamento Servico da Hora (DSH), # # History of Summer Time @@ -689,6 +695,8 @@ Zone Europe/Andorra 0:06:04 - LMT 1901 # Austria +# Milne says Vienna time was 1:05:21. + # From Paul Eggert (2006-03-22): Shanks & Pottenger give 1918-06-16 and # 1945-11-18, but the Austrian Federal Office of Metrology and # Surveying (BEV) gives 1918-09-16 and for Vienna gives the "alleged" @@ -706,7 +714,7 @@ Rule Austria 1948 only - Apr 18 2:00s 1:00 S Rule Austria 1980 only - Apr 6 0:00 1:00 S Rule Austria 1980 only - Sep 28 0:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Europe/Vienna 1:05:20 - LMT 1893 Apr +Zone Europe/Vienna 1:05:21 - LMT 1893 Apr 1:00 C-Eur CE%sT 1920 1:00 Austria CE%sT 1940 Apr 1 2:00s 1:00 C-Eur CE%sT 1945 Apr 2 2:00s @@ -1262,6 +1270,21 @@ Zone Europe/Berlin 0:53:28 - LMT 1893 Apr 1:00 Germany CE%sT 1980 1:00 EU CE%sT +# From Tobias Conradi (2011-09-12): +# Busingen , surrounded by the Swiss canton +# Schaffhausen, did not start observing DST in 1980 as the rest of DE +# (West Germany at that time) and DD (East Germany at that time) did. +# DD merged into DE, the area is currently covered by code DE in ISO 3166-1, +# which in turn is covered by the zone Europe/Berlin. +# +# Source for the time in Busingen 1980: +# http://www.srf.ch/player/video?id=c012c029-03b7-4c2b-9164-aa5902cd58d3 + +# From Arthur David Olson (2012-03-03): +# Busingen and Zurich have shared clocks since 1970. + +Link Europe/Zurich Europe/Busingen + # Georgia # Please see the "asia" file for Asia/Tbilisi. # Herodotus (Histories, IV.45) says Georgia north of the Phasis (now Rioni) @@ -2066,6 +2089,70 @@ Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct # Russia +# From Alexander Krivenyshev (2011-09-15): +# Based on last Russian Government Decree # 725 on August 31, 2011 +# (Government document +# +# http://www.government.ru/gov/results/16355/print/ +# +# in Russian) +# there are few corrections have to be made for some Russian time zones... +# All updated Russian Time Zones were placed in table and translated to English +# by WorldTimeZone.com at the link below: +# +# http://www.worldtimezone.com/dst_news/dst_news_russia36.htm +# + +# From Sanjeev Gupta (2011-09-27): +# Scans of [Decree #23 of January 8, 1992] are available at: +# +# http://government.consultant.ru/page.aspx?1223966 +# They are in Cyrillic letters (presumably Russian). + +# From Arthur David Olson (2012-05-09): +# Regarding the instant when clocks in time-zone-shifting parts of Russia +# changed in September 2011: +# +# One source is +# < a href="http://government.ru/gov/results/16355/> +# http://government.ru/gov/results/16355/ +# +# which, according to translate.google.com, begins "Decree of August 31, +# 2011 No 725" and contains no other dates or "effective date" information. +# +# Another source is +# +# http://www.rg.ru/2011/09/06/chas-zona-dok.html +# +# which, according to translate.google.com, begins "Resolution of the +# Government of the Russian Federation on August 31, 2011 N 725" and also +# contains "Date first official publication: September 6, 2011 Posted on: +# in the 'RG' - Federal Issue number 5573 September 6, 2011" but which +# does not contain any "effective date" information. +# +# Another source is +# +# http://en.wikipedia.org/wiki/Oymyakonsky_District#cite_note-RuTime-7 +# +# which, in note 8, contains "Resolution #725 of August 31, 2011... +# Effective as of after 7 days following the day of the official publication" +# but which does not contain any reference to September 6, 2011. +# +# The Wikipedia article refers to +# +# http://base.consultant.ru/cons/cgi/online.cgi?req=doc;base=LAW;n=118896 +# +# which seems to copy the text of the government.ru page. +# +# Tobias Conradi combines Wikipedia's +# "as of after 7 days following the day of the official publication" +# with www.rg.ru's "Date of first official publication: September 6, 2011" to get +# September 13, 2011 as the cutover date (unusually, a Tuesday, as Tobias Conradi notes). +# +# None of the sources indicates a time of day for changing clocks. +# +# Go with 2011-09-13 0:00s. + # From Paul Eggert (2006-03-22): # Except for Moscow after 1919-07-01, I invented the time zone abbreviations. # Moscow time zone abbreviations after 1919-07-01, and Moscow rules after 1991, @@ -2293,14 +2380,32 @@ Zone Asia/Yakutsk 8:38:40 - LMT 1919 Dec 15 # [parts of] Respublika Sakha (Yakutiya). # From Oscar van Vlijmen (2009-11-29): -# The Sakha districts are: Bulunskij, Verkhoyanskij, Tomponskij, Ust'-Majskij, -# Ust'-Yanskij. +# The Sakha districts are: Bulunskij, Verkhoyanskij, ... Ust'-Yanskij. Zone Asia/Vladivostok 8:47:44 - LMT 1922 Nov 15 9:00 - VLAT 1930 Jun 21 # Vladivostok Time 10:00 Russia VLA%sT 1991 Mar 31 2:00s 9:00 Russia VLA%sST 1992 Jan 19 2:00s 10:00 Russia VLA%sT 2011 Mar 27 2:00s 11:00 - VLAT + +# From Arthur David Olson (2012-05-09): +# Tomponskij and Ust'-Majskij switched from Vladivostok time to Yakutsk time +# in 2011. +# +# From Paul Eggert (2012-11-25): +# Shanks and Pottenger (2003) has Khandyga on Yakutsk time. +# Make a wild guess that it switched to Vladivostok time in 2004. +# This transition is no doubt wrong, but we have no better info. +# +Zone Asia/Khandyga 9:02:13 - LMT 1919 Dec 15 + 8:00 - YAKT 1930 Jun 21 # Yakutsk Time + 9:00 Russia YAK%sT 1991 Mar 31 2:00s + 8:00 Russia YAK%sT 1992 Jan 19 2:00s + 9:00 Russia YAK%sT 2004 + 10:00 Russia VLA%sT 2011 Mar 27 2:00s + 11:00 - VLAT 2011 Sep 13 0:00s # Decree 725? + 10:00 - YAKT + # # Sakhalinskaya oblast'. # The Zone name should be Yuzhno-Sakhalinsk, but that's too long. @@ -2319,14 +2424,26 @@ Zone Asia/Sakhalin 9:30:48 - LMT 1905 Aug 23 # From Oscar van Vlijmen (2009-11-29): # The Sakha districts are: Abyjskij, Allaikhovskij, Verkhhhnekolymskij, Momskij, -# Nizhnekolymskij, Ojmyakonskij, Srednekolymskij. +# Nizhnekolymskij, ... Srednekolymskij. Zone Asia/Magadan 10:03:12 - LMT 1924 May 2 10:00 - MAGT 1930 Jun 21 # Magadan Time 11:00 Russia MAG%sT 1991 Mar 31 2:00s 10:00 Russia MAG%sT 1992 Jan 19 2:00s 11:00 Russia MAG%sT 2011 Mar 27 2:00s 12:00 - MAGT -# + +# From Arthur David Olson (2012-05-09): +# Ojmyakonskij and the Kuril Islands switched from +# Magadan time to Vladivostok time in 2011. +Zone Asia/Ust-Nera 9:32:54 - LMT 1919 Dec 15 + 8:00 - YAKT 1930 Jun 21 # Yakutsk Time + 9:00 Russia YAKT 1981 Apr 1 + 11:00 Russia MAG%sT 1991 Mar 31 2:00s + 10:00 Russia MAG%sT 1992 Jan 19 2:00s + 11:00 Russia MAG%sT 2011 Mar 27 2:00s + 12:00 - MAGT 2011 Sep 13 0:00s # Decree 725? + 11:00 - VLAT + # From Oscar van Vlijmen (2001-08-25): [This region consists of] # Kamchatskaya oblast', Koryakskij avtonomnyj okrug. # diff --git a/jdk/make/sun/javazic/tzdata/northamerica b/jdk/make/sun/javazic/tzdata/northamerica index c3033267404..858bf811ac9 100644 --- a/jdk/make/sun/javazic/tzdata/northamerica +++ b/jdk/make/sun/javazic/tzdata/northamerica @@ -29,7 +29,7 @@ # This data is by no means authoritative; if you think you know better, # go ahead and edit the file (and please send any changes to -# tz@elsie.nci.nih.gov for general use in the future). +# tz@iana.org for general use in the future). # From Paul Eggert (1999-03-22): # A reliable and entertaining source about time zones is @@ -1042,6 +1042,9 @@ Zone America/Menominee -5:50:27 - LMT 1885 Sep 18 12:00 # William Willett, The Waste of Daylight, 19th edition # (1914-03) # +# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94 +# . +# # See the `europe' file for Greenland. # Canada @@ -2577,6 +2580,8 @@ Zone America/Antigua -4:07:12 - LMT 1912 Mar 2 # Bahamas # +# For 1899 Milne gives -5:09:29.5; round that. +# # From Sue Williams (2006-12-07): # The Bahamas announced about a month ago that they plan to change their DST # rules to sync with the U.S. starting in 2007.... @@ -2586,11 +2591,14 @@ Zone America/Antigua -4:07:12 - LMT 1912 Mar 2 Rule Bahamas 1964 1975 - Oct lastSun 2:00 0 S Rule Bahamas 1964 1975 - Apr lastSun 2:00 1:00 D # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone America/Nassau -5:09:24 - LMT 1912 Mar 2 +Zone America/Nassau -5:09:30 - LMT 1912 Mar 2 -5:00 Bahamas E%sT 1976 -5:00 US E%sT # Barbados + +# For 1899 Milne gives -3:58:29.2; round that. + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Barb 1977 only - Jun 12 2:00 1:00 D Rule Barb 1977 1978 - Oct Sun>=1 2:00 0 S @@ -2598,8 +2606,8 @@ Rule Barb 1978 1980 - Apr Sun>=15 2:00 1:00 D Rule Barb 1979 only - Sep 30 2:00 0 S Rule Barb 1980 only - Sep 25 2:00 0 S # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone America/Barbados -3:58:28 - LMT 1924 # Bridgetown - -3:58:28 - BMT 1932 # Bridgetown Mean Time +Zone America/Barbados -3:58:29 - LMT 1924 # Bridgetown + -3:58:29 - BMT 1932 # Bridgetown Mean Time -4:00 Barb A%sT # Belize @@ -2617,6 +2625,9 @@ Zone America/Belize -5:52:48 - LMT 1912 Apr # Bermuda +# For 1899 Milne gives -4:19:18.3 as the meridian of the clock tower, +# Bermuda dockyard, Ireland I; round that. + # From Dan Jones, reporting in The Royal Gazette (2006-06-26): # Next year, however, clocks in the US will go forward on the second Sunday @@ -2626,7 +2637,7 @@ Zone America/Belize -5:52:48 - LMT 1912 Apr # http://www.theroyalgazette.com/apps/pbcs.dll/article?AID=/20060529/NEWS/105290135 # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Atlantic/Bermuda -4:19:04 - LMT 1930 Jan 1 2:00 # Hamilton +Zone Atlantic/Bermuda -4:19:18 - LMT 1930 Jan 1 2:00 # Hamilton -4:00 - AST 1974 Apr 28 2:00 -4:00 Bahamas A%sT 1976 -4:00 US A%sT @@ -2638,6 +2649,9 @@ Zone America/Cayman -5:25:32 - LMT 1890 # Georgetown -5:00 - EST # Costa Rica + +# Milne gives -5:36:13.3 as San Jose mean time; round to nearest. + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule CR 1979 1980 - Feb lastSun 0:00 1:00 D Rule CR 1979 1980 - Jun Sun>=1 0:00 0 S @@ -2648,14 +2662,19 @@ Rule CR 1991 only - Jul 1 0:00 0 S Rule CR 1992 only - Mar 15 0:00 0 S # There are too many San Joses elsewhere, so we'll use `Costa Rica'. # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone America/Costa_Rica -5:36:20 - LMT 1890 # San Jose - -5:36:20 - SJMT 1921 Jan 15 # San Jose Mean Time +Zone America/Costa_Rica -5:36:13 - LMT 1890 # San Jose + -5:36:13 - SJMT 1921 Jan 15 # San Jose Mean Time -6:00 CR C%sT # Coco # no information; probably like America/Costa_Rica # Cuba +# From Paul Eggert (2013-02-21): +# Milne gives -5:28:50.45 for the observatory at Havana, -5:29:23.57 +# for the port, and -5:30 for meteorological observations. +# For now, stick with Shanks & Pottenger. + # From Arthur David Olson (1999-03-29): # The 1999-03-28 exhibition baseball game held in Havana, Cuba, between # the Cuban National Team and the Baltimore Orioles was carried live on @@ -3004,24 +3023,21 @@ Zone America/Guatemala -6:02:04 - LMT 1918 Oct 5 # apparently using the same start and end date as USA/Canada. # So this means they have already changed their time. # -# (Sources in French): -# # http://www.alterpresse.org/spip.php?article12510 -# -# # http://radiovision2000haiti.net/home/?p=13253 -# # -# Our coverage: -# -# http://www.timeanddate.com/news/time/haiti-dst-2012.html -# - # From Arthur David Olson (2012-03-11): # The alterpresse.org source seems to show a US-style leap from 2:00 a.m. to # 3:00 a.m. rather than the traditional Haitian jump at midnight. -# Assume a US-style fall back as well XXX. -# Do not yet assume that the change carries forward past 2012 XXX. +# Assume a US-style fall back as well. + +# From Steffen Thorsen (2013-03-10): +# It appears that Haiti is observing DST this year as well, same rules +# as US/Canada. They did it last year as well, and it looks like they +# are going to observe DST every year now... +# +# http://radiovision2000haiti.net/public/haiti-avis-changement-dheure-dimanche/ +# http://www.canalplushaiti.net/?p=6714 # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Haiti 1983 only - May 8 0:00 1:00 D @@ -3033,8 +3049,8 @@ Rule Haiti 1988 1997 - Apr Sun>=1 1:00s 1:00 D Rule Haiti 1988 1997 - Oct lastSun 1:00s 0 S Rule Haiti 2005 2006 - Apr Sun>=1 0:00 1:00 D Rule Haiti 2005 2006 - Oct lastSun 0:00 0 S -Rule Haiti 2012 only - Mar Sun>=8 2:00 1:00 D -Rule Haiti 2012 only - Nov Sun>=1 2:00 0 S +Rule Haiti 2012 max - Mar Sun>=8 2:00 1:00 D +Rule Haiti 2012 max - Nov Sun>=1 2:00 0 S # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone America/Port-au-Prince -4:49:20 - LMT 1890 -4:49 - PPMT 1917 Jan 24 12:00 # P-a-P MT diff --git a/jdk/make/sun/javazic/tzdata/southamerica b/jdk/make/sun/javazic/tzdata/southamerica index 0d6797eab6b..d1865d3f19b 100644 --- a/jdk/make/sun/javazic/tzdata/southamerica +++ b/jdk/make/sun/javazic/tzdata/southamerica @@ -27,13 +27,17 @@ # This data is by no means authoritative; if you think you know better, # go ahead and edit the file (and please send any changes to -# tz@elsie.nci.nih.gov for general use in the future). +# tz@iana.org for general use in the future). # From Paul Eggert (2006-03-22): # A good source for time zone historical data outside the U.S. is # Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition), # San Diego: ACS Publications, Inc. (2003). # +# For data circa 1899, a common source is: +# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94 +# . +# # Gwillim Law writes that a good source # for recent time zone data is the International Air Transport # Association's Standard Schedules Information Manual (IATA SSIM), @@ -404,21 +408,11 @@ Rule Arg 2008 only - Oct Sun>=15 0:00 1:00 S # # is the official page for the Province Government). # -# There's also a note in only one of the major national papers (La Nación) at -# +# There's also a note in only one of the major national papers ... # http://www.lanacion.com.ar/nota.asp?nota_id=1107912 -# # -# The press release says: -# (...) anunció que el próximo domingo a las 00:00 los puntanos deberán -# atrasar una hora sus relojes. -# -# A partir de entonces, San Luis establecerá el huso horario propio de -# la Provincia. De esta manera, durante el periodo del calendario anual -# 2009, el cambio horario quedará comprendido entre las 00:00 del tercer -# domingo de marzo y las 24:00 del segundo sábado de octubre. -# Quick&dirty translation -# (...) announced that next Sunday, at 00:00, Puntanos (the San Luis +# The press release says [quick and dirty translation]: +# ... announced that next Sunday, at 00:00, Puntanos (the San Luis # inhabitants) will have to turn back one hour their clocks # # Since then, San Luis will establish its own Province timezone. Thus, @@ -480,6 +474,9 @@ Rule Arg 2008 only - Oct Sun>=15 0:00 1:00 S # rules...San Luis is still using "Western ARgentina Time" and it got # stuck on Summer daylight savings time even though the summer is over. +# From Paul Eggert (2013-02-21): +# Milne says Cordoba time was -4:16:48.2. Round to the nearest second. + # Zone NAME GMTOFF RULES FORMAT [UNTIL] # # Buenos Aires (BA), Capital Federal (CF), @@ -835,9 +832,9 @@ Zone America/La_Paz -4:32:36 - LMT 1890 # From Guilherme Bernardes Rodrigues (2011-10-07): # There is news in the media, however there is still no decree about it. -# I just send a e-mail to Zulmira Brandão at +# I just send a e-mail to Zulmira Brandao at # http://pcdsh01.on.br/ the -# oficial agency about time in Brazil, and she confirmed that the old rule is +# official agency about time in Brazil, and she confirmed that the old rule is # still in force. # From Guilherme Bernardes Rodrigues (2011-10-14) @@ -1266,9 +1263,13 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # b. Saturday, September 1, 2012, clocks should go forward 60 minutes; that is, # at 23:59:59, instead of passing to 0:00, the time should be adjusted to be # 01:00 on September 2. -# -# Note that...this is yet another "temporary" change that will be reevaluated -# AGAIN in 2013. + +# From Steffen Thorsen (2013-02-15): +# According to several news sources, Chile has extended DST this year, +# they will end DST later and start DST earlier than planned. They +# hope to save energy. The new end date is 2013-04-28 00:00 and new +# start date is 2013-09-08 00:00.... +# http://www.gob.cl/informa/2013/02/15/gobierno-anuncia-fechas-de-cambio-de-hora-para-el-ano-2013.htm # NOTE: ChileAQ rules for Antarctic bases are stored separately in the # 'antarctica' file. @@ -1311,10 +1312,8 @@ Rule Chile 2009 only - Mar Sun>=9 3:00u 0 - Rule Chile 2010 only - Apr Sun>=1 3:00u 0 - Rule Chile 2011 only - May Sun>=2 3:00u 0 - Rule Chile 2011 only - Aug Sun>=16 4:00u 1:00 S -Rule Chile 2012 only - Apr Sun>=23 3:00u 0 - -Rule Chile 2012 only - Sep Sun>=2 4:00u 1:00 S -Rule Chile 2013 max - Mar Sun>=9 3:00u 0 - -Rule Chile 2013 max - Oct Sun>=9 4:00u 1:00 S +Rule Chile 2012 max - Apr Sun>=23 3:00u 0 - +Rule Chile 2012 max - Sep Sun>=2 4:00u 1:00 S # IATA SSIM anomalies: (1992-02) says 1992-03-14; # (1996-09) says 1998-03-08. Ignore these. # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -1336,17 +1335,23 @@ Zone Pacific/Easter -7:17:44 - LMT 1890 # San Felix, and Antarctic bases, are like America/Santiago. # Colombia + +# Milne gives 4:56:16.4 for Bogota time in 1899; round to nearest. He writes, +# "A variation of fifteen minutes in the public clocks of Bogota is not rare." + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule CO 1992 only - May 3 0:00 1:00 S Rule CO 1993 only - Apr 4 0:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone America/Bogota -4:56:20 - LMT 1884 Mar 13 - -4:56:20 - BMT 1914 Nov 23 # Bogota Mean Time +Zone America/Bogota -4:56:16 - LMT 1884 Mar 13 + -4:56:16 - BMT 1914 Nov 23 # Bogota Mean Time -5:00 CO CO%sT # Colombia Time # Malpelo, Providencia, San Andres # no information; probably like America/Bogota # Curacao + +# Milne gives 4:35:46.9 for Curacao mean time; round to nearest. # # From Paul Eggert (2006-03-22): # Shanks & Pottenger say that The Bottom and Philipsburg have been at @@ -1363,7 +1368,7 @@ Zone America/Bogota -4:56:20 - LMT 1884 Mar 13 # though, as far as we know. # # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone America/Curacao -4:35:44 - LMT 1912 Feb 12 # Willemstad +Zone America/Curacao -4:35:47 - LMT 1912 Feb 12 # Willemstad -4:30 - ANT 1965 # Netherlands Antilles Time -4:00 - AST @@ -1377,6 +1382,8 @@ Link America/Curacao America/Kralendijk # Bonaire, Sint Estatius and Saba # Ecuador # +# Milne says the Sentral and South American Telegraph Company used -5:24:15. +# # From Paul Eggert (2007-03-04): # Apparently Ecuador had a failed experiment with DST in 1992. # (2007-02-27) and @@ -1582,7 +1589,16 @@ Rule Para 2005 2009 - Mar Sun>=8 0:00 0 - # forward 60 minutes, in all the territory of the Paraguayan Republic. # ... Rule Para 2010 max - Oct Sun>=1 0:00 1:00 S -Rule Para 2010 max - Apr Sun>=8 0:00 0 - +Rule Para 2010 2012 - Apr Sun>=8 0:00 0 - +# +# From Steffen Thorsen (2013-03-07): +# Paraguay will end DST on 2013-03-24 00:00.... +# http://www.ande.gov.py/interna.php?id=1075 +# +# From Carlos Raul Perasso (2013-03-15): +# The change in Paraguay is now final. Decree number 10780 +# http://www.presidencia.gov.py/uploads/pdf/presidencia-3b86ff4b691c79d4f5927ca964922ec74772ce857c02ca054a52a37b49afc7fb.pdf +Rule Para 2013 max - Mar Sun>=22 0:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone America/Asuncion -3:50:40 - LMT 1890 diff --git a/jdk/make/sun/javazic/tzdata/zone.tab b/jdk/make/sun/javazic/tzdata/zone.tab index ef380cd19fb..cbcdc075bf7 100644 --- a/jdk/make/sun/javazic/tzdata/zone.tab +++ b/jdk/make/sun/javazic/tzdata/zone.tab @@ -65,7 +65,6 @@ AQ -6617+11031 Antarctica/Casey Casey Station, Bailey Peninsula AQ -7824+10654 Antarctica/Vostok Vostok Station, Lake Vostok AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Station, Terre Adelie AQ -690022+0393524 Antarctica/Syowa Syowa Station, E Ongul I -AQ -5430+15857 Antarctica/Macquarie Macquarie Island Station, Macquarie Island AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF) AR -3124-06411 America/Argentina/Cordoba most locations (CB, CC, CN, ER, FM, MN, SE, SF) AR -2447-06525 America/Argentina/Salta (SA, LP, NQ, RN) @@ -81,6 +80,7 @@ AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF) AS -1416-17042 Pacific/Pago_Pago AT +4813+01620 Europe/Vienna AU -3133+15905 Australia/Lord_Howe Lord Howe Island +AU -5430+15857 Antarctica/Macquarie Macquarie Island AU -4253+14719 Australia/Hobart Tasmania - most locations AU -3956+14352 Australia/Currie Tasmania - King Island AU -3749+14458 Australia/Melbourne Victoria @@ -182,7 +182,8 @@ CW +1211-06900 America/Curacao CX -1025+10543 Indian/Christmas CY +3510+03322 Asia/Nicosia CZ +5005+01426 Europe/Prague -DE +5230+01322 Europe/Berlin +DE +5230+01322 Europe/Berlin most locations +DE +4742+00841 Europe/Busingen Busingen DJ +1136+04309 Africa/Djibouti DK +5540+01235 Europe/Copenhagen DM +1518-06124 America/Dominica @@ -364,8 +365,10 @@ RU +5345+08707 Asia/Novokuznetsk Moscow+03 - Novokuznetsk RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal RU +6200+12940 Asia/Yakutsk Moscow+06 - Lena River +RU +623923+1353314 Asia/Khandyga Moscow+06 - Tomponsky, Ust-Maysky RU +4310+13156 Asia/Vladivostok Moscow+07 - Amur River RU +4658+14242 Asia/Sakhalin Moscow+07 - Sakhalin Island +RU +643337+1431336 Asia/Ust-Nera Moscow+07 - Oymyakonsky RU +5934+15048 Asia/Magadan Moscow+08 - Magadan RU +5301+15839 Asia/Kamchatka Moscow+08 - Kamchatka RU +6445+17729 Asia/Anadyr Moscow+08 - Bering Sea diff --git a/jdk/make/sun/nio/cs/Makefile b/jdk/make/sun/nio/cs/Makefile index 73fe55fbd08..3b45c774fe0 100644 --- a/jdk/make/sun/nio/cs/Makefile +++ b/jdk/make/sun/nio/cs/Makefile @@ -87,9 +87,6 @@ build: $(FILES_genout_extcs) $(CHARSETS_JAR) # # Extra rules to build character converters. -SERVICE_DESCRIPTION = java.nio.charset.spi.CharsetProvider -SERVICE_DESCRIPTION_PATH = META-INF/services/$(SERVICE_DESCRIPTION) - GENCSDATASRC = $(BUILDDIR)/tools/CharsetMapping GENCSSRCDIR = $(BUILDDIR)/tools/src/build/tools/charsetmapping GENCSEXT = $(GENSRCDIR)/sun/nio/cs/ext @@ -118,10 +115,6 @@ $(FILES_genout_extcs): \ $(GENCSSRCDIR)/HKSCS.java $(BOOT_JAVA_CMD) -jar $(CHARSETMAPPING_JARFILE) $(GENCSDATASRC) $(GENCSEXT) dbcs -$(CLASSDESTDIR)/$(SERVICE_DESCRIPTION_PATH): \ - $(SHARE_SRC)/classes/sun/nio/cs/ext/$(SERVICE_DESCRIPTION_PATH) - $(install-file) - # no compression unless requested ifndef COMPRESS_JARS CREATE_JAR_OPTS_NOMANIFEST = cf0 @@ -129,10 +122,9 @@ else CREATE_JAR_OPTS_NOMANIFEST = cf endif -$(CHARSETS_JAR): $(FILES_class) $(CLASSDESTDIR)/$(SERVICE_DESCRIPTION_PATH) $(FILES_DAT) +$(CHARSETS_JAR): $(FILES_class) $(FILES_DAT) $(BOOT_JAR_CMD) $(CREATE_JAR_OPTS_NOMANIFEST) $(CHARSETS_JAR) \ -C $(CLASSDESTDIR) sun \ - -C $(CLASSDESTDIR) $(SERVICE_DESCRIPTION_PATH) \ $(BOOT_JAR_JFLAGS) @$(java-vm-cleanup) diff --git a/jdk/make/sun/org/mozilla/Makefile b/jdk/make/sun/org/mozilla/Makefile deleted file mode 100644 index 0805da63bda..00000000000 --- a/jdk/make/sun/org/mozilla/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. -# 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. -# - -# -# Makefile for building Mozilla JavaScript modules -# - -BUILDDIR = ../../.. -PRODUCT = org -include $(BUILDDIR)/common/Defs.gmk - -SUBDIRS = javascript -include $(BUILDDIR)/common/Subdirs.gmk - -all build clean clobber:: - $(SUBDIRS-loop) - diff --git a/jdk/make/sun/org/mozilla/javascript/Makefile b/jdk/make/sun/org/mozilla/javascript/Makefile deleted file mode 100644 index f381b94e33c..00000000000 --- a/jdk/make/sun/org/mozilla/javascript/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -# -# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - -# -# Makefile for building all of sun.org.mozilla.javascript.internal.* -# - -BUILDDIR = ../../../.. -PACKAGE = sun.org.mozilla.javascript.internal -PRODUCT = sun -include $(BUILDDIR)/common/Defs.gmk - -AUTO_FILES_JAVA_DIRS = sun/org/mozilla/javascript/internal - -RESOURCEDIR = \ - $(CLASSDESTDIR)/sun/org/mozilla/javascript/internal/resources - -FILES_copy = \ - $(RESOURCEDIR)/Messages.properties \ - $(RESOURCEDIR)/Messages_fr.properties - -# -# Rules -# - -include $(BUILDDIR)/common/Classes.gmk - -all: classes copy-files - -# -# Copy resource messages file for Rhino JavaScript interpreter -# - -copy-files: $(FILES_copy) - -$(RESOURCEDIR)/%: $(CLOSED_SRC)/share/classes/sun/org/mozilla/javascript/internal/resources/% - $(install-file) - -.PHONY: copy-files - -clean clobber:: - $(RM) -rf $(CLASSDESTDIR)/sun/org/mozilla/javascript diff --git a/jdk/make/sun/security/Makefile b/jdk/make/sun/security/Makefile index 9e9f8c50d36..0a1a7aa7265 100644 --- a/jdk/make/sun/security/Makefile +++ b/jdk/make/sun/security/Makefile @@ -38,12 +38,10 @@ SUBDIRS_MAKEFLAGS += JAVAC_MAX_WARNINGS=true SUBDIRS_MAKEFLAGS += JAVAC_WARNINGS_FATAL=true include $(BUILDDIR)/common/Defs.gmk -# build sun/security/jgss/wrapper on non-windows non-macosx platforms +# build sun/security/jgss/wrapper on non-windows platforms JGSS_WRAPPER = ifneq ($(PLATFORM), windows) - ifneq ($(PLATFORM), macosx) - JGSS_WRAPPER = jgss/wrapper - endif + JGSS_WRAPPER = jgss/wrapper endif # Build PKCS#11 on all platforms diff --git a/jdk/make/sun/security/ec/Makefile b/jdk/make/sun/security/ec/Makefile index f04ec0eec17..bceb031ad0a 100644 --- a/jdk/make/sun/security/ec/Makefile +++ b/jdk/make/sun/security/ec/Makefile @@ -124,15 +124,6 @@ CLASSDESTDIR = $(TEMPDIR)/classes # AUTO_FILES_JAVA_DIRS = $(PKGDIR) -# -# Exclude the sources that get built by ../other/Makefile -# -AUTO_JAVA_PRUNE = \ - ECParameters.java \ - ECPrivateKeyImpl.java \ - ECPublicKeyImpl.java \ - NamedCurve.java - # # Some licensees do not get the native ECC sources, but we still need to # be able to build "all" for them. Check here to see if the sources are diff --git a/jdk/make/sun/security/other/Makefile b/jdk/make/sun/security/other/Makefile index 5a3d9b04c95..cb62c983c9e 100644 --- a/jdk/make/sun/security/other/Makefile +++ b/jdk/make/sun/security/other/Makefile @@ -49,15 +49,6 @@ AUTO_FILES_JAVA_DIRS = \ sun/security/x509 \ com/sun/net/ssl/internal/ssl -# -# EC classes used by the packages above -# -FILES_java += \ - sun/security/ec/ECParameters.java \ - sun/security/ec/ECPrivateKeyImpl.java \ - sun/security/ec/ECPublicKeyImpl.java \ - sun/security/ec/NamedCurve.java - # # Rules # diff --git a/jdk/make/tools/src/build/tools/cldrconverter/CLDRConverter.java b/jdk/make/tools/src/build/tools/cldrconverter/CLDRConverter.java index f1185f18978..9cbf02a9c3b 100644 --- a/jdk/make/tools/src/build/tools/cldrconverter/CLDRConverter.java +++ b/jdk/make/tools/src/build/tools/cldrconverter/CLDRConverter.java @@ -34,6 +34,8 @@ import java.nio.file.Path; import java.util.*; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; /** @@ -234,6 +236,17 @@ public class CLDRConverter { } } + /** + * Configure the parser to allow access to DTDs on the file system. + */ + private static void enableFileAccess(SAXParser parser) throws SAXNotSupportedException { + try { + parser.setProperty("http://javax.xml.XMLConstants/property/accessExternalDTD", "file"); + } catch (SAXNotRecognizedException ignore) { + // property requires >= JAXP 1.5 + } + } + private static List readBundleList() throws Exception { ResourceBundle.Control defCon = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT); List retList = new ArrayList<>(); @@ -279,6 +292,7 @@ public class CLDRConverter { SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setValidating(true); SAXParser parser = factory.newSAXParser(); + enableFileAccess(parser); LDMLParseHandler handler = new LDMLParseHandler(id); File file = new File(SOURCE_FILE_DIR + File.separator + id + ".xml"); if (!file.exists()) { @@ -314,6 +328,7 @@ public class CLDRConverter { SAXParserFactory factorySuppl = SAXParserFactory.newInstance(); factorySuppl.setValidating(true); SAXParser parserSuppl = factorySuppl.newSAXParser(); + enableFileAccess(parserSuppl); handlerSuppl = new SupplementDataParseHandler(); File fileSupply = new File(SPPL_SOURCE_FILE); parserSuppl.parse(fileSupply, handlerSuppl); @@ -322,6 +337,7 @@ public class CLDRConverter { SAXParserFactory numberingParser = SAXParserFactory.newInstance(); numberingParser.setValidating(true); SAXParser parserNumbering = numberingParser.newSAXParser(); + enableFileAccess(parserNumbering); handlerNumbering = new NumberingSystemsParseHandler(); File fileNumbering = new File(NUMBERING_SOURCE_FILE); parserNumbering.parse(fileNumbering, handlerNumbering); @@ -330,6 +346,7 @@ public class CLDRConverter { SAXParserFactory metazonesParser = SAXParserFactory.newInstance(); metazonesParser.setValidating(true); SAXParser parserMetaZones = metazonesParser.newSAXParser(); + enableFileAccess(parserMetaZones); handlerMetaZones = new MetaZonesParseHandler(); File fileMetaZones = new File(METAZONES_SOURCE_FILE); parserNumbering.parse(fileMetaZones, handlerMetaZones); diff --git a/jdk/make/tools/src/build/tools/deps/refs.allowed b/jdk/make/tools/src/build/tools/deps/refs.allowed index ef1bec7bbcd..7c15a04d91b 100644 --- a/jdk/make/tools/src/build/tools/deps/refs.allowed +++ b/jdk/make/tools/src/build/tools/deps/refs.allowed @@ -30,7 +30,5 @@ sun.security.krb5.Realm=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,comp # Residual references to java.beans. # The RemoveMethods tool does not yet purge the constant pool. -# Rhino is due to be replaced so not worth addressing this dependency now. # -java.beans.PropertyChangeListener=java.util.logging.LogManager,sun.org.mozilla.javascript.internal.Context,compact1,compact2,compact3 -java.beans.PropertyChangeEvent=sun.org.mozilla.javascript.internal.Context,compact3 +java.beans.PropertyChangeListener=java.util.logging.LogManager,compact1,compact2,compact3 diff --git a/jdk/makefiles/CompileDemos.gmk b/jdk/makefiles/CompileDemos.gmk index f61d9404020..0a093b586a9 100644 --- a/jdk/makefiles/CompileDemos.gmk +++ b/jdk/makefiles/CompileDemos.gmk @@ -1,3 +1,4 @@ + # # Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -432,20 +433,22 @@ endif ################################################################################################## ifndef OPENJDK - DB_DEMO_ZIPFILE := $(wildcard $(JDK_TOPDIR)/src/closed/share/db/*demo*.zip) + DB_DEMO_ZIPFILE := $(wildcard $(JDK_TOPDIR)/src/closed/share/db/*.zip) $(JDK_OUTPUTDIR)/demo/_the.db.unzipped: $(DB_DEMO_ZIPFILE) $(MKDIR) -p $(@D) $(RM) -r $(JDK_OUTPUTDIR)/demo/db $(JDK_OUTPUTDIR)/demo/demo $(CD) $(JDK_OUTPUTDIR)/demo && $(UNZIP) -q -o $< - $(MV) $(JDK_OUTPUTDIR)/demo/demo $(JDK_OUTPUTDIR)/demo/db + $(MV) $(JDK_OUTPUTDIR)/demo/db-derby-*-bin/demo $(JDK_OUTPUTDIR)/demo/db + $(CD) $(JDK_OUTPUTDIR)/demo && $(RM) -r db-derby-*-bin $(TOUCH) $@ # Copy this after the unzip above to avoid race with directory creation and mv command. $(JDK_OUTPUTDIR)/demo/db/README-JDK-DEMOS.html: \ $(JDK_TOPDIR)/src/closed/share/db/README-JDK-DEMOS.html \ | $(JDK_OUTPUTDIR)/demo/_the.db.unzipped - $(call install-file) + $(MKDIR) -p $(@D) + $(CAT) $< | $(SED) "s/XXXX/$(shell cat $(JDK_TOPDIR)/src/closed/share/db/COPYRIGHTYEAR)/" > $@ BUILD_DEMOS += $(JDK_OUTPUTDIR)/demo/_the.db.unzipped $(JDK_OUTPUTDIR)/demo/db/README-JDK-DEMOS.html endif diff --git a/jdk/makefiles/CompileLaunchers.gmk b/jdk/makefiles/CompileLaunchers.gmk index 7ecad956fbb..0621f4ce38b 100644 --- a/jdk/makefiles/CompileLaunchers.gmk +++ b/jdk/makefiles/CompileLaunchers.gmk @@ -472,6 +472,7 @@ $(eval $(call SetupNativeCompilation,BUILD_UNPACKEXE,\ -D "JDK_FNAME=unpack200.exe" \ -D "JDK_INTERNAL_NAME=unpack200" \ -D "JDK_FTYPE=0x1L",\ + DEBUG_SYMBOLS:=true,\ MANIFEST:=$(JDK_TOPDIR)/src/windows/resource/unpack200_proto.exe.manifest)) ifeq ($(OPENJDK_TARGET_OS),windows) @@ -555,6 +556,7 @@ ifneq ($(BUILD_JEXEC_SRC),) $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)), \ OBJECT_DIR:=$(JDK_OUTPUTDIR)/objs/jexec_obj,\ OUTPUT_DIR:=$(BUILD_JEXEC_DST_DIR),\ + DEBUG_SYMBOLS:=true,\ PROGRAM:=jexec)) BUILD_LAUNCHERS += $(BUILD_JEXEC) diff --git a/jdk/makefiles/CompileNativeLibraries.gmk b/jdk/makefiles/CompileNativeLibraries.gmk index bb30367c276..1836cbb13f9 100644 --- a/jdk/makefiles/CompileNativeLibraries.gmk +++ b/jdk/makefiles/CompileNativeLibraries.gmk @@ -2560,7 +2560,6 @@ BUILD_LIBRARIES += $(BUILD_LIBJ2PCSC) ########################################################################################## ifneq ($(OPENJDK_TARGET_OS), windows) -ifneq ($(OPENJDK_TARGET_OS), macosx) $(eval $(call SetupNativeCompilation,BUILD_LIBJ2GSS,\ LIBRARY:=j2gss,\ OUTPUT_DIR:=$(INSTALL_LIBRARIES_HERE),\ @@ -2581,7 +2580,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJ2GSS,\ BUILD_LIBRARIES += $(BUILD_LIBJ2GSS) endif -endif ########################################################################################## diff --git a/jdk/makefiles/CopyFiles.gmk b/jdk/makefiles/CopyFiles.gmk index ab3a360daaf..272fd1f28b6 100644 --- a/jdk/makefiles/CopyFiles.gmk +++ b/jdk/makefiles/CopyFiles.gmk @@ -458,24 +458,6 @@ endif # OPENJDK ifndef OPENJDK -JS_RESOURCES_FILES := Messages.properties Messages_fr.properties -JS_RESOURCES_SRC_DIR := $(JDK_TOPDIR)/src/closed/share/classes/sun/org/mozilla/javascript/internal/resources -JS_RESOURCES_DST_DIR := $(JDK_OUTPUTDIR)/classes/sun/org/mozilla/javascript/internal/resources - -JS_RESOURCES_SRC := $(foreach F,$(JS_RESOURCES_FILES),$(JS_RESOURCES_SRC_DIR)/$(F)) -JS_RESOURCES_DST := $(foreach F,$(JS_RESOURCES_FILES),$(JS_RESOURCES_DST_DIR)/$(F)) - -$(JS_RESOURCES_DST_DIR)/% : $(JS_RESOURCES_SRC_DIR)/% - $(call install-file) - -COPY_FILES += $(JS_RESOURCES_DST) - -endif - -########################################################################################## - -ifndef OPENJDK - # # Solaris X11 Direct Graphics Access library # diff --git a/jdk/makefiles/CopyIntoClasses.gmk b/jdk/makefiles/CopyIntoClasses.gmk index 8b5a1cd0a3f..88ab3c48e42 100644 --- a/jdk/makefiles/CopyIntoClasses.gmk +++ b/jdk/makefiles/CopyIntoClasses.gmk @@ -172,10 +172,6 @@ ifneq ($(ALL_META-INF_DIRS_targetapi),) else ALL_META-INF_DIRS:=$(ALL_META-INF_DIRS_share) endif -# Filter out META-INF dirs that shouldn't be included -ifdef OPENJDK - ALL_META-INF_DIRS:=$(filter-out %com/sun/script/javascript/META-INF,$(ALL_META-INF_DIRS)) -endif ifndef OPENJDK ALL_META-INF_DIRS += $(JDK_TOPDIR)/src/closed/share/classes/sun/java2d/cmm/kcms/META-INF diff --git a/jdk/makefiles/CreateJars.gmk b/jdk/makefiles/CreateJars.gmk index 8127b054459..3225a862653 100644 --- a/jdk/makefiles/CreateJars.gmk +++ b/jdk/makefiles/CreateJars.gmk @@ -201,7 +201,6 @@ RT_JAR_EXCLUDES += \ META-INF/services/com.sun.jdi.connect.spi.TransportService \ META-INF/services/com.sun.tools.attach.spi.AttachProvider \ META-INF/services/com.sun.tools.xjc.Plugin \ - META-INF/services/java.nio.charset.spi.CharsetProvider \ META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor \ org/relaxng/datatype \ sun/awt/HKSCS.class \ @@ -217,19 +216,7 @@ RT_JAR_EXCLUDES += \ sun/net/spi/nameservice/dns \ sun/nio/cs/ext \ sun/rmi/rmic \ - sun/security/ec/ECDHKeyAgreement.class \ - sun/security/ec/ECDSASignature.class \ - sun/security/ec/ECDSASignature\$$$$Raw.class \ - sun/security/ec/ECDSASignature\$$$$SHA1.class \ - sun/security/ec/ECDSASignature\$$$$SHA224.class \ - sun/security/ec/ECDSASignature\$$$$SHA256.class \ - sun/security/ec/ECDSASignature\$$$$SHA384.class \ - sun/security/ec/ECDSASignature\$$$$SHA512.class \ - sun/security/ec/ECKeyFactory.class \ - sun/security/ec/ECKeyPairGenerator.class \ - sun/security/ec/SunEC\$$$$1.class \ - sun/security/ec/SunEC.class \ - sun/security/ec/SunECEntries.class \ + sun/security/ec \ sun/security/internal \ sun/security/mscapi \ sun/security/pkcs11 \ @@ -428,8 +415,7 @@ $(eval $(call SetupArchive,BUILD_CHARSETS_JAR,,\ SUFFIXES:=.class .dat,\ INCLUDES:=sun/nio/cs/ext,\ EXTRA_FILES := sun/awt/HKSCS.class \ - $(CHARSETS_EXTRA_FILES) \ - META-INF/services/java.nio.charset.spi.CharsetProvider, \ + $(CHARSETS_EXTRA_FILES), \ JAR:=$(IMAGES_OUTPUTDIR)/lib/charsets.jar, \ SKIP_METAINF := true, \ CHECK_COMPRESS_JAR:=true)) diff --git a/jdk/makefiles/GensrcSwing.gmk b/jdk/makefiles/GensrcSwing.gmk index f5741ae5f46..5350c143b73 100644 --- a/jdk/makefiles/GensrcSwing.gmk +++ b/jdk/makefiles/GensrcSwing.gmk @@ -68,10 +68,17 @@ BEANS_SRC = $(BEANS:%=$(JDK_TOPDIR)/src/share/classes/javax/swing/%.java) \ # Dummy variable so far, in the old build system it was false by default SWINGBEAN_DEBUG_FLAG = false # GenDocletBeanInfo is compiled in Tools.gmk and picks up from $(JDK_OUTPUTDIR)/btclasses -$(JDK_OUTPUTDIR)/gensrc_no_srczip/_the.generated_beaninfo: $(BEANS_SRC) $(JDK_OUTPUTDIR)/gensrc_no_srczip/javax/swing/SwingBeanInfoBase.java $(JDK_OUTPUTDIR)/gensrc/sun/swing/BeanInfoUtils.java $(BUILD_TOOLS) +# LocaleDataMetaInfo needs to be generated before running this to avoid confusing errors +# in the build log. +$(JDK_OUTPUTDIR)/gensrc_no_srczip/_the.generated_beaninfo: $(BEANS_SRC) \ + $(JDK_OUTPUTDIR)/gensrc_no_srczip/javax/swing/SwingBeanInfoBase.java \ + $(JDK_OUTPUTDIR)/gensrc/sun/swing/BeanInfoUtils.java $(BUILD_TOOLS) \ + | $(GENSRC_LOCALEDATAMETAINFO) $(ECHO) Generating beaninfo $(MKDIR) -p $(JDK_OUTPUTDIR)/gensrc_no_srczip/javax/swing - $(JAVA) -Djava.awt.headless=true $(NEW_JAVADOC) -doclet GenDocletBeanInfo \ + $(JAVA) -Djava.awt.headless=true $(NEW_JAVADOC) \ + -sourcepath "$(JDK_TOPDIR)/src/share/classes$(PATH_SEP)$(JDK_OUTPUTDIR)/gensrc" \ + -doclet GenDocletBeanInfo \ -x $(SWINGBEAN_DEBUG_FLAG) -d $(JDK_OUTPUTDIR)/gensrc_no_srczip/javax/swing \ -t $(DOCLETSRC_DIR)/SwingBeanInfo.template -docletpath $(JDK_OUTPUTDIR)/btclasses \ -XDignore.symbol.file=true \ diff --git a/jdk/makefiles/Images.gmk b/jdk/makefiles/Images.gmk index 2dde16fdf66..a1db8b9a148 100644 --- a/jdk/makefiles/Images.gmk +++ b/jdk/makefiles/Images.gmk @@ -352,11 +352,8 @@ ifneq ($(OPENJDK_TARGET_OS),windows) JDK_MAN_PAGES += jvisualvm.1 endif - ifndef OPENJDK - MAN_SRC_BASEDIR:=$(JDK_TOPDIR)/src/closed - else - MAN_SRC_BASEDIR:=$(JDK_TOPDIR)/src - endif + # This variable is potentially overridden in the closed makefile. + MAN_SRC_BASEDIR ?= $(JDK_TOPDIR)/src ifeq ($(OPENJDK_TARGET_OS), linux) MAN_SRC_DIR:=$(MAN_SRC_BASEDIR)/linux/doc @@ -532,17 +529,22 @@ ifndef OPENJDK $(IMAGES_OUTPUTDIR)/_unzip/%.unzipped: $(JDK_TOPDIR)/src/closed/share/db/% $(ECHO) Unzipping $(patsubst $(SRC_ROOT)/%,%,$<) $(MKDIR) -p $(JDK_IMAGE_DIR)/db - cd $(JDK_IMAGE_DIR)/db && $(UNZIP) -q -o $< -x index.html 2> /dev/null + cd $(JDK_IMAGE_DIR)/db && $(UNZIP) -q -o $< -x */index.html */KEYS */test/* *javadoc/* */docs/* */demo/* 2> /dev/null + cd $(JDK_IMAGE_DIR)/db && $(MV) db-derby-*-bin/* . && $(RM) -r db-derby-*-bin $(MKDIR) -p $(@D) $(TOUCH) $@ $(JDK_IMAGE_DIR)/db/README-JDK.html: $(JDK_TOPDIR)/src/closed/share/db/README-JDK.html $(ECHO) $(LOG_INFO) Copying '$(patsubst $(OUTPUT_ROOT)/%,%,$@)' - $(install-file) + $(CAT) $< | $(SED) "s/XXXX/$(shell cat $(JDK_TOPDIR)/src/closed/share/db/COPYRIGHTYEAR)/" > $@ + + $(JDK_IMAGE_DIR)/db/3RDPARTY: $(JDK_TOPDIR)/src/closed/share/db/3RDPARTY + $(ECHO) $(LOG_INFO) Copying '$(patsubst $(OUTPUT_ROOT)/%,%,$@)' + $(CAT) $< | $(SED) "s/XXXX/$(shell cat $(JDK_TOPDIR)/src/closed/share/db/COPYRIGHTYEAR)/" > $@ JDK_DB_TARGETS := $(patsubst $(JDK_TOPDIR)/src/closed/share/db/%,$(IMAGES_OUTPUTDIR)/_unzip/%.unzipped,\ - $(call not-containing,demo,$(wildcard $(JDK_TOPDIR)/src/closed/share/db/*.zip))) \ - $(JDK_IMAGE_DIR)/db/README-JDK.html + $(wildcard $(JDK_TOPDIR)/src/closed/share/db/*.zip)) \ + $(JDK_IMAGE_DIR)/db/README-JDK.html $(JDK_IMAGE_DIR)/db/3RDPARTY endif diff --git a/jdk/makefiles/mapfiles/libawt/mapfile-vers b/jdk/makefiles/mapfiles/libawt/mapfile-vers index 924a2827a99..8af9d14dd57 100644 --- a/jdk/makefiles/mapfiles/libawt/mapfile-vers +++ b/jdk/makefiles/mapfiles/libawt/mapfile-vers @@ -86,6 +86,7 @@ SUNWprivate_1.1 { Java_sun_java2d_pipe_ShapeSpanIterator_setRule; Java_sun_java2d_pipe_ShapeSpanIterator_skipDownTo; + Java_java_awt_Choice_initIDs; Java_java_awt_Dimension_initIDs; Java_java_awt_event_MouseEvent_initIDs; Java_java_awt_image_DataBufferInt_initIDs; diff --git a/jdk/makefiles/mapfiles/libawt/mapfile-vers-linux b/jdk/makefiles/mapfiles/libawt/mapfile-vers-linux index 2514670ea3e..b0bfb1ca91a 100644 --- a/jdk/makefiles/mapfiles/libawt/mapfile-vers-linux +++ b/jdk/makefiles/mapfiles/libawt/mapfile-vers-linux @@ -86,6 +86,7 @@ SUNWprivate_1.1 { Java_sun_java2d_pipe_ShapeSpanIterator_setRule; Java_sun_java2d_pipe_ShapeSpanIterator_skipDownTo; + Java_java_awt_Choice_initIDs; Java_java_awt_Dimension_initIDs; Java_java_awt_event_MouseEvent_initIDs; Java_java_awt_image_DataBufferInt_initIDs; diff --git a/jdk/makefiles/profile-rtjar-includes.txt b/jdk/makefiles/profile-rtjar-includes.txt index a90af142db1..d740e01abe8 100644 --- a/jdk/makefiles/profile-rtjar-includes.txt +++ b/jdk/makefiles/profile-rtjar-includes.txt @@ -57,6 +57,7 @@ PROFILE_1_RTJAR_INCLUDE_PACKAGES := \ java/time \ java/util \ javax/net \ + javax/script \ javax/security \ jdk \ sun/invoke \ @@ -111,7 +112,6 @@ PROFILE_3_RTJAR_INCLUDE_PACKAGES := \ com/sun/nio/sctp \ com/sun/org/apache/xml/internal/security \ com/sun/rowset \ - com/sun/script \ com/sun/security/auth \ com/sun/security/jgss \ com/sun/security/ntlm \ @@ -125,7 +125,6 @@ PROFILE_3_RTJAR_INCLUDE_PACKAGES := \ javax/lang/model \ javax/management \ javax/naming \ - javax/script \ javax/security/auth/kerberos \ javax/security/sasl \ javax/smartcardio \ @@ -140,7 +139,6 @@ PROFILE_3_RTJAR_INCLUDE_PACKAGES := \ sun/net/www/protocol/http/ntlm \ sun/net/www/protocol/http/spnego \ sun/nio/ch/sctp \ - sun/org/mozilla \ sun/security/acl \ sun/security/jgss \ sun/security/krb5 \ @@ -161,10 +159,6 @@ PROFILE_3_RTJAR_EXCLUDE_TYPES := \ javax/management/remote/rmi/_RMIServerImpl_Tie.class \ javax/management/remote/rmi/_RMIServer_Stub.class -PROFILE_3_INCLUDE_METAINF_SERVICES := \ - META-INF/services/javax.script.ScriptEngineFactory - - FULL_JRE_RTJAR_INCLUDE_PACKAGES := \ com/oracle \ com/sun/accessibility/internal/resources \ diff --git a/jdk/src/macosx/classes/sun/lwawt/LWScrollBarPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWScrollBarPeer.java index dff48a4caa3..f5cb0d576e6 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWScrollBarPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWScrollBarPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,6 +56,8 @@ final class LWScrollBarPeer extends LWComponentPeer void initializeImpl() { super.initializeImpl(); final Scrollbar target = getTarget(); + setLineIncrement(target.getUnitIncrement()); + setPageIncrement(target.getBlockIncrement()); setValues(target.getValue(), target.getVisibleAmount(), target.getMinimum(), target.getMaximum()); diff --git a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java index cad6e4353ba..6ff3530db76 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java @@ -53,7 +53,12 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { private Clipboard clipboard; private MouseInfoPeer mouseInfoPeer; - public LWToolkit() { + /** + * Dynamic Layout Resize client code setting. + */ + private volatile boolean dynamicLayoutSetting = true; + + protected LWToolkit() { } /* @@ -561,4 +566,37 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { ((LWWindowPeer)w.getPeer()).ungrab(false); } } + + @Override + protected final Object lazilyLoadDesktopProperty(final String name) { + if (name.equals("awt.dynamicLayoutSupported")) { + return isDynamicLayoutSupported(); + } + return super.lazilyLoadDesktopProperty(name); + } + + @Override + public final void setDynamicLayout(final boolean dynamic) { + dynamicLayoutSetting = dynamic; + } + + @Override + protected final boolean isDynamicLayoutSet() { + return dynamicLayoutSetting; + } + + @Override + public final boolean isDynamicLayoutActive() { + // "Live resizing" is active by default and user's data is ignored. + return isDynamicLayoutSupported(); + } + + /** + * Returns true if dynamic layout of Containers on resize is supported by + * the underlying operating system and/or window manager. + */ + protected final boolean isDynamicLayoutSupported() { + // "Live resizing" is supported by default. + return true; + } } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java index 791182c1565..e198024dd0c 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java @@ -35,6 +35,7 @@ import java.security.PrivilegedAction; import javax.print.*; import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.HashPrintRequestAttributeSet; import sun.java2d.*; import sun.print.*; @@ -96,6 +97,14 @@ public class CPrinterJob extends RasterPrinterJob { return false; } + if (attributes == null) { + attributes = new HashPrintRequestAttributeSet(); + } + + if (getPrintService() instanceof StreamPrintService) { + return super.printDialog(attributes); + } + return jobSetup(getPageable(), checkAllowedToPrintToFile()); } @@ -130,6 +139,10 @@ public class CPrinterJob extends RasterPrinterJob { return page; } + if (getPrintService() instanceof StreamPrintService) { + return super.pageDialog(page); + } + PageFormat pageClone = (PageFormat) page.clone(); boolean doIt = pageSetup(pageClone, null); return doIt ? pageClone : page; diff --git a/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m b/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m index 6e9fbbca5ab..d12908c83a3 100644 --- a/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m +++ b/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #import "LWCToolkit.h" #import +#import @implementation AWTSurfaceLayers @@ -74,14 +75,12 @@ } - (void) setBounds:(CGRect)rect { - layer.anchorPoint = CGPointMake(0, 0); - // translates values to the coordinate system of the "root" layer - CGFloat newY = windowLayer.bounds.size.height - rect.origin.y - rect.size.height; - CGRect newRect = CGRectMake(rect.origin.x, newY, rect.size.width, rect.size.height); - - layer.frame = newRect; - + rect.origin.y = windowLayer.bounds.size.height - rect.origin.y - rect.size.height; + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + layer.frame = rect; + [CATransaction commit]; [AWTSurfaceLayers repaintLayersRecursively:layer]; } diff --git a/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m b/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m index e0074eb4ef3..f300ea404c4 100644 --- a/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m +++ b/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,11 +64,13 @@ AWT_ASSERT_APPKIT_THREAD; //Disable CALayer's default animation NSMutableDictionary * actions = [[NSMutableDictionary alloc] initWithObjectsAndKeys: + [NSNull null], @"anchorPoint", [NSNull null], @"bounds", [NSNull null], @"contents", [NSNull null], @"contentsScale", [NSNull null], @"onOrderIn", [NSNull null], @"onOrderOut", + [NSNull null], @"position", [NSNull null], @"sublayers", nil]; self.actions = actions; diff --git a/jdk/src/share/bin/java.c b/jdk/src/share/bin/java.c index f08a52a9db2..73c532676b3 100644 --- a/jdk/src/share/bin/java.c +++ b/jdk/src/share/bin/java.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,12 +149,15 @@ static int KnownVMIndex(const char* name); static void FreeKnownVMs(); static jboolean IsWildCardEnabled(); -#define ARG_CHECK(n, f, a) if (n < 1) { \ - JLI_ReportErrorMessage(f, a); \ - printUsage = JNI_TRUE; \ - *pret = 1; \ - return JNI_TRUE; \ -} +#define ARG_CHECK(AC_arg_count, AC_failure_message, AC_questionable_arg) \ + do { \ + if (AC_arg_count < 1) { \ + JLI_ReportErrorMessage(AC_failure_message, AC_questionable_arg); \ + printUsage = JNI_TRUE; \ + *pret = 1; \ + return JNI_TRUE; \ + } \ + } while (JNI_FALSE) /* * Running Java code in primordial thread caused many problems. We will @@ -310,29 +313,37 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ * mainThread.isAlive() to work as expected. */ #define LEAVE() \ - if ((*vm)->DetachCurrentThread(vm) != 0) { \ - JLI_ReportErrorMessage(JVM_ERROR2); \ - ret = 1; \ - } \ - (*vm)->DestroyJavaVM(vm); \ - return ret \ + do { \ + if ((*vm)->DetachCurrentThread(vm) != JNI_OK) { \ + JLI_ReportErrorMessage(JVM_ERROR2); \ + ret = 1; \ + } \ + if (JNI_TRUE) { \ + (*vm)->DestroyJavaVM(vm); \ + return ret; \ + } \ + } while (JNI_FALSE) -#define CHECK_EXCEPTION_NULL_LEAVE(e) \ - if ((*env)->ExceptionOccurred(env)) { \ - JLI_ReportExceptionDescription(env); \ - LEAVE(); \ - } \ - if ((e) == NULL) { \ - JLI_ReportErrorMessage(JNI_ERROR); \ - LEAVE(); \ - } +#define CHECK_EXCEPTION_NULL_LEAVE(CENL_exception) \ + do { \ + if ((*env)->ExceptionOccurred(env)) { \ + JLI_ReportExceptionDescription(env); \ + LEAVE(); \ + } \ + if ((CENL_exception) == NULL) { \ + JLI_ReportErrorMessage(JNI_ERROR); \ + LEAVE(); \ + } \ + } while (JNI_FALSE) -#define CHECK_EXCEPTION_LEAVE(rv) \ - if ((*env)->ExceptionOccurred(env)) { \ - JLI_ReportExceptionDescription(env); \ - ret = (rv); \ - LEAVE(); \ - } +#define CHECK_EXCEPTION_LEAVE(CEL_return_value) \ + do { \ + if ((*env)->ExceptionOccurred(env)) { \ + JLI_ReportExceptionDescription(env); \ + ret = (CEL_return_value); \ + LEAVE(); \ + } \ + } while (JNI_FALSE) int JNICALL JavaMain(void * _args) @@ -434,7 +445,7 @@ JavaMain(void * _args) * consistent in the UI we need to track and report the application main class. */ appClass = GetApplicationClass(env); - NULL_CHECK(appClass); + NULL_CHECK_RETURN_VALUE(appClass, -1); /* * PostJVMInit uses the class name as the application name for GUI purposes, * for example, on OSX this sets the application name in the menu bar for diff --git a/jdk/src/share/bin/java.h b/jdk/src/share/bin/java.h index ad1a1ff90e0..83e97e60d9c 100644 --- a/jdk/src/share/bin/java.h +++ b/jdk/src/share/bin/java.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -242,14 +242,18 @@ typedef struct { InvocationFunctions ifn; } JavaMainArgs; -#define NULL_CHECK0(e) if ((e) == 0) { \ - JLI_ReportErrorMessage(JNI_ERROR); \ - return 0; \ - } +#define NULL_CHECK_RETURN_VALUE(NCRV_check_pointer, NCRV_return_value) \ + do { \ + if ((NCRV_check_pointer) == NULL) { \ + JLI_ReportErrorMessage(JNI_ERROR); \ + return NCRV_return_value; \ + } \ + } while (JNI_FALSE) -#define NULL_CHECK(e) if ((e) == 0) { \ - JLI_ReportErrorMessage(JNI_ERROR); \ - return; \ - } +#define NULL_CHECK0(NC0_check_pointer) \ + NULL_CHECK_RETURN_VALUE(NC0_check_pointer, 0) + +#define NULL_CHECK(NC_check_pointer) \ + NULL_CHECK_RETURN_VALUE(NC_check_pointer, ) #endif /* _JAVA_H_ */ diff --git a/jdk/src/share/bin/wildcard.c b/jdk/src/share/bin/wildcard.c index f8f664450e3..96dac738aa0 100644 --- a/jdk/src/share/bin/wildcard.c +++ b/jdk/src/share/bin/wildcard.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -136,8 +136,10 @@ WildcardIterator_for(const char *wildcard) { WildcardIterator it = NEW_(WildcardIterator); HANDLE handle = FindFirstFile(wildcard, &find_data); - if (handle == INVALID_HANDLE_VALUE) + if (handle == INVALID_HANDLE_VALUE) { + JLI_MemFree(it); return NULL; + } it->handle = handle; it->firstFile = find_data.cFileName; return it; diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java index d281e11c8c8..0fbdefb8e0e 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java @@ -790,16 +790,12 @@ public class GIFImageReader extends ImageReader { } private void startPass(int pass) { - if (updateListeners == null) { + if (updateListeners == null || !imageMetadata.interlaceFlag) { return; } - int y = 0; - int yStep = 1; - if (imageMetadata.interlaceFlag) { - y = interlaceOffset[interlacePass]; - yStep = interlaceIncrement[interlacePass]; - } + int y = interlaceOffset[interlacePass]; + int yStep = interlaceIncrement[interlacePass]; int[] vals = ReaderUtil. computeUpdatedPixels(sourceRegion, diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java index a6033c97b14..19a7a08598e 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java @@ -99,6 +99,7 @@ class Attribute implements Comparable { return this == def.canon; } + @Override public int compareTo(Attribute that) { return this.def.compareTo(that.def); } @@ -212,20 +213,20 @@ class Attribute implements Comparable { // Metadata. // // We define metadata using similar layouts - // for all five kinds of metadata attributes. + // for all five kinds of metadata attributes and 2 type metadata attributes // // Regular annotations are a counted list of [RSHNH[RUH(1)]][...] // pack.method.attribute.RuntimeVisibleAnnotations=[NH[(1)]][RSHNH[RUH(1)]][TB...] // // Parameter annotations are a counted list of regular annotations. - // pack.method.attribute.RuntimeVisibleParameterAnnotations=[NH[(1)]][NH[(1)]][RSHNH[RUH(1)]][TB...] + // pack.method.attribute.RuntimeVisibleParameterAnnotations=[NB[(1)]][NH[(1)]][RSHNH[RUH(1)]][TB...] // // RuntimeInvisible annotations are defined similarly... // Non-method annotations are defined similarly... // // Annotation are a simple tagged value [TB...] // pack.attribute.method.AnnotationDefault=[TB...] - // + static { String mdLayouts[] = { Attribute.normalizeLayoutString @@ -238,6 +239,9 @@ class Attribute implements Comparable { +"\n # annotations :=" +"\n [ NH[(1)] ] # forward call to annotation" +"\n " + ), + Attribute.normalizeLayoutString + ("" +"\n # annotation :=" +"\n [RSH" +"\n NH[RUH (1)] # forward call to value" @@ -259,24 +263,67 @@ class Attribute implements Comparable { +"\n ()[] ]" ) }; + /* + * RuntimeVisibleTypeAnnotation and RuntimeInvisibleTypeAnnotatation are + * similar to RuntimeVisibleAnnotation and RuntimeInvisibleAnnotation, + * a type-annotation union and a type-path structure precedes the + * annotation structure + */ + String typeLayouts[] = { + Attribute.normalizeLayoutString + ("" + +"\n # type-annotations :=" + +"\n [ NH[(1)(2)(3)] ] # forward call to type-annotations" + ), + Attribute.normalizeLayoutString + ( "" + +"\n # type-annotation :=" + +"\n [TB" + +"\n (0-1) [B] # {CLASS, METHOD}_TYPE_PARAMETER" + +"\n (16) [FH] # CLASS_EXTENDS" + +"\n (17-18) [BB] # {CLASS, METHOD}_TYPE_PARAMETER_BOUND" + +"\n (19-21) [] # FIELD, METHOD_RETURN, METHOD_RECEIVER" + +"\n (22) [B] # METHOD_FORMAL_PARAMETER" + +"\n (23) [H] # THROWS" + +"\n (64-65) [NH[PHOHH]] # LOCAL_VARIABLE, RESOURCE_VARIABLE" + +"\n (66) [H] # EXCEPTION_PARAMETER" + +"\n (67-70) [PH] # INSTANCEOF, NEW, {CONSTRUCTOR, METHOD}_REFERENCE_RECEIVER" + +"\n (71-75) [PHB] # CAST, {CONSTRUCTOR,METHOD}_INVOCATION_TYPE_ARGUMENT, {CONSTRUCTOR, METHOD}_REFERENCE_TYPE_ARGUMENT" + +"\n ()[] ]" + ), + Attribute.normalizeLayoutString + ("" + +"\n # type-path" + +"\n [ NB[BB] ]" + ) + }; Map sd = standardDefs; - String defaultLayout = mdLayouts[2]; - String annotationsLayout = mdLayouts[1] + mdLayouts[2]; + String defaultLayout = mdLayouts[3]; + String annotationsLayout = mdLayouts[1] + mdLayouts[2] + mdLayouts[3]; String paramsLayout = mdLayouts[0] + annotationsLayout; + String typesLayout = typeLayouts[0] + typeLayouts[1] + + typeLayouts[2] + mdLayouts[2] + mdLayouts[3]; + for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { - if (ctype == ATTR_CONTEXT_CODE) continue; - define(sd, ctype, - "RuntimeVisibleAnnotations", annotationsLayout); - define(sd, ctype, - "RuntimeInvisibleAnnotations", annotationsLayout); - if (ctype == ATTR_CONTEXT_METHOD) { + if (ctype != ATTR_CONTEXT_CODE) { define(sd, ctype, - "RuntimeVisibleParameterAnnotations", paramsLayout); + "RuntimeVisibleAnnotations", annotationsLayout); define(sd, ctype, - "RuntimeInvisibleParameterAnnotations", paramsLayout); - define(sd, ctype, - "AnnotationDefault", defaultLayout); + "RuntimeInvisibleAnnotations", annotationsLayout); + + if (ctype == ATTR_CONTEXT_METHOD) { + define(sd, ctype, + "RuntimeVisibleParameterAnnotations", paramsLayout); + define(sd, ctype, + "RuntimeInvisibleParameterAnnotations", paramsLayout); + define(sd, ctype, + "AnnotationDefault", defaultLayout); + } } + define(sd, ctype, + "RuntimeVisibleTypeAnnotations", typesLayout); + define(sd, ctype, + "RuntimeInvisibleTypeAnnotations", typesLayout); } } @@ -529,6 +576,7 @@ class Attribute implements Comparable { return canon.addContent(bytes, null); } + @Override public boolean equals(Object x) { return ( x != null) && ( x.getClass() == Layout.class ) && equals((Layout)x); @@ -538,11 +586,13 @@ class Attribute implements Comparable { && this.layout.equals(that.layout) && this.ctype == that.ctype; } + @Override public int hashCode() { return (((17 + name.hashCode()) * 37 + layout.hashCode()) * 37 + ctype); } + @Override public int compareTo(Layout that) { int r; r = this.name.compareTo(that.name); @@ -551,6 +601,7 @@ class Attribute implements Comparable { if (r != 0) return r; return this.ctype - that.ctype; } + @Override public String toString() { String str = contextName(ctype)+"."+name+"["+layout+"]"; // If -ea, print out more informative strings! @@ -698,11 +749,14 @@ class Attribute implements Comparable { // References (to a local cpMap) are embedded in the bytes. def.parse(holder, bytes, 0, bytes.length, new ValueStream() { + @Override public void putInt(int bandIndex, int value) { } + @Override public void putRef(int bandIndex, Entry ref) { refs.add(ref); } + @Override public int encodeBCI(int bci) { return bci; } @@ -716,6 +770,7 @@ class Attribute implements Comparable { return def.unparse(in, out); } + @Override public String toString() { return def +"{"+(bytes == null ? -1 : size())+"}" @@ -1309,7 +1364,7 @@ class Attribute implements Comparable { } out.putRef(bandIndex, globalRef); break; - default: assert(false); continue; + default: assert(false); } } return pos; @@ -1416,8 +1471,7 @@ class Attribute implements Comparable { int localRef; if (globalRef != null) { // It's a one-element array, really an lvalue. - fixups[0] = Fixups.add(fixups[0], null, out.size(), - Fixups.U2_FORMAT, globalRef); + fixups[0] = Fixups.addRefWithLoc(fixups[0], out.size(), globalRef); localRef = 0; // placeholder for fixups } else { localRef = 0; // fixed null value diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java index 322e2c33326..1152aa73f0c 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java @@ -48,6 +48,7 @@ import java.util.List; import java.util.Map; import java.util.jar.Pack200; import static com.sun.java.util.jar.pack.Constants.*; +import java.util.LinkedList; /** * Define the structure and ordering of "bands" in a packed file. @@ -495,6 +496,7 @@ class BandStructure { } protected int lengthForDebug = -1; // DEBUG ONLY + @Override public String toString() { // DEBUG ONLY int length = (lengthForDebug != -1 ? lengthForDebug : length()); String str = name; @@ -518,20 +520,24 @@ class BandStructure { super(name, regularCoding); } + @Override public int capacity() { return values == null ? -1 : values.length; } /** Declare predicted or needed capacity. */ + @Override protected void setCapacity(int cap) { assert(length <= cap); if (cap == -1) { values = null; return; } values = realloc(values, cap); } + @Override public int length() { return length; } + @Override protected int valuesRemainingForDebug() { return length - valuesDisbursed; } @@ -583,6 +589,7 @@ class BandStructure { return true; } + @Override protected void chooseBandCodings() throws IOException { boolean canVary = canVaryCoding(); if (!canVary || !shouldVaryCoding()) { @@ -653,6 +660,7 @@ class BandStructure { } } + @Override protected long computeOutputSize() { outputSize = getCodingChooser().computeByteSize(bandCoding, values, 0, length); @@ -668,6 +676,7 @@ class BandStructure { return regularCoding.setD(0).getLength(X); } + @Override protected void writeDataTo(OutputStream out) throws IOException { if (length == 0) return; // nothing to write long len0 = 0; @@ -691,6 +700,7 @@ class BandStructure { if (optDumpBands) dumpBand(); } + @Override protected void readDataFrom(InputStream in) throws IOException { length = valuesExpected(); if (length == 0) return; // nothing to read @@ -707,7 +717,6 @@ class BandStructure { if (XB < 0) { // Do not consume this value. No alternate coding. in.reset(); - XB = _meta_default; bandCoding = regularCoding; metaCoding = noMetaCoding; } else if (XB == _meta_default) { @@ -733,6 +742,7 @@ class BandStructure { if (optDumpBands) dumpBand(); } + @Override public void doneDisbursing() { super.doneDisbursing(); values = null; // for GC @@ -763,7 +773,10 @@ class BandStructure { /** Disburse one value. */ protected int getValue() { assert(phase() == DISBURSE_PHASE); - assert(valuesDisbursed < length); + // when debugging return a zero if lengths are zero + if (optDebugBands && length == 0 && valuesDisbursed == length) + return 0; + assert(valuesDisbursed <= length); return values[valuesDisbursed++]; } @@ -784,9 +797,11 @@ class BandStructure { super(name, BYTE1); } + @Override public int capacity() { return bytes == null ? -1 : Integer.MAX_VALUE; } + @Override protected void setCapacity(int cap) { assert(bytes == null); // do this just once bytes = new ByteArrayOutputStream(cap); @@ -796,27 +811,32 @@ class BandStructure { bytes = null; } + @Override public int length() { return bytes == null ? -1 : bytes.size(); } public void reset() { bytes.reset(); } + @Override protected int valuesRemainingForDebug() { return (bytes == null) ? -1 : ((ByteArrayInputStream)in).available(); } + @Override protected void chooseBandCodings() throws IOException { // No-op. assert(decodeEscapeValue(regularCoding.min(), regularCoding) < 0); assert(decodeEscapeValue(regularCoding.max(), regularCoding) < 0); } + @Override protected long computeOutputSize() { // do not cache return bytes.size(); } + @Override public void writeDataTo(OutputStream out) throws IOException { if (length() == 0) return; bytes.writeTo(out); @@ -834,6 +854,7 @@ class BandStructure { } } + @Override public void readDataFrom(InputStream in) throws IOException { int vex = valuesExpected(); if (vex == 0) return; @@ -852,11 +873,13 @@ class BandStructure { if (optDumpBands) dumpBand(); } + @Override public void readyToDisburse() { in = new ByteArrayInputStream(bytes.toByteArray()); super.readyToDisburse(); } + @Override public void doneDisbursing() { super.doneDisbursing(); if (optDumpBands @@ -882,11 +905,13 @@ class BandStructure { // Tap the stream. bytesForDump = new ByteArrayOutputStream(); this.in = new FilterInputStream(in) { + @Override public int read() throws IOException { int ch = in.read(); if (ch >= 0) bytesForDump.write(ch); return ch; } + @Override public int read(byte b[], int off, int len) throws IOException { int nr = in.read(b, off, len); if (nr >= 0) bytesForDump.write(b, off, nr); @@ -917,6 +942,7 @@ class BandStructure { assert(b == (b & 0xFF)); collectorStream().write(b); } + @Override public String toString() { return "byte "+super.toString(); } @@ -1184,6 +1210,7 @@ class BandStructure { super(name, regularCoding); } + @Override public Band init() { super.init(); // This is all just to keep the asserts happy: @@ -1259,12 +1286,17 @@ class BandStructure { int bandCount() { return bandCount; } private int cap = -1; + @Override public int capacity() { return cap; } + @Override public void setCapacity(int cap) { this.cap = cap; } + @Override public int length() { return 0; } + @Override public int valuesRemainingForDebug() { return 0; } + @Override protected void chooseBandCodings() throws IOException { // coding decision pass for (int i = 0; i < bandCount; i++) { @@ -1273,6 +1305,7 @@ class BandStructure { } } + @Override protected long computeOutputSize() { // coding decision pass long sum = 0; @@ -1286,6 +1319,7 @@ class BandStructure { return sum; } + @Override protected void writeDataTo(OutputStream out) throws IOException { long preCount = 0; if (outputCounter != null) preCount = outputCounter.getCount(); @@ -1303,6 +1337,7 @@ class BandStructure { } } + @Override protected void readDataFrom(InputStream in) throws IOException { assert(false); // not called? for (int i = 0; i < bandCount; i++) { @@ -1314,6 +1349,7 @@ class BandStructure { } } + @Override public String toString() { return "{"+bandCount()+" bands: "+super.toString()+"}"; } @@ -1335,14 +1371,17 @@ class BandStructure { public long getCount() { return count; } public void setCount(long c) { count = c; } + @Override public void write(int b) throws IOException { count++; if (out != null) out.write(b); } + @Override public void write(byte b[], int off, int len) throws IOException { count += len; if (out != null) out.write(b, off, len); } + @Override public String toString() { return String.valueOf(getCount()); } @@ -1490,6 +1529,7 @@ class BandStructure { CPRefBand field_ConstantValue_KQ = field_attr_bands.newCPRefBand("field_ConstantValue_KQ", CONSTANT_FieldSpecific); CPRefBand field_Signature_RS = field_attr_bands.newCPRefBand("field_Signature_RS", CONSTANT_Signature); MultiBand field_metadata_bands = field_attr_bands.newMultiBand("(field_metadata_bands)", UNSIGNED5); + MultiBand field_type_metadata_bands = field_attr_bands.newMultiBand("(field_type_metadata_bands)", UNSIGNED5); CPRefBand method_descr = class_bands.newCPRefBand("method_descr", MDELTA5, CONSTANT_NameandType); MultiBand method_attr_bands = class_bands.newMultiBand("(method_attr_bands)", UNSIGNED5); @@ -1507,6 +1547,7 @@ class BandStructure { IntBand method_MethodParameters_NB = method_attr_bands.newIntBand("method_MethodParameters_NB", BYTE1); CPRefBand method_MethodParameters_name_RUN = method_attr_bands.newCPRefBand("method_MethodParameters_name_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK); IntBand method_MethodParameters_flag_FH = method_attr_bands.newIntBand("method_MethodParameters_flag_FH"); + MultiBand method_type_metadata_bands = method_attr_bands.newMultiBand("(method_type_metadata_bands)", UNSIGNED5); MultiBand class_attr_bands = class_bands.newMultiBand("(class_attr_bands)", UNSIGNED5); IntBand class_flags_hi = class_attr_bands.newIntBand("class_flags_hi"); @@ -1527,6 +1568,7 @@ class BandStructure { CPRefBand class_InnerClasses_name_RUN = class_attr_bands.newCPRefBand("class_InnerClasses_name_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK); IntBand class_ClassFile_version_minor_H = class_attr_bands.newIntBand("class_ClassFile_version_minor_H"); IntBand class_ClassFile_version_major_H = class_attr_bands.newIntBand("class_ClassFile_version_major_H"); + MultiBand class_type_metadata_bands = class_attr_bands.newMultiBand("(class_type_metadata_bands)", UNSIGNED5); MultiBand code_bands = class_bands.newMultiBand("(code_bands)", UNSIGNED5); ByteBand code_headers = code_bands.newByteBand("code_headers"); //BYTE1 @@ -1545,7 +1587,7 @@ class BandStructure { IntBand code_attr_indexes = code_attr_bands.newIntBand("code_attr_indexes"); IntBand code_attr_calls = code_attr_bands.newIntBand("code_attr_calls"); - MultiBand stackmap_bands = code_attr_bands.newMultiBand("StackMapTable_bands", UNSIGNED5); + MultiBand stackmap_bands = code_attr_bands.newMultiBand("(StackMapTable_bands)", UNSIGNED5); IntBand code_StackMapTable_N = stackmap_bands.newIntBand("code_StackMapTable_N"); IntBand code_StackMapTable_frame_T = stackmap_bands.newIntBand("code_StackMapTable_frame_T",BYTE1); IntBand code_StackMapTable_local_N = stackmap_bands.newIntBand("code_StackMapTable_local_N"); @@ -1573,6 +1615,7 @@ class BandStructure { CPRefBand code_LocalVariableTypeTable_name_RU = code_attr_bands.newCPRefBand("code_LocalVariableTypeTable_name_RU", CONSTANT_Utf8); CPRefBand code_LocalVariableTypeTable_type_RS = code_attr_bands.newCPRefBand("code_LocalVariableTypeTable_type_RS", CONSTANT_Signature); IntBand code_LocalVariableTypeTable_slot = code_attr_bands.newIntBand("code_LocalVariableTypeTable_slot"); + MultiBand code_type_metadata_bands = code_attr_bands.newMultiBand("(code_type_metadata_bands)", UNSIGNED5); // bands for bytecodes MultiBand bc_bands = all_bands.newMultiBand("(byte_codes)", UNSIGNED5); @@ -1678,6 +1721,14 @@ class BandStructure { metadataBands[ATTR_CONTEXT_FIELD] = field_metadata_bands; metadataBands[ATTR_CONTEXT_METHOD] = method_metadata_bands; } + // Table of bands which contains type_metadata (TypeAnnotations) + protected MultiBand[] typeMetadataBands = new MultiBand[ATTR_CONTEXT_LIMIT]; + { + typeMetadataBands[ATTR_CONTEXT_CLASS] = class_type_metadata_bands; + typeMetadataBands[ATTR_CONTEXT_FIELD] = field_type_metadata_bands; + typeMetadataBands[ATTR_CONTEXT_METHOD] = method_type_metadata_bands; + typeMetadataBands[ATTR_CONTEXT_CODE] = code_type_metadata_bands; + } // Attribute layouts. public static final int ADH_CONTEXT_MASK = 0x3; // (ad_hdr & ADH_CONTEXT_MASK) @@ -1793,36 +1844,47 @@ class BandStructure { for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { MultiBand xxx_metadata_bands = metadataBands[ctype]; - if (xxx_metadata_bands == null) - continue; // no code attrs + if (ctype != ATTR_CONTEXT_CODE) { + // These arguments cause the bands to be built + // automatically for this complicated layout: + predefineAttribute(X_ATTR_RuntimeVisibleAnnotations, + ATTR_CONTEXT_NAME[ctype]+"_RVA_", + xxx_metadata_bands, + Attribute.lookup(null, ctype, + "RuntimeVisibleAnnotations")); + predefineAttribute(X_ATTR_RuntimeInvisibleAnnotations, + ATTR_CONTEXT_NAME[ctype]+"_RIA_", + xxx_metadata_bands, + Attribute.lookup(null, ctype, + "RuntimeInvisibleAnnotations")); - // These arguments cause the bands to be built - // automatically for this complicated layout: - predefineAttribute(X_ATTR_RuntimeVisibleAnnotations, - ATTR_CONTEXT_NAME[ctype]+"_RVA_", - xxx_metadata_bands, - Attribute.lookup(null, ctype, - "RuntimeVisibleAnnotations")); - predefineAttribute(X_ATTR_RuntimeInvisibleAnnotations, - ATTR_CONTEXT_NAME[ctype]+"_RIA_", - xxx_metadata_bands, - Attribute.lookup(null, ctype, - "RuntimeInvisibleAnnotations")); - if (ctype != ATTR_CONTEXT_METHOD) - continue; - - predefineAttribute(METHOD_ATTR_RuntimeVisibleParameterAnnotations, - "method_RVPA_", xxx_metadata_bands, - Attribute.lookup(null, ctype, - "RuntimeVisibleParameterAnnotations")); - predefineAttribute(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, - "method_RIPA_", xxx_metadata_bands, - Attribute.lookup(null, ctype, - "RuntimeInvisibleParameterAnnotations")); - predefineAttribute(METHOD_ATTR_AnnotationDefault, - "method_AD_", xxx_metadata_bands, - Attribute.lookup(null, ctype, - "AnnotationDefault")); + if (ctype == ATTR_CONTEXT_METHOD) { + predefineAttribute(METHOD_ATTR_RuntimeVisibleParameterAnnotations, + "method_RVPA_", xxx_metadata_bands, + Attribute.lookup(null, ctype, + "RuntimeVisibleParameterAnnotations")); + predefineAttribute(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, + "method_RIPA_", xxx_metadata_bands, + Attribute.lookup(null, ctype, + "RuntimeInvisibleParameterAnnotations")); + predefineAttribute(METHOD_ATTR_AnnotationDefault, + "method_AD_", xxx_metadata_bands, + Attribute.lookup(null, ctype, + "AnnotationDefault")); + } + } + // All contexts have these + MultiBand xxx_type_metadata_bands = typeMetadataBands[ctype]; + predefineAttribute(X_ATTR_RuntimeVisibleTypeAnnotations, + ATTR_CONTEXT_NAME[ctype] + "_RVTA_", + xxx_type_metadata_bands, + Attribute.lookup(null, ctype, + "RuntimeVisibleTypeAnnotations")); + predefineAttribute(X_ATTR_RuntimeInvisibleTypeAnnotations, + ATTR_CONTEXT_NAME[ctype] + "_RITA_", + xxx_type_metadata_bands, + Attribute.lookup(null, ctype, + "RuntimeInvisibleTypeAnnotations")); } @@ -2053,8 +2115,7 @@ class BandStructure { Attribute.Layout def = attr.layout(); int ctype = def.ctype(); return predefineAttribute(index, ctype, - makeNewAttributeBands(bandPrefix, def, - addHere), + makeNewAttributeBands(bandPrefix, def, addHere), def.name(), def.layout()); } @@ -2539,7 +2600,7 @@ class BandStructure { return true; } - // DEBUG ONLY: Validate next input band. + // DEBUG ONLY: Validate next input band, ensure bands are read in sequence private boolean assertReadyToReadFrom(Band b, InputStream in) throws IOException { Band p = prevForAssertMap.get(b); // Any previous band must be done reading before this one starts. @@ -2547,30 +2608,19 @@ class BandStructure { Utils.log.warning("Previous band not done reading."); Utils.log.info(" Previous band: "+p); Utils.log.info(" Next band: "+b); - Thread.dumpStack(); assert(verbose > 0); // die unless verbose is true } String name = b.name; if (optDebugBands && !name.startsWith("(")) { + assert(bandSequenceList != null); // Verify synchronization between reader & writer: - StringBuilder buf = new StringBuilder(); - int ch; - while ((ch = in.read()) > 0) - buf.append((char)ch); - String inName = buf.toString(); + String inName = bandSequenceList.removeFirst(); + // System.out.println("Reading: " + name); if (!inName.equals(name)) { - StringBuilder sb = new StringBuilder(); - sb.append("Expected "+name+" but read: "); - inName += (char)ch; - while (inName.length() < 10) { - inName += (char) in.read(); - } - for (int i = 0; i < inName.length(); i++) { - sb.append(inName.charAt(i)); - } - Utils.log.warning(sb.toString()); + Utils.log.warning("Expected " + name + " but read: " + inName); return false; } + Utils.log.info("Read band in sequence: " + name); } return true; } @@ -2590,7 +2640,12 @@ class BandStructure { return true; } - // DEBUG ONLY: Maybe write a debugging cookie to next output band. + /* + * DEBUG ONLY: write the bands to a list and read back the list in order, + * this works perfectly if we use the java packer and unpacker, typically + * this will work with --repack or if they are in the same jvm instance. + */ + static LinkedList bandSequenceList = null; private boolean assertReadyToWriteTo(Band b, OutputStream out) throws IOException { Band p = prevForAssertMap.get(b); // Any previous band must be done writing before this one starts. @@ -2598,16 +2653,15 @@ class BandStructure { Utils.log.warning("Previous band not done writing."); Utils.log.info(" Previous band: "+p); Utils.log.info(" Next band: "+b); - Thread.dumpStack(); assert(verbose > 0); // die unless verbose is true } String name = b.name; if (optDebugBands && !name.startsWith("(")) { + if (bandSequenceList == null) + bandSequenceList = new LinkedList<>(); // Verify synchronization between reader & writer: - for (int j = 0; j < name.length(); j++) { - out.write((byte)name.charAt(j)); - } - out.write((byte)0); + bandSequenceList.add(name); + // System.out.println("Writing: " + b); } return true; } @@ -2664,7 +2718,7 @@ class BandStructure { buf.append("\\r"); } else { String str = "000"+Integer.toHexString(ch); - buf.append("\\u"+str.substring(str.length()-4)); + buf.append("\\u").append(str.substring(str.length()-4)); } } ps.println(buf); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Code.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Code.java index e84cdaa59a0..423b0d7f779 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Code.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Code.java @@ -146,7 +146,6 @@ class Code extends Attribute.Holder { int verbose = getPackage().verbose; if (verbose > 2) System.out.println("Reference scan "+this); - Class cls = thisClass(); refs.addAll(Arrays.asList(handler_class)); if (fixups != null) { fixups.visitRefs(refs); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java index 1ede29134b0..4f64ef41b7a 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java @@ -785,53 +785,55 @@ class ConstantPool { return new String(sig); } - static private int skipClassNameChars(String sig, int i) { - int len = sig.length(); - for (; i < len; i++) { - char ch = sig.charAt(i); - if (ch <= ' ') break; - if (ch >= ';' && ch <= '@') break; - } - return i; + static private int skipTo(char semi, String sig, int i) { + i = sig.indexOf(semi, i); + return (i >= 0) ? i : sig.length(); } static String[] structureSignature(String sig) { - sig = sig.intern(); - - int formLen = 0; - int nparts = 1; - for (int i = 0; i < sig.length(); i++) { - char ch = sig.charAt(i); - formLen++; - if (ch == 'L') { - nparts++; - int i2 = skipClassNameChars(sig, i+1); - i = i2-1; // keep the semicolon in the form - int i3 = sig.indexOf('<', i+1); - if (i3 > 0 && i3 < i2) - i = i3-1; - } - } - char[] form = new char[formLen]; - if (nparts == 1) { + int firstl = sig.indexOf('L'); + if (firstl < 0) { String[] parts = { sig }; return parts; } - String[] parts = new String[nparts]; - int j = 0; - int k = 1; - for (int i = 0; i < sig.length(); i++) { - char ch = sig.charAt(i); - form[j++] = ch; - if (ch == 'L') { - int i2 = skipClassNameChars(sig, i+1); - parts[k++] = sig.substring(i+1, i2); - i = i2; - --i; // keep the semicolon in the form + // Segment the string like sig.split("L\\([^;<]*\\)"). + // N.B.: Previous version of this code did a more complex match, + // to next ch < ' ' or ch in [';'..'@']. The only important + // characters are ';' and '<', since they are part of the + // signature syntax. + // Examples: + // "(Ljava/lang/Object;IJLLoo;)V" => {"(L;IJL;)V", "java/lang/Object", "Loo"} + // "Ljava/util/List;" => {"L;", "java/util/List", "java/lang/String"} + char[] form = null; + String[] parts = null; + for (int pass = 0; pass <= 1; pass++) { + // pass 0 is a sizing pass, pass 1 packs the arrays + int formPtr = 0; + int partPtr = 1; + int nextsemi = 0, nextangl = 0; // next ';' or '<', or zero, or sigLen + int lastj = 0; + for (int i = firstl + 1, j; i > 0; i = sig.indexOf('L', j) + 1) { + // sig[i-1] is 'L', while sig[j] will be the first ';' or '<' after it + // each part is in sig[i .. j-1] + if (nextsemi < i) nextsemi = skipTo(';', sig, i); + if (nextangl < i) nextangl = skipTo('<', sig, i); + j = (nextsemi < nextangl ? nextsemi : nextangl); + if (pass != 0) { + sig.getChars(lastj, i, form, formPtr); + parts[partPtr] = sig.substring(i, j); + } + formPtr += (i - lastj); + partPtr += 1; + lastj = j; } + if (pass != 0) { + sig.getChars(lastj, sig.length(), form, formPtr); + break; + } + formPtr += (sig.length() - lastj); + form = new char[formPtr]; + parts = new String[partPtr]; } - assert(j == formLen); - assert(k == parts.length); parts[0] = new String(form); //assert(flattenSignature(parts).equals(sig)); return parts; diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java index 5059bc07967..15991700f25 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java @@ -45,6 +45,7 @@ class Constants { 1.5 to 1.5.X 49,0 1.6 to 1.5.x 50,0 1.7 to 1.6.x 51,0 + 1.8 to 1.7.x 52,0 */ public final static Package.Version JAVA_MIN_CLASS_VERSION = @@ -161,7 +162,9 @@ class Constants { METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24, CLASS_ATTR_ClassFile_version = 24, METHOD_ATTR_AnnotationDefault = 25, - METHOD_ATTR_MethodParameters = 26, + METHOD_ATTR_MethodParameters = 26, // JDK8 + X_ATTR_RuntimeVisibleTypeAnnotations = 27, // JDK8 + X_ATTR_RuntimeInvisibleTypeAnnotations = 28, // JDK8 CODE_ATTR_StackMapTable = 0, // new in Java 6 CODE_ATTR_LineNumberTable = 1, CODE_ATTR_LocalVariableTable = 2, diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Fixups.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Fixups.java index 0c99351222a..647d1dbc413 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Fixups.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Fixups.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.util.AbstractCollection; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; +import java.util.Objects; /** * Collection of relocatable constant pool references. @@ -77,8 +78,9 @@ final class Fixups extends AbstractCollection { private static final int MINBIGSIZE = 1; // cleverly share empty bigDescs: - private static int[] noBigDescs = {MINBIGSIZE}; + private static final int[] noBigDescs = {MINBIGSIZE}; + @Override public int size() { return size; } @@ -105,6 +107,7 @@ final class Fixups extends AbstractCollection { } } + @Override public void clear() { if (bytes != null) { // Clean the bytes: @@ -141,16 +144,16 @@ final class Fixups extends AbstractCollection { assert(old.equals(new ArrayList<>(this))); } - static final int LOC_SHIFT = 1; - static final int FMT_MASK = 0x1; - static final byte UNUSED_BYTE = 0; - static final byte OVERFLOW_BYTE = -1; + private static final int LOC_SHIFT = 1; + private static final int FMT_MASK = 0x1; + private static final byte UNUSED_BYTE = 0; + private static final byte OVERFLOW_BYTE = -1; // fill pointer of bigDescs array is in element [0] - static final int BIGSIZE = 0; + private static final int BIGSIZE = 0; // Format values: - public static final int U2_FORMAT = 0; - public static final int U1_FORMAT = 1; + private static final int U2_FORMAT = 0; + private static final int U1_FORMAT = 1; // Special values for the static methods. private static final int SPECIAL_LOC = 0; @@ -232,6 +235,14 @@ final class Fixups extends AbstractCollection { } } + void addU1(int pc, Entry ref) { + add(pc, U1_FORMAT, ref); + } + + void addU2(int pc, Entry ref) { + add(pc, U2_FORMAT, ref); + } + /** Simple and necessary tuple to present each fixup. */ public static class Fixup implements Comparable { @@ -248,15 +259,25 @@ final class Fixups extends AbstractCollection { public int location() { return descLoc(desc); } public int format() { return descFmt(desc); } public Entry entry() { return entry; } + @Override public int compareTo(Fixup that) { // Ordering depends only on location. return this.location() - that.location(); } + @Override public boolean equals(Object x) { if (!(x instanceof Fixup)) return false; Fixup that = (Fixup) x; return this.desc == that.desc && this.entry == that.entry; } + @Override + public int hashCode() { + int hash = 7; + hash = 59 * hash + this.desc; + hash = 59 * hash + Objects.hashCode(this.entry); + return hash; + } + @Override public String toString() { return "@"+location()+(format()==U1_FORMAT?".1":"")+"="+entry; } @@ -267,8 +288,11 @@ final class Fixups extends AbstractCollection { int index = 0; // index into entries int bigIndex = BIGSIZE+1; // index into bigDescs int next = head; // desc pointing to next fixup + @Override public boolean hasNext() { return index < size; } + @Override public void remove() { throw new UnsupportedOperationException(); } + @Override public Fixup next() { int thisIndex = index; return new Fixup(nextDesc(), entries[thisIndex]); @@ -293,17 +317,20 @@ final class Fixups extends AbstractCollection { } } + @Override public Iterator iterator() { return new Itr(); } public void add(int location, int format, Entry entry) { addDesc(makeDesc(location, format), entry); } + @Override public boolean add(Fixup f) { addDesc(f.desc, f.entry); return true; } + @Override public boolean addAll(Collection c) { if (c instanceof Fixups) { // Use knowledge of Itr structure to avoid building little structs. @@ -367,7 +394,13 @@ final class Fixups extends AbstractCollection { } /// Static methods that optimize the use of this class. - public static + static Object addRefWithBytes(Object f, byte[] bytes, Entry e) { + return add(f, bytes, 0, U2_FORMAT, e); + } + static Object addRefWithLoc(Object f, int loc, Entry entry) { + return add(f, null, loc, U2_FORMAT, entry); + } + private static Object add(Object prevFixups, byte[] bytes, int loc, int fmt, Entry e) { diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java index 64f9db5c309..af78754e06b 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -259,7 +259,7 @@ class Package { byte[] bytes = new byte[2]; sfName = getRefString(obvious); Object f = null; - f = Fixups.add(f, bytes, 0, Fixups.U2_FORMAT, sfName); + f = Fixups.addRefWithBytes(f, bytes, sfName); a = attrSourceFileSpecial.addContent(bytes, f); } } else if (obvious.equals(sfName.stringValue())) { diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java index b42dda30eb4..000a643f873 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java @@ -116,7 +116,7 @@ class PackageReader extends BandStructure { int nr = super.read(b, off, len); servedPos = pos; if (nr >= 0) served += nr; - assert(served <= limit || limit == -1); + //assert(served <= limit || limit == -1); return nr; } public long skip(long n) throws IOException { @@ -1500,6 +1500,7 @@ class PackageReader extends BandStructure { // ic_local_bands // *class_ClassFile_version_minor_H :UNSIGNED5 // *class_ClassFile_version_major_H :UNSIGNED5 + // class_type_metadata_bands // // field_attr_bands: // *field_flags :UNSIGNED5 @@ -1509,6 +1510,7 @@ class PackageReader extends BandStructure { // *field_Signature_RS :UNSIGNED5 (cp_Signature) // field_metadata_bands // *field_ConstantValue_KQ :UNSIGNED5 (cp_Int, etc.; see note) + // field_type_metadata_bands // // method_attr_bands: // *method_flags :UNSIGNED5 @@ -1522,6 +1524,7 @@ class PackageReader extends BandStructure { // *method_MethodParameters_NB: BYTE1 // *method_MethodParameters_RUN: UNSIGNED5 (cp_Utf8) // *method_MethodParameters_FH: UNSIGNED5 (flag) + // method_type_metadata_bands // // code_attr_bands: // *code_flags :UNSIGNED5 @@ -1537,6 +1540,7 @@ class PackageReader extends BandStructure { // *code_LocalVariableTable_name_RU :UNSIGNED5 (cp_Utf8) // *code_LocalVariableTable_type_RS :UNSIGNED5 (cp_Signature) // *code_LocalVariableTable_slot :UNSIGNED5 + // code_type_metadata_bands countAttrs(ctype, holders); readAttrs(ctype, holders); @@ -1703,8 +1707,9 @@ class PackageReader extends BandStructure { class_InnerClasses_outer_RCN.readFrom(in); class_InnerClasses_name_RUN.expectLength(tupleCount); class_InnerClasses_name_RUN.readFrom(in); - } else if (totalCount == 0) { - // Expect no elements at all. Skip quickly. + } else if (!optDebugBands && totalCount == 0) { + // Expect no elements at all. Skip quickly. however if we + // are debugging bands, read all bands regardless for (int j = 0; j < ab.length; j++) { ab[j].doneWithUnusedBand(); } @@ -1723,11 +1728,17 @@ class PackageReader extends BandStructure { assert(cbles[j].kind == Attribute.EK_CBLE); int entryCount = forwardCounts[j]; forwardCounts[j] = -1; // No more, please! - if (cbles[j].flagTest(Attribute.EF_BACK)) + if (totalCount > 0 && cbles[j].flagTest(Attribute.EF_BACK)) entryCount += xxx_attr_calls.getInt(); readAttrBands(cbles[j].body, entryCount, forwardCounts, ab); } } + // mark them read, to satisfy asserts + if (optDebugBands && totalCount == 0) { + for (int j = 0; j < ab.length; j++) { + ab[j].doneDisbursing(); + } + } } } if (!predef) break; @@ -2154,11 +2165,10 @@ class PackageReader extends BandStructure { if (size == 1) ldcRefSet.add(ref); int fmt; switch (size) { - case 1: fmt = Fixups.U1_FORMAT; break; - case 2: fmt = Fixups.U2_FORMAT; break; + case 1: fixupBuf.addU1(pc, ref); break; + case 2: fixupBuf.addU2(pc, ref); break; default: assert(false); fmt = 0; } - fixupBuf.add(pc, fmt, ref); buf[pc+0] = buf[pc+1] = 0; pc += size; } @@ -2193,7 +2203,7 @@ class PackageReader extends BandStructure { int coding = bc_initref.getInt(); // Find the nth overloading of in classRef. MemberEntry ref = pkg.cp.getOverloadingForIndex(CONSTANT_Methodref, classRef, "", coding); - fixupBuf.add(pc, Fixups.U2_FORMAT, ref); + fixupBuf.addU2(pc, ref); buf[pc+0] = buf[pc+1] = 0; pc += 2; assert(Instruction.opLength(origBC) == (pc - curPC)); @@ -2226,7 +2236,7 @@ class PackageReader extends BandStructure { insnMap[numInsns++] = curPC; } buf[pc++] = (byte) origBC; - fixupBuf.add(pc, Fixups.U2_FORMAT, ref); + fixupBuf.addU2(pc, ref); buf[pc+0] = buf[pc+1] = 0; pc += 2; assert(Instruction.opLength(origBC) == (pc - curPC)); @@ -2289,11 +2299,10 @@ class PackageReader extends BandStructure { buf[pc++] = (byte) origBC; int fmt; switch (size) { - case 1: fmt = Fixups.U1_FORMAT; break; - case 2: fmt = Fixups.U2_FORMAT; break; + case 1: fixupBuf.addU1(pc, ref); break; + case 2: fixupBuf.addU2(pc, ref); break; default: assert(false); fmt = 0; } - fixupBuf.add(pc, fmt, ref); buf[pc+0] = buf[pc+1] = 0; pc += size; if (origBC == _multianewarray) { diff --git a/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java b/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java index 24f7343ac70..3c0b6a53137 100644 --- a/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java +++ b/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java @@ -102,7 +102,7 @@ public class DnsContext extends ComponentDirContext { this.domain = new DnsName(domain.endsWith(".") ? domain : domain + "."); - this.servers = servers; + this.servers = (servers == null) ? null : servers.clone(); this.environment = (Hashtable) environment.clone(); envShared = false; parentIsDns = false; @@ -129,11 +129,11 @@ public class DnsContext extends ComponentDirContext { * no conflict. */ private DnsContext(DnsContext ctx) { - environment = ctx.environment; + environment = ctx.environment; // shared environment, copy-on-write envShared = ctx.envShared = true; parentIsDns = ctx.parentIsDns; domain = ctx.domain; - servers = ctx.servers; + servers = ctx.servers; // shared servers, no write operation resolver = ctx.resolver; authoritative = ctx.authoritative; recursion = ctx.recursion; diff --git a/jdk/src/share/classes/com/sun/jndi/ldap/BasicControl.java b/jdk/src/share/classes/com/sun/jndi/ldap/BasicControl.java index d068704142a..007a40cb2e5 100644 --- a/jdk/src/share/classes/com/sun/jndi/ldap/BasicControl.java +++ b/jdk/src/share/classes/com/sun/jndi/ldap/BasicControl.java @@ -81,7 +81,7 @@ public class BasicControl implements Control { this.id = id; this.criticality = criticality; if (value != null) { - this.value = value; + this.value = value.clone(); } } diff --git a/jdk/src/share/classes/com/sun/jndi/ldap/BerDecoder.java b/jdk/src/share/classes/com/sun/jndi/ldap/BerDecoder.java index 44b46f844b8..55b46d36322 100644 --- a/jdk/src/share/classes/com/sun/jndi/ldap/BerDecoder.java +++ b/jdk/src/share/classes/com/sun/jndi/ldap/BerDecoder.java @@ -42,7 +42,7 @@ public final class BerDecoder extends Ber { */ public BerDecoder(byte buf[], int offset, int bufsize) { - this.buf = buf; + this.buf = buf; // shared buffer, be careful to use this class this.bufsize = bufsize; this.origOffset = offset; diff --git a/jdk/src/share/classes/com/sun/jndi/ldap/BerEncoder.java b/jdk/src/share/classes/com/sun/jndi/ldap/BerEncoder.java index fc8566dad49..a641b0dd7a4 100644 --- a/jdk/src/share/classes/com/sun/jndi/ldap/BerEncoder.java +++ b/jdk/src/share/classes/com/sun/jndi/ldap/BerEncoder.java @@ -99,7 +99,7 @@ public final class BerEncoder extends Ber { if (curSeqIndex != 0) { throw new IllegalStateException("BER encode error: Unbalanced SEQUENCEs."); } - return buf; + return buf; // shared buffer, be careful to use this method. } /** diff --git a/jdk/src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java b/jdk/src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java index 737036155ce..28745bdb0d5 100644 --- a/jdk/src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java +++ b/jdk/src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java @@ -134,7 +134,9 @@ final public class StartTlsResponseImpl extends StartTlsResponse { * @see #negotiate */ public void setEnabledCipherSuites(String[] suites) { - this.suites = suites; + // The impl does accept null suites, although the spec requires + // a non-null list. + this.suites = suites == null ? null : suites.clone(); } /** diff --git a/jdk/src/share/classes/com/sun/script/javascript/ExternalScriptable.java b/jdk/src/share/classes/com/sun/script/javascript/ExternalScriptable.java deleted file mode 100644 index 856562085d4..00000000000 --- a/jdk/src/share/classes/com/sun/script/javascript/ExternalScriptable.java +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. - * 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.script.javascript; -import sun.org.mozilla.javascript.internal.*; -import javax.script.*; -import java.util.*; - -/** - * ExternalScriptable is an implementation of Scriptable - * backed by a JSR 223 ScriptContext instance. - * - * @author Mike Grogan - * @author A. Sundararajan - * @since 1.6 - */ - -final class ExternalScriptable implements Scriptable { - /* Underlying ScriptContext that we use to store - * named variables of this scope. - */ - private ScriptContext context; - - /* JavaScript allows variables to be named as numbers (indexed - * properties). This way arrays, objects (scopes) are treated uniformly. - * Note that JSR 223 API supports only String named variables and - * so we can't store these in Bindings. Also, JavaScript allows name - * of the property name to be even empty String! Again, JSR 223 API - * does not support empty name. So, we use the following fallback map - * to store such variables of this scope. This map is not exposed to - * JSR 223 API. We can just script objects "as is" and need not convert. - */ - private Map indexedProps; - - // my prototype - private Scriptable prototype; - // my parent scope, if any - private Scriptable parent; - - ExternalScriptable(ScriptContext context) { - this(context, new HashMap()); - } - - ExternalScriptable(ScriptContext context, Map indexedProps) { - if (context == null) { - throw new NullPointerException("context is null"); - } - this.context = context; - this.indexedProps = indexedProps; - } - - ScriptContext getContext() { - return context; - } - - private boolean isEmpty(String name) { - return name.equals(""); - } - - /** - * Return the name of the class. - */ - public String getClassName() { - return "Global"; - } - - /** - * Returns the value of the named property or NOT_FOUND. - * - * If the property was created using defineProperty, the - * appropriate getter method is called. - * - * @param name the name of the property - * @param start the object in which the lookup began - * @return the value of the property (may be null), or NOT_FOUND - */ - public synchronized Object get(String name, Scriptable start) { - if (isEmpty(name)) { - if (indexedProps.containsKey(name)) { - return indexedProps.get(name); - } else { - return NOT_FOUND; - } - } else { - synchronized (context) { - int scope = context.getAttributesScope(name); - if (scope != -1) { - Object value = context.getAttribute(name, scope); - return Context.javaToJS(value, this); - } else { - return NOT_FOUND; - } - } - } - } - - /** - * Returns the value of the indexed property or NOT_FOUND. - * - * @param index the numeric index for the property - * @param start the object in which the lookup began - * @return the value of the property (may be null), or NOT_FOUND - */ - public synchronized Object get(int index, Scriptable start) { - Integer key = new Integer(index); - if (indexedProps.containsKey(index)) { - return indexedProps.get(key); - } else { - return NOT_FOUND; - } - } - - /** - * Returns true if the named property is defined. - * - * @param name the name of the property - * @param start the object in which the lookup began - * @return true if and only if the property was found in the object - */ - public synchronized boolean has(String name, Scriptable start) { - if (isEmpty(name)) { - return indexedProps.containsKey(name); - } else { - synchronized (context) { - return context.getAttributesScope(name) != -1; - } - } - } - - /** - * Returns true if the property index is defined. - * - * @param index the numeric index for the property - * @param start the object in which the lookup began - * @return true if and only if the property was found in the object - */ - public synchronized boolean has(int index, Scriptable start) { - Integer key = new Integer(index); - return indexedProps.containsKey(key); - } - - /** - * Sets the value of the named property, creating it if need be. - * - * @param name the name of the property - * @param start the object whose property is being set - * @param value value to set the property to - */ - public void put(String name, Scriptable start, Object value) { - if (start == this) { - synchronized (this) { - if (isEmpty(name)) { - indexedProps.put(name, value); - } else { - synchronized (context) { - int scope = context.getAttributesScope(name); - if (scope == -1) { - scope = ScriptContext.ENGINE_SCOPE; - } - context.setAttribute(name, jsToJava(value), scope); - } - } - } - } else { - start.put(name, start, value); - } - } - - /** - * Sets the value of the indexed property, creating it if need be. - * - * @param index the numeric index for the property - * @param start the object whose property is being set - * @param value value to set the property to - */ - public void put(int index, Scriptable start, Object value) { - if (start == this) { - synchronized (this) { - indexedProps.put(new Integer(index), value); - } - } else { - start.put(index, start, value); - } - } - - /** - * Removes a named property from the object. - * - * If the property is not found, no action is taken. - * - * @param name the name of the property - */ - public synchronized void delete(String name) { - if (isEmpty(name)) { - indexedProps.remove(name); - } else { - synchronized (context) { - int scope = context.getAttributesScope(name); - if (scope != -1) { - context.removeAttribute(name, scope); - } - } - } - } - - /** - * Removes the indexed property from the object. - * - * If the property is not found, no action is taken. - * - * @param index the numeric index for the property - */ - public void delete(int index) { - indexedProps.remove(new Integer(index)); - } - - /** - * Get the prototype of the object. - * @return the prototype - */ - public Scriptable getPrototype() { - return prototype; - } - - /** - * Set the prototype of the object. - * @param prototype the prototype to set - */ - public void setPrototype(Scriptable prototype) { - this.prototype = prototype; - } - - /** - * Get the parent scope of the object. - * @return the parent scope - */ - public Scriptable getParentScope() { - return parent; - } - - /** - * Set the parent scope of the object. - * @param parent the parent scope to set - */ - public void setParentScope(Scriptable parent) { - this.parent = parent; - } - - /** - * Get an array of property ids. - * - * Not all property ids need be returned. Those properties - * whose ids are not returned are considered non-enumerable. - * - * @return an array of Objects. Each entry in the array is either - * a java.lang.String or a java.lang.Number - */ - public synchronized Object[] getIds() { - String[] keys = getAllKeys(); - int size = keys.length + indexedProps.size(); - Object[] res = new Object[size]; - System.arraycopy(keys, 0, res, 0, keys.length); - int i = keys.length; - // now add all indexed properties - for (Object index : indexedProps.keySet()) { - res[i++] = index; - } - return res; - } - - /** - * Get the default value of the object with a given hint. - * The hints are String.class for type String, Number.class for type - * Number, Scriptable.class for type Object, and Boolean.class for - * type Boolean.

- * - * A hint of null means "no hint". - * - * See ECMA 8.6.2.6. - * - * @param hint the type hint - * @return the default value - */ - public Object getDefaultValue(Class typeHint) { - for (int i=0; i < 2; i++) { - boolean tryToString; - if (typeHint == ScriptRuntime.StringClass) { - tryToString = (i == 0); - } else { - tryToString = (i == 1); - } - - String methodName; - Object[] args; - if (tryToString) { - methodName = "toString"; - args = ScriptRuntime.emptyArgs; - } else { - methodName = "valueOf"; - args = new Object[1]; - String hint; - if (typeHint == null) { - hint = "undefined"; - } else if (typeHint == ScriptRuntime.StringClass) { - hint = "string"; - } else if (typeHint == ScriptRuntime.ScriptableClass) { - hint = "object"; - } else if (typeHint == ScriptRuntime.FunctionClass) { - hint = "function"; - } else if (typeHint == ScriptRuntime.BooleanClass - || typeHint == Boolean.TYPE) - { - hint = "boolean"; - } else if (typeHint == ScriptRuntime.NumberClass || - typeHint == ScriptRuntime.ByteClass || - typeHint == Byte.TYPE || - typeHint == ScriptRuntime.ShortClass || - typeHint == Short.TYPE || - typeHint == ScriptRuntime.IntegerClass || - typeHint == Integer.TYPE || - typeHint == ScriptRuntime.FloatClass || - typeHint == Float.TYPE || - typeHint == ScriptRuntime.DoubleClass || - typeHint == Double.TYPE) - { - hint = "number"; - } else { - throw Context.reportRuntimeError( - "Invalid JavaScript value of type " + - typeHint.toString()); - } - args[0] = hint; - } - Object v = ScriptableObject.getProperty(this, methodName); - if (!(v instanceof Function)) - continue; - Function fun = (Function) v; - Context cx = RhinoScriptEngine.enterContext(); - try { - v = fun.call(cx, fun.getParentScope(), this, args); - } finally { - cx.exit(); - } - if (v != null) { - if (!(v instanceof Scriptable)) { - return v; - } - if (typeHint == ScriptRuntime.ScriptableClass - || typeHint == ScriptRuntime.FunctionClass) - { - return v; - } - if (tryToString && v instanceof Wrapper) { - // Let a wrapped java.lang.String pass for a primitive - // string. - Object u = ((Wrapper)v).unwrap(); - if (u instanceof String) - return u; - } - } - } - // fall through to error - String arg = (typeHint == null) ? "undefined" : typeHint.getName(); - throw Context.reportRuntimeError( - "Cannot find default value for object " + arg); - } - - /** - * Implements the instanceof operator. - * - * @param instance The value that appeared on the LHS of the instanceof - * operator - * @return true if "this" appears in value's prototype chain - * - */ - public boolean hasInstance(Scriptable instance) { - // Default for JS objects (other than Function) is to do prototype - // chasing. - Scriptable proto = instance.getPrototype(); - while (proto != null) { - if (proto.equals(this)) return true; - proto = proto.getPrototype(); - } - return false; - } - - private String[] getAllKeys() { - ArrayList list = new ArrayList(); - synchronized (context) { - for (int scope : context.getScopes()) { - Bindings bindings = context.getBindings(scope); - if (bindings != null) { - list.ensureCapacity(bindings.size()); - for (String key : bindings.keySet()) { - list.add(key); - } - } - } - } - String[] res = new String[list.size()]; - list.toArray(res); - return res; - } - - /** - * We convert script values to the nearest Java value. - * We unwrap wrapped Java objects so that access from - * Bindings.get() would return "workable" value for Java. - * But, at the same time, we need to make few special cases - * and hence the following function is used. - */ - private Object jsToJava(Object jsObj) { - if (jsObj instanceof Wrapper) { - Wrapper njb = (Wrapper) jsObj; - /* importClass feature of ImporterTopLevel puts - * NativeJavaClass in global scope. If we unwrap - * it, importClass won't work. - */ - if (njb instanceof NativeJavaClass) { - return njb; - } - - /* script may use Java primitive wrapper type objects - * (such as java.lang.Integer, java.lang.Boolean etc) - * explicitly. If we unwrap, then these script objects - * will become script primitive types. For example, - * - * var x = new java.lang.Double(3.0); print(typeof x); - * - * will print 'number'. We don't want that to happen. - */ - Object obj = njb.unwrap(); - if (obj instanceof Number || obj instanceof String || - obj instanceof Boolean || obj instanceof Character) { - // special type wrapped -- we just leave it as is. - return njb; - } else { - // return unwrapped object for any other object. - return obj; - } - } else { // not-a-Java-wrapper - return jsObj; - } - } -} diff --git a/jdk/src/share/classes/com/sun/script/javascript/JSAdapter.java b/jdk/src/share/classes/com/sun/script/javascript/JSAdapter.java deleted file mode 100644 index 53497e95f62..00000000000 --- a/jdk/src/share/classes/com/sun/script/javascript/JSAdapter.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. - * 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.script.javascript; - -import sun.org.mozilla.javascript.internal.*; -import java.util.*; - -/** - * JSAdapter is java.lang.reflect.Proxy equivalent for JavaScript. JSAdapter - * calls specially named JavaScript methods on an adaptee object when property - * access is attempted on it. - * - * Example: - * - * var y = { - * __get__ : function (name) { ... } - * __has__ : function (name) { ... } - * __put__ : function (name, value) {...} - * __delete__ : function (name) { ... } - * __getIds__ : function () { ... } - * }; - * - * var x = new JSAdapter(y); - * - * x.i; // calls y.__get__ - * i in x; // calls y.__has__ - * x.p = 10; // calls y.__put__ - * delete x.p; // calls y.__delete__ - * for (i in x) { print(i); } // calls y.__getIds__ - * - * If a special JavaScript method is not found in the adaptee, then JSAdapter - * forwards the property access to the adaptee itself. - * - * JavaScript caller of adapter object is isolated from the fact that - * the property access/mutation/deletion are really calls to - * JavaScript methods on adaptee. Use cases include 'smart' - * properties, property access tracing/debugging, encaptulation with - * easy client access - in short JavaScript becomes more "Self" like. - * - * Note that Rhino already supports special properties like __proto__ - * (to set, get prototype), __parent__ (to set, get parent scope). We - * follow the same double underscore nameing convention here. Similarly - * the name JSAdapter is derived from JavaAdapter -- which is a facility - * to extend, implement Java classes/interfaces by JavaScript. - * - * @author A. Sundararajan - * @since 1.6 - */ -public final class JSAdapter implements Scriptable, Function { - private JSAdapter(Scriptable obj) { - setAdaptee(obj); - } - - // initializer to setup JSAdapter prototype in the given scope - public static void init(Context cx, Scriptable scope, boolean sealed) - throws RhinoException { - JSAdapter obj = new JSAdapter(cx.newObject(scope)); - obj.setParentScope(scope); - obj.setPrototype(getFunctionPrototype(scope)); - obj.isPrototype = true; - ScriptableObject.defineProperty(scope, "JSAdapter", obj, - ScriptableObject.DONTENUM); - } - - public String getClassName() { - return "JSAdapter"; - } - - public Object get(String name, Scriptable start) { - Function func = getAdapteeFunction(GET_PROP); - if (func != null) { - return call(func, new Object[] { name }); - } else { - start = getAdaptee(); - return start.get(name, start); - } - } - - public Object get(int index, Scriptable start) { - Function func = getAdapteeFunction(GET_PROP); - if (func != null) { - return call(func, new Object[] { new Integer(index) }); - } else { - start = getAdaptee(); - return start.get(index, start); - } - } - - public boolean has(String name, Scriptable start) { - Function func = getAdapteeFunction(HAS_PROP); - if (func != null) { - Object res = call(func, new Object[] { name }); - return Context.toBoolean(res); - } else { - start = getAdaptee(); - return start.has(name, start); - } - } - - public boolean has(int index, Scriptable start) { - Function func = getAdapteeFunction(HAS_PROP); - if (func != null) { - Object res = call(func, new Object[] { new Integer(index) }); - return Context.toBoolean(res); - } else { - start = getAdaptee(); - return start.has(index, start); - } - } - - public void put(String name, Scriptable start, Object value) { - if (start == this) { - Function func = getAdapteeFunction(PUT_PROP); - if (func != null) { - call(func, new Object[] { name, value }); - } else { - start = getAdaptee(); - start.put(name, start, value); - } - } else { - start.put(name, start, value); - } - } - - public void put(int index, Scriptable start, Object value) { - if (start == this) { - Function func = getAdapteeFunction(PUT_PROP); - if( func != null) { - call(func, new Object[] { new Integer(index), value }); - } else { - start = getAdaptee(); - start.put(index, start, value); - } - } else { - start.put(index, start, value); - } - } - - public void delete(String name) { - Function func = getAdapteeFunction(DEL_PROP); - if (func != null) { - call(func, new Object[] { name }); - } else { - getAdaptee().delete(name); - } - } - - public void delete(int index) { - Function func = getAdapteeFunction(DEL_PROP); - if (func != null) { - call(func, new Object[] { new Integer(index) }); - } else { - getAdaptee().delete(index); - } - } - - public Scriptable getPrototype() { - return prototype; - } - - public void setPrototype(Scriptable prototype) { - this.prototype = prototype; - } - - public Scriptable getParentScope() { - return parent; - } - - public void setParentScope(Scriptable parent) { - this.parent = parent; - } - - public Object[] getIds() { - Function func = getAdapteeFunction(GET_PROPIDS); - if (func != null) { - Object val = call(func, new Object[0]); - // in most cases, adaptee would return native JS array - if (val instanceof NativeArray) { - NativeArray array = (NativeArray) val; - Object[] res = new Object[(int)array.getLength()]; - for (int index = 0; index < res.length; index++) { - res[index] = mapToId(array.get(index, array)); - } - return res; - } else if (val instanceof NativeJavaArray) { - // may be attempt wrapped Java array - Object tmp = ((NativeJavaArray)val).unwrap(); - Object[] res; - if (tmp.getClass() == Object[].class) { - Object[] array = (Object[]) tmp; - res = new Object[array.length]; - for (int index = 0; index < array.length; index++) { - res[index] = mapToId(array[index]); - } - } else { - // just return an empty array - res = Context.emptyArgs; - } - return res; - } else { - // some other return type, just return empty array - return Context.emptyArgs; - } - } else { - return getAdaptee().getIds(); - } - } - - public boolean hasInstance(Scriptable scriptable) { - if (scriptable instanceof JSAdapter) { - return true; - } else { - Scriptable proto = scriptable.getPrototype(); - while (proto != null) { - if (proto.equals(this)) return true; - proto = proto.getPrototype(); - } - return false; - } - } - - public Object getDefaultValue(Class hint) { - return getAdaptee().getDefaultValue(hint); - } - - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - throws RhinoException { - if (isPrototype) { - return construct(cx, scope, args); - } else { - Scriptable tmp = getAdaptee(); - if (tmp instanceof Function) { - return ((Function)tmp).call(cx, scope, tmp, args); - } else { - throw Context.reportRuntimeError("TypeError: not a function"); - } - } - } - - public Scriptable construct(Context cx, Scriptable scope, Object[] args) - throws RhinoException { - if (isPrototype) { - Scriptable topLevel = ScriptableObject.getTopLevelScope(scope); - JSAdapter newObj; - if (args.length > 0) { - newObj = new JSAdapter(Context.toObject(args[0], topLevel)); - } else { - throw Context.reportRuntimeError("JSAdapter requires adaptee"); - } - return newObj; - } else { - Scriptable tmp = getAdaptee(); - if (tmp instanceof Function) { - return ((Function)tmp).construct(cx, scope, args); - } else { - throw Context.reportRuntimeError("TypeError: not a constructor"); - } - } - } - - public Scriptable getAdaptee() { - return adaptee; - } - - public void setAdaptee(Scriptable adaptee) { - if (adaptee == null) { - throw new NullPointerException("adaptee can not be null"); - } - this.adaptee = adaptee; - } - - //-- internals only below this point - - // map a property id. Property id can only be an Integer or String - private Object mapToId(Object tmp) { - if (tmp instanceof Double) { - return new Integer(((Double)tmp).intValue()); - } else { - return Context.toString(tmp); - } - } - - private static Scriptable getFunctionPrototype(Scriptable scope) { - return ScriptableObject.getFunctionPrototype(scope); - } - - private Function getAdapteeFunction(String name) { - Object o = ScriptableObject.getProperty(getAdaptee(), name); - return (o instanceof Function)? (Function)o : null; - } - - private Object call(Function func, Object[] args) { - Context cx = Context.getCurrentContext(); - Scriptable thisObj = getAdaptee(); - Scriptable scope = func.getParentScope(); - try { - return func.call(cx, scope, thisObj, args); - } catch (RhinoException re) { - throw Context.reportRuntimeError(re.getMessage()); - } - } - - private Scriptable prototype; - private Scriptable parent; - private Scriptable adaptee; - private boolean isPrototype; - - // names of adaptee JavaScript functions - private static final String GET_PROP = "__get__"; - private static final String HAS_PROP = "__has__"; - private static final String PUT_PROP = "__put__"; - private static final String DEL_PROP = "__delete__"; - private static final String GET_PROPIDS = "__getIds__"; -} diff --git a/jdk/src/share/classes/com/sun/script/javascript/JavaAdapter.java b/jdk/src/share/classes/com/sun/script/javascript/JavaAdapter.java deleted file mode 100644 index 4e670065f63..00000000000 --- a/jdk/src/share/classes/com/sun/script/javascript/JavaAdapter.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. - * 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.script.javascript; - -import javax.script.Invocable; -import sun.org.mozilla.javascript.internal.*; - -/** - * This class implements Rhino-like JavaAdapter to help implement a Java - * interface in JavaScript. We support this using Invocable.getInterface. - * Using this JavaAdapter, script author could write: - * - * var r = new java.lang.Runnable() { - * run: function() { script... } - * }; - * - * r.run(); - * new java.lang.Thread(r).start(); - * - * Note that Rhino's JavaAdapter support allows extending a Java class and/or - * implementing one or more interfaces. This JavaAdapter implementation does - * not support these. - * - * @author A. Sundararajan - * @since 1.6 - */ -final class JavaAdapter extends ScriptableObject implements Function { - private JavaAdapter(Invocable engine) { - this.engine = engine; - } - - static void init(Context cx, Scriptable scope, boolean sealed) - throws RhinoException { - RhinoTopLevel topLevel = (RhinoTopLevel) scope; - Invocable engine = topLevel.getScriptEngine(); - JavaAdapter obj = new JavaAdapter(engine); - obj.setParentScope(scope); - obj.setPrototype(getFunctionPrototype(scope)); - /* - * Note that we can't use defineProperty. A property of this - * name is already defined in Context.initStandardObjects. We - * simply overwrite the property value! - */ - ScriptableObject.putProperty(topLevel, "JavaAdapter", obj); - } - - public String getClassName() { - return "JavaAdapter"; - } - - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) throws RhinoException { - return construct(cx, scope, args); - } - - public Scriptable construct(Context cx, Scriptable scope, Object[] args) - throws RhinoException { - if (args.length == 2) { - Class clazz = null; - Object obj1 = args[0]; - if (obj1 instanceof Wrapper) { - Object o = ((Wrapper)obj1).unwrap(); - if (o instanceof Class && ((Class)o).isInterface()) { - clazz = (Class) o; - } - } else if (obj1 instanceof Class) { - if (((Class)obj1).isInterface()) { - clazz = (Class) obj1; - } - } - if (clazz == null) { - throw Context.reportRuntimeError("JavaAdapter: first arg should be interface Class"); - } - - Scriptable topLevel = ScriptableObject.getTopLevelScope(scope); - return cx.toObject(engine.getInterface(args[1], clazz), topLevel); - } else { - throw Context.reportRuntimeError("JavaAdapter requires two arguments"); - } - } - - private Invocable engine; -} diff --git a/jdk/src/share/classes/com/sun/script/javascript/META-INF/services/javax.script.ScriptEngineFactory b/jdk/src/share/classes/com/sun/script/javascript/META-INF/services/javax.script.ScriptEngineFactory deleted file mode 100644 index de576fbc308..00000000000 --- a/jdk/src/share/classes/com/sun/script/javascript/META-INF/services/javax.script.ScriptEngineFactory +++ /dev/null @@ -1,5 +0,0 @@ - -#script engines supported - -com.sun.script.javascript.RhinoScriptEngineFactory #javascript - diff --git a/jdk/src/share/classes/com/sun/script/javascript/RhinoClassShutter.java b/jdk/src/share/classes/com/sun/script/javascript/RhinoClassShutter.java deleted file mode 100644 index ea376e8c4b0..00000000000 --- a/jdk/src/share/classes/com/sun/script/javascript/RhinoClassShutter.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. - * 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.script.javascript; - -import java.util.*; -import sun.org.mozilla.javascript.internal.*; - -/** - * This class prevents script access to certain sensitive classes. - * Note that this class checks over and above SecurityManager. i.e., although - * a SecurityManager would pass, class shutter may still prevent access. - * - * @author A. Sundararajan - * @since 1.6 - */ -final class RhinoClassShutter implements ClassShutter { - private static Map protectedClasses; - private static RhinoClassShutter theInstance; - - private RhinoClassShutter() { - } - - static synchronized ClassShutter getInstance() { - if (theInstance == null) { - theInstance = new RhinoClassShutter(); - protectedClasses = new HashMap(); - - // For now, we just have AccessController. Allowing scripts - // to this class will allow it to execute doPrivileged in - // bootstrap context. We can add more classes for other reasons. - protectedClasses.put("java.security.AccessController", Boolean.TRUE); - } - return theInstance; - } - - public boolean visibleToScripts(String fullClassName) { - // first do the security check. - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - int i = fullClassName.lastIndexOf("."); - if (i != -1) { - try { - sm.checkPackageAccess(fullClassName.substring(0, i)); - } catch (SecurityException se) { - return false; - } - } - } - // now, check is it a protected class. - return protectedClasses.get(fullClassName) == null; - } -} diff --git a/jdk/src/share/classes/com/sun/script/javascript/RhinoCompiledScript.java b/jdk/src/share/classes/com/sun/script/javascript/RhinoCompiledScript.java deleted file mode 100644 index 4c6a82481c5..00000000000 --- a/jdk/src/share/classes/com/sun/script/javascript/RhinoCompiledScript.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. - * 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.script.javascript; -import javax.script.*; -import sun.org.mozilla.javascript.internal.*; - -/** - * Represents compiled JavaScript code. - * - * @author Mike Grogan - * @since 1.6 - */ -final class RhinoCompiledScript extends CompiledScript { - - private RhinoScriptEngine engine; - private Script script; - - - RhinoCompiledScript(RhinoScriptEngine engine, Script script) { - this.engine = engine; - this.script = script; - } - - public Object eval(ScriptContext context) throws ScriptException { - - Object result = null; - Context cx = RhinoScriptEngine.enterContext(); - try { - - Scriptable scope = engine.getRuntimeScope(context); - Object ret = script.exec(cx, scope); - result = engine.unwrapReturnValue(ret); - } catch (RhinoException re) { - int line = (line = re.lineNumber()) == 0 ? -1 : line; - String msg; - if (re instanceof JavaScriptException) { - msg = String.valueOf(((JavaScriptException)re).getValue()); - } else { - msg = re.toString(); - } - ScriptException se = new ScriptException(msg, re.sourceName(), line); - se.initCause(re); - throw se; - } finally { - Context.exit(); - } - - return result; - } - - public ScriptEngine getEngine() { - return engine; - } - -} diff --git a/jdk/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java b/jdk/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java deleted file mode 100644 index d168a76437e..00000000000 --- a/jdk/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.script.javascript; -import com.sun.script.util.*; -import javax.script.*; -import sun.org.mozilla.javascript.internal.*; -import java.lang.reflect.Method; -import java.io.*; -import java.util.*; - - -/** - * Implementation of ScriptEngine using the Mozilla Rhino - * interpreter. - * - * @author Mike Grogan - * @author A. Sundararajan - * @since 1.6 - */ -public final class RhinoScriptEngine extends AbstractScriptEngine - implements Invocable, Compilable { - - private static final boolean DEBUG = false; - - /* Scope where standard JavaScript objects and our - * extensions to it are stored. Note that these are not - * user defined engine level global variables. These are - * variables have to be there on all compliant ECMAScript - * scopes. We put these standard objects in this top level. - */ - private RhinoTopLevel topLevel; - - /* map used to store indexed properties in engine scope - * refer to comment on 'indexedProps' in ExternalScriptable.java. - */ - private Map indexedProps; - - private ScriptEngineFactory factory; - private InterfaceImplementor implementor; - - private static final int languageVersion = getLanguageVersion(); - private static final int optimizationLevel = getOptimizationLevel(); - static { - ContextFactory.initGlobal(new ContextFactory() { - protected Context makeContext() { - Context cx = super.makeContext(); - cx.setLanguageVersion(languageVersion); - cx.setOptimizationLevel(optimizationLevel); - cx.setClassShutter(RhinoClassShutter.getInstance()); - cx.setWrapFactory(RhinoWrapFactory.getInstance()); - return cx; - } - }); - } - - private static final String RHINO_JS_VERSION = "rhino.js.version"; - private static int getLanguageVersion() { - int version; - String tmp = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction(RHINO_JS_VERSION)); - if (tmp != null) { - version = Integer.parseInt((String)tmp); - } else { - version = Context.VERSION_1_8; - } - return version; - } - - private static final String RHINO_OPT_LEVEL = "rhino.opt.level"; - private static int getOptimizationLevel() { - int optLevel = -1; - // disable optimizer under security manager, for now. - if (System.getSecurityManager() == null) { - optLevel = Integer.getInteger(RHINO_OPT_LEVEL, -1); - } - return optLevel; - } - - /** - * Creates a new instance of RhinoScriptEngine - */ - public RhinoScriptEngine() { - - Context cx = enterContext(); - try { - topLevel = new RhinoTopLevel(cx, this); - } finally { - cx.exit(); - } - - indexedProps = new HashMap(); - - //construct object used to implement getInterface - implementor = new InterfaceImplementor(this) { - protected boolean isImplemented(Object thiz, Class iface) { - Context cx = enterContext(); - try { - if (thiz != null && !(thiz instanceof Scriptable)) { - thiz = cx.toObject(thiz, topLevel); - } - Scriptable engineScope = getRuntimeScope(context); - Scriptable localScope = (thiz != null)? (Scriptable) thiz : - engineScope; - for (Method method : iface.getMethods()) { - // ignore methods of java.lang.Object class - if (method.getDeclaringClass() == Object.class) { - continue; - } - Object obj = ScriptableObject.getProperty(localScope, method.getName()); - if (! (obj instanceof Function)) { - return false; - } - } - return true; - } finally { - cx.exit(); - } - } - - protected Object convertResult(Method method, Object res) - throws ScriptException { - Class desiredType = method.getReturnType(); - if (desiredType == Void.TYPE) { - return null; - } else { - return Context.jsToJava(res, desiredType); - } - } - }; - } - - public Object eval(Reader reader, ScriptContext ctxt) - throws ScriptException { - Object ret; - - Context cx = enterContext(); - try { - Scriptable scope = getRuntimeScope(ctxt); - String filename = (String) get(ScriptEngine.FILENAME); - filename = filename == null ? "" : filename; - - ret = cx.evaluateReader(scope, reader, filename , 1, null); - } catch (RhinoException re) { - if (DEBUG) re.printStackTrace(); - int line = (line = re.lineNumber()) == 0 ? -1 : line; - String msg; - if (re instanceof JavaScriptException) { - msg = String.valueOf(((JavaScriptException)re).getValue()); - } else { - msg = re.toString(); - } - ScriptException se = new ScriptException(msg, re.sourceName(), line); - se.initCause(re); - throw se; - } catch (IOException ee) { - throw new ScriptException(ee); - } finally { - cx.exit(); - } - - return unwrapReturnValue(ret); - } - - public Object eval(String script, ScriptContext ctxt) throws ScriptException { - if (script == null) { - throw new NullPointerException("null script"); - } - return eval(new StringReader(script) , ctxt); - } - - public ScriptEngineFactory getFactory() { - if (factory != null) { - return factory; - } else { - return new RhinoScriptEngineFactory(); - } - } - - public Bindings createBindings() { - return new SimpleBindings(); - } - - //Invocable methods - public Object invokeFunction(String name, Object... args) - throws ScriptException, NoSuchMethodException { - return invoke(null, name, args); - } - - public Object invokeMethod(Object thiz, String name, Object... args) - throws ScriptException, NoSuchMethodException { - if (thiz == null) { - throw new IllegalArgumentException("script object can not be null"); - } - return invoke(thiz, name, args); - } - - private Object invoke(Object thiz, String name, Object... args) - throws ScriptException, NoSuchMethodException { - Context cx = enterContext(); - try { - if (name == null) { - throw new NullPointerException("method name is null"); - } - - if (thiz != null && !(thiz instanceof Scriptable)) { - thiz = cx.toObject(thiz, topLevel); - } - - Scriptable engineScope = getRuntimeScope(context); - Scriptable localScope = (thiz != null)? (Scriptable) thiz : - engineScope; - Object obj = ScriptableObject.getProperty(localScope, name); - if (! (obj instanceof Function)) { - throw new NoSuchMethodException("no such method: " + name); - } - - Function func = (Function) obj; - Scriptable scope = func.getParentScope(); - if (scope == null) { - scope = engineScope; - } - Object result = func.call(cx, scope, localScope, - wrapArguments(args)); - return unwrapReturnValue(result); - } catch (RhinoException re) { - if (DEBUG) re.printStackTrace(); - int line = (line = re.lineNumber()) == 0 ? -1 : line; - ScriptException se = new ScriptException(re.toString(), re.sourceName(), line); - se.initCause(re); - throw se; - } finally { - cx.exit(); - } - } - - public T getInterface(Class clasz) { - try { - return implementor.getInterface(null, clasz); - } catch (ScriptException e) { - return null; - } - } - - public T getInterface(Object thiz, Class clasz) { - if (thiz == null) { - throw new IllegalArgumentException("script object can not be null"); - } - - try { - return implementor.getInterface(thiz, clasz); - } catch (ScriptException e) { - return null; - } - } - - private static final String printSource = - "function print(str, newline) { \n" + - " if (typeof(str) == 'undefined') { \n" + - " str = 'undefined'; \n" + - " } else if (str == null) { \n" + - " str = 'null'; \n" + - " } \n" + - " var out = context.getWriter(); \n" + - " if (!(out instanceof java.io.PrintWriter))\n" + - " out = new java.io.PrintWriter(out); \n" + - " out.print(String(str)); \n" + - " if (newline) out.print('\\n'); \n" + - " out.flush(); \n" + - "}\n" + - "function println(str) { \n" + - " print(str, true); \n" + - "}"; - - Scriptable getRuntimeScope(ScriptContext ctxt) { - if (ctxt == null) { - throw new NullPointerException("null script context"); - } - - // we create a scope for the given ScriptContext - Scriptable newScope = new ExternalScriptable(ctxt, indexedProps); - - // Set the prototype of newScope to be 'topLevel' so that - // JavaScript standard objects are visible from the scope. - newScope.setPrototype(topLevel); - - // define "context" variable in the new scope - newScope.put("context", newScope, ctxt); - - // define "print", "println" functions in the new scope - Context cx = enterContext(); - try { - cx.evaluateString(newScope, printSource, "print", 1, null); - } finally { - cx.exit(); - } - return newScope; - } - - - //Compilable methods - public CompiledScript compile(String script) throws ScriptException { - return compile(new StringReader(script)); - } - - public CompiledScript compile(java.io.Reader script) throws ScriptException { - CompiledScript ret = null; - Context cx = enterContext(); - - try { - String fileName = (String) get(ScriptEngine.FILENAME); - if (fileName == null) { - fileName = ""; - } - - Scriptable scope = getRuntimeScope(context); - Script scr = cx.compileReader(scope, script, fileName, 1, null); - ret = new RhinoCompiledScript(this, scr); - } catch (Exception e) { - if (DEBUG) e.printStackTrace(); - throw new ScriptException(e); - } finally { - cx.exit(); - } - return ret; - } - - - //package-private helpers - - static Context enterContext() { - // call this always so that initializer of this class runs - // and initializes custom wrap factory and class shutter. - return Context.enter(); - } - - void setEngineFactory(ScriptEngineFactory fac) { - factory = fac; - } - - Object[] wrapArguments(Object[] args) { - if (args == null) { - return Context.emptyArgs; - } - Object[] res = new Object[args.length]; - for (int i = 0; i < res.length; i++) { - res[i] = Context.javaToJS(args[i], topLevel); - } - return res; - } - - Object unwrapReturnValue(Object result) { - if (result instanceof Wrapper) { - result = ( (Wrapper) result).unwrap(); - } - - return result instanceof Undefined ? null : result; - } - - /* - public static void main(String[] args) throws Exception { - if (args.length == 0) { - System.out.println("No file specified"); - return; - } - - InputStreamReader r = new InputStreamReader(new FileInputStream(args[0])); - ScriptEngine engine = new RhinoScriptEngine(); - - engine.put("x", "y"); - engine.put(ScriptEngine.FILENAME, args[0]); - engine.eval(r); - System.out.println(engine.get("x")); - } - */ -} diff --git a/jdk/src/share/classes/com/sun/script/javascript/RhinoScriptEngineFactory.java b/jdk/src/share/classes/com/sun/script/javascript/RhinoScriptEngineFactory.java deleted file mode 100644 index c81ac796d9b..00000000000 --- a/jdk/src/share/classes/com/sun/script/javascript/RhinoScriptEngineFactory.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * 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.script.javascript; -import javax.script.*; -import java.util.*; -import sun.org.mozilla.javascript.internal.*; -import com.sun.script.util.*; - -/** - * Factory to create RhinoScriptEngine - * - * @author Mike Grogan - * @since 1.6 - */ -public class RhinoScriptEngineFactory extends ScriptEngineFactoryBase { - - public RhinoScriptEngineFactory() { - } - - public List getExtensions() { - return extensions; - } - - public List getMimeTypes() { - return mimeTypes; - } - - public List getNames() { - return names; - } - - public Object getParameter(String key) { - if (key.equals(ScriptEngine.NAME)) { - return "javascript"; - } else if (key.equals(ScriptEngine.ENGINE)) { - return "Mozilla Rhino"; - } else if (key.equals(ScriptEngine.ENGINE_VERSION)) { - return "1.7 release 3 PRERELEASE"; - } else if (key.equals(ScriptEngine.LANGUAGE)) { - return "ECMAScript"; - } else if (key.equals(ScriptEngine.LANGUAGE_VERSION)) { - return "1.8"; - } else if (key.equals("THREADING")) { - return "MULTITHREADED"; - } else { - throw new IllegalArgumentException("Invalid key"); - } - } - - public ScriptEngine getScriptEngine() { - RhinoScriptEngine ret = new RhinoScriptEngine(); - ret.setEngineFactory(this); - return ret; - } - - public String getMethodCallSyntax(String obj, String method, String... args) { - - String ret = obj + "." + method + "("; - int len = args.length; - if (len == 0) { - ret += ")"; - return ret; - } - - for (int i = 0; i < len; i++) { - ret += args[i]; - if (i != len - 1) { - ret += ","; - } else { - ret += ")"; - } - } - return ret; - } - - public String getOutputStatement(String toDisplay) { - StringBuffer buf = new StringBuffer(); - int len = toDisplay.length(); - buf.append("print(\""); - for (int i = 0; i < len; i++) { - char ch = toDisplay.charAt(i); - switch (ch) { - case '"': - buf.append("\\\""); - break; - case '\\': - buf.append("\\\\"); - break; - default: - buf.append(ch); - break; - } - } - buf.append("\")"); - return buf.toString(); - } - - public String getProgram(String... statements) { - int len = statements.length; - String ret = ""; - for (int i = 0; i < len; i++) { - ret += statements[i] + ";"; - } - - return ret; - } - - /* - public static void main(String[] args) { - RhinoScriptEngineFactory fact = new RhinoScriptEngineFactory(); - System.out.println(fact.getParameter(ScriptEngine.ENGINE_VERSION)); - } - */ - - private static List names; - private static List mimeTypes; - private static List extensions; - - static { - names = new ArrayList(6); - names.add("js"); - names.add("rhino"); - names.add("JavaScript"); - names.add("javascript"); - names.add("ECMAScript"); - names.add("ecmascript"); - names = Collections.unmodifiableList(names); - - mimeTypes = new ArrayList(4); - mimeTypes.add("application/javascript"); - mimeTypes.add("application/ecmascript"); - mimeTypes.add("text/javascript"); - mimeTypes.add("text/ecmascript"); - mimeTypes = Collections.unmodifiableList(mimeTypes); - - extensions = new ArrayList(1); - extensions.add("js"); - extensions = Collections.unmodifiableList(extensions); - } -} diff --git a/jdk/src/share/classes/com/sun/script/javascript/RhinoTopLevel.java b/jdk/src/share/classes/com/sun/script/javascript/RhinoTopLevel.java deleted file mode 100644 index 45295bb7833..00000000000 --- a/jdk/src/share/classes/com/sun/script/javascript/RhinoTopLevel.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * 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.script.javascript; - -import sun.org.mozilla.javascript.internal.*; -import javax.script.*; - -/** - * This class serves as top level scope for Rhino. This class adds - * 3 top level functions (bindings, scope, sync) and two constructors - * (JSAdapter, JavaAdapter). - * - * @author A. Sundararajan - * @since 1.6 - */ -public final class RhinoTopLevel extends ImporterTopLevel { - RhinoTopLevel(Context cx, RhinoScriptEngine engine) { - super(cx); - this.engine = engine; - - - // initialize JSAdapter lazily. Reduces footprint & startup time. - new LazilyLoadedCtor(this, "JSAdapter", - "com.sun.script.javascript.JSAdapter", - false); - - /* - * initialize JavaAdapter. We can't lazy initialize this because - * lazy initializer attempts to define a new property. But, JavaAdapter - * is an exisiting property that we overwrite. - */ - JavaAdapter.init(cx, this, false); - - // add top level functions - String names[] = { "bindings", "scope", "sync" }; - defineFunctionProperties(names, RhinoTopLevel.class, - ScriptableObject.DONTENUM); - } - - /** - * The bindings function takes a JavaScript scope object - * of type ExternalScriptable and returns the underlying Bindings - * instance. - * - * var page = scope(pageBindings); - * with (page) { - * // code that uses page scope - * } - * var b = bindings(page); - * // operate on bindings here. - */ - public static Object bindings(Context cx, Scriptable thisObj, Object[] args, - Function funObj) { - if (args.length == 1) { - Object arg = args[0]; - if (arg instanceof Wrapper) { - arg = ((Wrapper)arg).unwrap(); - } - if (arg instanceof ExternalScriptable) { - ScriptContext ctx = ((ExternalScriptable)arg).getContext(); - Bindings bind = ctx.getBindings(ScriptContext.ENGINE_SCOPE); - return Context.javaToJS(bind, - ScriptableObject.getTopLevelScope(thisObj)); - } - } - return cx.getUndefinedValue(); - } - - /** - * The scope function creates a new JavaScript scope object - * with given Bindings object as backing store. This can be used - * to create a script scope based on arbitrary Bindings instance. - * For example, in webapp scenario, a 'page' level Bindings instance - * may be wrapped as a scope and code can be run in JavaScripe 'with' - * statement: - * - * var page = scope(pageBindings); - * with (page) { - * // code that uses page scope - * } - */ - public static Object scope(Context cx, Scriptable thisObj, Object[] args, - Function funObj) { - if (args.length == 1) { - Object arg = args[0]; - if (arg instanceof Wrapper) { - arg = ((Wrapper)arg).unwrap(); - } - if (arg instanceof Bindings) { - ScriptContext ctx = new SimpleScriptContext(); - ctx.setBindings((Bindings)arg, ScriptContext.ENGINE_SCOPE); - Scriptable res = new ExternalScriptable(ctx); - res.setPrototype(ScriptableObject.getObjectPrototype(thisObj)); - res.setParentScope(ScriptableObject.getTopLevelScope(thisObj)); - return res; - } - } - return cx.getUndefinedValue(); - } - - /** - * The sync function creates a synchronized function (in the sense - * of a Java synchronized method) from an existing function. The - * new function synchronizes on the this object of - * its invocation. - * js> var o = { f : sync(function(x) { - * print("entry"); - * Packages.java.lang.Thread.sleep(x*1000); - * print("exit"); - * })}; - * js> thread(function() {o.f(5);}); - * entry - * js> thread(function() {o.f(5);}); - * js> - * exit - * entry - * exit - */ - public static Object sync(Context cx, Scriptable thisObj, Object[] args, - Function funObj) { - if (args.length == 1 && args[0] instanceof Function) { - return new Synchronizer((Function)args[0]); - } else { - throw Context.reportRuntimeError("wrong argument(s) for sync"); - } - } - - RhinoScriptEngine getScriptEngine() { - return engine; - } - - private RhinoScriptEngine engine; -} diff --git a/jdk/src/share/classes/com/sun/script/javascript/RhinoWrapFactory.java b/jdk/src/share/classes/com/sun/script/javascript/RhinoWrapFactory.java deleted file mode 100644 index 906ffbab5bb..00000000000 --- a/jdk/src/share/classes/com/sun/script/javascript/RhinoWrapFactory.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. - * 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.script.javascript; - -import java.lang.reflect.*; -import static sun.security.util.SecurityConstants.*; -import sun.org.mozilla.javascript.internal.*; - -/** - * This wrap factory is used for security reasons. JSR 223 script - * engine interface and JavaScript engine classes are run as bootstrap - * classes. For example, java.lang.Class.forName method (when called without - * class loader) uses caller's class loader. This may be exploited by script - * authors to access classes otherwise not accessible. For example, - * classes in sun.* namespace are normally not accessible to untrusted - * code and hence should not be accessible to JavaScript run from - * untrusted code. - * - * @author A. Sundararajan - * @since 1.6 - */ -final class RhinoWrapFactory extends WrapFactory { - private RhinoWrapFactory() {} - private static RhinoWrapFactory theInstance; - - static synchronized WrapFactory getInstance() { - if (theInstance == null) { - theInstance = new RhinoWrapFactory(); - } - return theInstance; - } - - // We use instance of this class to wrap security sensitive - // Java object. Please refer below. - private static class RhinoJavaObject extends NativeJavaObject { - RhinoJavaObject(Scriptable scope, Object obj, Class type) { - // we pass 'null' to object. NativeJavaObject uses - // passed 'type' to reflect fields and methods when - // object is null. - super(scope, null, type); - - // Now, we set actual object. 'javaObject' is protected - // field of NativeJavaObject. - javaObject = obj; - } - } - - public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, - Object javaObject, Class staticType) { - SecurityManager sm = System.getSecurityManager(); - ClassShutter classShutter = RhinoClassShutter.getInstance(); - if (javaObject instanceof ClassLoader) { - // Check with Security Manager whether we can expose a - // ClassLoader... - if (sm != null) { - sm.checkPermission(GET_CLASSLOADER_PERMISSION); - } - // if we fall through here, check permission succeeded. - return super.wrapAsJavaObject(cx, scope, javaObject, staticType); - } else { - String name = null; - if (javaObject instanceof Class) { - name = ((Class)javaObject).getName(); - } else if (javaObject instanceof Member) { - Member member = (Member) javaObject; - // Check member access. Don't allow reflective access to - // non-public members. Note that we can't call checkMemberAccess - // because that expects exact stack depth! - if (sm != null && !Modifier.isPublic(member.getModifiers())) { - return null; - } - name = member.getDeclaringClass().getName(); - } - // Now, make sure that no ClassShutter prevented Class or Member - // of it is accessed reflectively. Note that ClassShutter may - // prevent access to a class, even though SecurityManager permit. - if (name != null) { - if (!classShutter.visibleToScripts(name)) { - return null; - } else { - return super.wrapAsJavaObject(cx, scope, javaObject, staticType); - } - } - } - - // we have got some non-reflective object. - Class dynamicType = javaObject.getClass(); - String name = dynamicType.getName(); - if (!classShutter.visibleToScripts(name)) { - // Object of some sensitive class (such as sun.net.www.* - // objects returned from public method of java.net.URL class. - // We expose this object as though it is an object of some - // super class that is safe for access. - - Class type = null; - - // Whenever a Java Object is wrapped, we are passed with a - // staticType which is the type found from environment. For - // example, method return type known from signature. The dynamic - // type would be the actual Class of the actual returned object. - // If the staticType is an interface, we just use that type. - if (staticType != null && staticType.isInterface()) { - type = staticType; - } else { - // dynamicType is always a class type and never an interface. - // find an accessible super class of the dynamic type. - while (dynamicType != null) { - dynamicType = dynamicType.getSuperclass(); - name = dynamicType.getName(); - if (classShutter.visibleToScripts(name)) { - type = dynamicType; break; - } - } - // atleast java.lang.Object has to be accessible. So, when - // we reach here, type variable should not be null. - assert type != null: - "even java.lang.Object is not accessible?"; - } - // create custom wrapper with the 'safe' type. - return new RhinoJavaObject(scope, javaObject, type); - } else { - return super.wrapAsJavaObject(cx, scope, javaObject, staticType); - } - } -} diff --git a/jdk/src/share/classes/com/sun/script/util/BindingsBase.java b/jdk/src/share/classes/com/sun/script/util/BindingsBase.java deleted file mode 100644 index de0704cb164..00000000000 --- a/jdk/src/share/classes/com/sun/script/util/BindingsBase.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. - * 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.script.util; - -import javax.script.Bindings; -import java.util.Map; -import java.util.AbstractMap; - -/** - * Abstract super class for Bindings implementations - * - * @author Mike Grogan - * @since 1.6 - */ -public abstract class BindingsBase extends AbstractMap - implements Bindings { - - //AbstractMap methods - public Object get(Object name) { - checkKey(name); - return getImpl((String)name); - } - - public Object remove(Object key) { - checkKey(key); - return removeImpl((String)key); - } - - public Object put(String key, Object value) { - checkKey(key); - return putImpl(key, value); - } - - public void putAll(Map toMerge) { - for (Map.Entry entry : toMerge.entrySet()) { - String key = entry.getKey(); - checkKey(key); - putImpl(entry.getKey(), entry.getValue()); - } - } - - //BindingsBase methods - public abstract Object putImpl(String name, Object value); - public abstract Object getImpl(String name); - public abstract Object removeImpl(String name); - public abstract String[] getNames(); - - protected void checkKey(Object key) { - if (key == null) { - throw new NullPointerException("key can not be null"); - } - if (!(key instanceof String)) { - throw new ClassCastException("key should be String"); - } - if (key.equals("")) { - throw new IllegalArgumentException("key can not be empty"); - } - } -} diff --git a/jdk/src/share/classes/com/sun/script/util/BindingsEntrySet.java b/jdk/src/share/classes/com/sun/script/util/BindingsEntrySet.java deleted file mode 100644 index 37558441106..00000000000 --- a/jdk/src/share/classes/com/sun/script/util/BindingsEntrySet.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. - * 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.script.util; -import java.util.*; - -/** - * Entry set implementation for Bindings implementations - * - * @author Mike Grogan - * @since 1.6 - */ -public class BindingsEntrySet extends AbstractSet> { - - private BindingsBase base; - private String[] keys; - - public BindingsEntrySet(BindingsBase base) { - this.base = base; - keys = base.getNames(); - } - - public int size() { - return keys.length; - } - - public Iterator> iterator() { - return new BindingsIterator(); - } - - public class BindingsEntry implements Map.Entry { - private String key; - public BindingsEntry(String key) { - this.key = key; - } - - public Object setValue(Object value) { - throw new UnsupportedOperationException(); - } - - public String getKey() { - return key; - } - - public Object getValue() { - return base.get(key); - } - - } - - public class BindingsIterator implements Iterator> { - - private int current = 0; - private boolean stale = false; - - public boolean hasNext() { - return (current < keys.length); - } - - public BindingsEntry next() { - stale = false; - return new BindingsEntry(keys[current++]); - } - - public void remove() { - if (stale || current == 0) { - throw new IllegalStateException(); - } - - stale = true; - base.remove(keys[current - 1]); - } - - } - -} diff --git a/jdk/src/share/classes/com/sun/script/util/BindingsImpl.java b/jdk/src/share/classes/com/sun/script/util/BindingsImpl.java deleted file mode 100644 index 44eed886565..00000000000 --- a/jdk/src/share/classes/com/sun/script/util/BindingsImpl.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. - * 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.script.util; -import java.util.*; -import javax.script.Bindings; - -/* - * Abstract super class for Bindings implementations. Handles - * global and local scopes. - * - * @author Mike Grogan - * @since 1.6 - */ -public abstract class BindingsImpl extends BindingsBase { - - //get method delegates to global if key is not defined in - //base class or local scope - protected Bindings global = null; - - //get delegates to local scope - protected Bindings local = null; - - public void setGlobal(Bindings n) { - global = n; - } - - public void setLocal(Bindings n) { - local = n; - } - - public Set> entrySet() { - return new BindingsEntrySet(this); - } - - public Object get(Object key) { - checkKey(key); - - Object ret = null; - if ((local != null) && (null != (ret = local.get(key)))) { - return ret; - } - - ret = getImpl((String)key); - - if (ret != null) { - return ret; - } else if (global != null) { - return global.get(key); - } else { - return null; - } - } - - public Object remove(Object key) { - checkKey(key); - Object ret = get(key); - if (ret != null) { - removeImpl((String)key); - } - return ret; - } -} diff --git a/jdk/src/share/classes/com/sun/script/util/InterfaceImplementor.java b/jdk/src/share/classes/com/sun/script/util/InterfaceImplementor.java deleted file mode 100644 index 7e94c962f5c..00000000000 --- a/jdk/src/share/classes/com/sun/script/util/InterfaceImplementor.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.script.util; - -import javax.script.*; -import java.lang.reflect.*; -import java.security.*; - -/* - * java.lang.reflect.Proxy based interface implementor. This is meant - * to be used to implement Invocable.getInterface. - * - * @author Mike Grogan - * @since 1.6 - */ -public class InterfaceImplementor { - - private Invocable engine; - - /** Creates a new instance of Invocable */ - public InterfaceImplementor(Invocable engine) { - this.engine = engine; - } - - private final class InterfaceImplementorInvocationHandler - implements InvocationHandler { - private Object thiz; - private AccessControlContext accCtxt; - - public InterfaceImplementorInvocationHandler(Object thiz, - AccessControlContext accCtxt) { - this.thiz = thiz; - this.accCtxt = accCtxt; - } - - public Object invoke(Object proxy , Method method, Object[] args) - throws java.lang.Throwable { - // give chance to convert input args - args = convertArguments(method, args); - Object result; - final Method m = method; - final Object[] a = args; - result = AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception { - if (thiz == null) { - return engine.invokeFunction(m.getName(), a); - } else { - return engine.invokeMethod(thiz, m.getName(), a); - } - } - }, accCtxt); - // give chance to convert the method result - return convertResult(method, result); - } - } - - public T getInterface(Object thiz, Class iface) - throws ScriptException { - if (iface == null || !iface.isInterface()) { - throw new IllegalArgumentException("interface Class expected"); - } - if (! isImplemented(thiz, iface)) { - return null; - } - AccessControlContext accCtxt = AccessController.getContext(); - return iface.cast(Proxy.newProxyInstance(iface.getClassLoader(), - new Class[]{iface}, - new InterfaceImplementorInvocationHandler(thiz, accCtxt))); - } - - protected boolean isImplemented(Object thiz, Class iface) { - return true; - } - - // called to convert method result after invoke - protected Object convertResult(Method method, Object res) - throws ScriptException { - // default is identity conversion - return res; - } - - // called to convert method arguments before invoke - protected Object[] convertArguments(Method method, Object[] args) - throws ScriptException { - // default is identity conversion - return args; - } -} diff --git a/jdk/src/share/classes/com/sun/security/sasl/digest/DigestMD5Client.java b/jdk/src/share/classes/com/sun/security/sasl/digest/DigestMD5Client.java index 07072e3c898..44cee0bf7b9 100644 --- a/jdk/src/share/classes/com/sun/security/sasl/digest/DigestMD5Client.java +++ b/jdk/src/share/classes/com/sun/security/sasl/digest/DigestMD5Client.java @@ -348,14 +348,23 @@ final class DigestMD5Client extends DigestMD5Base implements SaslClient { 0, false); cbh.handle(new Callback[] {ccb, ncb, pcb}); - /* Acquire realm from RealmChoiceCallback*/ - negotiatedRealm = realmTokens[ccb.getSelectedIndexes()[0]]; + // Acquire realm from RealmChoiceCallback + int[] selected = ccb.getSelectedIndexes(); + if (selected == null + || selected[0] < 0 + || selected[0] >= realmTokens.length) { + throw new SaslException("DIGEST-MD5: Invalid realm chosen"); + } + negotiatedRealm = realmTokens[selected[0]]; } passwd = pcb.getPassword(); pcb.clearPassword(); username = ncb.getName(); + } catch (SaslException se) { + throw se; + } catch (UnsupportedCallbackException e) { throw new SaslException("DIGEST-MD5: Cannot perform callback to " + "acquire realm, authentication ID or password", e); diff --git a/jdk/src/share/classes/com/sun/tools/jdi/AbstractLauncher.java b/jdk/src/share/classes/com/sun/tools/jdi/AbstractLauncher.java index 1299201267a..736da0a05d3 100644 --- a/jdk/src/share/classes/com/sun/tools/jdi/AbstractLauncher.java +++ b/jdk/src/share/classes/com/sun/tools/jdi/AbstractLauncher.java @@ -142,7 +142,7 @@ abstract class AbstractLauncher extends ConnectorImpl implements LaunchingConnec * This class simply provides a context for a single launch and * accept. It provides instance fields that can be used by * all threads involved. This stuff can't be in the Connector proper - * because the connector is is a singleton and not specific to any + * because the connector is a singleton and is not specific to any * one launch. */ private class Helper { diff --git a/jdk/src/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java b/jdk/src/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java index b5086fd9d5f..20be57c85c4 100644 --- a/jdk/src/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java +++ b/jdk/src/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java @@ -213,7 +213,7 @@ public class SunCommandLineLauncher extends AbstractLauncher implements Launchin exePath = exe; } // Quote only if necessary in case the quote arg value is bogus - if (hasWhitespace(exe)) { + if (hasWhitespace(exePath)) { exePath = quote + exePath + quote; } diff --git a/jdk/src/share/classes/java/awt/Component.java b/jdk/src/share/classes/java/awt/Component.java index 0dfb99996db..846ea976450 100644 --- a/jdk/src/share/classes/java/awt/Component.java +++ b/jdk/src/share/classes/java/awt/Component.java @@ -1671,6 +1671,15 @@ public abstract class Component implements ImageObserver, MenuContainer, /* do nothing */ } + /* + * Delete references from LightweithDispatcher of a heavyweight parent + */ + void clearLightweightDispatcherOnRemove(Component removedComponent) { + if (parent != null) { + parent.clearLightweightDispatcherOnRemove(removedComponent); + } + } + /** * @deprecated As of JDK version 1.1, * replaced by setVisible(boolean). @@ -6974,6 +6983,8 @@ public abstract class Component implements ImageObserver, MenuContainer, } synchronized (getTreeLock()) { + clearLightweightDispatcherOnRemove(this); + if (isFocusOwner() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) { transferFocus(true); } diff --git a/jdk/src/share/classes/java/awt/Container.java b/jdk/src/share/classes/java/awt/Container.java index 1118852f0e9..1525a7497c2 100644 --- a/jdk/src/share/classes/java/awt/Container.java +++ b/jdk/src/share/classes/java/awt/Container.java @@ -3306,6 +3306,16 @@ public class Container extends Component { } } + @Override + void clearLightweightDispatcherOnRemove(Component removedComponent) { + if (dispatcher != null) { + dispatcher.removeReferences(removedComponent); + } else { + //It is a Lightweight Container, should clear parent`s Dispatcher + super.clearLightweightDispatcherOnRemove(removedComponent); + } + } + final Container getTraversalRoot() { if (isFocusCycleRoot()) { return findTraversalRoot(); @@ -4411,6 +4421,7 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener { //System.out.println("Disposing lw dispatcher"); stopListeningForOtherDrags(); mouseEventTarget = null; + targetLastEntered = null; } /** @@ -4502,6 +4513,7 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener { // MOUSE_CLICKED. if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) { mouseEventTarget = (mouseOver != nativeContainer) ? mouseOver: null; + isCleaned = false; } if (mouseEventTarget != null) { @@ -4545,10 +4557,14 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener { retargetMouseEvent(mouseOver, id, e); break; } - //Consuming of wheel events is implemented in "retargetMouseEvent". - if (id != MouseEvent.MOUSE_WHEEL) { - e.consume(); - } + //Consuming of wheel events is implemented in "retargetMouseEvent". + if (id != MouseEvent.MOUSE_WHEEL) { + e.consume(); + } + } else if (isCleaned && id != MouseEvent.MOUSE_WHEEL) { + //After mouseEventTarget was removed and cleaned should consume all events + //until new mouseEventTarget is found + e.consume(); } return e.isConsumed(); } @@ -4891,6 +4907,11 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener { */ private transient Component targetLastEntered; + /** + * Indicates whether {@code mouseEventTarget} was removed and nulled + */ + private transient boolean isCleaned; + /** * Is the mouse over the native container */ @@ -4925,4 +4946,14 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener { AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_WHEEL_EVENT_MASK; + + void removeReferences(Component removedComponent) { + if (mouseEventTarget == removedComponent) { + isCleaned = true; + mouseEventTarget = null; + } + if (targetLastEntered == removedComponent) { + targetLastEntered = null; + } + } } diff --git a/jdk/src/share/classes/java/io/BufferedReader.java b/jdk/src/share/classes/java/io/BufferedReader.java index 556abb2a403..d742233a0fd 100644 --- a/jdk/src/share/classes/java/io/BufferedReader.java +++ b/jdk/src/share/classes/java/io/BufferedReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,13 @@ package java.io; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + /** * Reads text from a character-input stream, buffering characters so as to * provide for the efficient reading of characters, arrays, and lines. @@ -522,4 +529,64 @@ public class BufferedReader extends Reader { } } } + + /** + * Returns a {@code Stream}, the elements of which are lines read from + * this {@code BufferedReader}. The {@link Stream} is lazily populated, + * i.e, read only occurs during the + * terminal + * stream operation. + * + *

The reader must not be operated on during the execution of the + * terminal stream operation. Otherwise, the result of the terminal stream + * operation is undefined. + * + *

After execution of the terminal stream operation there are no + * guarantees that the reader will be at a specific position from which to + * read the next character or line. + * + *

If an {@link IOException} is thrown when accessing the underlying + * {@code BufferedReader}, it is wrapped in an {@link + * UncheckedIOException} which will be thrown from the {@code Stream} + * method that caused the read to take place. This method will return a + * Stream if invoked on a BufferedReader that is closed. Any operation on + * that stream requires reading from the BufferedReader after is it closed + * will cause an UncheckedIOException to be thrown. + * + * @return a {@code Stream} providing the lines of text + * described by this {@code BufferedReader} + * + * @since 1.8 + */ + public Stream lines() { + Iterator iter = new Iterator() { + String nextLine = null; + + @Override + public boolean hasNext() { + if (nextLine != null) { + return true; + } else { + try { + nextLine = readLine(); + return (nextLine != null); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + } + + @Override + public String next() { + if (nextLine != null || hasNext()) { + String line = nextLine; + nextLine = null; + return line; + } else { + throw new NoSuchElementException(); + } + } + }; + return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iter, Spliterator.ORDERED)); + } } diff --git a/jdk/src/share/classes/java/io/File.java b/jdk/src/share/classes/java/io/File.java index dd313dd97d0..1f1d044b1ab 100644 --- a/jdk/src/share/classes/java/io/File.java +++ b/jdk/src/share/classes/java/io/File.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -156,7 +156,7 @@ public class File private static final FileSystem fs = DefaultFileSystem.getFileSystem(); /** - * This abstract pathname's normalized pathname string. A normalized + * This abstract pathname's normalized pathname string. A normalized * pathname string uses the default name-separator character and does not * contain any duplicate or redundant separators. * @@ -164,6 +164,32 @@ public class File */ private final String path; + /** + * Enum type that indicates the status of a file path. + */ + private static enum PathStatus { INVALID, CHECKED }; + + /** + * The flag indicating whether the file path is invalid. + */ + private transient PathStatus status = null; + + /** + * Check if the file has an invalid path. Currently, the inspection of + * a file path is very limited, and it only covers Nul character check. + * Returning true means the path is definitely invalid/garbage. But + * returning false does not guarantee that the path is valid. + * + * @return true if the file path is invalid. + */ + final boolean isInvalid() { + if (status == null) { + status = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED + : PathStatus.INVALID; + } + return status == PathStatus.INVALID; + } + /** * The length of this abstract pathname's prefix, or zero if it has no * prefix. @@ -586,6 +612,9 @@ public class File * @see Path#toRealPath */ public String getCanonicalPath() throws IOException { + if (isInvalid()) { + throw new IOException("Invalid file path"); + } return fs.canonicalize(fs.resolve(this)); } @@ -651,6 +680,9 @@ public class File */ @Deprecated public URL toURL() throws MalformedURLException { + if (isInvalid()) { + throw new MalformedURLException("Invalid file path"); + } return new URL("file", "", slashify(getAbsolutePath(), isDirectory())); } @@ -730,6 +762,9 @@ public class File if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return false; + } return fs.checkAccess(this, FileSystem.ACCESS_READ); } @@ -755,6 +790,9 @@ public class File if (security != null) { security.checkWrite(path); } + if (isInvalid()) { + return false; + } return fs.checkAccess(this, FileSystem.ACCESS_WRITE); } @@ -775,6 +813,9 @@ public class File if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return false; + } return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0); } @@ -802,6 +843,9 @@ public class File if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return false; + } return ((fs.getBooleanAttributes(this) & FileSystem.BA_DIRECTORY) != 0); } @@ -832,6 +876,9 @@ public class File if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return false; + } return ((fs.getBooleanAttributes(this) & FileSystem.BA_REGULAR) != 0); } @@ -858,6 +905,9 @@ public class File if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return false; + } return ((fs.getBooleanAttributes(this) & FileSystem.BA_HIDDEN) != 0); } @@ -887,6 +937,9 @@ public class File if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return 0L; + } return fs.getLastModifiedTime(this); } @@ -915,6 +968,9 @@ public class File if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return 0L; + } return fs.getLength(this); } @@ -950,6 +1006,9 @@ public class File public boolean createNewFile() throws IOException { SecurityManager security = System.getSecurityManager(); if (security != null) security.checkWrite(path); + if (isInvalid()) { + throw new IOException("Invalid file path"); + } return fs.createFileExclusively(path); } @@ -976,6 +1035,9 @@ public class File if (security != null) { security.checkDelete(path); } + if (isInvalid()) { + return false; + } return fs.delete(this); } @@ -1011,6 +1073,9 @@ public class File if (security != null) { security.checkDelete(path); } + if (isInvalid()) { + return; + } DeleteOnExitHook.add(path); } @@ -1051,6 +1116,9 @@ public class File if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return null; + } return fs.list(this); } @@ -1242,6 +1310,9 @@ public class File if (security != null) { security.checkWrite(path); } + if (isInvalid()) { + return false; + } return fs.createDirectory(this); } @@ -1317,6 +1388,12 @@ public class File security.checkWrite(path); security.checkWrite(dest.path); } + if (dest == null) { + throw new NullPointerException(); + } + if (this.isInvalid() || dest.isInvalid()) { + return false; + } return fs.rename(this, dest); } @@ -1352,6 +1429,9 @@ public class File if (security != null) { security.checkWrite(path); } + if (isInvalid()) { + return false; + } return fs.setLastModifiedTime(this, time); } @@ -1379,6 +1459,9 @@ public class File if (security != null) { security.checkWrite(path); } + if (isInvalid()) { + return false; + } return fs.setReadOnly(this); } @@ -1419,6 +1502,9 @@ public class File if (security != null) { security.checkWrite(path); } + if (isInvalid()) { + return false; + } return fs.setPermission(this, FileSystem.ACCESS_WRITE, writable, ownerOnly); } @@ -1493,6 +1579,9 @@ public class File if (security != null) { security.checkWrite(path); } + if (isInvalid()) { + return false; + } return fs.setPermission(this, FileSystem.ACCESS_READ, readable, ownerOnly); } @@ -1570,6 +1659,9 @@ public class File if (security != null) { security.checkWrite(path); } + if (isInvalid()) { + return false; + } return fs.setPermission(this, FileSystem.ACCESS_EXECUTE, executable, ownerOnly); } @@ -1629,6 +1721,9 @@ public class File if (security != null) { security.checkExec(path); } + if (isInvalid()) { + return false; + } return fs.checkAccess(this, FileSystem.ACCESS_EXECUTE); } @@ -1705,6 +1800,9 @@ public class File sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); sm.checkRead(path); } + if (isInvalid()) { + return 0L; + } return fs.getSpace(this, FileSystem.SPACE_TOTAL); } @@ -1721,7 +1819,7 @@ public class File * makes no guarantee that write operations to this file system * will succeed. * - * @return The number of unallocated bytes on the partition 0L + * @return The number of unallocated bytes on the partition or 0L * if the abstract pathname does not name a partition. This * value will be less than or equal to the total file system size * returned by {@link #getTotalSpace}. @@ -1740,6 +1838,9 @@ public class File sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); sm.checkRead(path); } + if (isInvalid()) { + return 0L; + } return fs.getSpace(this, FileSystem.SPACE_FREE); } @@ -1778,6 +1879,9 @@ public class File sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); sm.checkRead(path); } + if (isInvalid()) { + return 0L; + } return fs.getSpace(this, FileSystem.SPACE_USABLE); } @@ -1787,8 +1891,8 @@ public class File private TempDirectory() { } // temporary directory location - private static final File tmpdir = new File(fs.normalize(AccessController - .doPrivileged(new GetPropertyAction("java.io.tmpdir")))); + private static final File tmpdir = new File(AccessController + .doPrivileged(new GetPropertyAction("java.io.tmpdir"))); static File location() { return tmpdir; } @@ -1899,6 +2003,9 @@ public class File throw se; } } + if (f.isInvalid()) { + throw new IOException("Unable to create temporary file"); + } } while (!fs.createFileExclusively(f.getPath())); return f; } diff --git a/jdk/src/share/classes/java/io/FileInputStream.java b/jdk/src/share/classes/java/io/FileInputStream.java index d796bf090f0..740b6744047 100644 --- a/jdk/src/share/classes/java/io/FileInputStream.java +++ b/jdk/src/share/classes/java/io/FileInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -123,6 +123,9 @@ class FileInputStream extends InputStream if (name == null) { throw new NullPointerException(); } + if (file.isInvalid()) { + throw new FileNotFoundException("Invalid file path"); + } fd = new FileDescriptor(); fd.attach(this); open(name); diff --git a/jdk/src/share/classes/java/io/FileOutputStream.java b/jdk/src/share/classes/java/io/FileOutputStream.java index 50bd29bef5f..928e4f3cf15 100644 --- a/jdk/src/share/classes/java/io/FileOutputStream.java +++ b/jdk/src/share/classes/java/io/FileOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -196,6 +196,9 @@ class FileOutputStream extends OutputStream if (name == null) { throw new NullPointerException(); } + if (file.isInvalid()) { + throw new FileNotFoundException("Invalid file path"); + } this.fd = new FileDescriptor(); fd.attach(this); this.append = append; diff --git a/jdk/src/share/classes/java/io/RandomAccessFile.java b/jdk/src/share/classes/java/io/RandomAccessFile.java index cf1e5c7cef4..adccfbc757a 100644 --- a/jdk/src/share/classes/java/io/RandomAccessFile.java +++ b/jdk/src/share/classes/java/io/RandomAccessFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -228,6 +228,9 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { if (name == null) { throw new NullPointerException(); } + if (file.isInvalid()) { + throw new FileNotFoundException("Invalid file path"); + } fd = new FileDescriptor(); fd.attach(this); open(name, imode); diff --git a/jdk/src/share/classes/java/io/UncheckedIOException.java b/jdk/src/share/classes/java/io/UncheckedIOException.java new file mode 100644 index 00000000000..22c43e38079 --- /dev/null +++ b/jdk/src/share/classes/java/io/UncheckedIOException.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.io; + +import java.util.Objects; + +/** + * Wraps an {@link IOException} with an unchecked exception. + * + * @since 1.8 + */ +public class UncheckedIOException extends RuntimeException { + private static final long serialVersionUID = -8134305061645241065L; + + /** + * Constructs an instance of this class. + * + * @param message + * the detail message, can be null + * @param cause + * the {@code IOException} + * + * @throws NullPointerException + * if the cause is {@code null} + */ + public UncheckedIOException(String message, IOException cause) { + super(message, Objects.requireNonNull(cause)); + } + + /** + * Constructs an instance of this class. + * + * @param cause + * the {@code IOException} + * + * @throws NullPointerException + * if the cause is {@code null} + */ + public UncheckedIOException(IOException cause) { + super(Objects.requireNonNull(cause)); + } + + /** + * Returns the cause of this exception. + * + * @return the {@code IOException} which is the cause of this exception. + */ + @Override + public IOException getCause() { + return (IOException) super.getCause(); + } + + /** + * Called to read the object from a stream. + * + * @throws InvalidObjectException + * if the object is invalid or has a cause that is not + * an {@code IOException} + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + Throwable cause = super.getCause(); + if (!(cause instanceof IOException)) + throw new InvalidObjectException("Cause must be an IOException"); + } +} diff --git a/jdk/src/share/classes/java/lang/ProcessBuilder.java b/jdk/src/share/classes/java/lang/ProcessBuilder.java index 64f56d77829..b467f45c351 100644 --- a/jdk/src/share/classes/java/lang/ProcessBuilder.java +++ b/jdk/src/share/classes/java/lang/ProcessBuilder.java @@ -29,7 +29,6 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.FileOutputStream; import java.security.AccessControlException; import java.util.Arrays; import java.util.ArrayList; @@ -1024,10 +1023,10 @@ public final class ProcessBuilder dir, redirects, redirectErrorStream); - } catch (IOException e) { + } catch (IOException | IllegalArgumentException e) { String exceptionInfo = ": " + e.getMessage(); Throwable cause = e; - if (security != null) { + if ((e instanceof IOException) && security != null) { // Can not disclose the fail reason for read-protected files. try { security.checkRead(prog); diff --git a/jdk/src/share/classes/java/lang/StringBuffer.java b/jdk/src/share/classes/java/lang/StringBuffer.java index f31a53c98e6..8ead0721ffd 100644 --- a/jdk/src/share/classes/java/lang/StringBuffer.java +++ b/jdk/src/share/classes/java/lang/StringBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package java.lang; +import java.util.Arrays; /** * A thread-safe, mutable sequence of characters. @@ -98,6 +99,12 @@ package java.lang; implements java.io.Serializable, CharSequence { + /** + * A cache of the last value returned by toString. Cleared + * whenever the StringBuffer is modified. + */ + private transient char[] toStringCache; + /** use serialVersionUID from JDK 1.0.2 for interoperability */ static final long serialVersionUID = 3388685877147921107L; @@ -183,6 +190,7 @@ package java.lang; */ @Override public synchronized void setLength(int newLength) { + toStringCache = null; super.setLength(newLength); } @@ -247,17 +255,20 @@ package java.lang; public synchronized void setCharAt(int index, char ch) { if ((index < 0) || (index >= count)) throw new StringIndexOutOfBoundsException(index); + toStringCache = null; value[index] = ch; } @Override public synchronized StringBuffer append(Object obj) { + toStringCache = null; super.append(String.valueOf(obj)); return this; } @Override public synchronized StringBuffer append(String str) { + toStringCache = null; super.append(str); return this; } @@ -287,6 +298,7 @@ package java.lang; * @since 1.4 */ public synchronized StringBuffer append(StringBuffer sb) { + toStringCache = null; super.append(sb); return this; } @@ -296,6 +308,7 @@ package java.lang; */ @Override synchronized StringBuffer append(AbstractStringBuilder asb) { + toStringCache = null; super.append(asb); return this; } @@ -325,6 +338,7 @@ package java.lang; public StringBuffer append(CharSequence s) { // Note, synchronization achieved via invocations of other StringBuffer methods after // narrowing of s to specific type + // Ditto for toStringCache clearing super.append(s); return this; } @@ -336,12 +350,14 @@ package java.lang; @Override public synchronized StringBuffer append(CharSequence s, int start, int end) { + toStringCache = null; super.append(s, start, end); return this; } @Override public synchronized StringBuffer append(char[] str) { + toStringCache = null; super.append(str); return this; } @@ -351,24 +367,28 @@ package java.lang; */ @Override public synchronized StringBuffer append(char[] str, int offset, int len) { + toStringCache = null; super.append(str, offset, len); return this; } @Override public synchronized StringBuffer append(boolean b) { + toStringCache = null; super.append(b); return this; } @Override public synchronized StringBuffer append(char c) { + toStringCache = null; super.append(c); return this; } @Override public synchronized StringBuffer append(int i) { + toStringCache = null; super.append(i); return this; } @@ -378,24 +398,28 @@ package java.lang; */ @Override public synchronized StringBuffer appendCodePoint(int codePoint) { + toStringCache = null; super.appendCodePoint(codePoint); return this; } @Override public synchronized StringBuffer append(long lng) { + toStringCache = null; super.append(lng); return this; } @Override public synchronized StringBuffer append(float f) { + toStringCache = null; super.append(f); return this; } @Override public synchronized StringBuffer append(double d) { + toStringCache = null; super.append(d); return this; } @@ -406,6 +430,7 @@ package java.lang; */ @Override public synchronized StringBuffer delete(int start, int end) { + toStringCache = null; super.delete(start, end); return this; } @@ -416,6 +441,7 @@ package java.lang; */ @Override public synchronized StringBuffer deleteCharAt(int index) { + toStringCache = null; super.deleteCharAt(index); return this; } @@ -426,6 +452,7 @@ package java.lang; */ @Override public synchronized StringBuffer replace(int start, int end, String str) { + toStringCache = null; super.replace(start, end, str); return this; } @@ -465,6 +492,7 @@ package java.lang; public synchronized StringBuffer insert(int index, char[] str, int offset, int len) { + toStringCache = null; super.insert(index, str, offset, len); return this; } @@ -474,6 +502,7 @@ package java.lang; */ @Override public synchronized StringBuffer insert(int offset, Object obj) { + toStringCache = null; super.insert(offset, String.valueOf(obj)); return this; } @@ -483,6 +512,7 @@ package java.lang; */ @Override public synchronized StringBuffer insert(int offset, String str) { + toStringCache = null; super.insert(offset, str); return this; } @@ -492,6 +522,7 @@ package java.lang; */ @Override public synchronized StringBuffer insert(int offset, char[] str) { + toStringCache = null; super.insert(offset, str); return this; } @@ -504,6 +535,7 @@ package java.lang; public StringBuffer insert(int dstOffset, CharSequence s) { // Note, synchronization achieved via invocations of other StringBuffer methods // after narrowing of s to specific type + // Ditto for toStringCache clearing super.insert(dstOffset, s); return this; } @@ -516,6 +548,7 @@ package java.lang; public synchronized StringBuffer insert(int dstOffset, CharSequence s, int start, int end) { + toStringCache = null; super.insert(dstOffset, s, start, end); return this; } @@ -527,6 +560,7 @@ package java.lang; public StringBuffer insert(int offset, boolean b) { // Note, synchronization achieved via invocation of StringBuffer insert(int, String) // after conversion of b to String by super class method + // Ditto for toStringCache clearing super.insert(offset, b); return this; } @@ -536,6 +570,7 @@ package java.lang; */ @Override public synchronized StringBuffer insert(int offset, char c) { + toStringCache = null; super.insert(offset, c); return this; } @@ -547,6 +582,7 @@ package java.lang; public StringBuffer insert(int offset, int i) { // Note, synchronization achieved via invocation of StringBuffer insert(int, String) // after conversion of i to String by super class method + // Ditto for toStringCache clearing super.insert(offset, i); return this; } @@ -558,6 +594,7 @@ package java.lang; public StringBuffer insert(int offset, long l) { // Note, synchronization achieved via invocation of StringBuffer insert(int, String) // after conversion of l to String by super class method + // Ditto for toStringCache clearing super.insert(offset, l); return this; } @@ -569,6 +606,7 @@ package java.lang; public StringBuffer insert(int offset, float f) { // Note, synchronization achieved via invocation of StringBuffer insert(int, String) // after conversion of f to String by super class method + // Ditto for toStringCache clearing super.insert(offset, f); return this; } @@ -580,6 +618,7 @@ package java.lang; public StringBuffer insert(int offset, double d) { // Note, synchronization achieved via invocation of StringBuffer insert(int, String) // after conversion of d to String by super class method + // Ditto for toStringCache clearing super.insert(offset, d); return this; } @@ -623,13 +662,17 @@ package java.lang; */ @Override public synchronized StringBuffer reverse() { + toStringCache = null; super.reverse(); return this; } @Override public synchronized String toString() { - return new String(value, 0, count); + if (toStringCache == null) { + toStringCache = Arrays.copyOfRange(value, 0, count); + } + return new String(toStringCache, true); } /** diff --git a/jdk/src/share/classes/java/lang/System.java b/jdk/src/share/classes/java/lang/System.java index c7f69f5e496..bd72188c6b0 100644 --- a/jdk/src/share/classes/java/lang/System.java +++ b/jdk/src/share/classes/java/lang/System.java @@ -1246,6 +1246,9 @@ public final class System { public StackTraceElement getStackTraceElement(Throwable t, int i) { return t.getStackTraceElement(i); } + public String newStringUnsafe(char[] chars) { + return new String(chars, true); + } }); } } diff --git a/jdk/src/share/classes/java/lang/invoke/MemberName.java b/jdk/src/share/classes/java/lang/invoke/MemberName.java index 59096015acc..dfb468417d6 100644 --- a/jdk/src/share/classes/java/lang/invoke/MemberName.java +++ b/jdk/src/share/classes/java/lang/invoke/MemberName.java @@ -236,6 +236,8 @@ import java.util.Objects; assert(MethodHandleNatives.refKindIsMethod(refKind)); if (clazz.isInterface()) assert(refKind == REF_invokeInterface || + refKind == REF_invokeStatic || + refKind == REF_invokeSpecial || refKind == REF_invokeVirtual && isObjectPublicMethod()); } else { assert(false); @@ -268,7 +270,7 @@ import java.util.Objects; assert(refKind == REF_invokeSpecial) : this; return true; } - assert(false) : this; + assert(false) : this+" != "+MethodHandleNatives.refKindName((byte)originalRefKind); return true; } private boolean staticIsConsistent() { @@ -485,14 +487,19 @@ import java.util.Objects; if (this.type == null) this.type = new Object[] { m.getReturnType(), m.getParameterTypes() }; if (wantSpecial) { + assert(!isAbstract()) : this; if (getReferenceKind() == REF_invokeVirtual) changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual); + else if (getReferenceKind() == REF_invokeInterface) + // invokeSpecial on a default method + changeReferenceKind(REF_invokeSpecial, REF_invokeInterface); } } public MemberName asSpecial() { switch (getReferenceKind()) { case REF_invokeSpecial: return this; case REF_invokeVirtual: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual); + case REF_invokeInterface: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface); case REF_newInvokeSpecial: return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial); } throw new IllegalArgumentException(this.toString()); diff --git a/jdk/src/share/classes/java/lang/reflect/Executable.java b/jdk/src/share/classes/java/lang/reflect/Executable.java index 78a1db91e81..00e08a64375 100644 --- a/jdk/src/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java @@ -486,8 +486,8 @@ public abstract class Executable extends AccessibleObject } /** - * Returns an AnnotatedType object that represents the potentially - * annotated return type of the method/constructor represented by this + * Returns an AnnotatedType object that represents the use of a type to + * specify the return type of the method/constructor represented by this * Executable. * * If this Executable represents a constructor, the AnnotatedType object @@ -510,12 +510,12 @@ public abstract class Executable extends AccessibleObject */ AnnotatedType getAnnotatedReturnType0(Type returnType) { return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(), - sun.misc.SharedSecrets.getJavaLangAccess(). - getConstantPool(getDeclaringClass()), - this, - getDeclaringClass(), - returnType, - TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN_TYPE); + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + returnType, + TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN); } /** @@ -535,12 +535,12 @@ public abstract class Executable extends AccessibleObject */ public AnnotatedType getAnnotatedReceiverType() { return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(), - sun.misc.SharedSecrets.getJavaLangAccess(). - getConstantPool(getDeclaringClass()), - this, - getDeclaringClass(), - getDeclaringClass(), - TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER_TYPE); + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getDeclaringClass(), + TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER); } /** @@ -556,7 +556,13 @@ public abstract class Executable extends AccessibleObject * @since 1.8 */ public AnnotatedType[] getAnnotatedParameterTypes() { - throw new UnsupportedOperationException("Not yet"); + return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getParameterTypes(), + TypeAnnotation.TypeAnnotationTarget.METHOD_FORMAL_PARAMETER); } /** @@ -573,12 +579,12 @@ public abstract class Executable extends AccessibleObject */ public AnnotatedType[] getAnnotatedExceptionTypes() { return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes(), - sun.misc.SharedSecrets.getJavaLangAccess(). - getConstantPool(getDeclaringClass()), - this, - getDeclaringClass(), - getGenericExceptionTypes(), - TypeAnnotation.TypeAnnotationTarget.THROWS); + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getGenericExceptionTypes(), + TypeAnnotation.TypeAnnotationTarget.THROWS); } } diff --git a/jdk/src/share/classes/java/lang/reflect/Field.java b/jdk/src/share/classes/java/lang/reflect/Field.java index a25223f68c1..8b2603a663e 100644 --- a/jdk/src/share/classes/java/lang/reflect/Field.java +++ b/jdk/src/share/classes/java/lang/reflect/Field.java @@ -1161,6 +1161,6 @@ class Field extends AccessibleObject implements Member { this, getDeclaringClass(), getGenericType(), - TypeAnnotation.TypeAnnotationTarget.FIELD_TYPE); + TypeAnnotation.TypeAnnotationTarget.FIELD); } } diff --git a/jdk/src/share/classes/java/lang/reflect/Modifier.java b/jdk/src/share/classes/java/lang/reflect/Modifier.java index 227beeedd79..7387bbeaa75 100644 --- a/jdk/src/share/classes/java/lang/reflect/Modifier.java +++ b/jdk/src/share/classes/java/lang/reflect/Modifier.java @@ -350,8 +350,19 @@ public class Modifier { return (mod & MANDATED) != 0; } + // Note on the FOO_MODIFIERS fields and fooModifiers() methods: + // the sets of modifiers are not guaranteed to be constants + // across time and Java SE releases. Therefore, it would not be + // appropriate to expose an external interface to this information + // that would allow the values to be treated as Java-level + // constants since the values could be constant folded and updates + // to the sets of modifiers missed. Thus, the fooModifiers() + // methods return an unchanging values for a given release, but a + // value that can potentially change over time. + /** - * See JLSv3 section 8.1.1. + * The Java source modifiers that can be applied to a class. + * @jls 8.1.1 Class Modifiers */ private static final int CLASS_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | @@ -359,7 +370,8 @@ public class Modifier { Modifier.STRICT; /** - * See JLSv3 section 9.1.1. + * The Java source modifiers that can be applied to an interface. + * @jls 9.1.1 Interface Modifiers */ private static final int INTERFACE_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | @@ -367,13 +379,15 @@ public class Modifier { /** - * See JLSv3 section 8.8.3. + * The Java source modifiers that can be applied to a constructor. + * @jls 8.8.3 Constructor Modifiers */ private static final int CONSTRUCTOR_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE; /** - * See JLSv3 section 8.4.3. + * The Java source modifiers that can be applied to a method. + * @jls8.4.3 Method Modifiers */ private static final int METHOD_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | @@ -381,13 +395,21 @@ public class Modifier { Modifier.SYNCHRONIZED | Modifier.NATIVE | Modifier.STRICT; /** - * See JLSv3 section 8.3.1. + * The Java source modifiers that can be applied to a field. + * @jls 8.3.1 Field Modifiers */ private static final int FIELD_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL | Modifier.TRANSIENT | Modifier.VOLATILE; + /** + * The Java source modifiers that can be applied to a method or constructor parameter. + * @jls 8.4.1 Formal Parameters + */ + private static final int PARAMETER_MODIFIERS = + Modifier.FINAL; + /** * */ @@ -411,7 +433,7 @@ public class Modifier { * Return an {@code int} value OR-ing together the source language * modifiers that can be applied to an interface. * @return an {@code int} value OR-ing together the source language - * modifiers that can be applied to an inteface. + * modifiers that can be applied to an interface. * * @jls 9.1.1 Interface Modifiers * @since 1.7 @@ -446,7 +468,6 @@ public class Modifier { return METHOD_MODIFIERS; } - /** * Return an {@code int} value OR-ing together the source language * modifiers that can be applied to a field. @@ -459,4 +480,17 @@ public class Modifier { public static int fieldModifiers() { return FIELD_MODIFIERS; } + + /** + * Return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a parameter. + * @return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a parameter. + * + * @jls 8.4.1 Formal Parameters + * @since 1.8 + */ + public static int parameterModifiers() { + return PARAMETER_MODIFIERS; + } } diff --git a/jdk/src/share/classes/java/lang/reflect/Parameter.java b/jdk/src/share/classes/java/lang/reflect/Parameter.java index 57097e02c6f..c50e0febe41 100644 --- a/jdk/src/share/classes/java/lang/reflect/Parameter.java +++ b/jdk/src/share/classes/java/lang/reflect/Parameter.java @@ -200,6 +200,19 @@ public final class Parameter implements AnnotatedElement { return tmp; } + /** + * Returns an AnnotatedType object that represents the use of a type to + * specify the type of the formal parameter represented by this Parameter. + * + * @return an {@code AnnotatedType} object representing the use of a type + * to specify the type of the formal parameter represented by this + * Parameter + */ + public AnnotatedType getAnnotatedType() { + // no caching for now + return executable.getAnnotatedParameterTypes()[index]; + } + private transient volatile Class parameterClassCache = null; /** diff --git a/jdk/src/share/classes/java/lang/reflect/Proxy.java b/jdk/src/share/classes/java/lang/reflect/Proxy.java index 49dc21d5efc..7b3d90f9273 100644 --- a/jdk/src/share/classes/java/lang/reflect/Proxy.java +++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java @@ -31,6 +31,7 @@ import java.security.PrivilegedAction; import java.util.Arrays; import java.util.IdentityHashMap; import java.util.Map; +import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; import java.util.function.BiFunction; import sun.misc.ProxyGenerator; @@ -255,9 +256,13 @@ public class Proxy implements java.io.Serializable { * (typically, a dynamic proxy class) with the specified value * for its invocation handler. * - * @param h the invocation handler for this proxy instance + * @param h the invocation handler for this proxy instance + * + * @throws NullPointerException if the given invocation handler, {@code h}, + * is {@code null}. */ protected Proxy(InvocationHandler h) { + Objects.requireNonNull(h); this.h = h; } @@ -698,9 +703,7 @@ public class Proxy implements java.io.Serializable { InvocationHandler h) throws IllegalArgumentException { - if (h == null) { - throw new NullPointerException(); - } + Objects.requireNonNull(h); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { diff --git a/jdk/src/share/classes/java/net/HttpURLConnection.java b/jdk/src/share/classes/java/net/HttpURLConnection.java index d52c26789fa..193b9cef1c1 100644 --- a/jdk/src/share/classes/java/net/HttpURLConnection.java +++ b/jdk/src/share/classes/java/net/HttpURLConnection.java @@ -50,6 +50,18 @@ import java.util.Date; * Proxy settings as well as * various other settings. *

+ *

+ * Security permissions + *

+ * If a security manager is installed, and if a method is called which results in an + * attempt to open a connection, the caller must possess either:- + *

  • a "connect" {@link SocketPermission} to the host/port combination of the + * destination URL or
  • + *
  • a {@link HttpURLPermission} that permits this request.
  • + *

+ * If automatic redirection is enabled, and this request is redirected to another + * destination, then the caller must also have permission to connect to the + * redirected host/URL. * * @see java.net.HttpURLConnection#disconnect() * @since JDK1.1 diff --git a/jdk/src/share/classes/java/net/HttpURLPermission.java b/jdk/src/share/classes/java/net/HttpURLPermission.java new file mode 100644 index 00000000000..52d6e79344a --- /dev/null +++ b/jdk/src/share/classes/java/net/HttpURLPermission.java @@ -0,0 +1,406 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net; + +import java.io.ObjectInputStream; +import java.io.IOException; +import java.util.List; +import java.util.ArrayList; +import java.util.Collections; +import java.security.Permission; + +/** + * Represents permission to access a resource or set of resources defined by a + * given http or https url, and for a given set of user-settable request methods + * and request headers. The name of the permission is the url string. + * The actions string is a concatenation of the request methods and headers. + * The range of method and header names is not restricted by this class. + *

The url

+ * The url string is also used to instantiate a {@link URI} object which is + * used for comparison with other HttpURLPermission instances. Therefore, any + * references in this specification to url, mean this URI object. + * The path component of the url comprises a sequence of path segments, separated + * by '/' characters. The path is specified in a similar way to the path + * in {@link java.io.FilePermission}. There are three different ways + * as the following examples show: + * + * + * + * + * + * + * + * + * + * + *
Example urlDescription
http://www.oracle.com/a/b/c.htmlA url which identifies a specific (single) resource
http://www.oracle.com/a/b/*The '*' character refers to all resources in the same "directory" - in + * other words all resources with the same number of path components, and + * which only differ in the final path component, represented by the '*'. + *
http://www.oracle.com/a/b/- + * The '-' character refers to all resources recursively below the + * preceding path (eg. http://www.oracle.com/a/b/c/d/e.html matches this + * example). + *
+ *

+ * The '*' and '-' may only be specified in the final segment of a path and must be + * the only character in that segment. Any query or fragment components of the + * url are ignored when constructing HttpURLPermissions. + *

+ * As a special case, urls of the form, "http:*" or "https:*" are accepted to + * mean any url of the given scheme. + *

The actions string

+ * The actions string of a HttpURLPermission is a concatenation of the method list + * and the request headers list. These are lists of the permitted HTTP request + * methods and permitted request headers of the permission (respectively). The two lists + * are separated by a colon ':' character and elements of each list are comma separated. + * Some examples are: + *

+ *         "POST,GET,DELETE"
+ *         "GET:X-Foo-Request,X-Bar-Request"
+ *         "POST,GET:Header1,Header2"
+ * 
+ * The first example specifies the methods: POST, GET and DELETE, but no request headers. + * The second example specifies one request method and two headers. The third + * example specifies two request methods, and two headers. + *

+ * The colon separator need not be present if the request headers list is empty. + * No white-space is permitted in the actions string. The action strings supplied to + * the HttpURLPermission constructors are case-insensitive and are normalized by converting + * method names to upper-case and header names to the form defines in RFC2616 (lower case + * with initial letter of each word capitalized). Either list can contain a wild-card '*' + * character which signifies all request methods or headers respectively. + *

+ * Note. Depending on the context of use, some request methods and headers may be permitted + * at all times, and others may not be permitted at any time. For example, the + * HTTP protocol handler might disallow certain headers such as Content-Length + * from being set by application code, regardless of whether the security policy + * in force, permits it. + * + * @since 1.8 + */ +public final class HttpURLPermission extends Permission { + + private static final long serialVersionUID = -2702463814894478682L; + + private transient URI uri; + private transient List methods; + private transient List requestHeaders; + + // serialized field + private String actions; + + /** + * Creates a new HttpURLPermission from a url string and which permits the given + * request methods and user-settable request headers. + * The name of the permission is its url string. Only the scheme, authority + * and path components of the url are used. Any fragment or query + * components are ignored. The permissions action string is as specified above. + * + * @param url the url string + * + * @param actions the actions string + * + * @throws IllegalArgumentException if url does not result in a valid {@link URI}, + * its scheme is not http or https, or if actions contains white-space. + */ + public HttpURLPermission(String url, String actions) { + super(url); + init(actions); + } + + private void init(String actions) { + URI uri = parseURI(getName()); + int colon = actions.indexOf(':'); + if (actions.lastIndexOf(':') != colon) { + throw new IllegalArgumentException("invalid actions string"); + } + + String methods, headers; + if (colon == -1) { + methods = actions; + headers = ""; + } else { + methods = actions.substring(0, colon); + headers = actions.substring(colon+1); + } + + List l = normalizeMethods(methods); + Collections.sort(l); + this.methods = Collections.unmodifiableList(l); + + l = normalizeHeaders(headers); + Collections.sort(l); + this.requestHeaders = Collections.unmodifiableList(l); + + this.actions = actions(); + this.uri = uri; + } + + /** + * Creates a HttpURLPermission with the given url string and unrestricted + * methods and request headers by invoking the two argument + * constructor as follows: HttpURLPermission(url, "*:*") + * + * @throws IllegalArgumentException if url does not result in a valid {@link URI} + */ + public HttpURLPermission(String url) { + this(url, "*:*"); + } + + /** + * Returns the normalized method list and request + * header list, in the form: + *

+     *      "method-names : header-names"
+     * 
+ *

+ * where method-names is the list of methods separated by commas + * and header-names is the list of permitted headers separated by commas. + * There is no white space in the returned String. If header-names is empty + * then the colon separator will not be present. + */ + public String getActions() { + return actions; + } + + /** + * Checks if this HttpURLPermission implies the given permission. + * Specifically, the following checks are done as if in the + * following sequence: + *