# HG changeset patch # User chegar # Date 1369309458 -3600 # Node ID ce9ecec70f996823f9a5f7c195af9a7bebe898c0 # Parent cb92413c69340046621c69a2e441de0d4376d223# Parent 7cbdf0e3725c0c56a2ff7540fc70b6d4b5890d04 Merge diff -r cb92413c6934 -r ce9ecec70f99 .hgtags --- a/.hgtags Thu May 16 11:44:33 2013 +0100 +++ b/.hgtags Thu May 23 12:44:18 2013 +0100 @@ -341,3 +341,5 @@ 4ec91349972255650f97bedfd07e6423e02428cf hs25-b31 9c1fe0b419b40a9ecdd1653cc9af1b6d67a12c46 jdk8-b89 69494caf57908ba2c8efa9eaaa472b4d1875588a hs25-b32 +1ae0472ff3a0117b5b019d380ad59fface2fde14 jdk8-b90 +b19517cecc2e91636d7c16ba2f35e3d3dc628099 hs25-b33 diff -r cb92413c6934 -r ce9ecec70f99 agent/src/share/classes/sun/jvm/hotspot/ci/ciMethod.java --- a/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethod.java Thu May 16 11:44:33 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethod.java Thu May 23 12:44:18 2013 +0100 @@ -97,8 +97,8 @@ holder.getName().asString() + " " + OopUtilities.escapeString(method.getName().asString()) + " " + method.getSignature().asString() + " " + - method.getInvocationCounter() + " " + - method.getBackedgeCounter() + " " + + method.getInvocationCount() + " " + + method.getBackedgeCount() + " " + interpreterInvocationCount() + " " + interpreterThrowoutCount() + " " + instructionsSize()); diff -r cb92413c6934 -r ce9ecec70f99 agent/src/share/classes/sun/jvm/hotspot/oops/Method.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Thu May 16 11:44:33 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Thu May 23 12:44:18 2013 +0100 @@ -24,15 +24,21 @@ package sun.jvm.hotspot.oops; -import java.io.*; -import java.util.*; -import sun.jvm.hotspot.code.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.interpreter.*; -import sun.jvm.hotspot.memory.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.*; +import java.io.PrintStream; +import java.util.Observable; +import java.util.Observer; + +import sun.jvm.hotspot.code.NMethod; +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.interpreter.OopMapCacheEntry; +import sun.jvm.hotspot.runtime.SignatureConverter; +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.runtime.VMObjectFactory; +import sun.jvm.hotspot.types.AddressField; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; +import sun.jvm.hotspot.types.WrongTypeException; +import sun.jvm.hotspot.utilities.Assert; // A Method represents a Java method @@ -132,11 +138,13 @@ public long getAccessFlags() { return accessFlags.getValue(this); } public long getCodeSize() { return getConstMethod().getCodeSize(); } public long getVtableIndex() { return vtableIndex.getValue(this); } - public long getInvocationCounter() { - return getMethodCounters().getInvocationCounter(); + public long getInvocationCount() { + MethodCounters mc = getMethodCounters(); + return mc == null ? 0 : mc.getInvocationCounter(); } - public long getBackedgeCounter() { - return getMethodCounters().getBackedgeCounter(); + public long getBackedgeCount() { + MethodCounters mc = getMethodCounters(); + return mc == null ? 0 : mc.getBackedgeCounter(); } // get associated compiled native method, if available, else return null. @@ -349,8 +357,8 @@ holder.getName().asString() + " " + OopUtilities.escapeString(getName().asString()) + " " + getSignature().asString() + " " + - getInvocationCounter() + " " + - getBackedgeCounter() + " " + + getInvocationCount() + " " + + getBackedgeCount() + " " + interpreterInvocationCount() + " " + interpreterThrowoutCount() + " " + code_size); diff -r cb92413c6934 -r ce9ecec70f99 agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java Thu May 16 11:44:33 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java Thu May 23 12:44:18 2013 +0100 @@ -316,8 +316,8 @@ int iic = method.interpreterInvocationCount(); if (mileage < iic) mileage = iic; - long ic = method.getInvocationCounter(); - long bc = method.getBackedgeCounter(); + long ic = method.getInvocationCount(); + long bc = method.getBackedgeCount(); long icval = ic >> 3; if ((ic & 4) != 0) icval += CompileThreshold; diff -r cb92413c6934 -r ce9ecec70f99 make/Makefile --- a/make/Makefile Thu May 16 11:44:33 2013 +0100 +++ b/make/Makefile Thu May 23 12:44:18 2013 +0100 @@ -151,32 +151,43 @@ $(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 @@ 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 @@ $(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 @@ # 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 -r cb92413c6934 -r ce9ecec70f99 make/bsd/makefiles/buildtree.make --- a/make/bsd/makefiles/buildtree.make Thu May 16 11:44:33 2013 +0100 +++ b/make/bsd/makefiles/buildtree.make Thu May 23 12:44:18 2013 +0100 @@ -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 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 make/bsd/makefiles/fastdebug.make --- a/make/bsd/makefiles/fastdebug.make Thu May 16 11:44:33 2013 +0100 +++ b/make/bsd/makefiles/fastdebug.make Thu May 23 12:44:18 2013 +0100 @@ -58,6 +58,6 @@ # Linker mapfile MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug -VERSION = optimized +VERSION = fastdebug SYSDEFS += -DASSERT PICFLAGS = DEFAULT diff -r cb92413c6934 -r ce9ecec70f99 make/bsd/makefiles/launcher.make --- a/make/bsd/makefiles/launcher.make Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r cb92413c6934 -r ce9ecec70f99 make/bsd/makefiles/vm.make --- a/make/bsd/makefiles/vm.make Thu May 16 11:44:33 2013 +0100 +++ b/make/bsd/makefiles/vm.make Thu May 23 12:44:18 2013 +0100 @@ -144,6 +144,9 @@ ifeq ($(OS_VENDOR), Darwin) LIBJVM = lib$(JVM).dylib CFLAGS += -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE + ifeq (${VERSION}, $(filter ${VERSION}, debug fastdebug)) + CFLAGS += -DALLOW_OPERATOR_NEW_USAGE + endif else LIBJVM = lib$(JVM).so endif @@ -328,9 +331,6 @@ #---------------------------------------------------------------------- # Other files -# Gamma launcher -include $(MAKEFILES_DIR)/launcher.make - # Signal interposition library include $(MAKEFILES_DIR)/jsig.make diff -r cb92413c6934 -r ce9ecec70f99 make/hotspot.script --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/hotspot.script Thu May 23 12:44:18 2013 +0100 @@ -0,0 +1,218 @@ +#!/bin/sh + +# 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. + + +# This script launches HotSpot. +# +# If the first parameter is either "-gdb" or "-gud", HotSpot will be +# launched inside gdb. "-gud" means "open an Emacs window and run gdb +# inside Emacs". +# +# If the first parameter is "-dbx", HotSpot will be launched inside dbx. +# +# If the first parameter is "-valgrind", HotSpot will be launched +# inside Valgrind (http://valgrind.kde.org) using the Memcheck skin, +# and with memory leak detection enabled. This currently (2005jan19) +# requires at least Valgrind 2.3.0. -Xmx16m will also be passed as +# the first parameter to HotSpot, since lowering HotSpot's memory +# consumption makes execution inside of Valgrind *a lot* faster. +# + + +# +# User changeable parameters ------------------------------------------------ +# + +# This is the name of the gdb binary to use +if [ ! "$GDB" ] +then + GDB=gdb +fi + +# This is the name of the gdb binary to use +if [ ! "$DBX" ] +then + DBX=dbx +fi + +# This is the name of the Valgrind binary to use +if [ ! "$VALGRIND" ] +then + VALGRIND=valgrind +fi + +# This is the name of Emacs for running GUD +EMACS=emacs + +# +# End of user changeable parameters ----------------------------------------- +# + +# Make sure the paths are fully specified, i.e. they must begin with /. +REL_MYDIR=`dirname $0` +MYDIR=`cd $REL_MYDIR && pwd` + +# +# Look whether the user wants to run inside gdb +case "$1" in + -gdb) + MODE=gdb + shift + ;; + -gud) + MODE=gud + shift + ;; + -dbx) + MODE=dbx + shift + ;; + -valgrind) + MODE=valgrind + shift + ;; + *) + MODE=run + ;; +esac + +if [ "${ALT_JAVA_HOME}" != "" ]; then + JDK=${ALT_JAVA_HOME%%/jre} +else + JDK=@@JDK_IMPORT_PATH@@ +fi + +if [ "${JDK}" = "" ]; then + 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: +# o $JVMPATH (directory portion only) +# o $JRE/lib/$ARCH +# followed by the user's previous effective LD_LIBRARY_PATH, if +# any. +JRE=$JDK/jre +JAVA_HOME=$JDK +export JAVA_HOME + +ARCH=@@LIBARCH@@ +SBP=${MYDIR}:${JRE}/lib/${ARCH} + + +# Set up a suitable LD_LIBRARY_PATH or DYLD_LIBRARY_PATH +OS=`uname -s` +if [ "${OS}" = "Darwin" ] +then + if [ -z "$DYLD_LIBRARY_PATH" ] + then + DYLD_LIBRARY_PATH="$SBP" + else + DYLD_LIBRARY_PATH="$SBP:$DYLD_LIBRARY_PATH" + fi + export DYLD_LIBRARY_PATH +else + # not 'Darwin' + if [ -z "$LD_LIBRARY_PATH" ] + then + LD_LIBRARY_PATH="$SBP" + else + LD_LIBRARY_PATH="$SBP:$LD_LIBRARY_PATH" + fi + export LD_LIBRARY_PATH +fi + +JPARMS="-Dsun.java.launcher=gamma -XXaltjvm=$MYDIR $@ $JAVA_ARGS"; + +# Locate the java launcher +LAUNCHER=$JDK/bin/java +if [ ! -x $LAUNCHER ] ; then + echo Error: Cannot find the java launcher \"$LAUNCHER\" + exit 1 +fi + +GDBSRCDIR=$MYDIR +BASEDIR=`cd $MYDIR/../../.. && pwd` + +init_gdb() { +# Create a gdb script in case we should run inside gdb + GDBSCR=/tmp/hsl.$$ + rm -f $GDBSCR + cat >>$GDBSCR <= 22.1 + case `$EMACS -version 2> /dev/null` in + *GNU\ Emacs\ 2[23]*) + emacs_gud_cmd="gdba" + emacs_gud_args="--annotate=3" + ;; + *) + emacs_gud_cmd="gdb" + emacs_gud_args= + ;; + esac + $EMACS --eval "($emacs_gud_cmd \"$GDB $emacs_gud_args -x $GDBSCR\")"; + rm -f $GDBSCR + ;; + dbx) + $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 + echo + $VALGRIND --tool=memcheck --leak-check=yes --num-callers=50 $LAUNCHER -Xmx16m $JPARMS + ;; + run) + LD_PRELOAD=$PRELOADING exec $LAUNCHER $JPARMS + ;; + *) + echo Error: Internal error, unknown launch mode \"$MODE\" + exit 1 + ;; +esac +RETVAL=$? +exit $RETVAL diff -r cb92413c6934 -r ce9ecec70f99 make/hotspot_version --- a/make/hotspot_version Thu May 16 11:44:33 2013 +0100 +++ b/make/hotspot_version Thu May 23 12:44:18 2013 +0100 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=32 +HS_BUILD_NUMBER=33 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r cb92413c6934 -r ce9ecec70f99 make/jprt.properties --- a/make/jprt.properties Thu May 16 11:44:33 2013 +0100 +++ b/make/jprt.properties Thu May 23 12:44:18 2013 +0100 @@ -134,14 +134,14 @@ 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 -r cb92413c6934 -r ce9ecec70f99 make/linux/makefiles/buildtree.make --- a/make/linux/makefiles/buildtree.make Thu May 16 11:44:33 2013 +0100 +++ b/make/linux/makefiles/buildtree.make Thu May 23 12:44:18 2013 +0100 @@ -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 @@ # 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 make/linux/makefiles/launcher.make --- a/make/linux/makefiles/launcher.make Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r cb92413c6934 -r ce9ecec70f99 make/linux/makefiles/vm.make --- a/make/linux/makefiles/vm.make Thu May 16 11:44:33 2013 +0100 +++ b/make/linux/makefiles/vm.make Thu May 23 12:44:18 2013 +0100 @@ -372,9 +372,6 @@ #---------------------------------------------------------------------- # Other files -# Gamma launcher -include $(MAKEFILES_DIR)/launcher.make - # Signal interposition library include $(MAKEFILES_DIR)/jsig.make diff -r cb92413c6934 -r ce9ecec70f99 make/solaris/makefiles/buildtree.make --- a/make/solaris/makefiles/buildtree.make Thu May 16 11:44:33 2013 +0100 +++ b/make/solaris/makefiles/buildtree.make Thu May 23 12:44:18 2013 +0100 @@ -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 @@ # 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 make/solaris/makefiles/launcher.make --- a/make/solaris/makefiles/launcher.make Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r cb92413c6934 -r ce9ecec70f99 make/solaris/makefiles/vm.make --- a/make/solaris/makefiles/vm.make Thu May 16 11:44:33 2013 +0100 +++ b/make/solaris/makefiles/vm.make Thu May 23 12:44:18 2013 +0100 @@ -338,9 +338,6 @@ #---------------------------------------------------------------------- # Other files -# Gamma launcher -include $(MAKEFILES_DIR)/launcher.make - # Signal interposition library include $(MAKEFILES_DIR)/jsig.make diff -r cb92413c6934 -r ce9ecec70f99 make/windows/makefiles/debug.make --- a/make/windows/makefiles/debug.make Thu May 16 11:44:33 2013 +0100 +++ b/make/windows/makefiles/debug.make Thu May 23 12:44:18 2013 +0100 @@ -33,7 +33,7 @@ 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 @@ !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make -!include $(WorkSpace)/make/windows/makefiles/launcher.make diff -r cb92413c6934 -r ce9ecec70f99 make/windows/makefiles/fastdebug.make --- a/make/windows/makefiles/fastdebug.make Thu May 16 11:44:33 2013 +0100 +++ b/make/windows/makefiles/fastdebug.make Thu May 23 12:44:18 2013 +0100 @@ -33,7 +33,7 @@ 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 @@ !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make -!include $(WorkSpace)/make/windows/makefiles/launcher.make diff -r cb92413c6934 -r ce9ecec70f99 make/windows/makefiles/launcher.make --- a/make/windows/makefiles/launcher.make Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r cb92413c6934 -r ce9ecec70f99 make/windows/makefiles/product.make --- a/make/windows/makefiles/product.make Thu May 16 11:44:33 2013 +0100 +++ b/make/windows/makefiles/product.make Thu May 23 12:44:18 2013 +0100 @@ -32,7 +32,7 @@ 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 @@ !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make -!include $(WorkSpace)/make/windows/makefiles/launcher.make diff -r cb92413c6934 -r ce9ecec70f99 make/windows/makefiles/projectcreator.make --- a/make/windows/makefiles/projectcreator.make Thu May 16 11:44:33 2013 +0100 +++ b/make/windows/makefiles/projectcreator.make Thu May 23 12:44:18 2013 +0100 @@ -59,7 +59,6 @@ -relativeSrcInclude src \ -absoluteSrcInclude $(HOTSPOTBUILDSPACE) \ -ignorePath $(HOTSPOTBUILDSPACE) \ - -ignorePath launcher \ -ignorePath share\vm\adlc \ -ignorePath share\vm\shark \ -ignorePath share\tools \ @@ -105,7 +104,6 @@ -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 -r cb92413c6934 -r ce9ecec70f99 make/windows/projectfiles/common/Makefile --- a/make/windows/projectfiles/common/Makefile Thu May 16 11:44:33 2013 +0100 +++ b/make/windows/projectfiles/common/Makefile Thu May 23 12:44:18 2013 +0100 @@ -65,7 +65,6 @@ !endif HS_INTERNAL_NAME=jvm -!include $(HOTSPOTWORKSPACE)/make/windows/makefiles/launcher.make default:: $(AdditionalTargets) $(JvmtiGeneratedFiles) diff -r cb92413c6934 -r ce9ecec70f99 src/cpu/sparc/vm/globals_sparc.hpp --- a/src/cpu/sparc/vm/globals_sparc.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/cpu/sparc/vm/globals_sparc.hpp Thu May 23 12:44:18 2013 +0100 @@ -74,7 +74,7 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/cpu/x86/vm/globals_x86.hpp --- a/src/cpu/x86/vm/globals_x86.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/cpu/x86/vm/globals_x86.hpp Thu May 23 12:44:18 2013 +0100 @@ -77,7 +77,7 @@ #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 -r cb92413c6934 -r ce9ecec70f99 src/cpu/zero/vm/globals_zero.hpp --- a/src/cpu/zero/vm/globals_zero.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/cpu/zero/vm/globals_zero.hpp Thu May 23 12:44:18 2013 +0100 @@ -55,7 +55,7 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/os/posix/launcher/java_md.c --- a/src/os/posix/launcher/java_md.c Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r cb92413c6934 -r ce9ecec70f99 src/os/posix/launcher/java_md.h --- a/src/os/posix/launcher/java_md.h Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r cb92413c6934 -r ce9ecec70f99 src/os/posix/launcher/launcher.script --- a/src/os/posix/launcher/launcher.script Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,218 +0,0 @@ -#!/bin/sh - -# 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. - - -# This script launches HotSpot. -# -# If the first parameter is either "-gdb" or "-gud", HotSpot will be -# launched inside gdb. "-gud" means "open an Emacs window and run gdb -# inside Emacs". -# -# If the first parameter is "-dbx", HotSpot will be launched inside dbx. -# -# If the first parameter is "-valgrind", HotSpot will be launched -# inside Valgrind (http://valgrind.kde.org) using the Memcheck skin, -# and with memory leak detection enabled. This currently (2005jan19) -# requires at least Valgrind 2.3.0. -Xmx16m will also be passed as -# the first parameter to HotSpot, since lowering HotSpot's memory -# consumption makes execution inside of Valgrind *a lot* faster. -# - - -# -# User changeable parameters ------------------------------------------------ -# - -# This is the name of the gdb binary to use -if [ ! "$GDB" ] -then - GDB=gdb -fi - -# This is the name of the gdb binary to use -if [ ! "$DBX" ] -then - DBX=dbx -fi - -# This is the name of the Valgrind binary to use -if [ ! "$VALGRIND" ] -then - VALGRIND=valgrind -fi - -# This is the name of Emacs for running GUD -EMACS=emacs - -# -# End of user changeable parameters ----------------------------------------- -# - -# Make sure the paths are fully specified, i.e. they must begin with /. -REL_MYDIR=`dirname $0` -MYDIR=`cd $REL_MYDIR && pwd` - -# Look whether the user wants to run inside gdb -case "$1" in - -gdb) - MODE=gdb - shift - ;; - -gud) - MODE=gud - shift - ;; - -dbx) - MODE=dbx - shift - ;; - -valgrind) - MODE=valgrind - shift - ;; - *) - MODE=run - ;; -esac - -JDK= -if [ "${ALT_JAVA_HOME}" = "" ]; then - . ${MYDIR}/jdkpath.sh -else - JDK=${ALT_JAVA_HOME%%/jre}; -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 -fi - -# We will set the LD_LIBRARY_PATH as follows: -# o $JVMPATH (directory portion only) -# o $JRE/lib/$ARCH -# followed by the user's previous effective LD_LIBRARY_PATH, if -# any. -JRE=$JDK/jre -JAVA_HOME=$JDK -export JAVA_HOME - -ARCH=@@LIBARCH@@ -SBP=${MYDIR}:${JRE}/lib/${ARCH} - - -# Set up a suitable LD_LIBRARY_PATH or DYLD_LIBRARY_PATH -OS=`uname -s` -if [ "${OS}" = "Darwin" ] -then - if [ -z "$DYLD_LIBRARY_PATH" ] - then - DYLD_LIBRARY_PATH="$SBP" - else - DYLD_LIBRARY_PATH="$SBP:$DYLD_LIBRARY_PATH" - fi - export DYLD_LIBRARY_PATH -else - # not 'Darwin' - if [ -z "$LD_LIBRARY_PATH" ] - then - LD_LIBRARY_PATH="$SBP" - else - LD_LIBRARY_PATH="$SBP:$LD_LIBRARY_PATH" - fi - export LD_LIBRARY_PATH -fi - -JPARMS="$@ $JAVA_ARGS"; - -# Locate the gamma development launcher -LAUNCHER=${MYDIR}/gamma -if [ ! -x $LAUNCHER ] ; then - echo Error: Cannot find the gamma development launcher \"$LAUNCHER\" - exit 1 -fi - -GDBSRCDIR=$MYDIR -BASEDIR=`cd $MYDIR/../../.. && pwd` - -init_gdb() { -# Create a gdb script in case we should run inside gdb - GDBSCR=/tmp/hsl.$$ - rm -f $GDBSCR - cat >>$GDBSCR <= 22.1 - case `$EMACS -version 2> /dev/null` in - *GNU\ Emacs\ 2[23]*) - emacs_gud_cmd="gdba" - emacs_gud_args="--annotate=3" - ;; - *) - emacs_gud_cmd="gdb" - emacs_gud_args= - ;; - esac - $EMACS --eval "($emacs_gud_cmd \"$GDB $emacs_gud_args -x $GDBSCR\")"; - rm -f $GDBSCR - ;; - dbx) - $DBX -s $HOME/.dbxrc $LAUNCHER $JPARMS - ;; - valgrind) - echo Warning: Defaulting to 16Mb heap to make Valgrind run faster, use -Xmx for larger heap - echo - $VALGRIND --tool=memcheck --leak-check=yes --num-callers=50 $LAUNCHER -Xmx16m $JPARMS - ;; - run) - LD_PRELOAD=$PRELOADING exec $LAUNCHER $JPARMS - ;; - *) - echo Error: Internal error, unknown launch mode \"$MODE\" - exit 1 - ;; -esac -RETVAL=$? -exit $RETVAL diff -r cb92413c6934 -r ce9ecec70f99 src/os/windows/launcher/java_md.c --- a/src/os/windows/launcher/java_md.c Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r cb92413c6934 -r ce9ecec70f99 src/os/windows/launcher/java_md.h --- a/src/os/windows/launcher/java_md.h Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r cb92413c6934 -r ce9ecec70f99 src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/os/windows/vm/os_windows.cpp Thu May 23 12:44:18 2013 +0100 @@ -3307,7 +3307,7 @@ assert(ret != SYS_THREAD_ERROR, "StartThread failed"); // should propagate back } -class HighResolutionInterval { +class HighResolutionInterval : public CHeapObj { // The default timer resolution seems to be 10 milliseconds. // (Where is this written down?) // If someone wants to sleep for only a fraction of the default, diff -r cb92413c6934 -r ce9ecec70f99 src/share/tools/ProjectCreator/BuildConfig.java --- a/src/share/tools/ProjectCreator/BuildConfig.java Thu May 16 11:44:33 2013 +0100 +++ b/src/share/tools/ProjectCreator/BuildConfig.java Thu May 23 12:44:18 2013 +0100 @@ -65,6 +65,7 @@ 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 @@ put("BuildBase", buildBase); put("BuildSpace", buildSpace); put("OutputDll", outDir + Util.sep + outDll); + put("JdkTargetRoot", jdkTargetRoot); context = new String [] {flavourBuild, flavour, build, null}; } diff -r cb92413c6934 -r ce9ecec70f99 src/share/tools/ProjectCreator/WinGammaPlatformVC10.java --- a/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java Thu May 16 11:44:33 2013 +0100 +++ b/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java Thu May 23 12:44:18 2013 +0100 @@ -98,11 +98,6 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/tools/launcher/java.c --- a/src/share/tools/launcher/java.c Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r cb92413c6934 -r ce9ecec70f99 src/share/tools/launcher/java.h --- a/src/share/tools/launcher/java.h Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r cb92413c6934 -r ce9ecec70f99 src/share/tools/launcher/jli_util.c --- a/src/share/tools/launcher/jli_util.c Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r cb92413c6934 -r ce9ecec70f99 src/share/tools/launcher/jli_util.h --- a/src/share/tools/launcher/jli_util.h Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +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. - * - */ - -#ifndef _JLI_UTIL_H -#define _JLI_UTIL_H - -#include - -void *JLI_MemAlloc(size_t size); -void *JLI_MemRealloc(void *ptr, size_t size); -char *JLI_StringDup(const char *s1); -void JLI_MemFree(void *ptr); - -#endif /* _JLI_UTIL_H */ diff -r cb92413c6934 -r ce9ecec70f99 src/share/tools/launcher/wildcard.c --- a/src/share/tools/launcher/wildcard.c Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r cb92413c6934 -r ce9ecec70f99 src/share/tools/launcher/wildcard.h --- a/src/share/tools/launcher/wildcard.h Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +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. - * - */ - -#ifndef WILDCARD_H_ -#define WILDCARD_H_ - -#ifdef EXPAND_CLASSPATH_WILDCARDS -const char *JLI_WildcardExpandClasspath(const char *classpath); -#else -#define JLI_WildcardExpandClasspath(s) (s) -#endif - -#endif /* include guard */ diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/c1/c1_Runtime1.cpp --- a/src/share/vm/c1/c1_Runtime1.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/c1/c1_Runtime1.cpp Thu May 23 12:44:18 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -1261,7 +1261,7 @@ if (length == 0) return ac_ok; if (src->is_typeArray()) { - Klass* const klass_oop = src->klass(); + Klass* klass_oop = src->klass(); if (klass_oop != dst->klass()) return ac_failed; TypeArrayKlass* klass = TypeArrayKlass::cast(klass_oop); const int l2es = klass->log2_element_size(); diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/ci/ciInstanceKlass.cpp --- a/src/share/vm/ci/ciInstanceKlass.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/ci/ciInstanceKlass.cpp Thu May 23 12:44:18 2013 +0100 @@ -211,13 +211,42 @@ // ------------------------------------------------------------------ // 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 // // Is this klass in the given package? diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/ci/ciInstanceKlass.hpp --- a/src/share/vm/ci/ciInstanceKlass.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/ci/ciInstanceKlass.hpp Thu May 23 12:44:18 2013 +0100 @@ -217,10 +217,14 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/ci/ciMethod.cpp --- a/src/share/vm/ci/ciMethod.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/ci/ciMethod.cpp Thu May 23 12:44:18 2013 +0100 @@ -1179,6 +1179,44 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/ci/ciMethod.hpp --- a/src/share/vm/ci/ciMethod.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/ci/ciMethod.hpp Thu May 23 12:44:18 2013 +0100 @@ -298,6 +298,8 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/ci/ciReplay.cpp --- a/src/share/vm/ci/ciReplay.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/ci/ciReplay.cpp Thu May 23 12:44:18 2013 +0100 @@ -492,7 +492,9 @@ } Klass* k = parse_klass(CHECK); rec->oops_offsets[i] = offset; - rec->oops_handles[i] = (jobject)(new KlassHandle(THREAD, k)); + KlassHandle *kh = NEW_C_HEAP_OBJ(KlassHandle, mtCompiler); + ::new ((void*)kh) KlassHandle(THREAD, k); + rec->oops_handles[i] = (jobject)kh; } } diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/classfile/altHashing.cpp --- a/src/share/vm/classfile/altHashing.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/classfile/altHashing.cpp Thu May 23 12:44:18 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -242,8 +242,8 @@ void AltHashing::testMurmur3_32_ByteArray() { // printf("testMurmur3_32_ByteArray\n"); - jbyte* vector = new jbyte[256]; - jbyte* hashes = new jbyte[4 * 256]; + jbyte vector[256]; + jbyte hashes[4 * 256]; for (int i = 0; i < 256; i++) { vector[i] = (jbyte) i; diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/classfile/classFileParser.cpp Thu May 23 12:44:18 2013 +0100 @@ -3028,7 +3028,7 @@ } -#ifndef PRODUCT +#ifdef ASSERT static void parseAndPrintGenericSignatures( instanceKlassHandle this_klass, TRAPS) { assert(ParseAllGenericSignatures == true, "Shouldn't call otherwise"); @@ -3053,7 +3053,7 @@ } } } -#endif // ndef PRODUCT +#endif // def ASSERT instanceKlassHandle ClassFileParser::parse_super_class(int super_class_index, @@ -3114,9 +3114,6 @@ // Field size and offset computation int nonstatic_field_size = _super_klass() == NULL ? 0 : _super_klass()->nonstatic_field_size(); -#ifndef PRODUCT - int orig_nonstatic_field_size = 0; -#endif int next_static_oop_offset; int next_static_double_offset; int next_static_word_offset; @@ -3201,25 +3198,6 @@ first_nonstatic_oop_offset = 0; // will be set for first oop field -#ifndef PRODUCT - if( PrintCompactFieldsSavings ) { - next_nonstatic_double_offset = next_nonstatic_field_offset + - (nonstatic_oop_count * heapOopSize); - if ( nonstatic_double_count > 0 ) { - next_nonstatic_double_offset = align_size_up(next_nonstatic_double_offset, BytesPerLong); - } - next_nonstatic_word_offset = next_nonstatic_double_offset + - (nonstatic_double_count * BytesPerLong); - next_nonstatic_short_offset = next_nonstatic_word_offset + - (nonstatic_word_count * BytesPerInt); - next_nonstatic_byte_offset = next_nonstatic_short_offset + - (nonstatic_short_count * BytesPerShort); - next_nonstatic_type_offset = align_size_up((next_nonstatic_byte_offset + - nonstatic_byte_count ), heapOopSize ); - orig_nonstatic_field_size = nonstatic_field_size + - ((next_nonstatic_type_offset - first_nonstatic_field_offset)/heapOopSize); - } -#endif bool compact_fields = CompactFields; int allocation_style = FieldsAllocationStyle; if( allocation_style < 0 || allocation_style > 2 ) { // Out of range? @@ -3593,21 +3571,6 @@ first_nonstatic_oop_offset); #ifndef PRODUCT - if( PrintCompactFieldsSavings ) { - ResourceMark rm; - if( nonstatic_field_size < orig_nonstatic_field_size ) { - tty->print("[Saved %d of %d bytes in %s]\n", - (orig_nonstatic_field_size - nonstatic_field_size)*heapOopSize, - orig_nonstatic_field_size*heapOopSize, - _class_name); - } else if( nonstatic_field_size > orig_nonstatic_field_size ) { - tty->print("[Wasted %d over %d bytes in %s]\n", - (nonstatic_field_size - orig_nonstatic_field_size)*heapOopSize, - orig_nonstatic_field_size*heapOopSize, - _class_name); - } - } - if (PrintFieldLayout) { print_field_layout(_class_name, _fields, diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/classfile/dictionary.cpp --- a/src/share/vm/classfile/dictionary.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/classfile/dictionary.cpp Thu May 23 12:44:18 2013 +0100 @@ -253,22 +253,6 @@ } } - -// All classes, and their class loaders -// (added for helpers that use HandleMarks and ResourceMarks) -// Don't iterate over placeholders -void Dictionary::classes_do(void f(Klass*, ClassLoaderData*, TRAPS), TRAPS) { - for (int index = 0; index < table_size(); index++) { - for (DictionaryEntry* probe = bucket(index); - probe != NULL; - probe = probe->next()) { - Klass* k = probe->klass(); - f(k, probe->loader_data(), CHECK); - } - } -} - - // All classes, and their class loaders // Don't iterate over placeholders void Dictionary::classes_do(void f(Klass*, ClassLoaderData*)) { diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/classfile/dictionary.hpp --- a/src/share/vm/classfile/dictionary.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/classfile/dictionary.hpp Thu May 23 12:44:18 2013 +0100 @@ -90,7 +90,6 @@ void classes_do(void f(Klass*)); void classes_do(void f(Klass*, TRAPS), TRAPS); void classes_do(void f(Klass*, ClassLoaderData*)); - void classes_do(void f(Klass*, ClassLoaderData*, TRAPS), TRAPS); void methods_do(void f(Method*)); diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/classfile/systemDictionary.cpp Thu May 23 12:44:18 2013 +0100 @@ -1747,13 +1747,6 @@ dictionary()->classes_do(f); } -// All classes, and their class loaders -// (added for helpers that use HandleMarks and ResourceMarks) -// Don't iterate over placeholders -void SystemDictionary::classes_do(void f(Klass*, ClassLoaderData*, TRAPS), TRAPS) { - dictionary()->classes_do(f, CHECK); -} - void SystemDictionary::placeholders_do(void f(Symbol*)) { placeholders()->entries_do(f); } diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/classfile/systemDictionary.hpp Thu May 23 12:44:18 2013 +0100 @@ -313,10 +313,7 @@ static void classes_do(void f(Klass*, TRAPS), TRAPS); // All classes, and their class loaders static void classes_do(void f(Klass*, ClassLoaderData*)); - // All classes, and their class loaders - // (added for helpers that use HandleMarks and ResourceMarks) - static void classes_do(void f(Klass*, ClassLoaderData*, TRAPS), TRAPS); - // All entries in the placeholder table and their class loaders + static void placeholders_do(void f(Symbol*)); // Iterate over all methods in all klasses in dictionary diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/classfile/verifier.cpp --- a/src/share/vm/classfile/verifier.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/classfile/verifier.cpp Thu May 23 12:44:18 2013 +0100 @@ -362,7 +362,7 @@ } #endif -void ErrorContext::details(outputStream* ss, Method* method) const { +void ErrorContext::details(outputStream* ss, const Method* method) const { if (is_valid()) { ss->print_cr(""); ss->print_cr("Exception Details:"); @@ -435,7 +435,7 @@ ss->print_cr(""); } -void ErrorContext::location_details(outputStream* ss, Method* method) const { +void ErrorContext::location_details(outputStream* ss, const Method* method) const { if (_bci != -1 && method != NULL) { streamIndentor si(ss); const char* bytecode_name = ""; @@ -470,7 +470,7 @@ } } -void ErrorContext::bytecode_details(outputStream* ss, Method* method) const { +void ErrorContext::bytecode_details(outputStream* ss, const Method* method) const { if (method != NULL) { streamIndentor si(ss); ss->indent().print_cr("Bytecode:"); @@ -479,7 +479,7 @@ } } -void ErrorContext::handler_details(outputStream* ss, Method* method) const { +void ErrorContext::handler_details(outputStream* ss, const Method* method) const { if (method != NULL) { streamIndentor si(ss); ExceptionTable table(method); @@ -494,7 +494,7 @@ } } -void ErrorContext::stackmap_details(outputStream* ss, Method* method) const { +void ErrorContext::stackmap_details(outputStream* ss, const Method* method) const { if (method != NULL && method->has_stackmap_table()) { streamIndentor si(ss); ss->indent().print_cr("Stackmap Table:"); diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/classfile/verifier.hpp --- a/src/share/vm/classfile/verifier.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/classfile/verifier.hpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ -224,7 +224,7 @@ _expected.reset_frame(); } - void details(outputStream* ss, Method* method) const; + void details(outputStream* ss, const Method* method) const; #ifdef ASSERT void print_on(outputStream* str) const { @@ -237,12 +237,12 @@ #endif private: - void location_details(outputStream* ss, Method* method) const; + void location_details(outputStream* ss, const Method* method) const; void reason_details(outputStream* ss) const; void frame_details(outputStream* ss) const; - void bytecode_details(outputStream* ss, Method* method) const; - void handler_details(outputStream* ss, Method* method) const; - void stackmap_details(outputStream* ss, Method* method) const; + void bytecode_details(outputStream* ss, const Method* method) const; + void handler_details(outputStream* ss, const Method* method) const; + void stackmap_details(outputStream* ss, const Method* method) const; }; // A new instance of this class is created for each class being verified diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/classfile/vmSymbols.cpp --- a/src/share/vm/classfile/vmSymbols.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/classfile/vmSymbols.cpp Thu May 23 12:44:18 2013 +0100 @@ -49,7 +49,7 @@ } } -#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 @@ } return string; } -#endif //PRODUCT +#endif //ASSERT // Put all the VM symbol strings in one place. // Makes for a more compact libjvm. diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/code/nmethod.cpp Thu May 23 12:44:18 2013 +0100 @@ -1794,6 +1794,19 @@ Metadata* md = r->metadata_value(); f(md); } + } else if (iter.type() == relocInfo::virtual_call_type) { + // Check compiledIC holders associated with this nmethod + CompiledIC *ic = CompiledIC_at(iter.reloc()); + if (ic->is_icholder_call()) { + CompiledICHolder* cichk = ic->cached_icholder(); + f(cichk->holder_method()); + f(cichk->holder_klass()); + } else { + Metadata* ic_oop = ic->cached_metadata(); + if (ic_oop != NULL) { + f(ic_oop); + } + } } } } @@ -1804,6 +1817,7 @@ Metadata* md = *p; f(md); } + // Call function Method*, not embedded in these other places. if (_method != NULL) f(_method); } diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/compiler/compileBroker.cpp Thu May 23 12:44:18 2013 +0100 @@ -1854,8 +1854,10 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp Thu May 23 12:44:18 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -52,7 +52,7 @@ } void ConcurrentMarkSweepPolicy::initialize_generations() { - _generations = new GenerationSpecPtr[number_of_generations()]; + _generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, 0, AllocFailStrategy::RETURN_NULL); if (_generations == NULL) vm_exit_during_initialization("Unable to allocate gen spec"); diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu May 23 12:44:18 2013 +0100 @@ -692,8 +692,7 @@ _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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu May 23 12:44:18 2013 +0100 @@ -4515,7 +4515,8 @@ _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 @@ 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 @@ 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 @@ _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 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/g1/concurrentMark.hpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu May 23 12:44:18 2013 +0100 @@ -1257,6 +1257,9 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/g1/g1CardCounts.cpp --- a/src/share/vm/gc_implementation/g1/g1CardCounts.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CardCounts.cpp Thu May 23 12:44:18 2013 +0100 @@ -101,20 +101,23 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/g1/g1CardCounts.hpp --- a/src/share/vm/gc_implementation/g1/g1CardCounts.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CardCounts.hpp Thu May 23 12:44:18 2013 +0100 @@ -94,6 +94,14 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu May 23 12:44:18 2013 +0100 @@ -1549,7 +1549,7 @@ } if (G1Log::finer()) { - g1_policy()->print_detailed_heap_transition(); + g1_policy()->print_detailed_heap_transition(true /* full */); } print_heap_after_gc(); diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu May 23 12:44:18 2013 +0100 @@ -124,9 +124,12 @@ _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 @@ 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 @@ _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 @@ _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 @@ } } } + bool new_in_marking_window = _in_marking_window; bool new_in_marking_window_im = false; if (during_initial_mark_pause()) { @@ -1083,8 +1079,10 @@ } _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 @@ 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(); + + 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_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)); + 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu May 23 12:44:18 2013 +0100 @@ -175,7 +175,6 @@ 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 @@ 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 @@ // 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ -282,7 +282,8 @@ _fine_eviction_stride = _max_fine_entries / _fine_eviction_sample_size; } - _fine_grain_regions = new PerRegionTablePtr[_max_fine_entries]; + _fine_grain_regions = NEW_C_HEAP_ARRAY3(PerRegionTablePtr, _max_fine_entries, + mtGC, 0, AllocFailStrategy::RETURN_NULL); if (_fine_grain_regions == NULL) { vm_exit_out_of_memory(sizeof(void*)*_max_fine_entries, OOM_MALLOC_ERROR, @@ -706,10 +707,11 @@ // 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ 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 @@ // 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 @@ 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 @@ // 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 @@ 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 @@ 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 @@ 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_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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.inline.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.inline.hpp Thu May 16 11:44:33 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +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. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_INLINE_HPP -#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_INLINE_HPP - -#include "oops/oop.hpp" - -inline bool -ParMarkBitMap::mark_obj(oop obj) -{ - return mark_obj(obj, obj->size()); -} - -#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_INLINE_HPP diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ -213,7 +213,7 @@ int random_seed = 17; do { while (ParCompactionManager::steal_objarray(which, &random_seed, task)) { - ObjArrayKlass* const k = (ObjArrayKlass*)task.obj()->klass(); + ObjArrayKlass* k = (ObjArrayKlass*)task.obj()->klass(); k->oop_follow_contents(cm, task.obj(), task.index()); cm->follow_marking_stacks(); } diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ 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 @@ // 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 @@ // 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 @@ // // 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 @@ 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 @@ 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 @@ // "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 @@ 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 @@ // 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 @@ // 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::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 @@ 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 @@ // 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 @@ 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 @@ *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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ 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 @@ 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 @@ // 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 @@ 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 @@ // 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ -187,11 +187,8 @@ // Process ObjArrays one at a time to avoid marking stack bloat. ObjArrayTask task; - if (_objarray_stack.pop_overflow(task)) { - ObjArrayKlass* const k = (ObjArrayKlass*)task.obj()->klass(); - k->oop_follow_contents(this, task.obj(), task.index()); - } else if (_objarray_stack.pop_local(task)) { - ObjArrayKlass* const k = (ObjArrayKlass*)task.obj()->klass(); + if (_objarray_stack.pop_overflow(task) || _objarray_stack.pop_local(task)) { + ObjArrayKlass* k = (ObjArrayKlass*)task.obj()->klass(); k->oop_follow_contents(this, task.obj(), task.index()); } } while (!marking_stacks_empty()); diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp Thu May 23 12:44:18 2013 +0100 @@ -88,8 +88,7 @@ * 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ 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 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu May 23 12:44:18 2013 +0100 @@ -552,19 +552,33 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/shared/markSweep.cpp --- a/src/share/vm/gc_implementation/shared/markSweep.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/markSweep.cpp Thu May 23 12:44:18 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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,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; @@ -95,7 +95,7 @@ // Process ObjArrays one at a time to avoid marking stack bloat. if (!_objarray_stack.is_empty()) { ObjArrayTask task = _objarray_stack.pop(); - ObjArrayKlass* const k = (ObjArrayKlass*)task.obj()->klass(); + ObjArrayKlass* k = (ObjArrayKlass*)task.obj()->klass(); k->oop_follow_contents(task.obj(), task.index()); } } while (!_marking_stack.is_empty() || !_objarray_stack.is_empty()); diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/gc_implementation/shared/markSweep.hpp --- a/src/share/vm/gc_implementation/shared/markSweep.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/markSweep.hpp Thu May 23 12:44:18 2013 +0100 @@ -113,7 +113,7 @@ // 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/allocation.cpp --- a/src/share/vm/memory/allocation.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/allocation.cpp Thu May 23 12:44:18 2013 +0100 @@ -49,10 +49,15 @@ # include "os_bsd.inline.hpp" #endif -void* StackObj::operator new(size_t size) { ShouldNotCallThis(); return 0; }; -void StackObj::operator delete(void* p) { ShouldNotCallThis(); }; -void* _ValueObj::operator new(size_t size) { ShouldNotCallThis(); return 0; }; -void _ValueObj::operator delete(void* p) { ShouldNotCallThis(); }; +void* StackObj::operator new(size_t size) { ShouldNotCallThis(); return 0; } +void StackObj::operator delete(void* p) { ShouldNotCallThis(); } +void* StackObj::operator new [](size_t size) { ShouldNotCallThis(); return 0; } +void StackObj::operator delete [](void* p) { ShouldNotCallThis(); } + +void* _ValueObj::operator new(size_t size) { ShouldNotCallThis(); return 0; } +void _ValueObj::operator delete(void* p) { ShouldNotCallThis(); } +void* _ValueObj::operator new [](size_t size) { ShouldNotCallThis(); return 0; } +void _ValueObj::operator delete [](void* p) { ShouldNotCallThis(); } void* MetaspaceObj::operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, bool read_only, TRAPS) { @@ -81,7 +86,6 @@ st->print(" {"INTPTR_FORMAT"}", this); } - void* ResourceObj::operator new(size_t size, allocation_type type, MEMFLAGS flags) { address res; switch (type) { @@ -99,6 +103,10 @@ return res; } +void* ResourceObj::operator new [](size_t size, allocation_type type, MEMFLAGS flags) { + return (address) operator new(size, type, flags); +} + void* ResourceObj::operator new(size_t size, const std::nothrow_t& nothrow_constant, allocation_type type, MEMFLAGS flags) { //should only call this with std::nothrow, use other operator new() otherwise @@ -118,6 +126,10 @@ return res; } +void* ResourceObj::operator new [](size_t size, const std::nothrow_t& nothrow_constant, + allocation_type type, MEMFLAGS flags) { + return (address)operator new(size, nothrow_constant, type, flags); +} void ResourceObj::operator delete(void* p) { assert(((ResourceObj *)p)->allocated_on_C_heap(), @@ -126,6 +138,10 @@ FreeHeap(p); } +void ResourceObj::operator delete [](void* p) { + operator delete(p); +} + #ifdef ASSERT void ResourceObj::set_allocation_type(address res, allocation_type type) { // Set allocation type in the resource object @@ -215,8 +231,6 @@ tty->print_cr("Heap free " INTPTR_FORMAT, p); } -bool warn_new_operator = false; // see vm_main - //-------------------------------------------------------------------------------------- // ChunkPool implementation @@ -360,7 +374,7 @@ void* Chunk::operator new (size_t requested_size, AllocFailType alloc_failmode, size_t length) { // requested_size is equal to sizeof(Chunk) but in order for the arena // allocations to come out aligned as expected the size must be aligned - // to expected arean alignment. + // to expected arena alignment. // expect requested_size but if sizeof(Chunk) doesn't match isn't proper size we must align it. assert(ARENA_ALIGN(requested_size) == aligned_overhead_size(), "Bad alignment"); size_t bytes = ARENA_ALIGN(requested_size) + length; @@ -667,19 +681,40 @@ // a memory leak. Use CHeapObj as the base class of such objects to make it explicit // that they're allocated on the C heap. // Commented out in product version to avoid conflicts with third-party C++ native code. -// %% note this is causing a problem on solaris debug build. the global -// new is being called from jdk source and causing data corruption. -// src/share/native/sun/awt/font/fontmanager/textcache/hsMemory.cpp::hsSoftNew -// define CATCH_OPERATOR_NEW_USAGE if you want to use this. -#ifdef CATCH_OPERATOR_NEW_USAGE +// On certain platforms, such as Mac OS X (Darwin), in debug version, new is being called +// from jdk source and causing data corruption. Such as +// Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair +// define ALLOW_OPERATOR_NEW_USAGE for platform on which global operator new allowed. +// +#ifndef ALLOW_OPERATOR_NEW_USAGE void* operator new(size_t size){ - static bool warned = false; - if (!warned && warn_new_operator) - warning("should not call global (default) operator new"); - warned = true; - return (void *) AllocateHeap(size, "global operator new"); + assert(false, "Should not call global operator new"); + return 0; +} + +void* operator new [](size_t size){ + assert(false, "Should not call global operator new[]"); + return 0; +} + +void* operator new(size_t size, const std::nothrow_t& nothrow_constant){ + assert(false, "Should not call global operator new"); + return 0; } -#endif + +void* operator new [](size_t size, std::nothrow_t& nothrow_constant){ + assert(false, "Should not call global operator new[]"); + return 0; +} + +void operator delete(void* p) { + assert(false, "Should not call global delete"); +} + +void operator delete [](void* p) { + assert(false, "Should not call global delete []"); +} +#endif // ALLOW_OPERATOR_NEW_USAGE void AllocatedObj::print() const { print_on(tty); } void AllocatedObj::print_value() const { print_value_on(tty); } diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/allocation.hpp --- a/src/share/vm/memory/allocation.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/allocation.hpp Thu May 23 12:44:18 2013 +0100 @@ -86,12 +86,23 @@ // subclasses. // // The following macros and function should be used to allocate memory -// directly in the resource area or in the C-heap: +// directly in the resource area or in the C-heap, The _OBJ variants +// of the NEW/FREE_C_HEAP macros are used for alloc/dealloc simple +// objects which are not inherited from CHeapObj, note constructor and +// destructor are not called. The preferable way to allocate objects +// is using the new operator. // -// NEW_RESOURCE_ARRAY(type,size) +// WARNING: The array variant must only be used for a homogenous array +// where all objects are of the exact type specified. If subtypes are +// stored in the array then must pay attention to calling destructors +// at needed. +// +// NEW_RESOURCE_ARRAY(type, size) // NEW_RESOURCE_OBJ(type) -// NEW_C_HEAP_ARRAY(type,size) -// NEW_C_HEAP_OBJ(type) +// NEW_C_HEAP_ARRAY(type, size) +// NEW_C_HEAP_OBJ(type, memflags) +// FREE_C_HEAP_ARRAY(type, old, memflags) +// FREE_C_HEAP_OBJ(objname, type, memflags) // char* AllocateHeap(size_t size, const char* name); // void FreeHeap(void* p); // @@ -195,8 +206,11 @@ _NOINLINE_ void* operator new(size_t size, address caller_pc = 0); _NOINLINE_ void* operator new (size_t size, const std::nothrow_t& nothrow_constant, address caller_pc = 0); - + _NOINLINE_ void* operator new [](size_t size, address caller_pc = 0); + _NOINLINE_ void* operator new [](size_t size, const std::nothrow_t& nothrow_constant, + address caller_pc = 0); void operator delete(void* p); + void operator delete [] (void* p); }; // Base class for objects allocated on the stack only. @@ -206,6 +220,8 @@ private: void* operator new(size_t size); void operator delete(void* p); + void* operator new [](size_t size); + void operator delete [](void* p); }; // Base class for objects used as value objects. @@ -229,7 +245,9 @@ class _ValueObj { private: void* operator new(size_t size); - void operator delete(void* p); + void operator delete(void* p); + void* operator new [](size_t size); + void operator delete [](void* p); }; @@ -518,13 +536,24 @@ public: void* operator new(size_t size, allocation_type type, MEMFLAGS flags); + void* operator new [](size_t size, allocation_type type, MEMFLAGS flags); void* operator new(size_t size, const std::nothrow_t& nothrow_constant, allocation_type type, MEMFLAGS flags); + void* operator new [](size_t size, const std::nothrow_t& nothrow_constant, + allocation_type type, MEMFLAGS flags); + void* operator new(size_t size, Arena *arena) { address res = (address)arena->Amalloc(size); DEBUG_ONLY(set_allocation_type(res, ARENA);) return res; } + + void* operator new [](size_t size, Arena *arena) { + address res = (address)arena->Amalloc(size); + DEBUG_ONLY(set_allocation_type(res, ARENA);) + return res; + } + void* operator new(size_t size) { address res = (address)resource_allocate_bytes(size); DEBUG_ONLY(set_allocation_type(res, RESOURCE_AREA);) @@ -537,7 +566,20 @@ return res; } + void* operator new [](size_t size) { + address res = (address)resource_allocate_bytes(size); + DEBUG_ONLY(set_allocation_type(res, RESOURCE_AREA);) + return res; + } + + void* operator new [](size_t size, const std::nothrow_t& nothrow_constant) { + address res = (address)resource_allocate_bytes(size, AllocFailStrategy::RETURN_NULL); + DEBUG_ONLY(if (res != NULL) set_allocation_type(res, RESOURCE_AREA);) + return res; + } + void operator delete(void* p); + void operator delete [](void* p); }; // One of the following macros must be used when allocating an array @@ -571,24 +613,25 @@ #define REALLOC_C_HEAP_ARRAY(type, old, size, memflags)\ (type*) (ReallocateHeap((char*)old, (size) * sizeof(type), memflags)) -#define FREE_C_HEAP_ARRAY(type,old,memflags) \ +#define FREE_C_HEAP_ARRAY(type, old, memflags) \ FreeHeap((char*)(old), memflags) -#define NEW_C_HEAP_OBJ(type, memflags)\ - NEW_C_HEAP_ARRAY(type, 1, memflags) - - #define NEW_C_HEAP_ARRAY2(type, size, memflags, pc)\ (type*) (AllocateHeap((size) * sizeof(type), memflags, pc)) #define REALLOC_C_HEAP_ARRAY2(type, old, size, memflags, pc)\ (type*) (ReallocateHeap((char*)old, (size) * sizeof(type), memflags, pc)) -#define NEW_C_HEAP_OBJ2(type, memflags, pc)\ - NEW_C_HEAP_ARRAY2(type, 1, memflags, pc) +#define NEW_C_HEAP_ARRAY3(type, size, memflags, pc, allocfail) \ + (type*) AllocateHeap(size * sizeof(type), memflags, pc, allocfail) +// allocate type in heap without calling ctor +#define NEW_C_HEAP_OBJ(type, memflags)\ + NEW_C_HEAP_ARRAY(type, 1, memflags) -extern bool warn_new_operator; +// deallocate obj of type in heap without calling dtor +#define FREE_C_HEAP_OBJ(objname, memflags)\ + FreeHeap((char*)objname, memflags); // for statistics #ifndef PRODUCT diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/allocation.inline.hpp --- a/src/share/vm/memory/allocation.inline.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/allocation.inline.hpp Thu May 23 12:44:18 2013 +0100 @@ -86,30 +86,39 @@ template void* CHeapObj::operator new(size_t size, address caller_pc){ + void* p = (void*)AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC)); #ifdef ASSERT - void* p = (void*)AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC)); if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p); +#endif return p; -#else - return (void *) AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC)); -#endif } template void* CHeapObj::operator new (size_t size, const std::nothrow_t& nothrow_constant, address caller_pc) { -#ifdef ASSERT void* p = (void*)AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC), AllocFailStrategy::RETURN_NULL); +#ifdef ASSERT if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p); +#endif return p; -#else - return (void *) AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC), - AllocFailStrategy::RETURN_NULL); -#endif +} + +template void* CHeapObj::operator new [](size_t size, + address caller_pc){ + return CHeapObj::operator new(size, caller_pc); +} + +template void* CHeapObj::operator new [](size_t size, + const std::nothrow_t& nothrow_constant, address caller_pc) { + return CHeapObj::operator new(size, nothrow_constant, caller_pc); } template void CHeapObj::operator delete(void* p){ - FreeHeap(p, F); + FreeHeap(p, F); +} + +template void CHeapObj::operator delete [](void* p){ + FreeHeap(p, F); } template diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/cardTableModRefBS.cpp --- a/src/share/vm/memory/cardTableModRefBS.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/cardTableModRefBS.cpp Thu May 23 12:44:18 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -80,15 +80,11 @@ _covered = new MemRegion[max_covered_regions]; _committed = new MemRegion[max_covered_regions]; - if (_covered == NULL || _committed == NULL) + if (_covered == NULL || _committed == NULL) { vm_exit_during_initialization("couldn't alloc card table covered region set."); - int i; - for (i = 0; i < max_covered_regions; i++) { - _covered[i].set_word_size(0); - _committed[i].set_word_size(0); } + _cur_covered_regions = 0; - const size_t rs_align = _page_size == (size_t) os::vm_page_size() ? 0 : MAX2(_page_size, (size_t) os::vm_allocation_granularity()); ReservedSpace heap_rs(_byte_map_size, rs_align, false); @@ -134,7 +130,7 @@ || _lowest_non_clean_base_chunk_index == NULL || _last_LNC_resizing_collection == NULL) vm_exit_during_initialization("couldn't allocate an LNC array."); - for (i = 0; i < max_covered_regions; i++) { + for (int i = 0; i < max_covered_regions; i++) { _lowest_non_clean[i] = NULL; _lowest_non_clean_chunk_size[i] = 0; _last_LNC_resizing_collection[i] = -1; @@ -153,6 +149,33 @@ } } +CardTableModRefBS::~CardTableModRefBS() { + if (_covered) { + delete[] _covered; + _covered = NULL; + } + if (_committed) { + delete[] _committed; + _committed = NULL; + } + if (_lowest_non_clean) { + FREE_C_HEAP_ARRAY(CardArr, _lowest_non_clean, mtGC); + _lowest_non_clean = NULL; + } + if (_lowest_non_clean_chunk_size) { + FREE_C_HEAP_ARRAY(size_t, _lowest_non_clean_chunk_size, mtGC); + _lowest_non_clean_chunk_size = NULL; + } + if (_lowest_non_clean_base_chunk_index) { + FREE_C_HEAP_ARRAY(uintptr_t, _lowest_non_clean_base_chunk_index, mtGC); + _lowest_non_clean_base_chunk_index = NULL; + } + if (_last_LNC_resizing_collection) { + FREE_C_HEAP_ARRAY(int, _last_LNC_resizing_collection, mtGC); + _last_LNC_resizing_collection = NULL; + } +} + int CardTableModRefBS::find_covering_region_by_base(HeapWord* base) { int i; for (i = 0; i < _cur_covered_regions; i++) { diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/cardTableModRefBS.hpp --- a/src/share/vm/memory/cardTableModRefBS.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/cardTableModRefBS.hpp Thu May 23 12:44:18 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -280,6 +280,7 @@ } CardTableModRefBS(MemRegion whole_heap, int max_covered_regions); + ~CardTableModRefBS(); // *** Barrier set functions. diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/cardTableRS.cpp --- a/src/share/vm/memory/cardTableRS.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/cardTableRS.cpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ -54,9 +54,10 @@ _ct_bs = new CardTableModRefBSForCTRS(whole_heap, max_covered_regions); #endif set_bs(_ct_bs); - _last_cur_val_in_gen = new jbyte[GenCollectedHeap::max_gens + 1]; + _last_cur_val_in_gen = NEW_C_HEAP_ARRAY3(jbyte, GenCollectedHeap::max_gens + 1, + mtGC, 0, AllocFailStrategy::RETURN_NULL); if (_last_cur_val_in_gen == NULL) { - vm_exit_during_initialization("Could not last_cur_val_in_gen array."); + vm_exit_during_initialization("Could not create last_cur_val_in_gen array."); } for (int i = 0; i < GenCollectedHeap::max_gens + 1; i++) { _last_cur_val_in_gen[i] = clean_card_val(); @@ -64,6 +65,16 @@ _ct_bs->set_CTRS(this); } +CardTableRS::~CardTableRS() { + if (_ct_bs) { + delete _ct_bs; + _ct_bs = NULL; + } + if (_last_cur_val_in_gen) { + FREE_C_HEAP_ARRAY(jbyte, _last_cur_val_in_gen, mtInternal); + } +} + void CardTableRS::resize_covered_region(MemRegion new_region) { _ct_bs->resize_covered_region(new_region); } diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/cardTableRS.hpp --- a/src/share/vm/memory/cardTableRS.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/cardTableRS.hpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ -102,6 +102,7 @@ public: CardTableRS(MemRegion whole_heap, int max_covered_regions); + ~CardTableRS(); // *** GenRemSet functions. GenRemSet::Name rs_kind() { return GenRemSet::CardTable; } diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/collectorPolicy.cpp --- a/src/share/vm/memory/collectorPolicy.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/collectorPolicy.cpp Thu May 23 12:44:18 2013 +0100 @@ -264,6 +264,27 @@ // 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 @@ // 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 */, @@ -856,7 +877,7 @@ } void MarkSweepPolicy::initialize_generations() { - _generations = new GenerationSpecPtr[number_of_generations()]; + _generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, 0, AllocFailStrategy::RETURN_NULL); if (_generations == NULL) vm_exit_during_initialization("Unable to allocate gen spec"); diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/heapInspection.cpp --- a/src/share/vm/memory/heapInspection.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/heapInspection.cpp Thu May 23 12:44:18 2013 +0100 @@ -154,12 +154,12 @@ } } -uint KlassInfoTable::hash(Klass* p) { +uint KlassInfoTable::hash(const Klass* p) { assert(p->is_metadata(), "all klasses are metadata"); return (uint)(((uintptr_t)p - (uintptr_t)_ref) >> 2); } -KlassInfoEntry* KlassInfoTable::lookup(Klass* const k) { +KlassInfoEntry* KlassInfoTable::lookup(Klass* k) { uint idx = hash(k) % _size; assert(_buckets != NULL, "Allocation failure should have been caught"); KlassInfoEntry* e = _buckets[idx].lookup(k); diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/heapInspection.hpp --- a/src/share/vm/memory/heapInspection.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/heapInspection.hpp Thu May 23 12:44:18 2013 +0100 @@ -189,15 +189,15 @@ KlassInfoEntry(Klass* k, KlassInfoEntry* next) : _klass(k), _instance_count(0), _instance_words(0), _next(next), _index(-1) {} - KlassInfoEntry* next() { return _next; } - bool is_equal(Klass* k) { return k == _klass; } - Klass* klass() { return _klass; } - long count() { return _instance_count; } + KlassInfoEntry* next() const { return _next; } + bool is_equal(const Klass* k) { return k == _klass; } + Klass* klass() const { return _klass; } + long count() const { return _instance_count; } void set_count(long ct) { _instance_count = ct; } - size_t words() { return _instance_words; } + size_t words() const { return _instance_words; } void set_words(size_t wds) { _instance_words = wds; } void set_index(long index) { _index = index; } - long index() { return _index; } + long index() const { return _index; } int compare(KlassInfoEntry* e1, KlassInfoEntry* e2); void print_on(outputStream* st) const; const char* name() const; @@ -215,7 +215,7 @@ KlassInfoEntry* list() { return _list; } void set_list(KlassInfoEntry* l) { _list = l; } public: - KlassInfoEntry* lookup(Klass* const k); + KlassInfoEntry* lookup(Klass* k); void initialize() { _list = NULL; } void empty(); void iterate(KlassInfoClosure* cic); @@ -231,8 +231,8 @@ HeapWord* _ref; KlassInfoBucket* _buckets; - uint hash(Klass* p); - KlassInfoEntry* lookup(Klass* const k); // allocates if not found! + uint hash(const Klass* p); + KlassInfoEntry* lookup(Klass* k); // allocates if not found! class AllClassesFinder : public KlassClosure { KlassInfoTable *_table; diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/memRegion.cpp --- a/src/share/vm/memory/memRegion.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/memRegion.cpp Thu May 23 12:44:18 2013 +0100 @@ -23,6 +23,8 @@ */ #include "precompiled.hpp" +#include "memory/allocation.hpp" +#include "memory/allocation.inline.hpp" #include "memory/memRegion.hpp" #include "runtime/globals.hpp" @@ -99,3 +101,19 @@ ShouldNotReachHere(); return MemRegion(); } + +void* MemRegion::operator new(size_t size) { + return (address)AllocateHeap(size, mtGC, 0, AllocFailStrategy::RETURN_NULL); +} + +void* MemRegion::operator new [](size_t size) { + return (address)AllocateHeap(size, mtGC, 0, AllocFailStrategy::RETURN_NULL); +} +void MemRegion::operator delete(void* p) { + FreeHeap(p, mtGC); +} + +void MemRegion::operator delete [](void* p) { + FreeHeap(p, mtGC); +} + diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/memRegion.hpp --- a/src/share/vm/memory/memRegion.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/memRegion.hpp Thu May 23 12:44:18 2013 +0100 @@ -34,7 +34,9 @@ // Note that MemRegions are passed by value, not by reference. // The intent is that they remain very small and contain no -// objects. +// objects. _ValueObj should never be allocated in heap but we do +// create MemRegions (in CardTableModRefBS) in heap so operator +// new and operator new [] added for this special case. class MetaWord; @@ -92,6 +94,10 @@ size_t word_size() const { return _word_size; } bool is_empty() const { return word_size() == 0; } + void* operator new(size_t size); + void* operator new [](size_t size); + void operator delete(void* p); + void operator delete [](void* p); }; // For iteration over MemRegion's. diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/space.hpp --- a/src/share/vm/memory/space.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/space.hpp Thu May 23 12:44:18 2013 +0100 @@ -537,9 +537,8 @@ * 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/universe.cpp Thu May 23 12:44:18 2013 +0100 @@ -1445,25 +1445,25 @@ } -void ActiveMethodOopsCache::add_previous_version(Method* const method) { +void ActiveMethodOopsCache::add_previous_version(Method* method) { assert(Thread::current()->is_VM_thread(), "only VMThread can add previous versions"); // Only append the previous method if it is executing on the stack. if (method->on_stack()) { - if (_prev_methods == NULL) { - // This is the first previous version so make some space. - // Start with 2 elements under the assumption that the class - // won't be redefined much. + if (_prev_methods == NULL) { + // This is the first previous version so make some space. + // Start with 2 elements under the assumption that the class + // won't be redefined much. _prev_methods = new (ResourceObj::C_HEAP, mtClass) GrowableArray(2, true); - } + } - // RC_TRACE macro has an embedded ResourceMark - RC_TRACE(0x00000100, - ("add: %s(%s): adding prev version ref for cached method @%d", - method->name()->as_C_string(), method->signature()->as_C_string(), - _prev_methods->length())); + // RC_TRACE macro has an embedded ResourceMark + RC_TRACE(0x00000100, + ("add: %s(%s): adding prev version ref for cached method @%d", + method->name()->as_C_string(), method->signature()->as_C_string(), + _prev_methods->length())); _prev_methods->append(method); } @@ -1484,16 +1484,17 @@ MetadataFactory::free_metadata(method->method_holder()->class_loader_data(), method); } else { // RC_TRACE macro has an embedded ResourceMark - RC_TRACE(0x00000400, ("add: %s(%s): previous cached method @%d is alive", - method->name()->as_C_string(), method->signature()->as_C_string(), i)); + RC_TRACE(0x00000400, + ("add: %s(%s): previous cached method @%d is alive", + method->name()->as_C_string(), method->signature()->as_C_string(), i)); } } } // end add_previous_version() -bool ActiveMethodOopsCache::is_same_method(Method* const method) const { +bool ActiveMethodOopsCache::is_same_method(const Method* method) const { InstanceKlass* ik = InstanceKlass::cast(klass()); - Method* check_method = ik->method_with_idnum(method_idnum()); + const Method* check_method = ik->method_with_idnum(method_idnum()); assert(check_method != NULL, "sanity check"); if (check_method == method) { // done with the easy case diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/memory/universe.hpp --- a/src/share/vm/memory/universe.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/memory/universe.hpp Thu May 23 12:44:18 2013 +0100 @@ -90,8 +90,8 @@ ActiveMethodOopsCache() { _prev_methods = NULL; } ~ActiveMethodOopsCache(); - void add_previous_version(Method* const method); - bool is_same_method(Method* const method) const; + void add_previous_version(Method* method); + bool is_same_method(const Method* method) const; }; diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/oops/constantPool.hpp --- a/src/share/vm/oops/constantPool.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/oops/constantPool.hpp Thu May 23 12:44:18 2013 +0100 @@ -354,7 +354,7 @@ Symbol* klass_name_at(int which); // Returns the name, w/o resolving. - Klass* resolved_klass_at(int which) { // Used by Compiler + Klass* resolved_klass_at(int which) const { // Used by Compiler guarantee(tag_at(which).is_klass(), "Corrupted constant pool"); // Must do an acquire here in case another thread resolved the klass // behind our back, lest we later load stale values thru the oop. diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/oops/instanceKlass.cpp Thu May 23 12:44:18 2013 +0100 @@ -2724,7 +2724,7 @@ OsrList_lock->unlock(); } -nmethod* InstanceKlass::lookup_osr_nmethod(Method* const m, int bci, int comp_level, bool match_level) const { +nmethod* InstanceKlass::lookup_osr_nmethod(const Method* m, int bci, int comp_level, bool match_level) const { // This is a short non-blocking critical region, so the no safepoint check is ok. OsrList_lock->lock_without_safepoint_check(); nmethod* osr = osr_nmethods_head(); diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/oops/instanceKlass.hpp Thu May 23 12:44:18 2013 +0100 @@ -739,7 +739,7 @@ void set_osr_nmethods_head(nmethod* h) { _osr_nmethods_head = h; }; void add_osr_nmethod(nmethod* n); void remove_osr_nmethod(nmethod* n); - nmethod* lookup_osr_nmethod(Method* const m, int bci, int level, bool match_level) const; + nmethod* lookup_osr_nmethod(const Method* m, int bci, int level, bool match_level) const; // Breakpoint support (see methods on Method* for details) BreakpointInfo* breakpoints() const { return _breakpoints; }; diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/oops/klass.cpp --- a/src/share/vm/oops/klass.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/oops/klass.cpp Thu May 23 12:44:18 2013 +0100 @@ -50,7 +50,7 @@ if (_name != NULL) _name->increment_refcount(); } -bool Klass::is_subclass_of(Klass* k) const { +bool Klass::is_subclass_of(const Klass* k) const { // Run up the super chain and check if (this == k) return true; diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/oops/klass.hpp --- a/src/share/vm/oops/klass.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/oops/klass.hpp Thu May 23 12:44:18 2013 +0100 @@ -393,9 +393,10 @@ // vtables virtual klassVtable* vtable() const { return NULL; } + virtual int vtable_length() const { return 0; } // subclass check - bool is_subclass_of(Klass* k) const; + bool is_subclass_of(const Klass* k) const; // subtype check: true if is_subclass_of, or if k is interface and receiver implements it bool is_subtype_of(Klass* k) const { juint off = k->super_check_offset(); diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/oops/method.cpp Thu May 23 12:44:18 2013 +0100 @@ -832,7 +832,9 @@ 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); @@ -1581,7 +1583,7 @@ } int Method::highest_comp_level() const { - MethodData* mdo = method_data(); + const MethodData* mdo = method_data(); if (mdo != NULL) { return mdo->highest_comp_level(); } else { @@ -1590,7 +1592,7 @@ } int Method::highest_osr_comp_level() const { - MethodData* mdo = method_data(); + const MethodData* mdo = method_data(); if (mdo != NULL) { return mdo->highest_osr_comp_level(); } else { diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/oops/method.hpp --- a/src/share/vm/oops/method.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/oops/method.hpp Thu May 23 12:44:18 2013 +0100 @@ -986,7 +986,7 @@ u2 _length; public: - ExceptionTable(Method* m) { + ExceptionTable(const Method* m) { if (m->has_exception_handler()) { _table = m->exception_table_start(); _length = m->exception_table_length(); diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/oops/methodData.hpp --- a/src/share/vm/oops/methodData.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/oops/methodData.hpp Thu May 23 12:44:18 2013 +0100 @@ -1338,9 +1338,9 @@ void set_would_profile(bool p) { _would_profile = p; } bool would_profile() const { return _would_profile; } - int highest_comp_level() { return _highest_comp_level; } + int highest_comp_level() const { return _highest_comp_level; } void set_highest_comp_level(int level) { _highest_comp_level = level; } - int highest_osr_comp_level() { return _highest_osr_comp_level; } + int highest_osr_comp_level() const { return _highest_osr_comp_level; } void set_highest_osr_comp_level(int level) { _highest_osr_comp_level = level; } int num_loops() const { return _num_loops; } diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/bytecodeInfo.cpp --- a/src/share/vm/opto/bytecodeInfo.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/bytecodeInfo.cpp Thu May 23 12:44:18 2013 +0100 @@ -85,16 +85,35 @@ 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 @@ // 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 @@ 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 @@ } } - 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 @@ } 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/c2_globals.hpp --- a/src/share/vm/opto/c2_globals.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/c2_globals.hpp Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/c2compiler.cpp --- a/src/share/vm/opto/c2compiler.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/c2compiler.cpp Thu May 23 12:44:18 2013 +0100 @@ -125,9 +125,10 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/callGenerator.cpp --- a/src/share/vm/opto/callGenerator.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/callGenerator.cpp Thu May 23 12:44:18 2013 +0100 @@ -134,7 +134,7 @@ 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 @@ 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 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/callGenerator.hpp --- a/src/share/vm/opto/callGenerator.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/callGenerator.hpp Thu May 23 12:44:18 2013 +0100 @@ -125,6 +125,7 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/callnode.cpp --- a/src/share/vm/opto/callnode.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/callnode.cpp Thu May 23 12:44:18 2013 +0100 @@ -523,7 +523,9 @@ 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 @@ 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 @@ _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 @@ 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 @@ // 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 @@ 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 @@ 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::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 @@ 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 @@ } //============================================================================= -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 @@ // - 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/callnode.hpp --- a/src/share/vm/opto/callnode.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/callnode.hpp Thu May 23 12:44:18 2013 +0100 @@ -49,6 +49,7 @@ class CallLeafNoFPNode; class AllocateNode; class AllocateArrayNode; +class BoxLockNode; class LockNode; class UnlockNode; class JVMState; @@ -235,7 +236,6 @@ 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 @@ // 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ // 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 @@ 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 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/cfgnode.cpp --- a/src/share/vm/opto/cfgnode.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/cfgnode.cpp Thu May 23 12:44:18 2013 +0100 @@ -806,7 +806,7 @@ 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 @@ 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 @@ // 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 @@ _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 @@ _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 @@ _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 @@ 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 @@ _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 @@ { ResourceMark rm; - PhaseRemoveUseless pru(C->initial_gvn(), C->for_igvn()); + PhaseRemoveUseless pru(gvn, for_igvn()); } igvn = PhaseIterGVN(gvn); @@ -1929,12 +1973,25 @@ 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 @@ } 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/compile.hpp --- a/src/share/vm/opto/compile.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/compile.hpp Thu May 23 12:44:18 2013 +0100 @@ -262,6 +262,7 @@ 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 @@ 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 @@ // 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 @@ // 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 @@ 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 @@ #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 @@ // 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 @@ _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 @@ 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 @@ // 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/doCall.cpp --- a/src/share/vm/opto/doCall.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/doCall.cpp Thu May 23 12:44:18 2013 +0100 @@ -176,9 +176,12 @@ // 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 @@ // 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/escape.cpp --- a/src/share/vm/opto/escape.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/escape.cpp Thu May 23 12:44:18 2013 +0100 @@ -63,15 +63,19 @@ // 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 @@ { 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 @@ // 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 @@ 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 @@ // 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 @@ 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 @@ 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 @@ 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 @@ // 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 @@ 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 @@ 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 @@ // 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 @@ // 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 @@ // 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 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/graphKit.cpp --- a/src/share/vm/opto/graphKit.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/graphKit.cpp Thu May 23 12:44:18 2013 +0100 @@ -333,6 +333,7 @@ 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 @@ 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 @@ } 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 @@ 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 @@ // 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 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/idealGraphPrinter.hpp --- a/src/share/vm/opto/idealGraphPrinter.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/idealGraphPrinter.hpp Thu May 23 12:44:18 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -41,9 +41,8 @@ class InlineTree; class ciMethod; -class IdealGraphPrinter -{ -private: +class IdealGraphPrinter : public CHeapObj { + private: static const char *INDENT; static const char *TOP_ELEMENT; @@ -121,7 +120,7 @@ IdealGraphPrinter(); ~IdealGraphPrinter(); -public: + public: static void clean_up(); static IdealGraphPrinter *printer(); @@ -135,8 +134,6 @@ void print_method(Compile* compile, const char *name, int level=1, bool clear_nodes = false); void print(Compile* compile, const char *name, Node *root, int level=1, bool clear_nodes = false); void print_xml(const char *name); - - }; #endif diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/ifnode.cpp --- a/src/share/vm/opto/ifnode.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/ifnode.cpp Thu May 23 12:44:18 2013 +0100 @@ -673,7 +673,7 @@ // / 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/lcm.cpp --- a/src/share/vm/opto/lcm.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/lcm.cpp Thu May 23 12:44:18 2013 +0100 @@ -219,9 +219,10 @@ // 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/library_call.cpp --- a/src/share/vm/opto/library_call.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/library_call.cpp Thu May 23 12:44:18 2013 +0100 @@ -2783,7 +2783,7 @@ #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 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/loopPredicate.cpp --- a/src/share/vm/opto/loopPredicate.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/loopPredicate.cpp Thu May 23 12:44:18 2013 +0100 @@ -821,8 +821,8 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/machnode.cpp --- a/src/share/vm/opto/machnode.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/machnode.cpp Thu May 23 12:44:18 2013 +0100 @@ -349,11 +349,11 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/macro.cpp --- a/src/share/vm/opto/macro.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/macro.cpp Thu May 23 12:44:18 2013 +0100 @@ -666,7 +666,7 @@ 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 @@ if (field_val->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 @@ // to the allocated object with "sobj" int start = jvms->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 @@ // 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 @@ #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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/macro.hpp --- a/src/share/vm/opto/macro.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/macro.hpp Thu May 23 12:44:18 2013 +0100 @@ -86,10 +86,11 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/memnode.cpp --- a/src/share/vm/opto/memnode.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/memnode.cpp Thu May 23 12:44:18 2013 +0100 @@ -103,11 +103,15 @@ #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 @@ 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 @@ 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 @@ // 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 @@ // 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* 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 @@ 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 @@ 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 @@ 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 @@ //----------------------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 @@ 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 @@ // 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 @@ 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 (!base->in(Address)->is_AddP()) { + return NULL; // Complex address } - 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()) { + 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])); + 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 + 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; } - // 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)); - } -#ifdef _LP64 - result = new (phase->C) ConvL2INode(phase->transform(result)); -#endif - return result; } } } @@ -1293,65 +1263,131 @@ 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 @@ } 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 @@ 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 @@ } } } - 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // (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 @@ 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 @@ // 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 @@ // 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 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/memnode.hpp --- a/src/share/vm/opto/memnode.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/memnode.hpp Thu May 23 12:44:18 2013 +0100 @@ -75,8 +75,8 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/multnode.cpp --- a/src/share/vm/opto/multnode.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/multnode.cpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ 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 @@ //------------------------------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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/multnode.hpp --- a/src/share/vm/opto/multnode.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/multnode.hpp Thu May 23 12:44:18 2013 +0100 @@ -60,6 +60,7 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/node.cpp --- a/src/share/vm/opto/node.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/node.cpp Thu May 23 12:44:18 2013 +0100 @@ -67,7 +67,8 @@ } 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 @@ //------------------------------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 @@ 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 @@ (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 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/node.hpp --- a/src/share/vm/opto/node.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/node.hpp Thu May 23 12:44:18 2013 +0100 @@ -410,6 +410,7 @@ // 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 @@ } 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/output.cpp --- a/src/share/vm/opto/output.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/output.cpp Thu May 23 12:44:18 2013 +0100 @@ -929,7 +929,7 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/parse.hpp --- a/src/share/vm/opto/parse.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/parse.hpp Thu May 23 12:44:18 2013 +0100 @@ -330,6 +330,7 @@ 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 @@ 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 @@ // 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/parse1.cpp --- a/src/share/vm/opto/parse1.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/parse1.cpp Thu May 23 12:44:18 2013 +0100 @@ -390,6 +390,7 @@ _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 @@ // 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 @@ } 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 @@ // 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/parse2.cpp --- a/src/share/vm/opto/parse2.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/parse2.cpp Thu May 23 12:44:18 2013 +0100 @@ -987,7 +987,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ // Branch not taken. if (stopped()) { - if (EliminateAutoBox) { + if (C->eliminate_boxing()) { // Mark the successor block as parsed next_block->next_path_num(); } diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/parse3.cpp --- a/src/share/vm/opto/parse3.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/parse3.cpp Thu May 23 12:44:18 2013 +0100 @@ -150,6 +150,23 @@ // 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 @@ // 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/parseHelper.cpp --- a/src/share/vm/opto/parseHelper.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/parseHelper.cpp Thu May 23 12:44:18 2013 +0100 @@ -284,6 +284,11 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/phase.cpp --- a/src/share/vm/opto/phase.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/phase.cpp Thu May 23 12:44:18 2013 +0100 @@ -64,6 +64,7 @@ // 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/phase.hpp --- a/src/share/vm/opto/phase.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/phase.hpp Thu May 23 12:44:18 2013 +0100 @@ -100,6 +100,7 @@ // 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/phaseX.cpp --- a/src/share/vm/opto/phaseX.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/phaseX.cpp Thu May 23 12:44:18 2013 +0100 @@ -882,7 +882,7 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/runtime.cpp --- a/src/share/vm/opto/runtime.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/runtime.cpp Thu May 23 12:44:18 2013 +0100 @@ -126,17 +126,15 @@ // 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/subnode.cpp --- a/src/share/vm/opto/subnode.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/subnode.cpp Thu May 23 12:44:18 2013 +0100 @@ -863,10 +863,11 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/type.cpp --- a/src/share/vm/opto/type.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/type.cpp Thu May 23 12:44:18 2013 +0100 @@ -2372,7 +2372,12 @@ _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 @@ //------------------------------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 @@ 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 @@ 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 @@ 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 @@ //------------------------------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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/opto/type.hpp --- a/src/share/vm/opto/type.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/opto/type.hpp Thu May 23 12:44:18 2013 +0100 @@ -234,6 +234,9 @@ 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 @@ 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 @@ // 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 @@ // 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 @@ // 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 @@ //------------------------------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 @@ 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 @@ 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/prims/jvm.cpp Thu May 23 12:44:18 2013 +0100 @@ -1779,7 +1779,7 @@ for (int i = 0; i < num_params; i++) { MethodParametersElement* params = mh->method_parameters_start(); // For a 0 index, give a NULL symbol - Symbol* const sym = 0 != params[i].name_cp_index ? + Symbol* sym = 0 != params[i].name_cp_index ? mh->constants()->symbol_at(params[i].name_cp_index) : NULL; int flags = params[i].flags; oop param = Reflection::new_parameter(reflected_method, i, sym, diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/prims/jvmtiExport.cpp --- a/src/share/vm/prims/jvmtiExport.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/prims/jvmtiExport.cpp Thu May 23 12:44:18 2013 +0100 @@ -619,6 +619,9 @@ // data has been changed by the new retransformable agent // and it hasn't already been cached, cache it *_cached_data_ptr = (unsigned char *)os::malloc(_curr_len, mtInternal); + if (*_cached_data_ptr == NULL) { + vm_exit_out_of_memory(_curr_len, OOM_MALLOC_ERROR, "unable to allocate cached copy of original class bytes"); + } memcpy(*_cached_data_ptr, _curr_data, _curr_len); *_cached_length_ptr = _curr_len; } diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu May 23 12:44:18 2013 +0100 @@ -160,7 +160,8 @@ if (RC_TRACE_ENABLED(0x00004000)) { #endif RC_TRACE_WITH_THREAD(0x00004000, thread, ("calling check_class")); - SystemDictionary::classes_do(check_class, thread); + CheckClass check_class(thread); + ClassLoaderDataGraph::classes_do(&check_class); #ifdef PRODUCT } #endif @@ -2653,29 +2654,35 @@ } // end set_new_constant_pool() -void VM_RedefineClasses::adjust_array_vtable(Klass* k_oop) { - ArrayKlass* ak = ArrayKlass::cast(k_oop); - bool trace_name_printed = false; - ak->vtable()->adjust_method_entries(_matching_old_methods, - _matching_new_methods, - _matching_methods_length, - &trace_name_printed); -} - // Unevolving classes may point to methods of the_class directly // from their constant pool caches, itables, and/or vtables. We -// use the SystemDictionary::classes_do() facility and this helper +// use the ClassLoaderDataGraph::classes_do() facility and this helper // to fix up these pointers. -// -// Note: We currently don't support updating the vtable in -// arrayKlassOops. See Open Issues in jvmtiRedefineClasses.hpp. -void VM_RedefineClasses::adjust_cpool_cache_and_vtable(Klass* k_oop, - ClassLoaderData* initiating_loader, - TRAPS) { - Klass *k = k_oop; - if (k->oop_is_instance()) { - HandleMark hm(THREAD); - InstanceKlass *ik = (InstanceKlass *) k; + +// Adjust cpools and vtables closure +void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { + + // This is a very busy routine. We don't want too much tracing + // printed out. + bool trace_name_printed = false; + + // Very noisy: only enable this call if you are trying to determine + // that a specific class gets found by this routine. + // RC_TRACE macro has an embedded ResourceMark + // RC_TRACE_WITH_THREAD(0x00100000, THREAD, + // ("adjust check: name=%s", k->external_name())); + // trace_name_printed = true; + + // If the class being redefined is java.lang.Object, we need to fix all + // array class vtables also + if (k->oop_is_array() && _the_class_oop == SystemDictionary::Object_klass()) { + k->vtable()->adjust_method_entries(_matching_old_methods, + _matching_new_methods, + _matching_methods_length, + &trace_name_printed); + } else if (k->oop_is_instance()) { + HandleMark hm(_thread); + InstanceKlass *ik = InstanceKlass::cast(k); // HotSpot specific optimization! HotSpot does not currently // support delegation from the bootstrap class loader to a @@ -2695,23 +2702,6 @@ return; } - // If the class being redefined is java.lang.Object, we need to fix all - // array class vtables also - if (_the_class_oop == SystemDictionary::Object_klass()) { - ik->array_klasses_do(adjust_array_vtable); - } - - // This is a very busy routine. We don't want too much tracing - // printed out. - bool trace_name_printed = false; - - // Very noisy: only enable this call if you are trying to determine - // that a specific class gets found by this routine. - // RC_TRACE macro has an embedded ResourceMark - // RC_TRACE_WITH_THREAD(0x00100000, THREAD, - // ("adjust check: name=%s", ik->external_name())); - // trace_name_printed = true; - // Fix the vtable embedded in the_class and subclasses of the_class, // if one exists. We discard scratch_class and we don't keep an // InstanceKlass around to hold obsolete methods so we don't have @@ -2719,7 +2709,7 @@ // holds the Method*s for virtual (but not final) methods. if (ik->vtable_length() > 0 && ik->is_subtype_of(_the_class_oop)) { // ik->vtable() creates a wrapper object; rm cleans it up - ResourceMark rm(THREAD); + ResourceMark rm(_thread); ik->vtable()->adjust_method_entries(_matching_old_methods, _matching_new_methods, _matching_methods_length, @@ -2735,7 +2725,7 @@ if (ik->itable_length() > 0 && (_the_class_oop->is_interface() || ik->is_subclass_of(_the_class_oop))) { // ik->itable() creates a wrapper object; rm cleans it up - ResourceMark rm(THREAD); + ResourceMark rm(_thread); ik->itable()->adjust_method_entries(_matching_old_methods, _matching_new_methods, _matching_methods_length, @@ -2758,7 +2748,7 @@ constantPoolHandle other_cp; ConstantPoolCache* cp_cache; - if (k_oop != _the_class_oop) { + if (ik != _the_class_oop) { // this klass' constant pool cache may need adjustment other_cp = constantPoolHandle(ik->constants()); cp_cache = other_cp->cache(); @@ -2770,7 +2760,7 @@ } } { - ResourceMark rm(THREAD); + ResourceMark rm(_thread); // PreviousVersionInfo objects returned via PreviousVersionWalker // contain a GrowableArray of handles. We have to clean up the // GrowableArray _after_ the PreviousVersionWalker destructor @@ -3208,7 +3198,7 @@ // parts of the_class // - adjusting constant pool caches and vtables in other classes // that refer to methods in the_class. These adjustments use the -// SystemDictionary::classes_do() facility which only allows +// ClassLoaderDataGraph::classes_do() facility which only allows // a helper method to be specified. The interesting parameters // that we would like to pass to the helper method are saved in // static global fields in the VM operation. @@ -3366,6 +3356,10 @@ } #endif + // NULL out in scratch class to not delete twice. The class to be redefined + // always owns these bytes. + scratch_class->set_cached_class_file(NULL, 0); + // Replace inner_classes Array* old_inner_classes = the_class->inner_classes(); the_class->set_inner_classes(scratch_class->inner_classes()); @@ -3438,7 +3432,8 @@ // Adjust constantpool caches and vtables for all classes // that reference methods of the evolved class. - SystemDictionary::classes_do(adjust_cpool_cache_and_vtable, THREAD); + AdjustCpoolCacheAndVtable adjust_cpool_cache_and_vtable(THREAD); + ClassLoaderDataGraph::classes_do(&adjust_cpool_cache_and_vtable); // JSR-292 support MemberNameTable* mnt = the_class->member_names(); @@ -3499,34 +3494,33 @@ } } -void VM_RedefineClasses::check_class(Klass* k_oop, - ClassLoaderData* initiating_loader, - TRAPS) { - Klass *k = k_oop; +void VM_RedefineClasses::CheckClass::do_klass(Klass* k) { + bool no_old_methods = true; // be optimistic + + // Both array and instance classes have vtables. + // a vtable should never contain old or obsolete methods + ResourceMark rm(_thread); + if (k->vtable_length() > 0 && + !k->vtable()->check_no_old_or_obsolete_entries()) { + if (RC_TRACE_ENABLED(0x00004000)) { + RC_TRACE_WITH_THREAD(0x00004000, _thread, + ("klassVtable::check_no_old_or_obsolete_entries failure" + " -- OLD or OBSOLETE method found -- class: %s", + k->signature_name())); + k->vtable()->dump_vtable(); + } + no_old_methods = false; + } + if (k->oop_is_instance()) { - HandleMark hm(THREAD); - InstanceKlass *ik = (InstanceKlass *) k; - bool no_old_methods = true; // be optimistic - ResourceMark rm(THREAD); - - // a vtable should never contain old or obsolete methods - if (ik->vtable_length() > 0 && - !ik->vtable()->check_no_old_or_obsolete_entries()) { - if (RC_TRACE_ENABLED(0x00004000)) { - RC_TRACE_WITH_THREAD(0x00004000, THREAD, - ("klassVtable::check_no_old_or_obsolete_entries failure" - " -- OLD or OBSOLETE method found -- class: %s", - ik->signature_name())); - ik->vtable()->dump_vtable(); - } - no_old_methods = false; - } + HandleMark hm(_thread); + InstanceKlass *ik = InstanceKlass::cast(k); // an itable should never contain old or obsolete methods if (ik->itable_length() > 0 && !ik->itable()->check_no_old_or_obsolete_entries()) { if (RC_TRACE_ENABLED(0x00004000)) { - RC_TRACE_WITH_THREAD(0x00004000, THREAD, + RC_TRACE_WITH_THREAD(0x00004000, _thread, ("klassItable::check_no_old_or_obsolete_entries failure" " -- OLD or OBSOLETE method found -- class: %s", ik->signature_name())); @@ -3540,7 +3534,7 @@ ik->constants()->cache() != NULL && !ik->constants()->cache()->check_no_old_or_obsolete_entries()) { if (RC_TRACE_ENABLED(0x00004000)) { - RC_TRACE_WITH_THREAD(0x00004000, THREAD, + RC_TRACE_WITH_THREAD(0x00004000, _thread, ("cp-cache::check_no_old_or_obsolete_entries failure" " -- OLD or OBSOLETE method found -- class: %s", ik->signature_name())); @@ -3548,19 +3542,21 @@ } no_old_methods = false; } - - if (!no_old_methods) { - if (RC_TRACE_ENABLED(0x00004000)) { - dump_methods(); - } else { - tty->print_cr("INFO: use the '-XX:TraceRedefineClasses=16384' option " - "to see more info about the following guarantee() failure."); - } - guarantee(false, "OLD and/or OBSOLETE method(s) found"); + } + + // print and fail guarantee if old methods are found. + if (!no_old_methods) { + if (RC_TRACE_ENABLED(0x00004000)) { + dump_methods(); + } else { + tty->print_cr("INFO: use the '-XX:TraceRedefineClasses=16384' option " + "to see more info about the following guarantee() failure."); } + guarantee(false, "OLD and/or OBSOLETE method(s) found"); } } + void VM_RedefineClasses::dump_methods() { int j; RC_TRACE(0x00004000, ("_old_methods --")); diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/prims/jvmtiRedefineClasses.hpp --- a/src/share/vm/prims/jvmtiRedefineClasses.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/prims/jvmtiRedefineClasses.hpp Thu May 23 12:44:18 2013 +0100 @@ -87,7 +87,7 @@ // parts of the_class // - adjusting constant pool caches and vtables in other classes // that refer to methods in the_class. These adjustments use the -// SystemDictionary::classes_do() facility which only allows +// ClassLoaderDataGraph::classes_do() facility which only allows // a helper method to be specified. The interesting parameters // that we would like to pass to the helper method are saved in // static global fields in the VM operation. @@ -333,8 +333,8 @@ class VM_RedefineClasses: public VM_Operation { private: - // These static fields are needed by SystemDictionary::classes_do() - // facility and the adjust_cpool_cache_and_vtable() helper: + // These static fields are needed by ClassLoaderDataGraph::classes_do() + // facility and the AdjustCpoolCacheAndVtable helper: static Array* _old_methods; static Array* _new_methods; static Method** _matching_old_methods; @@ -408,13 +408,6 @@ int * emcp_method_count_p); void transfer_old_native_function_registrations(instanceKlassHandle the_class); - // Unevolving classes may point to methods of the_class directly - // from their constant pool caches, itables, and/or vtables. We - // use the SystemDictionary::classes_do() facility and this helper - // to fix up these pointers. - static void adjust_cpool_cache_and_vtable(Klass* k_oop, ClassLoaderData* initiating_loader, TRAPS); - static void adjust_array_vtable(Klass* k_oop); - // Install the redefinition of a class void redefine_single_class(jclass the_jclass, Klass* scratch_class_oop, TRAPS); @@ -480,10 +473,27 @@ void flush_dependent_code(instanceKlassHandle k_h, TRAPS); - static void check_class(Klass* k_oop, ClassLoaderData* initiating_loader, - TRAPS); static void dump_methods(); + // Check that there are no old or obsolete methods + class CheckClass : public KlassClosure { + Thread* _thread; + public: + CheckClass(Thread* t) : _thread(t) {} + void do_klass(Klass* k); + }; + + // Unevolving classes may point to methods of the_class directly + // from their constant pool caches, itables, and/or vtables. We + // use the ClassLoaderDataGraph::classes_do() facility and this helper + // to fix up these pointers. + class AdjustCpoolCacheAndVtable : public KlassClosure { + Thread* _thread; + public: + AdjustCpoolCacheAndVtable(Thread* t) : _thread(t) {} + void do_klass(Klass* k); + }; + public: VM_RedefineClasses(jint class_count, const jvmtiClassDefinition *class_defs, diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/prims/jvmtiTagMap.cpp --- a/src/share/vm/prims/jvmtiTagMap.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/prims/jvmtiTagMap.cpp Thu May 23 12:44:18 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, 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 @@ -2857,7 +2857,7 @@ // references from the constant pool { - ConstantPool* const pool = ik->constants(); + ConstantPool* pool = ik->constants(); for (int i = 1; i < pool->length(); i++) { constantTag tag = pool->tag_at(i).value(); if (tag.is_string() || tag.is_klass()) { diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/prims/methodHandles.cpp --- a/src/share/vm/prims/methodHandles.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/prims/methodHandles.cpp Thu May 23 12:44:18 2013 +0100 @@ -193,19 +193,15 @@ flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT); } else if (mods.is_static()) { flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT); - // Get vindex from itable if method holder is an interface. - if (m->method_holder()->is_interface()) { - vmindex = klassItable::compute_itable_index(m); - } } else if (receiver_limit != mklass && !receiver_limit->is_subtype_of(mklass)) { return NULL; // bad receiver limit - } else if (receiver_limit->is_interface() && + } else if (do_dispatch && receiver_limit->is_interface() && mklass->is_interface()) { flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT); receiver_limit = mklass; // ignore passed-in limit; interfaces are interconvertible vmindex = klassItable::compute_itable_index(m); - } else if (mklass != receiver_limit && mklass->is_interface()) { + } else if (do_dispatch && mklass != receiver_limit && mklass->is_interface()) { flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT); // it is a miranda method, so m->vtable_index is not what we want ResourceMark rm; @@ -250,10 +246,25 @@ } methodHandle m = info.resolved_method(); KlassHandle defc = info.resolved_klass(); - int vmindex = -1; + int vmindex = Method::invalid_vtable_index; if (defc->is_interface() && m->method_holder()->is_interface()) { - // LinkResolver does not report itable indexes! (fix this?) - vmindex = klassItable::compute_itable_index(m()); + // static interface methods do not reference vtable or itable + if (m->is_static()) { + vmindex = Method::nonvirtual_vtable_index; + } + // interface methods invoked via invokespecial also + // do not reference vtable or itable. + int ref_kind = ((java_lang_invoke_MemberName::flags(mname()) >> + REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK); + if (ref_kind == JVM_REF_invokeSpecial) { + vmindex = Method::nonvirtual_vtable_index; + } + // If neither m is static nor ref_kind is invokespecial, + // set it to itable index. + if (vmindex == Method::invalid_vtable_index) { + // LinkResolver does not report itable indexes! (fix this?) + vmindex = klassItable::compute_itable_index(m()); + } } else if (m->can_be_statically_bound()) { // LinkResolver reports vtable index even for final methods! vmindex = Method::nonvirtual_vtable_index; @@ -665,11 +676,9 @@ case IS_METHOD: { CallInfo result; - bool do_dispatch = true; // default, neutral setting { assert(!HAS_PENDING_EXCEPTION, ""); if (ref_kind == JVM_REF_invokeStatic) { - //do_dispatch = false; // no need, since statics are never dispatched LinkResolver::resolve_static_call(result, defc, name, type, KlassHandle(), false, false, THREAD); } else if (ref_kind == JVM_REF_invokeInterface) { @@ -680,7 +689,6 @@ LinkResolver::resolve_handle_call(result, defc, name, type, KlassHandle(), THREAD); } else if (ref_kind == JVM_REF_invokeSpecial) { - do_dispatch = false; // force non-virtual linkage LinkResolver::resolve_special_call(result, defc, name, type, KlassHandle(), false, THREAD); } else if (ref_kind == JVM_REF_invokeVirtual) { @@ -1298,6 +1306,28 @@ } 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 @@ -1317,7 +1347,7 @@ #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)}, @@ -1335,8 +1365,28 @@ {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."); @@ -1354,16 +1404,14 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/prims/nativeLookup.cpp Thu May 23 12:44:18 2013 +0100 @@ -383,10 +383,7 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/runtime/arguments.cpp Thu May 23 12:44:18 2013 +0100 @@ -1089,6 +1089,10 @@ 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 @@ // 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ -2100,6 +2197,26 @@ #endif } + // Need to limit the extent of the padding to reasonable size. + // 8K is well beyond the reasonable HW cache line size, even with the + // aggressive prefetching, while still leaving the room for segregating + // among the distinct pages. + if (ContendedPaddingWidth < 0 || ContendedPaddingWidth > 8192) { + jio_fprintf(defaultStream::error_stream(), + "ContendedPaddingWidth=" INTX_FORMAT " must be the between %d and %d\n", + ContendedPaddingWidth, 0, 8192); + status = false; + } + + // Need to enforce the padding not to break the existing field alignments. + // It is sufficient to check against the largest type size. + if ((ContendedPaddingWidth % BytesPerLong) != 0) { + jio_fprintf(defaultStream::error_stream(), + "ContendedPaddingWidth=" INTX_FORMAT " must be the multiple of %d\n", + ContendedPaddingWidth, BytesPerLong); + status = false; + } + return status; } @@ -2965,6 +3082,11 @@ 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) && @@ -3097,36 +3219,27 @@ } void Arguments::set_shared_spaces_flags() { - const bool must_share = DumpSharedSpaces || RequireSharedSpaces; - const bool might_share = must_share || UseSharedSpaces; - - // CompressedOops cannot be used with CDS. The offsets of oopmaps and - // static fields are incorrect in the archive. With some more clever - // initialization, this restriction can probably be lifted. - // ??? UseLargePages might be okay now - const bool cannot_share = UseCompressedOops || - (UseLargePages && FLAG_IS_CMDLINE(UseLargePages)); - if (cannot_share) { - if (must_share) { - warning("disabling large pages %s" - "because of %s", "" LP64_ONLY("and compressed oops "), - DumpSharedSpaces ? "-Xshare:dump" : "-Xshare:on"); - FLAG_SET_CMDLINE(bool, UseLargePages, false); - LP64_ONLY(FLAG_SET_CMDLINE(bool, UseCompressedOops, false)); - LP64_ONLY(FLAG_SET_CMDLINE(bool, UseCompressedKlassPointers, false)); - } else { - // Prefer compressed oops and large pages to class data sharing - if (UseSharedSpaces && Verbose) { - warning("turning off use of shared archive because of large pages%s", - "" LP64_ONLY(" and/or compressed oops")); +#ifdef _LP64 + const bool must_share = DumpSharedSpaces || RequireSharedSpaces; + + // CompressedOops cannot be used with CDS. The offsets of oopmaps and + // static fields are incorrect in the archive. With some more clever + // initialization, this restriction can probably be lifted. + if (UseCompressedOops) { + if (must_share) { + warning("disabling compressed oops because of %s", + DumpSharedSpaces ? "-Xshare:dump" : "-Xshare:on"); + FLAG_SET_CMDLINE(bool, UseCompressedOops, false); + FLAG_SET_CMDLINE(bool, UseCompressedKlassPointers, false); + } else { + // Prefer compressed oops to class data sharing + if (UseSharedSpaces && Verbose) { + warning("turning off use of shared archive because of compressed oops"); + } + no_shared_spaces(); } - no_shared_spaces(); } - } else if (UseLargePages && might_share) { - // Disable large pages to allow shared spaces. This is sub-optimal, since - // there may not even be a shared archive to use. - FLAG_SET_DEFAULT(UseLargePages, false); - } +#endif if (DumpSharedSpaces) { if (RequireSharedSpaces) { @@ -3171,25 +3284,37 @@ } #endif // INCLUDE_ALL_GCS +// Sharing support +// Construct the path to the archive +static char* get_shared_archive_path() { + char *shared_archive_path; + if (SharedArchiveFile == NULL) { + char jvm_path[JVM_MAXPATHLEN]; + os::jvm_path(jvm_path, sizeof(jvm_path)); + char *end = strrchr(jvm_path, *os::file_separator()); + if (end != NULL) *end = '\0'; + size_t jvm_path_len = strlen(jvm_path); + size_t file_sep_len = strlen(os::file_separator()); + shared_archive_path = NEW_C_HEAP_ARRAY(char, jvm_path_len + + file_sep_len + 20, mtInternal); + if (shared_archive_path != NULL) { + strncpy(shared_archive_path, jvm_path, jvm_path_len + 1); + strncat(shared_archive_path, os::file_separator(), file_sep_len); + strncat(shared_archive_path, "classes.jsa", 11); + } + } else { + shared_archive_path = NEW_C_HEAP_ARRAY(char, strlen(SharedArchiveFile) + 1, mtInternal); + if (shared_archive_path != NULL) { + strncpy(shared_archive_path, SharedArchiveFile, strlen(SharedArchiveFile) + 1); + } + } + return shared_archive_path; +} + // Parse entry point called from JNI_CreateJavaVM jint Arguments::parse(const JavaVMInitArgs* args) { - // Sharing support - // Construct the path to the archive - char jvm_path[JVM_MAXPATHLEN]; - os::jvm_path(jvm_path, sizeof(jvm_path)); - char *end = strrchr(jvm_path, *os::file_separator()); - if (end != NULL) *end = '\0'; - char *shared_archive_path = NEW_C_HEAP_ARRAY(char, strlen(jvm_path) + - strlen(os::file_separator()) + 20, mtInternal); - if (shared_archive_path == NULL) return JNI_ENOMEM; - strcpy(shared_archive_path, jvm_path); - strcat(shared_archive_path, os::file_separator()); - strcat(shared_archive_path, "classes"); - strcat(shared_archive_path, ".jsa"); - SharedArchivePath = shared_archive_path; - // Remaining part of option string const char* tail; @@ -3280,6 +3405,12 @@ return result; } + // Call get_shared_archive_path() here, after possible SharedArchiveFile option got parsed. + SharedArchivePath = get_shared_archive_path(); + if (SharedArchivePath == NULL) { + return JNI_ENOMEM; + } + // Delay warning until here so that we've had a chance to process // the -XX:-PrintWarnings flag if (needs_hotspotrc_warning) { diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/runtime/globals.hpp Thu May 23 12:44:18 2013 +0100 @@ -286,12 +286,12 @@ }; -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 @@ 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 @@ 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 @@ 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, \ @@ -1159,9 +1159,6 @@ product(bool, CompactFields, true, \ "Allocate nonstatic fields in gaps between previous fields") \ \ - notproduct(bool, PrintCompactFieldsSavings, false, \ - "Print how many words were saved with CompactFields") \ - \ notproduct(bool, PrintFieldLayout, false, \ "Print field layout for each class") \ \ @@ -1432,16 +1429,17 @@ 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" \ @@ -1519,7 +1517,7 @@ 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") \ \ @@ -1837,7 +1835,7 @@ 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") \ \ @@ -1876,7 +1874,7 @@ 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, \ @@ -2020,7 +2018,7 @@ "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") \ @@ -3049,7 +3047,7 @@ 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") \ \ @@ -3077,7 +3075,7 @@ "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)") \ \ @@ -3680,6 +3678,9 @@ product(bool , AllowNonVirtualCalls, false, \ "Obey the ACC_SUPER flag and allow invokenonvirtual calls") \ \ + diagnostic(ccstr, SharedArchiveFile, NULL, \ + "Override the default location of the CDS archive file") \ + \ experimental(uintx, ArrayAllocatorMallocLimit, \ SOLARIS_ONLY(64*K) NOT_SOLARIS(max_uintx), \ "Allocation less than this value will be allocated " \ diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/runtime/handles.cpp --- a/src/share/vm/runtime/handles.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/runtime/handles.cpp Thu May 23 12:44:18 2013 +0100 @@ -179,6 +179,22 @@ _thread->set_last_handle_mark(previous_handle_mark()); } +void* HandleMark::operator new(size_t size) { + return AllocateHeap(size, mtThread); +} + +void* HandleMark::operator new [] (size_t size) { + return AllocateHeap(size, mtThread); +} + +void HandleMark::operator delete(void* p) { + FreeHeap(p, mtThread); +} + +void HandleMark::operator delete[](void* p) { + FreeHeap(p, mtThread); +} + #ifdef ASSERT NoHandleMark::NoHandleMark() { diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/runtime/handles.hpp --- a/src/share/vm/runtime/handles.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/runtime/handles.hpp Thu May 23 12:44:18 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -281,7 +281,7 @@ // across the HandleMark boundary. // The base class of HandleMark should have been StackObj but we also heap allocate -// a HandleMark when a thread is created. +// a HandleMark when a thread is created. The operator new is for this special case. class HandleMark { private: @@ -308,6 +308,11 @@ void push(); // called in the destructor of HandleMarkCleaner void pop_and_restore(); + // overloaded operators + void* operator new(size_t size); + void* operator new [](size_t size); + void operator delete(void* p); + void operator delete[](void* p); }; //------------------------------------------------------------------------------------------------------------------------ diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/runtime/objectMonitor.hpp --- a/src/share/vm/runtime/objectMonitor.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/runtime/objectMonitor.hpp Thu May 23 12:44:18 2013 +0100 @@ -303,6 +303,18 @@ public: static int Knob_Verbose; static int Knob_SpinLimit; + void* operator new (size_t size) { + return AllocateHeap(size, mtInternal); + } + void* operator new[] (size_t size) { + return operator new (size); + } + void operator delete(void* p) { + FreeHeap(p, mtInternal); + } + void operator delete[] (void *p) { + operator delete(p); + } }; #undef TEVENT diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/runtime/reflectionUtils.hpp --- a/src/share/vm/runtime/reflectionUtils.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/runtime/reflectionUtils.hpp Thu May 23 12:44:18 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -136,10 +136,10 @@ } }; -class FilteredField { +class FilteredField : public CHeapObj { private: Klass* _klass; - int _field_offset; + int _field_offset; public: FilteredField(Klass* klass, int field_offset) { diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/runtime/sharedRuntime.cpp Thu May 23 12:44:18 2013 +0100 @@ -883,15 +883,23 @@ } -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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 src/share/vm/runtime/unhandledOops.hpp --- a/src/share/vm/runtime/unhandledOops.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/runtime/unhandledOops.hpp Thu May 23 12:44:18 2013 +0100 @@ -48,7 +48,7 @@ class oop; class Thread; -class UnhandledOopEntry { +class UnhandledOopEntry : public CHeapObj { friend class UnhandledOops; private: oop* _oop_ptr; @@ -62,7 +62,7 @@ }; -class UnhandledOops { +class UnhandledOops : public CHeapObj { friend class Thread; private: Thread* _thread; diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/runtime/vmStructs.cpp Thu May 23 12:44:18 2013 +0100 @@ -1057,6 +1057,7 @@ 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*) \ @@ -3119,15 +3120,15 @@ // Search for the base type by peeling off const and * size_t len = strlen(typeName); if (typeName[len-1] == '*') { - char * s = new char[len]; + char * s = NEW_C_HEAP_ARRAY(char, len, mtInternal); strncpy(s, typeName, len - 1); s[len-1] = '\0'; // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName); if (recursiveFindType(origtypes, s, true) == 1) { - delete [] s; + FREE_C_HEAP_ARRAY(char, s, mtInternal); return 1; } - delete [] s; + FREE_C_HEAP_ARRAY(char, s, mtInternal); } const char* start = NULL; if (strstr(typeName, "GrowableArray<") == typeName) { @@ -3138,15 +3139,15 @@ if (start != NULL) { const char * end = strrchr(typeName, '>'); int len = end - start + 1; - char * s = new char[len]; + char * s = NEW_C_HEAP_ARRAY(char, len, mtInternal); strncpy(s, start, len - 1); s[len-1] = '\0'; // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName); if (recursiveFindType(origtypes, s, true) == 1) { - delete [] s; + FREE_C_HEAP_ARRAY(char, s, mtInternal); return 1; } - delete [] s; + FREE_C_HEAP_ARRAY(char, s, mtInternal); } if (strstr(typeName, "const ") == typeName) { const char * s = typeName + strlen("const "); diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/utilities/events.hpp --- a/src/share/vm/utilities/events.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/utilities/events.hpp Thu May 23 12:44:18 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -69,7 +69,7 @@ // semantics aren't appropriate. The name is used as the label of the // log when it is dumped during a crash. template class EventLogBase : public EventLog { - template class EventRecord { + template class EventRecord : public CHeapObj { public: double timestamp; Thread* thread; diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/utilities/quickSort.cpp --- a/src/share/vm/utilities/quickSort.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/utilities/quickSort.cpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ -30,8 +30,11 @@ #include "runtime/os.hpp" #include "utilities/quickSort.hpp" +#include "memory/allocation.hpp" +#include "memory/allocation.inline.hpp" #include +#ifdef ASSERT static int test_comparator(int a, int b) { if (a == b) { return 0; @@ -41,6 +44,7 @@ } return 1; } +#endif // ASSERT static int test_even_odd_comparator(int a, int b) { bool a_is_odd = (a % 2) == 1; @@ -187,8 +191,8 @@ // test sorting random arrays for (int i = 0; i < 1000; i++) { int length = os::random() % 100; - int* test_array = new int[length]; - int* expected_array = new int[length]; + int* test_array = NEW_C_HEAP_ARRAY(int, length, mtInternal); + int* expected_array = NEW_C_HEAP_ARRAY(int, length, mtInternal); for (int j = 0; j < length; j++) { // Choose random values, but get a chance of getting duplicates test_array[j] = os::random() % (length * 2); @@ -210,8 +214,8 @@ sort(test_array, length, test_even_odd_comparator, true); assert(compare_arrays(test_array, expected_array, length), "Sorting already sorted array changed order of elements - not idempotent"); - delete[] test_array; - delete[] expected_array; + FREE_C_HEAP_ARRAY(int, test_array, mtInternal); + FREE_C_HEAP_ARRAY(int, expected_array, mtInternal); } } diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/utilities/workgroup.cpp --- a/src/share/vm/utilities/workgroup.cpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/utilities/workgroup.cpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ -529,7 +529,7 @@ FreeIdSet::FreeIdSet(int sz, Monitor* mon) : _sz(sz), _mon(mon), _hd(0), _waiters(0), _index(-1), _claimed(0) { - _ids = new int[sz]; + _ids = NEW_C_HEAP_ARRAY(int, sz, mtInternal); for (int i = 0; i < sz; i++) _ids[i] = i+1; _ids[sz-1] = end_of_list; // end of list. if (_stat_init) { @@ -549,6 +549,7 @@ FreeIdSet::~FreeIdSet() { _sets[_index] = NULL; + FREE_C_HEAP_ARRAY(int, _ids, mtInternal); } void FreeIdSet::set_safepoint(bool b) { diff -r cb92413c6934 -r ce9ecec70f99 src/share/vm/utilities/workgroup.hpp --- a/src/share/vm/utilities/workgroup.hpp Thu May 16 11:44:33 2013 +0100 +++ b/src/share/vm/utilities/workgroup.hpp Thu May 23 12:44:18 2013 +0100 @@ -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 @@ -494,7 +494,7 @@ }; // Represents a set of free small integer ids. -class FreeIdSet { +class FreeIdSet : public CHeapObj { enum { end_of_list = -1, claimed = -2 diff -r cb92413c6934 -r ce9ecec70f99 test/compiler/6934604/TestByteBoxing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6934604/TestByteBoxing.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/compiler/6934604/TestDoubleBoxing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6934604/TestDoubleBoxing.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/compiler/6934604/TestFloatBoxing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6934604/TestFloatBoxing.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/compiler/6934604/TestIntBoxing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6934604/TestIntBoxing.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/compiler/6934604/TestLongBoxing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6934604/TestLongBoxing.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/compiler/6934604/TestShortBoxing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6934604/TestShortBoxing.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/compiler/8009761/Test8009761.java --- a/test/compiler/8009761/Test8009761.java Thu May 16 11:44:33 2013 +0100 +++ b/test/compiler/8009761/Test8009761.java Thu May 23 12:44:18 2013 +0100 @@ -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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 test/compiler/ciReplay/TestSA.sh --- a/test/compiler/ciReplay/TestSA.sh Thu May 16 11:44:33 2013 +0100 +++ b/test/compiler/ciReplay/TestSA.sh Thu May 23 12:44:18 2013 +0100 @@ -77,10 +77,11 @@ "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 -r cb92413c6934 -r ce9ecec70f99 test/compiler/ciReplay/common.sh --- a/test/compiler/ciReplay/common.sh Thu May 16 11:44:33 2013 +0100 +++ b/test/compiler/ciReplay/common.sh Thu May 23 12:44:18 2013 +0100 @@ -182,8 +182,11 @@ # 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 @@ 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 -r cb92413c6934 -r ce9ecec70f99 test/gc/arguments/TestCMSHeapSizeFlags.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/arguments/TestCMSHeapSizeFlags.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/gc/arguments/TestG1HeapSizeFlags.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/arguments/TestG1HeapSizeFlags.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/gc/arguments/TestInitialTenuringThreshold.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/arguments/TestInitialTenuringThreshold.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/gc/arguments/TestMaxHeapSizeTools.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/arguments/TestMaxHeapSizeTools.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/gc/arguments/TestMinInitialErgonomics.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/arguments/TestMinInitialErgonomics.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/gc/arguments/TestParallelHeapSizeFlags.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/arguments/TestParallelHeapSizeFlags.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/gc/arguments/TestSerialHeapSizeFlags.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/arguments/TestSerialHeapSizeFlags.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/gc/g1/TestPrintGCDetails.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/g1/TestPrintGCDetails.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/gc/g1/TestPrintRegionRememberedSetInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/g1/TestPrintRegionRememberedSetInfo.java Thu May 23 12:44:18 2013 +0100 @@ -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 -r cb92413c6934 -r ce9ecec70f99 test/runtime/RedefineObject/Agent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/RedefineObject/Agent.java Thu May 23 12:44:18 2013 +0100 @@ -0,0 +1,61 @@ +/* + * 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.security.*; +import java.lang.instrument.*; + +public class Agent implements ClassFileTransformer { + public synchronized byte[] transform(final ClassLoader classLoader, + final String className, + Class classBeingRedefined, + ProtectionDomain protectionDomain, + byte[] classfileBuffer) { + //System.out.println("Transforming class " + className); + return classfileBuffer; + } + + public static void premain(String agentArgs, Instrumentation instrumentation) { + + Agent transformer = new Agent(); + + instrumentation.addTransformer(transformer, true); + + Class c = Object.class; + try { + instrumentation.retransformClasses(c); + } catch (Exception e) { + e.printStackTrace(); + } + + instrumentation.removeTransformer(transformer); + } + + public static void main(String[] args) { + byte[] ba = new byte[0]; + + // If it survives 1000 GC's, it's good. + for (int i = 0; i < 1000 ; i++) { + System.gc(); + ba.clone(); + } + } +} diff -r cb92413c6934 -r ce9ecec70f99 test/runtime/RedefineObject/TestRedefineObject.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/RedefineObject/TestRedefineObject.java Thu May 23 12:44:18 2013 +0100 @@ -0,0 +1,50 @@ +/* + * 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.io.PrintWriter; +import com.oracle.java.testlibrary.*; + +/* + * Test to redefine java/lang/Object and verify that it doesn't crash on vtable + * call on basic array type. + * + * @test + * @bug 8005056 + * @library /testlibrary + * @build Agent + * @run main ClassFileInstaller Agent + * @run main Test + * @run main/othervm -javaagent:agent.jar Agent + */ +public class Test { + public static void main(String[] args) throws Exception { + + PrintWriter pw = new PrintWriter("MANIFEST.MF"); + pw.println("Premain-Class: Agent"); + pw.println("Can-Retransform-Classes: true"); + pw.close(); + + ProcessBuilder pb = new ProcessBuilder(); + pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", "agent.jar", "Agent.class"}); + pb.start().waitFor(); + } +} diff -r cb92413c6934 -r ce9ecec70f99 test/runtime/SharedArchiveFile/SharedArchiveFile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/SharedArchiveFile/SharedArchiveFile.java Thu May 23 12:44:18 2013 +0100 @@ -0,0 +1,53 @@ +/* + * 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 8014138 + * @summary Testing new -XX:SharedArchiveFile= option + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class SharedArchiveFile { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:dump"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + try { + output.shouldContain("Loading classes to share"); + output.shouldHaveExitValue(0); + + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:on", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("sharing"); + output.shouldHaveExitValue(0); + + } catch (RuntimeException e) { + output.shouldContain("Unable to use shared archive"); + output.shouldHaveExitValue(1); + } + } +} diff -r cb92413c6934 -r ce9ecec70f99 test/testlibrary/ClassFileInstaller.java --- a/test/testlibrary/ClassFileInstaller.java Thu May 16 11:44:33 2013 +0100 +++ b/test/testlibrary/ClassFileInstaller.java Thu May 23 12:44:18 2013 +0100 @@ -45,7 +45,9 @@ // Create the class file's package directory Path p = Paths.get(pathName); - Files.createDirectories(p.getParent()); + if (pathName.contains("/")) { + Files.createDirectories(p.getParent()); + } // Create the class file Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING); }