diff --git a/.hgtags b/.hgtags index 0a357037091..2f2cb6c3aff 100644 --- a/.hgtags +++ b/.hgtags @@ -619,3 +619,6 @@ c7d4f2849dbfb755fc5860b362a4044ea0c9e082 jdk-15+8 4a87bb7ebfd7f6a25ec59a5982fe3607242777f8 jdk-14+35 62b5bfef8d618e08e6f3a56cf1fb0e67e89e9cc2 jdk-15+9 bc54620a3848c26cff9766e5e2a6e5ddab98ed18 jdk-14+36 +1bee69801aeea1a34261c93f35bc9de072a98704 jdk-15+10 +b2dd4028a6de4e40dda8b76109e4b5c6b294f980 jdk-15+11 +2ec0ff3042630ddbd3587e340fe0dd40391cb6c4 jdk-15+12 diff --git a/bin/idea.sh b/bin/idea.sh index 9ede324c7a5..eedd138fdde 100644 --- a/bin/idea.sh +++ b/bin/idea.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -113,6 +113,14 @@ if [ "x$SPEC" = "x" ] ; then echo "FATAL: SPEC is empty" >&2; exit 1 fi +if [ -d "$TOPLEVEL_DIR/.hg" ] ; then + VCS_TYPE="hg4idea" +fi + +if [ -d "$TOPLEVEL_DIR/.git" ] ; then + VCS_TYPE="Git" +fi + ### Replace template variables NUM_REPLACEMENTS=0 @@ -137,6 +145,7 @@ add_replacement() { } add_replacement "###MODULE_NAMES###" "$MODULE_NAMES" +add_replacement "###VCS_TYPE###" "$VCS_TYPE" SPEC_DIR=`dirname $SPEC` if [ "x$CYGPATH" = "x" ]; then add_replacement "###BUILD_DIR###" "$SPEC_DIR" diff --git a/doc/building.html b/doc/building.html index 2f59ca8775b..d34d94c2954 100644 --- a/doc/building.html +++ b/doc/building.html @@ -473,7 +473,7 @@ CC: Sun C++ 5.13 SunOS_i386 151846-10 2015/10/30
  • --with-version-string=<string> - Specify the version string this build will be identified with.
  • --with-version-<part>=<value> - A group of options, where <part> can be any of pre, opt, build, major, minor, security or patch. Use these options to modify just the corresponding part of the version string from the default, or the value provided by --with-version-string.
  • --with-jvm-variants=<variant>[,<variant>...] - Build the specified variant (or variants) of Hotspot. Valid variants are: server, client, minimal, core, zero, custom. Note that not all variants are possible to combine in a single build.
  • -
  • --with-jvm-features=<feature>[,<feature>...] - Use the specified JVM features when building Hotspot. The list of features will be enabled on top of the default list. For the custom JVM variant, this default list is empty. A complete list of available JVM features can be found using bash configure --help.
  • +
  • --enable-jvm-feature-<feature> or --disable-jvm-feature-<feature> - Include (or exclude) <feature> as a JVM feature in Hotspot. You can also specify a list of features to be enabled, separated by space or comma, as --with-jvm-features=<feature>[,<feature>...]. If you prefix <feature> with a -, it will be disabled. These options will modify the default list of features for the JVM variant(s) you are building. For the custom JVM variant, the default list is empty. A complete list of valid JVM features can be found using bash configure --help.
  • --with-target-bits=<bits> - Create a target binary suitable for running on a <bits> platform. Use this to create 32-bit output on a 64-bit build platform, instead of doing a full cross-compile. (This is known as a reduced build.)
  • On Linux, BSD and AIX, it is possible to override where Java by default searches for runtime/JNI libraries. This can be useful in situations where there is a special shared directory for system JNI libraries. This setting can in turn be overriden at runtime by setting the java.library.path property.

    diff --git a/doc/building.md b/doc/building.md index ca1634737be..a3c4ee66831 100644 --- a/doc/building.md +++ b/doc/building.md @@ -684,11 +684,14 @@ features, use `bash configure --help=short` instead.) (or variants) of Hotspot. Valid variants are: `server`, `client`, `minimal`, `core`, `zero`, `custom`. Note that not all variants are possible to combine in a single build. - * `--with-jvm-features=[,...]` - Use the specified JVM - features when building Hotspot. The list of features will be enabled on top - of the default list. For the `custom` JVM variant, this default list is - empty. A complete list of available JVM features can be found using `bash - configure --help`. + * `--enable-jvm-feature-` or `--disable-jvm-feature-` - + Include (or exclude) `` as a JVM feature in Hotspot. You can also + specify a list of features to be enabled, separated by space or comma, as + `--with-jvm-features=[,...]`. If you prefix `` + with a `-`, it will be disabled. These options will modify the default list + of features for the JVM variant(s) you are building. For the `custom` JVM + variant, the default list is empty. A complete list of valid JVM features + can be found using `bash configure --help`. * `--with-target-bits=` - Create a target binary suitable for running on a `` platform. Use this to create 32-bit output on a 64-bit build platform, instead of doing a full cross-compile. (This is known as a diff --git a/make/Bundles.gmk b/make/Bundles.gmk index 170f46a9a6c..c411bfe212b 100644 --- a/make/Bundles.gmk +++ b/make/Bundles.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -125,6 +125,13 @@ define SetupBundleFileBody && $(TAR) cf - -$(TAR_INCLUDE_PARAM) $$($1_$$d_LIST_FILE) \ $(TAR_IGNORE_EXIT_VALUE) ) \ | ( $(CD) $(SUPPORT_OUTPUTDIR)/bundles/$1/$$($1_SUBDIR) && $(TAR) xf - )$$(NEWLINE) ) + # Rename stripped pdb files + ifeq ($(call isTargetOs, windows)+$(SHIP_DEBUG_SYMBOLS), true+public) + for f in `$(FIND) $(SUPPORT_OUTPUTDIR)/bundles/$1/$$($1_SUBDIR) -name "*.stripped.pdb"`; do \ + $(ECHO) Renaming $$$${f} to $$$${f%stripped.pdb}pdb $(LOG_INFO); \ + $(MV) $$$${f} $$$${f%stripped.pdb}pdb; \ + done + endif # Unzip any zipped debuginfo files ifeq ($$($1_UNZIP_DEBUGINFO), true) for f in `$(FIND) $(SUPPORT_OUTPUTDIR)/bundles/$1/$$($1_SUBDIR) -name "*.diz"`; do \ @@ -183,7 +190,7 @@ endif ifneq ($(filter product-bundles% legacy-bundles, $(MAKECMDGOALS)), ) - SYMBOLS_EXCLUDE_PATTERN := %.debuginfo %.diz %.pdb %.map + SYMBOLS_EXCLUDE_PATTERN := %.debuginfo %.diz %.map # There may be files with spaces in the names, so use ShellFindFiles # explicitly. @@ -209,6 +216,21 @@ ifneq ($(filter product-bundles% legacy-bundles, $(MAKECMDGOALS)), ) endif endif + # Create special filter rules when dealing with debug symbols on windows + ifeq ($(call isTargetOs, windows), true) + ifeq ($(SHIP_DEBUG_SYMBOLS), ) + JDK_SYMBOLS_EXCLUDE_PATTERN := %.pdb + else + ifeq ($(SHIP_DEBUG_SYMBOLS), public) + JDK_SYMBOLS_EXCLUDE_PATTERN := \ + $(filter-out \ + %.stripped.pdb, \ + $(filter %.pdb, $(ALL_JDK_FILES)) \ + ) + endif + endif + endif + JDK_BUNDLE_FILES := \ $(filter-out \ $(JDK_SYMBOLS_EXCLUDE_PATTERN) \ @@ -218,13 +240,14 @@ ifneq ($(filter product-bundles% legacy-bundles, $(MAKECMDGOALS)), ) , \ $(ALL_JDK_FILES) \ ) + JDK_SYMBOLS_BUNDLE_FILES := \ $(filter \ $(JDK_SYMBOLS_EXCLUDE_PATTERN) \ $(SYMBOLS_EXCLUDE_PATTERN) \ , \ $(filter-out \ - $(JDK_IMAGE_HOMEDIR)/demo/% \ + $(JDK_IMAGE_HOMEDIR)/demo/% %.stripped.pdb \ , \ $(ALL_JDK_SYMBOLS_FILES) \ ) \ @@ -245,29 +268,116 @@ ifneq ($(filter product-bundles% legacy-bundles, $(MAKECMDGOALS)), ) endif endif + # Create special filter rules when dealing with debug symbols on windows + ifeq ($(call isTargetOs, windows), true) + ifeq ($(SHIP_DEBUG_SYMBOLS), ) + JRE_SYMBOLS_EXCLUDE_PATTERN := %.pdb + else + ifeq ($(SHIP_DEBUG_SYMBOLS), public) + JRE_SYMBOLS_EXCLUDE_PATTERN := \ + $(filter-out \ + %.stripped.pdb, \ + $(filter %.pdb, $(ALL_JRE_FILES)) \ + ) + endif + endif + endif + JRE_BUNDLE_FILES := $(filter-out \ $(JRE_SYMBOLS_EXCLUDE_PATTERN) \ $(SYMBOLS_EXCLUDE_PATTERN), \ $(ALL_JRE_FILES)) - $(eval $(call SetupBundleFile, BUILD_JDK_BUNDLE, \ - BUNDLE_NAME := $(JDK_BUNDLE_NAME), \ - FILES := $(JDK_BUNDLE_FILES), \ - SPECIAL_INCLUDES := $(JDK_SPECIAL_INCLUDES), \ - BASE_DIRS := $(JDK_IMAGE_DIR), \ - SUBDIR := $(JDK_BUNDLE_SUBDIR), \ - )) + # On Macosx release builds, when there is a code signing certificate available, + # the final bundle layout can be signed. + SIGN_BUNDLE := false + ifeq ($(call isTargetOs, macosx)+$(DEBUG_LEVEL), true+release) + ifneq ($(CODESIGN), ) + SIGN_BUNDLE := true + endif + endif - PRODUCT_TARGETS += $(BUILD_JDK_BUNDLE) + ifeq ($(SIGN_BUNDLE), true) + # Macosx release build and code signing available. - $(eval $(call SetupBundleFile, BUILD_JRE_BUNDLE, \ - BUNDLE_NAME := $(JRE_BUNDLE_NAME), \ - FILES := $(JRE_BUNDLE_FILES), \ - BASE_DIRS := $(JRE_IMAGE_DIR), \ - SUBDIR := $(JRE_BUNDLE_SUBDIR), \ - )) + ################################################################################ + # JDK bundle + $(eval $(call SetupCopyFiles, CREATE_JDK_BUNDLE_DIR_SIGNED, \ + SRC := $(JDK_IMAGE_DIR), \ + FILES := $(JDK_BUNDLE_FILES), \ + DEST := $(JDK_MACOSX_BUNDLE_DIR_SIGNED), \ + )) - LEGACY_TARGETS += $(BUILD_JRE_BUNDLE) + JDK_SIGNED_CODE_RESOURCES := \ + $(JDK_MACOSX_BUNDLE_DIR_SIGNED)/$(JDK_MACOSX_CONTENTS_SUBDIR)/_CodeSignature/CodeResources + + $(JDK_SIGNED_CODE_RESOURCES): $(CREATE_JDK_BUNDLE_DIR_SIGNED) + $(call LogWarn, Signing $(JDK_BUNDLE_NAME)) + $(CODESIGN) -s "$(MACOSX_CODESIGN_IDENTITY)" \ + --timestamp --options runtime --deep --force \ + $(JDK_MACOSX_BUNDLE_DIR_SIGNED)/$(JDK_MACOSX_BUNDLE_TOP_DIR) $(LOG_DEBUG) + $(TOUCH) $@ + + $(eval $(call SetupBundleFile, BUILD_JDK_BUNDLE, \ + BUNDLE_NAME := $(JDK_BUNDLE_NAME), \ + FILES := \ + $(CREATE_JDK_BUNDLE_DIR_SIGNED) \ + $(JDK_SIGNED_CODE_RESOURCES), \ + BASE_DIRS := $(JDK_MACOSX_BUNDLE_DIR_SIGNED), \ + SUBDIR := $(JDK_BUNDLE_SUBDIR), \ + )) + + PRODUCT_TARGETS += $(BUILD_JDK_BUNDLE) + + ################################################################################ + # JRE bundle + $(eval $(call SetupCopyFiles, CREATE_JRE_BUNDLE_DIR_SIGNED, \ + SRC := $(JRE_IMAGE_DIR), \ + FILES := $(JRE_BUNDLE_FILES), \ + DEST := $(JRE_MACOSX_BUNDLE_DIR_SIGNED), \ + )) + + JRE_SIGNED_CODE_RESOURCES := \ + $(JRE_MACOSX_BUNDLE_DIR_SIGNED)/$(JRE_MACOSX_CONTENTS_SUBDIR)/_CodeSignature/CodeResources + + $(JRE_SIGNED_CODE_RESOURCES): $(CREATE_JRE_BUNDLE_DIR_SIGNED) + $(call LogWarn, Signing $(JRE_BUNDLE_NAME)) + $(CODESIGN) -s "$(MACOSX_CODESIGN_IDENTITY)" \ + --timestamp --options runtime --deep --force \ + $(JRE_MACOSX_BUNDLE_DIR_SIGNED)/$(JRE_MACOSX_BUNDLE_TOP_DIR) $(LOG_DEBUG) + $(TOUCH) $@ + + $(eval $(call SetupBundleFile, BUILD_JRE_BUNDLE, \ + BUNDLE_NAME := $(JRE_BUNDLE_NAME), \ + FILES := \ + $(CREATE_JRE_BUNDLE_DIR_SIGNED) \ + $(JRE_SIGNED_CODE_RESOURCES), \ + BASE_DIRS := $(JRE_MACOSX_BUNDLE_DIR_SIGNED), \ + SUBDIR := $(JRE_BUNDLE_SUBDIR), \ + )) + + LEGACY_TARGETS += $(BUILD_JRE_BUNDLE) + else + # Not a Macosx release build or code signing not available. + $(eval $(call SetupBundleFile, BUILD_JDK_BUNDLE, \ + BUNDLE_NAME := $(JDK_BUNDLE_NAME), \ + FILES := $(JDK_BUNDLE_FILES), \ + SPECIAL_INCLUDES := $(JDK_SPECIAL_INCLUDES), \ + BASE_DIRS := $(JDK_IMAGE_DIR), \ + SUBDIR := $(JDK_BUNDLE_SUBDIR), \ + )) + + PRODUCT_TARGETS += $(BUILD_JDK_BUNDLE) + + $(eval $(call SetupBundleFile, BUILD_JRE_BUNDLE, \ + BUNDLE_NAME := $(JRE_BUNDLE_NAME), \ + FILES := $(JRE_BUNDLE_FILES), \ + BASE_DIRS := $(JRE_IMAGE_DIR), \ + SUBDIR := $(JRE_BUNDLE_SUBDIR), \ + )) + + LEGACY_TARGETS += $(BUILD_JRE_BUNDLE) + endif ifeq ($(COPY_DEBUG_SYMBOLS), true) $(eval $(call SetupBundleFile, BUILD_JDK_SYMBOLS_BUNDLE, \ diff --git a/make/CompileToolsJdk.gmk b/make/CompileToolsJdk.gmk index bbb84648fd8..abde9a2a87a 100644 --- a/make/CompileToolsJdk.gmk +++ b/make/CompileToolsJdk.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,6 @@ $(eval $(call IncludeCustomExtension, CompileTools.gmk)) # Use += to be able to add to this from a custom extension BUILD_TOOLS_SRC_DIRS += \ $(TOPDIR)/make/jdk/src/classes \ - $(BUILDTOOLS_OUTPUTDIR)/interim_cldrconverter_classes \ $(BUILDTOOLS_OUTPUTDIR)/interim_tzdb_classes \ # diff --git a/make/CreateJmods.gmk b/make/CreateJmods.gmk index 8c43f5e6410..59eb16ad471 100644 --- a/make/CreateJmods.gmk +++ b/make/CreateJmods.gmk @@ -1,4 +1,5 @@ -# Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. +# +# Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -58,12 +59,58 @@ $(call FillFindCache, \ ) ifneq ($(LIBS_DIR), ) - JMOD_FLAGS += --libs $(LIBS_DIR) DEPS += $(call FindFiles, $(LIBS_DIR)) + ifeq ($(call isTargetOs, windows)+$(SHIP_DEBUG_SYMBOLS), true+public) + # For public debug symbols on Windows, we have to use stripped pdbs and rename them + rename_stripped = $(patsubst %.stripped.pdb,%.pdb,$1) + LIBS_DIR_FILTERED := $(subst modules_libs,modules_libs_filtered, $(LIBS_DIR)) + FILES_LIBS := $(filter-out %.pdb, $(call FindFiles, $(LIBS_DIR))) \ + $(filter %.stripped.pdb, $(call FindFiles, $(LIBS_DIR))) + $(eval $(call SetupCopyFiles, COPY_FILTERED_LIBS, \ + SRC := $(LIBS_DIR), \ + DEST := $(LIBS_DIR_FILTERED), \ + FILES := $(FILES_LIBS), \ + NAME_MACRO := rename_stripped, \ + )) + DEPS += $(COPY_FILTERED_LIBS) + JMOD_FLAGS += --libs $(LIBS_DIR_FILTERED) + else + JMOD_FLAGS += --libs $(LIBS_DIR) + endif endif ifneq ($(CMDS_DIR), ) - JMOD_FLAGS += --cmds $(CMDS_DIR) DEPS += $(call FindFiles, $(CMDS_DIR)) + ifeq ($(call isTargetOs, windows)+$(SHIP_DEBUG_SYMBOLS), true+public) + # For public debug symbols on Windows, we have to use stripped pdbs, rename them + # and filter out a few launcher pdbs where there's a lib that goes by the same name + rename_stripped = $(patsubst %.stripped.pdb,%.pdb,$1) + CMDS_DIR_FILTERED := $(subst modules_cmds,modules_cmds_filtered, $(CMDS_DIR)) + FILES_CMDS := $(filter-out %.pdb, $(call FindFiles, $(CMDS_DIR))) \ + $(filter-out %jimage.stripped.pdb %jpackage.stripped.pdb %java.stripped.pdb, \ + $(filter %.stripped.pdb, $(call FindFiles, $(CMDS_DIR)))) + $(eval $(call SetupCopyFiles, COPY_FILTERED_CMDS, \ + SRC := $(CMDS_DIR), \ + DEST := $(CMDS_DIR_FILTERED), \ + FILES := $(FILES_CMDS), \ + NAME_MACRO := rename_stripped, \ + )) + DEPS += $(COPY_FILTERED_CMDS) + JMOD_FLAGS += --cmds $(CMDS_DIR_FILTERED) + else ifeq ($(call isTargetOs, windows)+$(SHIP_DEBUG_SYMBOLS), true+full) + # For full debug symbols on Windows, we have to filter out a few launcher pdbs + # where there's a lib that goes by the same name + CMDS_DIR_FILTERED := $(subst modules_cmds,modules_cmds_filtered, $(CMDS_DIR)) + $(eval $(call SetupCopyFiles, COPY_FILTERED_CMDS, \ + SRC := $(CMDS_DIR), \ + DEST := $(CMDS_DIR_FILTERED), \ + FILES := $(filter-out %jimage.pdb %jpackage.pdb %java.pdb, \ + $(call FindFiles, $(CMDS_DIR))), \ + )) + DEPS += $(COPY_FILTERED_CMDS) + JMOD_FLAGS += --cmds $(CMDS_DIR_FILTERED) + else + JMOD_FLAGS += --cmds $(CMDS_DIR) + endif endif ifneq ($(CONF_DIR), ) JMOD_FLAGS += --config $(CONF_DIR) @@ -159,7 +206,15 @@ ifeq ($(INTERIM_JMOD), true) INTERIM_MSG := interim$(SPACE) endif -JMOD_FLAGS += --exclude '**{_the.*,_*.marker,*.diz,*.debuginfo,*.dSYM/**,*.dSYM,*.pdb,*.map}' +ifeq ($(call isTargetOs, windows), true) + ifeq ($(SHIP_DEBUG_SYMBOLS), ) + JMOD_FLAGS += --exclude '**{_the.*,_*.marker,*.diz,*.pdb,*.map}' + else + JMOD_FLAGS += --exclude '**{_the.*,_*.marker,*.diz,*.map}' + endif +else + JMOD_FLAGS += --exclude '**{_the.*,_*.marker,*.diz,*.debuginfo,*.dSYM/**,*.dSYM}' +endif # Create jmods in the support dir and then move them into place to keep the # module path in $(IMAGES_OUTPUTDIR)/jmods valid at all times. diff --git a/make/GenerateLinkOptData.gmk b/make/GenerateLinkOptData.gmk index 87ad6c35754..8e2e0c11711 100644 --- a/make/GenerateLinkOptData.gmk +++ b/make/GenerateLinkOptData.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -104,6 +104,17 @@ $(eval $(call SetupCopyFiles, COPY_CLASSLIST, \ TARGETS += $(COPY_CLASSLIST) +# In case of shipping public debug symbols on windows, there is another temporary +# location from where jmods are compiled - need to deploy classlist there, too. +ifeq ($(call isTargetOs, windows)+$(SHIP_DEBUG_SYMBOLS), true+public) + $(eval $(call SetupCopyFiles, COPY_CLASSLIST_TO_FILTERED, \ + FILES := $(CLASSLIST_FILE), \ + DEST := $(SUPPORT_OUTPUTDIR)/modules_libs_filtered/java.base, \ + )) + + TARGETS += $(COPY_CLASSLIST_TO_FILTERED) +endif + # Copy the default_jli_trace.txt file into jdk.jlink $(eval $(call SetupCopyFiles, COPY_JLI_TRACE, \ FILES := $(JLI_TRACE_FILE), \ diff --git a/make/Help.gmk b/make/Global.gmk similarity index 95% rename from make/Help.gmk rename to make/Global.gmk index 7f6c9a4f4a6..b6eedb0bb82 100644 --- a/make/Help.gmk +++ b/make/Global.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -117,13 +117,14 @@ print-configurations: # We need a dummy rule otherwise make will complain @true -# This is not really a "help" target, but it is a global target, and those are -# all contained in this file. -run-test-prebuilt: +test-prebuilt: @( cd $(topdir) && \ $(MAKE) --no-print-directory -r -R -I make/common/ -f make/RunTestsPrebuilt.gmk \ - run-test-prebuilt CUSTOM_MAKE_DIR=$(CUSTOM_MAKE_DIR) TEST="$(TEST)" ) + test-prebuilt CUSTOM_MAKE_DIR=$(CUSTOM_MAKE_DIR) TEST="$(TEST)" ) -ALL_GLOBAL_TARGETS := help print-configurations run-test-prebuilt +# Alias for backwards compatibility +run-test-prebuilt: test-prebuilt + +ALL_GLOBAL_TARGETS := help print-configurations test-prebuilt run-test-prebuilt .PHONY: $(ALL_GLOBAL_TARGETS) diff --git a/make/Images.gmk b/make/Images.gmk index 100e35fcca9..1e038eb4aa4 100644 --- a/make/Images.gmk +++ b/make/Images.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -208,6 +208,7 @@ ifeq ($(call isTargetOs, windows), true) else LIBS_TARGET_SUBDIR := lib endif +CMDS_TARGET_SUBDIR := bin # Param 1 - dir to find debuginfo files in FindDebuginfoFiles = \ @@ -224,12 +225,15 @@ else # dirs. ifeq ($(call isTargetOs, macosx), true) $(call FillFindCache, \ - $(SUPPORT_OUTPUTDIR)/modules_cmds $(SUPPORT_OUTPUTDIR)/modules_libs) + $(SUPPORT_OUTPUTDIR)/modules_libs $(SUPPORT_OUTPUTDIR)/modules_cmds) FindDebuginfoFiles = \ $(if $(wildcard $1), $(call containing, .dSYM/, $(call FindFiles, $1))) endif endif +FILTERED_PDBS := %jimage.stripped.pdb %jpackage.stripped.pdb %java.stripped.pdb \ + %jimage.pdb %jpackage.pdb %java.pdb %jimage.map %jpackage.map %java.map + # Param 1 - either JDK or JRE SetupCopyDebuginfo = \ $(foreach m, $(ALL_$1_MODULES), \ @@ -240,6 +244,13 @@ SetupCopyDebuginfo = \ $(SUPPORT_OUTPUTDIR)/modules_libs/$m), \ )) \ $(eval $1_TARGETS += $$(COPY_$1_LIBS_DEBUGINFO_$m)) \ + $(eval $(call SetupCopyFiles, COPY_$1_CMDS_DEBUGINFO_$m, \ + SRC := $(SUPPORT_OUTPUTDIR)/modules_cmds/$m, \ + DEST := $($1_IMAGE_DIR)/$(CMDS_TARGET_SUBDIR), \ + FILES := $(filter-out $(FILTERED_PDBS), $(call FindDebuginfoFiles, \ + $(SUPPORT_OUTPUTDIR)/modules_cmds/$m)), \ + )) \ + $(eval $1_TARGETS += $$(COPY_$1_CMDS_DEBUGINFO_$m)) \ ) # No space before argument to avoid having to put $(strip ) everywhere in diff --git a/make/Init.gmk b/make/Init.gmk index d801499298b..a8ca9e0b8b0 100644 --- a/make/Init.gmk +++ b/make/Init.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ ifeq ($(HAS_SPEC),) # Here are "global" targets, i.e. targets that can be executed without having # a configuration. This will define ALL_GLOBAL_TARGETS. - include $(topdir)/make/Help.gmk + include $(topdir)/make/Global.gmk # Targets provided by Init.gmk. ALL_INIT_TARGETS := print-modules print-targets print-configuration \ diff --git a/make/Main.gmk b/make/Main.gmk index 4e26a4e840d..055910ed80a 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -75,9 +75,6 @@ interim-langtools: interim-rmic: +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f CompileInterimRmic.gmk) -interim-cldrconverter: - +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f CopyInterimCLDRConverter.gmk) - interim-tzdb: +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f CopyInterimTZDB.gmk) @@ -92,7 +89,7 @@ buildtools-hotspot: +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f CompileToolsHotspot.gmk) ALL_TARGETS += buildtools-langtools interim-langtools \ - interim-rmic interim-cldrconverter interim-tzdb buildtools-jdk buildtools-modules \ + interim-rmic interim-tzdb buildtools-jdk buildtools-modules \ buildtools-hotspot ################################################################################ @@ -677,7 +674,7 @@ else interim-langtools: $(INTERIM_LANGTOOLS_GENSRC_TARGETS) - buildtools-jdk: interim-langtools interim-cldrconverter interim-tzdb + buildtools-jdk: interim-langtools interim-tzdb buildtools-hotspot: interim-langtools diff --git a/make/RunTests.gmk b/make/RunTests.gmk index 8c718b57707..121cdc09fa0 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -1049,7 +1049,7 @@ define SetupRunSpecialTestBody else ifeq ($$($1_TEST_NAME), make) $1_TEST_COMMAND_LINE := \ ($(CD) $(TOPDIR)/test/make && $(MAKE) $(MAKE_ARGS) -f \ - TestMake.gmk $$($1_TEST_ARGS)) + TestMake.gmk $$($1_TEST_ARGS) TEST_SUPPORT_DIR="$$($1_TEST_SUPPORT_DIR)") else $$(error Invalid special test specification: $$($1_TEST_NAME)) endif diff --git a/make/RunTestsPrebuilt.gmk b/make/RunTestsPrebuilt.gmk index 58d1fca168a..213131fbf63 100644 --- a/make/RunTestsPrebuilt.gmk +++ b/make/RunTestsPrebuilt.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -336,7 +336,7 @@ SPEC := $(NEW_SPEC) default: all -run-test-prebuilt: +test-prebuilt: # Need to make sure the failure logs output dir exists since # ExecuteWithLog is called in RunTests.gmk. The PrepareFailureLogs macro # is unfortunately not available at this point. @@ -351,6 +351,6 @@ run-test-prebuilt: @cd $(TOPDIR) && $(MAKE) $(MAKE_ARGS) -f make/RunTests.gmk run-test \ TEST="$(TEST)" -all: run-test-prebuilt +all: test-prebuilt -.PHONY: default all +.PHONY: default all test-prebuilt diff --git a/make/autoconf/basic.m4 b/make/autoconf/basic.m4 new file mode 100644 index 00000000000..9536d99551f --- /dev/null +++ b/make/autoconf/basic.m4 @@ -0,0 +1,544 @@ +# +# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +m4_include([basic_tools.m4]) +m4_include([basic_windows.m4]) + +############################################################################### +AC_DEFUN_ONCE([BASIC_INIT], +[ + # Save the original command line. This is passed to us by the wrapper configure script. + AC_SUBST(CONFIGURE_COMMAND_LINE) + # AUTOCONF might be set in the environment by the user. Preserve for "make reconfigure". + AC_SUBST(AUTOCONF) + # Save the path variable before it gets changed + ORIGINAL_PATH="$PATH" + AC_SUBST(ORIGINAL_PATH) + DATE_WHEN_CONFIGURED=`date` + AC_SUBST(DATE_WHEN_CONFIGURED) + AC_MSG_NOTICE([Configuration created at $DATE_WHEN_CONFIGURED.]) +]) + +############################################################################### +# Check that there are no unprocessed overridden variables left. +# If so, they are an incorrect argument and we will exit with an error. +AC_DEFUN([BASIC_CHECK_LEFTOVER_OVERRIDDEN], +[ + if test "x$CONFIGURE_OVERRIDDEN_VARIABLES" != x; then + # Replace the separating ! with spaces before presenting for end user. + unknown_variables=${CONFIGURE_OVERRIDDEN_VARIABLES//!/ } + AC_MSG_WARN([The following variables might be unknown to configure: $unknown_variables]) + fi +]) + +############################################################################### +# Setup basic configuration paths, and platform-specific stuff related to PATHs. +AC_DEFUN_ONCE([BASIC_SETUP_PATHS], +[ + # Save the current directory this script was started from + CONFIGURE_START_DIR="$PWD" + + # We might need to rewrite ORIGINAL_PATH, if it includes "#", to quote them + # for make. We couldn't do this when we retrieved ORIGINAL_PATH, since SED + # was not available at that time. + REWRITTEN_PATH=`$ECHO "$ORIGINAL_PATH" | $SED -e 's/#/\\\\#/g'` + if test "x$REWRITTEN_PATH" != "x$ORIGINAL_PATH"; then + ORIGINAL_PATH="$REWRITTEN_PATH" + AC_MSG_NOTICE([Rewriting ORIGINAL_PATH to $REWRITTEN_PATH]) + fi + + if test "x$OPENJDK_TARGET_OS" = "xwindows"; then + PATH_SEP=";" + EXE_SUFFIX=".exe" + BASIC_CHECK_PATHS_WINDOWS + else + PATH_SEP=":" + EXE_SUFFIX="" + fi + AC_SUBST(PATH_SEP) + AC_SUBST(EXE_SUFFIX) + + # We get the top-level directory from the supporting wrappers. + AC_MSG_CHECKING([for top-level directory]) + AC_MSG_RESULT([$TOPDIR]) + AC_SUBST(TOPDIR) + AC_SUBST(CONFIGURE_START_DIR) + + # We can only call UTIL_FIXUP_PATH after BASIC_CHECK_PATHS_WINDOWS. + UTIL_FIXUP_PATH(CONFIGURE_START_DIR) + UTIL_FIXUP_PATH(TOPDIR) + + # Locate the directory of this script. + AUTOCONF_DIR=$TOPDIR/make/autoconf + + # Setup username (for use in adhoc version strings etc) + # Outer [ ] to quote m4. + [ USERNAME=`$ECHO "$USER" | $TR -d -c '[a-z][A-Z][0-9]'` ] + AC_SUBST(USERNAME) +]) + +############################################################################### +# Evaluates platform specific overrides for devkit variables. +# $1: Name of variable +AC_DEFUN([BASIC_EVAL_DEVKIT_VARIABLE], +[ + if test "x[$]$1" = x; then + eval $1="\${$1_${OPENJDK_TARGET_CPU}}" + fi +]) + +############################################################################### +AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT], +[ + AC_ARG_WITH([devkit], [AS_HELP_STRING([--with-devkit], + [use this devkit for compilers, tools and resources])]) + + if test "x$with_devkit" = xyes; then + AC_MSG_ERROR([--with-devkit must have a value]) + elif test "x$with_devkit" != x && test "x$with_devkit" != xno; then + UTIL_FIXUP_PATH([with_devkit]) + DEVKIT_ROOT="$with_devkit" + # Check for a meta data info file in the root of the devkit + if test -f "$DEVKIT_ROOT/devkit.info"; then + . $DEVKIT_ROOT/devkit.info + # This potentially sets the following: + # A descriptive name of the devkit + BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_NAME]) + # Corresponds to --with-extra-path + BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_EXTRA_PATH]) + # Corresponds to --with-toolchain-path + BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_TOOLCHAIN_PATH]) + # Corresponds to --with-sysroot + BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_SYSROOT]) + + # Identifies the Visual Studio version in the devkit + BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_VS_VERSION]) + # The Visual Studio include environment variable + BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_VS_INCLUDE]) + # The Visual Studio lib environment variable + BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_VS_LIB]) + # Corresponds to --with-msvcr-dll + BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_MSVCR_DLL]) + # Corresponds to --with-msvcp-dll + BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_MSVCP_DLL]) + # Corresponds to --with-ucrt-dll-dir + BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_UCRT_DLL_DIR]) + fi + + AC_MSG_CHECKING([for devkit]) + if test "x$DEVKIT_NAME" != x; then + AC_MSG_RESULT([$DEVKIT_NAME in $DEVKIT_ROOT]) + else + AC_MSG_RESULT([$DEVKIT_ROOT]) + fi + + UTIL_PREPEND_TO_PATH([EXTRA_PATH],$DEVKIT_EXTRA_PATH) + + # Fallback default of just /bin if DEVKIT_PATH is not defined + if test "x$DEVKIT_TOOLCHAIN_PATH" = x; then + DEVKIT_TOOLCHAIN_PATH="$DEVKIT_ROOT/bin" + fi + UTIL_PREPEND_TO_PATH([TOOLCHAIN_PATH],$DEVKIT_TOOLCHAIN_PATH) + + # If DEVKIT_SYSROOT is set, use that, otherwise try a couple of known + # places for backwards compatiblity. + if test "x$DEVKIT_SYSROOT" != x; then + SYSROOT="$DEVKIT_SYSROOT" + elif test -d "$DEVKIT_ROOT/$host_alias/libc"; then + SYSROOT="$DEVKIT_ROOT/$host_alias/libc" + elif test -d "$DEVKIT_ROOT/$host/sys-root"; then + SYSROOT="$DEVKIT_ROOT/$host/sys-root" + fi + + if test "x$DEVKIT_ROOT" != x; then + DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib" + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib64" + fi + AC_SUBST(DEVKIT_LIB_DIR) + fi + fi + + # You can force the sysroot if the sysroot encoded into the compiler tools + # is not correct. + AC_ARG_WITH(sys-root, [AS_HELP_STRING([--with-sys-root], + [alias for --with-sysroot for backwards compatability])], + [SYSROOT=$with_sys_root] + ) + + AC_ARG_WITH(sysroot, [AS_HELP_STRING([--with-sysroot], + [use this directory as sysroot])], + [SYSROOT=$with_sysroot] + ) + + AC_ARG_WITH([tools-dir], [AS_HELP_STRING([--with-tools-dir], + [alias for --with-toolchain-path for backwards compatibility])], + [UTIL_PREPEND_TO_PATH([TOOLCHAIN_PATH],$with_tools_dir)] + ) + + AC_ARG_WITH([toolchain-path], [AS_HELP_STRING([--with-toolchain-path], + [prepend these directories when searching for toolchain binaries (compilers etc)])], + [UTIL_PREPEND_TO_PATH([TOOLCHAIN_PATH],$with_toolchain_path)] + ) + + AC_ARG_WITH([extra-path], [AS_HELP_STRING([--with-extra-path], + [prepend these directories to the default path])], + [UTIL_PREPEND_TO_PATH([EXTRA_PATH],$with_extra_path)] + ) + + if test "x$OPENJDK_BUILD_OS" = "xmacosx"; then + # If a devkit has been supplied, find xcodebuild in the toolchain_path. + # If not, detect if Xcode is installed by running xcodebuild -version + # if no Xcode installed, xcodebuild exits with 1 + # if Xcode is installed, even if xcode-select is misconfigured, then it exits with 0 + if test "x$DEVKIT_ROOT" != x || /usr/bin/xcodebuild -version >/dev/null 2>&1; then + # We need to use xcodebuild in the toolchain dir provided by the user, this will + # fall back on the stub binary in /usr/bin/xcodebuild + AC_PATH_PROG([XCODEBUILD], [xcodebuild], [/usr/bin/xcodebuild], [$TOOLCHAIN_PATH]) + else + # this should result in SYSROOT being empty, unless --with-sysroot is provided + # when only the command line tools are installed there are no SDKs, so headers + # are copied into the system frameworks + XCODEBUILD= + AC_SUBST(XCODEBUILD) + fi + + AC_MSG_CHECKING([for sdk name]) + AC_ARG_WITH([sdk-name], [AS_HELP_STRING([--with-sdk-name], + [use the platform SDK of the given name. @<:@macosx@:>@])], + [SDKNAME=$with_sdk_name] + ) + AC_MSG_RESULT([$SDKNAME]) + + # if toolchain path is specified then don't rely on system headers, they may not compile + HAVE_SYSTEM_FRAMEWORK_HEADERS=0 + test -z "$TOOLCHAIN_PATH" && \ + HAVE_SYSTEM_FRAMEWORK_HEADERS=`test ! -f /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h; echo $?` + + if test -z "$SYSROOT"; then + if test -n "$XCODEBUILD"; then + # if we don't have system headers, use default SDK name (last resort) + if test -z "$SDKNAME" -a $HAVE_SYSTEM_FRAMEWORK_HEADERS -eq 0; then + SDKNAME=${SDKNAME:-macosx} + fi + + if test -n "$SDKNAME"; then + # Call xcodebuild to determine SYSROOT + SYSROOT=`"$XCODEBUILD" -sdk $SDKNAME -version | $GREP '^Path: ' | $SED 's/Path: //'` + fi + else + if test $HAVE_SYSTEM_FRAMEWORK_HEADERS -eq 0; then + AC_MSG_ERROR([No xcodebuild tool and no system framework headers found, use --with-sysroot or --with-sdk-name to provide a path to a valid SDK]) + fi + fi + else + # warn user if --with-sdk-name was also set + if test -n "$with_sdk_name"; then + AC_MSG_WARN([Both SYSROOT and --with-sdk-name are set, only SYSROOT will be used]) + fi + fi + + if test $HAVE_SYSTEM_FRAMEWORK_HEADERS -eq 0 -a -z "$SYSROOT"; then + # If no system framework headers, then SYSROOT must be set, or we won't build + AC_MSG_ERROR([Unable to determine SYSROOT and no headers found in /System/Library/Frameworks. Check Xcode configuration, --with-sysroot or --with-sdk-name arguments.]) + fi + + # Perform a basic sanity test + if test ! -f "$SYSROOT/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h"; then + if test -z "$SYSROOT"; then + AC_MSG_ERROR([Unable to find required framework headers, provide a path to an SDK via --with-sysroot or --with-sdk-name and be sure Xcode is installed properly]) + else + AC_MSG_ERROR([Invalid SDK or SYSROOT path, dependent framework headers not found]) + fi + fi + + # set SDKROOT too, Xcode tools will pick it up + SDKROOT="$SYSROOT" + AC_SUBST(SDKROOT) + fi + + # Prepend the extra path to the global path + UTIL_PREPEND_TO_PATH([PATH],$EXTRA_PATH) + + AC_MSG_CHECKING([for sysroot]) + AC_MSG_RESULT([$SYSROOT]) + AC_MSG_CHECKING([for toolchain path]) + AC_MSG_RESULT([$TOOLCHAIN_PATH]) + AC_MSG_CHECKING([for extra path]) + AC_MSG_RESULT([$EXTRA_PATH]) +]) + +############################################################################### +AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR], +[ + + AC_ARG_WITH(conf-name, [AS_HELP_STRING([--with-conf-name], + [use this as the name of the configuration @<:@generated from important configuration options@:>@])], + [ CONF_NAME=${with_conf_name} ]) + + # Test from where we are running configure, in or outside of src root. + AC_MSG_CHECKING([where to store configuration]) + if test "x$CONFIGURE_START_DIR" = "x$TOPDIR" \ + || test "x$CONFIGURE_START_DIR" = "x$CUSTOM_ROOT" \ + || test "x$CONFIGURE_START_DIR" = "x$TOPDIR/make/autoconf" \ + || test "x$CONFIGURE_START_DIR" = "x$TOPDIR/make" ; then + # We are running configure from the src root. + # Create a default ./build/target-variant-debuglevel output root. + if test "x${CONF_NAME}" = x; then + AC_MSG_RESULT([in default location]) + CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JVM_VARIANTS_WITH_AND}-${DEBUG_LEVEL}" + else + AC_MSG_RESULT([in build directory with custom name]) + fi + + if test "x$CUSTOM_ROOT" != x; then + WORKSPACE_ROOT="${CUSTOM_ROOT}" + else + WORKSPACE_ROOT="${TOPDIR}" + fi + OUTPUTDIR="${WORKSPACE_ROOT}/build/${CONF_NAME}" + $MKDIR -p "$OUTPUTDIR" + if test ! -d "$OUTPUTDIR"; then + AC_MSG_ERROR([Could not create build directory $OUTPUTDIR]) + fi + else + # We are running configure from outside of the src dir. + # Then use the current directory as output dir! + # If configuration is situated in normal build directory, just use the build + # directory name as configuration name, otherwise use the complete path. + if test "x${CONF_NAME}" = x; then + CONF_NAME=`$ECHO $CONFIGURE_START_DIR | $SED -e "s!^${TOPDIR}/build/!!"` + fi + OUTPUTDIR="$CONFIGURE_START_DIR" + AC_MSG_RESULT([in current directory]) + + # WARNING: This might be a bad thing to do. You need to be sure you want to + # have a configuration in this directory. Do some sanity checks! + + if test ! -e "$OUTPUTDIR/spec.gmk"; then + # If we have a spec.gmk, we have run here before and we are OK. Otherwise, check for + # other files + files_present=`$LS $OUTPUTDIR` + # Configure has already touched config.log and confdefs.h in the current dir when this check + # is performed. + filtered_files=`$ECHO "$files_present" \ + | $SED -e 's/config.log//g' \ + -e 's/configure.log//g' \ + -e 's/confdefs.h//g' \ + -e 's/configure-support//g' \ + -e 's/ //g' \ + | $TR -d '\n'` + if test "x$filtered_files" != x; then + AC_MSG_NOTICE([Current directory is $CONFIGURE_START_DIR.]) + AC_MSG_NOTICE([Since this is not the source root, configure will output the configuration here]) + AC_MSG_NOTICE([(as opposed to creating a configuration in /build/).]) + AC_MSG_NOTICE([However, this directory is not empty. This is not allowed, since it could]) + AC_MSG_NOTICE([seriously mess up just about everything.]) + AC_MSG_NOTICE([Try 'cd $TOPDIR' and restart configure]) + AC_MSG_NOTICE([(or create a new empty directory and cd to it).]) + AC_MSG_ERROR([Will not continue creating configuration in $CONFIGURE_START_DIR]) + fi + fi + fi + AC_MSG_CHECKING([what configuration name to use]) + AC_MSG_RESULT([$CONF_NAME]) + + UTIL_FIXUP_PATH(OUTPUTDIR) + + CONFIGURESUPPORT_OUTPUTDIR="$OUTPUTDIR/configure-support" + $MKDIR -p "$CONFIGURESUPPORT_OUTPUTDIR" + + SPEC="$OUTPUTDIR/spec.gmk" + AC_SUBST(SPEC) + AC_SUBST(CONF_NAME) + AC_SUBST(OUTPUTDIR) + AC_SUBST(WORKSPACE_ROOT) + AC_SUBST(CONFIGURESUPPORT_OUTPUTDIR) + + # The spec.gmk file contains all variables for the make system. + AC_CONFIG_FILES([$OUTPUTDIR/spec.gmk:$AUTOCONF_DIR/spec.gmk.in]) + # The bootcycle-spec.gmk file contains support for boot cycle builds. + AC_CONFIG_FILES([$OUTPUTDIR/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in]) + # The buildjdk-spec.gmk file contains support for building a buildjdk when cross compiling. + AC_CONFIG_FILES([$OUTPUTDIR/buildjdk-spec.gmk:$AUTOCONF_DIR/buildjdk-spec.gmk.in]) + # The compare.sh is used to compare the build output to other builds. + AC_CONFIG_FILES([$OUTPUTDIR/compare.sh:$AUTOCONF_DIR/compare.sh.in]) + # The generated Makefile knows where the spec.gmk is and where the source is. + # You can run make from the OUTPUTDIR, or from the top-level Makefile + # which will look for generated configurations + AC_CONFIG_FILES([$OUTPUTDIR/Makefile:$AUTOCONF_DIR/Makefile.in]) +]) + +############################################################################### +# Check if build directory is on local disk. If not possible to determine, +# we prefer to claim it's local. +# Argument 1: directory to test +# Argument 2: what to do if it is on local disk +# Argument 3: what to do otherwise (remote disk or failure) +AC_DEFUN([BASIC_CHECK_DIR_ON_LOCAL_DISK], +[ + # df -l lists only local disks; if the given directory is not found then + # a non-zero exit code is given + if test "x$DF" = x; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # msys does not have df; use Windows "net use" instead. + IS_NETWORK_DISK=`net use | grep \`pwd -W | cut -d ":" -f 1 | tr a-z A-Z\`:` + if test "x$IS_NETWORK_DISK" = x; then + $2 + else + $3 + fi + else + # No df here, say it's local + $2 + fi + else + # JDK-8189619 + # df on AIX does not understand -l. On modern AIXes it understands "-T local" which + # is the same. On older AIXes we just continue to live with a "not local build" warning. + if test "x$OPENJDK_TARGET_OS" = xaix; then + DF_LOCAL_ONLY_OPTION='-T local' + else + DF_LOCAL_ONLY_OPTION='-l' + fi + if $DF $DF_LOCAL_ONLY_OPTION $1 > /dev/null 2>&1; then + $2 + else + # In WSL, local Windows drives are considered remote by df, but we are + # required to build into a directory accessible from windows, so consider + # them local here. + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then + if $DF $1 | $GREP -q "^[[A-Z]]:"; then + $2 + else + $3 + fi + else + $3 + fi + fi + fi +]) + +############################################################################### +# Check that source files have basic read permissions set. This might +# not be the case in cygwin in certain conditions. +AC_DEFUN_ONCE([BASIC_CHECK_SRC_PERMS], +[ + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + file_to_test="$TOPDIR/LICENSE" + if test `$STAT -c '%a' "$file_to_test"` -lt 400; then + AC_MSG_ERROR([Bad file permissions on src files. This is usually caused by cloning the repositories with a non cygwin hg in a directory not created in cygwin.]) + fi + fi +]) + +############################################################################### +AC_DEFUN_ONCE([BASIC_TEST_USABILITY_ISSUES], +[ + AC_MSG_CHECKING([if build directory is on local disk]) + BASIC_CHECK_DIR_ON_LOCAL_DISK($OUTPUTDIR, + [OUTPUT_DIR_IS_LOCAL="yes"], + [OUTPUT_DIR_IS_LOCAL="no"]) + AC_MSG_RESULT($OUTPUT_DIR_IS_LOCAL) + + BASIC_CHECK_SRC_PERMS + + # Check if the user has any old-style ALT_ variables set. + FOUND_ALT_VARIABLES=`env | grep ^ALT_` + + # Before generating output files, test if they exist. If they do, this is a reconfigure. + # Since we can't properly handle the dependencies for this, warn the user about the situation + if test -e $OUTPUTDIR/spec.gmk; then + IS_RECONFIGURE=yes + else + IS_RECONFIGURE=no + fi +]) + +################################################################################ +# +# Default make target +# +AC_DEFUN_ONCE([BASIC_SETUP_DEFAULT_MAKE_TARGET], +[ + AC_ARG_WITH(default-make-target, [AS_HELP_STRING([--with-default-make-target], + [set the default make target @<:@exploded-image@:>@])]) + if test "x$with_default_make_target" = "x" \ + || test "x$with_default_make_target" = "xyes"; then + DEFAULT_MAKE_TARGET="exploded-image" + elif test "x$with_default_make_target" = "xno"; then + AC_MSG_ERROR([--without-default-make-target is not a valid option]) + else + DEFAULT_MAKE_TARGET="$with_default_make_target" + fi + + AC_SUBST(DEFAULT_MAKE_TARGET) +]) + +############################################################################### +# Setup the default value for LOG= +# +AC_DEFUN_ONCE([BASIC_SETUP_DEFAULT_LOG], +[ + AC_ARG_WITH(log, [AS_HELP_STRING([--with-log], + [[default vaue for make LOG argument [warn]]])]) + AC_MSG_CHECKING([for default LOG value]) + if test "x$with_log" = x; then + DEFAULT_LOG="" + else + # Syntax for valid LOG options is a bit too complex for it to be worth + # implementing a test for correctness in configure. Just accept it. + DEFAULT_LOG=$with_log + fi + AC_MSG_RESULT([$DEFAULT_LOG]) + AC_SUBST(DEFAULT_LOG) +]) + +############################################################################### +# Code to run after AC_OUTPUT +AC_DEFUN_ONCE([BASIC_POST_CONFIG_OUTPUT], +[ + # Try to move config.log (generated by autoconf) to the configure-support directory. + if test -e ./config.log; then + $MV -f ./config.log "$CONFIGURESUPPORT_OUTPUTDIR/config.log" 2> /dev/null + fi + + # Rotate our log file (configure.log) + if test -e "$OUTPUTDIR/configure.log.old"; then + $RM -f "$OUTPUTDIR/configure.log.old" + fi + if test -e "$OUTPUTDIR/configure.log"; then + $MV -f "$OUTPUTDIR/configure.log" "$OUTPUTDIR/configure.log.old" 2> /dev/null + fi + + # Move configure.log from current directory to the build output root + if test -e ./configure.log; then + $MV -f ./configure.log "$OUTPUTDIR/configure.log" 2> /dev/null + fi + + # Make the compare script executable + $CHMOD +x $OUTPUTDIR/compare.sh +]) diff --git a/make/autoconf/basic_tools.m4 b/make/autoconf/basic_tools.m4 new file mode 100644 index 00000000000..95577d9422b --- /dev/null +++ b/make/autoconf/basic_tools.m4 @@ -0,0 +1,475 @@ +# +# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +############################################################################### +# Setup the most fundamental tools that relies on not much else to set up, +# but is used by much of the early bootstrap code. +AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS], +[ + # Start with tools that do not need have cross compilation support + # and can be expected to be found in the default PATH. These tools are + # used by configure. + + # First are all the simple required tools. + UTIL_REQUIRE_PROGS(BASENAME, basename) + UTIL_REQUIRE_PROGS(BASH, bash) + UTIL_REQUIRE_PROGS(CAT, cat) + UTIL_REQUIRE_PROGS(CHMOD, chmod) + UTIL_REQUIRE_PROGS(CMP, cmp) + UTIL_REQUIRE_PROGS(COMM, comm) + UTIL_REQUIRE_PROGS(CP, cp) + UTIL_REQUIRE_PROGS(CUT, cut) + UTIL_REQUIRE_PROGS(DATE, date) + UTIL_REQUIRE_PROGS(DIFF, [gdiff diff]) + UTIL_REQUIRE_PROGS(DIRNAME, dirname) + UTIL_REQUIRE_PROGS(ECHO, echo) + UTIL_REQUIRE_PROGS(EXPR, expr) + UTIL_REQUIRE_PROGS(FILE, file) + UTIL_REQUIRE_PROGS(FIND, find) + UTIL_REQUIRE_PROGS(HEAD, head) + UTIL_REQUIRE_PROGS(GUNZIP, gunzip) + UTIL_REQUIRE_PROGS(GZIP, pigz gzip) + UTIL_REQUIRE_PROGS(LN, ln) + UTIL_REQUIRE_PROGS(LS, ls) + # gmkdir is known to be safe for concurrent invocations with -p flag. + UTIL_REQUIRE_PROGS(MKDIR, [gmkdir mkdir]) + UTIL_REQUIRE_PROGS(MKTEMP, mktemp) + UTIL_REQUIRE_PROGS(MV, mv) + UTIL_REQUIRE_PROGS(NAWK, [nawk gawk awk]) + UTIL_REQUIRE_PROGS(PRINTF, printf) + UTIL_REQUIRE_PROGS(READLINK, [greadlink readlink]) + UTIL_REQUIRE_PROGS(RM, rm) + UTIL_REQUIRE_PROGS(RMDIR, rmdir) + UTIL_REQUIRE_PROGS(SH, sh) + UTIL_REQUIRE_PROGS(SORT, sort) + UTIL_REQUIRE_PROGS(TAIL, tail) + UTIL_REQUIRE_PROGS(TAR, gtar tar) + UTIL_REQUIRE_PROGS(TEE, tee) + UTIL_REQUIRE_PROGS(TOUCH, touch) + UTIL_REQUIRE_PROGS(TR, tr) + UTIL_REQUIRE_PROGS(UNAME, uname) + UTIL_REQUIRE_PROGS(UNIQ, uniq) + UTIL_REQUIRE_PROGS(WC, wc) + UTIL_REQUIRE_PROGS(WHICH, which) + UTIL_REQUIRE_PROGS(XARGS, xargs) + + # Then required tools that require some special treatment. + UTIL_REQUIRE_SPECIAL(AWK, [AC_PROG_AWK]) + UTIL_REQUIRE_SPECIAL(GREP, [AC_PROG_GREP]) + UTIL_REQUIRE_SPECIAL(EGREP, [AC_PROG_EGREP]) + UTIL_REQUIRE_SPECIAL(FGREP, [AC_PROG_FGREP]) + UTIL_REQUIRE_SPECIAL(SED, [AC_PROG_SED]) + + # Always force rm. + RM="$RM -f" + + # pwd behaves differently on various platforms and some don't support the -L flag. + # Always use the bash builtin pwd to get uniform behavior. + THEPWDCMD=pwd + + # These are not required on all platforms + UTIL_PATH_PROGS(CYGPATH, cygpath) + UTIL_PATH_PROGS(WSLPATH, wslpath) + UTIL_PATH_PROGS(DF, df) + UTIL_PATH_PROGS(CPIO, [cpio bsdcpio]) + UTIL_PATH_PROGS(NICE, nice) + + UTIL_PATH_PROGS(LSB_RELEASE, lsb_release) + UTIL_PATH_PROGS(CMD, [cmd.exe /mnt/c/Windows/System32/cmd.exe]) +]) + +############################################################################### +# Check if we have found a usable version of make +# $1: the path to a potential make binary (or empty) +# $2: the description on how we found this +AC_DEFUN([BASIC_CHECK_MAKE_VERSION], +[ + MAKE_CANDIDATE="$1" + DESCRIPTION="$2" + + # On Cygwin, we require a newer version of make than on other platforms + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + MAKE_VERSION_EXPR="-e 4\." + MAKE_REQUIRED_VERSION="4.0" + else + MAKE_VERSION_EXPR="-e 3\.8[[12]] -e 4\." + MAKE_REQUIRED_VERSION="3.81" + fi + + if test "x$MAKE_CANDIDATE" != x; then + AC_MSG_NOTICE([Testing potential make at $MAKE_CANDIDATE, found using $DESCRIPTION]) + MAKE_VERSION_STRING=`$MAKE_CANDIDATE --version | $HEAD -n 1` + IS_GNU_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP 'GNU Make'` + if test "x$IS_GNU_MAKE" = x; then + AC_MSG_NOTICE([Found potential make at $MAKE_CANDIDATE, however, this is not GNU Make. Ignoring.]) + else + IS_MODERN_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP $MAKE_VERSION_EXPR` + if test "x$IS_MODERN_MAKE" = x; then + AC_MSG_NOTICE([Found GNU make at $MAKE_CANDIDATE, however this is not version $MAKE_REQUIRED_VERSION or later. (it is: $MAKE_VERSION_STRING). Ignoring.]) + else + if test "x$OPENJDK_BUILD_OS" = "xwindows"; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + MAKE_EXPECTED_ENV='cygwin' + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + MAKE_EXPECTED_ENV='msys' + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then + MAKE_EXPECTED_ENV='x86_64-.*-linux-gnu' + else + AC_MSG_ERROR([Unknown Windows environment]) + fi + MAKE_BUILT_FOR=`$MAKE_CANDIDATE --version | $GREP -i 'built for'` + IS_MAKE_CORRECT_ENV=`$ECHO $MAKE_BUILT_FOR | $GREP $MAKE_EXPECTED_ENV` + else + # Not relevant for non-Windows + IS_MAKE_CORRECT_ENV=true + fi + if test "x$IS_MAKE_CORRECT_ENV" = x; then + AC_MSG_NOTICE([Found GNU make version $MAKE_VERSION_STRING at $MAKE_CANDIDATE, but it is not for $MAKE_EXPECTED_ENV (it says: $MAKE_BUILT_FOR). Ignoring.]) + else + FOUND_MAKE=$MAKE_CANDIDATE + UTIL_FIXUP_EXECUTABLE(FOUND_MAKE) + fi + fi + fi + fi +]) + +############################################################################### +AC_DEFUN([BASIC_CHECK_MAKE_OUTPUT_SYNC], +[ + # Check if make supports the output sync option and if so, setup using it. + AC_MSG_CHECKING([if make --output-sync is supported]) + if $MAKE --version -O > /dev/null 2>&1; then + OUTPUT_SYNC_SUPPORTED=true + AC_MSG_RESULT([yes]) + AC_MSG_CHECKING([for output-sync value]) + AC_ARG_WITH([output-sync], [AS_HELP_STRING([--with-output-sync], + [set make output sync type if supported by make. @<:@recurse@:>@])], + [OUTPUT_SYNC=$with_output_sync]) + if test "x$OUTPUT_SYNC" = "x"; then + OUTPUT_SYNC=none + fi + AC_MSG_RESULT([$OUTPUT_SYNC]) + if ! $MAKE --version -O$OUTPUT_SYNC > /dev/null 2>&1; then + AC_MSG_ERROR([Make did not the support the value $OUTPUT_SYNC as output sync type.]) + fi + else + OUTPUT_SYNC_SUPPORTED=false + AC_MSG_RESULT([no]) + fi + AC_SUBST(OUTPUT_SYNC_SUPPORTED) + AC_SUBST(OUTPUT_SYNC) +]) + +############################################################################### +# Goes looking for a usable version of GNU make. +AC_DEFUN([BASIC_CHECK_GNU_MAKE], +[ + UTIL_SETUP_TOOL([MAKE], + [ + # Try our hardest to locate a correct version of GNU make + AC_PATH_PROGS(CHECK_GMAKE, gmake) + BASIC_CHECK_MAKE_VERSION("$CHECK_GMAKE", [gmake in PATH]) + + if test "x$FOUND_MAKE" = x; then + AC_PATH_PROGS(CHECK_MAKE, make) + BASIC_CHECK_MAKE_VERSION("$CHECK_MAKE", [make in PATH]) + fi + + if test "x$FOUND_MAKE" = x; then + if test "x$TOOLCHAIN_PATH" != x; then + # We have a toolchain path, check that as well before giving up. + OLD_PATH=$PATH + PATH=$TOOLCHAIN_PATH:$PATH + AC_PATH_PROGS(CHECK_TOOLSDIR_GMAKE, gmake) + BASIC_CHECK_MAKE_VERSION("$CHECK_TOOLSDIR_GMAKE", [gmake in tools-dir]) + if test "x$FOUND_MAKE" = x; then + AC_PATH_PROGS(CHECK_TOOLSDIR_MAKE, make) + BASIC_CHECK_MAKE_VERSION("$CHECK_TOOLSDIR_MAKE", [make in tools-dir]) + fi + PATH=$OLD_PATH + fi + fi + + if test "x$FOUND_MAKE" = x; then + AC_MSG_ERROR([Cannot find GNU make $MAKE_REQUIRED_VERSION or newer! Please put it in the path, or add e.g. MAKE=/opt/gmake3.81/make as argument to configure.]) + fi + ],[ + # If MAKE was set by user, verify the version + BASIC_CHECK_MAKE_VERSION("$MAKE", [user supplied MAKE=$MAKE]) + if test "x$FOUND_MAKE" = x; then + AC_MSG_ERROR([The specified make (by MAKE=$MAKE) is not GNU make $MAKE_REQUIRED_VERSION or newer.]) + fi + ]) + + MAKE=$FOUND_MAKE + AC_SUBST(MAKE) + AC_MSG_NOTICE([Using GNU make at $FOUND_MAKE (version: $MAKE_VERSION_STRING)]) + + BASIC_CHECK_MAKE_OUTPUT_SYNC +]) + +############################################################################### +AC_DEFUN([BASIC_CHECK_FIND_DELETE], +[ + # Test if find supports -delete + AC_MSG_CHECKING([if find supports -delete]) + FIND_DELETE="-delete" + + DELETEDIR=`$MKTEMP -d tmp.XXXXXXXXXX` || (echo Could not create temporary directory!; exit $?) + + echo Hejsan > $DELETEDIR/TestIfFindSupportsDelete + + TEST_DELETE=`$FIND "$DELETEDIR" -name TestIfFindSupportsDelete $FIND_DELETE 2>&1` + if test -f $DELETEDIR/TestIfFindSupportsDelete; then + # No, it does not. + $RM $DELETEDIR/TestIfFindSupportsDelete + if test "x$OPENJDK_TARGET_OS" = "xaix"; then + # AIX 'find' is buggy if called with '-exec {} \+' and an empty file list + FIND_DELETE="-print | $XARGS $RM" + else + FIND_DELETE="-exec $RM \{\} \+" + fi + AC_MSG_RESULT([no]) + else + AC_MSG_RESULT([yes]) + fi + $RMDIR $DELETEDIR + AC_SUBST(FIND_DELETE) +]) + +############################################################################### +AC_DEFUN([BASIC_CHECK_TAR], +[ + # Test which kind of tar was found + if test "x$($TAR --version | $GREP "GNU tar")" != "x"; then + TAR_TYPE="gnu" + elif test "x$($TAR --version | $GREP "bsdtar")" != "x"; then + TAR_TYPE="bsd" + elif test "x$($TAR -v | $GREP "bsdtar")" != "x"; then + TAR_TYPE="bsd" + elif test "x$OPENJDK_BUILD_OS" = "xsolaris"; then + TAR_TYPE="solaris" + elif test "x$OPENJDK_BUILD_OS" = "xaix"; then + TAR_TYPE="aix" + fi + AC_MSG_CHECKING([what type of tar was found]) + AC_MSG_RESULT([$TAR_TYPE]) + + TAR_CREATE_FILE_PARAM="" + + if test "x$TAR_TYPE" = "xgnu"; then + TAR_INCLUDE_PARAM="T" + TAR_SUPPORTS_TRANSFORM="true" + if test "x$OPENJDK_TARGET_OS" = "xsolaris"; then + # When using gnu tar for Solaris targets, need to use compatibility mode + TAR_CREATE_EXTRA_PARAM="--format=ustar" + fi + elif test "x$TAR_TYPE" = "aix"; then + # -L InputList of aix tar: name of file listing the files and directories + # that need to be archived or extracted + TAR_INCLUDE_PARAM="L" + TAR_SUPPORTS_TRANSFORM="false" + else + TAR_INCLUDE_PARAM="I" + TAR_SUPPORTS_TRANSFORM="false" + fi + AC_SUBST(TAR_TYPE) + AC_SUBST(TAR_CREATE_EXTRA_PARAM) + AC_SUBST(TAR_INCLUDE_PARAM) + AC_SUBST(TAR_SUPPORTS_TRANSFORM) +]) + +############################################################################### +AC_DEFUN([BASIC_CHECK_GREP], +[ + # Test that grep supports -Fx with a list of pattern which includes null pattern. + # This is a problem for the grep resident on AIX. + AC_MSG_CHECKING([that grep ($GREP) -Fx handles empty lines in the pattern list correctly]) + # Multiple subsequent spaces.. + STACK_SPACES='aaa bbb ccc' + # ..converted to subsequent newlines, causes STACK_LIST to be a list with some empty + # patterns in it. + STACK_LIST=${STACK_SPACES// /$'\n'} + NEEDLE_SPACES='ccc bbb aaa' + NEEDLE_LIST=${NEEDLE_SPACES// /$'\n'} + RESULT="$($GREP -Fvx "$STACK_LIST" <<< "$NEEDLE_LIST")" + if test "x$RESULT" == "x"; then + AC_MSG_RESULT([yes]) + else + if test "x$OPENJDK_TARGET_OS" = "xaix"; then + ADDINFO="Please make sure you use GNU grep, usually found at /opt/freeware/bin." + fi + AC_MSG_ERROR([grep does not handle -Fx correctly. ${ADDINFO}]) + fi +]) + +############################################################################### +AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS], +[ + BASIC_CHECK_GNU_MAKE + + BASIC_CHECK_FIND_DELETE + BASIC_CHECK_TAR + BASIC_CHECK_GREP + BASIC_SETUP_PANDOC + + # These tools might not be installed by default, + # need hint on how to install them. + UTIL_REQUIRE_PROGS(UNZIP, unzip) + # Since zip uses "ZIP" as a environment variable for passing options, we need + # to name our variable differently, hence ZIPEXE. + UTIL_REQUIRE_PROGS(ZIPEXE, zip) + + # Non-required basic tools + + UTIL_PATH_PROGS(LDD, ldd) + if test "x$LDD" = "x"; then + # List shared lib dependencies is used for + # debug output and checking for forbidden dependencies. + # We can build without it. + LDD="true" + fi + UTIL_PATH_PROGS(READELF, [greadelf readelf]) + UTIL_PATH_PROGS(DOT, dot) + UTIL_PATH_PROGS(HG, hg) + UTIL_PATH_PROGS(GIT, git) + UTIL_PATH_PROGS(STAT, stat) + UTIL_PATH_PROGS(TIME, time) + UTIL_PATH_PROGS(FLOCK, flock) + # Dtrace is usually found in /usr/sbin on Solaris, but that directory may not + # be in the user path. + UTIL_PATH_PROGS(DTRACE, dtrace, $PATH:/usr/sbin) + UTIL_PATH_PROGS(PATCH, [gpatch patch]) + # Check if it's GNU time + IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'` + if test "x$IS_GNU_TIME" != x; then + IS_GNU_TIME=yes + else + IS_GNU_TIME=no + fi + AC_SUBST(IS_GNU_TIME) + + if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then + UTIL_REQUIRE_PROGS(DSYMUTIL, dsymutil) + UTIL_REQUIRE_PROGS(MIG, mig) + UTIL_REQUIRE_PROGS(XATTR, xattr) + UTIL_PATH_PROGS(CODESIGN, codesign) + + if test "x$CODESIGN" != "x"; then + # Check for user provided code signing identity. + # If no identity was provided, fall back to "openjdk_codesign". + AC_ARG_WITH([macosx-codesign-identity], [AS_HELP_STRING([--with-macosx-codesign-identity], + [specify the code signing identity])], + [MACOSX_CODESIGN_IDENTITY=$with_macosx_codesign_identity], + [MACOSX_CODESIGN_IDENTITY=openjdk_codesign] + ) + + AC_SUBST(MACOSX_CODESIGN_IDENTITY) + + # Verify that the codesign certificate is present + AC_MSG_CHECKING([if codesign certificate is present]) + $RM codesign-testfile + $TOUCH codesign-testfile + $CODESIGN -s "$MACOSX_CODESIGN_IDENTITY" codesign-testfile 2>&AS_MESSAGE_LOG_FD >&AS_MESSAGE_LOG_FD || CODESIGN= + $RM codesign-testfile + if test "x$CODESIGN" = x; then + AC_MSG_RESULT([no]) + else + AC_MSG_RESULT([yes]) + fi + fi + UTIL_REQUIRE_PROGS(SETFILE, SetFile) + elif test "x$OPENJDK_TARGET_OS" = "xsolaris"; then + UTIL_REQUIRE_PROGS(ELFEDIT, elfedit) + fi + if ! test "x$OPENJDK_TARGET_OS" = "xwindows"; then + UTIL_REQUIRE_BUILTIN_PROGS(ULIMIT, ulimit) + fi +]) + +############################################################################### +# Check for support for specific options in bash +AC_DEFUN_ONCE([BASIC_CHECK_BASH_OPTIONS], +[ + # Check bash version + # Extra [ ] to stop m4 mangling + [ BASH_VER=`$BASH --version | $SED -n -e 's/^.*bash.*ersion *\([0-9.]*\).*$/\1/ p'` ] + AC_MSG_CHECKING([bash version]) + AC_MSG_RESULT([$BASH_VER]) + + BASH_MAJOR=`$ECHO $BASH_VER | $CUT -d . -f 1` + BASH_MINOR=`$ECHO $BASH_VER | $CUT -d . -f 2` + if test $BASH_MAJOR -lt 3 || (test $BASH_MAJOR -eq 3 && test $BASH_MINOR -lt 2); then + AC_MSG_ERROR([bash version 3.2 or better is required]) + fi + + # Test if bash supports pipefail. + AC_MSG_CHECKING([if bash supports pipefail]) + if ${BASH} -c 'set -o pipefail'; then + BASH_ARGS="$BASH_ARGS -o pipefail" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + + AC_MSG_CHECKING([if bash supports errexit (-e)]) + if ${BASH} -e -c 'true'; then + BASH_ARGS="$BASH_ARGS -e" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + + AC_SUBST(BASH_ARGS) +]) + +################################################################################ +# +# Setup Pandoc +# +AC_DEFUN_ONCE([BASIC_SETUP_PANDOC], +[ + UTIL_PATH_PROGS(PANDOC, pandoc) + + PANDOC_MARKDOWN_FLAG="markdown" + if test -n "$PANDOC"; then + AC_MSG_CHECKING(if the pandoc smart extension needs to be disabled for markdown) + if $PANDOC --list-extensions | $GREP -q '\+smart'; then + AC_MSG_RESULT([yes]) + PANDOC_MARKDOWN_FLAG="markdown-smart" + else + AC_MSG_RESULT([no]) + fi + fi + + if test -n "$PANDOC"; then + ENABLE_PANDOC="true" + else + ENABLE_PANDOC="false" + fi + AC_SUBST(ENABLE_PANDOC) + AC_SUBST(PANDOC_MARKDOWN_FLAG) +]) diff --git a/make/autoconf/basic_windows.m4 b/make/autoconf/basic_windows.m4 new file mode 100644 index 00000000000..11fb231d825 --- /dev/null +++ b/make/autoconf/basic_windows.m4 @@ -0,0 +1,183 @@ +# +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Setup basic configuration paths, and platform-specific stuff related to PATHs. +AC_DEFUN([BASIC_CHECK_PATHS_WINDOWS], +[ + SRC_ROOT_LENGTH=`$THEPWDCMD -L|$WC -m` + if test $SRC_ROOT_LENGTH -gt 100; then + AC_MSG_ERROR([Your base path is too long. It is $SRC_ROOT_LENGTH characters long, but only 100 is supported]) + fi + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + AC_MSG_CHECKING([cygwin release]) + CYGWIN_VERSION=`$UNAME -r` + AC_MSG_RESULT([$CYGWIN_VERSION]) + WINDOWS_ENV_VENDOR='cygwin' + WINDOWS_ENV_VERSION="$CYGWIN_VERSION" + + CYGWIN_VERSION_OLD=`$ECHO $CYGWIN_VERSION | $GREP -e '^1\.[0-6]'` + if test "x$CYGWIN_VERSION_OLD" != x; then + AC_MSG_NOTICE([Your cygwin is too old. You are running $CYGWIN_VERSION, but at least cygwin 1.7 is required. Please upgrade.]) + AC_MSG_ERROR([Cannot continue]) + fi + if test "x$CYGPATH" = x; then + AC_MSG_ERROR([Something is wrong with your cygwin installation since I cannot find cygpath.exe in your path]) + fi + AC_MSG_CHECKING([cygwin root directory as unix-style path]) + # The cmd output ends with Windows line endings (CR/LF) + cygwin_winpath_root=`cd / ; cmd /c cd | $TR -d '\r\n'` + # Force cygpath to report the proper root by including a trailing space, and then stripping it off again. + CYGWIN_ROOT_PATH=`$CYGPATH -u "$cygwin_winpath_root " | $CUT -f 1 -d " "` + AC_MSG_RESULT([$CYGWIN_ROOT_PATH]) + WINDOWS_ENV_ROOT_PATH="$CYGWIN_ROOT_PATH" + test_cygdrive_prefix=`$ECHO $CYGWIN_ROOT_PATH | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + AC_MSG_ERROR([Your cygdrive prefix is not /cygdrive. This is currently not supported. Change with mount -c.]) + fi + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + AC_MSG_CHECKING([msys release]) + MSYS_VERSION=`$UNAME -r` + AC_MSG_RESULT([$MSYS_VERSION]) + + WINDOWS_ENV_VENDOR='msys' + WINDOWS_ENV_VERSION="$MSYS_VERSION" + + AC_MSG_CHECKING([msys root directory as unix-style path]) + # The cmd output ends with Windows line endings (CR/LF), the grep command will strip that away + MSYS_ROOT_PATH=`cd / ; cmd /c cd | $GREP ".*"` + UTIL_REWRITE_AS_UNIX_PATH(MSYS_ROOT_PATH) + AC_MSG_RESULT([$MSYS_ROOT_PATH]) + WINDOWS_ENV_ROOT_PATH="$MSYS_ROOT_PATH" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then + AC_MSG_CHECKING([Windows version]) + # m4 replaces [ and ] so we use @<:@ and @:>@ instead + WINDOWS_VERSION=`$CMD /c ver.exe | $EGREP -o '(@<:@0-9@:>@+\.)+@<:@0-9@:>@+'` + AC_MSG_RESULT([$WINDOWS_VERSION]) + + AC_MSG_CHECKING([WSL kernel version]) + WSL_KERNEL_VERSION=`$UNAME -v` + AC_MSG_RESULT([$WSL_KERNEL_VERSION]) + + AC_MSG_CHECKING([WSL kernel release]) + WSL_KERNEL_RELEASE=`$UNAME -r` + AC_MSG_RESULT([$WSL_KERNEL_RELEASE]) + + AC_MSG_CHECKING([WSL distribution]) + WSL_DISTRIBUTION=`$LSB_RELEASE -d | sed 's/Description:\t//'` + AC_MSG_RESULT([$WSL_DISTRIBUTION]) + + WINDOWS_ENV_VENDOR='WSL' + WINDOWS_ENV_VERSION="$WSL_DISTRIBUTION $WSL_KERNEL_VERSION $WSL_KERNEL_RELEASE (on Windows build $WINDOWS_VERSION)" + else + AC_MSG_ERROR([Unknown Windows environment. Neither cygwin, msys, nor wsl was detected.]) + fi + + # Test if windows or unix (cygwin/msys) find is first in path. + AC_MSG_CHECKING([what kind of 'find' is first on the PATH]) + FIND_BINARY_OUTPUT=`find --version 2>&1` + if test "x`echo $FIND_BINARY_OUTPUT | $GREP GNU`" != x; then + AC_MSG_RESULT([unix style]) + elif test "x`echo $FIND_BINARY_OUTPUT | $GREP FIND`" != x; then + AC_MSG_RESULT([Windows]) + AC_MSG_NOTICE([Your path contains Windows tools (C:\Windows\system32) before your unix (cygwin or msys) tools.]) + AC_MSG_NOTICE([This will not work. Please correct and make sure /usr/bin (or similar) is first in path.]) + AC_MSG_ERROR([Cannot continue]) + else + AC_MSG_RESULT([unknown]) + AC_MSG_WARN([It seems that your find utility is non-standard.]) + fi +]) + +AC_DEFUN_ONCE([BASIC_COMPILE_FIXPATH], +[ + # When using cygwin or msys, we need a wrapper binary that renames + # /cygdrive/c/ arguments into c:/ arguments and peeks into + # @files and rewrites these too! This wrapper binary is + # called fixpath. + FIXPATH= + if test "x$OPENJDK_BUILD_OS" = xwindows; then + AC_MSG_CHECKING([if fixpath can be created]) + FIXPATH_SRC="$TOPDIR/make/src/native/fixpath.c" + FIXPATH_BIN="$CONFIGURESUPPORT_OUTPUTDIR/bin/fixpath.exe" + FIXPATH_DIR="$CONFIGURESUPPORT_OUTPUTDIR/fixpath" + if test "x$OPENJDK_BUILD_OS_ENV" = xwindows.cygwin; then + # Important to keep the .exe suffix on Cygwin for Hotspot makefiles + FIXPATH="$FIXPATH_BIN -c" + elif test "x$OPENJDK_BUILD_OS_ENV" = xwindows.msys; then + # Take all collected prefixes and turn them into a -m/c/foo@/c/bar@... command line + # @ was chosen as separator to minimize risk of other tools messing around with it + all_unique_prefixes=`echo "${all_fixpath_prefixes@<:@@@:>@}" \ + | tr ' ' '\n' | $GREP '^/./' | $SORT | $UNIQ` + fixpath_argument_list=`echo $all_unique_prefixes | tr ' ' '@'` + FIXPATH="$FIXPATH_BIN -m$fixpath_argument_list" + elif test "x$OPENJDK_BUILD_OS_ENV" = xwindows.wsl; then + FIXPATH="$FIXPATH_BIN -w" + fi + FIXPATH_SRC_W="$FIXPATH_SRC" + FIXPATH_BIN_W="$FIXPATH_BIN" + UTIL_REWRITE_AS_WINDOWS_MIXED_PATH([FIXPATH_SRC_W]) + UTIL_REWRITE_AS_WINDOWS_MIXED_PATH([FIXPATH_BIN_W]) + $RM -rf $FIXPATH_BIN $FIXPATH_DIR + $MKDIR -p $FIXPATH_DIR $CONFIGURESUPPORT_OUTPUTDIR/bin + cd $FIXPATH_DIR + $CC $FIXPATH_SRC_W -Fe$FIXPATH_BIN_W > $FIXPATH_DIR/fixpath1.log 2>&1 + cd $CONFIGURE_START_DIR + + if test ! -x $FIXPATH_BIN; then + AC_MSG_RESULT([no]) + cat $FIXPATH_DIR/fixpath1.log + AC_MSG_ERROR([Could not create $FIXPATH_BIN]) + fi + AC_MSG_RESULT([yes]) + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then + OLD_WSLENV="$WSLENV" + WSLENV=`$ECHO $WSLENV | $SED 's/PATH\/l://'` + UTIL_APPEND_TO_PATH(WSLENV, "FIXPATH_PATH") + export WSLENV + export FIXPATH_PATH=$VS_PATH_WINDOWS + AC_MSG_NOTICE([FIXPATH_PATH is $FIXPATH_PATH]) + AC_MSG_NOTICE([Rewriting WSLENV from $OLD_WSLENV to $WSLENV]) + fi + + AC_MSG_CHECKING([if fixpath.exe works]) + cd $FIXPATH_DIR + $FIXPATH $CC $FIXPATH_SRC -Fe$FIXPATH_DIR/fixpath2.exe \ + > $FIXPATH_DIR/fixpath2.log 2>&1 + cd $CONFIGURE_START_DIR + if test ! -x $FIXPATH_DIR/fixpath2.exe; then + AC_MSG_RESULT([no]) + cat $FIXPATH_DIR/fixpath2.log + AC_MSG_ERROR([fixpath did not work!]) + fi + AC_MSG_RESULT([yes]) + + FIXPATH_DETACH_FLAG="--detach" + fi + + AC_SUBST(FIXPATH) + AC_SUBST(FIXPATH_DETACH_FLAG) +]) diff --git a/make/autoconf/basics.m4 b/make/autoconf/basics.m4 deleted file mode 100644 index e1f1c080495..00000000000 --- a/make/autoconf/basics.m4 +++ /dev/null @@ -1,1537 +0,0 @@ -# -# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -############################################################################### -# Create a function/macro that takes a series of named arguments. The call is -# similar to AC_DEFUN, but the setup of the function looks like this: -# BASIC_DEFUN_NAMED([MYFUNC], [FOO *BAR], [$@], [ -# ... do something -# AC_MSG_NOTICE([Value of BAR is ARG_BAR]) -# ]) -# A star (*) in front of a named argument means that it is required and it's -# presence will be verified. To pass e.g. the first value as a normal indexed -# argument, use [m4_shift($@)] as the third argument instead of [$@]. These -# arguments are referenced in the function by their name prefixed by ARG_, e.g. -# "ARG_FOO". -# -# The generated function can be called like this: -# MYFUNC(FOO: [foo-val], -# BAR: [ -# $ECHO hello world -# ]) -# Note that the argument value must start on the same line as the argument name. -# -# Argument 1: Name of the function to define -# Argument 2: List of legal named arguments, with a * prefix for required arguments -# Argument 3: Argument array to treat as named, typically $@ -# Argument 4: The main function body -AC_DEFUN([BASIC_DEFUN_NAMED], -[ - AC_DEFUN($1, [ - m4_foreach(arg, m4_split($2), [ - m4_if(m4_bregexp(arg, [^\*]), -1, - [ - m4_set_add(legal_named_args, arg) - ], - [ - m4_set_add(legal_named_args, m4_substr(arg, 1)) - m4_set_add(required_named_args, m4_substr(arg, 1)) - ] - ) - ]) - - m4_foreach([arg], [$3], [ - m4_define(arg_name, m4_substr(arg, 0, m4_bregexp(arg, [: ]))) - m4_set_contains(legal_named_args, arg_name, [],[AC_MSG_ERROR([Internal error: arg_name is not a valid named argument to [$1]. Valid arguments are 'm4_set_contents(legal_named_args, [ ])'.])]) - m4_set_remove(required_named_args, arg_name) - m4_set_remove(legal_named_args, arg_name) - m4_pushdef([ARG_][]arg_name, m4_substr(arg, m4_incr(m4_incr(m4_bregexp(arg, [: ]))))) - m4_set_add(defined_args, arg_name) - m4_undefine([arg_name]) - ]) - m4_set_empty(required_named_args, [], [ - AC_MSG_ERROR([Internal error: Required named arguments are missing for [$1]. Missing arguments: 'm4_set_contents(required_named_args, [ ])']) - ]) - m4_foreach([arg], m4_indir([m4_dquote]m4_set_listc([legal_named_args])), [ - m4_pushdef([ARG_][]arg, []) - m4_set_add(defined_args, arg) - ]) - m4_set_delete(legal_named_args) - m4_set_delete(required_named_args) - - # Execute function body - $4 - - m4_foreach([arg], m4_indir([m4_dquote]m4_set_listc([defined_args])), [ - m4_popdef([ARG_][]arg) - ]) - - m4_set_delete(defined_args) - ]) -]) - -############################################################################### -# Check if a list of space-separated words are selected only from a list of -# space-separated legal words. Typical use is to see if a user-specified -# set of words is selected from a set of legal words. -# -# Sets the specified variable to list of non-matching (offending) words, or to -# the empty string if all words are matching the legal set. -# -# $1: result variable name -# $2: list of values to check -# $3: list of legal values -AC_DEFUN([BASIC_GET_NON_MATCHING_VALUES], -[ - # grep filter function inspired by a comment to http://stackoverflow.com/a/1617326 - # Notice that the original variant fails on SLES 10 and 11 - # Some grep versions (at least bsd) behaves strangely on the base case with - # no legal_values, so make it explicit. - values_to_check=`$ECHO $2 | $TR ' ' '\n'` - legal_values=`$ECHO $3 | $TR ' ' '\n'` - if test -z "$legal_values"; then - $1="$2" - else - result=`$GREP -Fvx "$legal_values" <<< "$values_to_check" | $GREP -v '^$'` - $1=${result//$'\n'/ } - fi -]) - -############################################################################### -# Check if a list of space-separated words contains any word(s) from a list of -# space-separated illegal words. Typical use is to see if a user-specified -# set of words contains any from a set of illegal words. -# -# Sets the specified variable to list of matching illegal words, or to -# the empty string if no words are matching the illegal set. -# -# $1: result variable name -# $2: list of values to check -# $3: list of illegal values -AC_DEFUN([BASIC_GET_MATCHING_VALUES], -[ - # grep filter function inspired by a comment to http://stackoverflow.com/a/1617326 - # Notice that the original variant fails on SLES 10 and 11 - # Some grep versions (at least bsd) behaves strangely on the base case with - # no legal_values, so make it explicit. - values_to_check=`$ECHO $2 | $TR ' ' '\n'` - illegal_values=`$ECHO $3 | $TR ' ' '\n'` - if test -z "$illegal_values"; then - $1="" - else - result=`$GREP -Fx "$illegal_values" <<< "$values_to_check" | $GREP -v '^$'` - $1=${result//$'\n'/ } - fi -]) - -############################################################################### -# Sort a space-separated list, and remove duplicates. -# -# Sets the specified variable to the resulting list. -# -# $1: result variable name -# $2: list of values to sort -AC_DEFUN([BASIC_SORT_LIST], -[ - values_to_sort=`$ECHO $2 | $TR ' ' '\n'` - result=`$SORT -u <<< "$values_to_sort" | $GREP -v '^$'` - $1=${result//$'\n'/ } -]) - -############################################################################### -# Test if $1 is a valid argument to $3 (often is $JAVA passed as $3) -# If so, then append $1 to $2 \ -# Also set JVM_ARG_OK to true/false depending on outcome. -AC_DEFUN([ADD_JVM_ARG_IF_OK], -[ - $ECHO "Check if jvm arg is ok: $1" >&AS_MESSAGE_LOG_FD - $ECHO "Command: $3 $1 -version" >&AS_MESSAGE_LOG_FD - OUTPUT=`$3 $1 $USER_BOOT_JDK_OPTIONS -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | $GREP -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | $GREP " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - $2="[$]$2 $1" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&AS_MESSAGE_LOG_FD - $ECHO "$OUTPUT" >&AS_MESSAGE_LOG_FD - JVM_ARG_OK=false - fi -]) - -# Appends a string to a path variable, only adding the : when needed. -AC_DEFUN([BASIC_APPEND_TO_PATH], -[ - if test "x$2" != x; then - if test "x[$]$1" = x; then - $1="$2" - else - $1="[$]$1:$2" - fi - fi -]) - -# Prepends a string to a path variable, only adding the : when needed. -AC_DEFUN([BASIC_PREPEND_TO_PATH], -[ - if test "x$2" != x; then - if test "x[$]$1" = x; then - $1="$2" - else - $1="$2:[$]$1" - fi - fi -]) - -################################################################################ -# This will make a path absolute. Assumes it's already a unix path. Also -# resolves ~ to homedir. -AC_DEFUN([BASIC_ABSOLUTE_PATH], -[ - if test "x[$]$1" != x; then - new_path="[$]$1" - - # Use eval to expand a potential ~. This technique does not work if there - # are spaces in the path (which is valid at this point on Windows), so only - # try to apply it if there is an actual ~ first in the path. - if [ [[ "$new_path" = "~"* ]] ]; then - eval new_path="$new_path" - if test ! -f "$new_path" && test ! -d "$new_path"; then - AC_MSG_ERROR([The new_path of $1, which resolves as "$new_path", is not found.]) - fi - fi - - if test -d "$new_path"; then - $1="`cd "$new_path"; $THEPWDCMD -L`" - else - dir="`$DIRNAME "$new_path"`" - base="`$BASENAME "$new_path"`" - $1="`cd "$dir"; $THEPWDCMD -L`/$base" - fi - fi -]) - -############################################################################### -# This will make sure the given variable points to a full and proper -# path. This means: -# 1) There will be no spaces in the path. On unix platforms, -# spaces in the path will result in an error. On Windows, -# the path will be rewritten using short-style to be space-free. -# 2) The path will be absolute, and it will be in unix-style (on -# cygwin). -# $1: The name of the variable to fix -AC_DEFUN([BASIC_FIXUP_PATH], -[ - # Only process if variable expands to non-empty - if test "x[$]$1" != x; then - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - BASIC_FIXUP_PATH_CYGWIN($1) - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - BASIC_FIXUP_PATH_MSYS($1) - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then - BASIC_FIXUP_PATH_WSL($1) - else - # We're on a unix platform. Hooray! :) - path="[$]$1" - has_space=`$ECHO "$path" | $GREP " "` - if test "x$has_space" != x; then - AC_MSG_NOTICE([The path of $1, which resolves as "$path", is invalid.]) - AC_MSG_ERROR([Spaces are not allowed in this path.]) - fi - - BASIC_ABSOLUTE_PATH(path) - $1="$path" - fi - fi -]) - -############################################################################### -# This will make sure the given variable points to a executable -# with a full and proper path. This means: -# 1) There will be no spaces in the path. On unix platforms, -# spaces in the path will result in an error. On Windows, -# the path will be rewritten using short-style to be space-free. -# 2) The path will be absolute, and it will be in unix-style (on -# cygwin). -# Any arguments given to the executable is preserved. -# If the input variable does not have a directory specification, then -# it need to be in the PATH. -# $1: The name of the variable to fix -AC_DEFUN([BASIC_FIXUP_EXECUTABLE], -[ - # Only process if variable expands to non-empty - - if test "x[$]$1" != x; then - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - BASIC_FIXUP_EXECUTABLE_CYGWIN($1) - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - BASIC_FIXUP_EXECUTABLE_MSYS($1) - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then - BASIC_FIXUP_EXECUTABLE_WSL($1) - else - # We're on a unix platform. Hooray! :) - # First separate the path from the arguments. This will split at the first - # space. - complete="[$]$1" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Cannot rely on the command "which" here since it doesn't always work. - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test -z "$is_absolute_path"; then - # Path to executable is not absolute. Find it. - IFS_save="$IFS" - IFS=: - for p in $PATH; do - if test -f "$p/$path" && test -x "$p/$path"; then - new_path="$p/$path" - break - fi - done - IFS="$IFS_save" - else - # This is an absolute path, we can use it without further modifications. - new_path="$path" - fi - - if test "x$new_path" = x; then - AC_MSG_NOTICE([The path of $1, which resolves as "$complete", is not found.]) - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - AC_MSG_NOTICE([This might be caused by spaces in the path, which is not allowed.]) - fi - AC_MSG_ERROR([Cannot locate the the path of $1]) - fi - fi - - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi - - if test "x$complete" != "x$new_complete"; then - $1="$new_complete" - AC_MSG_NOTICE([Rewriting $1 to "$new_complete"]) - fi - fi -]) - -############################################################################### -AC_DEFUN([BASIC_REMOVE_SYMBOLIC_LINKS], -[ - if test "x$OPENJDK_BUILD_OS" != xwindows; then - # Follow a chain of symbolic links. Use readlink - # where it exists, else fall back to horribly - # complicated shell code. - if test "x$READLINK_TESTED" != yes; then - # On MacOSX there is a readlink tool with a different - # purpose than the GNU readlink tool. Check the found readlink. - READLINK_ISGNU=`$READLINK --version 2>&1 | $GREP GNU` - # If READLINK_ISGNU is empty, then it's a non-GNU readlink. Don't use it. - READLINK_TESTED=yes - fi - - if test "x$READLINK" != x && test "x$READLINK_ISGNU" != x; then - $1=`$READLINK -f [$]$1` - else - # Save the current directory for restoring afterwards - STARTDIR=$PWD - COUNTER=0 - sym_link_dir=`$DIRNAME [$]$1` - sym_link_file=`$BASENAME [$]$1` - cd $sym_link_dir - # Use -P flag to resolve symlinks in directories. - cd `$THEPWDCMD -P` - sym_link_dir=`$THEPWDCMD -P` - # Resolve file symlinks - while test $COUNTER -lt 20; do - ISLINK=`$LS -l $sym_link_dir/$sym_link_file | $GREP '\->' | $SED -e 's/.*-> \(.*\)/\1/'` - if test "x$ISLINK" == x; then - # This is not a symbolic link! We are done! - break - fi - # Again resolve directory symlinks since the target of the just found - # link could be in a different directory - cd `$DIRNAME $ISLINK` - sym_link_dir=`$THEPWDCMD -P` - sym_link_file=`$BASENAME $ISLINK` - let COUNTER=COUNTER+1 - done - cd $STARTDIR - $1=$sym_link_dir/$sym_link_file - fi - fi -]) - -############################################################################### -# Register a --with argument but mark it as deprecated -# $1: The name of the with argument to deprecate, not including --with- -AC_DEFUN([BASIC_DEPRECATED_ARG_WITH], -[ - AC_ARG_WITH($1, [AS_HELP_STRING([--with-$1], - [Deprecated. Option is kept for backwards compatibility and is ignored])], - [AC_MSG_WARN([Option --with-$1 is deprecated and will be ignored.])]) -]) - -############################################################################### -# Register a --enable argument but mark it as deprecated -# $1: The name of the with argument to deprecate, not including --enable- -# $2: The name of the argument to deprecate, in shell variable style (i.e. with _ instead of -) -# $3: Messages to user. -AC_DEFUN([BASIC_DEPRECATED_ARG_ENABLE], -[ - AC_ARG_ENABLE($1, [AS_HELP_STRING([--enable-$1], - [Deprecated. Option is kept for backwards compatibility and is ignored])]) - if test "x$enable_$2" != x; then - AC_MSG_WARN([Option --enable-$1 is deprecated and will be ignored.]) - - if test "x$3" != x; then - AC_MSG_WARN([$3]) - fi - - fi -]) - -############################################################################### -AC_DEFUN_ONCE([BASIC_INIT], -[ - # Save the original command line. This is passed to us by the wrapper configure script. - AC_SUBST(CONFIGURE_COMMAND_LINE) - # AUTOCONF might be set in the environment by the user. Preserve for "make reconfigure". - AC_SUBST(AUTOCONF) - # Save the path variable before it gets changed - ORIGINAL_PATH="$PATH" - AC_SUBST(ORIGINAL_PATH) - DATE_WHEN_CONFIGURED=`date` - AC_SUBST(DATE_WHEN_CONFIGURED) - AC_MSG_NOTICE([Configuration created at $DATE_WHEN_CONFIGURED.]) -]) - -############################################################################### -# Test that variable $1 denoting a program is not empty. If empty, exit with an error. -# $1: variable to check -AC_DEFUN([BASIC_CHECK_NONEMPTY], -[ - if test "x[$]$1" = x; then - AC_MSG_ERROR([Could not find required tool for $1]) - fi -]) - -############################################################################### -# Check that there are no unprocessed overridden variables left. -# If so, they are an incorrect argument and we will exit with an error. -AC_DEFUN([BASIC_CHECK_LEFTOVER_OVERRIDDEN], -[ - if test "x$CONFIGURE_OVERRIDDEN_VARIABLES" != x; then - # Replace the separating ! with spaces before presenting for end user. - unknown_variables=${CONFIGURE_OVERRIDDEN_VARIABLES//!/ } - AC_MSG_WARN([The following variables might be unknown to configure: $unknown_variables]) - fi -]) - -############################################################################### -# Setup a tool for the given variable. If correctly specified by the user, -# use that value, otherwise search for the tool using the supplied code snippet. -# $1: variable to set -# $2: code snippet to call to look for the tool -# $3: code snippet to call if variable was used to find tool -AC_DEFUN([BASIC_SETUP_TOOL], -[ - # Publish this variable in the help. - AC_ARG_VAR($1, [Override default value for $1]) - - if [[ -z "${$1+x}" ]]; then - # The variable is not set by user, try to locate tool using the code snippet - $2 - else - # The variable is set, but is it from the command line or the environment? - - # Try to remove the string !$1! from our list. - try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!$1!/} - if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then - # If it failed, the variable was not from the command line. Ignore it, - # but warn the user (except for BASH, which is always set by the calling BASH). - if test "x$1" != xBASH; then - AC_MSG_WARN([Ignoring value of $1 from the environment. Use command line variables instead.]) - fi - # Try to locate tool using the code snippet - $2 - else - # If it succeeded, then it was overridden by the user. We will use it - # for the tool. - - # First remove it from the list of overridden variables, so we can test - # for unknown variables in the end. - CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" - - tool_override=[$]$1 - AC_MSG_NOTICE([User supplied override $1="$tool_override"]) - - # Check if we try to supply an empty value - if test "x$tool_override" = x; then - AC_MSG_CHECKING([for $1]) - AC_MSG_RESULT([disabled]) - else - # Split up override in command part and argument part - tool_and_args=($tool_override) - [ tool_command=${tool_and_args[0]} ] - [ unset 'tool_and_args[0]' ] - [ tool_args=${tool_and_args[@]} ] - - # Check if the provided tool contains a complete path. - tool_basename="${tool_command##*/}" - if test "x$tool_basename" = "x$tool_command"; then - # A command without a complete path is provided, search $PATH. - AC_MSG_NOTICE([Will search for user supplied tool "$tool_basename"]) - AC_PATH_PROG($1, $tool_basename) - if test "x[$]$1" = x; then - AC_MSG_ERROR([User supplied tool $1="$tool_basename" could not be found]) - fi - else - # Otherwise we believe it is a complete path. Use it as it is. - AC_MSG_NOTICE([Will use user supplied tool "$tool_command"]) - AC_MSG_CHECKING([for $tool_command]) - if test ! -x "$tool_command"; then - AC_MSG_RESULT([not found]) - AC_MSG_ERROR([User supplied tool $1="$tool_command" does not exist or is not executable]) - fi - $1="$tool_command" - AC_MSG_RESULT([found]) - fi - if test "x$tool_args" != x; then - # If we got arguments, re-append them to the command after the fixup. - $1="[$]$1 $tool_args" - fi - fi - fi - $3 - fi -]) - -############################################################################### -# Call BASIC_SETUP_TOOL with AC_PATH_PROGS to locate the tool -# $1: variable to set -# $2: executable name (or list of names) to look for -# $3: [path] -AC_DEFUN([BASIC_PATH_PROGS], -[ - BASIC_SETUP_TOOL($1, [AC_PATH_PROGS($1, $2, , $3)]) -]) - -############################################################################### -# Call BASIC_SETUP_TOOL with AC_CHECK_TOOLS to locate the tool -# $1: variable to set -# $2: executable name (or list of names) to look for -AC_DEFUN([BASIC_CHECK_TOOLS], -[ - BASIC_SETUP_TOOL($1, [AC_CHECK_TOOLS($1, $2)]) -]) - -############################################################################### -# Like BASIC_PATH_PROGS but fails if no tool was found. -# $1: variable to set -# $2: executable name (or list of names) to look for -# $3: [path] -AC_DEFUN([BASIC_REQUIRE_PROGS], -[ - BASIC_PATH_PROGS($1, $2, , $3) - BASIC_CHECK_NONEMPTY($1) -]) - -############################################################################### -# Like BASIC_SETUP_TOOL but fails if no tool was found. -# $1: variable to set -# $2: autoconf macro to call to look for the special tool -AC_DEFUN([BASIC_REQUIRE_SPECIAL], -[ - BASIC_SETUP_TOOL($1, [$2]) - BASIC_CHECK_NONEMPTY($1) -]) - -############################################################################### -# Like BASIC_REQUIRE_PROGS but also allows for bash built-ins -# $1: variable to set -# $2: executable name (or list of names) to look for -# $3: [path] -AC_DEFUN([BASIC_REQUIRE_BUILTIN_PROGS], -[ - BASIC_SETUP_TOOL($1, [AC_PATH_PROGS($1, $2, , $3)]) - if test "x[$]$1" = x; then - AC_MSG_NOTICE([Required tool $2 not found in PATH, checking built-in]) - if help $2 > /dev/null 2>&1; then - AC_MSG_NOTICE([Found $2 as shell built-in. Using it]) - $1="$2" - else - AC_MSG_ERROR([Required tool $2 also not found as built-in.]) - fi - fi - BASIC_CHECK_NONEMPTY($1) -]) - -############################################################################### -# Setup the most fundamental tools that relies on not much else to set up, -# but is used by much of the early bootstrap code. -AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS], -[ - # Start with tools that do not need have cross compilation support - # and can be expected to be found in the default PATH. These tools are - # used by configure. - - # First are all the simple required tools. - BASIC_REQUIRE_PROGS(BASENAME, basename) - BASIC_REQUIRE_PROGS(BASH, bash) - BASIC_REQUIRE_PROGS(CAT, cat) - BASIC_REQUIRE_PROGS(CHMOD, chmod) - BASIC_REQUIRE_PROGS(CMP, cmp) - BASIC_REQUIRE_PROGS(COMM, comm) - BASIC_REQUIRE_PROGS(CP, cp) - BASIC_REQUIRE_PROGS(CUT, cut) - BASIC_REQUIRE_PROGS(DATE, date) - BASIC_REQUIRE_PROGS(DIFF, [gdiff diff]) - BASIC_REQUIRE_PROGS(DIRNAME, dirname) - BASIC_REQUIRE_PROGS(ECHO, echo) - BASIC_REQUIRE_PROGS(EXPR, expr) - BASIC_REQUIRE_PROGS(FILE, file) - BASIC_REQUIRE_PROGS(FIND, find) - BASIC_REQUIRE_PROGS(HEAD, head) - BASIC_REQUIRE_PROGS(GUNZIP, gunzip) - BASIC_REQUIRE_PROGS(GZIP, pigz gzip) - BASIC_REQUIRE_PROGS(LN, ln) - BASIC_REQUIRE_PROGS(LS, ls) - # gmkdir is known to be safe for concurrent invocations with -p flag. - BASIC_REQUIRE_PROGS(MKDIR, [gmkdir mkdir]) - BASIC_REQUIRE_PROGS(MKTEMP, mktemp) - BASIC_REQUIRE_PROGS(MV, mv) - BASIC_REQUIRE_PROGS(NAWK, [nawk gawk awk]) - BASIC_REQUIRE_PROGS(PRINTF, printf) - BASIC_REQUIRE_PROGS(READLINK, [greadlink readlink]) - BASIC_REQUIRE_PROGS(RM, rm) - BASIC_REQUIRE_PROGS(RMDIR, rmdir) - BASIC_REQUIRE_PROGS(SH, sh) - BASIC_REQUIRE_PROGS(SORT, sort) - BASIC_REQUIRE_PROGS(TAIL, tail) - BASIC_REQUIRE_PROGS(TAR, gtar tar) - BASIC_REQUIRE_PROGS(TEE, tee) - BASIC_REQUIRE_PROGS(TOUCH, touch) - BASIC_REQUIRE_PROGS(TR, tr) - BASIC_REQUIRE_PROGS(UNAME, uname) - BASIC_REQUIRE_PROGS(UNIQ, uniq) - BASIC_REQUIRE_PROGS(WC, wc) - BASIC_REQUIRE_PROGS(WHICH, which) - BASIC_REQUIRE_PROGS(XARGS, xargs) - - # Then required tools that require some special treatment. - BASIC_REQUIRE_SPECIAL(AWK, [AC_PROG_AWK]) - BASIC_REQUIRE_SPECIAL(GREP, [AC_PROG_GREP]) - BASIC_REQUIRE_SPECIAL(EGREP, [AC_PROG_EGREP]) - BASIC_REQUIRE_SPECIAL(FGREP, [AC_PROG_FGREP]) - BASIC_REQUIRE_SPECIAL(SED, [AC_PROG_SED]) - - # Always force rm. - RM="$RM -f" - - # pwd behaves differently on various platforms and some don't support the -L flag. - # Always use the bash builtin pwd to get uniform behavior. - THEPWDCMD=pwd - - # These are not required on all platforms - BASIC_PATH_PROGS(CYGPATH, cygpath) - BASIC_PATH_PROGS(WSLPATH, wslpath) - BASIC_PATH_PROGS(DF, df) - BASIC_PATH_PROGS(CPIO, [cpio bsdcpio]) - BASIC_PATH_PROGS(NICE, nice) - - BASIC_PATH_PROGS(LSB_RELEASE, lsb_release) - BASIC_PATH_PROGS(CMD, [cmd.exe /mnt/c/Windows/System32/cmd.exe]) -]) - -############################################################################### -# Setup basic configuration paths, and platform-specific stuff related to PATHs. -AC_DEFUN_ONCE([BASIC_SETUP_PATHS], -[ - # Save the current directory this script was started from - CONFIGURE_START_DIR="$PWD" - - # We might need to rewrite ORIGINAL_PATH, if it includes "#", to quote them - # for make. We couldn't do this when we retrieved ORIGINAL_PATH, since SED - # was not available at that time. - REWRITTEN_PATH=`$ECHO "$ORIGINAL_PATH" | $SED -e 's/#/\\\\#/g'` - if test "x$REWRITTEN_PATH" != "x$ORIGINAL_PATH"; then - ORIGINAL_PATH="$REWRITTEN_PATH" - AC_MSG_NOTICE([Rewriting ORIGINAL_PATH to $REWRITTEN_PATH]) - fi - - if test "x$OPENJDK_TARGET_OS" = "xwindows"; then - PATH_SEP=";" - EXE_SUFFIX=".exe" - BASIC_CHECK_PATHS_WINDOWS - else - PATH_SEP=":" - EXE_SUFFIX="" - fi - AC_SUBST(PATH_SEP) - AC_SUBST(EXE_SUFFIX) - - # We get the top-level directory from the supporting wrappers. - AC_MSG_CHECKING([for top-level directory]) - AC_MSG_RESULT([$TOPDIR]) - AC_SUBST(TOPDIR) - AC_SUBST(CONFIGURE_START_DIR) - - # We can only call BASIC_FIXUP_PATH after BASIC_CHECK_PATHS_WINDOWS. - BASIC_FIXUP_PATH(CONFIGURE_START_DIR) - BASIC_FIXUP_PATH(TOPDIR) - - # Locate the directory of this script. - AUTOCONF_DIR=$TOPDIR/make/autoconf - - # Setup username (for use in adhoc version strings etc) - # Outer [ ] to quote m4. - [ USERNAME=`$ECHO "$USER" | $TR -d -c '[a-z][A-Z][0-9]'` ] - AC_SUBST(USERNAME) -]) - -############################################################################### -# Evaluates platform specific overrides for devkit variables. -# $1: Name of variable -AC_DEFUN([BASIC_EVAL_DEVKIT_VARIABLE], -[ - if test "x[$]$1" = x; then - eval $1="\${$1_${OPENJDK_TARGET_CPU}}" - fi -]) - -############################################################################### -AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT], -[ - AC_ARG_WITH([devkit], [AS_HELP_STRING([--with-devkit], - [use this devkit for compilers, tools and resources])]) - - if test "x$with_devkit" = xyes; then - AC_MSG_ERROR([--with-devkit must have a value]) - elif test "x$with_devkit" != x && test "x$with_devkit" != xno; then - BASIC_FIXUP_PATH([with_devkit]) - DEVKIT_ROOT="$with_devkit" - # Check for a meta data info file in the root of the devkit - if test -f "$DEVKIT_ROOT/devkit.info"; then - . $DEVKIT_ROOT/devkit.info - # This potentially sets the following: - # A descriptive name of the devkit - BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_NAME]) - # Corresponds to --with-extra-path - BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_EXTRA_PATH]) - # Corresponds to --with-toolchain-path - BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_TOOLCHAIN_PATH]) - # Corresponds to --with-sysroot - BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_SYSROOT]) - - # Identifies the Visual Studio version in the devkit - BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_VS_VERSION]) - # The Visual Studio include environment variable - BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_VS_INCLUDE]) - # The Visual Studio lib environment variable - BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_VS_LIB]) - # Corresponds to --with-msvcr-dll - BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_MSVCR_DLL]) - # Corresponds to --with-msvcp-dll - BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_MSVCP_DLL]) - # Corresponds to --with-ucrt-dll-dir - BASIC_EVAL_DEVKIT_VARIABLE([DEVKIT_UCRT_DLL_DIR]) - fi - - AC_MSG_CHECKING([for devkit]) - if test "x$DEVKIT_NAME" != x; then - AC_MSG_RESULT([$DEVKIT_NAME in $DEVKIT_ROOT]) - else - AC_MSG_RESULT([$DEVKIT_ROOT]) - fi - - BASIC_PREPEND_TO_PATH([EXTRA_PATH],$DEVKIT_EXTRA_PATH) - - # Fallback default of just /bin if DEVKIT_PATH is not defined - if test "x$DEVKIT_TOOLCHAIN_PATH" = x; then - DEVKIT_TOOLCHAIN_PATH="$DEVKIT_ROOT/bin" - fi - BASIC_PREPEND_TO_PATH([TOOLCHAIN_PATH],$DEVKIT_TOOLCHAIN_PATH) - - # If DEVKIT_SYSROOT is set, use that, otherwise try a couple of known - # places for backwards compatiblity. - if test "x$DEVKIT_SYSROOT" != x; then - SYSROOT="$DEVKIT_SYSROOT" - elif test -d "$DEVKIT_ROOT/$host_alias/libc"; then - SYSROOT="$DEVKIT_ROOT/$host_alias/libc" - elif test -d "$DEVKIT_ROOT/$host/sys-root"; then - SYSROOT="$DEVKIT_ROOT/$host/sys-root" - fi - - if test "x$DEVKIT_ROOT" != x; then - DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib" - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib64" - fi - AC_SUBST(DEVKIT_LIB_DIR) - fi - fi - - # You can force the sysroot if the sysroot encoded into the compiler tools - # is not correct. - AC_ARG_WITH(sys-root, [AS_HELP_STRING([--with-sys-root], - [alias for --with-sysroot for backwards compatability])], - [SYSROOT=$with_sys_root] - ) - - AC_ARG_WITH(sysroot, [AS_HELP_STRING([--with-sysroot], - [use this directory as sysroot])], - [SYSROOT=$with_sysroot] - ) - - AC_ARG_WITH([tools-dir], [AS_HELP_STRING([--with-tools-dir], - [alias for --with-toolchain-path for backwards compatibility])], - [BASIC_PREPEND_TO_PATH([TOOLCHAIN_PATH],$with_tools_dir)] - ) - - AC_ARG_WITH([toolchain-path], [AS_HELP_STRING([--with-toolchain-path], - [prepend these directories when searching for toolchain binaries (compilers etc)])], - [BASIC_PREPEND_TO_PATH([TOOLCHAIN_PATH],$with_toolchain_path)] - ) - - AC_ARG_WITH([extra-path], [AS_HELP_STRING([--with-extra-path], - [prepend these directories to the default path])], - [BASIC_PREPEND_TO_PATH([EXTRA_PATH],$with_extra_path)] - ) - - if test "x$OPENJDK_BUILD_OS" = "xmacosx"; then - # If a devkit has been supplied, find xcodebuild in the toolchain_path. - # If not, detect if Xcode is installed by running xcodebuild -version - # if no Xcode installed, xcodebuild exits with 1 - # if Xcode is installed, even if xcode-select is misconfigured, then it exits with 0 - if test "x$DEVKIT_ROOT" != x || /usr/bin/xcodebuild -version >/dev/null 2>&1; then - # We need to use xcodebuild in the toolchain dir provided by the user, this will - # fall back on the stub binary in /usr/bin/xcodebuild - AC_PATH_PROG([XCODEBUILD], [xcodebuild], [/usr/bin/xcodebuild], [$TOOLCHAIN_PATH]) - else - # this should result in SYSROOT being empty, unless --with-sysroot is provided - # when only the command line tools are installed there are no SDKs, so headers - # are copied into the system frameworks - XCODEBUILD= - AC_SUBST(XCODEBUILD) - fi - - AC_MSG_CHECKING([for sdk name]) - AC_ARG_WITH([sdk-name], [AS_HELP_STRING([--with-sdk-name], - [use the platform SDK of the given name. @<:@macosx@:>@])], - [SDKNAME=$with_sdk_name] - ) - AC_MSG_RESULT([$SDKNAME]) - - # if toolchain path is specified then don't rely on system headers, they may not compile - HAVE_SYSTEM_FRAMEWORK_HEADERS=0 - test -z "$TOOLCHAIN_PATH" && \ - HAVE_SYSTEM_FRAMEWORK_HEADERS=`test ! -f /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h; echo $?` - - if test -z "$SYSROOT"; then - if test -n "$XCODEBUILD"; then - # if we don't have system headers, use default SDK name (last resort) - if test -z "$SDKNAME" -a $HAVE_SYSTEM_FRAMEWORK_HEADERS -eq 0; then - SDKNAME=${SDKNAME:-macosx} - fi - - if test -n "$SDKNAME"; then - # Call xcodebuild to determine SYSROOT - SYSROOT=`"$XCODEBUILD" -sdk $SDKNAME -version | $GREP '^Path: ' | $SED 's/Path: //'` - fi - else - if test $HAVE_SYSTEM_FRAMEWORK_HEADERS -eq 0; then - AC_MSG_ERROR([No xcodebuild tool and no system framework headers found, use --with-sysroot or --with-sdk-name to provide a path to a valid SDK]) - fi - fi - else - # warn user if --with-sdk-name was also set - if test -n "$with_sdk_name"; then - AC_MSG_WARN([Both SYSROOT and --with-sdk-name are set, only SYSROOT will be used]) - fi - fi - - if test $HAVE_SYSTEM_FRAMEWORK_HEADERS -eq 0 -a -z "$SYSROOT"; then - # If no system framework headers, then SYSROOT must be set, or we won't build - AC_MSG_ERROR([Unable to determine SYSROOT and no headers found in /System/Library/Frameworks. Check Xcode configuration, --with-sysroot or --with-sdk-name arguments.]) - fi - - # Perform a basic sanity test - if test ! -f "$SYSROOT/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h"; then - if test -z "$SYSROOT"; then - AC_MSG_ERROR([Unable to find required framework headers, provide a path to an SDK via --with-sysroot or --with-sdk-name and be sure Xcode is installed properly]) - else - AC_MSG_ERROR([Invalid SDK or SYSROOT path, dependent framework headers not found]) - fi - fi - - # set SDKROOT too, Xcode tools will pick it up - SDKROOT="$SYSROOT" - AC_SUBST(SDKROOT) - fi - - # Prepend the extra path to the global path - BASIC_PREPEND_TO_PATH([PATH],$EXTRA_PATH) - - AC_MSG_CHECKING([for sysroot]) - AC_MSG_RESULT([$SYSROOT]) - AC_MSG_CHECKING([for toolchain path]) - AC_MSG_RESULT([$TOOLCHAIN_PATH]) - AC_MSG_CHECKING([for extra path]) - AC_MSG_RESULT([$EXTRA_PATH]) -]) - -############################################################################### -AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR], -[ - - AC_ARG_WITH(conf-name, [AS_HELP_STRING([--with-conf-name], - [use this as the name of the configuration @<:@generated from important configuration options@:>@])], - [ CONF_NAME=${with_conf_name} ]) - - # Test from where we are running configure, in or outside of src root. - AC_MSG_CHECKING([where to store configuration]) - if test "x$CONFIGURE_START_DIR" = "x$TOPDIR" \ - || test "x$CONFIGURE_START_DIR" = "x$CUSTOM_ROOT" \ - || test "x$CONFIGURE_START_DIR" = "x$TOPDIR/make/autoconf" \ - || test "x$CONFIGURE_START_DIR" = "x$TOPDIR/make" ; then - # We are running configure from the src root. - # Create a default ./build/target-variant-debuglevel output root. - if test "x${CONF_NAME}" = x; then - AC_MSG_RESULT([in default location]) - CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JVM_VARIANTS_WITH_AND}-${DEBUG_LEVEL}" - else - AC_MSG_RESULT([in build directory with custom name]) - fi - - if test "x$CUSTOM_ROOT" != x; then - WORKSPACE_ROOT="${CUSTOM_ROOT}" - else - WORKSPACE_ROOT="${TOPDIR}" - fi - OUTPUTDIR="${WORKSPACE_ROOT}/build/${CONF_NAME}" - $MKDIR -p "$OUTPUTDIR" - if test ! -d "$OUTPUTDIR"; then - AC_MSG_ERROR([Could not create build directory $OUTPUTDIR]) - fi - else - # We are running configure from outside of the src dir. - # Then use the current directory as output dir! - # If configuration is situated in normal build directory, just use the build - # directory name as configuration name, otherwise use the complete path. - if test "x${CONF_NAME}" = x; then - CONF_NAME=`$ECHO $CONFIGURE_START_DIR | $SED -e "s!^${TOPDIR}/build/!!"` - fi - OUTPUTDIR="$CONFIGURE_START_DIR" - AC_MSG_RESULT([in current directory]) - - # WARNING: This might be a bad thing to do. You need to be sure you want to - # have a configuration in this directory. Do some sanity checks! - - if test ! -e "$OUTPUTDIR/spec.gmk"; then - # If we have a spec.gmk, we have run here before and we are OK. Otherwise, check for - # other files - files_present=`$LS $OUTPUTDIR` - # Configure has already touched config.log and confdefs.h in the current dir when this check - # is performed. - filtered_files=`$ECHO "$files_present" \ - | $SED -e 's/config.log//g' \ - -e 's/configure.log//g' \ - -e 's/confdefs.h//g' \ - -e 's/configure-support//g' \ - -e 's/ //g' \ - | $TR -d '\n'` - if test "x$filtered_files" != x; then - AC_MSG_NOTICE([Current directory is $CONFIGURE_START_DIR.]) - AC_MSG_NOTICE([Since this is not the source root, configure will output the configuration here]) - AC_MSG_NOTICE([(as opposed to creating a configuration in /build/).]) - AC_MSG_NOTICE([However, this directory is not empty. This is not allowed, since it could]) - AC_MSG_NOTICE([seriously mess up just about everything.]) - AC_MSG_NOTICE([Try 'cd $TOPDIR' and restart configure]) - AC_MSG_NOTICE([(or create a new empty directory and cd to it).]) - AC_MSG_ERROR([Will not continue creating configuration in $CONFIGURE_START_DIR]) - fi - fi - fi - AC_MSG_CHECKING([what configuration name to use]) - AC_MSG_RESULT([$CONF_NAME]) - - BASIC_FIXUP_PATH(OUTPUTDIR) - - CONFIGURESUPPORT_OUTPUTDIR="$OUTPUTDIR/configure-support" - $MKDIR -p "$CONFIGURESUPPORT_OUTPUTDIR" - - SPEC="$OUTPUTDIR/spec.gmk" - AC_SUBST(SPEC) - AC_SUBST(CONF_NAME) - AC_SUBST(OUTPUTDIR) - AC_SUBST(WORKSPACE_ROOT) - AC_SUBST(CONFIGURESUPPORT_OUTPUTDIR) - - # The spec.gmk file contains all variables for the make system. - AC_CONFIG_FILES([$OUTPUTDIR/spec.gmk:$AUTOCONF_DIR/spec.gmk.in]) - # The bootcycle-spec.gmk file contains support for boot cycle builds. - AC_CONFIG_FILES([$OUTPUTDIR/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in]) - # The buildjdk-spec.gmk file contains support for building a buildjdk when cross compiling. - AC_CONFIG_FILES([$OUTPUTDIR/buildjdk-spec.gmk:$AUTOCONF_DIR/buildjdk-spec.gmk.in]) - # The compare.sh is used to compare the build output to other builds. - AC_CONFIG_FILES([$OUTPUTDIR/compare.sh:$AUTOCONF_DIR/compare.sh.in]) - # The generated Makefile knows where the spec.gmk is and where the source is. - # You can run make from the OUTPUTDIR, or from the top-level Makefile - # which will look for generated configurations - AC_CONFIG_FILES([$OUTPUTDIR/Makefile:$AUTOCONF_DIR/Makefile.in]) -]) - -#%%% Simple tools %%% - -############################################################################### -# Check if we have found a usable version of make -# $1: the path to a potential make binary (or empty) -# $2: the description on how we found this -AC_DEFUN([BASIC_CHECK_MAKE_VERSION], -[ - MAKE_CANDIDATE="$1" - DESCRIPTION="$2" - - # On Cygwin, we require a newer version of make than on other platforms - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - MAKE_VERSION_EXPR="-e 4\." - MAKE_REQUIRED_VERSION="4.0" - else - MAKE_VERSION_EXPR="-e 3\.8[[12]] -e 4\." - MAKE_REQUIRED_VERSION="3.81" - fi - - if test "x$MAKE_CANDIDATE" != x; then - AC_MSG_NOTICE([Testing potential make at $MAKE_CANDIDATE, found using $DESCRIPTION]) - MAKE_VERSION_STRING=`$MAKE_CANDIDATE --version | $HEAD -n 1` - IS_GNU_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP 'GNU Make'` - if test "x$IS_GNU_MAKE" = x; then - AC_MSG_NOTICE([Found potential make at $MAKE_CANDIDATE, however, this is not GNU Make. Ignoring.]) - else - IS_MODERN_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP $MAKE_VERSION_EXPR` - if test "x$IS_MODERN_MAKE" = x; then - AC_MSG_NOTICE([Found GNU make at $MAKE_CANDIDATE, however this is not version $MAKE_REQUIRED_VERSION or later. (it is: $MAKE_VERSION_STRING). Ignoring.]) - else - if test "x$OPENJDK_BUILD_OS" = "xwindows"; then - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - MAKE_EXPECTED_ENV='cygwin' - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - MAKE_EXPECTED_ENV='msys' - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then - MAKE_EXPECTED_ENV='x86_64-.*-linux-gnu' - else - AC_MSG_ERROR([Unknown Windows environment]) - fi - MAKE_BUILT_FOR=`$MAKE_CANDIDATE --version | $GREP -i 'built for'` - IS_MAKE_CORRECT_ENV=`$ECHO $MAKE_BUILT_FOR | $GREP $MAKE_EXPECTED_ENV` - else - # Not relevant for non-Windows - IS_MAKE_CORRECT_ENV=true - fi - if test "x$IS_MAKE_CORRECT_ENV" = x; then - AC_MSG_NOTICE([Found GNU make version $MAKE_VERSION_STRING at $MAKE_CANDIDATE, but it is not for $MAKE_EXPECTED_ENV (it says: $MAKE_BUILT_FOR). Ignoring.]) - else - FOUND_MAKE=$MAKE_CANDIDATE - BASIC_FIXUP_EXECUTABLE(FOUND_MAKE) - fi - fi - fi - fi -]) - -############################################################################### -AC_DEFUN([BASIC_CHECK_MAKE_OUTPUT_SYNC], -[ - # Check if make supports the output sync option and if so, setup using it. - AC_MSG_CHECKING([if make --output-sync is supported]) - if $MAKE --version -O > /dev/null 2>&1; then - OUTPUT_SYNC_SUPPORTED=true - AC_MSG_RESULT([yes]) - AC_MSG_CHECKING([for output-sync value]) - AC_ARG_WITH([output-sync], [AS_HELP_STRING([--with-output-sync], - [set make output sync type if supported by make. @<:@recurse@:>@])], - [OUTPUT_SYNC=$with_output_sync]) - if test "x$OUTPUT_SYNC" = "x"; then - OUTPUT_SYNC=none - fi - AC_MSG_RESULT([$OUTPUT_SYNC]) - if ! $MAKE --version -O$OUTPUT_SYNC > /dev/null 2>&1; then - AC_MSG_ERROR([Make did not the support the value $OUTPUT_SYNC as output sync type.]) - fi - else - OUTPUT_SYNC_SUPPORTED=false - AC_MSG_RESULT([no]) - fi - AC_SUBST(OUTPUT_SYNC_SUPPORTED) - AC_SUBST(OUTPUT_SYNC) -]) - -############################################################################### -# Goes looking for a usable version of GNU make. -AC_DEFUN([BASIC_CHECK_GNU_MAKE], -[ - BASIC_SETUP_TOOL([MAKE], - [ - # Try our hardest to locate a correct version of GNU make - AC_PATH_PROGS(CHECK_GMAKE, gmake) - BASIC_CHECK_MAKE_VERSION("$CHECK_GMAKE", [gmake in PATH]) - - if test "x$FOUND_MAKE" = x; then - AC_PATH_PROGS(CHECK_MAKE, make) - BASIC_CHECK_MAKE_VERSION("$CHECK_MAKE", [make in PATH]) - fi - - if test "x$FOUND_MAKE" = x; then - if test "x$TOOLCHAIN_PATH" != x; then - # We have a toolchain path, check that as well before giving up. - OLD_PATH=$PATH - PATH=$TOOLCHAIN_PATH:$PATH - AC_PATH_PROGS(CHECK_TOOLSDIR_GMAKE, gmake) - BASIC_CHECK_MAKE_VERSION("$CHECK_TOOLSDIR_GMAKE", [gmake in tools-dir]) - if test "x$FOUND_MAKE" = x; then - AC_PATH_PROGS(CHECK_TOOLSDIR_MAKE, make) - BASIC_CHECK_MAKE_VERSION("$CHECK_TOOLSDIR_MAKE", [make in tools-dir]) - fi - PATH=$OLD_PATH - fi - fi - - if test "x$FOUND_MAKE" = x; then - AC_MSG_ERROR([Cannot find GNU make $MAKE_REQUIRED_VERSION or newer! Please put it in the path, or add e.g. MAKE=/opt/gmake3.81/make as argument to configure.]) - fi - ],[ - # If MAKE was set by user, verify the version - BASIC_CHECK_MAKE_VERSION("$MAKE", [user supplied MAKE=$MAKE]) - if test "x$FOUND_MAKE" = x; then - AC_MSG_ERROR([The specified make (by MAKE=$MAKE) is not GNU make $MAKE_REQUIRED_VERSION or newer.]) - fi - ]) - - MAKE=$FOUND_MAKE - AC_SUBST(MAKE) - AC_MSG_NOTICE([Using GNU make at $FOUND_MAKE (version: $MAKE_VERSION_STRING)]) - - BASIC_CHECK_MAKE_OUTPUT_SYNC -]) - -############################################################################### -AC_DEFUN([BASIC_CHECK_FIND_DELETE], -[ - # Test if find supports -delete - AC_MSG_CHECKING([if find supports -delete]) - FIND_DELETE="-delete" - - DELETEDIR=`$MKTEMP -d tmp.XXXXXXXXXX` || (echo Could not create temporary directory!; exit $?) - - echo Hejsan > $DELETEDIR/TestIfFindSupportsDelete - - TEST_DELETE=`$FIND "$DELETEDIR" -name TestIfFindSupportsDelete $FIND_DELETE 2>&1` - if test -f $DELETEDIR/TestIfFindSupportsDelete; then - # No, it does not. - $RM $DELETEDIR/TestIfFindSupportsDelete - if test "x$OPENJDK_TARGET_OS" = "xaix"; then - # AIX 'find' is buggy if called with '-exec {} \+' and an empty file list - FIND_DELETE="-print | $XARGS $RM" - else - FIND_DELETE="-exec $RM \{\} \+" - fi - AC_MSG_RESULT([no]) - else - AC_MSG_RESULT([yes]) - fi - $RMDIR $DELETEDIR - AC_SUBST(FIND_DELETE) -]) - -############################################################################### -AC_DEFUN([BASIC_CHECK_TAR], -[ - # Test which kind of tar was found - if test "x$($TAR --version | $GREP "GNU tar")" != "x"; then - TAR_TYPE="gnu" - elif test "x$($TAR --version | $GREP "bsdtar")" != "x"; then - TAR_TYPE="bsd" - elif test "x$($TAR -v | $GREP "bsdtar")" != "x"; then - TAR_TYPE="bsd" - elif test "x$OPENJDK_BUILD_OS" = "xsolaris"; then - TAR_TYPE="solaris" - elif test "x$OPENJDK_BUILD_OS" = "xaix"; then - TAR_TYPE="aix" - fi - AC_MSG_CHECKING([what type of tar was found]) - AC_MSG_RESULT([$TAR_TYPE]) - - TAR_CREATE_FILE_PARAM="" - - if test "x$TAR_TYPE" = "xgnu"; then - TAR_INCLUDE_PARAM="T" - TAR_SUPPORTS_TRANSFORM="true" - if test "x$OPENJDK_TARGET_OS" = "xsolaris"; then - # When using gnu tar for Solaris targets, need to use compatibility mode - TAR_CREATE_EXTRA_PARAM="--format=ustar" - fi - elif test "x$TAR_TYPE" = "aix"; then - # -L InputList of aix tar: name of file listing the files and directories - # that need to be archived or extracted - TAR_INCLUDE_PARAM="L" - TAR_SUPPORTS_TRANSFORM="false" - else - TAR_INCLUDE_PARAM="I" - TAR_SUPPORTS_TRANSFORM="false" - fi - AC_SUBST(TAR_TYPE) - AC_SUBST(TAR_CREATE_EXTRA_PARAM) - AC_SUBST(TAR_INCLUDE_PARAM) - AC_SUBST(TAR_SUPPORTS_TRANSFORM) -]) - -############################################################################### -AC_DEFUN([BASIC_CHECK_GREP], -[ - # Test that grep supports -Fx with a list of pattern which includes null pattern. - # This is a problem for the grep resident on AIX. - AC_MSG_CHECKING([that grep ($GREP) -Fx handles empty lines in the pattern list correctly]) - # Multiple subsequent spaces.. - STACK_SPACES='aaa bbb ccc' - # ..converted to subsequent newlines, causes STACK_LIST to be a list with some empty - # patterns in it. - STACK_LIST=${STACK_SPACES// /$'\n'} - NEEDLE_SPACES='ccc bbb aaa' - NEEDLE_LIST=${NEEDLE_SPACES// /$'\n'} - RESULT="$($GREP -Fvx "$STACK_LIST" <<< "$NEEDLE_LIST")" - if test "x$RESULT" == "x"; then - AC_MSG_RESULT([yes]) - else - if test "x$OPENJDK_TARGET_OS" = "xaix"; then - ADDINFO="Please make sure you use GNU grep, usually found at /opt/freeware/bin." - fi - AC_MSG_ERROR([grep does not handle -Fx correctly. ${ADDINFO}]) - fi -]) - -############################################################################### -AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS], -[ - BASIC_CHECK_GNU_MAKE - - BASIC_CHECK_FIND_DELETE - BASIC_CHECK_TAR - BASIC_CHECK_GREP - BASIC_SETUP_PANDOC - - # These tools might not be installed by default, - # need hint on how to install them. - BASIC_REQUIRE_PROGS(UNZIP, unzip) - # Since zip uses "ZIP" as a environment variable for passing options, we need - # to name our variable differently, hence ZIPEXE. - BASIC_REQUIRE_PROGS(ZIPEXE, zip) - - # Non-required basic tools - - BASIC_PATH_PROGS(LDD, ldd) - if test "x$LDD" = "x"; then - # List shared lib dependencies is used for - # debug output and checking for forbidden dependencies. - # We can build without it. - LDD="true" - fi - BASIC_PATH_PROGS(READELF, [greadelf readelf]) - BASIC_PATH_PROGS(DOT, dot) - BASIC_PATH_PROGS(HG, hg) - BASIC_PATH_PROGS(GIT, git) - BASIC_PATH_PROGS(STAT, stat) - BASIC_PATH_PROGS(TIME, time) - BASIC_PATH_PROGS(FLOCK, flock) - # Dtrace is usually found in /usr/sbin on Solaris, but that directory may not - # be in the user path. - BASIC_PATH_PROGS(DTRACE, dtrace, $PATH:/usr/sbin) - BASIC_PATH_PROGS(PATCH, [gpatch patch]) - # Check if it's GNU time - IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'` - if test "x$IS_GNU_TIME" != x; then - IS_GNU_TIME=yes - else - IS_GNU_TIME=no - fi - AC_SUBST(IS_GNU_TIME) - - if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then - BASIC_REQUIRE_PROGS(DSYMUTIL, dsymutil) - BASIC_REQUIRE_PROGS(MIG, mig) - BASIC_REQUIRE_PROGS(XATTR, xattr) - BASIC_PATH_PROGS(CODESIGN, codesign) - - if test "x$CODESIGN" != "x"; then - # Check for user provided code signing identity. - # If no identity was provided, fall back to "openjdk_codesign". - AC_ARG_WITH([macosx-codesign-identity], [AS_HELP_STRING([--with-macosx-codesign-identity], - [specify the code signing identity])], - [MACOSX_CODESIGN_IDENTITY=$with_macosx_codesign_identity], - [MACOSX_CODESIGN_IDENTITY=openjdk_codesign] - ) - - AC_SUBST(MACOSX_CODESIGN_IDENTITY) - - # Verify that the codesign certificate is present - AC_MSG_CHECKING([if codesign certificate is present]) - $RM codesign-testfile - $TOUCH codesign-testfile - $CODESIGN -s "$MACOSX_CODESIGN_IDENTITY" codesign-testfile 2>&AS_MESSAGE_LOG_FD >&AS_MESSAGE_LOG_FD || CODESIGN= - $RM codesign-testfile - if test "x$CODESIGN" = x; then - AC_MSG_RESULT([no]) - else - AC_MSG_RESULT([yes]) - fi - fi - BASIC_REQUIRE_PROGS(SETFILE, SetFile) - elif test "x$OPENJDK_TARGET_OS" = "xsolaris"; then - BASIC_REQUIRE_PROGS(ELFEDIT, elfedit) - fi - if ! test "x$OPENJDK_TARGET_OS" = "xwindows"; then - BASIC_REQUIRE_BUILTIN_PROGS(ULIMIT, ulimit) - fi -]) - -############################################################################### -# Check if build directory is on local disk. If not possible to determine, -# we prefer to claim it's local. -# Argument 1: directory to test -# Argument 2: what to do if it is on local disk -# Argument 3: what to do otherwise (remote disk or failure) -AC_DEFUN([BASIC_CHECK_DIR_ON_LOCAL_DISK], -[ - # df -l lists only local disks; if the given directory is not found then - # a non-zero exit code is given - if test "x$DF" = x; then - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - # msys does not have df; use Windows "net use" instead. - IS_NETWORK_DISK=`net use | grep \`pwd -W | cut -d ":" -f 1 | tr a-z A-Z\`:` - if test "x$IS_NETWORK_DISK" = x; then - $2 - else - $3 - fi - else - # No df here, say it's local - $2 - fi - else - # JDK-8189619 - # df on AIX does not understand -l. On modern AIXes it understands "-T local" which - # is the same. On older AIXes we just continue to live with a "not local build" warning. - if test "x$OPENJDK_TARGET_OS" = xaix; then - DF_LOCAL_ONLY_OPTION='-T local' - else - DF_LOCAL_ONLY_OPTION='-l' - fi - if $DF $DF_LOCAL_ONLY_OPTION $1 > /dev/null 2>&1; then - $2 - else - # In WSL, local Windows drives are considered remote by df, but we are - # required to build into a directory accessible from windows, so consider - # them local here. - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then - if $DF $1 | $GREP -q "^[[A-Z]]:"; then - $2 - else - $3 - fi - else - $3 - fi - fi - fi -]) - -############################################################################### -# Check that source files have basic read permissions set. This might -# not be the case in cygwin in certain conditions. -AC_DEFUN_ONCE([BASIC_CHECK_SRC_PERMS], -[ - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - file_to_test="$TOPDIR/LICENSE" - if test `$STAT -c '%a' "$file_to_test"` -lt 400; then - AC_MSG_ERROR([Bad file permissions on src files. This is usually caused by cloning the repositories with a non cygwin hg in a directory not created in cygwin.]) - fi - fi -]) - -############################################################################### -AC_DEFUN_ONCE([BASIC_TEST_USABILITY_ISSUES], -[ - AC_MSG_CHECKING([if build directory is on local disk]) - BASIC_CHECK_DIR_ON_LOCAL_DISK($OUTPUTDIR, - [OUTPUT_DIR_IS_LOCAL="yes"], - [OUTPUT_DIR_IS_LOCAL="no"]) - AC_MSG_RESULT($OUTPUT_DIR_IS_LOCAL) - - BASIC_CHECK_SRC_PERMS - - # Check if the user has any old-style ALT_ variables set. - FOUND_ALT_VARIABLES=`env | grep ^ALT_` - - # Before generating output files, test if they exist. If they do, this is a reconfigure. - # Since we can't properly handle the dependencies for this, warn the user about the situation - if test -e $OUTPUTDIR/spec.gmk; then - IS_RECONFIGURE=yes - else - IS_RECONFIGURE=no - fi -]) - -############################################################################### -# Check for support for specific options in bash -AC_DEFUN_ONCE([BASIC_CHECK_BASH_OPTIONS], -[ - # Check bash version - # Extra [ ] to stop m4 mangling - [ BASH_VER=`$BASH --version | $SED -n -e 's/^.*bash.*ersion *\([0-9.]*\).*$/\1/ p'` ] - AC_MSG_CHECKING([bash version]) - AC_MSG_RESULT([$BASH_VER]) - - BASH_MAJOR=`$ECHO $BASH_VER | $CUT -d . -f 1` - BASH_MINOR=`$ECHO $BASH_VER | $CUT -d . -f 2` - if test $BASH_MAJOR -lt 3 || (test $BASH_MAJOR -eq 3 && test $BASH_MINOR -lt 2); then - AC_MSG_ERROR([bash version 3.2 or better is required]) - fi - - # Test if bash supports pipefail. - AC_MSG_CHECKING([if bash supports pipefail]) - if ${BASH} -c 'set -o pipefail'; then - BASH_ARGS="$BASH_ARGS -o pipefail" - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - - AC_MSG_CHECKING([if bash supports errexit (-e)]) - if ${BASH} -e -c 'true'; then - BASH_ARGS="$BASH_ARGS -e" - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - - AC_SUBST(BASH_ARGS) -]) - -################################################################################ -# -# Setup Pandoc -# -AC_DEFUN_ONCE([BASIC_SETUP_PANDOC], -[ - BASIC_PATH_PROGS(PANDOC, pandoc) - - PANDOC_MARKDOWN_FLAG="markdown" - if test -n "$PANDOC"; then - AC_MSG_CHECKING(if the pandoc smart extension needs to be disabled for markdown) - if $PANDOC --list-extensions | $GREP -q '\+smart'; then - AC_MSG_RESULT([yes]) - PANDOC_MARKDOWN_FLAG="markdown-smart" - else - AC_MSG_RESULT([no]) - fi - fi - - if test -n "$PANDOC"; then - ENABLE_PANDOC="true" - else - ENABLE_PANDOC="false" - fi - AC_SUBST(ENABLE_PANDOC) - AC_SUBST(PANDOC_MARKDOWN_FLAG) -]) - -################################################################################ -# -# Default make target -# -AC_DEFUN_ONCE([BASIC_SETUP_DEFAULT_MAKE_TARGET], -[ - AC_ARG_WITH(default-make-target, [AS_HELP_STRING([--with-default-make-target], - [set the default make target @<:@exploded-image@:>@])]) - if test "x$with_default_make_target" = "x" \ - || test "x$with_default_make_target" = "xyes"; then - DEFAULT_MAKE_TARGET="exploded-image" - elif test "x$with_default_make_target" = "xno"; then - AC_MSG_ERROR([--without-default-make-target is not a valid option]) - else - DEFAULT_MAKE_TARGET="$with_default_make_target" - fi - - AC_SUBST(DEFAULT_MAKE_TARGET) -]) - -############################################################################### -# Setup the default value for LOG= -# -AC_DEFUN_ONCE([BASIC_SETUP_DEFAULT_LOG], -[ - AC_ARG_WITH(log, [AS_HELP_STRING([--with-log], - [[default vaue for make LOG argument [warn]]])]) - AC_MSG_CHECKING([for default LOG value]) - if test "x$with_log" = x; then - DEFAULT_LOG="" - else - # Syntax for valid LOG options is a bit too complex for it to be worth - # implementing a test for correctness in configure. Just accept it. - DEFAULT_LOG=$with_log - fi - AC_MSG_RESULT([$DEFAULT_LOG]) - AC_SUBST(DEFAULT_LOG) -]) - -############################################################################### -# Code to run after AC_OUTPUT -AC_DEFUN_ONCE([BASIC_POST_CONFIG_OUTPUT], -[ - # Try to move config.log (generated by autoconf) to the configure-support directory. - if test -e ./config.log; then - $MV -f ./config.log "$CONFIGURESUPPORT_OUTPUTDIR/config.log" 2> /dev/null - fi - - # Rotate our log file (configure.log) - if test -e "$OUTPUTDIR/configure.log.old"; then - $RM -f "$OUTPUTDIR/configure.log.old" - fi - if test -e "$OUTPUTDIR/configure.log"; then - $MV -f "$OUTPUTDIR/configure.log" "$OUTPUTDIR/configure.log.old" 2> /dev/null - fi - - # Move configure.log from current directory to the build output root - if test -e ./configure.log; then - $MV -f ./configure.log "$OUTPUTDIR/configure.log" 2> /dev/null - fi - - # Make the compare script executable - $CHMOD +x $OUTPUTDIR/compare.sh -]) diff --git a/make/autoconf/boot-jdk.m4 b/make/autoconf/boot-jdk.m4 index 8aa2547f429..841f0e9bbe7 100644 --- a/make/autoconf/boot-jdk.m4 +++ b/make/autoconf/boot-jdk.m4 @@ -97,7 +97,7 @@ AC_DEFUN([BOOTJDK_DO_CHECK], else # We're done! :-) BOOT_JDK_FOUND=yes - BASIC_FIXUP_PATH(BOOT_JDK) + UTIL_FIXUP_PATH(BOOT_JDK) AC_MSG_CHECKING([for Boot JDK]) AC_MSG_RESULT([$BOOT_JDK]) AC_MSG_CHECKING([Boot JDK version]) @@ -150,7 +150,7 @@ AC_DEFUN([BOOTJDK_CHECK_JAVA_HOME], [ if test "x$JAVA_HOME" != x; then JAVA_HOME_PROCESSED="$JAVA_HOME" - BASIC_FIXUP_PATH(JAVA_HOME_PROCESSED) + UTIL_FIXUP_PATH(JAVA_HOME_PROCESSED) if test ! -d "$JAVA_HOME_PROCESSED"; then AC_MSG_NOTICE([Your JAVA_HOME points to a non-existing directory!]) else @@ -177,7 +177,7 @@ AC_DEFUN([BOOTJDK_CHECK_JAVA_IN_PATH_IS_SYMLINK], # Lets find the JDK/JRE directory by following symbolic links. # Linux/GNU systems often have links from /usr/bin/java to # /etc/alternatives/java to the real JDK binary. - BASIC_REMOVE_SYMBOLIC_LINKS(BINARY) + UTIL_REMOVE_SYMBOLIC_LINKS(BINARY) BOOT_JDK=`dirname "$BINARY"` BOOT_JDK=`cd "$BOOT_JDK/.."; pwd` if test -x "$BOOT_JDK/bin/javac" && test -x "$BOOT_JDK/bin/java"; then @@ -241,7 +241,7 @@ AC_DEFUN([BOOTJDK_FIND_BEST_JDK_IN_WINDOWS_VIRTUAL_DIRECTORY], [ if test "x[$]$1" != x; then VIRTUAL_DIR="[$]$1/Java" - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(VIRTUAL_DIR) + UTIL_REWRITE_AS_UNIX_PATH(VIRTUAL_DIR) BOOTJDK_FIND_BEST_JDK_IN_DIRECTORY($VIRTUAL_DIR) fi ]) @@ -269,7 +269,7 @@ AC_DEFUN([BOOTJDK_CHECK_WELL_KNOWN_LOCATIONS], AC_DEFUN([BOOTJDK_CHECK_TOOL_IN_BOOTJDK], [ # Use user overridden value if available, otherwise locate tool in the Boot JDK. - BASIC_SETUP_TOOL($1, + UTIL_SETUP_TOOL($1, [ AC_MSG_CHECKING([for $2 in Boot JDK]) $1=$BOOT_JDK/bin/$2 @@ -362,7 +362,7 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK], # Try to enable CDS AC_MSG_CHECKING([for local Boot JDK Class Data Sharing (CDS)]) BOOT_JDK_CDS_ARCHIVE=$CONFIGURESUPPORT_OUTPUTDIR/classes.jsa - ADD_JVM_ARG_IF_OK([-XX:+UnlockDiagnosticVMOptions -XX:-VerifySharedSpaces -XX:SharedArchiveFile=$BOOT_JDK_CDS_ARCHIVE],boot_jdk_cds_args,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-XX:+UnlockDiagnosticVMOptions -XX:-VerifySharedSpaces -XX:SharedArchiveFile=$BOOT_JDK_CDS_ARCHIVE],boot_jdk_cds_args,[$JAVA]) if test "x$boot_jdk_cds_args" != x; then # Try creating a CDS archive @@ -391,18 +391,18 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS], AC_MSG_CHECKING([flags for boot jdk java command] ) # Force en-US environment - ADD_JVM_ARG_IF_OK([-Duser.language=en -Duser.country=US],boot_jdk_jvmargs,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-Duser.language=en -Duser.country=US],boot_jdk_jvmargs,[$JAVA]) if test "x$BOOTJDK_USE_LOCAL_CDS" = xtrue; then # Use our own CDS archive - ADD_JVM_ARG_IF_OK([$boot_jdk_cds_args -Xshare:auto],boot_jdk_jvmargs,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([$boot_jdk_cds_args -Xshare:auto],boot_jdk_jvmargs,[$JAVA]) else # Otherwise optimistically use the system-wide one, if one is present - ADD_JVM_ARG_IF_OK([-Xshare:auto],boot_jdk_jvmargs,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-Xshare:auto],boot_jdk_jvmargs,[$JAVA]) fi # Finally append user provided options to allow them to override. - ADD_JVM_ARG_IF_OK([$USER_BOOT_JDK_OPTIONS],boot_jdk_jvmargs,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([$USER_BOOT_JDK_OPTIONS],boot_jdk_jvmargs,[$JAVA]) AC_MSG_RESULT([$boot_jdk_jvmargs]) @@ -413,7 +413,7 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS], AC_MSG_CHECKING([flags for boot jdk java command for big workloads]) # Starting amount of heap memory. - ADD_JVM_ARG_IF_OK([-Xms64M],boot_jdk_jvmargs_big,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-Xms64M],boot_jdk_jvmargs_big,[$JAVA]) BOOTCYCLE_JVM_ARGS_BIG=-Xms64M # Maximum amount of heap memory and stack size. @@ -441,8 +441,8 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS], STACK_SIZE=$STACK_SIZE_64 JVM_MAX_HEAP=$JVM_HEAP_LIMIT_64 fi - ADD_JVM_ARG_IF_OK([-Xmx${JVM_MAX_HEAP}M],boot_jdk_jvmargs_big,[$JAVA]) - ADD_JVM_ARG_IF_OK([-XX:ThreadStackSize=$STACK_SIZE],boot_jdk_jvmargs_big,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-Xmx${JVM_MAX_HEAP}M],boot_jdk_jvmargs_big,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-XX:ThreadStackSize=$STACK_SIZE],boot_jdk_jvmargs_big,[$JAVA]) AC_MSG_RESULT([$boot_jdk_jvmargs_big]) @@ -469,10 +469,10 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS], AC_MSG_CHECKING([flags for boot jdk java command for small workloads]) # Use serial gc for small short lived tools if possible - ADD_JVM_ARG_IF_OK([-XX:+UseSerialGC],boot_jdk_jvmargs_small,[$JAVA]) - ADD_JVM_ARG_IF_OK([-Xms32M],boot_jdk_jvmargs_small,[$JAVA]) - ADD_JVM_ARG_IF_OK([-Xmx512M],boot_jdk_jvmargs_small,[$JAVA]) - ADD_JVM_ARG_IF_OK([-XX:TieredStopAtLevel=1],boot_jdk_jvmargs_small,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-XX:+UseSerialGC],boot_jdk_jvmargs_small,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-Xms32M],boot_jdk_jvmargs_small,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-Xmx512M],boot_jdk_jvmargs_small,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-XX:TieredStopAtLevel=1],boot_jdk_jvmargs_small,[$JAVA]) AC_MSG_RESULT([$boot_jdk_jvmargs_small]) @@ -531,7 +531,7 @@ AC_DEFUN([BOOTJDK_CHECK_BUILD_JDK], else # We're done! BUILD_JDK_FOUND=yes - BASIC_FIXUP_PATH(BUILD_JDK) + UTIL_FIXUP_PATH(BUILD_JDK) AC_MSG_CHECKING([for Build JDK]) AC_MSG_RESULT([$BUILD_JDK]) AC_MSG_CHECKING([Build JDK version]) diff --git a/make/autoconf/build-performance.m4 b/make/autoconf/build-performance.m4 index dbda3abe597..9ec19c2643c 100644 --- a/make/autoconf/build-performance.m4 +++ b/make/autoconf/build-performance.m4 @@ -180,7 +180,7 @@ AC_DEFUN([BPERF_SETUP_CCACHE], if test "x$TOOLCHAIN_PATH" != x; then PATH=$TOOLCHAIN_PATH:$PATH fi - BASIC_REQUIRE_PROGS(CCACHE, ccache) + UTIL_REQUIRE_PROGS(CCACHE, ccache) PATH="$OLD_PATH" CCACHE_VERSION=[`$CCACHE --version | head -n1 | $SED 's/[A-Za-z ]*//'`] CCACHE_STATUS="Active ($CCACHE_VERSION)" @@ -288,12 +288,12 @@ AC_DEFUN([BPERF_SETUP_ICECC], [enable distribted compilation of native code using icecc/icecream @<:@disabled@:>@])]) if test "x${enable_icecc}" = "xyes"; then - BASIC_REQUIRE_PROGS(ICECC_CMD, icecc) + UTIL_REQUIRE_PROGS(ICECC_CMD, icecc) old_path="$PATH" # Look for icecc-create-env in some known places PATH="$PATH:/usr/lib/icecc:/usr/lib64/icecc" - BASIC_REQUIRE_PROGS(ICECC_CREATE_ENV, icecc-create-env) + UTIL_REQUIRE_PROGS(ICECC_CREATE_ENV, icecc-create-env) # Use icecc-create-env to create a minimal compilation environment that can # be sent to the other hosts in the icecream cluster. icecc_create_env_log="${CONFIGURESUPPORT_OUTPUTDIR}/icecc/icecc_create_env.log" @@ -308,7 +308,7 @@ AC_DEFUN([BPERF_SETUP_ICECC], elif test "x$TOOLCHAIN_TYPE" = "xclang"; then # For clang, the icecc compilerwrapper is needed. It usually resides next # to icecc-create-env. - BASIC_REQUIRE_PROGS(ICECC_WRAPPER, compilerwrapper) + UTIL_REQUIRE_PROGS(ICECC_WRAPPER, compilerwrapper) BPERF_RUN_ICECC_CREATE_ENV([--clang ${CC} ${ICECC_WRAPPER}], ${icecc_create_env_log}) else AC_MSG_ERROR([Can only create icecc compiler packages for toolchain types gcc and clang]) @@ -442,7 +442,7 @@ AC_DEFUN_ONCE([BPERF_SETUP_SMART_JAVAC], if test "$MX_VALUE" -lt "512"; then MX_VALUE=512 fi - ADD_JVM_ARG_IF_OK([-Xms${MS_VALUE}M -Xmx${MX_VALUE}M],SJAVAC_SERVER_JAVA_FLAGS,[$SJAVAC_SERVER_JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-Xms${MS_VALUE}M -Xmx${MX_VALUE}M],SJAVAC_SERVER_JAVA_FLAGS,[$SJAVAC_SERVER_JAVA]) AC_SUBST(SJAVAC_SERVER_JAVA_FLAGS) AC_ARG_ENABLE([sjavac], [AS_HELP_STRING([--enable-sjavac], diff --git a/make/autoconf/buildjdk-spec.gmk.in b/make/autoconf/buildjdk-spec.gmk.in index 4cd3165247b..07d2b0b1503 100644 --- a/make/autoconf/buildjdk-spec.gmk.in +++ b/make/autoconf/buildjdk-spec.gmk.in @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -96,6 +96,7 @@ BUILD_GTEST := false JVM_VARIANTS := server JVM_VARIANT_MAIN := server +JVM_FEATURES_server := cds compiler1 compiler2 g1gc serialgc # Some users still set EXTRA_*FLAGS on the make command line. Must # make sure to override that when building buildjdk. diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac index 7ba3ae011cf..decf29accd3 100644 --- a/make/autoconf/configure.ac +++ b/make/autoconf/configure.ac @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -36,10 +36,20 @@ AC_INIT(OpenJDK, openjdk, build-dev@openjdk.java.net,,http://openjdk.java.net) AC_CONFIG_AUX_DIR([$TOPDIR/make/autoconf/build-aux]) m4_include([build-aux/pkg.m4]) +AC_DEFUN_ONCE([CUSTOM_EARLY_HOOK]) +AC_DEFUN_ONCE([CUSTOM_LATE_HOOK]) +AC_DEFUN_ONCE([CUSTOM_CONFIG_OUTPUT_GENERATED_HOOK]) +AC_DEFUN_ONCE([CUSTOM_SUMMARY_AND_WARNINGS_HOOK]) + +# This line needs to be here, verbatim, after the dummy hook definitions but +# before all includes. It is replaced with custom functionality when building +# custom sources. +#CUSTOM_AUTOCONF_INCLUDE + # Include these first... -m4_include([basics.m4]) -m4_include([basics_windows.m4]) +m4_include([util.m4]) # ... then the rest +m4_include([basic.m4]) m4_include([boot-jdk.m4]) m4_include([build-performance.m4]) m4_include([flags.m4]) @@ -47,21 +57,11 @@ m4_include([help.m4]) m4_include([hotspot.m4]) m4_include([jdk-options.m4]) m4_include([jdk-version.m4]) +m4_include([jvm-features.m4]) m4_include([libraries.m4]) m4_include([platform.m4]) m4_include([source-dirs.m4]) m4_include([toolchain.m4]) -m4_include([toolchain_windows.m4]) - -AC_DEFUN_ONCE([CUSTOM_EARLY_HOOK]) -AC_DEFUN_ONCE([CUSTOM_LATE_HOOK]) -AC_DEFUN_ONCE([CUSTOM_CONFIG_OUTPUT_GENERATED_HOOK]) -AC_DEFUN_ONCE([CUSTOM_SUMMARY_AND_WARNINGS_HOOK]) - -# This line needs to be here, verbatim, after all includes and the dummy hook -# definitions. It is replaced with custom functionality when building -# custom sources. -#CUSTOM_AUTOCONF_INCLUDE ############################################################################### # @@ -203,12 +203,6 @@ JDKOPT_SETUP_CODE_COVERAGE # AddressSanitizer JDKOPT_SETUP_ADDRESS_SANITIZER -# Need toolchain to setup dtrace -HOTSPOT_SETUP_DTRACE -HOTSPOT_ENABLE_DISABLE_AOT -HOTSPOT_ENABLE_DISABLE_CDS -HOTSPOT_ENABLE_DISABLE_GTEST - ############################################################################### # # Check dependencies for external and internal libraries. @@ -221,9 +215,17 @@ BASIC_COMPILE_FIXPATH LIB_DETERMINE_DEPENDENCIES LIB_SETUP_LIBRARIES -# Hotspot setup depends on lib checks. +############################################################################### +# +# Setup hotspot and JVM features (needs toolchain). +# +############################################################################### -HOTSPOT_SETUP_JVM_FEATURES +JVM_FEATURES_PARSE_OPTIONS +JVM_FEATURES_SETUP + +HOTSPOT_ENABLE_DISABLE_GTEST +HOTSPOT_SETUP_MISC ############################################################################### # @@ -277,9 +279,6 @@ BASIC_TEST_USABILITY_ISSUES # At the end, call the custom hook. (Dummy macro if no custom sources available) CUSTOM_LATE_HOOK -# This needs to be done after CUSTOM_LATE_HOOK since we can setup custom features. -HOTSPOT_FINALIZE_JVM_FEATURES - # Did user specify any unknown variables? BASIC_CHECK_LEFTOVER_OVERRIDDEN diff --git a/make/autoconf/flags.m4 b/make/autoconf/flags.m4 index 131ce7a6338..582cd65d0df 100644 --- a/make/autoconf/flags.m4 +++ b/make/autoconf/flags.m4 @@ -430,7 +430,7 @@ AC_DEFUN([FLAGS_SETUP_FLAGS], # IF_FALSE: [RUN-IF-FALSE]) # ------------------------------------------------------------ # Check that the C compiler supports an argument -BASIC_DEFUN_NAMED([FLAGS_C_COMPILER_CHECK_ARGUMENTS], +UTIL_DEFUN_NAMED([FLAGS_C_COMPILER_CHECK_ARGUMENTS], [*ARGUMENT IF_TRUE IF_FALSE PREFIX], [$@], [ AC_MSG_CHECKING([if ARG_PREFIX[CC] supports "ARG_ARGUMENT"]) @@ -461,7 +461,7 @@ BASIC_DEFUN_NAMED([FLAGS_C_COMPILER_CHECK_ARGUMENTS], # IF_FALSE: [RUN-IF-FALSE]) # ------------------------------------------------------------ # Check that the C++ compiler supports an argument -BASIC_DEFUN_NAMED([FLAGS_CXX_COMPILER_CHECK_ARGUMENTS], +UTIL_DEFUN_NAMED([FLAGS_CXX_COMPILER_CHECK_ARGUMENTS], [*ARGUMENT IF_TRUE IF_FALSE PREFIX], [$@], [ AC_MSG_CHECKING([if ARG_PREFIX[CXX] supports "ARG_ARGUMENT"]) @@ -492,7 +492,7 @@ BASIC_DEFUN_NAMED([FLAGS_CXX_COMPILER_CHECK_ARGUMENTS], # IF_FALSE: [RUN-IF-FALSE]) # ------------------------------------------------------------ # Check that the C and C++ compilers support an argument -BASIC_DEFUN_NAMED([FLAGS_COMPILER_CHECK_ARGUMENTS], +UTIL_DEFUN_NAMED([FLAGS_COMPILER_CHECK_ARGUMENTS], [*ARGUMENT IF_TRUE IF_FALSE PREFIX], [$@], [ FLAGS_C_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [ARG_ARGUMENT], @@ -524,7 +524,7 @@ BASIC_DEFUN_NAMED([FLAGS_COMPILER_CHECK_ARGUMENTS], # IF_FALSE: [RUN-IF-FALSE]) # ------------------------------------------------------------ # Check that the linker support an argument -BASIC_DEFUN_NAMED([FLAGS_LINKER_CHECK_ARGUMENTS], +UTIL_DEFUN_NAMED([FLAGS_LINKER_CHECK_ARGUMENTS], [*ARGUMENT IF_TRUE IF_FALSE], [$@], [ AC_MSG_CHECKING([if linker supports "ARG_ARGUMENT"]) diff --git a/make/autoconf/help.m4 b/make/autoconf/help.m4 index 36b00c0b492..7507cd4c93e 100644 --- a/make/autoconf/help.m4 +++ b/make/autoconf/help.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -180,21 +180,25 @@ AC_DEFUN_ONCE([HELP_PRINT_ADDITIONAL_HELP_AND_EXIT], if test "x$CONFIGURE_PRINT_ADDITIONAL_HELP" != x; then # Print available toolchains - $PRINTF "The following toolchains are available as arguments to --with-toolchain-type.\n" - $PRINTF "Which are valid to use depends on the build platform.\n" + $PRINTF "The following toolchains are valid as arguments to --with-toolchain-type.\n" + $PRINTF "Which are available to use depends on the build platform.\n" for toolchain in $VALID_TOOLCHAINS_all; do # Use indirect variable referencing toolchain_var_name=TOOLCHAIN_DESCRIPTION_$toolchain TOOLCHAIN_DESCRIPTION=${!toolchain_var_name} - $PRINTF " %-10s %s\n" $toolchain "$TOOLCHAIN_DESCRIPTION" + $PRINTF " %-22s %s\n" $toolchain "$TOOLCHAIN_DESCRIPTION" done $PRINTF "\n" - # Print available jvm features - $PRINTF "The following JVM features are available as arguments to --with-jvm-features.\n" - $PRINTF "Which are valid to use depends on the target platform.\n " - $PRINTF "%s " $VALID_JVM_FEATURES - $PRINTF "\n" + # Print available JVM features + $PRINTF "The following JVM features are valid as arguments to --with-jvm-features.\n" + $PRINTF "Which are available to use depends on the environment and JVM variant.\n" + m4_foreach(FEATURE, m4_split(jvm_features_valid), [ + # Create an m4 variable containing the description for FEATURE. + m4_define(FEATURE_DESCRIPTION, [jvm_feature_desc_]m4_translit(FEATURE, -, _)) + $PRINTF " %-22s %s\n" FEATURE "FEATURE_DESCRIPTION" + m4_undefine([FEATURE_DESCRIPTION]) + ]) # And now exit directly exit 0 diff --git a/make/autoconf/hotspot.m4 b/make/autoconf/hotspot.m4 index d9005341058..91507bc0261 100644 --- a/make/autoconf/hotspot.m4 +++ b/make/autoconf/hotspot.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,14 +23,6 @@ # questions. # -# All valid JVM features, regardless of platform -VALID_JVM_FEATURES="compiler1 compiler2 zero minimal dtrace jvmti jvmci \ - graal vm-structs jni-check services management epsilongc g1gc parallelgc serialgc shenandoahgc zgc nmt cds \ - static-build link-time-opt aot jfr" - -# Deprecated JVM features (these are ignored, but with a warning) -DEPRECATED_JVM_FEATURES="trace cmsgc" - # All valid JVM variants VALID_JVM_VARIANTS="server client minimal core zero custom" @@ -46,32 +38,6 @@ VALID_JVM_VARIANTS="server client minimal core zero custom" AC_DEFUN([HOTSPOT_CHECK_JVM_VARIANT], [ [ [[ " $JVM_VARIANTS " =~ " $1 " ]] ] ]) -############################################################################### -# Check if the specified JVM feature is enabled. To be used in shell if -# constructs, like this: -# if HOTSPOT_CHECK_JVM_FEATURE(jvmti); then -# -# Only valid to use after HOTSPOT_SETUP_JVM_FEATURES has setup features. - -# Definition kept in one line to allow inlining in if statements. -# Additional [] needed to keep m4 from mangling shell constructs. -AC_DEFUN([HOTSPOT_CHECK_JVM_FEATURE], -[ [ [[ " $JVM_FEATURES " =~ " $1 " ]] ] ]) - -############################################################################### -# Check if the specified JVM feature is explicitly disabled. To be used in -# shell if constructs, like this: -# if HOTSPOT_IS_JVM_FEATURE_DISABLED(jvmci); then -# -# This function is internal to hotspot.m4, and is only used when constructing -# the valid set of enabled JVM features. Users outside of hotspot.m4 should just -# use HOTSPOT_CHECK_JVM_FEATURE to check if a feature is enabled or not. - -# Definition kept in one line to allow inlining in if statements. -# Additional [] needed to keep m4 from mangling shell constructs. -AC_DEFUN([HOTSPOT_IS_JVM_FEATURE_DISABLED], -[ [ [[ " $DISABLED_JVM_FEATURES " =~ " $1 " ]] ] ]) - ############################################################################### # Check which variants of the JVM that we want to build. Available variants are: # server: normal interpreter, and a tiered C1/C2 compiler @@ -84,7 +50,8 @@ AC_DEFUN([HOTSPOT_IS_JVM_FEATURE_DISABLED], AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_VARIANTS], [ AC_ARG_WITH([jvm-variants], [AS_HELP_STRING([--with-jvm-variants], - [JVM variants (separated by commas) to build (server,client,minimal,core,zero,custom) @<:@server@:>@])]) + [JVM variants to build, separated by commas (server client minimal core + zero custom) @<:@server@:>@])]) if test "x$with_jvm_variants" = x; then with_jvm_variants="server" @@ -108,7 +75,8 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_VARIANTS], AC_MSG_RESULT([$JVM_VARIANTS]) # Check that the selected variants are valid - BASIC_GET_NON_MATCHING_VALUES(INVALID_VARIANTS, $JVM_VARIANTS, $VALID_JVM_VARIANTS) + UTIL_GET_NON_MATCHING_VALUES(INVALID_VARIANTS, $JVM_VARIANTS, \ + $VALID_JVM_VARIANTS) if test "x$INVALID_VARIANTS" != x; then AC_MSG_NOTICE([Unknown variant(s) specified: "$INVALID_VARIANTS"]) AC_MSG_NOTICE([The available JVM variants are: "$VALID_JVM_VARIANTS"]) @@ -117,9 +85,11 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_VARIANTS], # All "special" variants share the same output directory ("server") VALID_MULTIPLE_JVM_VARIANTS="server client minimal" - BASIC_GET_NON_MATCHING_VALUES(INVALID_MULTIPLE_VARIANTS, $JVM_VARIANTS, $VALID_MULTIPLE_JVM_VARIANTS) - if test "x$INVALID_MULTIPLE_VARIANTS" != x && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xtrue; then - AC_MSG_ERROR([You cannot build multiple variants with anything else than $VALID_MULTIPLE_JVM_VARIANTS.]) + UTIL_GET_NON_MATCHING_VALUES(INVALID_MULTIPLE_VARIANTS, $JVM_VARIANTS, \ + $VALID_MULTIPLE_JVM_VARIANTS) + if test "x$INVALID_MULTIPLE_VARIANTS" != x && \ + test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xtrue; then + AC_MSG_ERROR([You can only build multiple variants using these variants: '$VALID_MULTIPLE_JVM_VARIANTS']) fi # The "main" variant is the one used by other libs to link against during the @@ -139,473 +109,9 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_VARIANTS], AC_SUBST(JVM_VARIANTS) AC_SUBST(VALID_JVM_VARIANTS) AC_SUBST(JVM_VARIANT_MAIN) - - if HOTSPOT_CHECK_JVM_VARIANT(zero); then - # zero behaves as a platform and rewrites these values. This is really weird. :( - # We are guaranteed that we do not build any other variants when building zero. - HOTSPOT_TARGET_CPU=zero - HOTSPOT_TARGET_CPU_ARCH=zero - fi ]) ############################################################################### -# Check if dtrace should be enabled and has all prerequisites present. -# -AC_DEFUN_ONCE([HOTSPOT_SETUP_DTRACE], -[ - # Test for dtrace dependencies - AC_ARG_ENABLE([dtrace], [AS_HELP_STRING([--enable-dtrace@<:@=yes/no/auto@:>@], - [enable dtrace. Default is auto, where dtrace is enabled if all dependencies - are present.])]) - - DTRACE_DEP_MISSING=false - - AC_MSG_CHECKING([for dtrace tool]) - if test "x$DTRACE" != "x" && test -x "$DTRACE"; then - AC_MSG_RESULT([$DTRACE]) - else - AC_MSG_RESULT([not found, cannot build dtrace]) - DTRACE_DEP_MISSING=true - fi - - AC_CHECK_HEADERS([sys/sdt.h], [DTRACE_HEADERS_OK=yes],[DTRACE_HEADERS_OK=no]) - if test "x$DTRACE_HEADERS_OK" != "xyes"; then - DTRACE_DEP_MISSING=true - fi - - AC_MSG_CHECKING([if dtrace should be built]) - if test "x$enable_dtrace" = "xyes"; then - if test "x$DTRACE_DEP_MISSING" = "xtrue"; then - AC_MSG_RESULT([no, missing dependencies]) - HELP_MSG_MISSING_DEPENDENCY([dtrace]) - AC_MSG_ERROR([Cannot enable dtrace with missing dependencies. See above. $HELP_MSG]) - else - INCLUDE_DTRACE=true - AC_MSG_RESULT([yes, forced]) - fi - elif test "x$enable_dtrace" = "xno"; then - INCLUDE_DTRACE=false - AC_MSG_RESULT([no, forced]) - elif test "x$enable_dtrace" = "xauto" || test "x$enable_dtrace" = "x"; then - if test "x$DTRACE_DEP_MISSING" = "xtrue"; then - INCLUDE_DTRACE=false - AC_MSG_RESULT([no, missing dependencies]) - else - INCLUDE_DTRACE=true - AC_MSG_RESULT([yes, dependencies present]) - fi - else - AC_MSG_ERROR([Invalid value for --enable-dtrace: $enable_dtrace]) - fi -]) - -################################################################################ -# Check if AOT should be enabled -# -AC_DEFUN_ONCE([HOTSPOT_ENABLE_DISABLE_AOT], -[ - AC_ARG_ENABLE([aot], [AS_HELP_STRING([--enable-aot@<:@=yes/no/auto@:>@], - [enable ahead of time compilation feature. Default is auto, where aot is enabled if all dependencies are present.])]) - - if test "x$enable_aot" = "x" || test "x$enable_aot" = "xauto"; then - ENABLE_AOT="true" - elif test "x$enable_aot" = "xyes"; then - ENABLE_AOT="true" - elif test "x$enable_aot" = "xno"; then - ENABLE_AOT="false" - else - AC_MSG_ERROR([Invalid value for --enable-aot: $enable_aot]) - fi - - if test "x$ENABLE_AOT" = "xtrue"; then - # Only enable AOT on X64 platforms. - if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then - if test -e "${TOPDIR}/src/jdk.aot"; then - if test -e "${TOPDIR}/src/jdk.internal.vm.compiler"; then - ENABLE_AOT="true" - else - ENABLE_AOT="false" - if test "x$enable_aot" = "xyes"; then - AC_MSG_ERROR([Cannot build AOT without src/jdk.internal.vm.compiler sources. Remove --enable-aot.]) - fi - fi - else - ENABLE_AOT="false" - if test "x$enable_aot" = "xyes"; then - AC_MSG_ERROR([Cannot build AOT without src/jdk.aot sources. Remove --enable-aot.]) - fi - fi - else - ENABLE_AOT="false" - if test "x$enable_aot" = "xyes"; then - AC_MSG_ERROR([AOT is currently only supported on x86_64 and aarch64. Remove --enable-aot.]) - fi - fi - fi - - AC_SUBST(ENABLE_AOT) -]) - -################################################################################ -# Allow to disable CDS -# -AC_DEFUN_ONCE([HOTSPOT_ENABLE_DISABLE_CDS], -[ - AC_ARG_ENABLE([cds], [AS_HELP_STRING([--enable-cds@<:@=yes/no/auto@:>@], - [enable class data sharing feature in non-minimal VM. Default is auto, where cds is enabled if supported on the platform.])]) - - if test "x$enable_cds" = "x" || test "x$enable_cds" = "xauto"; then - ENABLE_CDS="true" - elif test "x$enable_cds" = "xyes"; then - ENABLE_CDS="true" - elif test "x$enable_cds" = "xno"; then - ENABLE_CDS="false" - else - AC_MSG_ERROR([Invalid value for --enable-cds: $enable_cds]) - fi - - AC_SUBST(ENABLE_CDS) -]) - -############################################################################### -# Set up all JVM features for each JVM variant. -# -AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES], -[ - # Prettify the VALID_JVM_FEATURES string - BASIC_SORT_LIST(VALID_JVM_FEATURES, $VALID_JVM_FEATURES) - - # The user can in some cases supply additional jvm features. For the custom - # variant, this defines the entire variant. - AC_ARG_WITH([jvm-features], [AS_HELP_STRING([--with-jvm-features], - [JVM features to enable (foo) or disable (-foo), separated by comma. Use '--help' to show possible values @<:@none@:>@])]) - if test "x$with_jvm_features" != x; then - AC_MSG_CHECKING([user specified JVM feature list]) - USER_JVM_FEATURE_LIST=`$ECHO $with_jvm_features | $SED -e 's/,/ /g'` - AC_MSG_RESULT([$user_jvm_feature_list]) - # These features will be added to all variant defaults - JVM_FEATURES=`$ECHO $USER_JVM_FEATURE_LIST | $AWK '{ for (i=1; i<=NF; i++) if (!match($i, /^-.*/)) printf("%s ", $i) }'` - # These features will be removed from all variant defaults - DISABLED_JVM_FEATURES=`$ECHO $USER_JVM_FEATURE_LIST | $AWK '{ for (i=1; i<=NF; i++) if (match($i, /^-.*/)) printf("%s ", substr($i, 2))}'` - - # Verify that the user has provided valid features - BASIC_GET_NON_MATCHING_VALUES(INVALID_FEATURES, $JVM_FEATURES $DISABLED_JVM_FEATURES, $VALID_JVM_FEATURES $DEPRECATED_JVM_FEATURES) - if test "x$INVALID_FEATURES" != x; then - AC_MSG_NOTICE([Unknown JVM features specified: "$INVALID_FEATURES"]) - AC_MSG_NOTICE([The available JVM features are: "$VALID_JVM_FEATURES"]) - AC_MSG_ERROR([Cannot continue]) - fi - - # Check if the user has provided deprecated features - BASIC_GET_MATCHING_VALUES(DEPRECATED_FEATURES, $JVM_FEATURES $DISABLED_JVM_FEATURES, $DEPRECATED_JVM_FEATURES) - if test "x$DEPRECATED_FEATURES" != x; then - AC_MSG_WARN([Deprecated JVM features specified (will be ignored): "$DEPRECATED_FEATURES"]) - # Filter out deprecated features - BASIC_GET_NON_MATCHING_VALUES(JVM_FEATURES, $JVM_FEATURES, $DEPRECATED_FEATURES) - BASIC_GET_NON_MATCHING_VALUES(DISABLED_JVM_FEATURES, $DISABLED_JVM_FEATURES, $DEPRECATED_FEATURES) - fi - - fi - - # Override hotspot cpu definitions for ARM platforms - if test "x$OPENJDK_TARGET_CPU" = xarm; then - HOTSPOT_TARGET_CPU=arm_32 - HOTSPOT_TARGET_CPU_DEFINE="ARM32" - fi - - # Verify that dependencies are met for explicitly set features. - if HOTSPOT_CHECK_JVM_FEATURE(jvmti) && ! HOTSPOT_CHECK_JVM_FEATURE(services); then - AC_MSG_ERROR([Specified JVM feature 'jvmti' requires feature 'services']) - fi - - if HOTSPOT_CHECK_JVM_FEATURE(management) && ! HOTSPOT_CHECK_JVM_FEATURE(nmt); then - AC_MSG_ERROR([Specified JVM feature 'management' requires feature 'nmt']) - fi - - if HOTSPOT_CHECK_JVM_FEATURE(jvmci) && ! (HOTSPOT_CHECK_JVM_FEATURE(compiler1) || HOTSPOT_CHECK_JVM_FEATURE(compiler2)); then - AC_MSG_ERROR([Specified JVM feature 'jvmci' requires feature 'compiler2' or 'compiler1']) - fi - - # Enable JFR by default, except for Zero, linux-sparcv9 and on minimal. - if ! HOTSPOT_CHECK_JVM_VARIANT(zero); then - if test "x$OPENJDK_TARGET_OS" != xaix; then - if test "x$OPENJDK_TARGET_OS" != xlinux || test "x$OPENJDK_TARGET_CPU" != xsparcv9; then - NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES jfr" - fi - fi - fi - - # Only enable Shenandoah on supported arches - AC_MSG_CHECKING([if shenandoah can be built]) - if test "x$OPENJDK_TARGET_CPU_ARCH" = "xx86" || test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then - AC_MSG_RESULT([yes]) - else - DISABLED_JVM_FEATURES="$DISABLED_JVM_FEATURES shenandoahgc" - AC_MSG_RESULT([no, platform not supported]) - fi - - # Only enable ZGC on supported platforms - if (test "x$OPENJDK_TARGET_OS" = "xwindows" && test "x$OPENJDK_TARGET_CPU" = "xx86_64"); then - AC_MSG_CHECKING([if zgc can be built on windows]) - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([[#include ]], - [[struct MEM_EXTENDED_PARAMETER x;]]) - ], - [ - AC_MSG_RESULT([yes]) - CAN_BUILD_ZGC_ON_WINDOWS="yes" - ], - [ - AC_MSG_RESULT([no, missing required APIs]) - CAN_BUILD_ZGC_ON_WINDOWS="no" - ] - ) - fi - - AC_MSG_CHECKING([if zgc can be built]) - if (test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xx86_64") || \ - (test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xaarch64") || \ - (test "x$CAN_BUILD_ZGC_ON_WINDOWS" = "xyes") || \ - (test "x$OPENJDK_TARGET_OS" = "xmacosx" && test "x$OPENJDK_TARGET_CPU" = "xx86_64"); then - AC_MSG_RESULT([yes]) - else - DISABLED_JVM_FEATURES="$DISABLED_JVM_FEATURES zgc" - AC_MSG_RESULT([no, platform not supported]) - fi - - # Disable unsupported GCs for Zero - if HOTSPOT_CHECK_JVM_VARIANT(zero); then - DISABLED_JVM_FEATURES="$DISABLED_JVM_FEATURES epsilongc g1gc zgc shenandoahgc" - fi - - # Turn on additional features based on other parts of configure - if test "x$INCLUDE_DTRACE" = "xtrue"; then - JVM_FEATURES="$JVM_FEATURES dtrace" - else - if HOTSPOT_CHECK_JVM_FEATURE(dtrace); then - AC_MSG_ERROR([To enable dtrace, you must use --enable-dtrace]) - fi - fi - - if test "x$STATIC_BUILD" = "xtrue"; then - JVM_FEATURES="$JVM_FEATURES static-build" - else - if HOTSPOT_CHECK_JVM_FEATURE(static-build); then - AC_MSG_ERROR([To enable static-build, you must use --enable-static-build]) - fi - fi - - if ! HOTSPOT_CHECK_JVM_VARIANT(zero); then - if HOTSPOT_CHECK_JVM_FEATURE(zero); then - AC_MSG_ERROR([To enable zero, you must use --with-jvm-variants=zero]) - fi - fi - - AC_MSG_CHECKING([if jvmci module jdk.internal.vm.ci should be built]) - # Check if jvmci is diabled - if HOTSPOT_IS_JVM_FEATURE_DISABLED(jvmci); then - AC_MSG_RESULT([no, forced]) - JVM_FEATURES_jvmci="" - INCLUDE_JVMCI="false" - else - # Only enable jvmci on x86_64 and aarch64 - if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || \ - test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then - AC_MSG_RESULT([yes]) - JVM_FEATURES_jvmci="jvmci" - INCLUDE_JVMCI="true" - else - AC_MSG_RESULT([no]) - JVM_FEATURES_jvmci="" - INCLUDE_JVMCI="false" - if HOTSPOT_CHECK_JVM_FEATURE(jvmci); then - AC_MSG_ERROR([JVMCI is currently not supported on this platform.]) - fi - fi - fi - - AC_SUBST(INCLUDE_JVMCI) - - AC_MSG_CHECKING([if graal module jdk.internal.vm.compiler should be built]) - # Check if graal is diabled - if HOTSPOT_IS_JVM_FEATURE_DISABLED(graal); then - AC_MSG_RESULT([no, forced]) - JVM_FEATURES_graal="" - INCLUDE_GRAAL="false" - else - if HOTSPOT_CHECK_JVM_FEATURE(graal); then - AC_MSG_RESULT([yes, forced]) - if test "x$JVM_FEATURES_jvmci" != "xjvmci" ; then - AC_MSG_ERROR([Specified JVM feature 'graal' requires feature 'jvmci']) - fi - JVM_FEATURES_graal="graal" - INCLUDE_GRAAL="true" - else - # By default enable graal build on x64 or where AOT is available. - # graal build requires jvmci. - if test "x$JVM_FEATURES_jvmci" = "xjvmci" && \ - (test "x$OPENJDK_TARGET_CPU" = "xx86_64" || \ - test "x$ENABLE_AOT" = "xtrue") ; then - AC_MSG_RESULT([yes]) - JVM_FEATURES_graal="graal" - INCLUDE_GRAAL="true" - else - AC_MSG_RESULT([no]) - JVM_FEATURES_graal="" - INCLUDE_GRAAL="false" - fi - fi - fi - - AC_SUBST(INCLUDE_GRAAL) - - # Disable aot with '--with-jvm-features=-aot' - if HOTSPOT_IS_JVM_FEATURE_DISABLED(aot); then - ENABLE_AOT="false" - fi - - AC_MSG_CHECKING([if aot should be enabled]) - if test "x$ENABLE_AOT" = "xtrue"; then - if test "x$JVM_FEATURES_graal" != "xgraal"; then - if test "x$enable_aot" = "xyes" || HOTSPOT_CHECK_JVM_FEATURE(aot); then - AC_MSG_RESULT([yes, forced]) - AC_MSG_ERROR([Specified JVM feature 'aot' requires feature 'graal']) - else - AC_MSG_RESULT([no]) - fi - JVM_FEATURES_aot="" - ENABLE_AOT="false" - else - if test "x$enable_aot" = "xyes" || HOTSPOT_CHECK_JVM_FEATURE(aot); then - AC_MSG_RESULT([yes, forced]) - else - AC_MSG_RESULT([yes]) - fi - JVM_FEATURES_aot="aot" - fi - else - if test "x$enable_aot" = "xno" || HOTSPOT_IS_JVM_FEATURE_DISABLED(aot); then - AC_MSG_RESULT([no, forced]) - else - AC_MSG_RESULT([no]) - fi - JVM_FEATURES_aot="" - if HOTSPOT_CHECK_JVM_FEATURE(aot); then - AC_MSG_ERROR([To enable aot, you must use --enable-aot]) - fi - fi - - AC_SUBST(ENABLE_AOT) - - if test "x$OPENJDK_TARGET_CPU" = xarm ; then - # Default to use link time optimizations on minimal on arm - JVM_FEATURES_link_time_opt="link-time-opt" - else - JVM_FEATURES_link_time_opt="" - fi - - # All variants but minimal (and custom) get these features - NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES g1gc parallelgc serialgc epsilongc shenandoahgc jni-check jvmti management nmt services vm-structs zgc" - - # Disable CDS on AIX. - if test "x$OPENJDK_TARGET_OS" = "xaix"; then - ENABLE_CDS="false" - if test "x$enable_cds" = "xyes"; then - AC_MSG_ERROR([CDS is currently not supported on AIX. Remove --enable-cds.]) - fi - fi - - # Disable CDS if user requested it with --with-jvm-features=-cds. - if HOTSPOT_IS_JVM_FEATURE_DISABLED(cds); then - ENABLE_CDS="false" - if test "x$enable_cds" = "xyes"; then - AC_MSG_ERROR([CDS was disabled by --with-jvm-features=-cds. Remove --enable-cds.]) - fi - fi - - if ! HOTSPOT_CHECK_JVM_VARIANT(server) && ! HOTSPOT_CHECK_JVM_VARIANT(client); then - # ..except when the user explicitely requested it with --enable-jvm-features - if ! HOTSPOT_CHECK_JVM_FEATURE(cds); then - ENABLE_CDS="false" - if test "x$enable_cds" = "xyes"; then - AC_MSG_ERROR([CDS not implemented for variants zero, minimal, core. Remove --enable-cds.]) - fi - fi - fi - - AC_MSG_CHECKING([if cds should be enabled]) - if test "x$ENABLE_CDS" = "xtrue"; then - if test "x$enable_cds" = "xyes"; then - AC_MSG_RESULT([yes, forced]) - else - AC_MSG_RESULT([yes]) - fi - NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES cds" - else - if test "x$enable_cds" = "xno"; then - AC_MSG_RESULT([no, forced]) - else - AC_MSG_RESULT([no]) - fi - fi - - # Enable features depending on variant. - JVM_FEATURES_server="compiler1 compiler2 $NON_MINIMAL_FEATURES $JVM_FEATURES $JVM_FEATURES_jvmci $JVM_FEATURES_aot $JVM_FEATURES_graal" - JVM_FEATURES_client="compiler1 $NON_MINIMAL_FEATURES $JVM_FEATURES" - JVM_FEATURES_core="$NON_MINIMAL_FEATURES $JVM_FEATURES" - JVM_FEATURES_minimal="compiler1 minimal serialgc $JVM_FEATURES $JVM_FEATURES_link_time_opt" - JVM_FEATURES_zero="zero $NON_MINIMAL_FEATURES $JVM_FEATURES" - JVM_FEATURES_custom="$JVM_FEATURES" - - AC_SUBST(JVM_FEATURES_server) - AC_SUBST(JVM_FEATURES_client) - AC_SUBST(JVM_FEATURES_core) - AC_SUBST(JVM_FEATURES_minimal) - AC_SUBST(JVM_FEATURES_zero) - AC_SUBST(JVM_FEATURES_custom) - - # Used for verification of Makefiles by check-jvm-feature - AC_SUBST(VALID_JVM_FEATURES) - - # --with-cpu-port is no longer supported - BASIC_DEPRECATED_ARG_WITH(with-cpu-port) -]) - -############################################################################### -# Finalize JVM features once all setup is complete, including custom setup. -# -AC_DEFUN_ONCE([HOTSPOT_FINALIZE_JVM_FEATURES], -[ - for variant in $JVM_VARIANTS; do - AC_MSG_CHECKING([JVM features for JVM variant '$variant']) - features_var_name=JVM_FEATURES_$variant - JVM_FEATURES_FOR_VARIANT=${!features_var_name} - - # Filter out user-requested disabled features - BASIC_GET_NON_MATCHING_VALUES(JVM_FEATURES_FOR_VARIANT, $JVM_FEATURES_FOR_VARIANT, $DISABLED_JVM_FEATURES) - - # Keep feature lists sorted and free of duplicates - BASIC_SORT_LIST(JVM_FEATURES_FOR_VARIANT, $JVM_FEATURES_FOR_VARIANT) - - # Update real feature set variable - eval $features_var_name='"'$JVM_FEATURES_FOR_VARIANT'"' - AC_MSG_RESULT(["$JVM_FEATURES_FOR_VARIANT"]) - - # Verify that we have at least one gc selected - GC_FEATURES=`$ECHO $JVM_FEATURES_FOR_VARIANT | $GREP gc` - if test "x$GC_FEATURES" = x; then - AC_MSG_WARN([Invalid JVM features: No gc selected for variant $variant.]) - fi - - # Validate features (for configure script errors, not user errors) - BASIC_GET_NON_MATCHING_VALUES(INVALID_FEATURES, $JVM_FEATURES_FOR_VARIANT, $VALID_JVM_FEATURES) - if test "x$INVALID_FEATURES" != x; then - AC_MSG_ERROR([Internal configure script error. Invalid JVM feature(s): $INVALID_FEATURES]) - fi - done -]) - -################################################################################ # Check if gtest should be built # AC_DEFUN_ONCE([HOTSPOT_ENABLE_DISABLE_GTEST], @@ -613,25 +119,37 @@ AC_DEFUN_ONCE([HOTSPOT_ENABLE_DISABLE_GTEST], AC_ARG_ENABLE([hotspot-gtest], [AS_HELP_STRING([--disable-hotspot-gtest], [Disables building of the Hotspot unit tests @<:@enabled@:>@])]) + GTEST_AVAILABLE=true + + AC_MSG_CHECKING([if Hotspot gtest test source is present]) if test -e "${TOPDIR}/test/hotspot/gtest"; then - GTEST_DIR_EXISTS="true" + AC_MSG_RESULT([yes]) else - GTEST_DIR_EXISTS="false" + AC_MSG_RESULT([no, cannot run gtest]) + GTEST_AVAILABLE=false + fi + + # On solaris, we also must have the libstlport.so.1 library, setup in + # LIB_SETUP_LIBRARIES. + if test "x$OPENJDK_TARGET_OS" = "xsolaris"; then + if test "x$STLPORT_LIB" = "x"; then + GTEST_AVAILABLE=false + fi fi AC_MSG_CHECKING([if Hotspot gtest unit tests should be built]) if test "x$enable_hotspot_gtest" = "xyes"; then - if test "x$GTEST_DIR_EXISTS" = "xtrue"; then + if test "x$GTEST_AVAILABLE" = "xtrue"; then AC_MSG_RESULT([yes, forced]) BUILD_GTEST="true" else - AC_MSG_ERROR([Cannot build gtest without the test source]) + AC_MSG_ERROR([Cannot build gtest with missing dependencies]) fi elif test "x$enable_hotspot_gtest" = "xno"; then AC_MSG_RESULT([no, forced]) BUILD_GTEST="false" elif test "x$enable_hotspot_gtest" = "x"; then - if test "x$GTEST_DIR_EXISTS" = "xtrue"; then + if test "x$GTEST_AVAILABLE" = "xtrue"; then AC_MSG_RESULT([yes]) BUILD_GTEST="true" else @@ -644,3 +162,25 @@ AC_DEFUN_ONCE([HOTSPOT_ENABLE_DISABLE_GTEST], AC_SUBST(BUILD_GTEST) ]) + +############################################################################### +# Misc hotspot setup that does not fit elsewhere. +# +AC_DEFUN_ONCE([HOTSPOT_SETUP_MISC], +[ + if HOTSPOT_CHECK_JVM_VARIANT(zero); then + # zero behaves as a platform and rewrites these values. This is a bit weird. + # But when building zero, we never build any other variants so it works. + HOTSPOT_TARGET_CPU=zero + HOTSPOT_TARGET_CPU_ARCH=zero + fi + + # Override hotspot cpu definitions for ARM platforms + if test "x$OPENJDK_TARGET_CPU" = xarm; then + HOTSPOT_TARGET_CPU=arm_32 + HOTSPOT_TARGET_CPU_DEFINE="ARM32" + fi + + # --with-cpu-port is no longer supported + UTIL_DEPRECATED_ARG_WITH(with-cpu-port) +]) diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 2fed5c64c67..58980154ea9 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -34,7 +34,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_VARIANT], [ # Deprecated in JDK 12 - BASIC_DEPRECATED_ARG_WITH([jdk-variant]) + UTIL_DEPRECATED_ARG_WITH([jdk-variant]) ]) ############################################################################### @@ -314,7 +314,7 @@ AC_DEFUN_ONCE([JDKOPT_DETECT_INTREE_EC], AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS], [ # - # NATIVE_DEBUG_SYMBOLS + # Native debug symbols. # This must be done after the toolchain is setup, since we're looking at objcopy. # AC_MSG_CHECKING([what type of native debug symbols to use]) @@ -326,11 +326,9 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS], if test "x$withval" = xexternal || test "x$withval" = xzipped; then AC_MSG_ERROR([AIX only supports the parameters 'none' and 'internal' for --with-native-debug-symbols]) fi - else - if test "x$OPENJDK_TARGET_OS" = xwindows; then - if test "x$withval" = xinternal; then - AC_MSG_ERROR([Windows does not support the parameter 'internal' for --with-native-debug-symbols]) - fi + elif test "x$OPENJDK_TARGET_OS" = xwindows; then + if test "x$withval" = xinternal; then + AC_MSG_ERROR([Windows does not support the parameter 'internal' for --with-native-debug-symbols]) fi fi ], @@ -346,18 +344,17 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS], fi fi ]) - NATIVE_DEBUG_SYMBOLS=$with_native_debug_symbols - AC_MSG_RESULT([$NATIVE_DEBUG_SYMBOLS]) + AC_MSG_RESULT([$with_native_debug_symbols]) - if test "x$NATIVE_DEBUG_SYMBOLS" = xnone; then + if test "x$with_native_debug_symbols" = xnone; then COMPILE_WITH_DEBUG_SYMBOLS=false COPY_DEBUG_SYMBOLS=false ZIP_EXTERNAL_DEBUG_SYMBOLS=false - elif test "x$NATIVE_DEBUG_SYMBOLS" = xinternal; then + elif test "x$with_native_debug_symbols" = xinternal; then COMPILE_WITH_DEBUG_SYMBOLS=true COPY_DEBUG_SYMBOLS=false ZIP_EXTERNAL_DEBUG_SYMBOLS=false - elif test "x$NATIVE_DEBUG_SYMBOLS" = xexternal; then + elif test "x$with_native_debug_symbols" = xexternal; then if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; then if test "x$OBJCOPY" = x; then @@ -370,7 +367,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS], COMPILE_WITH_DEBUG_SYMBOLS=true COPY_DEBUG_SYMBOLS=true ZIP_EXTERNAL_DEBUG_SYMBOLS=false - elif test "x$NATIVE_DEBUG_SYMBOLS" = xzipped; then + elif test "x$with_native_debug_symbols" = xzipped; then if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; then if test "x$OBJCOPY" = x; then @@ -390,6 +387,33 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS], AC_SUBST(COMPILE_WITH_DEBUG_SYMBOLS) AC_SUBST(COPY_DEBUG_SYMBOLS) AC_SUBST(ZIP_EXTERNAL_DEBUG_SYMBOLS) + + # Should we add external native debug symbols to the shipped bundles? + AC_MSG_CHECKING([if we should add external native debug symbols to the shipped bundles]) + AC_ARG_WITH([external-symbols-in-bundles], + [AS_HELP_STRING([--with-external-symbols-in-bundles], + [which type of external native debug symbol information shall be shipped in product bundles (none, public, full) + (e.g. ship full/stripped pdbs on Windows) @<:@none@:>@])]) + + if test "x$with_external_symbols_in_bundles" = x || test "x$with_external_symbols_in_bundles" = xnone ; then + AC_MSG_RESULT([no]) + elif test "x$with_external_symbols_in_bundles" = xfull || test "x$with_external_symbols_in_bundles" = xpublic ; then + if test "x$OPENJDK_TARGET_OS" != xwindows ; then + AC_MSG_ERROR([--with-external-symbols-in-bundles currently only works on windows!]) + elif test "x$COPY_DEBUG_SYMBOLS" != xtrue ; then + AC_MSG_ERROR([--with-external-symbols-in-bundles only works when --with-native-debug-symbols=external is used!]) + elif test "x$with_external_symbols_in_bundles" = xfull ; then + AC_MSG_RESULT([full]) + SHIP_DEBUG_SYMBOLS=full + else + AC_MSG_RESULT([public]) + SHIP_DEBUG_SYMBOLS=public + fi + else + AC_MSG_ERROR([$with_external_symbols_in_bundles is an unknown value for --with-external-symbols-in-bundles]) + fi + + AC_SUBST(SHIP_DEBUG_SYMBOLS) ]) ################################################################################ @@ -449,14 +473,14 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_CODE_COVERAGE], AC_MSG_ERROR([Invalid JCov bundle: "$JCOV_HOME/lib/jcov.jar" does not exist]) fi JCOV_ENABLED="true" - BASIC_FIXUP_PATH(JCOV_HOME) + UTIL_FIXUP_PATH(JCOV_HOME) if test "x$with_jcov_input_jdk" != "x" ; then JCOV_INPUT_JDK="$with_jcov_input_jdk" if test ! -f "$JCOV_INPUT_JDK/bin/java$EXE_SUFFIX"; then AC_MSG_RESULT([fail]) AC_MSG_ERROR([Invalid JDK bundle: "$JCOV_INPUT_JDK/bin/java$EXE_SUFFIX" does not exist]) fi - BASIC_FIXUP_PATH(JCOV_INPUT_JDK) + UTIL_FIXUP_PATH(JCOV_INPUT_JDK) fi if test "x$with_jcov_filters" != "x" ; then JCOV_FILTERS="$with_jcov_filters" @@ -616,33 +640,24 @@ AC_DEFUN_ONCE([JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST], Default is to generate it when either the server or client JVMs are built and enable-cds is true.])]) - # Check if it's likely that it's possible to generate the classlist. Depending - # on exact jvm configuration it could be possible anyway. - if test "x$ENABLE_CDS" = "xtrue" && (HOTSPOT_CHECK_JVM_VARIANT(server) || HOTSPOT_CHECK_JVM_VARIANT(client) || HOTSPOT_CHECK_JVM_FEATURE(cds)); then - ENABLE_GENERATE_CLASSLIST_POSSIBLE="true" - else - ENABLE_GENERATE_CLASSLIST_POSSIBLE="false" - fi + # In jvm-features.m4 ENABLE_CDS is set to true iff all JVM variants has cds + # enabled. AC_MSG_CHECKING([if the CDS classlist generation should be enabled]) if test "x$enable_generate_classlist" = "xyes"; then AC_MSG_RESULT([yes, forced]) ENABLE_GENERATE_CLASSLIST="true" - if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xfalse"; then - if test "x$ENABLE_CDS" = "xfalse"; then - # In GenerateLinkOptData.gmk, DumpLoadedClassList is used to generate the - # classlist file. It never will work in this case since the VM will report - # an error for DumpLoadedClassList when CDS is disabled. - AC_MSG_ERROR([Generation of classlist is not possible with enable-cds=false]) - else - AC_MSG_WARN([Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS and enable-cds=$ENABLE_CDS]) - fi + if test "x$ENABLE_CDS" = "xfalse"; then + # In GenerateLinkOptData.gmk, DumpLoadedClassList is used to generate the + # classlist file. It never will work in this case since the VM will report + # an error for DumpLoadedClassList when CDS is disabled. + AC_MSG_ERROR([Generation of classlist is not possible without JVM feature 'cds']) fi elif test "x$enable_generate_classlist" = "xno"; then AC_MSG_RESULT([no, forced]) ENABLE_GENERATE_CLASSLIST="false" elif test "x$enable_generate_classlist" = "x"; then - if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xtrue"; then + if test "x$ENABLE_CDS" = "xtrue"; then AC_MSG_RESULT([yes]) ENABLE_GENERATE_CLASSLIST="true" else diff --git a/make/autoconf/jvm-features.m4 b/make/autoconf/jvm-features.m4 new file mode 100644 index 00000000000..9a76bd6a5f3 --- /dev/null +++ b/make/autoconf/jvm-features.m4 @@ -0,0 +1,669 @@ +# +# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +############################################################################### +# Terminology used in this file: +# +# Valid features == All possible features that the JVM knows about. +# Deprecated features == Previously known features (not considered valid). +# Available features == Features that are possible to use in this configuration. +# Default features == Features that are on by default in this configuration. +# Enabled features == Features requested by the user to be present. +# Disabled features == Features excluded from being used by the user. +# Active features == The exact set of features to be used for a JVM variant. +# +# All valid features are considered available, unless listed as unavailable. +# All available features will be turned on as default, unless listed in a filter. +############################################################################### + +# We need these as m4 defines to be able to loop over them using m4 later on. + +# All valid JVM features, regardless of platform +m4_define(jvm_features_valid, m4_normalize( \ + ifdef([custom_jvm_features_valid], custom_jvm_features_valid) \ + \ + aot cds compiler1 compiler2 dtrace epsilongc g1gc graal jfr jni-check \ + jvmci jvmti link-time-opt management minimal nmt opt-size parallelgc \ + serialgc services shenandoahgc static-build vm-structs zero zgc \ +)) + +# Deprecated JVM features (these are ignored, but with a warning) +m4_define(jvm_features_deprecated, m4_normalize( + cmsgc trace \ +)) + +# Feature descriptions +m4_define(jvm_feature_desc_aot, [enable ahead of time compilation (AOT)]) +m4_define(jvm_feature_desc_cds, [enable class data sharing (CDS)]) +m4_define(jvm_feature_desc_compiler1, [enable hotspot compiler C1]) +m4_define(jvm_feature_desc_compiler2, [enable hotspot compiler C2]) +m4_define(jvm_feature_desc_dtrace, [enable dtrace support]) +m4_define(jvm_feature_desc_epsilongc, [include the epsilon (no-op) garbage collector]) +m4_define(jvm_feature_desc_g1gc, [include the G1 garbage collector]) +m4_define(jvm_feature_desc_graal, [enable Graal (jdk.internal.vm.compiler)]) +m4_define(jvm_feature_desc_jfr, [enable JDK Flight Recorder (JFR)]) +m4_define(jvm_feature_desc_jni_check, [enable -Xcheck:jni support]) +m4_define(jvm_feature_desc_jvmci, [enable JVM Compiler Interface (JVMCI)]) +m4_define(jvm_feature_desc_jvmti, [enable Java Virtual Machine Tool Interface (JVM TI)]) +m4_define(jvm_feature_desc_link_time_opt, [enable link time optimization]) +m4_define(jvm_feature_desc_management, [enable java.lang.management API support]) +m4_define(jvm_feature_desc_minimal, [support building variant 'minimal']) +m4_define(jvm_feature_desc_nmt, [include native memory tracking (NMT)]) +m4_define(jvm_feature_desc_opt_size, [optimize the JVM library for size]) +m4_define(jvm_feature_desc_parallelgc, [include the parallel garbage collector]) +m4_define(jvm_feature_desc_serialgc, [include the serial garbage collector]) +m4_define(jvm_feature_desc_services, [enable diagnostic services and client attaching]) +m4_define(jvm_feature_desc_shenandoahgc, [include the Shenandoah garbage collector]) +m4_define(jvm_feature_desc_static_build, [build static library instead of dynamic]) +m4_define(jvm_feature_desc_vm_structs, [export JVM structures to the Serviceablility Agent]) +m4_define(jvm_feature_desc_zero, [support building variant 'zero']) +m4_define(jvm_feature_desc_zgc, [include the Z garbage collector]) + +############################################################################### +# Parse command line options for JVM feature selection. After this function +# has run $JVM_FEATURES_ENABLED, $JVM_FEATURES_DISABLED and $JVM_FEATURES_VALID +# can be used. +# +AC_DEFUN_ONCE([JVM_FEATURES_PARSE_OPTIONS], +[ + # Setup shell variables from the m4 lists + UTIL_SORT_LIST(JVM_FEATURES_VALID, "jvm_features_valid") + UTIL_SORT_LIST(JVM_FEATURES_DEPRECATED, "jvm_features_deprecated") + + # For historical reasons, some jvm features have their own, shorter names. + # Keep those as aliases for the --enable-jvm-feature-* style arguments. + UTIL_ALIASED_ARG_ENABLE(aot, --enable-jvm-feature-aot) + UTIL_ALIASED_ARG_ENABLE(cds, --enable-jvm-feature-cds) + UTIL_ALIASED_ARG_ENABLE(dtrace, --enable-jvm-feature-dtrace) + + # First check for features using the + # --with-jvm-features="<[-]feature>[,<[-]feature> ...]" syntax. + AC_ARG_WITH([jvm-features], [AS_HELP_STRING([--with-jvm-features], + [JVM features to enable (foo) or disable (-foo), separated by comma. Use + '--help' to show possible values @<:@none@:>@])]) + if test "x$with_jvm_features" != x; then + # Replace "," with " ". + user_jvm_feature_list=${with_jvm_features//,/ } + JVM_FEATURES_ENABLED=`$ECHO $user_jvm_feature_list | \ + $AWK '{ for (i=1; i<=NF; i++) if (!match($i, /^-.*/)) printf("%s ", $i) }'` + JVM_FEATURES_DISABLED=`$ECHO $user_jvm_feature_list | \ + $AWK '{ for (i=1; i<=NF; i++) if (match($i, /^-.*/)) printf("%s ", substr($i, 2))}'` + + # Verify that the user has provided only valid (or deprecated) features + UTIL_GET_NON_MATCHING_VALUES(invalid_features, $JVM_FEATURES_ENABLED \ + $JVM_FEATURES_DISABLED, $JVM_FEATURES_VALID $JVM_FEATURES_DEPRECATED) + if test "x$invalid_features" != x; then + AC_MSG_NOTICE([Unknown JVM features specified: '$invalid_features']) + AC_MSG_NOTICE([The available JVM features are: '$JVM_FEATURES_VALID']) + AC_MSG_ERROR([Cannot continue]) + fi + + # Check if the user has provided deprecated features + UTIL_GET_MATCHING_VALUES(deprecated_features, $JVM_FEATURES_ENABLED \ + $JVM_FEATURES_DISABLED, $JVM_FEATURES_DEPRECATED) + if test "x$deprecated_features" != x; then + AC_MSG_WARN([Deprecated JVM features specified (will be ignored): '$deprecated_features']) + # Filter out deprecated features + UTIL_GET_NON_MATCHING_VALUES(JVM_FEATURES_ENABLED, \ + $JVM_FEATURES_ENABLED, $deprecated_features) + UTIL_GET_NON_MATCHING_VALUES(JVM_FEATURES_DISABLED, \ + $JVM_FEATURES_DISABLED, $deprecated_features) + fi + fi + + # Then check for features using the "--enable-jvm-feature-" syntax. + # Using m4, loop over all features with the variable FEATURE. + m4_foreach(FEATURE, m4_split(jvm_features_valid), [ + # Create an m4 variable containing a shell variable name (like + # "enable_jvm_feature_static_build"), and the description. + m4_define(FEATURE_SHELL, [enable_jvm_feature_]m4_translit(FEATURE, -, _)) + m4_define(FEATURE_DESCRIPTION, [jvm_feature_desc_]m4_translit(FEATURE, -, _)) + + AC_ARG_ENABLE(jvm-feature-FEATURE, AS_HELP_STRING( + [--enable-jvm-feature-FEATURE], [enable jvm feature 'FEATURE' (FEATURE_DESCRIPTION)])) + + if test "x$FEATURE_SHELL" = xyes; then + JVM_FEATURES_ENABLED="$JVM_FEATURES_ENABLED FEATURE" + elif test "x$FEATURE_SHELL" = xno; then + JVM_FEATURES_DISABLED="$JVM_FEATURES_DISABLED FEATURE" + elif test "x$FEATURE_SHELL" != x; then + AC_MSG_ERROR([Invalid value for --enable-jvm-feature-FEATURE: '$FEATURE_SHELL']) + fi + + m4_undefine([FEATURE_SHELL]) + m4_undefine([FEATURE_DESCRIPTION]) + ]) + + # Likewise, check for deprecated arguments. + m4_foreach(FEATURE, m4_split(jvm_features_deprecated), [ + AC_ARG_ENABLE(jvm-feature-FEATURE, AS_HELP_STRING( + [--enable-jvm-feature-FEATURE], + [Deprecated. Option is kept for backwards compatibility and is ignored])) + + m4_define(FEATURE_SHELL, [enable_jvm_feature_]m4_translit(FEATURE, -, _)) + + if test "x$FEATURE_SHELL" != x; then + AC_MSG_WARN([Deprecated JVM feature, will be ignored: --enable-jvm-feature-FEATURE]) + fi + + m4_undefine([FEATURE_SHELL]) + ]) + + # Warn if the user has both enabled and disabled a feature + # If this happens, disable will override enable. + UTIL_GET_MATCHING_VALUES(enabled_and_disabled, $JVM_FEATURES_ENABLED, \ + $JVM_FEATURES_DISABLED) + if test "x$enabled_and_disabled" != x; then + AC_MSG_WARN([Disabling of these features will override enabling: '$enabled_and_disabled']) + fi + + # Clean up lists and announce results to user + UTIL_SORT_LIST(JVM_FEATURES_ENABLED, $JVM_FEATURES_ENABLED) + AC_MSG_CHECKING([for JVM features enabled by the user]) + if test "x$JVM_FEATURES_ENABLED" != x; then + AC_MSG_RESULT(['$JVM_FEATURES_ENABLED']) + else + AC_MSG_RESULT([none]) + fi + + UTIL_SORT_LIST(JVM_FEATURES_DISABLED, $JVM_FEATURES_DISABLED) + AC_MSG_CHECKING([for JVM features disabled by the user]) + if test "x$JVM_FEATURES_DISABLED" != x; then + AC_MSG_RESULT(['$JVM_FEATURES_DISABLED']) + else + AC_MSG_RESULT([none]) + fi + + # Makefiles use VALID_JVM_FEATURES in check-jvm-feature to verify correctness. + VALID_JVM_FEATURES="$JVM_FEATURES_VALID" + AC_SUBST(VALID_JVM_FEATURES) +]) + +############################################################################### +# Helper function for the JVM_FEATURES_CHECK_* suite. +# The code in the code block should assign 'false' to the variable AVAILABLE +# if the feature is not available, and this function will handle everything +# else that is needed. +# +# arg 1: The name of the feature to test +# arg 2: The code block to execute +# +AC_DEFUN([JVM_FEATURES_CHECK_AVAILABILITY], +[ + # Assume that feature is available + AVAILABLE=true + + # Execute feature test block + $2 + + AC_MSG_CHECKING([if JVM feature '$1' is available]) + if test "x$AVAILABLE" = "xtrue"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + JVM_FEATURES_PLATFORM_UNAVAILABLE="$JVM_FEATURES_PLATFORM_UNAVAILABLE $1" + fi +]) + +############################################################################### +# Check if the feature 'aot' is available on this platform. +# +AC_DEFUN_ONCE([JVM_FEATURES_CHECK_AOT], +[ + JVM_FEATURES_CHECK_AVAILABILITY(aot, [ + AC_MSG_CHECKING([if platform is supported by AOT]) + # AOT is only available where JVMCI is available since it requires JVMCI. + if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || \ + test "x$OPENJDK_TARGET_CPU" = "xaarch64"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no, $OPENJDK_TARGET_CPU]) + AVAILABLE=false + fi + + AC_MSG_CHECKING([if AOT source code is present]) + if test -e "${TOPDIR}/src/jdk.internal.vm.compiler" && \ + test -e "${TOPDIR}/src/jdk.aot"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no, missing src/jdk.internal.vm.compiler or src/jdk.aot]) + AVAILABLE=false + fi + ]) +]) + +############################################################################### +# Check if the feature 'cds' is available on this platform. +# +AC_DEFUN_ONCE([JVM_FEATURES_CHECK_CDS], +[ + JVM_FEATURES_CHECK_AVAILABILITY(cds, [ + AC_MSG_CHECKING([if platform is supported by CDS]) + if test "x$OPENJDK_TARGET_OS" != xaix; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no, $OPENJDK_TARGET_OS]) + AVAILABLE=false + fi + ]) +]) + +############################################################################### +# Check if the feature 'dtrace' is available on this platform. +# +AC_DEFUN_ONCE([JVM_FEATURES_CHECK_DTRACE], +[ + JVM_FEATURES_CHECK_AVAILABILITY(dtrace, [ + AC_MSG_CHECKING([for dtrace tool]) + if test "x$DTRACE" != "x" && test -x "$DTRACE"; then + AC_MSG_RESULT([$DTRACE]) + else + AC_MSG_RESULT([no]) + AVAILABLE=false + fi + + AC_CHECK_HEADERS([sys/sdt.h], [dtrace_headers_ok=true]) + if test "x$dtrace_headers_ok" != "xtrue"; then + HELP_MSG_MISSING_DEPENDENCY([dtrace]) + AC_MSG_NOTICE([Cannot enable dtrace with missing dependencies. See above.]) + AVAILABLE=false + fi + ]) +]) + +############################################################################### +# Check if the feature 'graal' is available on this platform. +# +AC_DEFUN_ONCE([JVM_FEATURES_CHECK_GRAAL], +[ + JVM_FEATURES_CHECK_AVAILABILITY(graal, [ + AC_MSG_CHECKING([if platform is supported by Graal]) + # Graal is only available where JVMCI is available since it requires JVMCI. + if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || \ + test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no, $OPENJDK_TARGET_CPU]) + AVAILABLE=false + fi + ]) +]) + +############################################################################### +# Check if the feature 'jfr' is available on this platform. +# +AC_DEFUN_ONCE([JVM_FEATURES_CHECK_JFR], +[ + JVM_FEATURES_CHECK_AVAILABILITY(jfr, [ + AC_MSG_CHECKING([if platform is supported by JFR]) + if test "x$OPENJDK_TARGET_OS" = xaix || \ + test "x$OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU" = "xlinux-sparcv9"; then + AC_MSG_RESULT([no, $OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU]) + AVAILABLE=false + else + AC_MSG_RESULT([yes]) + fi + ]) +]) + +############################################################################### +# Check if the feature 'jvmci' is available on this platform. +# +AC_DEFUN_ONCE([JVM_FEATURES_CHECK_JVMCI], +[ + JVM_FEATURES_CHECK_AVAILABILITY(jvmci, [ + AC_MSG_CHECKING([if platform is supported by JVMCI]) + if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || \ + test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no, $OPENJDK_TARGET_CPU]) + AVAILABLE=false + fi + ]) +]) + +############################################################################### +# Check if the feature 'shenandoahgc' is available on this platform. +# +AC_DEFUN_ONCE([JVM_FEATURES_CHECK_SHENANDOAHGC], +[ + JVM_FEATURES_CHECK_AVAILABILITY(shenandoahgc, [ + AC_MSG_CHECKING([if platform is supported by Shenandoah]) + if test "x$OPENJDK_TARGET_CPU_ARCH" = "xx86" || \ + test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no, $OPENJDK_TARGET_CPU]) + AVAILABLE=false + fi + ]) +]) + +############################################################################### +# Check if the feature 'static-build' is available on this platform. +# +AC_DEFUN_ONCE([JVM_FEATURES_CHECK_STATIC_BUILD], +[ + JVM_FEATURES_CHECK_AVAILABILITY(static-build, [ + AC_MSG_CHECKING([if static-build is enabled in configure]) + if test "x$STATIC_BUILD" = "xtrue"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no, use --enable-static-build to enable static build.]) + AVAILABLE=false + fi + ]) +]) + +############################################################################### +# Check if the feature 'zgc' is available on this platform. +# +AC_DEFUN_ONCE([JVM_FEATURES_CHECK_ZGC], +[ + JVM_FEATURES_CHECK_AVAILABILITY(zgc, [ + AC_MSG_CHECKING([if platform is supported by ZGC]) + if test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then + if test "x$OPENJDK_TARGET_OS" = "xlinux" || \ + test "x$OPENJDK_TARGET_OS" = "xwindows" || \ + test "x$OPENJDK_TARGET_OS" = "xmacosx"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no, $OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU]) + AVAILABLE=false + fi + elif test "x$OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU" = "xlinux-aarch64"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no, $OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU]) + AVAILABLE=false + fi + + if test "x$OPENJDK_TARGET_OS" = "xwindows"; then + AC_MSG_CHECKING([if Windows APIs required for ZGC is present]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include ]], + [[struct MEM_EXTENDED_PARAMETER x;]]) + ], + [ + AC_MSG_RESULT([yes]) + ], + [ + AC_MSG_RESULT([no, missing required APIs]) + AVAILABLE=false + ] + ) + fi + ]) +]) + +############################################################################### +# Setup JVM_FEATURES_PLATFORM_UNAVAILABLE and JVM_FEATURES_PLATFORM_FILTER +# to contain those features that are unavailable, or should be off by default, +# for this platform, regardless of JVM variant. +# +AC_DEFUN_ONCE([JVM_FEATURES_PREPARE_PLATFORM], +[ + # The checks below should add unavailable features to + # JVM_FEATURES_PLATFORM_UNAVAILABLE. + + JVM_FEATURES_CHECK_AOT + JVM_FEATURES_CHECK_CDS + JVM_FEATURES_CHECK_DTRACE + JVM_FEATURES_CHECK_GRAAL + JVM_FEATURES_CHECK_JFR + JVM_FEATURES_CHECK_JVMCI + JVM_FEATURES_CHECK_SHENANDOAHGC + JVM_FEATURES_CHECK_STATIC_BUILD + JVM_FEATURES_CHECK_ZGC + + # Filter out features by default for all variants on certain platforms. + # Make sure to just add to JVM_FEATURES_PLATFORM_FILTER, since it could + # have a value already from custom extensions. + if test "x$OPENJDK_TARGET_OS" = xaix; then + JVM_FEATURES_PLATFORM_FILTER="$JVM_FEATURES_PLATFORM_FILTER jfr" + fi + + if test "x$OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU" = "xlinux-sparcv9"; then + JVM_FEATURES_PLATFORM_FILTER="$JVM_FEATURES_PLATFORM_FILTER jfr" + fi +]) + +############################################################################### +# Setup JVM_FEATURES_VARIANT_UNAVAILABLE and JVM_FEATURES_VARIANT_FILTER +# to contain those features that are unavailable, or should be off by default, +# for this particular JVM variant. +# +# arg 1: JVM variant +# +AC_DEFUN([JVM_FEATURES_PREPARE_VARIANT], +[ + variant=$1 + + # Check which features are unavailable for this JVM variant. + # This means that is not possible to build these features for this variant. + if test "x$variant" = "xminimal"; then + JVM_FEATURES_VARIANT_UNAVAILABLE="cds zero" + elif test "x$variant" = "xcore"; then + JVM_FEATURES_VARIANT_UNAVAILABLE="cds minimal zero" + elif test "x$variant" = "xzero"; then + JVM_FEATURES_VARIANT_UNAVAILABLE="aot cds compiler1 compiler2 \ + epsilongc g1gc graal jvmci minimal shenandoahgc zgc" + else + JVM_FEATURES_VARIANT_UNAVAILABLE="minimal zero" + fi + + # Check which features should be off by default for this JVM variant. + if test "x$variant" = "xclient"; then + JVM_FEATURES_VARIANT_FILTER="aot compiler2 graal jvmci link-time-opt opt-size" + elif test "x$variant" = "xminimal"; then + JVM_FEATURES_VARIANT_FILTER="aot cds compiler2 dtrace epsilongc g1gc \ + graal jfr jni-check jvmci jvmti management nmt parallelgc services \ + shenandoahgc vm-structs zgc" + if test "x$OPENJDK_TARGET_CPU" = xarm ; then + JVM_FEATURES_VARIANT_FILTER="$JVM_FEATURES_VARIANT_FILTER opt-size" + else + # Only arm-32 should have link-time-opt enabled as default. + JVM_FEATURES_VARIANT_FILTER="$JVM_FEATURES_VARIANT_FILTER \ + link-time-opt" + fi + elif test "x$variant" = "xcore"; then + JVM_FEATURES_VARIANT_FILTER="aot compiler1 compiler2 graal jvmci \ + link-time-opt opt-size" + elif test "x$variant" = "xzero"; then + JVM_FEATURES_VARIANT_FILTER="jfr link-time-opt opt-size" + else + JVM_FEATURES_VARIANT_FILTER="link-time-opt opt-size" + fi +]) + +############################################################################### +# Calculate the actual set of active JVM features for this JVM variant. Store +# the result in JVM_FEATURES_ACTIVE. +# +# arg 1: JVM variant +# +AC_DEFUN([JVM_FEATURES_CALCULATE_ACTIVE], +[ + variant=$1 + + # The default is set to all valid features except those unavailable or listed + # in a filter. + if test "x$variant" != xcustom; then + UTIL_GET_NON_MATCHING_VALUES(default_for_variant, $JVM_FEATURES_VALID, \ + $JVM_FEATURES_PLATFORM_UNAVAILABLE $JVM_FEATURES_VARIANT_UNAVAILABLE \ + $JVM_FEATURES_PLATFORM_FILTER $JVM_FEATURES_VARIANT_FILTER) + else + # Except for the 'custom' variant, where the default is to start with an + # empty set. + default_for_variant="" + fi + + # Verify that explicitly enabled features are available + UTIL_GET_MATCHING_VALUES(enabled_but_unavailable, $JVM_FEATURES_ENABLED, \ + $JVM_FEATURES_PLATFORM_UNAVAILABLE $JVM_FEATURES_VARIANT_UNAVAILABLE) + if test "x$enabled_but_unavailable" != x; then + AC_MSG_NOTICE([ERROR: Unavailable JVM features explicitly enabled for '$variant': '$enabled_but_unavailable']) + AC_MSG_ERROR([Cannot continue]) + fi + + # Notify the user if their command line options has no real effect + UTIL_GET_MATCHING_VALUES(enabled_but_default, $JVM_FEATURES_ENABLED, \ + $default_for_variant) + if test "x$enabled_but_default" != x; then + AC_MSG_NOTICE([Default JVM features explicitly enabled for '$variant': '$enabled_but_default']) + fi + UTIL_GET_MATCHING_VALUES(disabled_but_unavailable, $JVM_FEATURES_DISABLED, \ + $JVM_FEATURES_PLATFORM_UNAVAILABLE $JVM_FEATURES_VARIANT_UNAVAILABLE) + if test "x$disabled_but_unavailable" != x; then + AC_MSG_NOTICE([Unavailable JVM features explicitly disabled for '$variant': '$disabled_but_unavailable']) + fi + + # JVM_FEATURES_ACTIVE is the set of all default features and all explicitly + # enabled features, with the explicitly disabled features filtered out. + UTIL_GET_NON_MATCHING_VALUES(JVM_FEATURES_ACTIVE, $default_for_variant \ + $JVM_FEATURES_ENABLED, $JVM_FEATURES_DISABLED) +]) + +############################################################################### +# Helper function for JVM_FEATURES_VERIFY. Check if the specified JVM +# feature is active. To be used in shell if constructs, like this: +# 'if JVM_FEATURES_IS_ACTIVE(jvmti); then' +# +# Definition kept in one line to allow inlining in if statements. +# Additional [] needed to keep m4 from mangling shell constructs. +AC_DEFUN([JVM_FEATURES_IS_ACTIVE], +[ [ [[ " $JVM_FEATURES_ACTIVE " =~ ' '$1' ' ]] ] ]) + +############################################################################### +# Verify that the resulting set of features is consistent and legal. +# +# arg 1: JVM variant +# +AC_DEFUN([JVM_FEATURES_VERIFY], +[ + variant=$1 + + # Verify that dependencies are met for inter-feature relations. + if JVM_FEATURES_IS_ACTIVE(aot) && ! JVM_FEATURES_IS_ACTIVE(graal); then + AC_MSG_ERROR([Specified JVM feature 'aot' requires feature 'graal' for variant '$variant']) + fi + + if JVM_FEATURES_IS_ACTIVE(graal) && ! JVM_FEATURES_IS_ACTIVE(jvmci); then + AC_MSG_ERROR([Specified JVM feature 'graal' requires feature 'jvmci' for variant '$variant']) + fi + + if JVM_FEATURES_IS_ACTIVE(jvmci) && ! (JVM_FEATURES_IS_ACTIVE(compiler1) || \ + JVM_FEATURES_IS_ACTIVE(compiler2)); then + AC_MSG_ERROR([Specified JVM feature 'jvmci' requires feature 'compiler2' or 'compiler1' for variant '$variant']) + fi + + if JVM_FEATURES_IS_ACTIVE(jvmti) && ! JVM_FEATURES_IS_ACTIVE(services); then + AC_MSG_ERROR([Specified JVM feature 'jvmti' requires feature 'services' for variant '$variant']) + fi + + if JVM_FEATURES_IS_ACTIVE(management) && ! JVM_FEATURES_IS_ACTIVE(nmt); then + AC_MSG_ERROR([Specified JVM feature 'management' requires feature 'nmt' for variant '$variant']) + fi + + # For backwards compatibility, disable a feature "globally" if one variant + # is missing the feature. + if ! JVM_FEATURES_IS_ACTIVE(aot); then + ENABLE_AOT="false" + fi + if ! JVM_FEATURES_IS_ACTIVE(cds); then + ENABLE_CDS="false" + fi + if ! JVM_FEATURES_IS_ACTIVE(graal); then + INCLUDE_GRAAL="false" + fi + if ! JVM_FEATURES_IS_ACTIVE(jvmci); then + INCLUDE_JVMCI="false" + fi + + # Verify that we have at least one gc selected (i.e., feature named "*gc"). + if ! JVM_FEATURES_IS_ACTIVE(.*gc); then + AC_MSG_NOTICE([At least one gc needed for variant '$variant'.]) + AC_MSG_NOTICE([Specified features: '$JVM_FEATURES_ACTIVE']) + AC_MSG_ERROR([Cannot continue]) + fi +]) + +############################################################################### +# Set up all JVM features for each enabled JVM variant. Requires that +# JVM_FEATURES_PARSE_OPTIONS has been called. +# +AC_DEFUN_ONCE([JVM_FEATURES_SETUP], +[ + # Set up variant-independent factors + JVM_FEATURES_PREPARE_PLATFORM + + # For backwards compatibility, tentatively enable these features "globally", + # and disable them in JVM_FEATURES_VERIFY if a variant is found that are + # missing any of them. + ENABLE_AOT="true" + ENABLE_CDS="true" + INCLUDE_GRAAL="true" + INCLUDE_JVMCI="true" + + for variant in $JVM_VARIANTS; do + # Figure out if any features are unavailable, or should be filtered out + # by default, for this variant. + # Store the result in JVM_FEATURES_VARIANT_UNAVAILABLE and + # JVM_FEATURES_VARIANT_FILTER. + JVM_FEATURES_PREPARE_VARIANT($variant) + + # Calculate the resulting set of enabled features for this variant. + # The result is stored in JVM_FEATURES_ACTIVE. + JVM_FEATURES_CALCULATE_ACTIVE($variant) + + # Verify consistency for JVM_FEATURES_ACTIVE. + JVM_FEATURES_VERIFY($variant) + + # Keep feature list sorted and free of duplicates + UTIL_SORT_LIST(JVM_FEATURES_ACTIVE, $JVM_FEATURES_ACTIVE) + AC_MSG_CHECKING([JVM features to use for variant '$variant']) + AC_MSG_RESULT(['$JVM_FEATURES_ACTIVE']) + + # Save this as e.g. JVM_FEATURES_server, using indirect variable + # referencing. + features_var_name=JVM_FEATURES_$variant + eval $features_var_name=\"$JVM_FEATURES_ACTIVE\" + done + + # Unfortunately AC_SUBST does not work with non-literally named variables, + # so list all variants here. + AC_SUBST(JVM_FEATURES_server) + AC_SUBST(JVM_FEATURES_client) + AC_SUBST(JVM_FEATURES_minimal) + AC_SUBST(JVM_FEATURES_core) + AC_SUBST(JVM_FEATURES_zero) + AC_SUBST(JVM_FEATURES_custom) + + AC_SUBST(ENABLE_AOT) + AC_SUBST(INCLUDE_GRAAL) + AC_SUBST(INCLUDE_JVMCI) + +]) diff --git a/make/autoconf/lib-tests.m4 b/make/autoconf/lib-tests.m4 index 043d94a7a84..b1437024332 100644 --- a/make/autoconf/lib-tests.m4 +++ b/make/autoconf/lib-tests.m4 @@ -51,7 +51,7 @@ AC_DEFUN_ONCE([LIB_TESTS_SETUP_GRAALUNIT], fi fi - BASIC_FIXUP_PATH([GRAALUNIT_LIB]) + UTIL_FIXUP_PATH([GRAALUNIT_LIB]) AC_SUBST(GRAALUNIT_LIB) ]) @@ -77,7 +77,7 @@ AC_DEFUN_ONCE([LIB_TESTS_SETUP_JMH], AC_MSG_RESULT([no, error]) AC_MSG_ERROR([$JMH_HOME does not exist or is not a directory]) fi - BASIC_FIXUP_PATH([JMH_HOME]) + UTIL_FIXUP_PATH([JMH_HOME]) jar_names="jmh-core jmh-generator-annprocess jopt-simple commons-math3" for jar in $jar_names; do diff --git a/make/autoconf/libraries.m4 b/make/autoconf/libraries.m4 index 5f16f08b208..8618077d1bb 100644 --- a/make/autoconf/libraries.m4 +++ b/make/autoconf/libraries.m4 @@ -196,7 +196,7 @@ AC_DEFUN_ONCE([LIB_SETUP_MISC_LIBS], ################################################################################ AC_DEFUN_ONCE([LIB_SETUP_SOLARIS_STLPORT], [ - if test "$OPENJDK_TARGET_OS" = "solaris" && test "x$BUILD_GTEST" = "xtrue"; then + if test "x$OPENJDK_TARGET_OS" = "xsolaris"; then # Find the root of the Solaris Studio installation from the compiler path SOLARIS_STUDIO_DIR="$(dirname $CC)/.." STLPORT_LIB="$SOLARIS_STUDIO_DIR/lib/stlport4$OPENJDK_TARGET_CPU_ISADIR/libstlport.so.1" @@ -207,10 +207,9 @@ AC_DEFUN_ONCE([LIB_SETUP_SOLARIS_STLPORT], fi if test -f "$STLPORT_LIB"; then AC_MSG_RESULT([yes, $STLPORT_LIB]) - BASIC_FIXUP_PATH([STLPORT_LIB]) + UTIL_FIXUP_PATH([STLPORT_LIB]) else - AC_MSG_RESULT([no, not found at $STLPORT_LIB]) - AC_MSG_ERROR([Failed to find libstlport.so.1, cannot build Hotspot gtests]) + AC_MSG_RESULT([no, not found at $STLPORT_LIB, cannot build Hotspot gtests]) fi AC_SUBST(STLPORT_LIB) fi diff --git a/make/autoconf/source-dirs.m4 b/make/autoconf/source-dirs.m4 index 617ef0c4b4f..8ac7c542cab 100644 --- a/make/autoconf/source-dirs.m4 +++ b/make/autoconf/source-dirs.m4 @@ -46,7 +46,7 @@ AC_DEFUN_ONCE([SRCDIRS_SETUP_IMPORT_MODULES], && test "x$with_import_modules" != "xno"; then if test -d "$with_import_modules"; then IMPORT_MODULES_TOPDIR="$with_import_modules" - BASIC_FIXUP_PATH([IMPORT_MODULES_TOPDIR]) + UTIL_FIXUP_PATH([IMPORT_MODULES_TOPDIR]) elif test -e "$with_import_modules"; then IMPORT_MODULES_TOPDIR="$CONFIGURESUPPORT_OUTPUTDIR/import-modules" $RM -rf "$IMPORT_MODULES_TOPDIR" diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index 14f14ed76c9..241725e40bd 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -303,6 +303,9 @@ ENABLE_HEADLESS_ONLY := @ENABLE_HEADLESS_ONLY@ ENABLE_LINKTIME_GC := @ENABLE_LINKTIME_GC@ +# Ship debug symbols (e.g. pdbs on Windows) +SHIP_DEBUG_SYMBOLS := @SHIP_DEBUG_SYMBOLS@ + ENABLE_FULL_DOCS := @ENABLE_FULL_DOCS@ # JDK_OUTPUTDIR specifies where a working jvm is built. @@ -911,10 +914,16 @@ GRAAL_BUILDER_IMAGE_DIR := $(IMAGES_OUTPUTDIR)/$(GRAAL_BUILDER_IMAGE_SUBDIR) # Macosx bundles directory definitions JDK_MACOSX_BUNDLE_SUBDIR=jdk-bundle JRE_MACOSX_BUNDLE_SUBDIR=jre-bundle +JDK_MACOSX_BUNDLE_SUBDIR_SIGNED=jdk-bundle-signed +JRE_MACOSX_BUNDLE_SUBDIR_SIGNED=jre-bundle-signed JDK_MACOSX_BUNDLE_DIR=$(IMAGES_OUTPUTDIR)/$(JDK_MACOSX_BUNDLE_SUBDIR) JRE_MACOSX_BUNDLE_DIR=$(IMAGES_OUTPUTDIR)/$(JRE_MACOSX_BUNDLE_SUBDIR) -JDK_MACOSX_CONTENTS_SUBDIR=jdk-$(VERSION_NUMBER).jdk/Contents -JRE_MACOSX_CONTENTS_SUBDIR=jre-$(VERSION_NUMBER).jre/Contents +JDK_MACOSX_BUNDLE_DIR_SIGNED=$(IMAGES_OUTPUTDIR)/$(JDK_MACOSX_BUNDLE_SUBDIR_SIGNED) +JRE_MACOSX_BUNDLE_DIR_SIGNED=$(IMAGES_OUTPUTDIR)/$(JRE_MACOSX_BUNDLE_SUBDIR_SIGNED) +JDK_MACOSX_BUNDLE_TOP_DIR=jdk-$(VERSION_NUMBER).jdk +JRE_MACOSX_BUNDLE_TOP_DIR=jre-$(VERSION_NUMBER).jre +JDK_MACOSX_CONTENTS_SUBDIR=$(JDK_MACOSX_BUNDLE_TOP_DIR)/Contents +JRE_MACOSX_CONTENTS_SUBDIR=$(JRE_MACOSX_BUNDLE_TOP_DIR)/Contents JDK_MACOSX_CONTENTS_DIR=$(JDK_MACOSX_BUNDLE_DIR)/$(JDK_MACOSX_CONTENTS_SUBDIR) JRE_MACOSX_CONTENTS_DIR=$(JRE_MACOSX_BUNDLE_DIR)/$(JRE_MACOSX_CONTENTS_SUBDIR) diff --git a/make/autoconf/toolchain.m4 b/make/autoconf/toolchain.m4 index 01bef676deb..698f4cd75f4 100644 --- a/make/autoconf/toolchain.m4 +++ b/make/autoconf/toolchain.m4 @@ -32,6 +32,7 @@ # compilers and related tools that are used. ######################################################################## +m4_include([toolchain_windows.m4]) # All valid toolchains, regardless of platform (used by help.m4) VALID_TOOLCHAINS_all="gcc clang solstudio xlc microsoft" @@ -92,7 +93,7 @@ AC_DEFUN([TOOLCHAIN_PREPARE_FOR_VERSION_COMPARISONS], # IF_AT_LEAST: block to run if the compiler is at least this version (>=) # IF_OLDER_THAN: block to run if the compiler is older than this version (<) # PREFIX: Optional variable prefix for compiler to compare version for (OPENJDK_BUILD_) -BASIC_DEFUN_NAMED([TOOLCHAIN_CHECK_COMPILER_VERSION], +UTIL_DEFUN_NAMED([TOOLCHAIN_CHECK_COMPILER_VERSION], [*VERSION PREFIX IF_AT_LEAST IF_OLDER_THAN], [$@], [ # Need to assign to a variable since m4 is blocked from modifying parts in []. @@ -143,7 +144,7 @@ AC_DEFUN([TOOLCHAIN_PREPARE_FOR_LD_VERSION_COMPARISONS], # IF_AT_LEAST: block to run if the compiler is at least this version (>=) # IF_OLDER_THAN: block to run if the compiler is older than this version (<) # PREFIX: Optional variable prefix for compiler to compare version for (OPENJDK_BUILD_) -BASIC_DEFUN_NAMED([TOOLCHAIN_CHECK_LINKER_VERSION], +UTIL_DEFUN_NAMED([TOOLCHAIN_CHECK_LINKER_VERSION], [*VERSION PREFIX IF_AT_LEAST IF_OLDER_THAN], [$@], [ # Need to assign to a variable since m4 is blocked from modifying parts in []. @@ -349,8 +350,8 @@ AC_DEFUN_ONCE([TOOLCHAIN_PRE_DETECTION], if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then # Append VS_PATH. In WSL, VS_PATH will not contain the WSL env path needed # for using basic Unix tools, so need to keep the original PATH. - BASIC_APPEND_TO_PATH(PATH, $VS_PATH) - BASIC_APPEND_TO_PATH(WSLENV, "PATH/l:LIB:INCLUDE") + UTIL_APPEND_TO_PATH(PATH, $VS_PATH) + UTIL_APPEND_TO_PATH(WSLENV, "PATH/l:LIB:INCLUDE") export WSLENV else # Reset path to VS_PATH. It will include everything that was on PATH at the time we @@ -580,12 +581,12 @@ AC_DEFUN([TOOLCHAIN_FIND_COMPILER], fi # Now we have a compiler binary in $1. Make sure it's okay. - BASIC_FIXUP_EXECUTABLE($1) + UTIL_FIXUP_EXECUTABLE($1) TEST_COMPILER="[$]$1" AC_MSG_CHECKING([resolved symbolic links for $1]) SYMLINK_ORIGINAL="$TEST_COMPILER" - BASIC_REMOVE_SYMBOLIC_LINKS(SYMLINK_ORIGINAL) + UTIL_REMOVE_SYMBOLIC_LINKS(SYMLINK_ORIGINAL) if test "x$TEST_COMPILER" = "x$SYMLINK_ORIGINAL"; then AC_MSG_RESULT([no symlink]) else @@ -716,9 +717,9 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_CORE], # Setup the preprocessor (CPP and CXXCPP) # AC_PROG_CPP - BASIC_FIXUP_EXECUTABLE(CPP) + UTIL_FIXUP_EXECUTABLE(CPP) AC_PROG_CXXCPP - BASIC_FIXUP_EXECUTABLE(CXXCPP) + UTIL_FIXUP_EXECUTABLE(CXXCPP) # # Setup the linker (LD) @@ -728,7 +729,7 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_CORE], # Make sure we reject /usr/bin/link (as determined in CYGWIN_LINK), which is # a cygwin program for something completely different. AC_CHECK_PROG([LD], [link$EXE_SUFFIX],[link$EXE_SUFFIX],,, [$CYGWIN_LINK]) - BASIC_FIXUP_EXECUTABLE(LD) + UTIL_FIXUP_EXECUTABLE(LD) # Verify that we indeed succeeded with this trick. AC_MSG_CHECKING([if the found link.exe is actually the Visual Studio linker]) "$LD" --version > /dev/null @@ -746,8 +747,8 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_CORE], LD="$CC" LDCXX="$CXX" # jaotc expects 'ld' as the linker rather than the compiler. - BASIC_CHECK_TOOLS([LD_JAOTC], ld) - BASIC_FIXUP_EXECUTABLE(LD_JAOTC) + UTIL_CHECK_TOOLS([LD_JAOTC], ld) + UTIL_FIXUP_EXECUTABLE(LD_JAOTC) fi AC_SUBST(LD) AC_SUBST(LD_JAOTC) @@ -769,8 +770,8 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_CORE], # Setup the assembler (AS) # if test "x$OPENJDK_TARGET_OS" = xsolaris; then - BASIC_PATH_PROGS(AS, as) - BASIC_FIXUP_EXECUTABLE(AS) + UTIL_PATH_PROGS(AS, as) + UTIL_FIXUP_EXECUTABLE(AS) if test "x$AS" = x; then AC_MSG_ERROR([Solaris assembler (as) is required. Please install via "pkg install pkg:/developer/assembler".]) fi @@ -787,11 +788,11 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_CORE], # The corresponding ar tool is lib.exe (used to create static libraries) AC_CHECK_PROG([AR], [lib$EXE_SUFFIX],[lib$EXE_SUFFIX],,,) elif test "x$TOOLCHAIN_TYPE" = xgcc; then - BASIC_CHECK_TOOLS(AR, ar gcc-ar) + UTIL_CHECK_TOOLS(AR, ar gcc-ar) else - BASIC_CHECK_TOOLS(AR, ar) + UTIL_CHECK_TOOLS(AR, ar) fi - BASIC_FIXUP_EXECUTABLE(AR) + UTIL_FIXUP_EXECUTABLE(AR) ]) # Setup additional tools that is considered a part of the toolchain, but not the @@ -800,22 +801,22 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_CORE], AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_EXTRA], [ if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then - BASIC_PATH_PROGS(LIPO, lipo) - BASIC_FIXUP_EXECUTABLE(LIPO) - BASIC_REQUIRE_PROGS(OTOOL, otool) - BASIC_FIXUP_EXECUTABLE(OTOOL) - BASIC_REQUIRE_PROGS(INSTALL_NAME_TOOL, install_name_tool) - BASIC_FIXUP_EXECUTABLE(INSTALL_NAME_TOOL) + UTIL_PATH_PROGS(LIPO, lipo) + UTIL_FIXUP_EXECUTABLE(LIPO) + UTIL_REQUIRE_PROGS(OTOOL, otool) + UTIL_FIXUP_EXECUTABLE(OTOOL) + UTIL_REQUIRE_PROGS(INSTALL_NAME_TOOL, install_name_tool) + UTIL_FIXUP_EXECUTABLE(INSTALL_NAME_TOOL) fi if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then AC_CHECK_PROG([MT], [mt$EXE_SUFFIX], [mt$EXE_SUFFIX],,, [/usr/bin/mt]) - BASIC_FIXUP_EXECUTABLE(MT) + UTIL_FIXUP_EXECUTABLE(MT) # Setup the resource compiler (RC) AC_CHECK_PROG([RC], [rc$EXE_SUFFIX], [rc$EXE_SUFFIX],,, [/usr/bin/rc]) - BASIC_FIXUP_EXECUTABLE(RC) + UTIL_FIXUP_EXECUTABLE(RC) AC_CHECK_PROG([DUMPBIN], [dumpbin$EXE_SUFFIX], [dumpbin$EXE_SUFFIX],,,) - BASIC_FIXUP_EXECUTABLE(DUMPBIN) + UTIL_FIXUP_EXECUTABLE(DUMPBIN) # We need to check for 'msbuild.exe' because at the place where we expect to # find 'msbuild.exe' there's also a directory called 'msbuild' and configure # won't find the 'msbuild.exe' executable in that case (and the @@ -827,22 +828,22 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_EXTRA], fi if test "x$OPENJDK_TARGET_OS" = xsolaris; then - BASIC_PATH_PROGS(STRIP, strip) - BASIC_FIXUP_EXECUTABLE(STRIP) - BASIC_PATH_PROGS(NM, nm) - BASIC_FIXUP_EXECUTABLE(NM) - BASIC_PATH_PROGS(GNM, gnm) - BASIC_FIXUP_EXECUTABLE(GNM) + UTIL_PATH_PROGS(STRIP, strip) + UTIL_FIXUP_EXECUTABLE(STRIP) + UTIL_PATH_PROGS(NM, nm) + UTIL_FIXUP_EXECUTABLE(NM) + UTIL_PATH_PROGS(GNM, gnm) + UTIL_FIXUP_EXECUTABLE(GNM) elif test "x$OPENJDK_TARGET_OS" != xwindows; then # FIXME: we should unify this with the solaris case above. - BASIC_CHECK_TOOLS(STRIP, strip) - BASIC_FIXUP_EXECUTABLE(STRIP) + UTIL_CHECK_TOOLS(STRIP, strip) + UTIL_FIXUP_EXECUTABLE(STRIP) if test "x$TOOLCHAIN_TYPE" = xgcc; then - BASIC_CHECK_TOOLS(NM, nm gcc-nm) + UTIL_CHECK_TOOLS(NM, nm gcc-nm) else - BASIC_CHECK_TOOLS(NM, nm) + UTIL_CHECK_TOOLS(NM, nm) fi - BASIC_FIXUP_EXECUTABLE(NM) + UTIL_FIXUP_EXECUTABLE(NM) GNM="$NM" AC_SUBST(GNM) fi @@ -850,10 +851,10 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_EXTRA], # objcopy is used for moving debug symbols to separate files when # full debug symbols are enabled. if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; then - BASIC_CHECK_TOOLS(OBJCOPY, [gobjcopy objcopy]) + UTIL_CHECK_TOOLS(OBJCOPY, [gobjcopy objcopy]) # Only call fixup if objcopy was found. if test -n "$OBJCOPY"; then - BASIC_FIXUP_EXECUTABLE(OBJCOPY) + UTIL_FIXUP_EXECUTABLE(OBJCOPY) if test "x$OPENJDK_BUILD_OS" = xsolaris; then # objcopy prior to 2.21.1 on solaris is broken and is not usable. # Rewrite objcopy version output to VALID_VERSION or BAD_VERSION. @@ -894,18 +895,18 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_EXTRA], fi fi - BASIC_CHECK_TOOLS(OBJDUMP, [gobjdump objdump]) + UTIL_CHECK_TOOLS(OBJDUMP, [gobjdump objdump]) if test "x$OBJDUMP" != x; then - # Only used for compare.sh; we can live without it. BASIC_FIXUP_EXECUTABLE + # Only used for compare.sh; we can live without it. UTIL_FIXUP_EXECUTABLE # bails if argument is missing. - BASIC_FIXUP_EXECUTABLE(OBJDUMP) + UTIL_FIXUP_EXECUTABLE(OBJDUMP) fi case $TOOLCHAIN_TYPE in gcc|clang|solstudio) - BASIC_CHECK_TOOLS(CXXFILT, [c++filt]) - BASIC_CHECK_NONEMPTY(CXXFILT) - BASIC_FIXUP_EXECUTABLE(CXXFILT) + UTIL_CHECK_TOOLS(CXXFILT, [c++filt]) + UTIL_CHECK_NONEMPTY(CXXFILT) + UTIL_FIXUP_EXECUTABLE(CXXFILT) ;; esac ]) @@ -933,7 +934,7 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_BUILD_COMPILERS], if test ! -d "$with_build_devkit"; then AC_MSG_ERROR([--with-build-devkit points to non existing dir: $with_build_devkit]) else - BASIC_FIXUP_PATH([with_build_devkit]) + UTIL_FIXUP_PATH([with_build_devkit]) BUILD_DEVKIT_ROOT="$with_build_devkit" # Check for a meta data info file in the root of the devkit if test -f "$BUILD_DEVKIT_ROOT/devkit.info"; then @@ -977,18 +978,18 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_BUILD_COMPILERS], # FIXME: we should list the discovered compilers as an exclude pattern! # If we do that, we can do this detection before POST_DETECTION, and still # find the build compilers in the tools dir, if needed. - BASIC_REQUIRE_PROGS(BUILD_CC, [cl cc gcc]) - BASIC_FIXUP_EXECUTABLE(BUILD_CC) - BASIC_REQUIRE_PROGS(BUILD_CXX, [cl CC g++]) - BASIC_FIXUP_EXECUTABLE(BUILD_CXX) - BASIC_PATH_PROGS(BUILD_NM, nm gcc-nm) - BASIC_FIXUP_EXECUTABLE(BUILD_NM) - BASIC_PATH_PROGS(BUILD_AR, ar gcc-ar) - BASIC_FIXUP_EXECUTABLE(BUILD_AR) - BASIC_PATH_PROGS(BUILD_OBJCOPY, objcopy) - BASIC_FIXUP_EXECUTABLE(BUILD_OBJCOPY) - BASIC_PATH_PROGS(BUILD_STRIP, strip) - BASIC_FIXUP_EXECUTABLE(BUILD_STRIP) + UTIL_REQUIRE_PROGS(BUILD_CC, [cl cc gcc]) + UTIL_FIXUP_EXECUTABLE(BUILD_CC) + UTIL_REQUIRE_PROGS(BUILD_CXX, [cl CC g++]) + UTIL_FIXUP_EXECUTABLE(BUILD_CXX) + UTIL_PATH_PROGS(BUILD_NM, nm gcc-nm) + UTIL_FIXUP_EXECUTABLE(BUILD_NM) + UTIL_PATH_PROGS(BUILD_AR, ar gcc-ar) + UTIL_FIXUP_EXECUTABLE(BUILD_AR) + UTIL_PATH_PROGS(BUILD_OBJCOPY, objcopy) + UTIL_FIXUP_EXECUTABLE(BUILD_OBJCOPY) + UTIL_PATH_PROGS(BUILD_STRIP, strip) + UTIL_FIXUP_EXECUTABLE(BUILD_STRIP) # Assume the C compiler is the assembler BUILD_AS="$BUILD_CC -c" # Just like for the target compiler, use the compiler as linker @@ -1082,7 +1083,7 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_JTREG], elif test "x$with_jtreg" != xyes && test "x$with_jtreg" != x; then # An explicit path is specified, use it. JT_HOME="$with_jtreg" - BASIC_FIXUP_PATH([JT_HOME]) + UTIL_FIXUP_PATH([JT_HOME]) if test ! -d "$JT_HOME"; then AC_MSG_ERROR([jtreg home directory from --with-jtreg=$with_jtreg does not exist]) fi @@ -1122,7 +1123,7 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_JTREG], if test "x$JT_HOME" = x; then # JT_HOME is not set in environment, or was deemed invalid. # Try to find jtreg on path - BASIC_PATH_PROGS(JTREGEXE, jtreg) + UTIL_PATH_PROGS(JTREGEXE, jtreg) if test "x$JTREGEXE" != x; then # That's good, now try to derive JT_HOME JT_HOME=`(cd $($DIRNAME $JTREGEXE)/.. && pwd)` @@ -1148,8 +1149,8 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_JTREG], fi fi - BASIC_FIXUP_EXECUTABLE(JTREGEXE) - BASIC_FIXUP_PATH(JT_HOME) + UTIL_FIXUP_EXECUTABLE(JTREGEXE) + UTIL_FIXUP_PATH(JT_HOME) AC_SUBST(JT_HOME) AC_SUBST(JTREGEXE) ]) diff --git a/make/autoconf/toolchain_windows.m4 b/make/autoconf/toolchain_windows.m4 index 90482ab78f8..462d14a0f69 100644 --- a/make/autoconf/toolchain_windows.m4 +++ b/make/autoconf/toolchain_windows.m4 @@ -112,7 +112,7 @@ AC_DEFUN([TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT], VS_BASE="$2" METHOD="$3" - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(VS_BASE) + UTIL_REWRITE_AS_UNIX_PATH(VS_BASE) # In VS 2017 and VS 2019, the default installation is in a subdir named after the edition. # Find the first one present and use that. if test "x$VS_EDITIONS" != x; then @@ -160,7 +160,7 @@ AC_DEFUN([TOOLCHAIN_CHECK_POSSIBLE_WIN_SDK_ROOT], VS_VERSION="$1" WIN_SDK_BASE="$2" METHOD="$3" - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(WIN_SDK_BASE) + UTIL_REWRITE_AS_UNIX_PATH(WIN_SDK_BASE) if test -d "$WIN_SDK_BASE"; then # There have been cases of partial or broken SDK installations. A missing # lib dir is not going to work. @@ -313,7 +313,7 @@ AC_DEFUN([TOOLCHAIN_FIND_VISUAL_STUDIO], VS_PATH_WINDOWS="" for i in $TOOLCHAIN_PATH; do path=$i - BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH([path]) + UTIL_REWRITE_AS_WINDOWS_MIXED_PATH([path]) VS_PATH_WINDOWS="$VS_PATH_WINDOWS;$path" done IFS="$OLDIFS" @@ -331,14 +331,14 @@ AC_DEFUN([TOOLCHAIN_FIND_VISUAL_STUDIO], IFS=";" for i in $DEVKIT_VS_INCLUDE; do ipath=$i - BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH([ipath]) + UTIL_REWRITE_AS_WINDOWS_MIXED_PATH([ipath]) VS_INCLUDE="$VS_INCLUDE;$ipath" done # Convert DEVKIT_VS_LIB into VS_LIB so that it can still be exported # as LIB for compiler invocations without SYSROOT_LDFLAGS for i in $DEVKIT_VS_LIB; do libpath=$i - BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH([libpath]) + UTIL_REWRITE_AS_WINDOWS_MIXED_PATH([libpath]) VS_LIB="$VS_LIB;$libpath" done IFS="$OLDIFS" @@ -408,7 +408,7 @@ AC_DEFUN([TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV], if test "x$DEVKIT_VS_VERSION" = x; then if test "x$VS_ENV_CMD" != x; then # We have found a Visual Studio environment on disk, let's extract variables from the vsvars bat file. - BASIC_FIXUP_EXECUTABLE(VS_ENV_CMD) + UTIL_FIXUP_EXECUTABLE(VS_ENV_CMD) # Lets extract the variables that are set by vcvarsall.bat/vsvars32.bat/vsvars64.bat AC_MSG_NOTICE([Trying to extract Visual Studio environment variables]) @@ -420,13 +420,13 @@ AC_DEFUN([TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV], # Cannot use the VS10 setup script directly (since it only updates the DOS subshell environment). # Instead create a shell script which will set the relevant variables when run. WINPATH_VS_ENV_CMD="$VS_ENV_CMD" - BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH([WINPATH_VS_ENV_CMD]) + UTIL_REWRITE_AS_WINDOWS_MIXED_PATH([WINPATH_VS_ENV_CMD]) if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then WINPATH_BASH="bash" else WINPATH_BASH="$BASH" - BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH([WINPATH_BASH]) + UTIL_REWRITE_AS_WINDOWS_MIXED_PATH([WINPATH_BASH]) fi # Generate a DOS batch file which runs $VS_ENV_CMD, and then creates a shell @@ -521,10 +521,10 @@ AC_DEFUN([TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV], IFS="$OLDIFS" # Check that directory exists before calling fixup_path testpath=$path - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH([testpath]) + UTIL_REWRITE_AS_UNIX_PATH([testpath]) if test -d "$testpath"; then - BASIC_FIXUP_PATH([path]) - BASIC_APPEND_TO_PATH(VS_PATH, $path) + UTIL_FIXUP_PATH([path]) + UTIL_APPEND_TO_PATH(VS_PATH, $path) fi IFS=";" fi @@ -576,9 +576,9 @@ AC_DEFUN([TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV], IFS="$OLDIFS" # Check that directory exists before calling fixup_path testpath=$ipath - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH([testpath]) + UTIL_REWRITE_AS_UNIX_PATH([testpath]) if test -d "$testpath"; then - BASIC_FIXUP_PATH([ipath]) + UTIL_FIXUP_PATH([ipath]) SYSROOT_CFLAGS="$SYSROOT_CFLAGS -I$ipath" fi IFS=";" @@ -592,9 +592,9 @@ AC_DEFUN([TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV], IFS="$OLDIFS" # Check that directory exists before calling fixup_path testpath=$libpath - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH([testpath]) + UTIL_REWRITE_AS_UNIX_PATH([testpath]) if test -d "$testpath"; then - BASIC_FIXUP_PATH([libpath]) + UTIL_FIXUP_PATH([libpath]) SYSROOT_LDFLAGS="$SYSROOT_LDFLAGS -libpath:$libpath" fi IFS=";" @@ -665,7 +665,7 @@ AC_DEFUN([TOOLCHAIN_SETUP_MSVC_DLL], if test "x$MSVC_DLL" = x; then if test "x$VCINSTALLDIR" != x; then CYGWIN_VC_INSTALL_DIR="$VCINSTALLDIR" - BASIC_FIXUP_PATH(CYGWIN_VC_INSTALL_DIR) + UTIL_FIXUP_PATH(CYGWIN_VC_INSTALL_DIR) if test "$VS_VERSION" -lt 2017; then # Probe: Using well-known location from Visual Studio 12.0 and older if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then @@ -675,7 +675,7 @@ AC_DEFUN([TOOLCHAIN_SETUP_MSVC_DLL], fi else CYGWIN_VC_TOOLS_REDIST_DIR="$VCToolsRedistDir" - BASIC_FIXUP_PATH(CYGWIN_VC_TOOLS_REDIST_DIR) + UTIL_FIXUP_PATH(CYGWIN_VC_TOOLS_REDIST_DIR) # Probe: Using well-known location from VS 2017 and VS 2019 if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then POSSIBLE_MSVC_DLL="`ls $CYGWIN_VC_TOOLS_REDIST_DIR/x64/Microsoft.VC${VS_VERSION_INTERNAL}.CRT/$DLL_NAME`" @@ -702,7 +702,7 @@ AC_DEFUN([TOOLCHAIN_SETUP_MSVC_DLL], if test "x$MSVC_DLL" = x; then # Probe: Look in the Windows system32 directory CYGWIN_SYSTEMROOT="$SYSTEMROOT" - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(CYGWIN_SYSTEMROOT) + UTIL_REWRITE_AS_UNIX_PATH(CYGWIN_SYSTEMROOT) POSSIBLE_MSVC_DLL="$CYGWIN_SYSTEMROOT/system32/$DLL_NAME" TOOLCHAIN_CHECK_POSSIBLE_MSVC_DLL([$DLL_NAME], [$POSSIBLE_MSVC_DLL], [well-known location in SYSTEMROOT]) @@ -712,7 +712,7 @@ AC_DEFUN([TOOLCHAIN_SETUP_MSVC_DLL], # Probe: If Visual Studio Express is installed, there is usually one with the debugger if test "x$VS100COMNTOOLS" != x; then CYGWIN_VS_TOOLS_DIR="$VS100COMNTOOLS/.." - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(CYGWIN_VS_TOOLS_DIR) + UTIL_REWRITE_AS_UNIX_PATH(CYGWIN_VS_TOOLS_DIR) if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then POSSIBLE_MSVC_DLL=`$FIND "$CYGWIN_VS_TOOLS_DIR" -name $DLL_NAME \ | $GREP -i /x64/ | $HEAD --lines 1` @@ -814,14 +814,14 @@ AC_DEFUN([TOOLCHAIN_SETUP_VS_RUNTIME_DLLS], else AC_MSG_RESULT([$with_ucrt_dll_dir]) UCRT_DLL_DIR="$with_ucrt_dll_dir" - BASIC_FIXUP_PATH([UCRT_DLL_DIR]) + UTIL_FIXUP_PATH([UCRT_DLL_DIR]) fi elif test "x$DEVKIT_UCRT_DLL_DIR" != "x"; then UCRT_DLL_DIR="$DEVKIT_UCRT_DLL_DIR" AC_MSG_RESULT($UCRT_DLL_DIR) else CYGWIN_WINDOWSSDKDIR="${WINDOWSSDKDIR}" - BASIC_FIXUP_PATH([CYGWIN_WINDOWSSDKDIR]) + UTIL_FIXUP_PATH([CYGWIN_WINDOWSSDKDIR]) dll_subdir=$OPENJDK_TARGET_CPU if test "x$dll_subdir" = "xx86_64"; then dll_subdir="x64" diff --git a/make/autoconf/util.m4 b/make/autoconf/util.m4 new file mode 100644 index 00000000000..7a1acb1a95c --- /dev/null +++ b/make/autoconf/util.m4 @@ -0,0 +1,399 @@ +# +# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +m4_include([util_paths.m4]) +m4_include([util_windows.m4]) + +############################################################################### +# Create a function/macro that takes a series of named arguments. The call is +# similar to AC_DEFUN, but the setup of the function looks like this: +# UTIL_DEFUN_NAMED([MYFUNC], [FOO *BAR], [$@], [ +# ... do something +# AC_MSG_NOTICE([Value of BAR is ARG_BAR]) +# ]) +# A star (*) in front of a named argument means that it is required and it's +# presence will be verified. To pass e.g. the first value as a normal indexed +# argument, use [m4_shift($@)] as the third argument instead of [$@]. These +# arguments are referenced in the function by their name prefixed by ARG_, e.g. +# "ARG_FOO". +# +# The generated function can be called like this: +# MYFUNC(FOO: [foo-val], +# BAR: [ +# $ECHO hello world +# ]) +# Note that the argument value must start on the same line as the argument name. +# +# Argument 1: Name of the function to define +# Argument 2: List of legal named arguments, with a * prefix for required arguments +# Argument 3: Argument array to treat as named, typically $@ +# Argument 4: The main function body +AC_DEFUN([UTIL_DEFUN_NAMED], +[ + AC_DEFUN($1, [ + m4_foreach(arg, m4_split($2), [ + m4_if(m4_bregexp(arg, [^\*]), -1, + [ + m4_set_add(legal_named_args, arg) + ], + [ + m4_set_add(legal_named_args, m4_substr(arg, 1)) + m4_set_add(required_named_args, m4_substr(arg, 1)) + ] + ) + ]) + + m4_foreach([arg], [$3], [ + m4_define(arg_name, m4_substr(arg, 0, m4_bregexp(arg, [: ]))) + m4_set_contains(legal_named_args, arg_name, [],[AC_MSG_ERROR([Internal error: arg_name is not a valid named argument to [$1]. Valid arguments are 'm4_set_contents(legal_named_args, [ ])'.])]) + m4_set_remove(required_named_args, arg_name) + m4_set_remove(legal_named_args, arg_name) + m4_pushdef([ARG_][]arg_name, m4_substr(arg, m4_incr(m4_incr(m4_bregexp(arg, [: ]))))) + m4_set_add(defined_args, arg_name) + m4_undefine([arg_name]) + ]) + m4_set_empty(required_named_args, [], [ + AC_MSG_ERROR([Internal error: Required named arguments are missing for [$1]. Missing arguments: 'm4_set_contents(required_named_args, [ ])']) + ]) + m4_foreach([arg], m4_indir([m4_dquote]m4_set_listc([legal_named_args])), [ + m4_pushdef([ARG_][]arg, []) + m4_set_add(defined_args, arg) + ]) + m4_set_delete(legal_named_args) + m4_set_delete(required_named_args) + + # Execute function body + $4 + + m4_foreach([arg], m4_indir([m4_dquote]m4_set_listc([defined_args])), [ + m4_popdef([ARG_][]arg) + ]) + + m4_set_delete(defined_args) + ]) +]) + +############################################################################### +# Assert that a programmatic condition holds. If not, exit with an error message. +# Check that two strings are equal. +# +# $1: The actual string found +# $2: The expected string +# $3: An message to print in case of failure [optional] +# +AC_DEFUN([UTIL_ASSERT_STRING_EQUALS], +[ + ASSERTION_MSG="m4_normalize([$3])" + if test "x[$1]" != "x[$2]"; then + $ECHO Assertion failed: Actual value '[$1]' \("[$1]"\) did not match \ + expected value '[$2]' \("[$2]"\) + if test "x$ASSERTION_MSG" != x; then + $ECHO Assertion message: "$ASSERTION_MSG" + fi + exit 1 + fi +]) + +############################################################################### +# Check if a list of space-separated words are selected only from a list of +# space-separated legal words. Typical use is to see if a user-specified +# set of words is selected from a set of legal words. +# +# Sets the specified variable to list of non-matching (offending) words, or to +# the empty string if all words are matching the legal set. +# +# $1: result variable name +# $2: list of values to check +# $3: list of legal values +AC_DEFUN([UTIL_GET_NON_MATCHING_VALUES], +[ + # grep filter function inspired by a comment to http://stackoverflow.com/a/1617326 + # Notice that the original variant fails on SLES 10 and 11 + # Some grep versions (at least bsd) behaves strangely on the base case with + # no legal_values, so make it explicit. + values_to_check=`$ECHO $2 | $TR ' ' '\n'` + legal_values=`$ECHO $3 | $TR ' ' '\n'` + if test -z "$legal_values"; then + $1="$2" + else + result=`$GREP -Fvx "$legal_values" <<< "$values_to_check" | $GREP -v '^$'` + $1=${result//$'\n'/ } + fi +]) + +############################################################################### +# Check if a list of space-separated words contains any word(s) from a list of +# space-separated illegal words. Typical use is to see if a user-specified +# set of words contains any from a set of illegal words. +# +# Sets the specified variable to list of matching illegal words, or to +# the empty string if no words are matching the illegal set. +# +# $1: result variable name +# $2: list of values to check +# $3: list of illegal values +AC_DEFUN([UTIL_GET_MATCHING_VALUES], +[ + # grep filter function inspired by a comment to http://stackoverflow.com/a/1617326 + # Notice that the original variant fails on SLES 10 and 11 + # Some grep versions (at least bsd) behaves strangely on the base case with + # no legal_values, so make it explicit. + values_to_check=`$ECHO $2 | $TR ' ' '\n'` + illegal_values=`$ECHO $3 | $TR ' ' '\n'` + if test -z "$illegal_values"; then + $1="" + else + result=`$GREP -Fx "$illegal_values" <<< "$values_to_check" | $GREP -v '^$'` + $1=${result//$'\n'/ } + fi +]) + +############################################################################### +# Sort a space-separated list, and remove duplicates. +# +# Sets the specified variable to the resulting list. +# +# $1: result variable name +# $2: list of values to sort +AC_DEFUN([UTIL_SORT_LIST], +[ + values_to_sort=`$ECHO $2 | $TR ' ' '\n'` + result=`$SORT -u <<< "$values_to_sort" | $GREP -v '^$'` + $1=${result//$'\n'/ } +]) + +############################################################################### +# Test if $1 is a valid argument to $3 (often is $JAVA passed as $3) +# If so, then append $1 to $2 \ +# Also set JVM_ARG_OK to true/false depending on outcome. +AC_DEFUN([UTIL_ADD_JVM_ARG_IF_OK], +[ + $ECHO "Check if jvm arg is ok: $1" >&AS_MESSAGE_LOG_FD + $ECHO "Command: $3 $1 -version" >&AS_MESSAGE_LOG_FD + OUTPUT=`$3 $1 $USER_BOOT_JDK_OPTIONS -version 2>&1` + FOUND_WARN=`$ECHO "$OUTPUT" | $GREP -i warn` + FOUND_VERSION=`$ECHO $OUTPUT | $GREP " version \""` + if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then + $2="[$]$2 $1" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&AS_MESSAGE_LOG_FD + $ECHO "$OUTPUT" >&AS_MESSAGE_LOG_FD + JVM_ARG_OK=false + fi +]) + +############################################################################### +# Register a --with argument but mark it as deprecated +# $1: The name of the with argument to deprecate, not including --with- +AC_DEFUN([UTIL_DEPRECATED_ARG_WITH], +[ + AC_ARG_WITH($1, [AS_HELP_STRING([--with-$1], + [Deprecated. Option is kept for backwards compatibility and is ignored])], + [AC_MSG_WARN([Option --with-$1 is deprecated and will be ignored.])]) +]) + +############################################################################### +# Register a --enable argument but mark it as deprecated +# $1: The name of the with argument to deprecate, not including --enable- +# $2: The name of the argument to deprecate, in shell variable style (i.e. with _ instead of -) +# $3: Messages to user. +AC_DEFUN([UTIL_DEPRECATED_ARG_ENABLE], +[ + AC_ARG_ENABLE($1, [AS_HELP_STRING([--enable-$1], + [Deprecated. Option is kept for backwards compatibility and is ignored])]) + if test "x$enable_$2" != x; then + AC_MSG_WARN([Option --enable-$1 is deprecated and will be ignored.]) + + if test "x$3" != x; then + AC_MSG_WARN([$3]) + fi + + fi +]) + +############################################################################### +# Register an --enable-* argument as an alias for another argument. +# $1: The name of the enable argument for the new alias, not including --enable- +# $2: The full name of the argument of which to make this an alias, including +# --enable- or --with-. +AC_DEFUN([UTIL_ALIASED_ARG_ENABLE], +[ + AC_ARG_ENABLE($1, [AS_HELP_STRING([--enable-$1], [alias for $2])], [ + # Use m4 to strip initial -- from target ($2), convert - to _, prefix enable_ + # to new alias name, and create a shell variable assignment, + # e.g.: enable_old_style="$enable_new_alias" + m4_translit(m4_bpatsubst($2, --), -, _)="$[enable_]m4_translit($1, -, _)" + ]) +]) + +############################################################################### +# Test that variable $1 denoting a program is not empty. If empty, exit with an error. +# $1: variable to check +AC_DEFUN([UTIL_CHECK_NONEMPTY], +[ + if test "x[$]$1" = x; then + AC_MSG_ERROR([Could not find required tool for $1]) + fi +]) + +############################################################################### +# Setup a tool for the given variable. If correctly specified by the user, +# use that value, otherwise search for the tool using the supplied code snippet. +# $1: variable to set +# $2: code snippet to call to look for the tool +# $3: code snippet to call if variable was used to find tool +AC_DEFUN([UTIL_SETUP_TOOL], +[ + # Publish this variable in the help. + AC_ARG_VAR($1, [Override default value for $1]) + + if [[ -z "${$1+x}" ]]; then + # The variable is not set by user, try to locate tool using the code snippet + $2 + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !$1! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!$1!/} + if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then + # If it failed, the variable was not from the command line. Ignore it, + # but warn the user (except for BASH, which is always set by the calling BASH). + if test "x$1" != xBASH; then + AC_MSG_WARN([Ignoring value of $1 from the environment. Use command line variables instead.]) + fi + # Try to locate tool using the code snippet + $2 + else + # If it succeeded, then it was overridden by the user. We will use it + # for the tool. + + # First remove it from the list of overridden variables, so we can test + # for unknown variables in the end. + CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" + + tool_override=[$]$1 + AC_MSG_NOTICE([User supplied override $1="$tool_override"]) + + # Check if we try to supply an empty value + if test "x$tool_override" = x; then + AC_MSG_CHECKING([for $1]) + AC_MSG_RESULT([disabled]) + else + # Split up override in command part and argument part + tool_and_args=($tool_override) + [ tool_command=${tool_and_args[0]} ] + [ unset 'tool_and_args[0]' ] + [ tool_args=${tool_and_args[@]} ] + + # Check if the provided tool contains a complete path. + tool_basename="${tool_command##*/}" + if test "x$tool_basename" = "x$tool_command"; then + # A command without a complete path is provided, search $PATH. + AC_MSG_NOTICE([Will search for user supplied tool "$tool_basename"]) + AC_PATH_PROG($1, $tool_basename) + if test "x[$]$1" = x; then + AC_MSG_ERROR([User supplied tool $1="$tool_basename" could not be found]) + fi + else + # Otherwise we believe it is a complete path. Use it as it is. + AC_MSG_NOTICE([Will use user supplied tool "$tool_command"]) + AC_MSG_CHECKING([for $tool_command]) + if test ! -x "$tool_command"; then + AC_MSG_RESULT([not found]) + AC_MSG_ERROR([User supplied tool $1="$tool_command" does not exist or is not executable]) + fi + $1="$tool_command" + AC_MSG_RESULT([found]) + fi + if test "x$tool_args" != x; then + # If we got arguments, re-append them to the command after the fixup. + $1="[$]$1 $tool_args" + fi + fi + fi + $3 + fi +]) + +############################################################################### +# Call UTIL_SETUP_TOOL with AC_PATH_PROGS to locate the tool +# $1: variable to set +# $2: executable name (or list of names) to look for +# $3: [path] +AC_DEFUN([UTIL_PATH_PROGS], +[ + UTIL_SETUP_TOOL($1, [AC_PATH_PROGS($1, $2, , $3)]) +]) + +############################################################################### +# Call UTIL_SETUP_TOOL with AC_CHECK_TOOLS to locate the tool +# $1: variable to set +# $2: executable name (or list of names) to look for +AC_DEFUN([UTIL_CHECK_TOOLS], +[ + UTIL_SETUP_TOOL($1, [AC_CHECK_TOOLS($1, $2)]) +]) + +############################################################################### +# Like UTIL_PATH_PROGS but fails if no tool was found. +# $1: variable to set +# $2: executable name (or list of names) to look for +# $3: [path] +AC_DEFUN([UTIL_REQUIRE_PROGS], +[ + UTIL_PATH_PROGS($1, $2, , $3) + UTIL_CHECK_NONEMPTY($1) +]) + +############################################################################### +# Like UTIL_SETUP_TOOL but fails if no tool was found. +# $1: variable to set +# $2: autoconf macro to call to look for the special tool +AC_DEFUN([UTIL_REQUIRE_SPECIAL], +[ + UTIL_SETUP_TOOL($1, [$2]) + UTIL_CHECK_NONEMPTY($1) +]) + +############################################################################### +# Like UTIL_REQUIRE_PROGS but also allows for bash built-ins +# $1: variable to set +# $2: executable name (or list of names) to look for +# $3: [path] +AC_DEFUN([UTIL_REQUIRE_BUILTIN_PROGS], +[ + UTIL_SETUP_TOOL($1, [AC_PATH_PROGS($1, $2, , $3)]) + if test "x[$]$1" = x; then + AC_MSG_NOTICE([Required tool $2 not found in PATH, checking built-in]) + if help $2 > /dev/null 2>&1; then + AC_MSG_NOTICE([Found $2 as shell built-in. Using it]) + $1="$2" + else + AC_MSG_ERROR([Required tool $2 also not found as built-in.]) + fi + fi + UTIL_CHECK_NONEMPTY($1) +]) diff --git a/make/autoconf/util_paths.m4 b/make/autoconf/util_paths.m4 new file mode 100644 index 00000000000..9a3d3e2bb04 --- /dev/null +++ b/make/autoconf/util_paths.m4 @@ -0,0 +1,232 @@ +# +# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Appends a string to a path variable, only adding the : when needed. +AC_DEFUN([UTIL_APPEND_TO_PATH], +[ + if test "x$2" != x; then + if test "x[$]$1" = x; then + $1="$2" + else + $1="[$]$1:$2" + fi + fi +]) + +# Prepends a string to a path variable, only adding the : when needed. +AC_DEFUN([UTIL_PREPEND_TO_PATH], +[ + if test "x$2" != x; then + if test "x[$]$1" = x; then + $1="$2" + else + $1="$2:[$]$1" + fi + fi +]) + +################################################################################ +# This will make a path absolute. Assumes it's already a unix path. Also +# resolves ~ to homedir. +AC_DEFUN([UTIL_ABSOLUTE_PATH], +[ + if test "x[$]$1" != x; then + new_path="[$]$1" + + # Use eval to expand a potential ~. This technique does not work if there + # are spaces in the path (which is valid at this point on Windows), so only + # try to apply it if there is an actual ~ first in the path. + if [ [[ "$new_path" = "~"* ]] ]; then + eval new_path="$new_path" + if test ! -f "$new_path" && test ! -d "$new_path"; then + AC_MSG_ERROR([The new_path of $1, which resolves as "$new_path", is not found.]) + fi + fi + + if test -d "$new_path"; then + $1="`cd "$new_path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$new_path"`" + base="`$BASENAME "$new_path"`" + $1="`cd "$dir"; $THEPWDCMD -L`/$base" + fi + fi +]) + +############################################################################### +# This will make sure the given variable points to a full and proper +# path. This means: +# 1) There will be no spaces in the path. On unix platforms, +# spaces in the path will result in an error. On Windows, +# the path will be rewritten using short-style to be space-free. +# 2) The path will be absolute, and it will be in unix-style (on +# cygwin). +# $1: The name of the variable to fix +AC_DEFUN([UTIL_FIXUP_PATH], +[ + # Only process if variable expands to non-empty + if test "x[$]$1" != x; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + UTIL_FIXUP_PATH_CYGWIN($1) + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + UTIL_FIXUP_PATH_MSYS($1) + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then + UTIL_FIXUP_PATH_WSL($1) + else + # We're on a unix platform. Hooray! :) + path="[$]$1" + has_space=`$ECHO "$path" | $GREP " "` + if test "x$has_space" != x; then + AC_MSG_NOTICE([The path of $1, which resolves as "$path", is invalid.]) + AC_MSG_ERROR([Spaces are not allowed in this path.]) + fi + + UTIL_ABSOLUTE_PATH(path) + $1="$path" + fi + fi +]) + +############################################################################### +# This will make sure the given variable points to a executable +# with a full and proper path. This means: +# 1) There will be no spaces in the path. On unix platforms, +# spaces in the path will result in an error. On Windows, +# the path will be rewritten using short-style to be space-free. +# 2) The path will be absolute, and it will be in unix-style (on +# cygwin). +# Any arguments given to the executable is preserved. +# If the input variable does not have a directory specification, then +# it need to be in the PATH. +# $1: The name of the variable to fix +AC_DEFUN([UTIL_FIXUP_EXECUTABLE], +[ + # Only process if variable expands to non-empty + + if test "x[$]$1" != x; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + UTIL_FIXUP_EXECUTABLE_CYGWIN($1) + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + UTIL_FIXUP_EXECUTABLE_MSYS($1) + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then + UTIL_FIXUP_EXECUTABLE_WSL($1) + else + # We're on a unix platform. Hooray! :) + # First separate the path from the arguments. This will split at the first + # space. + complete="[$]$1" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + # This is an absolute path, we can use it without further modifications. + new_path="$path" + fi + + if test "x$new_path" = x; then + AC_MSG_NOTICE([The path of $1, which resolves as "$complete", is not found.]) + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + AC_MSG_NOTICE([This might be caused by spaces in the path, which is not allowed.]) + fi + AC_MSG_ERROR([Cannot locate the the path of $1]) + fi + fi + + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi + + if test "x$complete" != "x$new_complete"; then + $1="$new_complete" + AC_MSG_NOTICE([Rewriting $1 to "$new_complete"]) + fi + fi +]) + +############################################################################### +AC_DEFUN([UTIL_REMOVE_SYMBOLIC_LINKS], +[ + if test "x$OPENJDK_BUILD_OS" != xwindows; then + # Follow a chain of symbolic links. Use readlink + # where it exists, else fall back to horribly + # complicated shell code. + if test "x$READLINK_TESTED" != yes; then + # On MacOSX there is a readlink tool with a different + # purpose than the GNU readlink tool. Check the found readlink. + READLINK_ISGNU=`$READLINK --version 2>&1 | $GREP GNU` + # If READLINK_ISGNU is empty, then it's a non-GNU readlink. Don't use it. + READLINK_TESTED=yes + fi + + if test "x$READLINK" != x && test "x$READLINK_ISGNU" != x; then + $1=`$READLINK -f [$]$1` + else + # Save the current directory for restoring afterwards + STARTDIR=$PWD + COUNTER=0 + sym_link_dir=`$DIRNAME [$]$1` + sym_link_file=`$BASENAME [$]$1` + cd $sym_link_dir + # Use -P flag to resolve symlinks in directories. + cd `$THEPWDCMD -P` + sym_link_dir=`$THEPWDCMD -P` + # Resolve file symlinks + while test $COUNTER -lt 20; do + ISLINK=`$LS -l $sym_link_dir/$sym_link_file | $GREP '\->' | $SED -e 's/.*-> \(.*\)/\1/'` + if test "x$ISLINK" == x; then + # This is not a symbolic link! We are done! + break + fi + # Again resolve directory symlinks since the target of the just found + # link could be in a different directory + cd `$DIRNAME $ISLINK` + sym_link_dir=`$THEPWDCMD -P` + sym_link_file=`$BASENAME $ISLINK` + let COUNTER=COUNTER+1 + done + cd $STARTDIR + $1=$sym_link_dir/$sym_link_file + fi + fi +]) + diff --git a/make/autoconf/basics_windows.m4 b/make/autoconf/util_windows.m4 similarity index 65% rename from make/autoconf/basics_windows.m4 rename to make/autoconf/util_windows.m4 index 1c2536c72ce..625f360f2f9 100644 --- a/make/autoconf/basics_windows.m4 +++ b/make/autoconf/util_windows.m4 @@ -23,7 +23,7 @@ # questions. # -AC_DEFUN([BASIC_WINDOWS_REWRITE_AS_UNIX_PATH], +AC_DEFUN([UTIL_REWRITE_AS_UNIX_PATH], [ windows_path="[$]$1" if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then @@ -42,7 +42,7 @@ AC_DEFUN([BASIC_WINDOWS_REWRITE_AS_UNIX_PATH], fi ]) -AC_DEFUN([BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH], +AC_DEFUN([UTIL_REWRITE_AS_WINDOWS_MIXED_PATH], [ unix_path="[$]$1" if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then @@ -60,7 +60,7 @@ AC_DEFUN([BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH], # Helper function which possibly converts a path using DOS-style short mode. # If so, the updated path is stored in $new_path. # $1: The path to check -AC_DEFUN([BASIC_MAKE_WINDOWS_SPACE_SAFE_CYGWIN], +AC_DEFUN([UTIL_MAKE_WINDOWS_SPACE_SAFE_CYGWIN], [ input_path="$1" # Check if we need to convert this using DOS-style short mode. If the path @@ -96,7 +96,7 @@ AC_DEFUN([BASIC_MAKE_WINDOWS_SPACE_SAFE_CYGWIN], # Helper function which possibly converts a path using DOS-style short mode. # If so, the updated path is stored in $new_path. # $1: The path to check -AC_DEFUN([BASIC_MAKE_WINDOWS_SPACE_SAFE_MSYS], +AC_DEFUN([UTIL_MAKE_WINDOWS_SPACE_SAFE_MSYS], [ input_path="$1" # Check if we need to convert this using DOS-style short mode. If the path @@ -113,7 +113,7 @@ AC_DEFUN([BASIC_MAKE_WINDOWS_SPACE_SAFE_MSYS], # Helper function which possibly converts a path using DOS-style short mode. # If so, the updated path is stored in $new_path. # $1: The path to check -AC_DEFUN([BASIC_MAKE_WINDOWS_SPACE_SAFE_WSL], +AC_DEFUN([UTIL_MAKE_WINDOWS_SPACE_SAFE_WSL], [ input_path="$1" # Check if we need to convert this using DOS-style short mode. If the path @@ -124,31 +124,31 @@ AC_DEFUN([BASIC_MAKE_WINDOWS_SPACE_SAFE_WSL], if test "x$has_forbidden_chars" != x; then # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) TOPDIR_windows="$TOPDIR" - BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH([TOPDIR_windows]) + UTIL_REWRITE_AS_WINDOWS_MIXED_PATH([TOPDIR_windows]) # First convert to Windows path to make input valid for cmd - BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH([input_path]) + UTIL_REWRITE_AS_WINDOWS_MIXED_PATH([input_path]) new_path=`$CMD /c $TOPDIR_windows/make/scripts/windowsShortName.bat "$input_path" \ | $SED -e 's|\r||g' \ | $TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Rewrite back to unix style - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH([new_path]) + UTIL_REWRITE_AS_UNIX_PATH([new_path]) fi ]) -# FIXME: The BASIC_FIXUP_*_CYGWIN/MSYS is most likely too convoluted +# FIXME: The UTIL_FIXUP_*_CYGWIN/MSYS is most likely too convoluted # and could probably be heavily simplified. However, all changes in this # area tend to need lot of testing in different scenarios, and in lack of # proper unit testing, cleaning this up has not been deemed worth the effort # at the moment. -AC_DEFUN([BASIC_FIXUP_PATH_CYGWIN], +AC_DEFUN([UTIL_FIXUP_PATH_CYGWIN], [ # Input might be given as Windows format, start by converting to # unix format. path="[$]$1" new_path=`$CYGPATH -u "$path"` - BASIC_ABSOLUTE_PATH(new_path) + UTIL_ABSOLUTE_PATH(new_path) # Cygwin tries to hide some aspects of the Windows file system, such that binaries are # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered @@ -165,7 +165,7 @@ AC_DEFUN([BASIC_FIXUP_PATH_CYGWIN], # Call helper function which possibly converts this using DOS-style short mode. # If so, the updated path is stored in $new_path. - BASIC_MAKE_WINDOWS_SPACE_SAFE_CYGWIN([$new_path]) + UTIL_MAKE_WINDOWS_SPACE_SAFE_CYGWIN([$new_path]) if test "x$path" != "x$new_path"; then $1="$new_path" @@ -173,7 +173,7 @@ AC_DEFUN([BASIC_FIXUP_PATH_CYGWIN], fi ]) -AC_DEFUN([BASIC_FIXUP_PATH_MSYS], +AC_DEFUN([UTIL_FIXUP_PATH_MSYS], [ path="[$]$1" has_colon=`$ECHO $path | $GREP ^.:` @@ -183,10 +183,10 @@ AC_DEFUN([BASIC_FIXUP_PATH_MSYS], new_path=`cmd //c echo $path` fi - BASIC_ABSOLUTE_PATH(new_path) + UTIL_ABSOLUTE_PATH(new_path) - BASIC_MAKE_WINDOWS_SPACE_SAFE_MSYS([$new_path]) - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(new_path) + UTIL_MAKE_WINDOWS_SPACE_SAFE_MSYS([$new_path]) + UTIL_REWRITE_AS_UNIX_PATH(new_path) if test "x$path" != "x$new_path"; then $1="$new_path" AC_MSG_NOTICE([Rewriting $1 to "$new_path"]) @@ -196,18 +196,18 @@ AC_DEFUN([BASIC_FIXUP_PATH_MSYS], all_fixpath_prefixes=("${all_fixpath_prefixes@<:@@@:>@}" "${new_path:0:10}") ]) -AC_DEFUN([BASIC_FIXUP_PATH_WSL], +AC_DEFUN([UTIL_FIXUP_PATH_WSL], [ # Input might be given as Windows format, start by converting to # unix format. new_path="[$]$1" - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH([new_path]) + UTIL_REWRITE_AS_UNIX_PATH([new_path]) - BASIC_ABSOLUTE_PATH(new_path) + UTIL_ABSOLUTE_PATH(new_path) # Call helper function which possibly converts this using DOS-style short mode. # If so, the updated path is stored in $new_path. - BASIC_MAKE_WINDOWS_SPACE_SAFE_WSL([$new_path]) + UTIL_MAKE_WINDOWS_SPACE_SAFE_WSL([$new_path]) if test "x$path" != "x$new_path"; then $1="$new_path" @@ -215,7 +215,7 @@ AC_DEFUN([BASIC_FIXUP_PATH_WSL], fi ]) -AC_DEFUN([BASIC_FIXUP_EXECUTABLE_CYGWIN], +AC_DEFUN([UTIL_FIXUP_EXECUTABLE_CYGWIN], [ # First separate the path from the arguments. This will split at the first # space. @@ -291,12 +291,12 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE_CYGWIN], # Call helper function which possibly converts this using DOS-style short mode. # If so, the updated path is stored in $new_path. new_path="$input_to_shortpath" - BASIC_MAKE_WINDOWS_SPACE_SAFE_CYGWIN([$input_to_shortpath]) + UTIL_MAKE_WINDOWS_SPACE_SAFE_CYGWIN([$input_to_shortpath]) # remove trailing .exe if any new_path="${new_path/%.exe/}" ]) -AC_DEFUN([BASIC_FIXUP_EXECUTABLE_MSYS], +AC_DEFUN([UTIL_FIXUP_EXECUTABLE_MSYS], [ # First separate the path from the arguments. This will split at the first # space. @@ -308,7 +308,7 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE_MSYS], # Input might be given as Windows format, start by converting to # unix format. new_path="$path" - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(new_path) + UTIL_REWRITE_AS_UNIX_PATH(new_path) # Now try to locate executable using which new_path=`$WHICH "$new_path" 2> /dev/null` @@ -321,7 +321,7 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE_MSYS], path="$complete" arguments="EOL" new_path="$path" - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(new_path) + UTIL_REWRITE_AS_UNIX_PATH(new_path) new_path=`$WHICH "$new_path" 2> /dev/null` # bat and cmd files are not always considered executable in MSYS causing which @@ -330,7 +330,7 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE_MSYS], && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ && test "x`$LS \"$path\" 2>/dev/null`" != x; then new_path="$path" - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(new_path) + UTIL_REWRITE_AS_UNIX_PATH(new_path) fi if test "x$new_path" = x; then @@ -352,9 +352,9 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE_MSYS], else # Not in mixed or Windows style, start by that. new_path=`cmd //c echo $new_path` - BASIC_MAKE_WINDOWS_SPACE_SAFE_MSYS([$new_path]) + UTIL_MAKE_WINDOWS_SPACE_SAFE_MSYS([$new_path]) # Output is in $new_path - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(new_path) + UTIL_REWRITE_AS_UNIX_PATH(new_path) # remove trailing .exe if any new_path="${new_path/%.exe/}" @@ -363,7 +363,7 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE_MSYS], fi ]) -AC_DEFUN([BASIC_FIXUP_EXECUTABLE_WSL], +AC_DEFUN([UTIL_FIXUP_EXECUTABLE_WSL], [ # First separate the path from the arguments. This will split at the first # space. @@ -375,7 +375,7 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE_WSL], # Input might be given as Windows format, start by converting to # unix format. new_path="$path" - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH([new_path]) + UTIL_REWRITE_AS_UNIX_PATH([new_path]) # Now try to locate executable using which new_path_bak="$new_path" @@ -394,7 +394,7 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE_WSL], path="$complete" arguments="EOL" new_path="$path" - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH([new_path]) + UTIL_REWRITE_AS_UNIX_PATH([new_path]) new_path_bak="$new_path" new_path=`$WHICH "$new_path" 2> /dev/null` # bat and cmd files are not considered executable in WSL @@ -433,164 +433,6 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE_WSL], # Call helper function which possibly converts this using DOS-style short mode. # If so, the updated path is stored in $new_path. new_path="$input_to_shortpath" - BASIC_MAKE_WINDOWS_SPACE_SAFE_WSL([$input_to_shortpath]) + UTIL_MAKE_WINDOWS_SPACE_SAFE_WSL([$input_to_shortpath]) ]) -# Setup basic configuration paths, and platform-specific stuff related to PATHs. -AC_DEFUN([BASIC_CHECK_PATHS_WINDOWS], -[ - SRC_ROOT_LENGTH=`$THEPWDCMD -L|$WC -m` - if test $SRC_ROOT_LENGTH -gt 100; then - AC_MSG_ERROR([Your base path is too long. It is $SRC_ROOT_LENGTH characters long, but only 100 is supported]) - fi - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - AC_MSG_CHECKING([cygwin release]) - CYGWIN_VERSION=`$UNAME -r` - AC_MSG_RESULT([$CYGWIN_VERSION]) - WINDOWS_ENV_VENDOR='cygwin' - WINDOWS_ENV_VERSION="$CYGWIN_VERSION" - - CYGWIN_VERSION_OLD=`$ECHO $CYGWIN_VERSION | $GREP -e '^1\.[0-6]'` - if test "x$CYGWIN_VERSION_OLD" != x; then - AC_MSG_NOTICE([Your cygwin is too old. You are running $CYGWIN_VERSION, but at least cygwin 1.7 is required. Please upgrade.]) - AC_MSG_ERROR([Cannot continue]) - fi - if test "x$CYGPATH" = x; then - AC_MSG_ERROR([Something is wrong with your cygwin installation since I cannot find cygpath.exe in your path]) - fi - AC_MSG_CHECKING([cygwin root directory as unix-style path]) - # The cmd output ends with Windows line endings (CR/LF) - cygwin_winpath_root=`cd / ; cmd /c cd | $TR -d '\r\n'` - # Force cygpath to report the proper root by including a trailing space, and then stripping it off again. - CYGWIN_ROOT_PATH=`$CYGPATH -u "$cygwin_winpath_root " | $CUT -f 1 -d " "` - AC_MSG_RESULT([$CYGWIN_ROOT_PATH]) - WINDOWS_ENV_ROOT_PATH="$CYGWIN_ROOT_PATH" - test_cygdrive_prefix=`$ECHO $CYGWIN_ROOT_PATH | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - AC_MSG_ERROR([Your cygdrive prefix is not /cygdrive. This is currently not supported. Change with mount -c.]) - fi - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - AC_MSG_CHECKING([msys release]) - MSYS_VERSION=`$UNAME -r` - AC_MSG_RESULT([$MSYS_VERSION]) - - WINDOWS_ENV_VENDOR='msys' - WINDOWS_ENV_VERSION="$MSYS_VERSION" - - AC_MSG_CHECKING([msys root directory as unix-style path]) - # The cmd output ends with Windows line endings (CR/LF), the grep command will strip that away - MSYS_ROOT_PATH=`cd / ; cmd /c cd | $GREP ".*"` - BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(MSYS_ROOT_PATH) - AC_MSG_RESULT([$MSYS_ROOT_PATH]) - WINDOWS_ENV_ROOT_PATH="$MSYS_ROOT_PATH" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then - AC_MSG_CHECKING([Windows version]) - # m4 replaces [ and ] so we use @<:@ and @:>@ instead - WINDOWS_VERSION=`$CMD /c ver.exe | $EGREP -o '(@<:@0-9@:>@+\.)+@<:@0-9@:>@+'` - AC_MSG_RESULT([$WINDOWS_VERSION]) - - AC_MSG_CHECKING([WSL kernel version]) - WSL_KERNEL_VERSION=`$UNAME -v` - AC_MSG_RESULT([$WSL_KERNEL_VERSION]) - - AC_MSG_CHECKING([WSL kernel release]) - WSL_KERNEL_RELEASE=`$UNAME -r` - AC_MSG_RESULT([$WSL_KERNEL_RELEASE]) - - AC_MSG_CHECKING([WSL distribution]) - WSL_DISTRIBUTION=`$LSB_RELEASE -d | sed 's/Description:\t//'` - AC_MSG_RESULT([$WSL_DISTRIBUTION]) - - WINDOWS_ENV_VENDOR='WSL' - WINDOWS_ENV_VERSION="$WSL_DISTRIBUTION $WSL_KERNEL_VERSION $WSL_KERNEL_RELEASE (on Windows build $WINDOWS_VERSION)" - else - AC_MSG_ERROR([Unknown Windows environment. Neither cygwin, msys, nor wsl was detected.]) - fi - - # Test if windows or unix (cygwin/msys) find is first in path. - AC_MSG_CHECKING([what kind of 'find' is first on the PATH]) - FIND_BINARY_OUTPUT=`find --version 2>&1` - if test "x`echo $FIND_BINARY_OUTPUT | $GREP GNU`" != x; then - AC_MSG_RESULT([unix style]) - elif test "x`echo $FIND_BINARY_OUTPUT | $GREP FIND`" != x; then - AC_MSG_RESULT([Windows]) - AC_MSG_NOTICE([Your path contains Windows tools (C:\Windows\system32) before your unix (cygwin or msys) tools.]) - AC_MSG_NOTICE([This will not work. Please correct and make sure /usr/bin (or similar) is first in path.]) - AC_MSG_ERROR([Cannot continue]) - else - AC_MSG_RESULT([unknown]) - AC_MSG_WARN([It seems that your find utility is non-standard.]) - fi -]) - -AC_DEFUN_ONCE([BASIC_COMPILE_FIXPATH], -[ - # When using cygwin or msys, we need a wrapper binary that renames - # /cygdrive/c/ arguments into c:/ arguments and peeks into - # @files and rewrites these too! This wrapper binary is - # called fixpath. - FIXPATH= - if test "x$OPENJDK_BUILD_OS" = xwindows; then - AC_MSG_CHECKING([if fixpath can be created]) - FIXPATH_SRC="$TOPDIR/make/src/native/fixpath.c" - FIXPATH_BIN="$CONFIGURESUPPORT_OUTPUTDIR/bin/fixpath.exe" - FIXPATH_DIR="$CONFIGURESUPPORT_OUTPUTDIR/fixpath" - if test "x$OPENJDK_BUILD_OS_ENV" = xwindows.cygwin; then - # Important to keep the .exe suffix on Cygwin for Hotspot makefiles - FIXPATH="$FIXPATH_BIN -c" - elif test "x$OPENJDK_BUILD_OS_ENV" = xwindows.msys; then - # Take all collected prefixes and turn them into a -m/c/foo@/c/bar@... command line - # @ was chosen as separator to minimize risk of other tools messing around with it - all_unique_prefixes=`echo "${all_fixpath_prefixes@<:@@@:>@}" \ - | tr ' ' '\n' | $GREP '^/./' | $SORT | $UNIQ` - fixpath_argument_list=`echo $all_unique_prefixes | tr ' ' '@'` - FIXPATH="$FIXPATH_BIN -m$fixpath_argument_list" - elif test "x$OPENJDK_BUILD_OS_ENV" = xwindows.wsl; then - FIXPATH="$FIXPATH_BIN -w" - fi - FIXPATH_SRC_W="$FIXPATH_SRC" - FIXPATH_BIN_W="$FIXPATH_BIN" - BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH([FIXPATH_SRC_W]) - BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH([FIXPATH_BIN_W]) - $RM -rf $FIXPATH_BIN $FIXPATH_DIR - $MKDIR -p $FIXPATH_DIR $CONFIGURESUPPORT_OUTPUTDIR/bin - cd $FIXPATH_DIR - $CC $FIXPATH_SRC_W -Fe$FIXPATH_BIN_W > $FIXPATH_DIR/fixpath1.log 2>&1 - cd $CONFIGURE_START_DIR - - if test ! -x $FIXPATH_BIN; then - AC_MSG_RESULT([no]) - cat $FIXPATH_DIR/fixpath1.log - AC_MSG_ERROR([Could not create $FIXPATH_BIN]) - fi - AC_MSG_RESULT([yes]) - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then - OLD_WSLENV="$WSLENV" - WSLENV=`$ECHO $WSLENV | $SED 's/PATH\/l://'` - BASIC_APPEND_TO_PATH(WSLENV, "FIXPATH_PATH") - export WSLENV - export FIXPATH_PATH=$VS_PATH_WINDOWS - AC_MSG_NOTICE([FIXPATH_PATH is $FIXPATH_PATH]) - AC_MSG_NOTICE([Rewriting WSLENV from $OLD_WSLENV to $WSLENV]) - fi - - AC_MSG_CHECKING([if fixpath.exe works]) - cd $FIXPATH_DIR - $FIXPATH $CC $FIXPATH_SRC -Fe$FIXPATH_DIR/fixpath2.exe \ - > $FIXPATH_DIR/fixpath2.log 2>&1 - cd $CONFIGURE_START_DIR - if test ! -x $FIXPATH_DIR/fixpath2.exe; then - AC_MSG_RESULT([no]) - cat $FIXPATH_DIR/fixpath2.log - AC_MSG_ERROR([fixpath did not work!]) - fi - AC_MSG_RESULT([yes]) - - FIXPATH_DETACH_FLAG="--detach" - fi - - AC_SUBST(FIXPATH) - AC_SUBST(FIXPATH_DETACH_FLAG) -]) diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index c3a7b0b1bd4..9b08709e697 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -917,6 +917,9 @@ define SetupNativeCompilationBody ifeq ($(call isTargetOs, windows), true) $1_EXTRA_LDFLAGS += -debug "-pdb:$$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).pdb" \ "-map:$$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).map" + ifeq ($(SHIP_DEBUG_SYMBOLS), public) + $1_EXTRA_LDFLAGS += "-pdbstripped:$$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).stripped.pdb" + endif $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).pdb \ $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).map diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 1bd85efcf78..67955c1dbc2 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -251,7 +251,7 @@ var getJibProfilesCommon = function (input, data) { configure_args: concat(["--enable-jtreg-failure-handler"], "--with-exclude-translations=de,es,fr,it,ko,pt_BR,sv,ca,tr,cs,sk,ja_JP_A,ja_JP_HA,ja_JP_HI,ja_JP_I,zh_TW,zh_HK", "--disable-manpages", - "--with-jvm-features=-shenandoahgc", + "--disable-jvm-feature-shenandoahgc", versionArgs(input, common)) }; // Extra settings for debug profiles @@ -866,7 +866,7 @@ var getJibProfilesProfiles = function (input, common, data) { testImageProfile = testedProfile; } var testedProfileTest = testImageProfile + ".test" - var testOnlyMake = [ "run-test-prebuilt", "LOG_CMDLINES=true", "JTREG_VERBOSE=fail,error,time" ]; + var testOnlyMake = [ "test-prebuilt", "LOG_CMDLINES=true", "JTREG_VERBOSE=fail,error,time" ]; if (testedProfile.endsWith("-gcov")) { testOnlyMake = concat(testOnlyMake, "GCOV_ENABLED=true") } @@ -974,7 +974,7 @@ var getJibProfilesDependencies = function (input, common) { solaris_x64: "SS12u4-Solaris11u1+1.0", solaris_sparcv9: "SS12u6-Solaris11u3+1.0", windows_x64: "VS2017-15.9.16+1.0", - linux_aarch64: "gcc8.2.0-Fedora27+1.0", + linux_aarch64: "gcc8.3.0-OL7.6+1.0", linux_arm: "gcc8.2.0-Fedora27+1.0", linux_ppc64le: "gcc8.2.0-Fedora27+1.0", linux_s390x: "gcc8.2.0-Fedora27+1.0" @@ -1004,9 +1004,17 @@ var getJibProfilesDependencies = function (input, common) { ? input.get("gnumake", "install_path") + "/cygwin/bin" : input.get("gnumake", "install_path") + "/bin"); - var dependencies = { - - boot_jdk: { + if (input.build_cpu == 'aarch64') { + boot_jdk = { + organization: common.organization, + ext: "tar.gz", + module: "jdk-linux_aarch64", + revision: "13+1.0", + configure_args: "--with-boot-jdk=" + common.boot_jdk_home, + environment_path: common.boot_jdk_home + "/bin" + } + } else { + boot_jdk = { server: "jpg", product: "jdk", version: common.boot_jdk_version, @@ -1015,7 +1023,11 @@ var getJibProfilesDependencies = function (input, common) { + boot_jdk_platform + "_bin" + boot_jdk_ext, configure_args: "--with-boot-jdk=" + common.boot_jdk_home, environment_path: common.boot_jdk_home + "/bin" - }, + } + } + + var dependencies = { + boot_jdk: boot_jdk, devkit: { organization: common.organization, @@ -1041,11 +1053,12 @@ var getJibProfilesDependencies = function (input, common) { }, jtreg: { - server: "javare", - revision: "4.2", - build_number: "b16", + server: "jpg", + product: "jtreg", + version: "5.0", + build_number: "b01", checksum_file: "MD5_VALUES", - file: "jtreg_bin-4.2.zip", + file: "bundles/jtreg_bin-5.0.zip", environment_name: "JT_HOME", environment_path: input.get("jtreg", "install_path") + "/jtreg/bin" }, diff --git a/make/data/charsetmapping/IBM943.c2b b/make/data/charsetmapping/IBM943.c2b new file mode 100644 index 00000000000..f5424fd9842 --- /dev/null +++ b/make/data/charsetmapping/IBM943.c2b @@ -0,0 +1,49 @@ +# +# source: 34B003AF.RPMAP130 +# c->b only entries +# +815C 2015 +8160 FF5E +8161 2225 +817C FF0D +88A0 555E +898B 7130 +89A8 9DD7 +8A9A 5699 +8BA0 4FE0 +8BEB 8EC0 +8C71 7E6B +8C74 8346 +8CB2 9E7C +8D8D 9EB4 +8DF2 6805 +8EC6 5C62 +8F4A 7E61 +8FD3 8523 +8FDD 91AC +90E4 87EC +917E 6414 +9189 7626 +91CB 9A52 +925C 7C1E +92CD 6451 +9355 5861 +935E 985A +9398 79B1 +93C0 7006 +9458 56CA +948D 525D +94AC 6F51 +94AE 91B1 +966A 9830 +96CB 9EB5 +9789 840A +9858 881F +9BA0 5C5B +9DB7 6522 +9E94 688E +E379 7E48 +E445 8141 +E8F6 9839 +FA55 FFE4 +FA59 F86F diff --git a/make/devkit/Tools.gmk b/make/devkit/Tools.gmk index 435ad9145df..590e7df117c 100644 --- a/make/devkit/Tools.gmk +++ b/make/devkit/Tools.gmk @@ -51,9 +51,17 @@ endif $(info ARCH=$(ARCH)) +KERNEL_HEADERS_RPM := kernel-headers + ifeq ($(BASE_OS), OL) - BASE_URL := http://yum.oracle.com/repo/OracleLinux/OL6/4/base/$(ARCH)/ - LINUX_VERSION := OL6.4 + ifeq ($(ARCH), aarch64) + BASE_URL := http://yum.oracle.com/repo/OracleLinux/OL7/6/base/$(ARCH)/ + LINUX_VERSION := OL7.6 + KERNEL_HEADERS_RPM := kernel-uek-headers + else + BASE_URL := http://yum.oracle.com/repo/OracleLinux/OL6/4/base/$(ARCH)/ + LINUX_VERSION := OL6.4 + endif else ifeq ($(BASE_OS), Fedora) DEFAULT_OS_VERSION := 27 ifeq ($(BASE_OS_VERSION), ) @@ -118,7 +126,7 @@ GDB := http://ftp.gnu.org/gnu/gdb/${gdb_ver}.tar.xz # RPMs used by all BASE_OS RPM_LIST := \ - kernel-headers \ + $(KERNEL_HEADERS_RPM) \ glibc glibc-headers glibc-devel \ cups-libs cups-devel \ libX11 libX11-devel \ diff --git a/make/hotspot/lib/JvmFeatures.gmk b/make/hotspot/lib/JvmFeatures.gmk index 9f784eae784..2fbc959f46d 100644 --- a/make/hotspot/lib/JvmFeatures.gmk +++ b/make/hotspot/lib/JvmFeatures.gmk @@ -186,95 +186,95 @@ ifeq ($(call check-jvm-feature, link-time-opt), true) JVM_LDFLAGS_FEATURES += -O3 -flto -fuse-linker-plugin -fno-strict-aliasing endif -ifeq ($(call check-jvm-feature, minimal), true) - ifeq ($(call check-jvm-feature, link-time-opt), false) - JVM_OPTIMIZATION := SIZE - OPT_SPEED_SRC := \ - allocation.cpp \ - assembler.cpp \ - barrierSet.cpp \ - basicLock.cpp \ - biasedLocking.cpp \ - bytecode.cpp \ - bytecodeInterpreter.cpp \ - c1_Compilation.cpp \ - c1_Compiler.cpp \ - c1_GraphBuilder.cpp \ - c1_LinearScan.cpp \ - c1_LIR.cpp \ - ciEnv.cpp \ - ciObjectFactory.cpp \ - codeBlob.cpp \ - constantPool.cpp \ - constMethod.cpp \ - classLoader.cpp \ - classLoaderData.cpp \ - classFileParser.cpp \ - classFileStream.cpp \ - cpCache.cpp \ - defNewGeneration.cpp \ - frame_arm.cpp \ - frame_aarch64.cpp \ - frame_ppc.cpp \ - frame_s390.cpp \ - frame_x86.cpp \ - genCollectedHeap.cpp \ - generation.cpp \ - genMarkSweep.cpp \ - growableArray.cpp \ - handles.cpp \ - hashtable.cpp \ - heap.cpp \ - icache.cpp \ - icache_arm.cpp \ - icache_aarch64.cpp \ - icache_ppc.cpp \ - icache_s390.cpp \ - icache_x86.cpp \ - instanceKlass.cpp \ - invocationCounter.cpp \ - iterator.cpp \ - javaCalls.cpp \ - javaClasses.cpp \ - jniFastGetField_arm.cpp \ - jvm.cpp \ - linkResolver.cpp \ - klass.cpp \ - klassVtable.cpp \ - markSweep.cpp \ - memRegion.cpp \ - memoryPool.cpp \ - method.cpp \ - methodHandles.cpp \ - methodHandles_arm.cpp \ - methodLiveness.cpp \ - metaspace.cpp \ - mutex.cpp \ - mutexLocker.cpp \ - nativeLookup.cpp \ - objArrayKlass.cpp \ - os_linux.cpp \ - os_linux_arm.cpp \ - resourceArea.cpp \ - rewriter.cpp \ - sharedRuntime.cpp \ - signature.cpp \ - space.cpp \ - stackMapTable.cpp \ - symbolTable.cpp \ - systemDictionary.cpp \ - symbol.cpp \ - synchronizer.cpp \ - timer.cpp \ - typeArrayKlass.cpp \ - unsafe.cpp \ - utf8.cpp \ - vmSymbols.cpp \ - # +ifeq ($(call check-jvm-feature, opt-size), true) + JVM_OPTIMIZATION := SIZE + OPT_SPEED_SRC := \ + allocation.cpp \ + assembler.cpp \ + barrierSet.cpp \ + basicLock.cpp \ + biasedLocking.cpp \ + bytecode.cpp \ + bytecodeInterpreter.cpp \ + c1_Compilation.cpp \ + c1_Compiler.cpp \ + c1_GraphBuilder.cpp \ + c1_LinearScan.cpp \ + c1_LIR.cpp \ + ciEnv.cpp \ + ciObjectFactory.cpp \ + codeBlob.cpp \ + constantPool.cpp \ + constMethod.cpp \ + classLoader.cpp \ + classLoaderData.cpp \ + classFileParser.cpp \ + classFileStream.cpp \ + cpCache.cpp \ + defNewGeneration.cpp \ + frame_arm.cpp \ + frame_aarch64.cpp \ + frame_ppc.cpp \ + frame_s390.cpp \ + frame_x86.cpp \ + genCollectedHeap.cpp \ + generation.cpp \ + genMarkSweep.cpp \ + growableArray.cpp \ + handles.cpp \ + hashtable.cpp \ + heap.cpp \ + icache.cpp \ + icache_arm.cpp \ + icache_aarch64.cpp \ + icache_ppc.cpp \ + icache_s390.cpp \ + icache_x86.cpp \ + instanceKlass.cpp \ + invocationCounter.cpp \ + iterator.cpp \ + javaCalls.cpp \ + javaClasses.cpp \ + jniFastGetField_arm.cpp \ + jvm.cpp \ + linkResolver.cpp \ + klass.cpp \ + klassVtable.cpp \ + markSweep.cpp \ + memRegion.cpp \ + memoryPool.cpp \ + method.cpp \ + methodHandles.cpp \ + methodHandles_arm.cpp \ + methodLiveness.cpp \ + metaspace.cpp \ + mutex.cpp \ + mutexLocker.cpp \ + nativeLookup.cpp \ + objArrayKlass.cpp \ + os_linux.cpp \ + os_linux_arm.cpp \ + resourceArea.cpp \ + rewriter.cpp \ + sharedRuntime.cpp \ + signature.cpp \ + space.cpp \ + stackMapTable.cpp \ + symbolTable.cpp \ + systemDictionary.cpp \ + symbol.cpp \ + synchronizer.cpp \ + timer.cpp \ + typeArrayKlass.cpp \ + unsafe.cpp \ + utf8.cpp \ + vmSymbols.cpp \ + # - $(foreach s, $(OPT_SPEED_SRC), \ - $(eval BUILD_LIBJVM_$s_OPTIMIZATION := HIGHEST_JVM)) + $(foreach s, $(OPT_SPEED_SRC), \ + $(eval BUILD_LIBJVM_$s_OPTIMIZATION := HIGHEST_JVM)) + ifneq ($(filter $(TOOLCHAIN_TYPE), gcc clang), ) BUILD_LIBJVM_systemDictionary.cpp_CXXFLAGS := -fno-optimize-sibling-calls endif endif diff --git a/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp b/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp index b863411aa95..c0ace26b684 100644 --- a/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp +++ b/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp @@ -213,7 +213,7 @@ int generateJvmOffsets(GEN_variant gen_variant) { GEN_VALUE(AccessFlags_NATIVE, JVM_ACC_NATIVE); GEN_VALUE(ConstMethod_has_linenumber_table, ConstMethod::_has_linenumber_table); GEN_OFFS(AccessFlags, _flags); - GEN_OFFS(Symbol, _length_and_refcount); + GEN_OFFS(Symbol, _length); GEN_OFFS(Symbol, _body); printf("\n"); diff --git a/make/idea/template/vcs.xml b/make/idea/template/vcs.xml index 21997970079..ee4faed424a 100644 --- a/make/idea/template/vcs.xml +++ b/make/idea/template/vcs.xml @@ -1,6 +1,6 @@ - + diff --git a/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java b/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java index f84adcbc02e..d140fbb30b9 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java @@ -294,7 +294,6 @@ class Bundle { } // First, weed out any empty timezone or metazone names from myMap. - // Fill in any missing abbreviations if locale is "en". for (Iterator it = myMap.keySet().iterator(); it.hasNext();) { String key = it.next(); if (key.startsWith(CLDRConverter.TIMEZONE_ID_PREFIX) @@ -307,10 +306,6 @@ class Bundle { it.remove(); continue; } - - if (id.equals("en")) { - fillInJREs(key, nameMap); - } } } for (Iterator it = myMap.keySet().iterator(); it.hasNext();) { @@ -636,42 +631,6 @@ class Bundle { return null; } - static List jreTimeZoneNames = Arrays.asList(TimeZoneNames.getContents()); - private void fillInJREs(String key, Map map) { - String tzid = null; - - if (key.startsWith(CLDRConverter.METAZONE_ID_PREFIX)) { - // Look for tzid - String meta = key.substring(CLDRConverter.METAZONE_ID_PREFIX.length()); - if (meta.equals("GMT")) { - tzid = meta; - } else { - for (String tz : CLDRConverter.handlerMetaZones.keySet()) { - if (CLDRConverter.handlerMetaZones.get(tz).equals(meta)) { - tzid = tz; - break; - } - } - } - } else { - tzid = key.substring(CLDRConverter.TIMEZONE_ID_PREFIX.length()); - } - - if (tzid != null) { - for (Object[] jreZone : jreTimeZoneNames) { - if (jreZone[0].equals(tzid)) { - for (int i = 0; i < ZONE_NAME_KEYS.length; i++) { - if (map.get(ZONE_NAME_KEYS[i]) == null) { - String[] jreNames = (String[])jreZone[1]; - map.put(ZONE_NAME_KEYS[i], jreNames[i]); - } - } - break; - } - } - } - } - /** * Perform a generic conversion of CLDR date-time format pattern letter based * on the support given by the SimpleDateFormat and the j.t.f.DateTimeFormatter diff --git a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java index ad30b3297c1..b598f3ff3fc 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package build.tools.cldrconverter; -import static build.tools.cldrconverter.Bundle.jreTimeZoneNames; import build.tools.cldrconverter.BundleGenerator.BundleType; import java.io.File; import java.io.IOException; @@ -89,7 +88,9 @@ public class CLDRConverter { static final String ZONE_NAME_PREFIX = "timezone.displayname."; static final String METAZONE_ID_PREFIX = "metazone.id."; static final String PARENT_LOCALE_PREFIX = "parentLocale."; + static final String META_EMPTY_ZONE_NAME = "EMPTY_ZONE"; static final String[] EMPTY_ZONE = {"", "", "", "", "", ""}; + static final String META_ETCUTC_ZONE_NAME = "ETC_UTC"; private static SupplementDataParseHandler handlerSuppl; private static LikelySubtagsParseHandler handlerLikelySubtags; @@ -684,61 +685,7 @@ public class CLDRConverter { } private static Map extractZoneNames(Map map, String id) { - Map names = new HashMap<>(); - - // Copy over missing time zone ids from JRE for English locale - if (id.equals("en")) { - Map jreMetaMap = new HashMap<>(); - jreTimeZoneNames.stream().forEach(e -> { - String tzid = (String)e[0]; - String[] data = (String[])e[1]; - - if (map.get(TIMEZONE_ID_PREFIX + tzid) == null && - handlerMetaZones.get(tzid) == null || - handlerMetaZones.get(tzid) != null && - map.get(METAZONE_ID_PREFIX + handlerMetaZones.get(tzid)) == null) { - - // First, check the alias - String canonID = canonicalTZMap.get(tzid); - if (canonID != null && !tzid.equals(canonID)) { - Object value = map.get(TIMEZONE_ID_PREFIX + canonID); - if (value != null) { - names.put(tzid, value); - return; - } else { - String meta = handlerMetaZones.get(canonID); - if (meta != null) { - value = map.get(METAZONE_ID_PREFIX + meta); - if (value != null) { - names.put(tzid, meta); - return; - } - } - } - } - - // Check the CLDR meta key - Optional> cldrMeta = - handlerMetaZones.getData().entrySet().stream() - .filter(me -> - Arrays.deepEquals(data, - (String[])map.get(METAZONE_ID_PREFIX + me.getValue()))) - .findAny(); - cldrMeta.ifPresentOrElse(meta -> names.put(tzid, meta.getValue()), () -> { - // Check the JRE meta key, add if there is not. - Optional> jreMeta = - jreMetaMap.entrySet().stream() - .filter(jm -> Arrays.deepEquals(data, jm.getKey())) - .findAny(); - jreMeta.ifPresentOrElse(meta -> names.put(tzid, meta.getValue()), () -> { - String metaName = "JRE_" + tzid.replaceAll("[/-]", "_"); - names.put(METAZONE_ID_PREFIX + metaName, data); - names.put(tzid, metaName); - }); - }); - } - }); - } + Map names = new TreeMap<>(KeyComparator.INSTANCE); getAvailableZoneIds().stream().forEach(tzid -> { // If the tzid is deprecated, get the data for the replacement id @@ -747,7 +694,14 @@ public class CLDRConverter { Object data = map.get(TIMEZONE_ID_PREFIX + tzKey); if (data instanceof String[]) { - names.put(tzid, data); + // Hack for UTC. UTC is an alias to Etc/UTC in CLDR + if (tzid.equals("Etc/UTC") && !map.containsKey(TIMEZONE_ID_PREFIX + "UTC")) { + names.put(METAZONE_ID_PREFIX + META_ETCUTC_ZONE_NAME, data); + names.put(tzid, META_ETCUTC_ZONE_NAME); + names.put("UTC", META_ETCUTC_ZONE_NAME); + } else { + names.put(tzid, data); + } } else { String meta = handlerMetaZones.get(tzKey); if (meta != null) { @@ -764,24 +718,23 @@ public class CLDRConverter { // exemplar cities. Map exCities = map.entrySet().stream() - .filter(e -> e.getKey().startsWith(CLDRConverter.EXEMPLAR_CITY_PREFIX)) - .collect(Collectors - .toMap(Map.Entry::getKey, Map.Entry::getValue)); + .filter(e -> e.getKey().startsWith(CLDRConverter.EXEMPLAR_CITY_PREFIX)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); names.putAll(exCities); - if (!id.equals("en") && - !names.isEmpty()) { - // CLDR does not have UTC entry, so add it here. - names.put("UTC", EMPTY_ZONE); - - // no metazone zones - Arrays.asList(handlerMetaZones.get(MetaZonesParseHandler.NO_METAZONE_KEY) - .split("\\s")).stream() - .forEach(tz -> { - names.put(tz, EMPTY_ZONE); - }); + // If there's no UTC entry at this point, add an empty one + if (!names.isEmpty() && !names.containsKey("UTC")) { + names.putIfAbsent(METAZONE_ID_PREFIX + META_EMPTY_ZONE_NAME, EMPTY_ZONE); + names.put("UTC", META_EMPTY_ZONE_NAME); } + // Finally some compatibility stuff + ZoneId.SHORT_IDS.entrySet().stream() + .filter(e -> !names.containsKey(e.getKey()) && names.containsKey(e.getValue())) + .forEach(e -> { + names.put(e.getKey(), names.get(e.getValue())); + }); + return names; } diff --git a/make/jdk/src/classes/build/tools/taglet/ModuleGraph.java b/make/jdk/src/classes/build/tools/taglet/ModuleGraph.java index 98117b3cdb6..5f28cb41ba4 100644 --- a/make/jdk/src/classes/build/tools/taglet/ModuleGraph.java +++ b/make/jdk/src/classes/build/tools/taglet/ModuleGraph.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,9 +73,7 @@ public class ModuleGraph implements Taglet { + getImage(moduleName, imageFile, -1, true) + ""; } - return "
    " - + "Module Graph:\n" - + "
    " + return "
    Module Graph:
    " + "
    " + "" + getImage(moduleName, imageFile, thumbnailHeight, false) diff --git a/make/jdk/src/classes/build/tools/taglet/ToolGuide.java b/make/jdk/src/classes/build/tools/taglet/ToolGuide.java index b6e57275a00..ae70d424222 100644 --- a/make/jdk/src/classes/build/tools/taglet/ToolGuide.java +++ b/make/jdk/src/classes/build/tools/taglet/ToolGuide.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,7 +95,7 @@ public class ToolGuide implements Taglet { return ""; StringBuilder sb = new StringBuilder(); - sb.append("
    Tool Guides:
    \n") + sb.append("
    Tool Guides:
    \n") .append("
    "); boolean needComma = false; diff --git a/make/launcher/Launcher-java.base.gmk b/make/launcher/Launcher-java.base.gmk index e26e423df8a..cc5fb458312 100644 --- a/make/launcher/Launcher-java.base.gmk +++ b/make/launcher/Launcher-java.base.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,24 +34,13 @@ JAVA_RC_FLAGS += -I$(TOPDIR)/src/java.base/windows/native/launcher/icons ################################################################################ -# On windows, the debuginfo files get the same name as for java.dll. Build -# into another dir and copy selectively so debuginfo for java.dll isn't -# overwritten. $(eval $(call SetupBuildLauncher, java, \ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \ EXTRA_RC_FLAGS := $(JAVA_RC_FLAGS), \ VERSION_INFO_RESOURCE := $(JAVA_VERSION_INFO_RESOURCE), \ - OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/java_objs, \ OPTIMIZATION := HIGH, \ )) -$(SUPPORT_OUTPUTDIR)/modules_cmds/java.base/java$(EXE_SUFFIX): $(BUILD_LAUNCHER_java) - $(call MakeTargetDir) - $(RM) $@ - $(CP) $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/java_objs/java$(EXE_SUFFIX) $@ - -TARGETS += $(SUPPORT_OUTPUTDIR)/modules_cmds/java.base/java$(EXE_SUFFIX) - ifeq ($(call isTargetOs, windows), true) $(eval $(call SetupBuildLauncher, javaw, \ CFLAGS := -DJAVAW -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \ diff --git a/make/scripts/compare.sh b/make/scripts/compare.sh index 1e203e5961c..e1fd8a3aa63 100644 --- a/make/scripts/compare.sh +++ b/make/scripts/compare.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -810,7 +810,6 @@ compare_bin_file() { # pdb files. PDB_DIRS="$(ls -d \ {$OTHER,$THIS}/support/modules_{cmds,libs}/{*,*/*} \ - {$OTHER,$THIS}/support/native/java.base/java_objs \ {$OTHER,$THIS}/support/native/jdk.incubator.jpackage/* \ )" export _NT_SYMBOL_PATH="$(echo $PDB_DIRS | tr ' ' ';')" diff --git a/make/src/classes/build/tools/jfr/GenerateJfrFiles.java b/make/src/classes/build/tools/jfr/GenerateJfrFiles.java index 544336007e0..f90dc2b7e5b 100644 --- a/make/src/classes/build/tools/jfr/GenerateJfrFiles.java +++ b/make/src/classes/build/tools/jfr/GenerateJfrFiles.java @@ -636,6 +636,12 @@ public class GenerateJfrFiles { } out.write(" }"); } + + // Avoid clash with static commit() method + if (event.fields.isEmpty()) { + return; + } + out.write(""); StringJoiner sj = new StringJoiner(",\n "); if (event.startTime) { diff --git a/src/hotspot/.mx.jvmci/mx_jvmci.py b/src/hotspot/.mx.jvmci/mx_jvmci.py index 98f4f6e3485..9162cd16af8 100644 --- a/src/hotspot/.mx.jvmci/mx_jvmci.py +++ b/src/hotspot/.mx.jvmci/mx_jvmci.py @@ -1,7 +1,7 @@ # # ---------------------------------------------------------------------------------------------------- # -# Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -153,8 +153,8 @@ To build hotspot and import it into the JDK: "mx make hotspot import-hotspot" # JDK10 must be bootstrapped with a JDK9 compliance = mx.JavaCompliance('9') jdk9 = mx.get_jdk(compliance.exactMatch, versionDescription=compliance.value) - cmd = ['sh', 'configure', '--with-debug-level=' + _vm.debugLevel, '--with-native-debug-symbols=external', '--disable-precompiled-headers', '--with-jvm-features=graal', - '--with-jvm-variants=' + _vm.jvmVariant, '--disable-warnings-as-errors', '--with-boot-jdk=' + jdk9.home, '--with-jvm-features=graal'] + cmd = ['sh', 'configure', '--with-debug-level=' + _vm.debugLevel, '--with-native-debug-symbols=external', '--disable-precompiled-headers', '--enable-jvm-feature-graal', + '--with-jvm-variants=' + _vm.jvmVariant, '--disable-warnings-as-errors', '--with-boot-jdk=' + jdk9.home] mx.run(cmd, cwd=_get_jdk_dir()) cmd = [mx.gmake_cmd(), 'CONF=' + _vm.debugLevel] if mx.get_opts().verbose: diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 8a7e3ea9624..aba731983fb 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -2074,15 +2074,24 @@ const bool Matcher::match_rule_supported(int opcode) { return ret_value; // Per default match rules are supported. } +// Identify extra cases that we might want to provide match rules for vector nodes and +// other intrinsics guarded with vector length (vlen) and element type (bt). const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { + if (!match_rule_supported(opcode)) { + return false; + } - // TODO - // identify extra cases that we might want to provide match rules for - // e.g. Op_ vector nodes and other intrinsics while guarding with vlen - bool ret_value = match_rule_supported(opcode); - // Add rules here. + // Special cases which require vector length + switch (opcode) { + case Op_MulAddVS2VI: { + if (vlen != 4) { + return false; + } + break; + } + } - return ret_value; // Per default match rules are supported. + return true; // Per default match rules are supported. } const bool Matcher::has_predicated_vectors(void) { @@ -2257,8 +2266,7 @@ void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) { Unimplemented(); } -// Advertise here if the CPU requires explicit rounding operations to -// implement the UseStrictFP mode. +// Advertise here if the CPU requires explicit rounding operations to implement strictfp mode. const bool Matcher::strict_fp_requires_explicit_rounding = false; // Are floats converted to double when stored to stack during @@ -10556,6 +10564,22 @@ instruct smnegL(iRegLNoSp dst, iRegIorL2I src1, iRegIorL2I src2, immL0 zero) %{ ins_pipe(imac_reg_reg); %} +// Combined Multiply-Add Shorts into Integer (dst = src1 * src2 + src3 * src4) + +instruct muladdS2I(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, iRegIorL2I src3, iRegIorL2I src4) %{ + match(Set dst (MulAddS2I (Binary src1 src2) (Binary src3 src4))); + + ins_cost(INSN_COST * 5); + format %{ "mulw rscratch1, $src1, $src2\n\t" + "maddw $dst, $src3, $src4, rscratch1" %} + + ins_encode %{ + __ mulw(rscratch1, as_Register($src1$$reg), as_Register($src2$$reg)); + __ maddw(as_Register($dst$$reg), as_Register($src3$$reg), as_Register($src4$$reg), rscratch1); %} + + ins_pipe(imac_reg_reg); +%} + // Integer Divide instruct divI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{ @@ -16936,6 +16960,30 @@ instruct vmls2D(vecX dst, vecX src1, vecX src2) %{ ins_pipe(vmuldiv_fp128); %} +// --------------- Vector Multiply-Add Shorts into Integer -------------------- + +instruct vmuladdS2I(vecX dst, vecX src1, vecX src2, vecX tmp) %{ + predicate(n->in(1)->bottom_type()->is_vect()->element_basic_type() == T_SHORT); + match(Set dst (MulAddVS2VI src1 src2)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "smullv $tmp, $src1, $src2\t# vector (4H)\n\t" + "smullv $dst, $src1, $src2\t# vector (8H)\n\t" + "addpv $dst, $tmp, $dst\t# vector (4S)\n\t" %} + ins_encode %{ + __ smullv(as_FloatRegister($tmp$$reg), __ T4H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + __ smullv(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + __ addpv(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($tmp$$reg), + as_FloatRegister($dst$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + // --------------------------------- DIV -------------------------------------- instruct vdiv2F(vecD dst, vecD src1, vecD src2) @@ -17313,7 +17361,7 @@ instruct vsrl16B(vecX dst, vecX src, vecX shift, vecX tmp) %{ instruct vsll8B_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 4 || n->as_Vector()->length() == 8); - match(Set dst (LShiftVB src shift)); + match(Set dst (LShiftVB src (LShiftCntV shift))); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (8B)" %} ins_encode %{ @@ -17332,7 +17380,7 @@ instruct vsll8B_imm(vecD dst, vecD src, immI shift) %{ instruct vsll16B_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 16); - match(Set dst (LShiftVB src shift)); + match(Set dst (LShiftVB src (LShiftCntV shift))); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (16B)" %} ins_encode %{ @@ -17352,7 +17400,7 @@ instruct vsll16B_imm(vecX dst, vecX src, immI shift) %{ instruct vsra8B_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 4 || n->as_Vector()->length() == 8); - match(Set dst (RShiftVB src shift)); + match(Set dst (RShiftVB src (RShiftCntV shift))); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (8B)" %} ins_encode %{ @@ -17366,7 +17414,7 @@ instruct vsra8B_imm(vecD dst, vecD src, immI shift) %{ instruct vsra16B_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 16); - match(Set dst (RShiftVB src shift)); + match(Set dst (RShiftVB src (RShiftCntV shift))); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (16B)" %} ins_encode %{ @@ -17381,7 +17429,7 @@ instruct vsra16B_imm(vecX dst, vecX src, immI shift) %{ instruct vsrl8B_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 4 || n->as_Vector()->length() == 8); - match(Set dst (URShiftVB src shift)); + match(Set dst (URShiftVB src (RShiftCntV shift))); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (8B)" %} ins_encode %{ @@ -17400,7 +17448,7 @@ instruct vsrl8B_imm(vecD dst, vecD src, immI shift) %{ instruct vsrl16B_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 16); - match(Set dst (URShiftVB src shift)); + match(Set dst (URShiftVB src (RShiftCntV shift))); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (16B)" %} ins_encode %{ @@ -17517,7 +17565,7 @@ instruct vsrl8S(vecX dst, vecX src, vecX shift, vecX tmp) %{ instruct vsll4S_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 2 || n->as_Vector()->length() == 4); - match(Set dst (LShiftVS src shift)); + match(Set dst (LShiftVS src (LShiftCntV shift))); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (4H)" %} ins_encode %{ @@ -17536,7 +17584,7 @@ instruct vsll4S_imm(vecD dst, vecD src, immI shift) %{ instruct vsll8S_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 8); - match(Set dst (LShiftVS src shift)); + match(Set dst (LShiftVS src (LShiftCntV shift))); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (8H)" %} ins_encode %{ @@ -17556,7 +17604,7 @@ instruct vsll8S_imm(vecX dst, vecX src, immI shift) %{ instruct vsra4S_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 2 || n->as_Vector()->length() == 4); - match(Set dst (RShiftVS src shift)); + match(Set dst (RShiftVS src (LShiftCntV shift))); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (4H)" %} ins_encode %{ @@ -17570,7 +17618,7 @@ instruct vsra4S_imm(vecD dst, vecD src, immI shift) %{ instruct vsra8S_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 8); - match(Set dst (RShiftVS src shift)); + match(Set dst (RShiftVS src (LShiftCntV shift))); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (8H)" %} ins_encode %{ @@ -17585,7 +17633,7 @@ instruct vsra8S_imm(vecX dst, vecX src, immI shift) %{ instruct vsrl4S_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 2 || n->as_Vector()->length() == 4); - match(Set dst (URShiftVS src shift)); + match(Set dst (URShiftVS src (RShiftCntV shift))); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (4H)" %} ins_encode %{ @@ -17604,7 +17652,7 @@ instruct vsrl4S_imm(vecD dst, vecD src, immI shift) %{ instruct vsrl8S_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 8); - match(Set dst (URShiftVS src shift)); + match(Set dst (URShiftVS src (RShiftCntV shift))); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (8H)" %} ins_encode %{ @@ -17717,7 +17765,7 @@ instruct vsrl4I(vecX dst, vecX src, vecX shift, vecX tmp) %{ instruct vsll2I_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 2); - match(Set dst (LShiftVI src shift)); + match(Set dst (LShiftVI src (LShiftCntV shift))); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (2S)" %} ins_encode %{ @@ -17730,7 +17778,7 @@ instruct vsll2I_imm(vecD dst, vecD src, immI shift) %{ instruct vsll4I_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 4); - match(Set dst (LShiftVI src shift)); + match(Set dst (LShiftVI src (LShiftCntV shift))); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (4S)" %} ins_encode %{ @@ -17743,7 +17791,7 @@ instruct vsll4I_imm(vecX dst, vecX src, immI shift) %{ instruct vsra2I_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 2); - match(Set dst (RShiftVI src shift)); + match(Set dst (RShiftVI src (RShiftCntV shift))); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (2S)" %} ins_encode %{ @@ -17756,7 +17804,7 @@ instruct vsra2I_imm(vecD dst, vecD src, immI shift) %{ instruct vsra4I_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 4); - match(Set dst (RShiftVI src shift)); + match(Set dst (RShiftVI src (RShiftCntV shift))); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (4S)" %} ins_encode %{ @@ -17769,7 +17817,7 @@ instruct vsra4I_imm(vecX dst, vecX src, immI shift) %{ instruct vsrl2I_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 2); - match(Set dst (URShiftVI src shift)); + match(Set dst (URShiftVI src (RShiftCntV shift))); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (2S)" %} ins_encode %{ @@ -17782,7 +17830,7 @@ instruct vsrl2I_imm(vecD dst, vecD src, immI shift) %{ instruct vsrl4I_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 4); - match(Set dst (URShiftVI src shift)); + match(Set dst (URShiftVI src (RShiftCntV shift))); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (4S)" %} ins_encode %{ @@ -17842,7 +17890,7 @@ instruct vsrl2L(vecX dst, vecX src, vecX shift, vecX tmp) %{ instruct vsll2L_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 2); - match(Set dst (LShiftVL src shift)); + match(Set dst (LShiftVL src (LShiftCntV shift))); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (2D)" %} ins_encode %{ @@ -17855,7 +17903,7 @@ instruct vsll2L_imm(vecX dst, vecX src, immI shift) %{ instruct vsra2L_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 2); - match(Set dst (RShiftVL src shift)); + match(Set dst (RShiftVL src (RShiftCntV shift))); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (2D)" %} ins_encode %{ @@ -17868,7 +17916,7 @@ instruct vsra2L_imm(vecX dst, vecX src, immI shift) %{ instruct vsrl2L_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 2); - match(Set dst (URShiftVL src shift)); + match(Set dst (URShiftVL src (RShiftCntV shift))); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (2D)" %} ins_encode %{ diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index 9f6297c62cb..1491b53dabf 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -2259,6 +2259,8 @@ public: INSN(mlsv, 1, 0b100101, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(sshl, 0, 0b010001, true); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D INSN(ushl, 1, 0b010001, true); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D + INSN(addpv, 0, 0b101111, true); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D + INSN(smullv, 0, 0b110000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(umullv, 1, 0b110000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(umlalv, 1, 0b100000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp index a8e4394de0c..a743e16a1bf 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp @@ -40,10 +40,10 @@ #include "oops/objArrayKlass.hpp" #include "runtime/frame.inline.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/powerOfTwo.hpp" #include "vmreg_aarch64.inline.hpp" - #ifndef PRODUCT #define COMMENT(x) do { __ block_comment(x); } while (0) #else @@ -1747,7 +1747,7 @@ void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr code == lir_add ? __ add(dreg, lreg_lo, c) : __ sub(dreg, lreg_lo, c); break; case lir_div: - assert(c > 0 && is_power_of_2_long(c), "divisor must be power-of-2 constant"); + assert(c > 0 && is_power_of_2(c), "divisor must be power-of-2 constant"); if (c == 1) { // move lreg_lo to dreg if divisor is 1 __ mov(dreg, lreg_lo); @@ -1760,7 +1760,7 @@ void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr } break; case lir_rem: - assert(c > 0 && is_power_of_2_long(c), "divisor must be power-of-2 constant"); + assert(c > 0 && is_power_of_2(c), "divisor must be power-of-2 constant"); if (c == 1) { // move 0 to dreg if divisor is 1 __ mov(dreg, zr); diff --git a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp index eecc18d2b3e..312002e851a 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp @@ -37,6 +37,7 @@ #include "ci/ciTypeArrayKlass.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" +#include "utilities/powerOfTwo.hpp" #include "vmreg_aarch64.inline.hpp" #ifdef ASSERT @@ -447,7 +448,7 @@ void LIRGenerator::do_ArithmeticOp_Long(ArithmeticOp* x) { // no need to do div-by-zero check if the divisor is a non-zero constant if (c != 0) need_zero_check = false; // do not load right if the divisor is a power-of-2 constant - if (c > 0 && is_power_of_2_long(c)) { + if (c > 0 && is_power_of_2(c)) { right.dont_load_item(); } else { right.load_item(); diff --git a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp index 99883ddf32d..bc49f84985a 100644 --- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp @@ -43,6 +43,7 @@ #include "runtime/signature.hpp" #include "runtime/vframe.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/powerOfTwo.hpp" #include "vmreg_aarch64.inline.hpp" diff --git a/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp b/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp index 33be72a19a5..b1e04095535 100644 --- a/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp @@ -61,7 +61,6 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G); define_pd_global(bool, CICompileOSR, true ); #endif // !TIERED define_pd_global(bool, UseTypeProfile, false); -define_pd_global(bool, RoundFPResults, true ); define_pd_global(bool, LIRFillDelaySlots, false); define_pd_global(bool, OptimizeSinglePrecision, true ); diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp index d3e4432cbb7..b6e706aa8a6 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -59,16 +59,8 @@ bool frame::safe_for_sender(JavaThread *thread) { address unextended_sp = (address)_unextended_sp; // consider stack guards when trying to determine "safe" stack pointers - static size_t stack_guard_size = os::uses_stack_guard_pages() ? - (JavaThread::stack_red_zone_size() + JavaThread::stack_yellow_zone_size()) : 0; - size_t usable_stack_size = thread->stack_size() - stack_guard_size; - // sp must be within the usable part of the stack (not in guards) - bool sp_safe = (sp < thread->stack_base()) && - (sp >= thread->stack_base() - usable_stack_size); - - - if (!sp_safe) { + if (!thread->is_in_usable_stack(sp)) { return false; } @@ -84,16 +76,14 @@ bool frame::safe_for_sender(JavaThread *thread) { // So unextended sp must be within the stack but we need not to check // that unextended sp >= sp - - bool unextended_sp_safe = (unextended_sp < thread->stack_base()); - - if (!unextended_sp_safe) { + if (!thread->is_in_full_stack(unextended_sp)) { return false; } // an fp must be within the stack and above (but not equal) sp // second evaluation on fp+ is added to handle situation where fp is -1 - bool fp_safe = (fp < thread->stack_base() && (fp > sp) && (((fp + (return_addr_offset * sizeof(void*))) < thread->stack_base()))); + bool fp_safe = thread->is_in_stack_range_excl(fp, sp) && + thread->is_in_full_stack(fp + (return_addr_offset * sizeof(void*))); // We know sp/unextended_sp are safe only fp is questionable here @@ -155,7 +145,7 @@ bool frame::safe_for_sender(JavaThread *thread) { sender_sp = _unextended_sp + _cb->frame_size(); // Is sender_sp safe? - if ((address)sender_sp >= thread->stack_base()) { + if (!thread->is_in_full_stack((address)sender_sp)) { return false; } sender_unextended_sp = sender_sp; @@ -172,9 +162,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // only if the sender is interpreted/call_stub (c1 too?) are we certain that the saved fp // is really a frame pointer. - bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp); - - if (!saved_fp_safe) { + if (!thread->is_in_stack_range_excl((address)saved_fp, (address)sender_sp)) { return false; } @@ -209,9 +197,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // Could be the call_stub if (StubRoutines::returns_to_call_stub(sender_pc)) { - bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp); - - if (!saved_fp_safe) { + if (!thread->is_in_stack_range_excl((address)saved_fp, (address)sender_sp)) { return false; } @@ -222,9 +208,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // Validate the JavaCallWrapper an entry frame must have address jcw = (address)sender.entry_frame_call_wrapper(); - bool jcw_safe = (jcw < thread->stack_base()) && (jcw > (address)sender.fp()); - - return jcw_safe; + return thread->is_in_stack_range_excl(jcw, (address)sender.fp()); } CompiledMethod* nm = sender_blob->as_compiled_method_or_null(); @@ -565,11 +549,7 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { // validate locals address locals = (address) *interpreter_frame_locals_addr(); - - if (locals > thread->stack_base() || locals < (address) fp()) return false; - - // We'd have to be pretty unlucky to be mislead at this point - return true; + return thread->is_in_stack_range_incl(locals, (address)fp()); } BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) { diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp index 0dca6833461..e564f965ac4 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp @@ -100,7 +100,7 @@ LIR_Opr ShenandoahBarrierSetC1::atomic_xchg_at_resolved(LIRAccess& access, LIRIt __ xchg(access.resolved_addr(), value_opr, result, tmp); if (access.is_oop()) { - result = load_reference_barrier(access.gen(), result, LIR_OprFact::addressConst(0)); + result = load_reference_barrier(access.gen(), result, LIR_OprFact::addressConst(0), false); LIR_Opr tmp = gen->new_register(type); __ move(result, tmp); result = tmp; diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp index d099ffc4b51..74dc35bcb6c 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp @@ -581,7 +581,11 @@ void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assemble __ bind(slow_path); ce->store_parameter(res, 0); ce->store_parameter(addr, 1); - __ far_call(RuntimeAddress(bs->load_reference_barrier_rt_code_blob()->code_begin())); + if (stub->is_native()) { + __ far_call(RuntimeAddress(bs->load_reference_barrier_native_rt_code_blob()->code_begin())); + } else { + __ far_call(RuntimeAddress(bs->load_reference_barrier_rt_code_blob()->code_begin())); + } __ b(*stub->continuation()); } @@ -636,14 +640,16 @@ void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAss __ epilogue(); } -void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm) { +void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, bool is_native) { __ prologue("shenandoah_load_reference_barrier", false); // arg0 : object to be resolved __ push_call_clobbered_registers(); __ load_parameter(0, r0); __ load_parameter(1, r1); - if (UseCompressedOops) { + if (is_native) { + __ mov(lr, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native)); + } else if (UseCompressedOops) { __ mov(lr, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_narrow)); } else { __ mov(lr, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier)); diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp index 4cf589c6596..e2a45425235 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp @@ -72,7 +72,7 @@ public: void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub); void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub); void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm); - void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm); + void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, bool is_native); #endif virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp index 1a9df423ade..4891be542fb 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp @@ -43,7 +43,7 @@ #include "runtime/safepointMechanism.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/thread.inline.hpp" - +#include "utilities/powerOfTwo.hpp" void InterpreterMacroAssembler::narrow(Register result) { diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index a63fcfc891a..c8d3dde8c16 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -47,6 +47,7 @@ #include "runtime/jniHandles.inline.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/thread.hpp" +#include "utilities/powerOfTwo.hpp" #ifdef COMPILER1 #include "c1/c1_LIRAssembler.hpp" #endif diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index 34973d49f75..2168a8c835c 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -28,6 +28,7 @@ #include "asm/assembler.hpp" #include "oops/compressedOops.hpp" +#include "utilities/powerOfTwo.hpp" // MacroAssembler extends Assembler by frequently used macros. // diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index 973a0a7eb68..48aa12c2c79 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -43,6 +43,7 @@ #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" #include "utilities/align.hpp" +#include "utilities/powerOfTwo.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index 0f68771dcb3..d31cd5f0994 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -49,6 +49,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/powerOfTwo.hpp" #include #ifndef PRODUCT diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp index f09ccc6a40a..a8ba062f932 100644 --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp @@ -40,6 +40,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" +#include "utilities/powerOfTwo.hpp" #define __ _masm-> diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 427e419824d..890abc9e5d3 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015, 2019, Red Hat Inc. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -451,6 +451,10 @@ void VM_Version::get_processor_features() { if (FLAG_IS_DEFAULT(OptoScheduling)) { OptoScheduling = true; } + + if (FLAG_IS_DEFAULT(AlignVector)) { + AlignVector = AvoidUnalignedAccesses; + } #endif } diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index b525b5c7859..c87d8093cce 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -1140,8 +1140,7 @@ const bool Matcher::misaligned_doubles_ok = false; void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) { } -// Advertise here if the CPU requires explicit rounding operations -// to implement the UseStrictFP mode. +// Advertise here if the CPU requires explicit rounding operations to implement strictfp mode. const bool Matcher::strict_fp_requires_explicit_rounding = false; // Are floats converted to double when stored to stack during deoptimization? @@ -10619,7 +10618,7 @@ instruct vsl16B_reg(vecX dst, vecX src, vecX shift) %{ instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 8); - match(Set dst (LShiftVB src shift)); + match(Set dst (LShiftVB src (LShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ @@ -10635,7 +10634,7 @@ instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{ instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 16); - match(Set dst (LShiftVB src shift)); + match(Set dst (LShiftVB src (LShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ @@ -10674,7 +10673,7 @@ instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{ instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 4); - match(Set dst (LShiftVS src shift)); + match(Set dst (LShiftVS src (LShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ @@ -10729,7 +10728,7 @@ instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{ instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); - match(Set dst (LShiftVI src shift)); + match(Set dst (LShiftVI src (LShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ @@ -10745,7 +10744,7 @@ instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{ instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); - match(Set dst (LShiftVI src shift)); + match(Set dst (LShiftVI src (LShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ @@ -10773,7 +10772,7 @@ instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{ instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 2); - match(Set dst (LShiftVL src shift)); + match(Set dst (LShiftVL src (LShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ @@ -10796,7 +10795,7 @@ instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{ // Chars vector logical right shift instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 4); - match(Set dst (URShiftVS src shift)); + match(Set dst (URShiftVS src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ @@ -10812,7 +10811,7 @@ instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{ instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 8); - match(Set dst (URShiftVS src shift)); + match(Set dst (URShiftVS src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ @@ -10829,7 +10828,7 @@ instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{ // Integers vector logical right shift instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); - match(Set dst (URShiftVI src shift)); + match(Set dst (URShiftVI src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ @@ -10845,7 +10844,7 @@ instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{ instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); - match(Set dst (URShiftVI src shift)); + match(Set dst (URShiftVI src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ @@ -10862,7 +10861,7 @@ instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{ // Longs vector logical right shift instruct vsrl2L_immI(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 2); - match(Set dst (URShiftVL src shift)); + match(Set dst (URShiftVL src (RShiftCntV shift))); size(4); ins_cost(DEFAULT_COST); // FIXME format %{ diff --git a/src/hotspot/cpu/arm/assembler_arm_32.hpp b/src/hotspot/cpu/arm/assembler_arm_32.hpp index fb5ad2e7dd4..44997ddcbce 100644 --- a/src/hotspot/cpu/arm/assembler_arm_32.hpp +++ b/src/hotspot/cpu/arm/assembler_arm_32.hpp @@ -963,8 +963,8 @@ class Assembler : public AbstractAssembler { F(fldmia, 1, 1) F(fldmfd, 1, 1) F(fldmdb, 1, 2) F(fldmea, 1, 2) - F(fstmia, 0, 1) F(fstmfd, 0, 1) - F(fstmdb, 0, 2) F(fstmea, 0, 2) + F(fstmia, 0, 1) F(fstmea, 0, 1) + F(fstmdb, 0, 2) F(fstmfd, 0, 2) #undef F // fconst{s,d} encoding: diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp index 9ab3f64c6b0..ebf81d4ba0c 100644 --- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp @@ -37,6 +37,7 @@ #include "oops/objArrayKlass.hpp" #include "runtime/frame.inline.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/powerOfTwo.hpp" #include "vmreg_arm.inline.hpp" #define __ _masm-> diff --git a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp index 7cf2ff055b5..4dc1f81c63e 100644 --- a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp @@ -40,6 +40,7 @@ #include "gc/shared/cardTableBarrierSet.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" +#include "utilities/powerOfTwo.hpp" #include "vmreg_arm.inline.hpp" #ifdef ASSERT diff --git a/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp index 6c4c3ad408f..dd82f993338 100644 --- a/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp @@ -35,6 +35,7 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" +#include "utilities/powerOfTwo.hpp" // Note: Rtemp usage is this file should not impact C2 and should be // correct as long as it is not implicitly used in lower layers (the diff --git a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp index 4428d3ea5cb..f823660fa25 100644 --- a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp +++ b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp @@ -189,7 +189,7 @@ static OopMap* save_live_registers(StubAssembler* sasm, bool save_fpu_registers __ push(RegisterSet(FP) | RegisterSet(LR)); __ push(RegisterSet(R0, R6) | RegisterSet(R8, R10) | R12 | altFP_7_11); if (save_fpu_registers) { - __ fstmdbd(SP, FloatRegisterSet(D0, fpu_save_size / 2), writeback); + __ fpush(FloatRegisterSet(D0, fpu_save_size / 2)); } else { __ sub(SP, SP, fpu_save_size * wordSize); } @@ -206,7 +206,7 @@ static void restore_live_registers(StubAssembler* sasm, __ block_comment("restore_live_registers"); if (restore_fpu_registers) { - __ fldmiad(SP, FloatRegisterSet(D0, fpu_save_size / 2), writeback); + __ fpop(FloatRegisterSet(D0, fpu_save_size / 2)); if (!restore_R0) { __ add(SP, SP, (R1_offset - fpu_save_size) * wordSize); } diff --git a/src/hotspot/cpu/arm/c1_globals_arm.hpp b/src/hotspot/cpu/arm/c1_globals_arm.hpp index 312c19f8b94..4fd8720c816 100644 --- a/src/hotspot/cpu/arm/c1_globals_arm.hpp +++ b/src/hotspot/cpu/arm/c1_globals_arm.hpp @@ -62,8 +62,6 @@ define_pd_global(uint64_t, MaxRAM, 1ULL*G); define_pd_global(bool, CICompileOSR, true ); #endif // COMPILER2 define_pd_global(bool, UseTypeProfile, false); -define_pd_global(bool, RoundFPResults, false); - define_pd_global(bool, LIRFillDelaySlots, false); define_pd_global(bool, OptimizeSinglePrecision, true); diff --git a/src/hotspot/cpu/arm/frame_arm.cpp b/src/hotspot/cpu/arm/frame_arm.cpp index 5c2e85a068e..180a04f4e8c 100644 --- a/src/hotspot/cpu/arm/frame_arm.cpp +++ b/src/hotspot/cpu/arm/frame_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,31 +57,19 @@ bool frame::safe_for_sender(JavaThread *thread) { address fp = (address)_fp; address unextended_sp = (address)_unextended_sp; - static size_t stack_guard_size = os::uses_stack_guard_pages() ? - (JavaThread::stack_red_zone_size() + JavaThread::stack_yellow_zone_size()) : 0; - size_t usable_stack_size = thread->stack_size() - stack_guard_size; - + // consider stack guards when trying to determine "safe" stack pointers // sp must be within the usable part of the stack (not in guards) - bool sp_safe = (sp != NULL && - (sp <= thread->stack_base()) && - (sp >= thread->stack_base() - usable_stack_size)); - - if (!sp_safe) { + if (!thread->is_in_usable_stack(sp)) { return false; } - bool unextended_sp_safe = (unextended_sp != NULL && - (unextended_sp <= thread->stack_base()) && - (unextended_sp >= sp)); - if (!unextended_sp_safe) { + if (!thread->is_in_stack_range_incl(unextended_sp, sp)) { return false; } // We know sp/unextended_sp are safe. Only fp is questionable here. - bool fp_safe = (fp != NULL && - (fp <= thread->stack_base()) && - fp >= sp); + bool fp_safe = thread->is_in_stack_range_incl(fp, sp); if (_cb != NULL ) { @@ -125,7 +113,7 @@ bool frame::safe_for_sender(JavaThread *thread) { sender_sp = _unextended_sp + _cb->frame_size(); // Is sender_sp safe? - if ((address)sender_sp >= thread->stack_base()) { + if (!thread->is_in_full_stack((address)sender_sp)) { return false; } // With our calling conventions, the return_address should @@ -148,9 +136,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // is really a frame pointer. intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset + link_offset); - bool saved_fp_safe = ((address)saved_fp <= thread->stack_base()) && (saved_fp > sender_sp); - - if (!saved_fp_safe) { + if (!thread->is_in_stack_range_excl((address)saved_fp, (address)sender_sp)) { return false; } @@ -178,9 +164,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // Could be the call_stub if (StubRoutines::returns_to_call_stub(sender_pc)) { intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset + link_offset); - bool saved_fp_safe = ((address)saved_fp <= thread->stack_base()) && (saved_fp >= sender_sp); - - if (!saved_fp_safe) { + if (!thread->is_in_stack_range_excl((address)saved_fp, (address)sender_sp)) { return false; } @@ -191,9 +175,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // Validate the JavaCallWrapper an entry frame must have address jcw = (address)sender.entry_frame_call_wrapper(); - bool jcw_safe = (jcw <= thread->stack_base()) && (jcw > (address)sender.fp()); - - return jcw_safe; + return thread->is_in_stack_range_excl(jcw, (address)sender.fp()); } // If the frame size is 0 something (or less) is bad because every nmethod has a non-zero frame size @@ -500,12 +482,7 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { // validate locals address locals = (address) *interpreter_frame_locals_addr(); - - if (locals > thread->stack_base() || locals < (address) fp()) return false; - - // We'd have to be pretty unlucky to be mislead at this point - - return true; + return thread->is_in_stack_range_incl(locals, (address)fp()); } BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) { diff --git a/src/hotspot/cpu/arm/interp_masm_arm.cpp b/src/hotspot/cpu/arm/interp_masm_arm.cpp index 60ddb874630..f3417f17ee2 100644 --- a/src/hotspot/cpu/arm/interp_masm_arm.cpp +++ b/src/hotspot/cpu/arm/interp_masm_arm.cpp @@ -44,6 +44,7 @@ #include "runtime/frame.inline.hpp" #include "runtime/safepointMechanism.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/powerOfTwo.hpp" //-------------------------------------------------------------------- // Implementation of InterpreterMacroAssembler diff --git a/src/hotspot/cpu/arm/interpreterRT_arm.cpp b/src/hotspot/cpu/arm/interpreterRT_arm.cpp index 1708a3382b2..adc55bbbba3 100644 --- a/src/hotspot/cpu/arm/interpreterRT_arm.cpp +++ b/src/hotspot/cpu/arm/interpreterRT_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,22 +50,22 @@ InterpreterRuntime::SignatureHandlerGenerator::SignatureHandlerGenerator( #ifdef SHARING_FAST_NATIVE_FINGERPRINTS // mapping from SignatureIterator param to (common) type of parsing -static const u1 shared_type[] = { - (u1) SignatureIterator::int_parm, // bool - (u1) SignatureIterator::int_parm, // byte - (u1) SignatureIterator::int_parm, // char - (u1) SignatureIterator::int_parm, // short - (u1) SignatureIterator::int_parm, // int - (u1) SignatureIterator::long_parm, // long +static const BasicType shared_type[] = { + T_INT, // bool + T_INT, // char #ifndef __ABI_HARD__ - (u1) SignatureIterator::int_parm, // float, passed as int - (u1) SignatureIterator::long_parm, // double, passed as long + T_INT, // float, passed as int + T_LONG, // double, passed as long #else - (u1) SignatureIterator::float_parm, // float - (u1) SignatureIterator::double_parm, // double + T_FLOAT, // float + T_DOUBLE, // double #endif - (u1) SignatureIterator::obj_parm, // obj - (u1) SignatureIterator::done_parm // done + T_INT, // byte + T_INT, // short + T_INT, // int + T_LONG, // long + T_OBJECT, // obj + T_OBJECT, // array }; uint64_t InterpreterRuntime::normalize_fast_native_fingerprint(uint64_t fingerprint) { @@ -73,37 +73,33 @@ uint64_t InterpreterRuntime::normalize_fast_native_fingerprint(uint64_t fingerpr // special signature used when the argument list cannot be encoded in a 64 bits value return fingerprint; } - int shift = SignatureIterator::static_feature_size; - uint64_t result = fingerprint & ((1 << shift) - 1); - fingerprint >>= shift; + int shift = SignatureIterator::fp_static_feature_size; + SignatureIterator::fingerprint_t result = fingerprint & ((1 << shift) - 1); - BasicType ret_type = (BasicType) (fingerprint & SignatureIterator::result_feature_mask); + BasicType ret_type = SignatureIterator::fp_return_type(fingerprint); // For ARM, the fast signature handler only needs to know whether // the return value must be unboxed. T_OBJECT and T_ARRAY need not // be distinguished from each other and all other return values // behave like integers with respect to the handler except T_BOOLEAN // which must be mapped to the range 0..1. - bool unbox = (ret_type == T_OBJECT) || (ret_type == T_ARRAY); - if (unbox) { + if (is_reference_type(ret_type)) { ret_type = T_OBJECT; } else if (ret_type != T_BOOLEAN) { ret_type = T_INT; } - result |= ((uint64_t) ret_type) << shift; - shift += SignatureIterator::result_feature_size; - fingerprint >>= SignatureIterator::result_feature_size; + result |= ((SignatureIterator::fingerprint_t) ret_type) << shift; + shift += SignatureIterator::fp_result_feature_size; + SignatureIterator::fingerprint_t unaccumulator = SignatureIterator::fp_start_parameters(fingerprint); while (true) { - uint32_t type = (uint32_t) (fingerprint & SignatureIterator::parameter_feature_mask); - if (type == SignatureIterator::done_parm) { - result |= ((uint64_t) SignatureIterator::done_parm) << shift; + BasicType type = SignatureIterator::fp_next_parameter(unaccumulator); + if (type == (BasicType)SignatureIterator::fp_parameters_done) { return result; } - assert((type >= SignatureIterator::bool_parm) && (type <= SignatureIterator::obj_parm), "check fingerprint encoding"); - int shared = shared_type[type - SignatureIterator::bool_parm]; - result |= ((uint64_t) shared) << shift; - shift += SignatureIterator::parameter_feature_size; - fingerprint >>= SignatureIterator::parameter_feature_size; + assert(SignatureIterator::fp_is_valid_type(type), "garbled fingerprint"); + BasicType shared = shared_type[type - T_BOOLEAN]; + result |= ((SignatureIterator::fingerprint_t) shared) << shift; + shift += SignatureIterator::fp_parameter_feature_size; } } #endif // SHARING_FAST_NATIVE_FINGERPRINTS @@ -222,7 +218,7 @@ void InterpreterRuntime::SignatureHandlerGenerator::pass_double() { void InterpreterRuntime::SignatureHandlerGenerator::generate(uint64_t fingerprint) { iterate(fingerprint); - BasicType result_type = SignatureIterator::return_type(fingerprint); + BasicType result_type = SignatureIterator::fp_return_type(fingerprint); address result_handler = Interpreter::result_handler(result_type); diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.cpp b/src/hotspot/cpu/arm/macroAssembler_arm.cpp index f02d5a50f55..6418cafd58a 100644 --- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp @@ -46,6 +46,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" // Implementation of AddressLiteral diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.hpp b/src/hotspot/cpu/arm/macroAssembler_arm.hpp index ccb01b66851..14bdfaf6d94 100644 --- a/src/hotspot/cpu/arm/macroAssembler_arm.hpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.hpp @@ -26,6 +26,7 @@ #define CPU_ARM_MACROASSEMBLER_ARM_HPP #include "code/relocInfo.hpp" +#include "utilities/powerOfTwo.hpp" class BiasedLockingCounters; @@ -435,6 +436,26 @@ public: fldmias(SP, FloatRegisterSet(fd), writeback, cond); } + void fpush(FloatRegisterSet reg_set) { + fstmdbd(SP, reg_set, writeback); + } + + void fpop(FloatRegisterSet reg_set) { + fldmiad(SP, reg_set, writeback); + } + + void fpush_hardfp(FloatRegisterSet reg_set) { +#ifndef __SOFTFP__ + fpush(reg_set); +#endif + } + + void fpop_hardfp(FloatRegisterSet reg_set) { +#ifndef __SOFTFP__ + fpop(reg_set); +#endif + } + // Order access primitives enum Membar_mask_bits { StoreStore = 1 << 3, diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp index fef14e9643c..47f750a8ff5 100644 --- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp +++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp @@ -37,6 +37,7 @@ #include "runtime/safepointMechanism.hpp" #include "runtime/vframeArray.hpp" #include "utilities/align.hpp" +#include "utilities/powerOfTwo.hpp" #include "vmreg_arm.inline.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" @@ -133,14 +134,14 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, __ push(SAVED_BASE_REGS); if (HaveVFP) { if (VM_Version::has_vfp3_32()) { - __ fstmdbd(SP, FloatRegisterSet(D16, 16), writeback); + __ fpush(FloatRegisterSet(D16, 16)); } else { if (FloatRegisterImpl::number_of_registers > 32) { assert(FloatRegisterImpl::number_of_registers == 64, "nb fp registers should be 64"); __ sub(SP, SP, 32 * wordSize); } } - __ fstmdbd(SP, FloatRegisterSet(D0, 16), writeback); + __ fpush(FloatRegisterSet(D0, 16)); } else { __ sub(SP, SP, fpu_save_size * wordSize); } @@ -174,9 +175,9 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_lr) { if (HaveVFP) { - __ fldmiad(SP, FloatRegisterSet(D0, 16), writeback); + __ fpop(FloatRegisterSet(D0, 16)); if (VM_Version::has_vfp3_32()) { - __ fldmiad(SP, FloatRegisterSet(D16, 16), writeback); + __ fpop(FloatRegisterSet(D16, 16)); } else { if (FloatRegisterImpl::number_of_registers > 32) { assert(FloatRegisterImpl::number_of_registers == 64, "nb fp registers should be 64"); @@ -221,26 +222,21 @@ static void push_param_registers(MacroAssembler* masm, int fp_regs_in_arguments) // R1-R3 arguments need to be saved, but we push 4 registers for 8-byte alignment __ push(RegisterSet(R0, R3)); -#ifdef __ABI_HARD__ // preserve arguments // Likely not needed as the locking code won't probably modify volatile FP registers, // but there is no way to guarantee that if (fp_regs_in_arguments) { // convert fp_regs_in_arguments to a number of double registers int double_regs_num = (fp_regs_in_arguments + 1) >> 1; - __ fstmdbd(SP, FloatRegisterSet(D0, double_regs_num), writeback); + __ fpush_hardfp(FloatRegisterSet(D0, double_regs_num)); } -#endif // __ ABI_HARD__ } static void pop_param_registers(MacroAssembler* masm, int fp_regs_in_arguments) { -#ifdef __ABI_HARD__ if (fp_regs_in_arguments) { int double_regs_num = (fp_regs_in_arguments + 1) >> 1; - __ fldmiad(SP, FloatRegisterSet(D0, double_regs_num), writeback); + __ fpop_hardfp(FloatRegisterSet(D0, double_regs_num)); } -#endif // __ABI_HARD__ - __ pop(RegisterSet(R0, R3)); } @@ -462,11 +458,13 @@ static void patch_callers_callsite(MacroAssembler *masm) { // Pushing an even number of registers for stack alignment. // Selecting R9, which had to be saved anyway for some platforms. __ push(RegisterSet(R0, R3) | R9 | LR); + __ fpush_hardfp(FloatRegisterSet(D0, 8)); __ mov(R0, Rmethod); __ mov(R1, LR); __ call(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite)); + __ fpop_hardfp(FloatRegisterSet(D0, 8)); __ pop(RegisterSet(R0, R3) | R9 | LR); __ bind(skip); diff --git a/src/hotspot/cpu/arm/stubGenerator_arm.cpp b/src/hotspot/cpu/arm/stubGenerator_arm.cpp index 6acaf0fddda..fd82a6d20bb 100644 --- a/src/hotspot/cpu/arm/stubGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/stubGenerator_arm.cpp @@ -41,6 +41,7 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/align.hpp" +#include "utilities/powerOfTwo.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif @@ -179,9 +180,7 @@ class StubGenerator: public StubCodeGenerator { __ mov(Rtemp, SP); __ push(RegisterSet(FP) | RegisterSet(LR)); -#ifndef __SOFTFP__ - __ fstmdbd(SP, FloatRegisterSet(D8, 8), writeback); -#endif + __ fpush_hardfp(FloatRegisterSet(D8, 8)); __ stmdb(SP, RegisterSet(R0, R2) | RegisterSet(R4, R6) | RegisterSet(R8, R10) | altFP_7_11, writeback); __ mov(Rmethod, R3); __ ldmia(Rtemp, RegisterSet(R1, R3) | Rthread); // stacked arguments @@ -243,9 +242,7 @@ class StubGenerator: public StubCodeGenerator { #endif __ pop(RegisterSet(R4, R6) | RegisterSet(R8, R10) | altFP_7_11); -#ifndef __SOFTFP__ - __ fldmiad(SP, FloatRegisterSet(D8, 8), writeback); -#endif + __ fpop_hardfp(FloatRegisterSet(D8, 8)); __ pop(RegisterSet(FP) | RegisterSet(PC)); return start; diff --git a/src/hotspot/cpu/arm/stubRoutinesCrypto_arm.cpp b/src/hotspot/cpu/arm/stubRoutinesCrypto_arm.cpp index c82fa6ca861..b4e58e81944 100644 --- a/src/hotspot/cpu/arm/stubRoutinesCrypto_arm.cpp +++ b/src/hotspot/cpu/arm/stubRoutinesCrypto_arm.cpp @@ -129,7 +129,7 @@ address generate_aescrypt_encryptBlock() { // Register tbox = R3; // transposition box reference __ push (RegisterSet(R4, R12) | LR); - __ fstmdbd(SP, FloatRegisterSet(D0, 4), writeback); + __ fpush(FloatRegisterSet(D0, 4)); __ sub(SP, SP, 32); // preserve TBox references @@ -308,7 +308,7 @@ address generate_aescrypt_encryptBlock() { __ str(R0, Address(R9)); __ add(SP, SP, 32); - __ fldmiad(SP, FloatRegisterSet(D0, 4), writeback);; + __ fpop(FloatRegisterSet(D0, 4)); __ pop(RegisterSet(R4, R12) | PC); return start; @@ -326,7 +326,7 @@ address generate_aescrypt_decryptBlock() { // Register tbox = R3; // transposition box reference __ push (RegisterSet(R4, R12) | LR); - __ fstmdbd(SP, FloatRegisterSet(D0, 4), writeback); + __ fpush(FloatRegisterSet(D0, 4)); __ sub(SP, SP, 32); // retrieve key length @@ -521,7 +521,7 @@ address generate_aescrypt_decryptBlock() { __ str(R0, Address(R9)); __ add(SP, SP, 32); - __ fldmiad(SP, FloatRegisterSet(D0, 4), writeback);; + __ fpop(FloatRegisterSet(D0, 4)); __ pop(RegisterSet(R4, R12) | PC); return start; @@ -680,7 +680,7 @@ address generate_cipherBlockChaining_decryptAESCrypt() { Label decrypt_8_blocks; int quad = 1; // Process 8 blocks in parallel - __ fstmdbd(SP, FloatRegisterSet(D8, 8), writeback); + __ fpush(FloatRegisterSet(D8, 8)); __ sub(SP, SP, 40); // record output buffer end address (used as a block counter) @@ -1020,7 +1020,7 @@ address generate_cipherBlockChaining_decryptAESCrypt() { __ b(decrypt_8_blocks, ne); __ add(SP, SP, 40); - __ fldmiad(SP, FloatRegisterSet(D8, 8), writeback);; + __ fpop(FloatRegisterSet(D8, 8)); } __ bind(cbc_done); diff --git a/src/hotspot/cpu/arm/templateTable_arm.cpp b/src/hotspot/cpu/arm/templateTable_arm.cpp index 60dbabb6944..28eb576fc4d 100644 --- a/src/hotspot/cpu/arm/templateTable_arm.cpp +++ b/src/hotspot/cpu/arm/templateTable_arm.cpp @@ -39,6 +39,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" +#include "utilities/powerOfTwo.hpp" #define __ _masm-> diff --git a/src/hotspot/cpu/ppc/assembler_ppc.cpp b/src/hotspot/cpu/ppc/assembler_ppc.cpp index b646371b6d6..105790c6047 100644 --- a/src/hotspot/cpu/ppc/assembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/assembler_ppc.cpp @@ -37,6 +37,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #ifdef PRODUCT #define BLOCK_COMMENT(str) // nothing @@ -78,13 +79,13 @@ int Assembler::branch_destination(int inst, int pos) { // Low-level andi-one-instruction-macro. void Assembler::andi(Register a, Register s, const long ui16) { - if (is_power_of_2_long(((jlong) ui16)+1)) { + if (is_power_of_2(((jlong) ui16)+1)) { // pow2minus1 clrldi(a, s, 64-log2_long((((jlong) ui16)+1))); - } else if (is_power_of_2_long((jlong) ui16)) { + } else if (is_power_of_2((jlong) ui16)) { // pow2 rlwinm(a, s, 0, 31-log2_long((jlong) ui16), 31-log2_long((jlong) ui16)); - } else if (is_power_of_2_long((jlong)-ui16)) { + } else if (is_power_of_2((jlong)-ui16)) { // negpow2 clrrdi(a, s, log2_long((jlong)-ui16)); } else { diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp index 8d195243535..346f79bcef1 100644 --- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp @@ -40,6 +40,7 @@ #include "runtime/frame.inline.hpp" #include "runtime/safepointMechanism.inline.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/powerOfTwo.hpp" #define __ _masm-> @@ -1762,7 +1763,7 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr switch (code) { case lir_logic_and: - if (uimmss != 0 || (uimms != 0 && (uimm & 0xFFFF) != 0) || is_power_of_2_long(uimm)) { + if (uimmss != 0 || (uimms != 0 && (uimm & 0xFFFF) != 0) || is_power_of_2(uimm)) { __ andi(d, l, uimm); // special cases } else if (uimms != 0) { __ andis_(d, l, uimms); } else { __ andi_(d, l, uimm); } diff --git a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp index 88ef0cd9878..9c15fbccfbd 100644 --- a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp @@ -37,6 +37,7 @@ #include "ci/ciTypeArrayKlass.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" +#include "utilities/powerOfTwo.hpp" #include "vmreg_ppc.inline.hpp" #ifdef ASSERT @@ -574,13 +575,13 @@ inline bool can_handle_logic_op_as_uimm(ValueType *type, Bytecodes::Code bc) { // see Assembler::andi if (bc == Bytecodes::_iand && - (is_power_of_2_long(int_or_long_const+1) || - is_power_of_2_long(int_or_long_const) || - is_power_of_2_long(-int_or_long_const))) return true; + (is_power_of_2(int_or_long_const+1) || + is_power_of_2(int_or_long_const) || + is_power_of_2(-int_or_long_const))) return true; if (bc == Bytecodes::_land && - (is_power_of_2_long(int_or_long_const+1) || - (Assembler::is_uimm(int_or_long_const, 32) && is_power_of_2_long(int_or_long_const)) || - (int_or_long_const != min_jlong && is_power_of_2_long(-int_or_long_const)))) return true; + (is_power_of_2(int_or_long_const+1) || + (Assembler::is_uimm(int_or_long_const, 32) && is_power_of_2(int_or_long_const)) || + (int_or_long_const != min_jlong && is_power_of_2(-int_or_long_const)))) return true; // special case: xor -1 if ((bc == Bytecodes::_ixor || bc == Bytecodes::_lxor) && diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp index 28ee116eb31..4fd6a35642f 100644 --- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp @@ -38,7 +38,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/align.hpp" - +#include "utilities/powerOfTwo.hpp" void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { const Register temp_reg = R12_scratch2; diff --git a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp index 925b5d8d206..37f4566b34a 100644 --- a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp @@ -42,6 +42,7 @@ #include "runtime/vframeArray.hpp" #include "utilities/align.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #include "vmreg_ppc.inline.hpp" // Implementation of StubAssembler diff --git a/src/hotspot/cpu/ppc/c1_globals_ppc.hpp b/src/hotspot/cpu/ppc/c1_globals_ppc.hpp index 5a5dd1fb4d1..2758727409e 100644 --- a/src/hotspot/cpu/ppc/c1_globals_ppc.hpp +++ b/src/hotspot/cpu/ppc/c1_globals_ppc.hpp @@ -62,7 +62,6 @@ define_pd_global(uintx, InitialCodeCacheSize, 160*K); #endif // !TIERED define_pd_global(bool, UseTypeProfile, false); -define_pd_global(bool, RoundFPResults, false); define_pd_global(bool, LIRFillDelaySlots, false); define_pd_global(bool, OptimizeSinglePrecision, false); diff --git a/src/hotspot/cpu/ppc/frame_ppc.cpp b/src/hotspot/cpu/ppc/frame_ppc.cpp index aaa145fd050..404a8f6d563 100644 --- a/src/hotspot/cpu/ppc/frame_ppc.cpp +++ b/src/hotspot/cpu/ppc/frame_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2017 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -55,33 +55,22 @@ bool frame::safe_for_sender(JavaThread *thread) { address fp = (address)_fp; address unextended_sp = (address)_unextended_sp; - // Consider stack guards when trying to determine "safe" stack pointers - static size_t stack_guard_size = os::uses_stack_guard_pages() ? - JavaThread::stack_red_zone_size() + JavaThread::stack_yellow_reserved_zone_size() : 0; - size_t usable_stack_size = thread->stack_size() - stack_guard_size; - + // consider stack guards when trying to determine "safe" stack pointers // sp must be within the usable part of the stack (not in guards) - bool sp_safe = (sp < thread->stack_base()) && - (sp >= thread->stack_base() - usable_stack_size); - - - if (!sp_safe) { + if (!thread->is_in_usable_stack(sp)) { return false; } // Unextended sp must be within the stack - bool unextended_sp_safe = (unextended_sp < thread->stack_base()); - - if (!unextended_sp_safe) { + if (!thread->is_in_full_stack(unextended_sp)) { return false; } // An fp must be within the stack and above (but not equal) sp. - bool fp_safe = (fp <= thread->stack_base()) && (fp > sp); + bool fp_safe = thread->is_in_stack_range_excl(fp, sp); // An interpreter fp must be within the stack and above (but not equal) sp. // Moreover, it must be at least the size of the ijava_state structure. - bool fp_interp_safe = (fp <= thread->stack_base()) && (fp > sp) && - ((fp - sp) >= ijava_state_size); + bool fp_interp_safe = fp_safe && ((fp - sp) >= ijava_state_size); // We know sp/unextended_sp are safe, only fp is questionable here @@ -140,7 +129,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // sender_fp must be within the stack and above (but not // equal) current frame's fp. - if (sender_fp > thread->stack_base() || sender_fp <= fp) { + if (!thread->is_in_stack_range_excl(sender_fp, fp)) { return false; } diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp index 1fbcf9c32fb..ab14c5beb16 100644 --- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp @@ -34,6 +34,7 @@ #include "runtime/frame.inline.hpp" #include "runtime/safepointMechanism.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/powerOfTwo.hpp" // Implementation of InterpreterMacroAssembler. diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index b6c4dbf2490..d7796d36e1e 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -44,6 +44,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #ifdef COMPILER2 #include "opto/intrinsicnode.hpp" #endif diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp index 6ac8491aa2e..28f3210b5b7 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp @@ -35,6 +35,7 @@ #include "oops/accessDecorators.hpp" #include "oops/compressedOops.hpp" #include "runtime/safepointMechanism.hpp" +#include "utilities/powerOfTwo.hpp" inline bool MacroAssembler::is_ld_largeoffset(address a) { const int inst1 = *(int *)a; @@ -56,7 +57,7 @@ inline int MacroAssembler::get_ld_largeoffset_offset(address a) { } inline void MacroAssembler::round_to(Register r, int modulus) { - assert(is_power_of_2_long((jlong)modulus), "must be power of 2"); + assert(is_power_of_2((jlong)modulus), "must be power of 2"); addi(r, r, modulus-1); clrrdi(r, r, log2_long((jlong)modulus)); } diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index a4e11602d5a..34cb0f8947e 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -2501,8 +2501,7 @@ void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) { Unimplemented(); } -// Advertise here if the CPU requires explicit rounding operations -// to implement the UseStrictFP mode. +// Advertise here if the CPU requires explicit rounding operations to implement strictfp mode. const bool Matcher::strict_fp_requires_explicit_rounding = false; // Do floats take an entire double register or just half? @@ -4351,7 +4350,7 @@ operand immIhi16() %{ %} operand immInegpow2() %{ - predicate(is_power_of_2_long((jlong) (julong) (juint) (-(n->get_int())))); + predicate(is_power_of_2((jlong) (julong) (juint) (-(n->get_int())))); match(ConI); op_cost(0); format %{ %} @@ -4359,7 +4358,7 @@ operand immInegpow2() %{ %} operand immIpow2minus1() %{ - predicate(is_power_of_2_long((((jlong) (n->get_int()))+1))); + predicate(is_power_of_2((((jlong) (n->get_int()))+1))); match(ConI); op_cost(0); format %{ %} @@ -4367,7 +4366,7 @@ operand immIpow2minus1() %{ %} operand immIpowerOf2() %{ - predicate(is_power_of_2_long((((jlong) (julong) (juint) (n->get_int()))))); + predicate(is_power_of_2((((jlong) (julong) (juint) (n->get_int()))))); match(ConI); op_cost(0); format %{ %} @@ -4601,7 +4600,7 @@ operand immLhighest16() %{ %} operand immLnegpow2() %{ - predicate(is_power_of_2_long((jlong)-(n->get_long()))); + predicate(is_power_of_2((jlong)-(n->get_long()))); match(ConL); op_cost(0); format %{ %} @@ -4609,7 +4608,7 @@ operand immLnegpow2() %{ %} operand immLpow2minus1() %{ - predicate(is_power_of_2_long((((jlong) (n->get_long()))+1)) && + predicate(is_power_of_2((((jlong) (n->get_long()))+1)) && (n->get_long() != (jlong)0xffffffffffffffffL)); match(ConL); op_cost(0); diff --git a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp index 3cf4d7fe193..071ee8ce7fd 100644 --- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp @@ -41,6 +41,7 @@ #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" #include "utilities/align.hpp" +#include "utilities/powerOfTwo.hpp" // Declaration and definition of StubGenerator (no .hpp file). // For a more detailed description of the stub routine structure diff --git a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp index c6e13a93762..b7bd9d27d20 100644 --- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp @@ -42,6 +42,7 @@ #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #undef __ #define __ _masm-> diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index 1b98ca46e6c..a00c9512dcc 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -36,6 +36,7 @@ #include "utilities/align.hpp" #include "utilities/defaultStream.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/powerOfTwo.hpp" #include #if defined(_AIX) @@ -224,6 +225,10 @@ void VM_Version::initialize() { assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); + if (FLAG_IS_DEFAULT(ContendedPaddingWidth) && (cache_line_size > ContendedPaddingWidth)) { + ContendedPaddingWidth = cache_line_size; + } + // If running on Power8 or newer hardware, the implementation uses the available vector instructions. // In all other cases, the implementation uses only generally available instructions. if (!UseCRC32Intrinsics) { @@ -535,6 +540,13 @@ bool VM_Version::use_biased_locking() { void VM_Version::print_features() { tty->print_cr("Version: %s L1_data_cache_line_size=%d", features_string(), L1_data_cache_line_size()); + + if (Verbose) { + if (ContendedPaddingWidth > 0) { + tty->cr(); + tty->print_cr("ContendedPaddingWidth " INTX_FORMAT, ContendedPaddingWidth); + } + } } #ifdef COMPILER2 diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp index 0ef75ab1436..d68e27f8b21 100644 --- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp @@ -39,6 +39,7 @@ #include "runtime/frame.inline.hpp" #include "runtime/safepointMechanism.inline.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/powerOfTwo.hpp" #include "vmreg_s390.inline.hpp" #define __ _masm-> @@ -1798,7 +1799,7 @@ void LIR_Assembler::arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right, if (left->is_double_cpu()) { // 64 bit integer case assert(left->is_double_cpu(), "left must be register"); - assert(right->is_double_cpu() || is_power_of_2_long(right->as_jlong()), + assert(right->is_double_cpu() || is_power_of_2(right->as_jlong()), "right must be register or power of 2 constant"); assert(result->is_double_cpu(), "result must be register"); diff --git a/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp b/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp index f3e3e3a9f65..8ff4b3a5152 100644 --- a/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp @@ -37,6 +37,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "vmreg_s390.inline.hpp" +#include "utilities/powerOfTwo.hpp" #ifdef ASSERT #define __ gen()->lir(__FILE__, __LINE__)-> diff --git a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp index e7526d17c6d..42914737e29 100644 --- a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp +++ b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp @@ -38,12 +38,13 @@ #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "register_s390.hpp" +#include "registerSaver_s390.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" #include "runtime/vframeArray.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #include "vmreg_s390.inline.hpp" -#include "registerSaver_s390.hpp" // Implementation of StubAssembler diff --git a/src/hotspot/cpu/s390/c1_globals_s390.hpp b/src/hotspot/cpu/s390/c1_globals_s390.hpp index ea9f5323c21..91788953215 100644 --- a/src/hotspot/cpu/s390/c1_globals_s390.hpp +++ b/src/hotspot/cpu/s390/c1_globals_s390.hpp @@ -63,7 +63,6 @@ define_pd_global(uintx, InitialCodeCacheSize, 160*K); #endif // !TIERED define_pd_global(bool, UseTypeProfile, false); -define_pd_global(bool, RoundFPResults, false); define_pd_global(bool, LIRFillDelaySlots, false); define_pd_global(bool, OptimizeSinglePrecision, false); diff --git a/src/hotspot/cpu/s390/frame_s390.cpp b/src/hotspot/cpu/s390/frame_s390.cpp index bc19df7a68b..8c3301f86c5 100644 --- a/src/hotspot/cpu/s390/frame_s390.cpp +++ b/src/hotspot/cpu/s390/frame_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2019, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -59,33 +59,22 @@ bool frame::safe_for_sender(JavaThread *thread) { address fp = (address)_fp; address unextended_sp = (address)_unextended_sp; - // Consider stack guards when trying to determine "safe" stack pointers - static size_t stack_guard_size = os::uses_stack_guard_pages() ? - JavaThread::stack_red_zone_size() + JavaThread::stack_yellow_reserved_zone_size() : 0; - size_t usable_stack_size = thread->stack_size() - stack_guard_size; - + // consider stack guards when trying to determine "safe" stack pointers // sp must be within the usable part of the stack (not in guards) - bool sp_safe = (sp < thread->stack_base()) && - (sp >= thread->stack_base() - usable_stack_size); - - - if (!sp_safe) { + if (!thread->is_in_usable_stack(sp)) { return false; } // Unextended sp must be within the stack - bool unextended_sp_safe = (unextended_sp < thread->stack_base()); - - if (!unextended_sp_safe) { + if (!thread->is_in_full_stack(unextended_sp)) { return false; } // An fp must be within the stack and above (but not equal) sp. - bool fp_safe = (fp <= thread->stack_base()) && (fp > sp); + bool fp_safe = thread->is_in_stack_range_excl(fp, sp); // An interpreter fp must be within the stack and above (but not equal) sp. // Moreover, it must be at least the size of the z_ijava_state structure. - bool fp_interp_safe = (fp <= thread->stack_base()) && (fp > sp) && - ((fp - sp) >= z_ijava_state_size); + bool fp_interp_safe = fp_safe && ((fp - sp) >= z_ijava_state_size); // We know sp/unextended_sp are safe, only fp is questionable here @@ -144,7 +133,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // sender_fp must be within the stack and above (but not // equal) current frame's fp. - if (sender_fp > thread->stack_base() || sender_fp <= fp) { + if (!thread->is_in_stack_range_excl(sender_fp, fp)) { return false; } diff --git a/src/hotspot/cpu/s390/interp_masm_s390.cpp b/src/hotspot/cpu/s390/interp_masm_s390.cpp index cbee39e3eae..7d085e6b59b 100644 --- a/src/hotspot/cpu/s390/interp_masm_s390.cpp +++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp @@ -42,6 +42,7 @@ #include "runtime/safepointMechanism.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/thread.inline.hpp" +#include "utilities/powerOfTwo.hpp" // Implementation of InterpreterMacroAssembler. // This file specializes the assembler with interpreter-specific macros. diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index e774e0a9748..4abc0d3efed 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -55,6 +55,7 @@ #include "runtime/stubRoutines.hpp" #include "utilities/events.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #include diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 197f5f23821..170fad74ae8 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -1710,8 +1710,7 @@ const bool Matcher::rematerialize_float_constants = false; // Java calling convention forces doubles to be aligned. const bool Matcher::misaligned_doubles_ok = true; -// Advertise here if the CPU requires explicit rounding operations -// to implement the UseStrictFP mode. +// Advertise here if the CPU requires explicit rounding operations to implement strictfp mode. const bool Matcher::strict_fp_requires_explicit_rounding = false; // Do floats take an entire double register or just half? diff --git a/src/hotspot/cpu/s390/stubGenerator_s390.cpp b/src/hotspot/cpu/s390/stubGenerator_s390.cpp index 4a2e28b9569..f5540d41fe2 100644 --- a/src/hotspot/cpu/s390/stubGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/stubGenerator_s390.cpp @@ -42,6 +42,7 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" +#include "utilities/powerOfTwo.hpp" // Declaration and definition of StubGenerator (no .hpp file). // For a more detailed description of the stub routine structure diff --git a/src/hotspot/cpu/s390/templateTable_s390.cpp b/src/hotspot/cpu/s390/templateTable_s390.cpp index fc127e7afd5..79ca843447d 100644 --- a/src/hotspot/cpu/s390/templateTable_s390.cpp +++ b/src/hotspot/cpu/s390/templateTable_s390.cpp @@ -39,6 +39,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" +#include "utilities/powerOfTwo.hpp" #ifdef PRODUCT #define __ _masm-> diff --git a/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp b/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp index 73f05246dab..4faa45fdc72 100644 --- a/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp +++ b/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp @@ -40,6 +40,7 @@ #include "runtime/jniHandles.inline.hpp" #include "runtime/safepointMechanism.inline.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/powerOfTwo.hpp" #define __ _masm-> diff --git a/src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp b/src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp index 618220b8296..403f7cc5e52 100644 --- a/src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp +++ b/src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp @@ -37,6 +37,7 @@ #include "runtime/safepointMechanism.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" +#include "utilities/powerOfTwo.hpp" #include "vmreg_sparc.inline.hpp" #ifdef ASSERT diff --git a/src/hotspot/cpu/sparc/c1_globals_sparc.hpp b/src/hotspot/cpu/sparc/c1_globals_sparc.hpp index 378480c4226..31841bd0f2b 100644 --- a/src/hotspot/cpu/sparc/c1_globals_sparc.hpp +++ b/src/hotspot/cpu/sparc/c1_globals_sparc.hpp @@ -61,7 +61,6 @@ define_pd_global(uintx, InitialCodeCacheSize, 160*K); #endif // !TIERED define_pd_global(bool, UseTypeProfile, false); -define_pd_global(bool, RoundFPResults, false); define_pd_global(bool, LIRFillDelaySlots, true ); define_pd_global(bool, OptimizeSinglePrecision, false); diff --git a/src/hotspot/cpu/sparc/frame_sparc.cpp b/src/hotspot/cpu/sparc/frame_sparc.cpp index 7405f2b7eb6..5e370ff7098 100644 --- a/src/hotspot/cpu/sparc/frame_sparc.cpp +++ b/src/hotspot/cpu/sparc/frame_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -177,23 +177,20 @@ bool frame::safe_for_sender(JavaThread *thread) { address _SP = (address) sp(); address _FP = (address) fp(); address _UNEXTENDED_SP = (address) unextended_sp(); - // sp must be within the stack - bool sp_safe = (_SP <= thread->stack_base()) && - (_SP >= thread->stack_base() - thread->stack_size()); - if (!sp_safe) { + // consider stack guards when trying to determine "safe" stack pointers + // sp must be within the usable part of the stack (not in guards) + if (!thread->is_in_usable_stack(_SP)) { return false; } // unextended sp must be within the stack and above or equal sp - bool unextended_sp_safe = (_UNEXTENDED_SP <= thread->stack_base()) && - (_UNEXTENDED_SP >= _SP); - - if (!unextended_sp_safe) return false; + if (!thread->is_in_stack_range_incl(_UNEXTENDED_SP, _SP)) { + return false; + } // an fp must be within the stack and above (but not equal) sp - bool fp_safe = (_FP <= thread->stack_base()) && - (_FP > _SP); + bool fp_safe = thread->is_in_stack_range_excl(_FP, _SP); // We know sp/unextended_sp are safe only fp is questionable here @@ -252,10 +249,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // an fp must be within the stack and above (but not equal) current frame's _FP - bool sender_fp_safe = (sender_fp <= thread->stack_base()) && - (sender_fp > _FP); - - if (!sender_fp_safe) { + if (!thread->is_in_stack_range_excl(sender_fp, _FP)) { return false; } @@ -277,12 +271,9 @@ bool frame::safe_for_sender(JavaThread *thread) { if (sender.is_entry_frame()) { // Validate the JavaCallWrapper an entry frame must have - address jcw = (address)sender.entry_frame_call_wrapper(); - bool jcw_safe = (jcw <= thread->stack_base()) && (jcw > sender_fp); - - return jcw_safe; + return thread->is_in_stack_range_excl(jcw, sender_fp); } // If the frame size is 0 something (or less) is bad because every nmethod has a non-zero frame size @@ -671,11 +662,7 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { // validate locals address locals = (address) *interpreter_frame_locals_addr(); - - if (locals > thread->stack_base() || locals < (address) fp()) return false; - - // We'd have to be pretty unlucky to be mislead at this point - return true; + return thread->is_in_stack_range_incl(locals, (address)fp()); } diff --git a/src/hotspot/cpu/sparc/interp_masm_sparc.cpp b/src/hotspot/cpu/sparc/interp_masm_sparc.cpp index 21b69206a87..a8dd0bb6600 100644 --- a/src/hotspot/cpu/sparc/interp_masm_sparc.cpp +++ b/src/hotspot/cpu/sparc/interp_masm_sparc.cpp @@ -42,6 +42,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/thread.inline.hpp" #include "utilities/align.hpp" +#include "utilities/powerOfTwo.hpp" // Implementation of InterpreterMacroAssembler diff --git a/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp b/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp index 8c9e8703558..3f77ca85720 100644 --- a/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp +++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp @@ -48,6 +48,7 @@ #include "runtime/stubRoutines.hpp" #include "utilities/align.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #ifdef COMPILER2 #include "opto/intrinsicnode.hpp" #endif diff --git a/src/hotspot/cpu/sparc/macroAssembler_sparc.hpp b/src/hotspot/cpu/sparc/macroAssembler_sparc.hpp index 0f12570a72b..051123f55fb 100644 --- a/src/hotspot/cpu/sparc/macroAssembler_sparc.hpp +++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.hpp @@ -478,6 +478,9 @@ class Argument { class RegistersForDebugging : public StackObj { + private: + static const RegistersForDebugging& _dummy; // not ODR-used so not defined + public: intptr_t i[8], l[8], o[8], g[8]; float f[32]; @@ -485,12 +488,12 @@ class RegistersForDebugging : public StackObj { void print(outputStream* s); - static int i_offset(int j) { return offset_of(RegistersForDebugging, i[j]); } - static int l_offset(int j) { return offset_of(RegistersForDebugging, l[j]); } - static int o_offset(int j) { return offset_of(RegistersForDebugging, o[j]); } - static int g_offset(int j) { return offset_of(RegistersForDebugging, g[j]); } - static int f_offset(int j) { return offset_of(RegistersForDebugging, f[j]); } - static int d_offset(int j) { return offset_of(RegistersForDebugging, d[j / 2]); } + static int i_offset(int j) { return offset_of(RegistersForDebugging, i) + j * sizeof(_dummy.i[0]); } + static int l_offset(int j) { return offset_of(RegistersForDebugging, l) + j * sizeof(_dummy.l[0]); } + static int o_offset(int j) { return offset_of(RegistersForDebugging, o) + j * sizeof(_dummy.o[0]); } + static int g_offset(int j) { return offset_of(RegistersForDebugging, g) + j * sizeof(_dummy.g[0]); } + static int f_offset(int j) { return offset_of(RegistersForDebugging, f) + j * sizeof(_dummy.f[0]); } + static int d_offset(int j) { return offset_of(RegistersForDebugging, d) + (j / 2) * sizeof(_dummy.d[0]); } // gen asm code to save regs static void save_registers(MacroAssembler* a); diff --git a/src/hotspot/cpu/sparc/sparc.ad b/src/hotspot/cpu/sparc/sparc.ad index ea05926e3b3..eb9fdd091cd 100644 --- a/src/hotspot/cpu/sparc/sparc.ad +++ b/src/hotspot/cpu/sparc/sparc.ad @@ -1873,8 +1873,7 @@ const bool Matcher::misaligned_doubles_ok = true; void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) { } -// Advertise here if the CPU requires explicit rounding operations -// to implement the UseStrictFP mode. +// Advertise here if the CPU requires explicit rounding operations to implement strictfp mode. const bool Matcher::strict_fp_requires_explicit_rounding = false; // Are floats converted to double when stored to stack during deoptimization? diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index f9eb6cf5fce..520000bb855 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -7159,7 +7159,7 @@ void Assembler::evbroadcasti64x2(XMMRegister dst, Address src, int vector_len) { // scalar single/double precision replicate // duplicate single precision data from src into programmed locations in dest : requires AVX512VL -void Assembler::vpbroadcastss(XMMRegister dst, XMMRegister src, int vector_len) { +void Assembler::vbroadcastss(XMMRegister dst, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); @@ -7167,7 +7167,7 @@ void Assembler::vpbroadcastss(XMMRegister dst, XMMRegister src, int vector_len) emit_int8((unsigned char)(0xC0 | encode)); } -void Assembler::vpbroadcastss(XMMRegister dst, Address src, int vector_len) { +void Assembler::vbroadcastss(XMMRegister dst, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); assert(dst != xnoreg, "sanity"); InstructionMark im(this); @@ -7180,7 +7180,7 @@ void Assembler::vpbroadcastss(XMMRegister dst, Address src, int vector_len) { } // duplicate double precision data from src into programmed locations in dest : requires AVX512VL -void Assembler::vpbroadcastsd(XMMRegister dst, XMMRegister src, int vector_len) { +void Assembler::vbroadcastsd(XMMRegister dst, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); InstructionAttr attributes(vector_len, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_rex_vex_w_reverted(); @@ -7189,7 +7189,7 @@ void Assembler::vpbroadcastsd(XMMRegister dst, XMMRegister src, int vector_len) emit_int8((unsigned char)(0xC0 | encode)); } -void Assembler::vpbroadcastsd(XMMRegister dst, Address src, int vector_len) { +void Assembler::vbroadcastsd(XMMRegister dst, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); assert(dst != xnoreg, "sanity"); InstructionMark im(this); diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index 5d7260f1ee5..2781a0fa963 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -27,6 +27,7 @@ #include "asm/register.hpp" #include "runtime/vm_version.hpp" +#include "utilities/powerOfTwo.hpp" class BiasedLockingCounters; @@ -2217,10 +2218,10 @@ private: void evbroadcasti64x2(XMMRegister dst, Address src, int vector_len); // scalar single/double precision replicate - void vpbroadcastss(XMMRegister dst, XMMRegister src, int vector_len); - void vpbroadcastss(XMMRegister dst, Address src, int vector_len); - void vpbroadcastsd(XMMRegister dst, XMMRegister src, int vector_len); - void vpbroadcastsd(XMMRegister dst, Address src, int vector_len); + void vbroadcastss(XMMRegister dst, XMMRegister src, int vector_len); + void vbroadcastss(XMMRegister dst, Address src, int vector_len); + void vbroadcastsd(XMMRegister dst, XMMRegister src, int vector_len); + void vbroadcastsd(XMMRegister dst, Address src, int vector_len); // gpr sourced byte/word/dword/qword replicate void evpbroadcastb(XMMRegister dst, Register src, int vector_len); diff --git a/src/hotspot/cpu/x86/c1_Defs_x86.hpp b/src/hotspot/cpu/x86/c1_Defs_x86.hpp index 27e9889bcbe..1631a0a763e 100644 --- a/src/hotspot/cpu/x86/c1_Defs_x86.hpp +++ b/src/hotspot/cpu/x86/c1_Defs_x86.hpp @@ -33,7 +33,7 @@ enum { // explicit rounding operations are required to implement the strictFP mode enum { - pd_strict_fp_requires_explicit_rounding = true + pd_strict_fp_requires_explicit_rounding = LP64_ONLY( false ) NOT_LP64 ( true ) }; diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp index f0f6eaf000f..868a3f5d019 100644 --- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp @@ -38,6 +38,7 @@ #include "runtime/frame.inline.hpp" #include "runtime/safepointMechanism.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/powerOfTwo.hpp" #include "vmreg_x86.inline.hpp" @@ -908,11 +909,6 @@ void LIR_Assembler::reg2reg(LIR_Opr src, LIR_Opr dest) { } else if (dest->is_double_xmm() && !src->is_double_xmm()) { __ fstp_d(Address(rsp, 0)); __ movdbl(dest->as_xmm_double_reg(), Address(rsp, 0)); - - // move between fpu-registers (no instruction necessary because of fpu-stack) - } else if (dest->is_single_fpu() || dest->is_double_fpu()) { - assert(src->is_single_fpu() || src->is_double_fpu(), "must match"); - assert(src->fpu() == dest->fpu(), "currently should be nothing to do"); #endif // !_LP64 // move between xmm-registers @@ -923,6 +919,13 @@ void LIR_Assembler::reg2reg(LIR_Opr src, LIR_Opr dest) { assert(src->is_double_xmm(), "must match"); __ movdbl(dest->as_xmm_double_reg(), src->as_xmm_double_reg()); +#ifndef _LP64 + // move between fpu-registers (no instruction necessary because of fpu-stack) + } else if (dest->is_single_fpu() || dest->is_double_fpu()) { + assert(src->is_single_fpu() || src->is_double_fpu(), "must match"); + assert(src->fpu() == dest->fpu(), "currently should be nothing to do"); +#endif // !_LP64 + } else { ShouldNotReachHere(); } @@ -1595,6 +1598,7 @@ void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { __ movl(Address(rsp, BytesPerWord), src->as_register_hi()); __ fild_d(Address(rsp, 0)); // float result is rounded later through spilling + break; case Bytecodes::_f2i: case Bytecodes::_d2i: diff --git a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp index cf736d5a6fb..bcb2afbf800 100644 --- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp @@ -36,6 +36,7 @@ #include "gc/shared/c1/barrierSetC1.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" +#include "utilities/powerOfTwo.hpp" #include "vmreg_x86.inline.hpp" #ifdef ASSERT diff --git a/src/hotspot/cpu/x86/c1_globals_x86.hpp b/src/hotspot/cpu/x86/c1_globals_x86.hpp index b9dd15b59fb..de754f9f842 100644 --- a/src/hotspot/cpu/x86/c1_globals_x86.hpp +++ b/src/hotspot/cpu/x86/c1_globals_x86.hpp @@ -60,7 +60,6 @@ define_pd_global(uint64_t, MaxRAM, 1ULL*G); define_pd_global(bool, CICompileOSR, true ); #endif // !TIERED define_pd_global(bool, UseTypeProfile, false); -define_pd_global(bool, RoundFPResults, true ); define_pd_global(bool, LIRFillDelaySlots, false); define_pd_global(bool, OptimizeSinglePrecision, true ); diff --git a/src/hotspot/cpu/x86/c2_intelJccErratum_x86.cpp b/src/hotspot/cpu/x86/c2_intelJccErratum_x86.cpp new file mode 100644 index 00000000000..271d7a2a892 --- /dev/null +++ b/src/hotspot/cpu/x86/c2_intelJccErratum_x86.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" +#include "c2_intelJccErratum_x86.hpp" +#include "opto/cfgnode.hpp" +#include "opto/compile.hpp" +#include "opto/machnode.hpp" +#include "opto/node.hpp" +#include "opto/regalloc.hpp" +#include "utilities/align.hpp" +#include "utilities/debug.hpp" + +// Compute which 32 byte boundary an address corresponds to +uintptr_t IntelJccErratum::boundary(uintptr_t addr) { + return addr >> 5; +} + +bool IntelJccErratum::is_crossing_or_ending_at_32_byte_boundary(uintptr_t start_pc, uintptr_t end_pc) { + int jcc_size = int(end_pc - start_pc); + assert(jcc_size <= largest_jcc_size(), "invalid jcc size: %d", jcc_size); + return boundary(start_pc) != boundary(end_pc); +} + +bool IntelJccErratum::is_jcc_erratum_branch(const Block* block, const MachNode* node, uint node_index) { + if (node->is_MachCall() && !node->is_MachCallJava()) { + return true; + } + return node_index == (block->number_of_nodes() - 1); +} + +int IntelJccErratum::jcc_erratum_taint_node(MachNode* node, PhaseRegAlloc* regalloc) { + node->add_flag(Node::Flag_intel_jcc_erratum); + return node->size(regalloc); +} + +int IntelJccErratum::tag_affected_machnodes(Compile* C, PhaseCFG* cfg, PhaseRegAlloc* regalloc) { + ResourceMark rm; + int nop_size = 0; + MachNode* last_m = NULL; + + for (uint i = 0; i < cfg->number_of_blocks(); ++i) { + const Block* const block = cfg->get_block(i); + for (uint j = 0; j < block->number_of_nodes(); ++j) { + const Node* const node = block->get_node(j); + if (!node->is_Mach()) { + continue; + } + MachNode* m = node->as_Mach(); + if (is_jcc_erratum_branch(block, m, j)) { + // Found a root jcc erratum branch, flag it as problematic + nop_size += jcc_erratum_taint_node(m, regalloc); + + if (!m->is_MachReturn() && !m->is_MachCall()) { + // We might fuse a problematic jcc erratum branch with a preceding + // ALU instruction - we must catch such problematic macro fusions + // and flag the ALU instruction as problematic too. + for (uint k = 1; k < m->req(); ++k) { + const Node* const use = m->in(k); + if (use == last_m && !m->is_MachReturn()) { + // Flag fused conditions too + nop_size += jcc_erratum_taint_node(last_m, regalloc); + } + } + } + last_m = NULL; + } else { + last_m = m; + } + } + } + return nop_size; +} + +int IntelJccErratum::compute_padding(uintptr_t current_offset, const MachNode* mach, Block* block, uint index_in_block, PhaseRegAlloc* regalloc) { + int jcc_size = mach->size(regalloc); + if (index_in_block < block->number_of_nodes() - 1) { + Node* next = block->get_node(index_in_block + 1); + if (next->is_Mach() && (next->as_Mach()->flags() & Node::Flag_intel_jcc_erratum)) { + jcc_size += mach->size(regalloc); + } + } + if (jcc_size > largest_jcc_size()) { + // Let's not try fixing this for nodes that seem unreasonably large + return false; + } + if (is_crossing_or_ending_at_32_byte_boundary(current_offset, current_offset + jcc_size)) { + return int(align_up(current_offset, 32) - current_offset); + } else { + return 0; + } +} + +#define __ _masm. + +uintptr_t IntelJccErratumAlignment::pc() { + return (uintptr_t)__ pc(); +} + +IntelJccErratumAlignment::IntelJccErratumAlignment(MacroAssembler& masm, int jcc_size) : + _masm(masm), + _start_pc(pc()) { + if (!VM_Version::has_intel_jcc_erratum()) { + return; + } + + if (Compile::current()->in_scratch_emit_size()) { + // When we measure the size of this 32 byte alignment, we apply a conservative guess. + __ nop(jcc_size); + } else if (IntelJccErratum::is_crossing_or_ending_at_32_byte_boundary(_start_pc, _start_pc + jcc_size)) { + // The affected branch might get slowed down by micro code mitigations + // as it could be susceptible to the erratum. Place nops until the next + // 32 byte boundary to make sure the branch will be cached. + const int alignment_nops = (int)(align_up(_start_pc, 32) - _start_pc); + __ nop(alignment_nops); + _start_pc = pc(); + } +} + +IntelJccErratumAlignment::~IntelJccErratumAlignment() { + if (!VM_Version::has_intel_jcc_erratum() || + Compile::current()->in_scratch_emit_size()) { + return; + } + + assert(!IntelJccErratum::is_crossing_or_ending_at_32_byte_boundary(_start_pc, pc()), "Invalid jcc_size estimate"); +} diff --git a/src/hotspot/cpu/x86/c2_intelJccErratum_x86.hpp b/src/hotspot/cpu/x86/c2_intelJccErratum_x86.hpp new file mode 100644 index 00000000000..f0db7c9b207 --- /dev/null +++ b/src/hotspot/cpu/x86/c2_intelJccErratum_x86.hpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 CPU_X86_INTELJCCERRATUM_X86_HPP +#define CPU_X86_INTELJCCERRATUM_X86_HPP + +#include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" + +class Block; +class Compile; +class MachNode; +class MacroAssembler; +class PhaseCFG; +class PhaseRegAlloc; + +class IntelJccErratum : public AllStatic { +private: + // Compute which 32 byte boundary an address corresponds to + static uintptr_t boundary(uintptr_t addr); + static int jcc_erratum_taint_node(MachNode* node, PhaseRegAlloc* regalloc); + +public: + static bool is_crossing_or_ending_at_32_byte_boundary(uintptr_t start_pc, uintptr_t end_pc); + static bool is_jcc_erratum_branch(const Block* block, const MachNode* node, uint node_index); + // Analyze JCC erratum branches. Affected nodes get tagged with Flag_intel_jcc_erratum. + // The function returns a conservative estimate of all required nops on all mach nodes. + static int tag_affected_machnodes(Compile* C, PhaseCFG* cfg, PhaseRegAlloc* regalloc); + // Computes the exact padding for a mach node + static int compute_padding(uintptr_t current_offset, const MachNode* mach, Block* block, uint index_in_block, PhaseRegAlloc* regalloc); + static int largest_jcc_size() { return 20; } +}; + +class IntelJccErratumAlignment { +private: + MacroAssembler& _masm; + uintptr_t _start_pc; + + uintptr_t pc(); + +public: + IntelJccErratumAlignment(MacroAssembler& masm, int jcc_size); + ~IntelJccErratumAlignment(); +}; + +#endif // CPU_X86_INTELJCCERRATUM_X86_HPP + diff --git a/src/hotspot/cpu/x86/frame_x86.cpp b/src/hotspot/cpu/x86/frame_x86.cpp index a55abe87121..c655d46057f 100644 --- a/src/hotspot/cpu/x86/frame_x86.cpp +++ b/src/hotspot/cpu/x86/frame_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,35 +57,25 @@ bool frame::safe_for_sender(JavaThread *thread) { address unextended_sp = (address)_unextended_sp; // consider stack guards when trying to determine "safe" stack pointers - static size_t stack_guard_size = os::uses_stack_guard_pages() ? - JavaThread::stack_red_zone_size() + JavaThread::stack_yellow_zone_size() : 0; - size_t usable_stack_size = thread->stack_size() - stack_guard_size; - // sp must be within the usable part of the stack (not in guards) - bool sp_safe = (sp < thread->stack_base()) && - (sp >= thread->stack_base() - usable_stack_size); - - - if (!sp_safe) { + if (!thread->is_in_usable_stack(sp)) { return false; } // unextended sp must be within the stack and above or equal sp - bool unextended_sp_safe = (unextended_sp < thread->stack_base()) && - (unextended_sp >= sp); - - if (!unextended_sp_safe) { + if (!thread->is_in_stack_range_incl(unextended_sp, sp)) { return false; } // an fp must be within the stack and above (but not equal) sp // second evaluation on fp+ is added to handle situation where fp is -1 - bool fp_safe = (fp < thread->stack_base() && (fp > sp) && (((fp + (return_addr_offset * sizeof(void*))) < thread->stack_base()))); + bool fp_safe = thread->is_in_stack_range_excl(fp, sp) && + thread->is_in_full_stack(fp + (return_addr_offset * sizeof(void*))); // We know sp/unextended_sp are safe only fp is questionable here // If the current frame is known to the code cache then we can attempt to - // to construct the sender and do some validation of it. This goes a long way + // construct the sender and do some validation of it. This goes a long way // toward eliminating issues when we get in frame construction code if (_cb != NULL ) { @@ -142,7 +132,7 @@ bool frame::safe_for_sender(JavaThread *thread) { sender_sp = _unextended_sp + _cb->frame_size(); // Is sender_sp safe? - if ((address)sender_sp >= thread->stack_base()) { + if (!thread->is_in_full_stack((address)sender_sp)) { return false; } sender_unextended_sp = sender_sp; @@ -160,9 +150,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // only if the sender is interpreted/call_stub (c1 too?) are we certain that the saved ebp // is really a frame pointer. - bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp); - - if (!saved_fp_safe) { + if (!thread->is_in_stack_range_excl((address)saved_fp, (address)sender_sp)) { return false; } @@ -197,9 +185,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // Could be the call_stub if (StubRoutines::returns_to_call_stub(sender_pc)) { - bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp); - - if (!saved_fp_safe) { + if (!thread->is_in_stack_range_excl((address)saved_fp, (address)sender_sp)) { return false; } @@ -210,9 +196,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // Validate the JavaCallWrapper an entry frame must have address jcw = (address)sender.entry_frame_call_wrapper(); - bool jcw_safe = (jcw < thread->stack_base()) && (jcw > (address)sender.fp()); - - return jcw_safe; + return thread->is_in_stack_range_excl(jcw, (address)sender.fp()); } CompiledMethod* nm = sender_blob->as_compiled_method_or_null(); @@ -552,11 +536,7 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { // validate locals address locals = (address) *interpreter_frame_locals_addr(); - - if (locals > thread->stack_base() || locals < (address) fp()) return false; - - // We'd have to be pretty unlucky to be mislead at this point - return true; + return thread->is_in_stack_range_incl(locals, (address)fp()); } BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) { diff --git a/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp index e3d17be4dcc..58dcd9ed5fb 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp @@ -111,7 +111,7 @@ LIR_Opr ShenandoahBarrierSetC1::atomic_xchg_at_resolved(LIRAccess& access, LIRIt __ xchg(access.resolved_addr(), result, result, LIR_OprFact::illegalOpr); if (access.is_oop()) { - result = load_reference_barrier(access.gen(), result, LIR_OprFact::addressConst(0)); + result = load_reference_barrier(access.gen(), result, LIR_OprFact::addressConst(0), false); LIR_Opr tmp = gen->new_register(type); __ move(result, tmp); result = tmp; diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp index dce988daa22..23dbb9e6666 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved. + * Copyright (c) 2018, 2020, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -824,7 +824,7 @@ void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assemble Register obj = stub->obj()->as_register(); Register res = stub->result()->as_register(); - Register addr = stub->addr()->as_register(); + Register addr = stub->addr()->as_pointer_register(); Register tmp1 = stub->tmp1()->as_register(); Register tmp2 = stub->tmp2()->as_register(); assert_different_registers(obj, res, addr, tmp1, tmp2); @@ -859,8 +859,11 @@ void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assemble __ bind(slow_path); ce->store_parameter(res, 0); ce->store_parameter(addr, 1); - __ call(RuntimeAddress(bs->load_reference_barrier_rt_code_blob()->code_begin())); - + if (stub->is_native()) { + __ call(RuntimeAddress(bs->load_reference_barrier_native_rt_code_blob()->code_begin())); + } else { + __ call(RuntimeAddress(bs->load_reference_barrier_rt_code_blob()->code_begin())); + } __ jmp(*stub->continuation()); } @@ -924,7 +927,7 @@ void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAss __ epilogue(); } -void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm) { +void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, bool is_native) { __ prologue("shenandoah_load_reference_barrier", false); // arg0 : object to be resolved @@ -933,7 +936,9 @@ void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_s #ifdef _LP64 __ load_parameter(0, c_rarg0); __ load_parameter(1, c_rarg1); - if (UseCompressedOops) { + if (is_native) { + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native), c_rarg0, c_rarg1); + } else if (UseCompressedOops) { __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_narrow), c_rarg0, c_rarg1); } else { __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier), c_rarg0, c_rarg1); @@ -941,7 +946,11 @@ void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_s #else __ load_parameter(0, rax); __ load_parameter(1, rbx); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier), rax, rbx); + if (is_native) { + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native), rax, rbx); + } else { + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier), rax, rbx); + } #endif __ restore_live_registers_except_rax(true); diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp index bd90ee45a22..60aa3b4600d 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp @@ -70,7 +70,7 @@ public: void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub); void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub); void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm); - void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm); + void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, bool is_native); #endif void load_reference_barrier(MacroAssembler* masm, Register dst, Address src); diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp index 13883f18d82..31f0b43cdec 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -304,7 +304,7 @@ void ZBarrierSetAssembler::generate_c1_load_barrier_stub(LIR_Assembler* ce, __ addptr(rsp, 2 * BytesPerWord); // Verify result - __ verify_oop(rax, "Bad oop"); + __ verify_oop(rax); // Move result into place if (ref != rax) { diff --git a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad index 3620b79258d..a8fd8f2748a 100644 --- a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad +++ b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. // 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,16 +30,29 @@ source_hpp %{ source %{ +#include "c2_intelJccErratum_x86.hpp" + static void z_load_barrier(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp, bool weak) { ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, weak); - __ testptr(ref, Address(r15_thread, ZThreadLocalData::address_bad_mask_offset())); - __ jcc(Assembler::notZero, *stub->entry()); + { + IntelJccErratumAlignment intel_alignment(_masm, 10 /* jcc_size */); + __ testptr(ref, Address(r15_thread, ZThreadLocalData::address_bad_mask_offset())); + __ jcc(Assembler::notZero, *stub->entry()); + } __ bind(*stub->continuation()); } -static void z_load_barrier_slow_path(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp) { +static void z_load_barrier_cmpxchg(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp, Label& good) { ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, false /* weak */); - __ jmp(*stub->entry()); + { + IntelJccErratumAlignment intel_alignment(_masm, 10 /* jcc_size */); + __ testptr(ref, Address(r15_thread, ZThreadLocalData::address_bad_mask_offset())); + __ jcc(Assembler::zero, good); + } + { + IntelJccErratumAlignment intel_alignment(_masm, 5 /* jcc_size */); + __ jmp(*stub->entry()); + } __ bind(*stub->continuation()); } @@ -101,9 +114,7 @@ instruct zCompareAndExchangeP(memory mem, rax_RegP oldval, rRegP newval, rRegP t __ cmpxchgptr($newval$$Register, $mem$$Address); if (barrier_data() != ZLoadBarrierElided) { Label good; - __ testptr($oldval$$Register, Address(r15_thread, ZThreadLocalData::address_bad_mask_offset())); - __ jcc(Assembler::zero, good); - z_load_barrier_slow_path(_masm, this, $mem$$Address, $oldval$$Register, $tmp$$Register); + z_load_barrier_cmpxchg(_masm, this, $mem$$Address, $oldval$$Register, $tmp$$Register, good); __ movptr($oldval$$Register, $tmp$$Register); __ lock(); __ cmpxchgptr($newval$$Register, $mem$$Address); @@ -133,9 +144,7 @@ instruct zCompareAndSwapP(rRegI res, memory mem, rRegP newval, rRegP tmp, rFlags __ cmpxchgptr($newval$$Register, $mem$$Address); if (barrier_data() != ZLoadBarrierElided) { Label good; - __ testptr($oldval$$Register, Address(r15_thread, ZThreadLocalData::address_bad_mask_offset())); - __ jcc(Assembler::zero, good); - z_load_barrier_slow_path(_masm, this, $mem$$Address, $oldval$$Register, $tmp$$Register); + z_load_barrier_cmpxchg(_masm, this, $mem$$Address, $oldval$$Register, $tmp$$Register, good); __ movptr($oldval$$Register, $tmp$$Register); __ lock(); __ cmpxchgptr($newval$$Register, $mem$$Address); diff --git a/src/hotspot/cpu/x86/interp_masm_x86.cpp b/src/hotspot/cpu/x86/interp_masm_x86.cpp index 4ed93169c76..76f830684cb 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.cpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ #include "runtime/safepointMechanism.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/thread.inline.hpp" +#include "utilities/powerOfTwo.hpp" // Implementation of InterpreterMacroAssembler @@ -50,7 +51,7 @@ void InterpreterMacroAssembler::jump_to_entry(address entry) { void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) { Label update, next, none; - verify_oop(obj); + interp_verify_oop(obj, atos); testptr(obj, obj); jccb(Assembler::notZero, update); @@ -348,7 +349,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) { switch (state) { case atos: movptr(rax, oop_addr); movptr(oop_addr, (int32_t)NULL_WORD); - verify_oop(rax, state); break; + interp_verify_oop(rax, state); break; case ltos: movptr(rax, val_addr); break; case btos: // fall through case ztos: // fall through @@ -369,7 +370,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) { switch (state) { case atos: movptr(rax, oop_addr); movptr(oop_addr, NULL_WORD); - verify_oop(rax, state); break; + interp_verify_oop(rax, state); break; case ltos: movl(rdx, val_addr1); // fall through case btos: // fall through @@ -655,11 +656,11 @@ void InterpreterMacroAssembler::pop(TosState state) { case vtos: /* nothing to do */ break; default: ShouldNotReachHere(); } - verify_oop(rax, state); + interp_verify_oop(rax, state); } void InterpreterMacroAssembler::push(TosState state) { - verify_oop(rax, state); + interp_verify_oop(rax, state); switch (state) { case atos: push_ptr(); break; case btos: @@ -721,7 +722,7 @@ void InterpreterMacroAssembler::pop(TosState state) { case vtos: /* nothing to do */ break; default : ShouldNotReachHere(); } - verify_oop(rax, state); + interp_verify_oop(rax, state); } @@ -744,7 +745,7 @@ void InterpreterMacroAssembler::push_d() { void InterpreterMacroAssembler::push(TosState state) { - verify_oop(rax, state); + interp_verify_oop(rax, state); switch (state) { case atos: push_ptr(rax); break; case btos: // fall through @@ -843,7 +844,7 @@ void InterpreterMacroAssembler::dispatch_base(TosState state, bind(L); } if (verifyoop) { - verify_oop(rax, state); + interp_verify_oop(rax, state); } address* const safepoint_table = Interpreter::safept_table(state); @@ -1958,9 +1959,9 @@ void InterpreterMacroAssembler::profile_switch_case(Register index, -void InterpreterMacroAssembler::verify_oop(Register reg, TosState state) { +void InterpreterMacroAssembler::_interp_verify_oop(Register reg, TosState state, const char* file, int line) { if (state == atos) { - MacroAssembler::verify_oop(reg); + MacroAssembler::_verify_oop(reg, "broken oop", file, line); } } diff --git a/src/hotspot/cpu/x86/interp_masm_x86.hpp b/src/hotspot/cpu/x86/interp_masm_x86.hpp index 1324db24da9..372023f0e8c 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.hpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * 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,7 +280,8 @@ class InterpreterMacroAssembler: public MacroAssembler { // Debugging // only if +VerifyOops && state == atos - void verify_oop(Register reg, TosState state = atos); +#define interp_verify_oop(reg, state) _interp_verify_oop(reg, state, __FILE__, __LINE__); + void _interp_verify_oop(Register reg, TosState state, const char* file, int line); // only if +VerifyFPU && (state == ftos || state == dtos) void verify_FPU(int stack_depth, TosState state = ftos); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index b4f05c033b3..288ffa4c847 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2447,7 +2447,7 @@ void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Reg void MacroAssembler::get_vm_result(Register oop_result, Register java_thread) { movptr(oop_result, Address(java_thread, JavaThread::vm_result_offset())); movptr(Address(java_thread, JavaThread::vm_result_offset()), NULL_WORD); - verify_oop(oop_result, "broken oop in call_VM_base"); + verify_oop_msg(oop_result, "broken oop in call_VM_base"); } void MacroAssembler::get_vm_result_2(Register metadata_result, Register java_thread) { @@ -4638,7 +4638,7 @@ void MacroAssembler::cmov32(Condition cc, Register dst, Register src) { } } -void MacroAssembler::verify_oop(Register reg, const char* s) { +void MacroAssembler::_verify_oop(Register reg, const char* s, const char* file, int line) { if (!VerifyOops) return; // Pass register number to verify_oop_subroutine @@ -4646,7 +4646,7 @@ void MacroAssembler::verify_oop(Register reg, const char* s) { { ResourceMark rm; stringStream ss; - ss.print("verify_oop: %s: %s", reg->name(), s); + ss.print("verify_oop: %s: %s (%s:%d)", reg->name(), s, file, line); b = code_string(ss.as_string()); } BLOCK_COMMENT("verify_oop {"); @@ -4728,7 +4728,7 @@ Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, } -void MacroAssembler::verify_oop_addr(Address addr, const char* s) { +void MacroAssembler::_verify_oop_addr(Address addr, const char* s, const char* file, int line) { if (!VerifyOops) return; // Address adjust(addr.base(), addr.index(), addr.scale(), addr.disp() + BytesPerWord); @@ -4737,7 +4737,7 @@ void MacroAssembler::verify_oop_addr(Address addr, const char* s) { { ResourceMark rm; stringStream ss; - ss.print("verify_oop_addr: %s", s); + ss.print("verify_oop_addr: %s (%s:%d)", s, file, line); b = code_string(ss.as_string()); } #ifdef _LP64 @@ -5333,7 +5333,7 @@ void MacroAssembler::encode_heap_oop(Register r) { #ifdef ASSERT verify_heapbase("MacroAssembler::encode_heap_oop: heap base corrupted?"); #endif - verify_oop(r, "broken oop in encode_heap_oop"); + verify_oop_msg(r, "broken oop in encode_heap_oop"); if (CompressedOops::base() == NULL) { if (CompressedOops::shift() != 0) { assert (LogMinObjAlignmentInBytes == CompressedOops::shift(), "decode alg wrong"); @@ -5358,7 +5358,7 @@ void MacroAssembler::encode_heap_oop_not_null(Register r) { bind(ok); } #endif - verify_oop(r, "broken oop in encode_heap_oop_not_null"); + verify_oop_msg(r, "broken oop in encode_heap_oop_not_null"); if (CompressedOops::base() != NULL) { subq(r, r12_heapbase); } @@ -5379,7 +5379,7 @@ void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) { bind(ok); } #endif - verify_oop(src, "broken oop in encode_heap_oop_not_null2"); + verify_oop_msg(src, "broken oop in encode_heap_oop_not_null2"); if (dst != src) { movq(dst, src); } @@ -5408,7 +5408,7 @@ void MacroAssembler::decode_heap_oop(Register r) { addq(r, r12_heapbase); bind(done); } - verify_oop(r, "broken oop in decode_heap_oop"); + verify_oop_msg(r, "broken oop in decode_heap_oop"); } void MacroAssembler::decode_heap_oop_not_null(Register r) { diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 5e664258c71..81081f90578 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -599,14 +599,16 @@ class MacroAssembler: public Assembler { // Debugging // only if +VerifyOops - // TODO: Make these macros with file and line like sparc version! - void verify_oop(Register reg, const char* s = "broken oop"); - void verify_oop_addr(Address addr, const char * s = "broken oop addr"); + void _verify_oop(Register reg, const char* s, const char* file, int line); + void _verify_oop_addr(Address addr, const char* s, const char* file, int line); // TODO: verify method and klass metadata (compare against vptr?) void _verify_method_ptr(Register reg, const char * msg, const char * file, int line) {} void _verify_klass_ptr(Register reg, const char * msg, const char * file, int line){} +#define verify_oop(reg) _verify_oop(reg, "broken oop " #reg, __FILE__, __LINE__) +#define verify_oop_msg(reg, msg) _verify_oop(reg, "broken oop " #reg ", " #msg, __FILE__, __LINE__) +#define verify_oop_addr(addr) _verify_oop_addr(addr, "broken oop addr " #addr, __FILE__, __LINE__) #define verify_method_ptr(reg) _verify_method_ptr(reg, "broken method " #reg, __FILE__, __LINE__) #define verify_klass_ptr(reg) _verify_klass_ptr(reg, "broken klass " #reg, __FILE__, __LINE__) diff --git a/src/hotspot/cpu/x86/nativeInst_x86.cpp b/src/hotspot/cpu/x86/nativeInst_x86.cpp index 03525f8515e..1ac15489562 100644 --- a/src/hotspot/cpu/x86/nativeInst_x86.cpp +++ b/src/hotspot/cpu/x86/nativeInst_x86.cpp @@ -40,15 +40,17 @@ void NativeInstruction::wrote(int offset) { ICache::invalidate_word(addr_at(offset)); } +#ifdef ASSERT void NativeLoadGot::report_and_fail() const { - tty->print_cr("Addr: " INTPTR_FORMAT, p2i(instruction_address())); + tty->print_cr("Addr: " INTPTR_FORMAT " Code: %x %x %x", p2i(instruction_address()), + (has_rex ? ubyte_at(0) : 0), ubyte_at(rex_size), ubyte_at(rex_size + 1)); fatal("not a indirect rip mov to rbx"); } void NativeLoadGot::verify() const { if (has_rex) { int rex = ubyte_at(0); - if (rex != rex_prefix) { + if (rex != rex_prefix && rex != rex_b_prefix) { report_and_fail(); } } @@ -62,6 +64,7 @@ void NativeLoadGot::verify() const { report_and_fail(); } } +#endif intptr_t NativeLoadGot::data() const { return *(intptr_t *) got_address(); @@ -149,14 +152,30 @@ address NativeGotJump::destination() const { return *got_entry; } +#ifdef ASSERT +void NativeGotJump::report_and_fail() const { + tty->print_cr("Addr: " INTPTR_FORMAT " Code: %x %x %x", p2i(instruction_address()), + (has_rex() ? ubyte_at(0) : 0), ubyte_at(rex_size()), ubyte_at(rex_size() + 1)); + fatal("not a indirect rip jump"); +} + void NativeGotJump::verify() const { - int inst = ubyte_at(0); + if (has_rex()) { + int rex = ubyte_at(0); + if (rex != rex_prefix) { + report_and_fail(); + } + } + int inst = ubyte_at(rex_size()); if (inst != instruction_code) { - tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", p2i(instruction_address()), - inst); - fatal("not a indirect rip jump"); + report_and_fail(); + } + int modrm = ubyte_at(rex_size() + 1); + if (modrm != modrm_code) { + report_and_fail(); } } +#endif void NativeCall::verify() { // Make sure code pattern is actually a call imm32 instruction. diff --git a/src/hotspot/cpu/x86/nativeInst_x86.hpp b/src/hotspot/cpu/x86/nativeInst_x86.hpp index 45888b98066..8e7eee7c674 100644 --- a/src/hotspot/cpu/x86/nativeInst_x86.hpp +++ b/src/hotspot/cpu/x86/nativeInst_x86.hpp @@ -455,9 +455,10 @@ class NativeLoadGot: public NativeInstruction { static const bool has_rex = false; static const int rex_size = 0; #endif -public: + enum Intel_specific_constants { rex_prefix = 0x48, + rex_b_prefix = 0x49, instruction_code = 0x8b, modrm_rbx_code = 0x1d, modrm_rax_code = 0x05, @@ -465,11 +466,16 @@ public: offset_offset = 2 + rex_size }; - address instruction_address() const { return addr_at(0); } - address rip_offset_address() const { return addr_at(offset_offset); } int rip_offset() const { return int_at(offset_offset); } address return_address() const { return addr_at(instruction_length); } address got_address() const { return return_address() + rip_offset(); } + +#ifdef ASSERT + void report_and_fail() const; + address instruction_address() const { return addr_at(0); } +#endif + +public: address next_instruction_address() const { return return_address(); } intptr_t data() const; void set_data(intptr_t data) { @@ -477,9 +483,7 @@ public: *addr = data; } - void verify() const; -private: - void report_and_fail() const; + DEBUG_ONLY( void verify() const ); }; inline NativeLoadGot* nativeLoadGot_at(address addr) { @@ -607,27 +611,37 @@ inline NativeGeneralJump* nativeGeneralJump_at(address address) { } class NativeGotJump: public NativeInstruction { -public: enum Intel_specific_constants { + rex_prefix = 0x41, instruction_code = 0xff, - instruction_offset = 0, + modrm_code = 0x25, instruction_size = 6, rip_offset = 2 }; - void verify() const; - address instruction_address() const { return addr_at(instruction_offset); } - address destination() const; - address return_address() const { return addr_at(instruction_size); } - int got_offset() const { return (jint) int_at(rip_offset); } - address got_address() const { return return_address() + got_offset(); } - address next_instruction_address() const { return addr_at(instruction_size); } - bool is_GotJump() const { return ubyte_at(0) == instruction_code; } + bool has_rex() const { return ubyte_at(0) == rex_prefix; } + int rex_size() const { return has_rex() ? 1 : 0; } + address return_address() const { return addr_at(instruction_size + rex_size()); } + int got_offset() const { return (jint) int_at(rip_offset + rex_size()); } + +#ifdef ASSERT + void report_and_fail() const; + address instruction_address() const { return addr_at(0); } +#endif + +public: + address got_address() const { return return_address() + got_offset(); } + address next_instruction_address() const { return return_address(); } + bool is_GotJump() const { return ubyte_at(rex_size()) == instruction_code; } + + address destination() const; void set_jump_destination(address dest) { address *got_entry = (address *) got_address(); *got_entry = dest; } + + DEBUG_ONLY( void verify() const; ) }; inline NativeGotJump* nativeGotJump_at(address addr) { diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 3edda88244f..3424b0b261b 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -33,6 +33,7 @@ #include "runtime/os.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/vm_version.hpp" +#include "utilities/powerOfTwo.hpp" #include "utilities/virtualizationSupport.hpp" #include OS_HEADER_INLINE(os) @@ -40,6 +41,7 @@ int VM_Version::_cpu; int VM_Version::_model; int VM_Version::_stepping; +bool VM_Version::_has_intel_jcc_erratum; VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, }; // Address of instruction which causes SEGV @@ -719,6 +721,8 @@ void VM_Version::get_processor_features() { } } + _has_intel_jcc_erratum = compute_has_intel_jcc_erratum(); + char buf[256]; jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", cores_per_cpu(), threads_per_core(), @@ -1697,6 +1701,70 @@ bool VM_Version::use_biased_locking() { return UseBiasedLocking; } +bool VM_Version::compute_has_intel_jcc_erratum() { + if (!is_intel_family_core()) { + // Only Intel CPUs are affected. + return false; + } + // The following table of affected CPUs is based on the following document released by Intel: + // https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf + switch (_model) { + case 0x8E: + // 06_8EH | 9 | 8th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Amber Lake Y + // 06_8EH | 9 | 7th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Kaby Lake U + // 06_8EH | 9 | 7th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Kaby Lake U 23e + // 06_8EH | 9 | 7th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Kaby Lake Y + // 06_8EH | A | 8th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Coffee Lake U43e + // 06_8EH | B | 8th Generation Intel® Coreâ„¢ Processors based on microarchitecture code name Whiskey Lake U + // 06_8EH | C | 8th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Amber Lake Y + // 06_8EH | C | 10th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Comet Lake U42 + // 06_8EH | C | 8th Generation Intel® Coreâ„¢ Processors based on microarchitecture code name Whiskey Lake U + return _stepping == 0x9 || _stepping == 0xA || _stepping == 0xB || _stepping == 0xC; + case 0x4E: + // 06_4E | 3 | 6th Generation Intel® Coreâ„¢ Processors based on microarchitecture code name Skylake U + // 06_4E | 3 | 6th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Skylake U23e + // 06_4E | 3 | 6th Generation Intel® Coreâ„¢ Processors based on microarchitecture code name Skylake Y + return _stepping == 0x3; + case 0x55: + // 06_55H | 4 | Intel® Xeon® Processor D Family based on microarchitecture code name Skylake D, Bakerville + // 06_55H | 4 | Intel® Xeon® Scalable Processors based on microarchitecture code name Skylake Server + // 06_55H | 4 | Intel® Xeon® Processor W Family based on microarchitecture code name Skylake W + // 06_55H | 4 | Intel® Coreâ„¢ X-series Processors based on microarchitecture code name Skylake X + // 06_55H | 4 | Intel® Xeon® Processor E3 v5 Family based on microarchitecture code name Skylake Xeon E3 + // 06_55 | 7 | 2nd Generation Intel® Xeon® Scalable Processors based on microarchitecture code name Cascade Lake (server) + return _stepping == 0x4 || _stepping == 0x7; + case 0x5E: + // 06_5E | 3 | 6th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Skylake H + // 06_5E | 3 | 6th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Skylake S + return _stepping == 0x3; + case 0x9E: + // 06_9EH | 9 | 8th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Kaby Lake G + // 06_9EH | 9 | 7th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Kaby Lake H + // 06_9EH | 9 | 7th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Kaby Lake S + // 06_9EH | 9 | Intel® Coreâ„¢ X-series Processors based on microarchitecture code name Kaby Lake X + // 06_9EH | 9 | Intel® Xeon® Processor E3 v6 Family Kaby Lake Xeon E3 + // 06_9EH | A | 8th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Coffee Lake H + // 06_9EH | A | 8th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Coffee Lake S + // 06_9EH | A | 8th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Coffee Lake S (6+2) x/KBP + // 06_9EH | A | Intel® Xeon® Processor E Family based on microarchitecture code name Coffee Lake S (6+2) + // 06_9EH | A | Intel® Xeon® Processor E Family based on microarchitecture code name Coffee Lake S (4+2) + // 06_9EH | B | 8th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Coffee Lake S (4+2) + // 06_9EH | B | Intel® Celeron® Processor G Series based on microarchitecture code name Coffee Lake S (4+2) + // 06_9EH | D | 9th Generation Intel® Coreâ„¢ Processor Family based on microarchitecturecode name Coffee Lake H (8+2) + // 06_9EH | D | 9th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Coffee Lake S (8+2) + return _stepping == 0x9 || _stepping == 0xA || _stepping == 0xB || _stepping == 0xD; + case 0xA6: + // 06_A6H | 0 | 10th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Comet Lake U62 + return _stepping == 0x0; + case 0xAE: + // 06_AEH | A | 8th Generation Intel® Coreâ„¢ Processor Family based on microarchitecture code name Kaby Lake Refresh U (4+2) + return _stepping == 0xA; + default: + // If we are running on another intel machine not recognized in the table, we are okay. + return false; + } +} + // On Xen, the cpuid instruction returns // eax / registers[0]: Version of Xen // ebx / registers[1]: chars 'XenV' diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index b546fd53631..3526d1ab4fe 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -293,6 +293,8 @@ protected: static int _model; static int _stepping; + static bool _has_intel_jcc_erratum; + static address _cpuinfo_segv_addr; // address of instruction which causes SEGV static address _cpuinfo_cont_addr; // address of instruction after the one which causes SEGV @@ -499,6 +501,8 @@ enum Extended_Family { return result; } + static bool compute_has_intel_jcc_erratum(); + static uint64_t feature_flags() { uint64_t result = 0; if (_cpuid_info.std_cpuid1_edx.bits.cmpxchg8 != 0) @@ -889,6 +893,12 @@ public: return false; } + // This checks if the JVM is potentially affected by an erratum on Intel CPUs (SKX102) + // that causes unpredictable behaviour when jcc crosses 64 byte boundaries. Its microcode + // mitigation causes regressions when jumps or fused conditional branches cross or end at + // 32 byte boundaries. + static bool has_intel_jcc_erratum() { return _has_intel_jcc_erratum; } + // AMD features static bool supports_3dnow_prefetch() { return (_features & CPU_3DNOW_PREFETCH) != 0; } static bool supports_mmx_ext() { return is_amd_family() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; } diff --git a/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp b/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp index 3906a12e95c..24e080dbe45 100644 --- a/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp +++ b/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,7 +97,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { start_pc = __ pc(); // check offset vs vtable length __ cmpl(Address(rax, Klass::vtable_length_offset()), vtable_index*vtableEntry::size()); - slop_delta = 6 - (__ pc() - start_pc); // cmpl varies in length, depending on data + slop_delta = 10 - (__ pc() - start_pc); // cmpl varies in length, depending on data slop_bytes += slop_delta; assert(slop_delta >= 0, "negative slop(%d) encountered, adjust code size estimate!", slop_delta); @@ -106,7 +106,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { // VTABLE TODO: find upper bound for call_VM length. start_pc = __ pc(); __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), rcx, rbx); - slop_delta = 480 - (__ pc() - start_pc); + slop_delta = 500 - (__ pc() - start_pc); slop_bytes += slop_delta; assert(slop_delta >= 0, "negative slop(%d) encountered, adjust code size estimate!", slop_delta); __ bind(L); diff --git a/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp b/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp index 6c518f5e8db..bf67008f3dd 100644 --- a/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp +++ b/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,7 +97,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { // VTABLE TODO: find upper bound for call_VM length. start_pc = __ pc(); __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), j_rarg0, rbx); - slop_delta = 480 - (__ pc() - start_pc); + slop_delta = 550 - (__ pc() - start_pc); slop_bytes += slop_delta; assert(slop_delta >= 0, "negative slop(%d) encountered, adjust code size estimate!", slop_delta); __ bind(L); diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index f5560d37b82..878b5c5a50b 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -3377,20 +3377,18 @@ instruct ReplS_zero(vec dst, immI0 zero) %{ // ====================ReplicateI======================================= instruct ReplI_reg(vec dst, rRegI src) %{ - predicate((n->as_Vector()->length() <= 8) || - (n->as_Vector()->length() == 16 && VM_Version::supports_avx512vl())); match(Set dst (ReplicateI src)); format %{ "replicateI $dst,$src" %} ins_encode %{ uint vlen = vector_length(this); - if (VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands + if (vlen == 16 || VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands int vlen_enc = vector_length_encoding(this); __ evpbroadcastd($dst$$XMMRegister, $src$$Register, vlen_enc); } else { __ movdl($dst$$XMMRegister, $src$$Register); __ pshufd($dst$$XMMRegister, $dst$$XMMRegister, 0x00); if (vlen >= 8) { - assert(vlen == 8, "sanity"); // vlen == 16 && !AVX512VL is covered by ReplI_reg_leg + assert(vlen == 8, "sanity"); __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); } } @@ -3398,33 +3396,19 @@ instruct ReplI_reg(vec dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct ReplI_reg_leg(legVec dst, rRegI src) %{ - predicate(n->as_Vector()->length() == 16 && !VM_Version::supports_avx512vl()); - match(Set dst (ReplicateI src)); - format %{ "replicateI $dst,$src" %} - ins_encode %{ - __ movdl($dst$$XMMRegister, $src$$Register); - __ pshufd($dst$$XMMRegister, $dst$$XMMRegister, 0x00); - __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti64x4($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, 0x1); - %} - ins_pipe( pipe_slow ); -%} - instruct ReplI_mem(vec dst, memory mem) %{ - predicate((n->as_Vector()->length() <= 8 && VM_Version::supports_avx()) || - (n->as_Vector()->length() == 16 && VM_Version::supports_avx512vl())); + predicate(VM_Version::supports_avx()); // use VEX-encoded pshufd to relax 16-byte alignment restriction on the source match(Set dst (ReplicateI (LoadI mem))); format %{ "replicateI $dst,$mem" %} ins_encode %{ uint vlen = vector_length(this); if (vlen <= 4) { __ pshufd($dst$$XMMRegister, $mem$$Address, 0x00); - } else if (VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands + } else if (vlen == 16 || VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands int vector_len = vector_length_encoding(this); __ vpbroadcastd($dst$$XMMRegister, $mem$$Address, vector_len); } else { - assert(vlen == 8, "sanity"); // vlen == 16 && !AVX512VL is covered by ReplI_mem_leg + assert(vlen == 8, "sanity"); __ pshufd($dst$$XMMRegister, $mem$$Address, 0x00); __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); } @@ -3432,21 +3416,7 @@ instruct ReplI_mem(vec dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct ReplI_mem_leg(legVec dst, memory mem) %{ - predicate(n->as_Vector()->length() == 16 && !VM_Version::supports_avx512vl()); - match(Set dst (ReplicateI (LoadI mem))); - format %{ "replicateI $dst,$mem" %} - ins_encode %{ - __ pshufd($dst$$XMMRegister, $mem$$Address, 0x00); - __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti64x4($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, 0x1); - %} - ins_pipe( pipe_slow ); -%} - instruct ReplI_imm(vec dst, immI con) %{ - predicate((n->as_Vector()->length() <= 8) || - (n->as_Vector()->length() == 16 && VM_Version::supports_avx512vl())); match(Set dst (ReplicateI con)); format %{ "replicateI $dst,$con" %} ins_encode %{ @@ -3454,7 +3424,7 @@ instruct ReplI_imm(vec dst, immI con) %{ InternalAddress constaddr = $constantaddress(replicate8_imm($con$$constant, 4)); if (vlen == 2) { __ movq($dst$$XMMRegister, constaddr); - } else if (VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands + } else if (vlen == 16 || VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands int vector_len = vector_length_encoding(this); __ movq($dst$$XMMRegister, constaddr); __ vpbroadcastd($dst$$XMMRegister, $dst$$XMMRegister, vector_len); @@ -3470,19 +3440,6 @@ instruct ReplI_imm(vec dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct ReplI_imm_leg(legVec dst, immI con) %{ - predicate(n->as_Vector()->length() == 16 && !VM_Version::supports_avx512vl()); - match(Set dst (ReplicateI con)); - format %{ "replicateI $dst,$con" %} - ins_encode %{ - __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 4))); - __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti64x4($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, 0x1); - %} - ins_pipe( pipe_slow ); -%} - // Replicate integer (4 byte) scalar zero to be vector instruct ReplI_zero(vec dst, immI0 zero) %{ match(Set dst (ReplicateI zero)); @@ -3504,8 +3461,6 @@ instruct ReplI_zero(vec dst, immI0 zero) %{ #ifdef _LP64 // Replicate long (8 byte) scalar to be vector instruct ReplL_reg(vec dst, rRegL src) %{ - predicate((n->as_Vector()->length() <= 4) || - (n->as_Vector()->length() == 8 && VM_Version::supports_avx512vl())); match(Set dst (ReplicateL src)); format %{ "replicateL $dst,$src" %} ins_encode %{ @@ -3513,11 +3468,11 @@ instruct ReplL_reg(vec dst, rRegL src) %{ if (vlen == 2) { __ movdq($dst$$XMMRegister, $src$$Register); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - } else if (VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands + } else if (vlen == 8 || VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands int vlen_enc = vector_length_encoding(this); __ evpbroadcastq($dst$$XMMRegister, $src$$Register, vlen_enc); } else { - assert(vlen == 4, "sanity"); // vlen == 8 && !AVX512VL is covered by ReplL_reg_leg + assert(vlen == 4, "sanity"); __ movdq($dst$$XMMRegister, $src$$Register); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); @@ -3525,19 +3480,6 @@ instruct ReplL_reg(vec dst, rRegL src) %{ %} ins_pipe( pipe_slow ); %} - -instruct ReplL_reg_leg(legVec dst, rRegL src) %{ - predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); - match(Set dst (ReplicateL src)); - format %{ "replicateL $dst,$src" %} - ins_encode %{ - __ movdq($dst$$XMMRegister, $src$$Register); - __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti64x4($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, 0x1); - %} - ins_pipe( pipe_slow ); -%} #else // _LP64 // Replicate long (8 byte) scalar to be vector instruct ReplL_reg(vec dst, eRegL src, vec tmp) %{ @@ -3595,8 +3537,6 @@ instruct ReplL_reg_leg(legVec dst, eRegL src, legVec tmp) %{ #endif // _LP64 instruct ReplL_mem(vec dst, memory mem) %{ - predicate((n->as_Vector()->length() <= 4) || - (n->as_Vector()->length() == 8 && VM_Version::supports_avx512vl())); match(Set dst (ReplicateL (LoadL mem))); format %{ "replicateL $dst,$mem" %} ins_encode %{ @@ -3604,11 +3544,11 @@ instruct ReplL_mem(vec dst, memory mem) %{ if (vlen == 2) { __ movq($dst$$XMMRegister, $mem$$Address); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - } else if (VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands + } else if (vlen == 8 || VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands int vlen_enc = vector_length_encoding(this); __ vpbroadcastq($dst$$XMMRegister, $mem$$Address, vlen_enc); } else { - assert(vlen == 4, "sanity"); // vlen == 8 && !AVX512VL is covered by ReplL_mem_leg + assert(vlen == 4, "sanity"); __ movq($dst$$XMMRegister, $mem$$Address); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); @@ -3617,23 +3557,8 @@ instruct ReplL_mem(vec dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct ReplL_mem_leg(legVec dst, memory mem) %{ - predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); - match(Set dst (ReplicateL (LoadL mem))); - format %{ "replicateL $dst,$mem" %} - ins_encode %{ - __ movq($dst$$XMMRegister, $mem$$Address); - __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti64x4($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, 0x1); - %} - ins_pipe( pipe_slow ); -%} - // Replicate long (8 byte) scalar immediate to be vector by loading from const table. instruct ReplL_imm(vec dst, immL con) %{ - predicate((n->as_Vector()->length() <= 4) || - (n->as_Vector()->length() == 8 && VM_Version::supports_avx512vl())); match(Set dst (ReplicateL con)); format %{ "replicateL $dst,$con" %} ins_encode %{ @@ -3642,12 +3567,12 @@ instruct ReplL_imm(vec dst, immL con) %{ if (vlen == 2) { __ movq($dst$$XMMRegister, const_addr); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - } else if (VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands + } else if (vlen == 8 || VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands int vlen_enc = vector_length_encoding(this); __ movq($dst$$XMMRegister, const_addr); __ vpbroadcastq($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); } else { - assert(vlen == 4, "sanity"); // vlen == 8 && !AVX512VL is covered by ReplL_imm_leg + assert(vlen == 4, "sanity"); __ movq($dst$$XMMRegister, const_addr); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); @@ -3656,19 +3581,6 @@ instruct ReplL_imm(vec dst, immL con) %{ ins_pipe( pipe_slow ); %} -instruct ReplL_imm_leg(legVec dst, immL con) %{ - predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); - match(Set dst (ReplicateL con)); - format %{ "replicateL $dst,$con" %} - ins_encode %{ - __ movq($dst$$XMMRegister, $constantaddress($con)); - __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti64x4($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, 0x1); - %} - ins_pipe( pipe_slow ); -%} - instruct ReplL_zero(vec dst, immL0 zero) %{ match(Set dst (ReplicateL zero)); format %{ "replicateL $dst,$zero" %} @@ -3687,19 +3599,17 @@ instruct ReplL_zero(vec dst, immL0 zero) %{ // ====================ReplicateF======================================= instruct ReplF_reg(vec dst, vlRegF src) %{ - predicate((n->as_Vector()->length() <= 8) || - (n->as_Vector()->length() == 16 && VM_Version::supports_avx512vl())); match(Set dst (ReplicateF src)); format %{ "replicateF $dst,$src" %} ins_encode %{ uint vlen = vector_length(this); if (vlen <= 4) { __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0x00); - } else if (VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands + } else if (vlen == 16 || VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands int vector_len = vector_length_encoding(this); - __ vpbroadcastss($dst$$XMMRegister, $src$$XMMRegister, vector_len); + __ vbroadcastss($dst$$XMMRegister, $src$$XMMRegister, vector_len); } else { - assert(vlen == 8, "sanity"); // vlen == 16 && !AVX512VL is covered by ReplF_reg_leg + assert(vlen == 8, "sanity"); __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0x00); __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); } @@ -3707,32 +3617,19 @@ instruct ReplF_reg(vec dst, vlRegF src) %{ ins_pipe( pipe_slow ); %} -instruct ReplF_reg_leg(legVec dst, vlRegF src) %{ - predicate(n->as_Vector()->length() == 16 && !VM_Version::supports_avx512vl()); - match(Set dst (ReplicateF src)); - format %{ "replicateF $dst,$src" %} - ins_encode %{ - __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0x00); - __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti64x4($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, 0x1); - %} - ins_pipe( pipe_slow ); -%} - instruct ReplF_mem(vec dst, memory mem) %{ - predicate((n->as_Vector()->length() <= 8 && VM_Version::supports_avx()) || - (n->as_Vector()->length() == 16 && VM_Version::supports_avx512vl())); + predicate(VM_Version::supports_avx()); // use VEX-encoded pshufd to relax 16-byte alignment restriction on the source match(Set dst (ReplicateF (LoadF mem))); format %{ "replicateF $dst,$mem" %} ins_encode %{ uint vlen = vector_length(this); if (vlen <= 4) { __ pshufd($dst$$XMMRegister, $mem$$Address, 0x00); - } else if (VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands + } else if (vlen == 16 || VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands int vector_len = vector_length_encoding(this); - __ vpbroadcastss($dst$$XMMRegister, $mem$$Address, vector_len); + __ vbroadcastss($dst$$XMMRegister, $mem$$Address, vector_len); } else { - assert(vlen == 8, "sanity"); // vlen == 16 && !AVX512VL is covered by ReplF_mem_leg + assert(vlen == 8, "sanity"); __ pshufd($dst$$XMMRegister, $mem$$Address, 0x00); __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); } @@ -3740,18 +3637,6 @@ instruct ReplF_mem(vec dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct ReplF_mem_leg(legVec dst, memory mem) %{ - predicate(n->as_Vector()->length() == 16 && !VM_Version::supports_avx512vl()); - match(Set dst (ReplicateF (LoadF mem))); - format %{ "replicateF $dst,$mem" %} - ins_encode %{ - __ pshufd($dst$$XMMRegister, $mem$$Address, 0x00); - __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti64x4($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, 0x1); - %} - ins_pipe( pipe_slow ); -%} - instruct ReplF_zero(vec dst, immF0 zero) %{ match(Set dst (ReplicateF zero)); format %{ "replicateF $dst,$zero" %} @@ -3771,19 +3656,17 @@ instruct ReplF_zero(vec dst, immF0 zero) %{ // Replicate double (8 bytes) scalar to be vector instruct ReplD_reg(vec dst, vlRegD src) %{ - predicate((n->as_Vector()->length() <= 4) || - (n->as_Vector()->length() == 8 && VM_Version::supports_avx512vl())); match(Set dst (ReplicateD src)); format %{ "replicateD $dst,$src" %} ins_encode %{ uint vlen = vector_length(this); if (vlen == 2) { __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0x44); - } else if (VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands + } else if (vlen == 8 || VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands int vector_len = vector_length_encoding(this); - __ vpbroadcastsd($dst$$XMMRegister, $src$$XMMRegister, vector_len); + __ vbroadcastsd($dst$$XMMRegister, $src$$XMMRegister, vector_len); } else { - assert(vlen == 4, "sanity"); // vlen == 8 && !AVX512VL is covered by ReplD_reg_leg + assert(vlen == 4, "sanity"); __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0x44); __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); } @@ -3791,32 +3674,19 @@ instruct ReplD_reg(vec dst, vlRegD src) %{ ins_pipe( pipe_slow ); %} -instruct ReplD_reg_leg(legVec dst, vlRegD src) %{ - predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); - match(Set dst (ReplicateD src)); - format %{ "replicateD $dst,$src" %} - ins_encode %{ - __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0x44); - __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti64x4($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, 0x1); - %} - ins_pipe( pipe_slow ); -%} - instruct ReplD_mem(vec dst, memory mem) %{ - predicate((n->as_Vector()->length() <= 4 && VM_Version::supports_avx()) || - (n->as_Vector()->length() == 8 && VM_Version::supports_avx512vl())); + predicate(VM_Version::supports_avx()); // use VEX-encoded pshufd to relax 16-byte alignment restriction on the source match(Set dst (ReplicateD (LoadD mem))); format %{ "replicateD $dst,$mem" %} ins_encode %{ uint vlen = vector_length(this); if (vlen == 2) { __ pshufd($dst$$XMMRegister, $mem$$Address, 0x44); - } else if (VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands + } else if (vlen == 8 || VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands int vector_len = vector_length_encoding(this); - __ vpbroadcastsd($dst$$XMMRegister, $mem$$Address, vector_len); + __ vbroadcastsd($dst$$XMMRegister, $mem$$Address, vector_len); } else { - assert(vlen == 4, "sanity"); // vlen == 8 && !AVX512VL is covered by ReplD_mem_leg + assert(vlen == 4, "sanity"); __ pshufd($dst$$XMMRegister, $mem$$Address, 0x44); __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); } @@ -3824,18 +3694,6 @@ instruct ReplD_mem(vec dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct ReplD_mem_leg(legVec dst, memory mem) %{ - predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); - match(Set dst (ReplicateD (LoadD mem))); - format %{ "replicateD $dst,$mem" %} - ins_encode %{ - __ pshufd($dst$$XMMRegister, $mem$$Address, 0x44); - __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti64x4($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, 0x1); - %} - ins_pipe( pipe_slow ); -%} - instruct ReplD_zero(vec dst, immD0 zero) %{ match(Set dst (ReplicateD zero)); format %{ "replicateD $dst,$zero" %} @@ -5396,18 +5254,6 @@ instruct vshiftcnt(vec dst, rRegI cnt) %{ ins_pipe( pipe_slow ); %} -instruct vshiftcntimm(vec dst, immI8 cnt, rRegI tmp) %{ - match(Set dst cnt); - effect(TEMP tmp); - format %{ "movl $tmp,$cnt\t" - "movdl $dst,$tmp\t! load shift count" %} - ins_encode %{ - __ movl($tmp$$Register, $cnt$$constant); - __ movdl($dst$$XMMRegister, $tmp$$Register); - %} - ins_pipe( pipe_slow ); -%} - // Byte vector shift instruct vshiftB(vec dst, vec src, vec shift, vec tmp, rRegI scratch) %{ predicate(n->as_Vector()->length() <= 8); diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index 44d0567e87b..d81952cc11b 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -1516,8 +1516,7 @@ void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) { node->_opnds[opcnt] = new_memory; } -// Advertise here if the CPU requires explicit rounding operations -// to implement the UseStrictFP mode. +// Advertise here if the CPU requires explicit rounding operations to implement strictfp mode. const bool Matcher::strict_fp_requires_explicit_rounding = true; // Are floats conerted to double when stored to stack during deoptimization? diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index d0ed3e4dc43..9c286576893 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -1700,9 +1700,8 @@ const bool Matcher::misaligned_doubles_ok = true; // No-op on amd64 void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) {} -// Advertise here if the CPU requires explicit rounding operations to -// implement the UseStrictFP mode. -const bool Matcher::strict_fp_requires_explicit_rounding = true; +// Advertise here if the CPU requires explicit rounding operations to implement strictfp mode. +const bool Matcher::strict_fp_requires_explicit_rounding = false; // Are floats conerted to double when stored to stack during deoptimization? // On x64 it is stored without convertion so we can use normal access. @@ -3121,7 +3120,7 @@ operand immL32() operand immL_Pow2() %{ - predicate(is_power_of_2_long(n->get_long())); + predicate(is_power_of_2(n->get_long())); match(ConL); op_cost(15); @@ -3131,7 +3130,7 @@ operand immL_Pow2() operand immL_NotPow2() %{ - predicate(is_power_of_2_long(~n->get_long())); + predicate(is_power_of_2(~n->get_long())); match(ConL); op_cost(15); @@ -10521,24 +10520,6 @@ instruct cmpD_imm(rRegI dst, regD src, immD con, rFlagsReg cr) %{ //----------Arithmetic Conversion Instructions--------------------------------- -instruct roundFloat_nop(regF dst) -%{ - match(Set dst (RoundFloat dst)); - - ins_cost(0); - ins_encode(); - ins_pipe(empty); -%} - -instruct roundDouble_nop(regD dst) -%{ - match(Set dst (RoundDouble dst)); - - ins_cost(0); - ins_encode(); - ins_pipe(empty); -%} - instruct convF2D_reg_reg(regD dst, regF src) %{ match(Set dst (ConvF2D src)); diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index 47f0ba29901..5b30fc7affa 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2019 SAP SE. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3720,10 +3720,18 @@ int os::open(const char *path, int oflag, int mode) { errno = ENAMETOOLONG; return -1; } - int fd; + // AIX 7.X now supports O_CLOEXEC too, like modern Linux; but we have to be careful, see + // IV90804: OPENING A FILE IN AFS WITH O_CLOEXEC FAILS WITH AN EINVAL ERROR APPLIES TO AIX 7100-04 17/04/14 PTF PECHANGE + int oflag_with_o_cloexec = oflag | O_CLOEXEC; - fd = ::open64(path, oflag, mode); - if (fd == -1) return -1; + int fd = ::open64(path, oflag_with_o_cloexec, mode); + if (fd == -1) { + // we might fail in the open call when O_CLOEXEC is set, so try again without (see IV90804) + fd = ::open64(path, oflag, mode); + if (fd == -1) { + return -1; + } + } // If the open succeeded, the file might still be a directory. { @@ -3755,21 +3763,25 @@ int os::open(const char *path, int oflag, int mode) { // // - might cause an fopen in the subprocess to fail on a system // suffering from bug 1085341. - // - // (Yes, the default setting of the close-on-exec flag is a Unix - // design flaw.) - // - // See: - // 1085341: 32-bit stdio routines should support file descriptors >255 - // 4843136: (process) pipe file descriptor from Runtime.exec not being closed - // 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9 -#ifdef FD_CLOEXEC - { + + // Validate that the use of the O_CLOEXEC flag on open above worked. + static sig_atomic_t O_CLOEXEC_is_known_to_work = 0; + if (O_CLOEXEC_is_known_to_work == 0) { int flags = ::fcntl(fd, F_GETFD); - if (flags != -1) + if (flags != -1) { + if ((flags & FD_CLOEXEC) != 0) { + O_CLOEXEC_is_known_to_work = 1; + } else { // it does not work + ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + O_CLOEXEC_is_known_to_work = -1; + } + } + } else if (O_CLOEXEC_is_known_to_work == -1) { + int flags = ::fcntl(fd, F_GETFD); + if (flags != -1) { ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + } } -#endif return fd; } diff --git a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp index c08f93ec212..fd011b22102 100644 --- a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp +++ b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp @@ -137,16 +137,12 @@ ZPhysicalMemoryBacking::ZPhysicalMemoryBacking() : _block_size = buf.f_bsize; _available = buf.f_bavail * _block_size; - // Make sure we're on a supported filesystem - if (!is_tmpfs() && !is_hugetlbfs()) { - log_error(gc)("Backing file must be located on a %s or a %s filesystem", - ZFILESYSTEM_TMPFS, ZFILESYSTEM_HUGETLBFS); - return; - } + log_info(gc, init)("Heap Backing Filesystem: %s (0x" UINT64_FORMAT_X ")", + is_tmpfs() ? ZFILESYSTEM_TMPFS : is_hugetlbfs() ? ZFILESYSTEM_HUGETLBFS : "other", _filesystem); // Make sure the filesystem type matches requested large page type if (ZLargePages::is_transparent() && !is_tmpfs()) { - log_error(gc)("-XX:+UseTransparentHugePages can only be enable when using a %s filesystem", + log_error(gc)("-XX:+UseTransparentHugePages can only be enabled when using a %s filesystem", ZFILESYSTEM_TMPFS); return; } @@ -169,10 +165,22 @@ ZPhysicalMemoryBacking::ZPhysicalMemoryBacking() : return; } - const size_t expected_block_size = is_tmpfs() ? os::vm_page_size() : os::large_page_size(); - if (expected_block_size != _block_size) { + if (ZLargePages::is_explicit() && os::large_page_size() != ZGranuleSize) { + log_error(gc)("Incompatible large page size configured " SIZE_FORMAT " (expected " SIZE_FORMAT ")", + os::large_page_size(), ZGranuleSize); + return; + } + + // Make sure the filesystem block size is compatible + if (ZGranuleSize % _block_size != 0) { + log_error(gc)("Filesystem backing the heap has incompatible block size (" SIZE_FORMAT ")", + _block_size); + return; + } + + if (is_hugetlbfs() && _block_size != ZGranuleSize) { log_error(gc)("%s filesystem has unexpected block size " SIZE_FORMAT " (expected " SIZE_FORMAT ")", - is_tmpfs() ? ZFILESYSTEM_TMPFS : ZFILESYSTEM_HUGETLBFS, _block_size, expected_block_size); + ZFILESYSTEM_HUGETLBFS, _block_size, ZGranuleSize); return; } @@ -195,7 +203,7 @@ int ZPhysicalMemoryBacking::create_mem_fd(const char* name) const { return -1; } - log_info(gc, init)("Heap backed by file: /memfd:%s", filename); + log_info(gc, init)("Heap Backing File: /memfd:%s", filename); return fd; } @@ -231,7 +239,7 @@ int ZPhysicalMemoryBacking::create_file_fd(const char* name) const { return -1; } - log_info(gc, init)("Heap backed by file: %s/#" UINT64_FORMAT, mountpoint.get(), (uint64_t)stat_buf.st_ino); + log_info(gc, init)("Heap Backing File: %s/#" UINT64_FORMAT, mountpoint.get(), (uint64_t)stat_buf.st_ino); return fd_anon; } @@ -257,7 +265,7 @@ int ZPhysicalMemoryBacking::create_file_fd(const char* name) const { return -1; } - log_info(gc, init)("Heap backed by file: %s", filename); + log_info(gc, init)("Heap Backing File: %s", filename); return fd; } diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 3eeb58f0e8e..747fd171b0f 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,6 +74,7 @@ #include "utilities/elfFile.hpp" #include "utilities/growableArray.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #include "utilities/vmError.hpp" // put OS-includes here @@ -717,9 +718,8 @@ void os::Linux::expand_stack_to(address bottom) { bool os::Linux::manually_expand_stack(JavaThread * t, address addr) { assert(t!=NULL, "just checking"); assert(t->osthread()->expanding_stack(), "expand should be set"); - assert(t->stack_base() != NULL, "stack_base was not initialized"); - if (addr < t->stack_base() && addr >= t->stack_reserved_zone_base()) { + if (t->is_in_usable_stack(addr)) { sigset_t mask_all, old_sigset; sigfillset(&mask_all); pthread_sigmask(SIG_SETMASK, &mask_all, &old_sigset); @@ -5126,8 +5126,9 @@ void os::Linux::numa_init() { } else { if ((Linux::numa_max_node() < 1) || Linux::is_bound_to_single_node()) { // If there's only one node (they start from 0) or if the process - // is bound explicitly to a single node using membind, disable NUMA. - UseNUMA = false; + // is bound explicitly to a single node using membind, disable NUMA unless + // user explicilty forces NUMA optimizations on single-node/UMA systems + UseNUMA = ForceNUMA; } else { LogTarget(Info,os) log; @@ -5166,10 +5167,6 @@ void os::Linux::numa_init() { UseAdaptiveNUMAChunkSizing = false; } } - - if (!UseNUMA && ForceNUMA) { - UseNUMA = true; - } } // this is called _after_ the global arguments have been parsed diff --git a/src/hotspot/os/solaris/dtrace/jhelper.d b/src/hotspot/os/solaris/dtrace/jhelper.d index 3412c1af4cd..87bdf4b07fc 100644 --- a/src/hotspot/os/solaris/dtrace/jhelper.d +++ b/src/hotspot/os/solaris/dtrace/jhelper.d @@ -111,7 +111,7 @@ dtrace:helper:ustack: copyin_offset(OFFSET_HeapBlockHeader_used); copyin_offset(OFFSET_oopDesc_metadata); - copyin_offset(OFFSET_Symbol_length_and_refcount); + copyin_offset(OFFSET_Symbol_length); copyin_offset(OFFSET_Symbol_body); copyin_offset(OFFSET_Method_constMethod); @@ -463,17 +463,15 @@ dtrace:helper:ustack: /* The symbol is a CPSlot and has lower bit set to indicate metadata */ this->nameSymbol &= (~1); /* remove metadata lsb */ - /* Because sparc is big endian, the top half length is at the correct offset. */ this->nameSymbolLength = copyin_uint16(this->nameSymbol + - OFFSET_Symbol_length_and_refcount); + OFFSET_Symbol_length); this->signatureSymbol = copyin_ptr(this->constantPool + this->signatureIndex * sizeof (pointer) + SIZE_ConstantPool); this->signatureSymbol &= (~1); /* remove metadata lsb */ - /* Because sparc is big endian, the top half length is at the correct offset. */ this->signatureSymbolLength = copyin_uint16(this->signatureSymbol + - OFFSET_Symbol_length_and_refcount); + OFFSET_Symbol_length); this->klassPtr = copyin_ptr(this->constantPool + OFFSET_ConstantPool_pool_holder); @@ -481,9 +479,8 @@ dtrace:helper:ustack: this->klassSymbol = copyin_ptr(this->klassPtr + OFFSET_Klass_name); - /* Because sparc is big endian, the top half length is at the correct offset. */ this->klassSymbolLength = copyin_uint16(this->klassSymbol + - OFFSET_Symbol_length_and_refcount); + OFFSET_Symbol_length); /* * Enough for three strings, plus the '.', plus the trailing '\0'. diff --git a/src/hotspot/os/solaris/os_solaris.cpp b/src/hotspot/os/solaris/os_solaris.cpp index cdaf66c2594..863ff90b3f8 100644 --- a/src/hotspot/os/solaris/os_solaris.cpp +++ b/src/hotspot/os/solaris/os_solaris.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -539,13 +539,6 @@ void os::breakpoint() { BREAKPOINT; } -bool os::Solaris::valid_stack_address(Thread* thread, address sp) { - address stackStart = (address)thread->stack_base(); - address stackEnd = (address)(stackStart - (address)thread->stack_size()); - if (sp < stackStart && sp >= stackEnd) return true; - return false; -} - extern "C" void breakpoint() { // use debugger to set breakpoint here } @@ -3934,13 +3927,11 @@ jint os::init_2(void) { size_t lgrp_num = os::numa_get_leaf_groups(lgrp_ids, lgrp_limit); FREE_C_HEAP_ARRAY(int, lgrp_ids); if (lgrp_num < 2) { - // There's only one locality group, disable NUMA. - UseNUMA = false; + // There's only one locality group, disable NUMA unless + // user explicilty forces NUMA optimizations on single-node/UMA systems + UseNUMA = ForceNUMA; } } - if (!UseNUMA && ForceNUMA) { - UseNUMA = true; - } } Solaris::signal_sets_init(); diff --git a/src/hotspot/os/solaris/os_solaris.hpp b/src/hotspot/os/solaris/os_solaris.hpp index d01272ee590..6464277abf4 100644 --- a/src/hotspot/os/solaris/os_solaris.hpp +++ b/src/hotspot/os/solaris/os_solaris.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,7 +119,6 @@ class Solaris { static address handler_start, handler_end; // start and end pc of thr_sighndlrinfo - static bool valid_stack_address(Thread* thread, address sp); static bool valid_ucontext(Thread* thread, const ucontext_t* valid, const ucontext_t* suspect); static const ucontext_t* get_valid_uc_in_signal_handler(Thread* thread, const ucontext_t* uc); diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index b2532500d98..24684b8935b 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2542,7 +2542,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { // PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; address addr = (address) exceptionRecord->ExceptionInformation[1]; - if (addr > thread->stack_reserved_zone_base() && addr < thread->stack_base()) { + if (thread->is_in_usable_stack(addr)) { addr = (address)((uintptr_t)addr & (~((uintptr_t)os::vm_page_size() - (uintptr_t)1))); os::commit_memory((char *)addr, thread->stack_base() - addr, diff --git a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp index 2e5cdbe7447..5a3a0909865 100644 --- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp +++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -266,7 +266,7 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec if (thread != NULL) { // Handle ALL stack overflow variations here - if (sig == SIGSEGV && thread->on_local_stack(addr)) { + if (sig == SIGSEGV && thread->is_in_full_stack(addr)) { // stack overflow // // If we are in a yellow zone and we are inside java, we disable the yellow zone and diff --git a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp index 2c436d416a0..0f408bef86a 100644 --- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp +++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -520,7 +520,7 @@ JVM_handle_bsd_signal(int sig, address addr = (address) info->si_addr; // check if fault address is within thread stack - if (thread->on_local_stack(addr)) { + if (thread->is_in_full_stack(addr)) { // stack overflow if (thread->in_stack_yellow_reserved_zone(addr)) { if (thread->thread_state() == _thread_in_Java) { diff --git a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp index d63579d735a..0130ddae61a 100644 --- a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp +++ b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -177,7 +177,7 @@ JVM_handle_bsd_signal(int sig, address addr = (address) info->si_addr; // check if fault address is within thread stack - if (thread->on_local_stack(addr)) { + if (thread->is_in_full_stack(addr)) { // stack overflow if (thread->in_stack_yellow_reserved_zone(addr)) { thread->disable_stack_yellow_reserved_zone(); diff --git a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp index 4cc4702e708..b7c9131a2cb 100644 --- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -293,7 +293,7 @@ JVM_handle_linux_signal(int sig, // Handle ALL stack overflow variations here if (sig == SIGSEGV) { // check if fault address is within thread stack - if (thread->on_local_stack(addr)) { + if (thread->is_in_full_stack(addr)) { // stack overflow if (thread->in_stack_yellow_reserved_zone(addr)) { if (thread->thread_state() == _thread_in_Java) { diff --git a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp index 55c037dfa3e..423bde6b690 100644 --- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp +++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -336,8 +336,7 @@ extern "C" int JVM_handle_linux_signal(int sig, siginfo_t* info, return 1; } // check if fault address is within thread stack - if (addr < thread->stack_base() && - addr >= thread->stack_base() - thread->stack_size()) { + if (thread->is_in_full_stack(addr)) { // stack overflow if (thread->in_stack_yellow_reserved_zone(addr)) { thread->disable_stack_yellow_reserved_zone(); diff --git a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp index 7c78216eef0..3fffc0092c5 100644 --- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp +++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -326,7 +326,7 @@ JVM_handle_linux_signal(int sig, } // Check if fault address is within thread stack. - if (thread->on_local_stack(addr)) { + if (thread->is_in_full_stack(addr)) { // stack overflow if (thread->in_stack_yellow_reserved_zone(addr)) { if (thread->thread_state() == _thread_in_Java) { diff --git a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp index c68244b442c..fb0c3f025f1 100644 --- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp +++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -321,7 +321,7 @@ JVM_handle_linux_signal(int sig, address addr = (address)info->si_addr; // Address causing SIGSEGV, usually mem ref target. // Check if fault address is within thread stack. - if (thread->on_local_stack(addr)) { + if (thread->is_in_full_stack(addr)) { // stack overflow if (thread->in_stack_yellow_reserved_zone(addr)) { if (thread->thread_state() == _thread_in_Java) { diff --git a/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp b/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp index f2fb4e30e7e..4f14f9969f7 100644 --- a/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp +++ b/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -63,7 +63,7 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, if (ret_frame.is_interpreted_frame()) { frame::z_ijava_state* istate = ret_frame.ijava_state_unchecked(); - if (stack_base() >= (address)istate && (address)istate > stack_end()) { + if (is_in_full_stack((address)istate)) { return false; } const Method *m = (const Method*)(istate->method); diff --git a/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp b/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp index 9661e495071..0acfdca7dea 100644 --- a/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp +++ b/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -326,7 +326,7 @@ inline static bool checkOverflow(sigcontext* uc, JavaThread* thread, address* stub) { // check if fault address is within thread stack - if (thread->on_local_stack(addr)) { + if (thread->is_in_full_stack(addr)) { // stack overflow if (thread->in_stack_yellow_reserved_zone(addr)) { thread->disable_stack_yellow_reserved_zone(); diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp index 461bee64cea..e705413e335 100644 --- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -359,7 +359,7 @@ JVM_handle_linux_signal(int sig, address addr = (address) info->si_addr; // check if fault address is within thread stack - if (thread->on_local_stack(addr)) { + if (thread->is_in_full_stack(addr)) { // stack overflow if (thread->in_stack_yellow_reserved_zone(addr)) { if (thread->thread_state() == _thread_in_Java) { diff --git a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp index ce49cf55354..5cf2ea744be 100644 --- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp +++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -173,7 +173,7 @@ JVM_handle_linux_signal(int sig, address addr = (address) info->si_addr; // check if fault address is within thread stack - if (thread->on_local_stack(addr)) { + if (thread->is_in_full_stack(addr)) { // stack overflow if (thread->in_stack_yellow_reserved_zone(addr)) { thread->disable_stack_yellow_reserved_zone(); diff --git a/src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.cpp b/src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.cpp index 9ad8cece991..00e6af2e4d2 100644 --- a/src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.cpp +++ b/src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,12 +120,12 @@ bool os::Solaris::valid_ucontext(Thread* thread, const ucontext_t* valid, const } if (thread->is_Java_thread()) { - if (!valid_stack_address(thread, (address)suspect)) { + if (!thread->is_in_full_stack((address)suspect)) { DEBUG_ONLY(tty->print_cr("valid_ucontext: uc_link not in thread stack");) return false; } address _sp = (address)((intptr_t)suspect->uc_mcontext.gregs[REG_SP] + STACK_BIAS); - if (!valid_stack_address(thread, _sp) || + if (!thread->is_in_full_stack(_sp) || !frame::is_valid_stack_pointer(((JavaThread*)thread)->base_of_stack_pointer(), (intptr_t*)_sp)) { DEBUG_ONLY(tty->print_cr("valid_ucontext: stackpointer not in thread stack");) return false; diff --git a/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp b/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp index a1b89fa823a..6411b1e7f46 100644 --- a/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp +++ b/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -140,11 +140,11 @@ bool os::Solaris::valid_ucontext(Thread* thread, const ucontext_t* valid, const } if (thread->is_Java_thread()) { - if (!valid_stack_address(thread, (address)suspect)) { + if (!thread->is_in_full_stack((address)suspect)) { DEBUG_ONLY(tty->print_cr("valid_ucontext: uc_link not in thread stack");) return false; } - if (!valid_stack_address(thread, (address) suspect->uc_mcontext.gregs[REG_SP])) { + if (!thread->is_in_full_stack((address) suspect->uc_mcontext.gregs[REG_SP])) { DEBUG_ONLY(tty->print_cr("valid_ucontext: stackpointer not in thread stack");) return false; } diff --git a/src/hotspot/os_cpu/solaris_x86/thread_solaris_x86.cpp b/src/hotspot/os_cpu/solaris_x86/thread_solaris_x86.cpp index 1317f74ada1..3ab41905ba4 100644 --- a/src/hotspot/os_cpu/solaris_x86/thread_solaris_x86.cpp +++ b/src/hotspot/os_cpu/solaris_x86/thread_solaris_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,12 +84,12 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, // If sp and fp are nonsense just leave them out - if (!jt->on_local_stack((address)ret_sp)) { + if (!jt->is_in_full_stack((address)ret_sp)) { ret_sp = NULL; ret_fp = NULL; } else { // sp is reasonable is fp reasonable? - if ((address)ret_fp >= jt->stack_base() || ret_fp < ret_sp) { + if (!jt->is_in_stack_range_incl((address)ret_fp, (address)ret_sp)) { ret_fp = NULL; } } @@ -102,4 +102,3 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, } void JavaThread::cache_global_variables() { } - diff --git a/src/hotspot/share/adlc/dfa.cpp b/src/hotspot/share/adlc/dfa.cpp index 3b56d03ef59..da516b8e7e0 100644 --- a/src/hotspot/share/adlc/dfa.cpp +++ b/src/hotspot/share/adlc/dfa.cpp @@ -471,7 +471,7 @@ void ArchDesc::buildDFA(FILE* fp) { class dfa_shared_preds { - enum { count = 4 }; + enum { count = 3 IA32_ONLY( + 1 ) }; static bool _found[count]; static const char* _type [count]; @@ -582,15 +582,10 @@ public: } }; // shared predicates, _var and _pred entry should be the same length -bool dfa_shared_preds::_found[dfa_shared_preds::count] - = { false, false, false, false }; -const char* dfa_shared_preds::_type[dfa_shared_preds::count] - = { "int", "jlong", "intptr_t", "bool" }; -const char* dfa_shared_preds::_var [dfa_shared_preds::count] - = { "_n_get_int__", "_n_get_long__", "_n_get_intptr_t__", "Compile__current____select_24_bit_instr__" }; -const char* dfa_shared_preds::_pred[dfa_shared_preds::count] - = { "n->get_int()", "n->get_long()", "n->get_intptr_t()", "Compile::current()->select_24_bit_instr()" }; - +bool dfa_shared_preds::_found[dfa_shared_preds::count] = { false, false, false IA32_ONLY(COMMA false) }; +const char* dfa_shared_preds::_type [dfa_shared_preds::count] = { "int", "jlong", "intptr_t" IA32_ONLY(COMMA "bool") }; +const char* dfa_shared_preds::_var [dfa_shared_preds::count] = { "_n_get_int__", "_n_get_long__", "_n_get_intptr_t__" IA32_ONLY(COMMA "Compile__current____select_24_bit_instr__") }; +const char* dfa_shared_preds::_pred [dfa_shared_preds::count] = { "n->get_int()", "n->get_long()", "n->get_intptr_t()" IA32_ONLY(COMMA "Compile::current()->select_24_bit_instr()") }; void ArchDesc::gen_dfa_state_body(FILE* fp, Dict &minimize, ProductionState &status, Dict &operands_chained_from, int i) { // Start the body of each Op_XXX sub-dfa with a clean state. diff --git a/src/hotspot/share/adlc/main.cpp b/src/hotspot/share/adlc/main.cpp index 1423cb38dc9..be04e91a84a 100644 --- a/src/hotspot/share/adlc/main.cpp +++ b/src/hotspot/share/adlc/main.cpp @@ -233,6 +233,7 @@ int main(int argc, char *argv[]) AD.addInclude(AD._CPP_file, "runtime/sharedRuntime.hpp"); AD.addInclude(AD._CPP_file, "runtime/stubRoutines.hpp"); AD.addInclude(AD._CPP_file, "utilities/growableArray.hpp"); + AD.addInclude(AD._CPP_file, "utilities/powerOfTwo.hpp"); AD.addInclude(AD._HPP_file, "memory/allocation.hpp"); AD.addInclude(AD._HPP_file, "oops/compressedOops.hpp"); AD.addInclude(AD._HPP_file, "code/nativeInst.hpp"); @@ -268,6 +269,8 @@ int main(int argc, char *argv[]) AD.addInclude(AD._DFA_file, "opto/narrowptrnode.hpp"); AD.addInclude(AD._DFA_file, "opto/opcodes.hpp"); AD.addInclude(AD._DFA_file, "opto/convertnode.hpp"); + AD.addInclude(AD._DFA_file, "utilities/powerOfTwo.hpp"); + // Make sure each .cpp file starts with include lines: // files declaring and defining generators for Mach* Objects (hpp,cpp) // Generate the result files: diff --git a/src/hotspot/share/aot/aotCodeHeap.cpp b/src/hotspot/share/aot/aotCodeHeap.cpp index 7aec0a29e46..970f373ebca 100644 --- a/src/hotspot/share/aot/aotCodeHeap.cpp +++ b/src/hotspot/share/aot/aotCodeHeap.cpp @@ -47,6 +47,7 @@ #include "runtime/safepointVerifiers.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/vmOperations.hpp" +#include "utilities/powerOfTwo.hpp" #include "utilities/sizes.hpp" bool AOTLib::_narrow_oop_shift_initialized = false; diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp index 1f494843af7..558dee23ecc 100644 --- a/src/hotspot/share/asm/codeBuffer.cpp +++ b/src/hotspot/share/asm/codeBuffer.cpp @@ -32,6 +32,7 @@ #include "runtime/safepointVerifiers.hpp" #include "utilities/align.hpp" #include "utilities/copy.hpp" +#include "utilities/powerOfTwo.hpp" #include "utilities/xmlstream.hpp" // The structure of a CodeSection: diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index 2ddf577252b..fd970d2ea9f 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -42,6 +42,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/vm_version.hpp" #include "utilities/bitMap.inline.hpp" +#include "utilities/powerOfTwo.hpp" class BlockListBuilder { private: @@ -607,9 +608,15 @@ class MemoryBuffer: public CompilationResourceObj { return load; } - if (RoundFPResults && UseSSE < 2 && load->type()->is_float_kind()) { - // can't skip load since value might get rounded as a side effect - return load; + if (strict_fp_requires_explicit_rounding && load->type()->is_float_kind()) { +#ifdef IA32 + if (UseSSE < 2) { + // can't skip load since value might get rounded as a side effect + return load; + } +#else + Unimplemented(); +#endif // IA32 } ciField* field = load->field(); @@ -2272,17 +2279,23 @@ void GraphBuilder::throw_op(int bci) { Value GraphBuilder::round_fp(Value fp_value) { - // no rounding needed if SSE2 is used - if (RoundFPResults && UseSSE < 2) { - // Must currently insert rounding node for doubleword values that - // are results of expressions (i.e., not loads from memory or - // constants) - if (fp_value->type()->tag() == doubleTag && - fp_value->as_Constant() == NULL && - fp_value->as_Local() == NULL && // method parameters need no rounding - fp_value->as_RoundFP() == NULL) { - return append(new RoundFP(fp_value)); + if (strict_fp_requires_explicit_rounding) { +#ifdef IA32 + // no rounding needed if SSE2 is used + if (UseSSE < 2) { + // Must currently insert rounding node for doubleword values that + // are results of expressions (i.e., not loads from memory or + // constants) + if (fp_value->type()->tag() == doubleTag && + fp_value->as_Constant() == NULL && + fp_value->as_Local() == NULL && // method parameters need no rounding + fp_value->as_RoundFP() == NULL) { + return append(new RoundFP(fp_value)); + } } +#else + Unimplemented(); +#endif // IA32 } return fp_value; } @@ -3766,11 +3779,17 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, bool ign // Proper inlining of methods with jsrs requires a little more work. if (callee->has_jsrs() ) INLINE_BAILOUT("jsrs not handled properly by inliner yet"); - // When SSE2 is used on intel, then no special handling is needed - // for strictfp because the enum-constant is fixed at compile time, - // the check for UseSSE2 is needed here - if (strict_fp_requires_explicit_rounding && UseSSE < 2 && method()->is_strict() != callee->is_strict()) { - INLINE_BAILOUT("caller and callee have different strict fp requirements"); + if (strict_fp_requires_explicit_rounding && + method()->is_strict() != callee->is_strict()) { +#ifdef IA32 + // If explicit rounding is required, do not inline strict code into non-strict code (or the reverse). + // When SSE2 is present, no special handling is needed. + if (UseSSE < 2) { + INLINE_BAILOUT("caller and callee have different strict fp requirements"); + } +#else + Unimplemented(); +#endif // IA32 } if (is_profiling() && !callee->ensure_method_data()) { diff --git a/src/hotspot/share/c1/c1_LIRAssembler.cpp b/src/hotspot/share/c1/c1_LIRAssembler.cpp index b9eb8f1974e..4854f8b0450 100644 --- a/src/hotspot/share/c1/c1_LIRAssembler.cpp +++ b/src/hotspot/share/c1/c1_LIRAssembler.cpp @@ -778,6 +778,7 @@ void LIR_Assembler::build_frame() { void LIR_Assembler::roundfp_op(LIR_Opr src, LIR_Opr tmp, LIR_Opr dest, bool pop_fpu_stack) { + assert(strict_fp_requires_explicit_rounding, "not required"); assert((src->is_single_fpu() && dest->is_single_stack()) || (src->is_double_fpu() && dest->is_double_stack()), "round_fp: rounds register -> stack location"); diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index 05f1d61f77a..260895e998d 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -43,6 +43,7 @@ #include "runtime/vm_version.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #ifdef ASSERT #define __ gen()->lir(__FILE__, __LINE__)-> @@ -899,13 +900,19 @@ void LIRGenerator::arraycopy_helper(Intrinsic* x, int* flagsp, ciArrayKlass** ex LIR_Opr LIRGenerator::round_item(LIR_Opr opr) { assert(opr->is_register(), "why spill if item is not register?"); - if (RoundFPResults && UseSSE < 1 && opr->is_single_fpu()) { - LIR_Opr result = new_register(T_FLOAT); - set_vreg_flag(result, must_start_in_memory); - assert(opr->is_register(), "only a register can be spilled"); - assert(opr->value_type()->is_float(), "rounding only for floats available"); - __ roundfp(opr, LIR_OprFact::illegalOpr, result); - return result; + if (strict_fp_requires_explicit_rounding) { +#ifdef IA32 + if (UseSSE < 1 && opr->is_single_fpu()) { + LIR_Opr result = new_register(T_FLOAT); + set_vreg_flag(result, must_start_in_memory); + assert(opr->is_register(), "only a register can be spilled"); + assert(opr->value_type()->is_float(), "rounding only for floats available"); + __ roundfp(opr, LIR_OprFact::illegalOpr, result); + return result; + } +#else + Unimplemented(); +#endif // IA32 } return opr; } @@ -1951,6 +1958,8 @@ void LIRGenerator::do_Throw(Throw* x) { void LIRGenerator::do_RoundFP(RoundFP* x) { + assert(strict_fp_requires_explicit_rounding, "not required"); + LIRItem input(x->input(), this); input.load_item(); LIR_Opr input_opr = input.result(); diff --git a/src/hotspot/share/c1/c1_RangeCheckElimination.cpp b/src/hotspot/share/c1/c1_RangeCheckElimination.cpp index 0ec8d49ef33..884cf5cc137 100644 --- a/src/hotspot/share/c1/c1_RangeCheckElimination.cpp +++ b/src/hotspot/share/c1/c1_RangeCheckElimination.cpp @@ -30,6 +30,9 @@ #include "c1/c1_ValueMap.hpp" #include "ci/ciMethodData.hpp" #include "runtime/deoptimization.hpp" +#ifdef ASSERT +#include "utilities/bitMap.inline.hpp" +#endif // Macros for the Trace and the Assertion flag #ifdef ASSERT @@ -1050,6 +1053,7 @@ void RangeCheckEliminator::dump_condition_stack(BlockBegin *block) { } #endif +#ifdef ASSERT // Verification or the IR RangeCheckEliminator::Verification::Verification(IR *ir) : _used(BlockBegin::number_of_blocks(), BlockBegin::number_of_blocks(), false) { this->_ir = ir; @@ -1099,21 +1103,16 @@ void RangeCheckEliminator::Verification::block_do(BlockBegin *block) { BlockList *all_blocks = _ir->linear_scan_order(); assert(block->number_of_preds() >= 1, "Block must have at least one predecessor"); assert(!block->is_set(BlockBegin::exception_entry_flag), "Loop header must not be exception handler!"); - // Sometimes, the backbranch comes from an exception handler. In - // this case, loop indexes/loop depths may not appear correct. - bool loop_through_xhandler = false; - for (int i = 0; i < block->number_of_exception_handlers(); i++) { - BlockBegin *xhandler = block->exception_handler_at(i); - for (int j = 0; j < block->number_of_preds(); j++) { - if (dominates(xhandler, block->pred_at(j)) || xhandler == block->pred_at(j)) { - loop_through_xhandler = true; - } - } - } + bool loop_through_xhandler = false; for (int i=0; inumber_of_sux(); i++) { BlockBegin *sux = block->sux_at(i); - assert(sux->loop_depth() != block->loop_depth() || sux->loop_index() == block->loop_index() || loop_through_xhandler, "Loop index has to be same"); + if (!loop_through_xhandler) { + if (sux->loop_depth() == block->loop_depth() && sux->loop_index() != block->loop_index()) { + loop_through_xhandler = is_backbranch_from_xhandler(block); + assert(loop_through_xhandler, "Loop indices have to be the same if same depths but no backbranch from xhandler"); + } + } assert(sux->loop_depth() == block->loop_depth() || sux->loop_index() != block->loop_index(), "Loop index has to be different"); } @@ -1132,6 +1131,54 @@ void RangeCheckEliminator::Verification::block_do(BlockBegin *block) { } } +// Called when a successor of a block has the same loop depth but a different loop index. This can happen if a backbranch comes from +// an exception handler of a loop head block, for example, when a loop is only executed once on the non-exceptional path but is +// repeated in case of an exception. In this case, the edge block->sux is not critical and was not split before. +// Check if there is such a backbranch from an xhandler of 'block'. +bool RangeCheckEliminator::Verification::is_backbranch_from_xhandler(BlockBegin* block) { + for (int i = 0; i < block->number_of_exception_handlers(); i++) { + BlockBegin *xhandler = block->exception_handler_at(i); + for (int j = 0; j < block->number_of_preds(); j++) { + if (dominates(xhandler, block->pred_at(j)) || xhandler == block->pred_at(j)) { + return true; + } + } + } + + // In case of nested xhandlers, we need to walk through the loop (and all blocks belonging to exception handlers) + // to find an xhandler of 'block'. + if (block->number_of_exception_handlers() > 0) { + for (int i = 0; i < block->number_of_preds(); i++) { + BlockBegin* pred = block->pred_at(i); + if (pred->loop_index() == block->loop_index()) { + // Only check blocks that belong to the loop + // Do a BFS to find an xhandler block of 'block' starting from 'pred' + ResourceMark rm; + ResourceBitMap visited(BlockBegin::number_of_blocks()); + BlockBeginList list; + list.push(pred); + while (!list.is_empty()) { + BlockBegin* next = list.pop(); + if (!visited.at(next->block_id())) { + visited.set_bit(next->block_id()); + for (int j = 0; j < block->number_of_exception_handlers(); j++) { + if (next == block->exception_handler_at(j)) { + return true; + } + } + for (int j = 0; j < next->number_of_preds(); j++) { + if (next->pred_at(j) != block) { + list.push(next->pred_at(j)); + } + } + } + } + } + } + } + return false; +} + // Loop header must dominate all loop blocks bool RangeCheckEliminator::Verification::dominates(BlockBegin *dominator, BlockBegin *block) { BlockBegin *cur = block->dominator(); @@ -1195,6 +1242,7 @@ bool RangeCheckEliminator::Verification::can_reach(BlockBegin *start, BlockBegin return false; } +#endif // ASSERT // Bound RangeCheckEliminator::Bound::~Bound() { diff --git a/src/hotspot/share/c1/c1_RangeCheckElimination.hpp b/src/hotspot/share/c1/c1_RangeCheckElimination.hpp index 629d89245cf..dd5e47cac98 100644 --- a/src/hotspot/share/c1/c1_RangeCheckElimination.hpp +++ b/src/hotspot/share/c1/c1_RangeCheckElimination.hpp @@ -43,6 +43,7 @@ private: typedef GrowableArray BlockBeginList; typedef GrowableArray IntegerStack; +#ifdef ASSERT class Verification : public BlockClosure { // RangeCheckEliminator::Verification should never get instatiated on the heap. private: @@ -51,6 +52,10 @@ private: void operator delete(void* p) { ShouldNotReachHere(); } void operator delete[](void* p) { ShouldNotReachHere(); } + bool can_reach(BlockBegin *start, BlockBegin *end, BlockBegin *dont_use = NULL); + bool dominates(BlockBegin *dominator, BlockBegin *block); + bool is_backbranch_from_xhandler(BlockBegin* block); + IR *_ir; boolArray _used; BlockBeginList _current; @@ -59,9 +64,8 @@ private: public: Verification(IR *ir); virtual void block_do(BlockBegin *block); - bool can_reach(BlockBegin *start, BlockBegin *end, BlockBegin *dont_use = NULL); - bool dominates(BlockBegin *dominator, BlockBegin *block); }; +#endif public: // Bounds for an instruction in the form x + c which c integer diff --git a/src/hotspot/share/c1/c1_globals.hpp b/src/hotspot/share/c1/c1_globals.hpp index cefd889fe84..7d7d440ef5c 100644 --- a/src/hotspot/share/c1/c1_globals.hpp +++ b/src/hotspot/share/c1/c1_globals.hpp @@ -170,9 +170,6 @@ develop(bool, UseTableRanges, true, \ "Faster versions of lookup table using ranges") \ \ - develop_pd(bool, RoundFPResults, \ - "Indicates whether rounding is needed for floating point results")\ - \ develop(intx, NestedInliningSizeRatio, 90, \ "Percentage of prev. allowed inline size in recursive inlining") \ range(0, 100) \ diff --git a/src/hotspot/share/ci/ciArray.cpp b/src/hotspot/share/ci/ciArray.cpp index e7c6dd62890..6db31f4cb88 100644 --- a/src/hotspot/share/ci/ciArray.cpp +++ b/src/hotspot/share/ci/ciArray.cpp @@ -31,6 +31,7 @@ #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayOop.inline.hpp" +#include "utilities/powerOfTwo.hpp" // ciArray // diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index 032eaea3757..8b923bb244d 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -5274,7 +5274,7 @@ const char* ClassFileParser::skip_over_field_signature(const char* signature, if (!legal) { classfile_parse_error("Class name is empty or contains illegal character " "in descriptor in class file %s", - CHECK_0); + CHECK_NULL); return NULL; } return signature + newlen + 1; @@ -5286,7 +5286,7 @@ const char* ClassFileParser::skip_over_field_signature(const char* signature, array_dim++; if (array_dim > 255) { // 4277370: array descriptor is valid only if it represents 255 or fewer dimensions. - classfile_parse_error("Array type descriptor has more than 255 dimensions in class file %s", CHECK_0); + classfile_parse_error("Array type descriptor has more than 255 dimensions in class file %s", CHECK_NULL); } // The rest of what's there better be a legal signature signature++; diff --git a/src/hotspot/share/classfile/classListParser.cpp b/src/hotspot/share/classfile/classListParser.cpp index b4f83e3ec47..b036ebb8ac4 100644 --- a/src/hotspot/share/classfile/classListParser.cpp +++ b/src/hotspot/share/classfile/classListParser.cpp @@ -349,9 +349,9 @@ Klass* ClassListParser::load_current_class(TRAPS) { // delegate to the correct loader (boot, platform or app) depending on // the class name. - Handle s = java_lang_String::create_from_symbol(class_name_symbol, CHECK_0); + Handle s = java_lang_String::create_from_symbol(class_name_symbol, CHECK_NULL); // ClassLoader.loadClass() wants external class name format, i.e., convert '/' chars to '.' - Handle ext_class_name = java_lang_String::externalize_classname(s, CHECK_0); + Handle ext_class_name = java_lang_String::externalize_classname(s, CHECK_NULL); Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); JavaCalls::call_virtual(&result, diff --git a/src/hotspot/share/classfile/fieldLayoutBuilder.cpp b/src/hotspot/share/classfile/fieldLayoutBuilder.cpp index fd38a3fe246..5f30f61597e 100644 --- a/src/hotspot/share/classfile/fieldLayoutBuilder.cpp +++ b/src/hotspot/share/classfile/fieldLayoutBuilder.cpp @@ -134,13 +134,12 @@ void FieldLayout::initialize_instance_layout(const InstanceKlass* super_klass) { _start = _blocks; insert(first_empty_block(), new LayoutRawBlock(LayoutRawBlock::RESERVED, instanceOopDesc::base_offset_in_bytes())); } else { - reconstruct_layout(super_klass); + bool has_fields = reconstruct_layout(super_klass); fill_holes(super_klass); - if (UseEmptySlotsInSupers && !super_klass->has_contended_annotations()) { - _start = _blocks; // Setting _start to _blocks instead of _last would allow subclasses - // to allocate fields in empty slots of their super classes + if ((UseEmptySlotsInSupers && !super_klass->has_contended_annotations()) || !has_fields) { + _start = _blocks; // start allocating fields from the first empty block } else { - _start = _last; + _start = _last; // append fields at the end of the reconstructed layout } } } @@ -294,13 +293,15 @@ LayoutRawBlock* FieldLayout::insert_field_block(LayoutRawBlock* slot, LayoutRawB return block; } -void FieldLayout::reconstruct_layout(const InstanceKlass* ik) { +bool FieldLayout::reconstruct_layout(const InstanceKlass* ik) { + bool has_instance_fields = false; GrowableArray* all_fields = new GrowableArray(32); while (ik != NULL) { for (AllFieldStream fs(ik->fields(), ik->constants()); !fs.done(); fs.next()) { BasicType type = Signature::basic_type(fs.signature()); // distinction between static and non-static fields is missing if (fs.access_flags().is_static()) continue; + has_instance_fields = true; int size = type2aelembytes(type); // INHERITED blocks are marked as non-reference because oop_maps are handled by their holder class LayoutRawBlock* block = new LayoutRawBlock(fs.index(), LayoutRawBlock::INHERITED, size, size, false); @@ -322,6 +323,7 @@ void FieldLayout::reconstruct_layout(const InstanceKlass* ik) { _last = b; } _start = _blocks; + return has_instance_fields; } // Called during the reconstruction of a layout, after fields from super @@ -353,7 +355,7 @@ void FieldLayout::fill_holes(const InstanceKlass* super_klass) { // If the super class has @Contended annotation, a padding block is // inserted at the end to ensure that fields from the subclasses won't share // the cache line of the last field of the contended class - if (super_klass->has_contended_annotations()) { + if (super_klass->has_contended_annotations() && ContendedPaddingWidth > 0) { LayoutRawBlock* p = new LayoutRawBlock(LayoutRawBlock::PADDING, ContendedPaddingWidth); p->set_offset(b->offset() + b->size()); b->set_next_block(p); diff --git a/src/hotspot/share/classfile/fieldLayoutBuilder.hpp b/src/hotspot/share/classfile/fieldLayoutBuilder.hpp index f7c009e39e9..96c1eb3195f 100644 --- a/src/hotspot/share/classfile/fieldLayoutBuilder.hpp +++ b/src/hotspot/share/classfile/fieldLayoutBuilder.hpp @@ -192,7 +192,7 @@ class FieldLayout : public ResourceObj { void add_field_at_offset(LayoutRawBlock* blocks, int offset, LayoutRawBlock* start = NULL); void add_contiguously(GrowableArray* list, LayoutRawBlock* start = NULL); LayoutRawBlock* insert_field_block(LayoutRawBlock* slot, LayoutRawBlock* block); - void reconstruct_layout(const InstanceKlass* ik); + bool reconstruct_layout(const InstanceKlass* ik); void fill_holes(const InstanceKlass* ik); LayoutRawBlock* insert(LayoutRawBlock* slot, LayoutRawBlock* block); void remove(LayoutRawBlock* block); diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 86ceb4f43bf..b2932cd7e88 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -296,7 +296,7 @@ Handle java_lang_String::create_from_unicode(const jchar* unicode, int length, T } oop java_lang_String::create_oop_from_unicode(const jchar* unicode, int length, TRAPS) { - Handle h_obj = create_from_unicode(unicode, length, CHECK_0); + Handle h_obj = create_from_unicode(unicode, length, CHECK_NULL); return h_obj(); } @@ -343,7 +343,7 @@ Handle java_lang_String::create_from_str(const char* utf8_str, TRAPS) { } oop java_lang_String::create_oop_from_str(const char* utf8_str, TRAPS) { - Handle h_obj = create_from_str(utf8_str, CHECK_0); + Handle h_obj = create_from_str(utf8_str, CHECK_NULL); return h_obj(); } @@ -1441,7 +1441,7 @@ void java_lang_Class::set_source_file(oop java_class, oop source_file) { oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) { // This should be improved by adding a field at the Java level or by // introducing a new VM klass (see comment in ClassFileParser) - oop java_class = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(NULL, CHECK_0); + oop java_class = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(NULL, CHECK_NULL); if (type != T_VOID) { Klass* aklass = Universe::typeArrayKlassObj(type); assert(aklass != NULL, "correct bootstrap"); @@ -2647,13 +2647,13 @@ oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRA InstanceKlass* k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); if (k->should_be_initialized()) { - k->initialize(CHECK_0); + k->initialize(CHECK_NULL); } - Handle element = k->allocate_instance_handle(CHECK_0); + Handle element = k->allocate_instance_handle(CHECK_NULL); int version = method->constants()->version(); - fill_in(element, method->method_holder(), method, version, bci, method->name(), CHECK_0); + fill_in(element, method->method_holder(), method, version, bci, method->name(), CHECK_NULL); return element(); } @@ -3399,13 +3399,13 @@ oop java_lang_boxing_object::initialize_and_allocate(BasicType type, TRAPS) { Klass* k = SystemDictionary::box_klass(type); if (k == NULL) return NULL; InstanceKlass* ik = InstanceKlass::cast(k); - if (!ik->is_initialized()) ik->initialize(CHECK_0); + if (!ik->is_initialized()) ik->initialize(CHECK_NULL); return ik->allocate_instance(THREAD); } oop java_lang_boxing_object::create(BasicType type, jvalue* value, TRAPS) { - oop box = initialize_and_allocate(type, CHECK_0); + oop box = initialize_and_allocate(type, CHECK_NULL); if (box == NULL) return NULL; switch (type) { case T_BOOLEAN: @@ -4036,9 +4036,9 @@ oop java_security_AccessControlContext::create(objArrayHandle context, bool isPr assert(_isPrivileged_offset != 0, "offsets should have been initialized"); assert(_isAuthorized_offset != -1, "offsets should have been initialized"); // Ensure klass is initialized - SystemDictionary::AccessControlContext_klass()->initialize(CHECK_0); + SystemDictionary::AccessControlContext_klass()->initialize(CHECK_NULL); // Allocate result - oop result = SystemDictionary::AccessControlContext_klass()->allocate_instance(CHECK_0); + oop result = SystemDictionary::AccessControlContext_klass()->allocate_instance(CHECK_NULL); // Fill in values result->obj_field_put(_context_offset, context()); result->obj_field_put(_privilegedContext_offset, privileged_context()); @@ -4782,9 +4782,9 @@ void JavaClasses::compute_hard_coded_offsets() { // Compute non-hard-coded field offsets of all the classes in this file void JavaClasses::compute_offsets() { if (UseSharedSpaces) { - assert(JvmtiExport::is_early_phase() && !(JvmtiExport::should_post_class_file_load_hook() && - JvmtiExport::has_early_class_hook_env()), - "JavaClasses::compute_offsets() must be called in early JVMTI phase."); + JVMTI_ONLY(assert(JvmtiExport::is_early_phase() && !(JvmtiExport::should_post_class_file_load_hook() && + JvmtiExport::has_early_class_hook_env()), + "JavaClasses::compute_offsets() must be called in early JVMTI phase.")); // None of the classes used by the rest of this function can be replaced by // JMVTI ClassFileLoadHook. // We are safe to use the archived offsets, which have already been restored diff --git a/src/hotspot/share/classfile/stackMapFrame.cpp b/src/hotspot/share/classfile/stackMapFrame.cpp index c102e32c3ff..3edc5868563 100644 --- a/src/hotspot/share/classfile/stackMapFrame.cpp +++ b/src/hotspot/share/classfile/stackMapFrame.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -106,7 +106,7 @@ VerificationType StackMapFrame::set_locals_from_arg( // Create another symbol to save as signature stream unreferences // this symbol. Symbol *sig_copy = - verifier()->create_temporary_symbol(sig, 0, sig->utf8_length()); + verifier()->create_temporary_symbol(sig); assert(sig_copy == sig, "symbols don't match"); sig = sig_copy; } diff --git a/src/hotspot/share/classfile/symbolTable.cpp b/src/hotspot/share/classfile/symbolTable.cpp index 8db26e02657..17dfbc9599d 100644 --- a/src/hotspot/share/classfile/symbolTable.cpp +++ b/src/hotspot/share/classfile/symbolTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ const size_t ON_STACK_BUFFER_LENGTH = 128; inline bool symbol_equals_compact_hashtable_entry(Symbol* value, const char* key, int len) { if (value->equals(key, len)) { - assert(value->refcount() == PERM_REFCOUNT, "must be shared"); + assert(value->is_permanent(), "must be shared"); return true; } else { return false; @@ -139,10 +139,10 @@ public: static void free_node(void* memory, Value const& value) { // We get here because #1 some threads lost a race to insert a newly created Symbol // or #2 we're cleaning up unused symbol. - // If #1, then the symbol can be either permanent (refcount==PERM_REFCOUNT), + // If #1, then the symbol can be either permanent, // or regular newly created one (refcount==1) // If #2, then the symbol is dead (refcount==0) - assert((value->refcount() == PERM_REFCOUNT) || (value->refcount() == 1) || (value->refcount() == 0), + assert(value->is_permanent() || (value->refcount() == 1) || (value->refcount() == 0), "refcount %d", value->refcount()); if (value->refcount() == 1) { value->decrement_refcount(); @@ -176,7 +176,7 @@ void SymbolTable::create_table () { } void SymbolTable::delete_symbol(Symbol* sym) { - if (sym->refcount() == PERM_REFCOUNT) { + if (sym->is_permanent()) { MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena // Deleting permanent symbol should not occur very often (insert race condition), // so log it. diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index decaabe2d56..2d60154b6bf 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -1336,11 +1336,16 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik, ik->restore_unshareable_info(loader_data, protection_domain, CHECK_NULL); } + load_shared_class_misc(ik, loader_data, CHECK_NULL); + return ik; +} + +void SystemDictionary::load_shared_class_misc(InstanceKlass* ik, ClassLoaderData* loader_data, TRAPS) { ik->print_class_load_logging(loader_data, NULL, NULL); // For boot loader, ensure that GetSystemPackage knows that a class in this // package was loaded. - if (class_loader.is_null()) { + if (loader_data->is_the_null_class_loader_data()) { int path_index = ik->shared_classpath_index(); ResourceMark rm(THREAD); ClassLoader::add_package(ik->name()->as_C_string(), path_index, THREAD); @@ -1372,8 +1377,37 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik, } } } +} - return ik; +void SystemDictionary::quick_resolve(InstanceKlass* klass, ClassLoaderData* loader_data, Handle domain, TRAPS) { + assert(!Universe::is_fully_initialized(), "We can make short cuts only during VM initialization"); + assert(klass->is_shared(), "Must be shared class"); + if (klass->class_loader_data() != NULL) { + return; + } + + // add super and interfaces first + Klass* super = klass->super(); + if (super != NULL && super->class_loader_data() == NULL) { + assert(super->is_instance_klass(), "Super should be instance klass"); + quick_resolve(InstanceKlass::cast(super), loader_data, domain, CHECK); + } + + Array* ifs = klass->local_interfaces(); + for (int i = 0; i < ifs->length(); i++) { + InstanceKlass* ik = ifs->at(i); + if (ik->class_loader_data() == NULL) { + quick_resolve(ik, loader_data, domain, CHECK); + } + } + + klass->restore_unshareable_info(loader_data, domain, THREAD); + load_shared_class_misc(klass, loader_data, CHECK); + Dictionary* dictionary = loader_data->dictionary(); + unsigned int hash = dictionary->compute_hash(klass->name()); + dictionary->add_klass(hash, klass->name(), klass); + add_to_hierarchy(klass, CHECK); + assert(klass->is_loaded(), "Must be in at least loaded state"); } #endif // INCLUDE_CDS @@ -1785,7 +1819,9 @@ InstanceKlass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData* void SystemDictionary::add_to_hierarchy(InstanceKlass* k, TRAPS) { assert(k != NULL, "just checking"); - assert_locked_or_safepoint(Compile_lock); + if (Universe::is_fully_initialized()) { + assert_locked_or_safepoint(Compile_lock); + } k->set_init_state(InstanceKlass::loaded); // make sure init_state store is already done. @@ -1798,7 +1834,9 @@ void SystemDictionary::add_to_hierarchy(InstanceKlass* k, TRAPS) { // Now flush all code that depended on old class hierarchy. // Note: must be done *after* linking k into the hierarchy (was bug 12/9/97) - CodeCache::flush_dependents_on(k); + if (Universe::is_fully_initialized()) { + CodeCache::flush_dependents_on(k); + } } // ---------------------------------------------------------------------------- @@ -1917,8 +1955,19 @@ bool SystemDictionary::resolve_wk_klass(WKID id, TRAPS) { Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid); InstanceKlass** klassp = &_well_known_klasses[id]; - if ((*klassp) == NULL) { - Klass* k = resolve_or_fail(symbol, true, CHECK_0); +#if INCLUDE_CDS + if (UseSharedSpaces && !JvmtiExport::should_post_class_prepare()) { + InstanceKlass* k = *klassp; + assert(k->is_shared_boot_class(), "must be"); + + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + quick_resolve(k, loader_data, Handle(), CHECK_false); + return true; + } +#endif // INCLUDE_CDS + + if (!is_wk_klass_loaded(*klassp)) { + Klass* k = resolve_or_fail(symbol, true, CHECK_false); (*klassp) = InstanceKlass::cast(k); } return ((*klassp) != NULL); @@ -1936,7 +1985,7 @@ void SystemDictionary::resolve_wk_klasses_until(WKID limit_id, WKID &start_id, T } void SystemDictionary::resolve_well_known_classes(TRAPS) { - assert(WK_KLASS(Object_klass) == NULL, "well-known classes should only be initialized once"); + assert(!Object_klass_loaded(), "well-known classes should only be initialized once"); // Create the ModuleEntry for java.base. This call needs to be done here, // after vmSymbols::initialize() is called but before any classes are pre-loaded. @@ -1984,10 +2033,6 @@ void SystemDictionary::resolve_well_known_classes(TRAPS) { java_lang_Class::compute_offsets(); // Fixup mirrors for classes loaded before java.lang.Class. - // These calls iterate over the objects currently in the perm gen - // so calling them at this point is matters (not before when there - // are fewer objects and not later after there are more objects - // in the perm gen. Universe::initialize_basic_type_mirrors(CHECK); Universe::fixup_mirrors(CHECK); @@ -2025,8 +2070,8 @@ void SystemDictionary::resolve_well_known_classes(TRAPS) { #ifdef ASSERT if (UseSharedSpaces) { - assert(JvmtiExport::is_early_phase(), - "All well known classes must be resolved in JVMTI early phase"); + JVMTI_ONLY(assert(JvmtiExport::is_early_phase(), + "All well known classes must be resolved in JVMTI early phase")); for (int i = FIRST_WKID; i < last; i++) { InstanceKlass* k = _well_known_klasses[i]; assert(k->is_shared(), "must not be replaced by JVMTI class file load hook"); diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index 838c1089bc3..fc216239f57 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -387,13 +387,15 @@ public: resolve_wk_klasses_until((WKID) limit, start_id, THREAD); } public: + #define WK_KLASS(name) _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)] + #define WK_KLASS_DECLARE(name, symbol) \ static InstanceKlass* name() { return check_klass(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } \ static InstanceKlass** name##_addr() { \ return &_well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]; \ } \ static bool name##_is_loaded() { \ - return _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)] != NULL; \ + return is_wk_klass_loaded(WK_KLASS(name)); \ } WK_KLASSES_DO(WK_KLASS_DECLARE); #undef WK_KLASS_DECLARE @@ -409,9 +411,6 @@ public: } static void well_known_klasses_do(MetaspaceClosure* it); - // Local definition for direct access to the private array: - #define WK_KLASS(name) _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)] - static InstanceKlass* box_klass(BasicType t) { assert((uint)t < T_VOID+1, "range check"); return check_klass(_box_klasses[t]); @@ -431,12 +430,16 @@ protected: return ClassLoaderData::class_loader_data(class_loader()); } + static bool is_wk_klass_loaded(InstanceKlass* klass) { + return !(klass == NULL || !klass->is_loaded()); + } + public: - static bool Parameter_klass_loaded() { return WK_KLASS(reflect_Parameter_klass) != NULL; } - static bool Class_klass_loaded() { return WK_KLASS(Class_klass) != NULL; } - static bool Cloneable_klass_loaded() { return WK_KLASS(Cloneable_klass) != NULL; } - static bool Object_klass_loaded() { return WK_KLASS(Object_klass) != NULL; } - static bool ClassLoader_klass_loaded() { return WK_KLASS(ClassLoader_klass) != NULL; } + static bool Object_klass_loaded() { return is_wk_klass_loaded(WK_KLASS(Object_klass)); } + static bool Class_klass_loaded() { return is_wk_klass_loaded(WK_KLASS(Class_klass)); } + static bool Cloneable_klass_loaded() { return is_wk_klass_loaded(WK_KLASS(Cloneable_klass)); } + static bool Parameter_klass_loaded() { return is_wk_klass_loaded(WK_KLASS(reflect_Parameter_klass)); } + static bool ClassLoader_klass_loaded() { return is_wk_klass_loaded(WK_KLASS(ClassLoader_klass)); } // Returns java system loader static oop java_system_loader(); @@ -596,6 +599,8 @@ protected: Handle protection_domain, const ClassFileStream *cfs, TRAPS); + // Second part of load_shared_class + static void load_shared_class_misc(InstanceKlass* ik, ClassLoaderData* loader_data, TRAPS) NOT_CDS_RETURN; static InstanceKlass* load_shared_boot_class(Symbol* class_name, TRAPS); static InstanceKlass* load_instance_class(Symbol* class_name, Handle class_loader, TRAPS); @@ -628,6 +633,8 @@ protected: // Resolve well-known classes so they can be used like SystemDictionary::String_klass() static void resolve_well_known_classes(TRAPS); + // quick resolve using CDS for well-known classes only. + static void quick_resolve(InstanceKlass* klass, ClassLoaderData* loader_data, Handle domain, TRAPS) NOT_CDS_RETURN; // Class loader constraints static void check_constraints(unsigned int hash, diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index d7725d2ca92..d784c299fb2 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -979,7 +979,7 @@ bool SystemDictionaryShared::add_unregistered_class(InstanceKlass* k, TRAPS) { bool isnew = _loaded_unregistered_classes.put(name, true); assert(isnew, "sanity"); MutexLocker mu_r(THREAD, Compile_lock); // add_to_hierarchy asserts this. - SystemDictionary::add_to_hierarchy(k, CHECK_0); + SystemDictionary::add_to_hierarchy(k, CHECK_false); return true; } } @@ -1410,6 +1410,12 @@ void SystemDictionaryShared::serialize_dictionary_headers(SerializeClosure* soc, } } +void SystemDictionaryShared::serialize_well_known_klasses(SerializeClosure* soc) { + for (int i = FIRST_WKID; i < WKID_LIMIT; i++) { + soc->do_ptr((void**)&_well_known_klasses[i]); + } +} + const RunTimeSharedClassInfo* SystemDictionaryShared::find_record(RunTimeSharedDictionary* static_dict, RunTimeSharedDictionary* dynamic_dict, Symbol* name) { if (!UseSharedSpaces || !name->is_shared()) { diff --git a/src/hotspot/share/classfile/systemDictionaryShared.hpp b/src/hotspot/share/classfile/systemDictionaryShared.hpp index a507856d945..98fdd1ce8ce 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.hpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -303,6 +303,7 @@ public: static void write_to_archive(bool is_static_archive = true); static void serialize_dictionary_headers(class SerializeClosure* soc, bool is_static_archive = true); + static void serialize_well_known_klasses(class SerializeClosure* soc); static void print() { return print_on(tty); } static void print_on(outputStream* st) NOT_CDS_RETURN; static void print_table_statistics(outputStream* st) NOT_CDS_RETURN; diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp index d1de0bc35de..e409ebf8cb9 100644 --- a/src/hotspot/share/classfile/verifier.cpp +++ b/src/hotspot/share/classfile/verifier.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3153,13 +3153,6 @@ void ClassVerifier::verify_return_value( // The verifier creates symbols which are substrings of Symbols. // These are stored in the verifier until the end of verification so that // they can be reference counted. -Symbol* ClassVerifier::create_temporary_symbol(const Symbol *s, int begin, - int end) { - const char* name = (const char*)s->base() + begin; - int length = end - begin; - return create_temporary_symbol(name, length); -} - Symbol* ClassVerifier::create_temporary_symbol(const char *name, int length) { // Quick deduplication check if (_previous_symbol != NULL && _previous_symbol->equals(name, length)) { diff --git a/src/hotspot/share/classfile/verifier.hpp b/src/hotspot/share/classfile/verifier.hpp index f6db892a6fa..e629b4f5623 100644 --- a/src/hotspot/share/classfile/verifier.hpp +++ b/src/hotspot/share/classfile/verifier.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -456,7 +456,6 @@ class ClassVerifier : public StackObj { // their reference counts need to be decremented when the verifier object // goes out of scope. Since these symbols escape the scope in which they're // created, we can't use a TempNewSymbol. - Symbol* create_temporary_symbol(const Symbol* s, int begin, int end); Symbol* create_temporary_symbol(const char *s, int length); Symbol* create_temporary_symbol(Symbol* s) { if (s == _previous_symbol) { diff --git a/src/hotspot/share/code/codeHeapState.cpp b/src/hotspot/share/code/codeHeapState.cpp index ca5c439fcde..19d336a661a 100644 --- a/src/hotspot/share/code/codeHeapState.cpp +++ b/src/hotspot/share/code/codeHeapState.cpp @@ -27,6 +27,7 @@ #include "code/codeHeapState.hpp" #include "compiler/compileBroker.hpp" #include "runtime/sweeper.hpp" +#include "utilities/powerOfTwo.hpp" // ------------------------- // | General Description | diff --git a/src/hotspot/share/code/vtableStubs.cpp b/src/hotspot/share/code/vtableStubs.cpp index b1bf9e8e5df..08914882dc3 100644 --- a/src/hotspot/share/code/vtableStubs.cpp +++ b/src/hotspot/share/code/vtableStubs.cpp @@ -38,6 +38,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/align.hpp" +#include "utilities/powerOfTwo.hpp" #ifdef COMPILER2 #include "opto/matcher.hpp" #endif @@ -128,7 +129,7 @@ void VtableStubs::initialize() { { MutexLocker ml(VtableStubs_lock, Mutex::_no_safepoint_check_flag); assert(_number_of_vtable_stubs == 0, "potential performance bug: VtableStubs initialized more than once"); - assert(is_power_of_2(N), "N must be a power of 2"); + assert(is_power_of_2(int(N)), "N must be a power of 2"); for (int i = 0; i < N; i++) { _table[i] = NULL; } diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp index 5eadf3c8b9c..b5ce247f917 100644 --- a/src/hotspot/share/compiler/compilationPolicy.cpp +++ b/src/hotspot/share/compiler/compilationPolicy.cpp @@ -295,8 +295,8 @@ void SimpleCompPolicy::reset_counter_for_invocation_event(const methodHandle& m) // Set carry bit and reduce counter's value to min(count, CompileThreshold/2). MethodCounters* mcs = m->method_counters(); assert(mcs != NULL, "MethodCounters cannot be NULL for profiling"); - mcs->invocation_counter()->set_carry(); - mcs->backedge_counter()->set_carry(); + mcs->invocation_counter()->set_carry_and_reduce(); + mcs->backedge_counter()->set_carry_and_reduce(); assert(!m->was_never_executed(), "don't reset to 0 -- could be mistaken for never-executed"); } @@ -312,9 +312,9 @@ void SimpleCompPolicy::reset_counter_for_back_branch_event(const methodHandle& m // Don't set invocation_counter's value too low otherwise the method will // look like immature (ic < ~5300) which prevents the inlining based on // the type profiling. - i->set(i->state(), CompileThreshold); + i->set(CompileThreshold); // Don't reset counter too low - it is used to check if OSR method is ready. - b->set(b->state(), CompileThreshold / 2); + b->set(CompileThreshold / 2); } // Called at the end of the safepoint @@ -340,7 +340,7 @@ void SimpleCompPolicy::reprofile(ScopeDesc* trap_scope, bool is_osr) { c = mcs->invocation_counter(); if (is_osr) { // It was an OSR method, so bump the count higher. - c->set(c->state(), CompileThreshold); + c->set(CompileThreshold); } else { c->reset(); } @@ -358,14 +358,6 @@ void SimpleCompPolicy::delay_compilation(Method* method) { } } -void SimpleCompPolicy::disable_compilation(Method* method) { - MethodCounters* mcs = method->method_counters(); - if (mcs != NULL) { - mcs->invocation_counter()->set_state(InvocationCounter::wait_for_nothing); - mcs->backedge_counter()->set_state(InvocationCounter::wait_for_nothing); - } -} - CompileTask* SimpleCompPolicy::select_task(CompileQueue* compile_queue) { return select_task_helper(compile_queue); } diff --git a/src/hotspot/share/compiler/compilationPolicy.hpp b/src/hotspot/share/compiler/compilationPolicy.hpp index cc5b8cb4f6a..088b2673e2a 100644 --- a/src/hotspot/share/compiler/compilationPolicy.hpp +++ b/src/hotspot/share/compiler/compilationPolicy.hpp @@ -71,9 +71,6 @@ public: // delay_compilation(method) can be called by any component of the runtime to notify the policy // that it's recommended to delay the compilation of this method. virtual void delay_compilation(Method* method) = 0; - // disable_compilation() is called whenever the runtime decides to disable compilation of the - // specified method. - virtual void disable_compilation(Method* method) = 0; // Select task is called by CompileBroker. The queue is guaranteed to have at least one // element and is locked. The function should select one and return it. virtual CompileTask* select_task(CompileQueue* compile_queue) = 0; @@ -102,7 +99,6 @@ class SimpleCompPolicy : public CompilationPolicy { virtual void do_safepoint_work(); virtual void reprofile(ScopeDesc* trap_scope, bool is_osr); virtual void delay_compilation(Method* method); - virtual void disable_compilation(Method* method); virtual bool is_mature(Method* method); virtual void initialize(); virtual CompileTask* select_task(CompileQueue* compile_queue); diff --git a/src/hotspot/share/compiler/tieredThresholdPolicy.cpp b/src/hotspot/share/compiler/tieredThresholdPolicy.cpp index fb76545ce41..3177a833bf4 100644 --- a/src/hotspot/share/compiler/tieredThresholdPolicy.cpp +++ b/src/hotspot/share/compiler/tieredThresholdPolicy.cpp @@ -379,23 +379,17 @@ CompLevel TieredThresholdPolicy::initial_compile_level(const methodHandle& metho return limit_level(initial_compile_level_helper(method)); } -void TieredThresholdPolicy::set_carry_if_necessary(InvocationCounter *counter) { - if (!counter->carry() && counter->count() > InvocationCounter::count_limit / 2) { - counter->set_carry_flag(); - } -} - // Set carry flags on the counters if necessary void TieredThresholdPolicy::handle_counter_overflow(Method* method) { MethodCounters *mcs = method->method_counters(); if (mcs != NULL) { - set_carry_if_necessary(mcs->invocation_counter()); - set_carry_if_necessary(mcs->backedge_counter()); + mcs->invocation_counter()->set_carry_on_overflow(); + mcs->backedge_counter()->set_carry_on_overflow(); } MethodData* mdo = method->method_data(); if (mdo != NULL) { - set_carry_if_necessary(mdo->invocation_counter()); - set_carry_if_necessary(mdo->backedge_counter()); + mdo->invocation_counter()->set_carry_on_overflow(); + mdo->backedge_counter()->set_carry_on_overflow(); } } diff --git a/src/hotspot/share/gc/g1/g1BiasedArray.hpp b/src/hotspot/share/gc/g1/g1BiasedArray.hpp index e669a139fab..1e98033a2db 100644 --- a/src/hotspot/share/gc/g1/g1BiasedArray.hpp +++ b/src/hotspot/share/gc/g1/g1BiasedArray.hpp @@ -27,6 +27,7 @@ #include "memory/memRegion.hpp" #include "utilities/debug.hpp" +#include "utilities/powerOfTwo.hpp" // Implements the common base functionality for arrays that contain provisions // for accessing its elements using a biased index. diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 2f08c359b23..ca55da6383e 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1799,8 +1799,8 @@ jint G1CollectedHeap::initialize() { // Create the G1ConcurrentMark data structure and thread. // (Must do this late, so that "max_regions" is defined.) _cm = new G1ConcurrentMark(this, prev_bitmap_storage, next_bitmap_storage); - if (_cm == NULL || !_cm->completed_initialization()) { - vm_shutdown_during_initialization("Could not create/initialize G1ConcurrentMark"); + if (!_cm->completed_initialization()) { + vm_shutdown_during_initialization("Could not initialize G1ConcurrentMark"); return JNI_ENOMEM; } _cm_thread = _cm->cm_thread(); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 7282d4ab7e8..a03718e622c 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -261,20 +261,15 @@ void G1CMMarkStack::set_empty() { } G1CMRootMemRegions::G1CMRootMemRegions(uint const max_regions) : - _root_regions(NULL), + _root_regions(MemRegion::create_array(max_regions, mtGC)), _max_regions(max_regions), _num_root_regions(0), _claimed_root_regions(0), _scan_in_progress(false), - _should_abort(false) { - _root_regions = new MemRegion[_max_regions]; - if (_root_regions == NULL) { - vm_exit_during_initialization("Could not allocate root MemRegion set."); - } -} + _should_abort(false) { } G1CMRootMemRegions::~G1CMRootMemRegions() { - delete[] _root_regions; + FREE_C_HEAP_ARRAY(MemRegion, _root_regions); } void G1CMRootMemRegions::reset() { diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp index 7a8563f4576..3cf1907fd5a 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp @@ -72,11 +72,7 @@ jint G1ConcurrentRefineThreadControl::initialize(G1ConcurrentRefine* cr, uint nu _cr = cr; _num_max_threads = num_max_threads; - _threads = NEW_C_HEAP_ARRAY_RETURN_NULL(G1ConcurrentRefineThread*, num_max_threads, mtGC); - if (_threads == NULL) { - vm_shutdown_during_initialization("Could not allocate thread holder array."); - return JNI_ENOMEM; - } + _threads = NEW_C_HEAP_ARRAY(G1ConcurrentRefineThread*, num_max_threads, mtGC); for (uint i = 0; i < num_max_threads; i++) { if (UseDynamicNumberOfGCThreads && i != 0 /* Always start first thread. */) { @@ -303,13 +299,6 @@ G1ConcurrentRefine* G1ConcurrentRefine::create(jint* ecode) { yellow_zone, red_zone, min_yellow_zone_size); - - if (cr == NULL) { - *ecode = JNI_ENOMEM; - vm_shutdown_during_initialization("Could not create G1ConcurrentRefine"); - return NULL; - } - *ecode = cr->initialize(); return cr; } diff --git a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp index 694aa86df98..54d7137f217 100644 --- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp +++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp @@ -138,7 +138,6 @@ void G1DirtyCardQueueSet::Queue::append(BufferNode& first, BufferNode& last) { assert(last.next() == NULL, "precondition"); BufferNode* old_tail = Atomic::xchg(&_tail, &last); if (old_tail == NULL) { // Was empty. - assert(Atomic::load(&_head) == NULL, "invariant"); Atomic::store(&_head, &first); } else { assert(old_tail->next() == NULL, "invariant"); @@ -146,53 +145,65 @@ void G1DirtyCardQueueSet::Queue::append(BufferNode& first, BufferNode& last) { } } -// pop gets the queue head as the candidate result (returning NULL if the -// queue head was NULL), and then gets that result node's "next" value. If -// that "next" value is NULL and the queue head hasn't changed, then there -// is only one element in the accessible part of the list (the sequence from -// head to a node with a NULL "next" value). We can't return that element, -// because it may be the old tail of a concurrent push/append that has not -// yet had its "next" field set to the new tail. So return NULL in this case. -// Otherwise, attempt to cmpxchg that "next" value into the queue head, -// retrying the whole operation if that fails. This is the "usual" lock-free -// pop from the head of a singly linked list, with the additional restriction -// on taking the last element. BufferNode* G1DirtyCardQueueSet::Queue::pop() { Thread* current_thread = Thread::current(); while (true) { // Use a critical section per iteration, rather than over the whole - // operation. We're not guaranteed to make progress, because of possible - // contention on the queue head. Lingering in one CS the whole time could - // lead to excessive allocation of buffers, because the CS blocks return - // of released buffers to the free list for reuse. + // operation. We're not guaranteed to make progress. Lingering in one + // CS could lead to excessive allocation of buffers, because the CS + // blocks return of released buffers to the free list for reuse. GlobalCounter::CriticalSection cs(current_thread); BufferNode* result = Atomic::load_acquire(&_head); - // Check for empty queue. Only needs to be done on first iteration, - // since we never take the last element, but it's messy to make use - // of that and we expect one iteration to be the common case. - if (result == NULL) return NULL; + if (result == NULL) return NULL; // Queue is empty. BufferNode* next = Atomic::load_acquire(BufferNode::next_ptr(*result)); if (next != NULL) { - next = Atomic::cmpxchg(&_head, result, next); - if (next == result) { + // The "usual" lock-free pop from the head of a singly linked list. + if (result == Atomic::cmpxchg(&_head, result, next)) { // Former head successfully taken; it is not the last. assert(Atomic::load(&_tail) != result, "invariant"); assert(result->next() != NULL, "invariant"); result->set_next(NULL); return result; } - // cmpxchg failed; try again. - } else if (result == Atomic::load_acquire(&_head)) { - // If follower of head is NULL and head hasn't changed, then only - // the one element is currently accessible. We don't take the last - // accessible element, because there may be a concurrent add using it. - // The check for unchanged head isn't needed for correctness, but the - // retry on change may sometimes let us get a buffer after all. - return NULL; + // Lost the race; try again. + continue; } - // Head changed; try again. + + // next is NULL. This case is handled differently from the "usual" + // lock-free pop from the head of a singly linked list. + + // If _tail == result then result is the only element in the list. We can + // remove it from the list by first setting _tail to NULL and then setting + // _head to NULL, the order being important. We set _tail with cmpxchg in + // case of a concurrent push/append/pop also changing _tail. If we win + // then we've claimed result. + if (Atomic::cmpxchg(&_tail, result, (BufferNode*)NULL) == result) { + assert(result->next() == NULL, "invariant"); + // Now that we've claimed result, also set _head to NULL. But we must + // be careful of a concurrent push/append after we NULLed _tail, since + // it may have already performed its list-was-empty update of _head, + // which we must not overwrite. + Atomic::cmpxchg(&_head, result, (BufferNode*)NULL); + return result; + } + + // If _head != result then we lost the race to take result; try again. + if (result != Atomic::load_acquire(&_head)) { + continue; + } + + // An in-progress concurrent operation interfered with taking the head + // element when it was the only element. A concurrent pop may have won + // the race to clear the tail but not yet cleared the head. Alternatively, + // a concurrent push/append may have changed the tail but not yet linked + // result->next(). We cannot take result in either case. We don't just + // try again, because we could spin for a long time waiting for that + // concurrent operation to finish. In the first case, returning NULL is + // fine; we lost the race for the only element to another thread. We + // also return NULL for the second case, and let the caller cope. + return NULL; } } @@ -217,19 +228,17 @@ void G1DirtyCardQueueSet::enqueue_completed_buffer(BufferNode* cbn) { } BufferNode* G1DirtyCardQueueSet::get_completed_buffer(size_t stop_at) { - enqueue_previous_paused_buffers(); - - // Check for insufficient cards to satisfy request. We only do this once, - // up front, rather than on each iteration below, since the test is racy - // regardless of when we do it. - if (Atomic::load_acquire(&_num_cards) <= stop_at) { + if (Atomic::load_acquire(&_num_cards) < stop_at) { return NULL; } BufferNode* result = _completed.pop(); - if (result != NULL) { - Atomic::sub(&_num_cards, buffer_size() - result->index()); + if (result == NULL) { // Unlikely if no paused buffers. + enqueue_previous_paused_buffers(); + result = _completed.pop(); + if (result == NULL) return NULL; } + Atomic::sub(&_num_cards, buffer_size() - result->index()); return result; } @@ -287,31 +296,24 @@ G1DirtyCardQueueSet::PausedBuffers::PausedBuffers() : _plist(NULL) {} #ifdef ASSERT G1DirtyCardQueueSet::PausedBuffers::~PausedBuffers() { - assert(is_empty(), "invariant"); + assert(Atomic::load(&_plist) == NULL, "invariant"); } #endif // ASSERT -bool G1DirtyCardQueueSet::PausedBuffers::is_empty() const { - return Atomic::load(&_plist) == NULL; -} - void G1DirtyCardQueueSet::PausedBuffers::add(BufferNode* node) { assert_not_at_safepoint(); PausedList* plist = Atomic::load_acquire(&_plist); - if (plist != NULL) { - // Already have a next list, so use it. We know it's a next list because - // of the precondition that take_previous() has already been called. - assert(plist->is_next(), "invariant"); - } else { + if (plist == NULL) { // Try to install a new next list. plist = new PausedList(); PausedList* old_plist = Atomic::cmpxchg(&_plist, (PausedList*)NULL, plist); if (old_plist != NULL) { - // Some other thread installed a new next list. Use it instead. + // Some other thread installed a new next list. Use it instead. delete plist; plist = old_plist; } } + assert(plist->is_next(), "invariant"); plist->add(node); } @@ -355,6 +357,8 @@ G1DirtyCardQueueSet::HeadTail G1DirtyCardQueueSet::PausedBuffers::take_all() { void G1DirtyCardQueueSet::record_paused_buffer(BufferNode* node) { assert_not_at_safepoint(); assert(node->next() == NULL, "precondition"); + // Ensure there aren't any paused buffers from a previous safepoint. + enqueue_previous_paused_buffers(); // Cards for paused buffers are included in count, to contribute to // notification checking after the coming safepoint if it doesn't GC. // Note that this means the queue's _num_cards differs from the number @@ -373,25 +377,7 @@ void G1DirtyCardQueueSet::enqueue_paused_buffers_aux(const HeadTail& paused) { void G1DirtyCardQueueSet::enqueue_previous_paused_buffers() { assert_not_at_safepoint(); - // The fast-path still satisfies the precondition for record_paused_buffer - // and PausedBuffers::add, even with a racy test. If there are paused - // buffers from a previous safepoint, is_empty() will return false; there - // will have been a safepoint between recording and test, so there can't be - // a false negative (is_empty() returns true) while such buffers are present. - // If is_empty() is false, there are two cases: - // - // (1) There were paused buffers from a previous safepoint. A concurrent - // caller may take and enqueue them first, but that's okay; the precondition - // for a possible later record_paused_buffer by this thread will still hold. - // - // (2) There are paused buffers for a requested next safepoint. - // - // In each of those cases some effort may be spent detecting and dealing - // with those circumstances; any wasted effort in such cases is expected to - // be well compensated by the fast path. - if (!_paused.is_empty()) { - enqueue_paused_buffers_aux(_paused.take_previous()); - } + enqueue_paused_buffers_aux(_paused.take_previous()); } void G1DirtyCardQueueSet::enqueue_all_paused_buffers() { diff --git a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp index 443bc6021c7..e27cf428cce 100644 --- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp +++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp @@ -77,11 +77,8 @@ class G1DirtyCardQueueSet: public PtrQueueSet { }; // A lock-free FIFO of BufferNodes, linked through their next() fields. - // This class has a restriction that pop() cannot return the last buffer - // in the queue, or what was the last buffer for a concurrent push/append - // operation. It is expected that there will be a later push/append that - // will make that buffer available to a future pop(), or there will - // eventually be a complete transfer via take_all(). + // This class has a restriction that pop() may return NULL when there are + // buffers in the queue if there is a concurrent push/append operation. class Queue { BufferNode* volatile _head; DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(BufferNode*)); @@ -105,9 +102,10 @@ class G1DirtyCardQueueSet: public PtrQueueSet { void append(BufferNode& first, BufferNode& last); // Thread-safe attempt to remove and return the first buffer in the queue. - // Returns NULL if the queue is empty, or if only one buffer is found. - // Uses GlobalCounter critical sections to address the ABA problem; this - // works with the buffer allocator's use of GlobalCounter synchronization. + // Returns NULL if the queue is empty, or if a concurrent push/append + // interferes. Uses GlobalCounter critical sections to address the ABA + // problem; this works with the buffer allocator's use of GlobalCounter + // synchronization. BufferNode* pop(); // Take all the buffers from the queue, leaving the queue empty. @@ -180,10 +178,6 @@ class G1DirtyCardQueueSet: public PtrQueueSet { PausedBuffers(); DEBUG_ONLY(~PausedBuffers();) - // Test whether there are any paused lists. - // Thread-safe, but the answer may change immediately. - bool is_empty() const; - // Thread-safe add the buffer to paused list for next safepoint. // precondition: not at safepoint. // precondition: does not have paused buffers from a previous safepoint. @@ -230,7 +224,6 @@ class G1DirtyCardQueueSet: public PtrQueueSet { // Thread-safe add a buffer to paused list for next safepoint. // precondition: not at safepoint. - // precondition: does not have paused buffers from a previous safepoint. void record_paused_buffer(BufferNode* node); void enqueue_paused_buffers_aux(const HeadTail& paused); // Thread-safe transfer paused buffers for previous safepoints to the queue. diff --git a/src/hotspot/share/gc/g1/g1RegionMarkStatsCache.cpp b/src/hotspot/share/gc/g1/g1RegionMarkStatsCache.cpp index d436efa51b5..f5ff7b404ac 100644 --- a/src/hotspot/share/gc/g1/g1RegionMarkStatsCache.cpp +++ b/src/hotspot/share/gc/g1/g1RegionMarkStatsCache.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "gc/g1/g1RegionMarkStatsCache.inline.hpp" #include "memory/allocation.inline.hpp" +#include "utilities/powerOfTwo.hpp" G1RegionMarkStatsCache::G1RegionMarkStatsCache(G1RegionMarkStats* target, uint max_regions, uint num_cache_entries) : _target(target), diff --git a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp index b187f90ac75..cef4c9b1ab3 100644 --- a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp +++ b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp @@ -35,6 +35,7 @@ #include "utilities/align.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/formatBuffer.hpp" +#include "utilities/powerOfTwo.hpp" G1RegionToSpaceMapper::G1RegionToSpaceMapper(ReservedSpace rs, size_t used_size, diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp index ef0a31b8d3c..b7babde2c49 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp @@ -92,14 +92,7 @@ OtherRegionsTable::OtherRegionsTable(Mutex* m) : _fine_eviction_stride = _max_fine_entries / _fine_eviction_sample_size; } - _fine_grain_regions = NEW_C_HEAP_ARRAY3(PerRegionTablePtr, _max_fine_entries, - mtGC, CURRENT_PC, AllocFailStrategy::RETURN_NULL); - - if (_fine_grain_regions == NULL) { - vm_exit_out_of_memory(sizeof(void*)*_max_fine_entries, OOM_MALLOC_ERROR, - "Failed to allocate _fine_grain_entries."); - } - + _fine_grain_regions = NEW_C_HEAP_ARRAY(PerRegionTablePtr, _max_fine_entries, mtGC); for (size_t i = 0; i < _max_fine_entries; i++) { _fine_grain_regions[i] = NULL; } diff --git a/src/hotspot/share/gc/parallel/asPSYoungGen.cpp b/src/hotspot/share/gc/parallel/asPSYoungGen.cpp index 30e7580e09a..279c93efd48 100644 --- a/src/hotspot/share/gc/parallel/asPSYoungGen.cpp +++ b/src/hotspot/share/gc/parallel/asPSYoungGen.cpp @@ -60,8 +60,7 @@ void ASPSYoungGen::initialize_virtual_space(ReservedSpace rs, assert(_init_gen_size != 0, "Should have a finite size"); _virtual_space = new PSVirtualSpaceHighToLow(rs, alignment); if (!_virtual_space->expand_by(_init_gen_size)) { - vm_exit_during_initialization("Could not reserve enough space for " - "object heap"); + vm_exit_during_initialization("Could not reserve enough space for object heap"); } } diff --git a/src/hotspot/share/gc/parallel/parallelArguments.cpp b/src/hotspot/share/gc/parallel/parallelArguments.cpp index 30216323ffd..23dcbe52d08 100644 --- a/src/hotspot/share/gc/parallel/parallelArguments.cpp +++ b/src/hotspot/share/gc/parallel/parallelArguments.cpp @@ -35,6 +35,7 @@ #include "runtime/globals_extension.hpp" #include "runtime/java.hpp" #include "utilities/defaultStream.hpp" +#include "utilities/powerOfTwo.hpp" static const double MaxRamFractionForYoung = 0.8; diff --git a/src/hotspot/share/gc/parallel/parallel_globals.hpp b/src/hotspot/share/gc/parallel/parallel_globals.hpp index 20e0ce294d2..f949fa5f133 100644 --- a/src/hotspot/share/gc/parallel/parallel_globals.hpp +++ b/src/hotspot/share/gc/parallel/parallel_globals.hpp @@ -51,22 +51,16 @@ "Use maximum compaction in the Parallel Old garbage collector " \ "for a system GC") \ \ - product(size_t, ParallelOldDeadWoodLimiterMean, 50, \ + product(size_t, ParallelOldDeadWoodLimiterMean, 50, \ "The mean used by the parallel compact dead wood " \ "limiter (a number between 0-100)") \ range(0, 100) \ \ - product(size_t, ParallelOldDeadWoodLimiterStdDev, 80, \ + product(size_t, ParallelOldDeadWoodLimiterStdDev, 80, \ "The standard deviation used by the parallel compact dead wood " \ "limiter (a number between 0-100)") \ range(0, 100) \ \ - develop(bool, TraceParallelOldGCMarkingPhase, false, \ - "Trace marking phase in ParallelOldGC") \ - \ - develop(bool, TraceParallelOldGCDensePrefix, false, \ - "Trace dense prefix computation for ParallelOldGC") \ - \ develop(uintx, GCWorkerDelayMillis, 0, \ "Delay in scheduling GC workers (in milliseconds)") \ \ diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.cpp b/src/hotspot/share/gc/parallel/psCompactionManager.cpp index 63dfc6ffa7c..f5cf79916d5 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.cpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.cpp @@ -40,15 +40,15 @@ #include "oops/objArrayKlass.inline.hpp" #include "oops/oop.inline.hpp" -PSOldGen* ParCompactionManager::_old_gen = NULL; +PSOldGen* ParCompactionManager::_old_gen = NULL; ParCompactionManager** ParCompactionManager::_manager_array = NULL; -OopTaskQueueSet* ParCompactionManager::_stack_array = NULL; -ParCompactionManager::ObjArrayTaskQueueSet* - ParCompactionManager::_objarray_queues = NULL; +ParCompactionManager::OopTaskQueueSet* ParCompactionManager::_oop_task_queues = NULL; +ParCompactionManager::ObjArrayTaskQueueSet* ParCompactionManager::_objarray_task_queues = NULL; +ParCompactionManager::RegionTaskQueueSet* ParCompactionManager::_region_task_queues = NULL; + ObjectStartArray* ParCompactionManager::_start_array = NULL; ParMarkBitMap* ParCompactionManager::_mark_bitmap = NULL; -RegionTaskQueueSet* ParCompactionManager::_region_array = NULL; GrowableArray* ParCompactionManager::_shadow_region_array = NULL; Monitor* ParCompactionManager::_shadow_region_monitor = NULL; @@ -77,27 +77,21 @@ void ParCompactionManager::initialize(ParMarkBitMap* mbm) { assert(_manager_array == NULL, "Attempt to initialize twice"); _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1, mtGC); - _stack_array = new OopTaskQueueSet(parallel_gc_threads); - guarantee(_stack_array != NULL, "Could not allocate stack_array"); - _objarray_queues = new ObjArrayTaskQueueSet(parallel_gc_threads); - guarantee(_objarray_queues != NULL, "Could not allocate objarray_queues"); - _region_array = new RegionTaskQueueSet(parallel_gc_threads); - guarantee(_region_array != NULL, "Could not allocate region_array"); + _oop_task_queues = new OopTaskQueueSet(parallel_gc_threads); + _objarray_task_queues = new ObjArrayTaskQueueSet(parallel_gc_threads); + _region_task_queues = new RegionTaskQueueSet(parallel_gc_threads); // Create and register the ParCompactionManager(s) for the worker threads. for(uint i=0; iregister_queue(i, _manager_array[i]->marking_stack()); - _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_stack); - region_array()->register_queue(i, _manager_array[i]->region_stack()); + oop_task_queues()->register_queue(i, _manager_array[i]->marking_stack()); + _objarray_task_queues->register_queue(i, &_manager_array[i]->_objarray_stack); + region_task_queues()->register_queue(i, _manager_array[i]->region_stack()); } // The VMThread gets its own ParCompactionManager, which is not available // for work stealing. _manager_array[parallel_gc_threads] = new ParCompactionManager(); - guarantee(_manager_array[parallel_gc_threads] != NULL, - "Could not create ParCompactionManager"); assert(ParallelScavengeHeap::heap()->workers().total_workers() != 0, "Not initialized?"); diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.hpp b/src/hotspot/share/gc/parallel/psCompactionManager.hpp index 4b80a68b512..6b899231ac6 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.hpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.hpp @@ -51,17 +51,22 @@ class ParCompactionManager : public CHeapObj { private: + typedef GenericTaskQueue OopTaskQueue; + typedef GenericTaskQueueSet OopTaskQueueSet; + // 32-bit: 4K * 8 = 32KiB; 64-bit: 8K * 16 = 128KiB #define QUEUE_SIZE (1 << NOT_LP64(12) LP64_ONLY(13)) typedef OverflowTaskQueue ObjArrayTaskQueue; typedef GenericTaskQueueSet ObjArrayTaskQueueSet; #undef QUEUE_SIZE + typedef OverflowTaskQueue RegionTaskQueue; + typedef GenericTaskQueueSet RegionTaskQueueSet; static ParCompactionManager** _manager_array; - static OopTaskQueueSet* _stack_array; - static ObjArrayTaskQueueSet* _objarray_queues; + static OopTaskQueueSet* _oop_task_queues; + static ObjArrayTaskQueueSet* _objarray_task_queues; static ObjectStartArray* _start_array; - static RegionTaskQueueSet* _region_array; + static RegionTaskQueueSet* _region_task_queues; static PSOldGen* _old_gen; private: @@ -90,13 +95,13 @@ private: static PSOldGen* old_gen() { return _old_gen; } static ObjectStartArray* start_array() { return _start_array; } - static OopTaskQueueSet* stack_array() { return _stack_array; } + static OopTaskQueueSet* oop_task_queues() { return _oop_task_queues; } static void initialize(ParMarkBitMap* mbm); protected: // Array of task queues. Needed by the task terminator. - static RegionTaskQueueSet* region_array() { return _region_array; } + static RegionTaskQueueSet* region_task_queues() { return _region_task_queues; } OverflowTaskQueue* marking_stack() { return &_marking_stack; } // Pushes onto the marking stack. If the marking stack is full, diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp index 1a1cd8d85f6..1d38e0c01b4 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,15 +70,15 @@ public: }; inline bool ParCompactionManager::steal(int queue_num, oop& t) { - return stack_array()->steal(queue_num, t); + return oop_task_queues()->steal(queue_num, t); } inline bool ParCompactionManager::steal_objarray(int queue_num, ObjArrayTask& t) { - return _objarray_queues->steal(queue_num, t); + return _objarray_task_queues->steal(queue_num, t); } inline bool ParCompactionManager::steal(int queue_num, size_t& region) { - return region_array()->steal(queue_num, region); + return region_task_queues()->steal(queue_num, region); } inline void ParCompactionManager::push(oop obj) { diff --git a/src/hotspot/share/gc/parallel/psOldGen.cpp b/src/hotspot/share/gc/parallel/psOldGen.cpp index faa7d90c7d4..e5998186576 100644 --- a/src/hotspot/share/gc/parallel/psOldGen.cpp +++ b/src/hotspot/share/gc/parallel/psOldGen.cpp @@ -135,10 +135,6 @@ void PSOldGen::initialize_work(const char* perf_data_name, int level) { // _object_space = new MutableSpace(virtual_space()->alignment()); - - if (_object_space == NULL) - vm_exit_during_initialization("Could not allocate an old gen space"); - object_space()->initialize(cmr, SpaceDecorator::Clear, SpaceDecorator::Mangle); diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 8e9c12d2713..8cc853e5727 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1115,14 +1115,14 @@ PSParallelCompact::compute_dense_prefix_via_density(const SpaceId id, (1.0 - cur_density) * (1.0 - cur_density) * cur_density * cur_density; const size_t deadwood_goal = size_t(space_capacity * deadwood_density); - if (TraceParallelOldGCDensePrefix) { - tty->print_cr("cur_dens=%5.3f dw_dens=%5.3f dw_goal=" SIZE_FORMAT, - cur_density, deadwood_density, deadwood_goal); - tty->print_cr("space_live=" SIZE_FORMAT " " "space_used=" SIZE_FORMAT " " - "space_cap=" SIZE_FORMAT, - space_live, space_used, - space_capacity); - } + log_develop_debug(gc, compaction)( + "cur_dens=%5.3f dw_dens=%5.3f dw_goal=" SIZE_FORMAT, + cur_density, deadwood_density, deadwood_goal); + log_develop_debug(gc, compaction)( + "space_live=" SIZE_FORMAT " space_used=" SIZE_FORMAT " " + "space_cap=" SIZE_FORMAT, + space_live, space_used, + space_capacity); // XXX - Use binary search? HeapWord* dense_prefix = sd.region_to_addr(cp); @@ -1131,12 +1131,12 @@ PSParallelCompact::compute_dense_prefix_via_density(const SpaceId id, while (cp < end_cp) { HeapWord* region_destination = cp->destination(); const size_t cur_deadwood = pointer_delta(dense_prefix, region_destination); - if (TraceParallelOldGCDensePrefix && Verbose) { - tty->print_cr("c#=" SIZE_FORMAT_W(4) " dst=" PTR_FORMAT " " - "dp=" PTR_FORMAT " " "cdw=" SIZE_FORMAT_W(8), - sd.region(cp), p2i(region_destination), - p2i(dense_prefix), cur_deadwood); - } + + log_develop_trace(gc, compaction)( + "c#=" SIZE_FORMAT_W(4) " dst=" PTR_FORMAT " " + "dp=" PTR_FORMAT " cdw=" SIZE_FORMAT_W(8), + sd.region(cp), p2i(region_destination), + p2i(dense_prefix), cur_deadwood); if (cur_deadwood >= deadwood_goal) { // Found the region that has the correct amount of deadwood to the left. @@ -1158,11 +1158,13 @@ PSParallelCompact::compute_dense_prefix_via_density(const SpaceId id, if (density_to_right <= prev_region_density_to_right) { return dense_prefix; } - if (TraceParallelOldGCDensePrefix && Verbose) { - tty->print_cr("backing up from c=" SIZE_FORMAT_W(4) " d2r=%10.8f " - "pc_d2r=%10.8f", sd.region(cp), density_to_right, - prev_region_density_to_right); - } + + log_develop_trace(gc, compaction)( + "backing up from c=" SIZE_FORMAT_W(4) " d2r=%10.8f " + "pc_d2r=%10.8f", + sd.region(cp), density_to_right, + prev_region_density_to_right); + dense_prefix -= region_size; live_to_right = prev_region_live_to_right; space_to_right = prev_region_space_to_right; @@ -1196,16 +1198,17 @@ void PSParallelCompact::print_dense_prefix_stats(const char* const algorithm, const size_t live_to_right = new_top - cp->destination(); const size_t dead_to_right = space->top() - addr - live_to_right; - tty->print_cr("%s=" PTR_FORMAT " dpc=" SIZE_FORMAT_W(5) " " - "spl=" SIZE_FORMAT " " - "d2l=" SIZE_FORMAT " d2l%%=%6.4f " - "d2r=" SIZE_FORMAT " l2r=" SIZE_FORMAT - " ratio=%10.8f", - algorithm, p2i(addr), region_idx, - space_live, - dead_to_left, dead_to_left_pct, - dead_to_right, live_to_right, - double(dead_to_right) / live_to_right); + log_develop_debug(gc, compaction)( + "%s=" PTR_FORMAT " dpc=" SIZE_FORMAT_W(5) " " + "spl=" SIZE_FORMAT " " + "d2l=" SIZE_FORMAT " d2l%%=%6.4f " + "d2r=" SIZE_FORMAT " l2r=" SIZE_FORMAT " " + "ratio=%10.8f", + algorithm, p2i(addr), region_idx, + space_live, + dead_to_left, dead_to_left_pct, + dead_to_right, live_to_right, + double(dead_to_right) / live_to_right); } #endif // #ifndef PRODUCT @@ -1413,16 +1416,16 @@ PSParallelCompact::compute_dense_prefix(const SpaceId id, const size_t dead_wood_limit = MIN2(size_t(space_capacity * limiter), dead_wood_max); - if (TraceParallelOldGCDensePrefix) { - tty->print_cr("space_live=" SIZE_FORMAT " " "space_used=" SIZE_FORMAT " " - "space_cap=" SIZE_FORMAT, - space_live, space_used, - space_capacity); - tty->print_cr("dead_wood_limiter(%6.4f, " SIZE_FORMAT ")=%6.4f " - "dead_wood_max=" SIZE_FORMAT " dead_wood_limit=" SIZE_FORMAT, - density, min_percent_free, limiter, - dead_wood_max, dead_wood_limit); - } + log_develop_debug(gc, compaction)( + "space_live=" SIZE_FORMAT " space_used=" SIZE_FORMAT " " + "space_cap=" SIZE_FORMAT, + space_live, space_used, + space_capacity); + log_develop_debug(gc, compaction)( + "dead_wood_limiter(%6.4f, " SIZE_FORMAT ")=%6.4f " + "dead_wood_max=" SIZE_FORMAT " dead_wood_limit=" SIZE_FORMAT, + density, min_percent_free, limiter, + dead_wood_max, dead_wood_limit); // Locate the region with the desired amount of dead space to the left. const RegionData* const limit_cp = @@ -1536,7 +1539,7 @@ PSParallelCompact::summarize_space(SpaceId id, bool maximum_compaction) _space_info[id].set_dense_prefix(dense_prefix_end); #ifndef PRODUCT - if (TraceParallelOldGCDensePrefix) { + if (log_is_enabled(Debug, gc, compaction)) { print_dense_prefix_stats("ratio", id, maximum_compaction, dense_prefix_end); HeapWord* addr = compute_dense_prefix_via_density(id, maximum_compaction); @@ -1610,16 +1613,16 @@ void PSParallelCompact::summary_phase(ParCompactionManager* cm, { GCTraceTime(Info, gc, phases) tm("Summary Phase", &_gc_timer); -#ifdef ASSERT - if (TraceParallelOldGCMarkingPhase) { - tty->print_cr("add_obj_count=" SIZE_FORMAT " " - "add_obj_bytes=" SIZE_FORMAT, - add_obj_count, add_obj_size * HeapWordSize); - tty->print_cr("mark_bitmap_count=" SIZE_FORMAT " " - "mark_bitmap_bytes=" SIZE_FORMAT, - mark_bitmap_count, mark_bitmap_size * HeapWordSize); - } -#endif // #ifdef ASSERT + log_develop_debug(gc, marking)( + "add_obj_count=" SIZE_FORMAT " " + "add_obj_bytes=" SIZE_FORMAT, + add_obj_count, + add_obj_size * HeapWordSize); + log_develop_debug(gc, marking)( + "mark_bitmap_count=" SIZE_FORMAT " " + "mark_bitmap_bytes=" SIZE_FORMAT, + mark_bitmap_count, + mark_bitmap_size * HeapWordSize); // Quick summarization of each space into itself, to see how much is live. summarize_spaces_quick(); @@ -2178,7 +2181,7 @@ public: AbstractGangTask("MarkFromRootsTask"), _strong_roots_scope(active_workers), _subtasks(), - _terminator(active_workers, ParCompactionManager::stack_array()), + _terminator(active_workers, ParCompactionManager::oop_task_queues()), _active_workers(active_workers) { _subtasks.set_n_threads(active_workers); _subtasks.set_n_tasks(ParallelRootType::sentinel); @@ -2210,7 +2213,7 @@ public: AbstractGangTask("PCRefProcTask"), _task(task), _ergo_workers(ergo_workers), - _terminator(_ergo_workers, ParCompactionManager::stack_array()) { + _terminator(_ergo_workers, ParCompactionManager::oop_task_queues()) { } virtual void work(uint worker_id) { @@ -2626,7 +2629,7 @@ public: UpdateDensePrefixAndCompactionTask(TaskQueue& tq, uint active_workers) : AbstractGangTask("UpdateDensePrefixAndCompactionTask"), _tq(tq), - _terminator(active_workers, ParCompactionManager::region_array()), + _terminator(active_workers, ParCompactionManager::region_task_queues()), _active_workers(active_workers) { } virtual void work(uint worker_id) { diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.cpp b/src/hotspot/share/gc/parallel/psPromotionManager.cpp index c3865bb4a2a..9729998b940 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.cpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.cpp @@ -43,7 +43,7 @@ #include "oops/compressedOops.inline.hpp" PaddedEnd* PSPromotionManager::_manager_array = NULL; -OopStarTaskQueueSet* PSPromotionManager::_stack_array_depth = NULL; +PSPromotionManager::OopStarTaskQueueSet* PSPromotionManager::_stack_array_depth = NULL; PreservedMarksSet* PSPromotionManager::_preserved_marks_set = NULL; PSOldGen* PSPromotionManager::_old_gen = NULL; MutableSpace* PSPromotionManager::_young_space = NULL; @@ -60,10 +60,8 @@ void PSPromotionManager::initialize() { // and make sure that the first instance starts at a cache line. assert(_manager_array == NULL, "Attempt to initialize twice"); _manager_array = PaddedArray::create_unfreeable(promotion_manager_num); - guarantee(_manager_array != NULL, "Could not initialize promotion manager"); _stack_array_depth = new OopStarTaskQueueSet(ParallelGCThreads); - guarantee(_stack_array_depth != NULL, "Could not initialize promotion manager"); // Create and register the PSPromotionManager(s) for the worker threads. for(uint i=0; iinit(promotion_manager_num); for (uint i = 0; i < promotion_manager_num; i += 1) { _manager_array[i].register_preserved_marks(_preserved_marks_set->get(i)); diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.hpp index 025eada67f8..25b24dcc579 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,6 +56,9 @@ class PSPromotionManager { friend class PSRefProcTask; private: + typedef OverflowTaskQueue OopStarTaskQueue; + typedef GenericTaskQueueSet OopStarTaskQueueSet; + static PaddedEnd* _manager_array; static OopStarTaskQueueSet* _stack_array_depth; static PreservedMarksSet* _preserved_marks_set; diff --git a/src/hotspot/share/gc/parallel/psYoungGen.cpp b/src/hotspot/share/gc/parallel/psYoungGen.cpp index e98db1c0712..b6d252629f6 100644 --- a/src/hotspot/share/gc/parallel/psYoungGen.cpp +++ b/src/hotspot/share/gc/parallel/psYoungGen.cpp @@ -88,10 +88,6 @@ void PSYoungGen::initialize_work() { _from_space = new MutableSpace(virtual_space()->alignment()); _to_space = new MutableSpace(virtual_space()->alignment()); - if (_eden_space == NULL || _from_space == NULL || _to_space == NULL) { - vm_exit_during_initialization("Could not allocate a young gen space"); - } - // Generation Counters - generation 0, 3 subspaces _gen_counters = new PSGenerationCounters("new", 0, 3, _min_gen_size, _max_gen_size, _virtual_space); diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index d4429d6ebcc..06bb7c21971 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -168,10 +168,6 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs, _from_space = new ContiguousSpace(); _to_space = new ContiguousSpace(); - if (_eden_space == NULL || _from_space == NULL || _to_space == NULL) { - vm_exit_during_initialization("Could not allocate a new gen space"); - } - // Compute the maximum eden and survivor space sizes. These sizes // are computed assuming the entire reserved space is committed. // These values are exported as performance counters. diff --git a/src/hotspot/share/gc/shared/cardGeneration.cpp b/src/hotspot/share/gc/shared/cardGeneration.cpp index fac2fe92279..361770fcdfd 100644 --- a/src/hotspot/share/gc/shared/cardGeneration.cpp +++ b/src/hotspot/share/gc/shared/cardGeneration.cpp @@ -53,9 +53,6 @@ CardGeneration::CardGeneration(ReservedSpace rs, heap_word_size(initial_byte_size)); MemRegion committed_mr(start, heap_word_size(initial_byte_size)); _rs->resize_covered_region(committed_mr); - if (_bts == NULL) { - vm_exit_during_initialization("Could not allocate a BlockOffsetArray"); - } // Verify that the start and end of this generation is the start of a card. // If this wasn't true, a single card could span more than on generation, diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index f1061ea1093..f0cd858e73f 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -51,30 +51,19 @@ CardTable::CardTable(MemRegion whole_heap, bool conc_scan) : _byte_map(NULL), _byte_map_base(NULL), _cur_covered_regions(0), - _covered(NULL), - _committed(NULL), + _covered(MemRegion::create_array(_max_covered_regions, mtGC)), + _committed(MemRegion::create_array(_max_covered_regions, mtGC)), _guard_region() { assert((uintptr_t(_whole_heap.start()) & (card_size - 1)) == 0, "heap must start at card boundary"); assert((uintptr_t(_whole_heap.end()) & (card_size - 1)) == 0, "heap must end at card boundary"); assert(card_size <= 512, "card_size must be less than 512"); // why? - - _covered = new MemRegion[_max_covered_regions]; - if (_covered == NULL) { - vm_exit_during_initialization("Could not allocate card table covered region set."); - } } CardTable::~CardTable() { - if (_covered) { - delete[] _covered; - _covered = NULL; - } - if (_committed) { - delete[] _committed; - _committed = NULL; - } + FREE_C_HEAP_ARRAY(MemRegion, _covered); + FREE_C_HEAP_ARRAY(MemRegion, _committed); } void CardTable::initialize() { @@ -87,10 +76,6 @@ void CardTable::initialize() { HeapWord* high_bound = _whole_heap.end(); _cur_covered_regions = 0; - _committed = new MemRegion[_max_covered_regions]; - if (_committed == NULL) { - vm_exit_during_initialization("Could not allocate card table committed region set."); - } const size_t rs_align = _page_size == (size_t) os::vm_page_size() ? 0 : MAX2(_page_size, (size_t) os::vm_allocation_granularity()); diff --git a/src/hotspot/share/gc/shared/cardTableRS.cpp b/src/hotspot/share/gc/shared/cardTableRS.cpp index 285fd662cef..2b16a8b70e9 100644 --- a/src/hotspot/share/gc/shared/cardTableRS.cpp +++ b/src/hotspot/share/gc/shared/cardTableRS.cpp @@ -579,11 +579,7 @@ CardTableRS::CardTableRS(MemRegion whole_heap, bool scanned_concurrently) : // max_gens is really GenCollectedHeap::heap()->gen_policy()->number_of_generations() // (which is always 2, young & old), but GenCollectedHeap has not been initialized yet. uint max_gens = 2; - _last_cur_val_in_gen = NEW_C_HEAP_ARRAY3(CardValue, max_gens + 1, - mtGC, CURRENT_PC, AllocFailStrategy::RETURN_NULL); - if (_last_cur_val_in_gen == NULL) { - vm_exit_during_initialization("Could not create last_cur_val_in_gen array."); - } + _last_cur_val_in_gen = NEW_C_HEAP_ARRAY(CardValue, max_gens + 1, mtGC); for (uint i = 0; i < max_gens + 1; i++) { _last_cur_val_in_gen[i] = clean_card_val(); } diff --git a/src/hotspot/share/gc/shared/generation.cpp b/src/hotspot/share/gc/shared/generation.cpp index 492bd823d4e..9bbe80f258f 100644 --- a/src/hotspot/share/gc/shared/generation.cpp +++ b/src/hotspot/share/gc/shared/generation.cpp @@ -79,9 +79,6 @@ void Generation::ref_processor_init() { assert(!_reserved.is_empty(), "empty generation?"); _span_based_discoverer.set_span(_reserved); _ref_processor = new ReferenceProcessor(&_span_based_discoverer); // a vanilla reference processor - if (_ref_processor == NULL) { - vm_exit_during_initialization("Could not allocate ReferenceProcessor object"); - } } void Generation::print() const { print_on(tty); } diff --git a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp index 35fc39e287a..af3c8832f9b 100644 --- a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp +++ b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp @@ -36,6 +36,7 @@ #include "runtime/thread.inline.hpp" #include "utilities/align.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #if INCLUDE_G1GC #include "gc/g1/jvmFlagConstraintsG1.hpp" #endif diff --git a/src/hotspot/share/gc/shared/oopStorage.cpp b/src/hotspot/share/gc/shared/oopStorage.cpp index 71aff618080..416afce7034 100644 --- a/src/hotspot/share/gc/shared/oopStorage.cpp +++ b/src/hotspot/share/gc/shared/oopStorage.cpp @@ -45,6 +45,7 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" #include "utilities/ostream.hpp" +#include "utilities/powerOfTwo.hpp" OopStorage::AllocationListEntry::AllocationListEntry() : _prev(NULL), _next(NULL) {} diff --git a/src/hotspot/share/gc/shared/referenceProcessor.cpp b/src/hotspot/share/gc/shared/referenceProcessor.cpp index 07c25b30f6b..4dde12e4f8d 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.cpp @@ -64,9 +64,6 @@ void ReferenceProcessor::init_statics() { } else { _default_soft_ref_policy = new LRUCurrentHeapPolicy(); } - if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) { - vm_exit_during_initialization("Could not allocate reference policy object"); - } guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery || RefDiscoveryPolicy == ReferentBasedDiscovery, "Unrecognized RefDiscoveryPolicy"); diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp index ee7e8efc9a4..27fe53f6868 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp @@ -38,6 +38,7 @@ #include "runtime/atomic.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/safepointVerifiers.hpp" +#include "utilities/powerOfTwo.hpp" // // List of deduplication table entries. Links table diff --git a/src/hotspot/share/gc/shared/taskqueue.hpp b/src/hotspot/share/gc/shared/taskqueue.hpp index d03860c6a7a..ed8727b839f 100644 --- a/src/hotspot/share/gc/shared/taskqueue.hpp +++ b/src/hotspot/share/gc/shared/taskqueue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -443,9 +443,6 @@ public: virtual bool should_exit_termination() = 0; }; -typedef GenericTaskQueue OopTaskQueue; -typedef GenericTaskQueueSet OopTaskQueueSet; - #ifdef _MSC_VER #pragma warning(push) // warning C4522: multiple assignment operators specified @@ -524,10 +521,4 @@ private: #pragma warning(pop) #endif -typedef OverflowTaskQueue OopStarTaskQueue; -typedef GenericTaskQueueSet OopStarTaskQueueSet; - -typedef OverflowTaskQueue RegionTaskQueue; -typedef GenericTaskQueueSet RegionTaskQueueSet; - #endif // SHARE_GC_SHARED_TASKQUEUE_HPP diff --git a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp index 2c1ed47808f..8aa9f8ad0ba 100644 --- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp +++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved. + * Copyright (c) 2018, 2020, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,25 +107,25 @@ void ShenandoahBarrierSetC1::pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, __ branch_destination(slow->continuation()); } -LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr) { +LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr, bool is_native) { if (ShenandoahLoadRefBarrier) { - return load_reference_barrier_impl(gen, obj, addr); + return load_reference_barrier_impl(gen, obj, addr, is_native); } else { return obj; } } -LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr) { +LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr, bool is_native) { assert(ShenandoahLoadRefBarrier, "Should be enabled"); - obj = ensure_in_register(gen, obj); + obj = ensure_in_register(gen, obj, T_OBJECT); assert(obj->is_register(), "must be a register at this point"); - addr = ensure_in_register(gen, addr); + addr = ensure_in_register(gen, addr, T_ADDRESS); assert(addr->is_register(), "must be a register at this point"); LIR_Opr result = gen->result_register_for(obj->value_type()); __ move(obj, result); - LIR_Opr tmp1 = gen->new_register(T_OBJECT); - LIR_Opr tmp2 = gen->new_register(T_OBJECT); + LIR_Opr tmp1 = gen->new_register(T_ADDRESS); + LIR_Opr tmp2 = gen->new_register(T_ADDRESS); LIR_Opr thrd = gen->getThreadPointer(); LIR_Address* active_flag_addr = @@ -150,27 +150,21 @@ LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier_impl(LIRGenerator* gen, L } __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0)); - CodeStub* slow = new ShenandoahLoadReferenceBarrierStub(obj, addr, result, tmp1, tmp2); + CodeStub* slow = new ShenandoahLoadReferenceBarrierStub(obj, addr, result, tmp1, tmp2, is_native); __ branch(lir_cond_notEqual, T_INT, slow); __ branch_destination(slow->continuation()); return result; } -LIR_Opr ShenandoahBarrierSetC1::ensure_in_register(LIRGenerator* gen, LIR_Opr obj) { +LIR_Opr ShenandoahBarrierSetC1::ensure_in_register(LIRGenerator* gen, LIR_Opr obj, BasicType type) { if (!obj->is_register()) { LIR_Opr obj_reg; if (obj->is_constant()) { - obj_reg = gen->new_register(T_OBJECT); + obj_reg = gen->new_register(type); __ move(obj, obj_reg); } else { -#ifdef AARCH64 - // AArch64 expects double-size register. obj_reg = gen->new_pointer_register(); -#else - // x86 expects single-size register. - obj_reg = gen->new_register(T_OBJECT); -#endif __ leal(obj, obj_reg); } obj = obj_reg; @@ -180,7 +174,7 @@ LIR_Opr ShenandoahBarrierSetC1::ensure_in_register(LIRGenerator* gen, LIR_Opr ob LIR_Opr ShenandoahBarrierSetC1::storeval_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, DecoratorSet decorators) { if (ShenandoahStoreValEnqueueBarrier) { - obj = ensure_in_register(gen, obj); + obj = ensure_in_register(gen, obj, T_OBJECT); pre_barrier(gen, info, decorators, LIR_OprFact::illegalOpr, obj); } return obj; @@ -217,26 +211,11 @@ void ShenandoahBarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) // 2: load a reference from src location and apply LRB if ShenandoahLoadRefBarrier is set if (ShenandoahBarrierSet::need_load_reference_barrier(decorators, type)) { - if (ShenandoahBarrierSet::use_load_reference_barrier_native(decorators, type)) { - BarrierSetC1::load_at_resolved(access, result); - LIR_OprList* args = new LIR_OprList(); - LIR_Opr addr = access.resolved_addr(); - addr = ensure_in_register(gen, addr); - args->append(result); - args->append(addr); - BasicTypeList signature; - signature.append(T_OBJECT); - signature.append(T_ADDRESS); - LIR_Opr call_result = gen->call_runtime(&signature, args, - CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native), - objectType, NULL); - __ move(call_result, result); - } else { - LIR_Opr tmp = gen->new_register(T_OBJECT); - BarrierSetC1::load_at_resolved(access, tmp); - tmp = load_reference_barrier(gen, tmp, access.resolved_addr()); - __ move(tmp, result); - } + LIR_Opr tmp = gen->new_register(T_OBJECT); + BarrierSetC1::load_at_resolved(access, tmp); + bool is_native = ShenandoahBarrierSet::use_load_reference_barrier_native(decorators, type); + tmp = load_reference_barrier(gen, tmp, access.resolved_addr(), is_native); + __ move(tmp, result); } else { BarrierSetC1::load_at_resolved(access, result); } @@ -274,9 +253,15 @@ class C1ShenandoahPreBarrierCodeGenClosure : public StubAssemblerCodeGenClosure }; class C1ShenandoahLoadReferenceBarrierCodeGenClosure : public StubAssemblerCodeGenClosure { +private: + const bool _is_native; + +public: + C1ShenandoahLoadReferenceBarrierCodeGenClosure(bool is_native) : _is_native(is_native) {} + virtual OopMapSet* generate_code(StubAssembler* sasm) { ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler(); - bs->generate_c1_load_reference_barrier_runtime_stub(sasm); + bs->generate_c1_load_reference_barrier_runtime_stub(sasm, _is_native); return NULL; } }; @@ -287,16 +272,14 @@ void ShenandoahBarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) "shenandoah_pre_barrier_slow", false, &pre_code_gen_cl); if (ShenandoahLoadRefBarrier) { - C1ShenandoahLoadReferenceBarrierCodeGenClosure lrb_code_gen_cl; + C1ShenandoahLoadReferenceBarrierCodeGenClosure lrb_code_gen_cl(false); _load_reference_barrier_rt_code_blob = Runtime1::generate_blob(buffer_blob, -1, "shenandoah_load_reference_barrier_slow", false, &lrb_code_gen_cl); - } -} -const char* ShenandoahBarrierSetC1::rtcall_name_for_address(address entry) { - if (entry == CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native)) { - return "ShenandoahRuntime::load_reference_barrier_native"; + C1ShenandoahLoadReferenceBarrierCodeGenClosure lrb_native_code_gen_cl(true); + _load_reference_barrier_native_rt_code_blob = Runtime1::generate_blob(buffer_blob, -1, + "shenandoah_load_reference_barrier_native_slow", + false, &lrb_native_code_gen_cl); } - return NULL; } diff --git a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.hpp b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.hpp index 5757060b46f..e97f3af0926 100644 --- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.hpp +++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved. + * Copyright (c) 2018, 2020, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -94,10 +94,10 @@ private: LIR_Opr _result; LIR_Opr _tmp1; LIR_Opr _tmp2; - + bool _is_native; public: - ShenandoahLoadReferenceBarrierStub(LIR_Opr obj, LIR_Opr addr, LIR_Opr result, LIR_Opr tmp1, LIR_Opr tmp2) : - _obj(obj), _addr(addr), _result(result), _tmp1(tmp1), _tmp2(tmp2) + ShenandoahLoadReferenceBarrierStub(LIR_Opr obj, LIR_Opr addr, LIR_Opr result, LIR_Opr tmp1, LIR_Opr tmp2, bool is_native) : + _obj(obj), _addr(addr), _result(result), _tmp1(tmp1), _tmp2(tmp2), _is_native(is_native) { assert(_obj->is_register(), "should be register"); assert(_addr->is_register(), "should be register"); @@ -111,6 +111,7 @@ public: LIR_Opr result() const { return _result; } LIR_Opr tmp1() const { return _tmp1; } LIR_Opr tmp2() const { return _tmp2; } + bool is_native() const { return _is_native; } virtual void emit_code(LIR_Assembler* e); virtual void visit(LIR_OpVisitState* visitor) { @@ -190,15 +191,16 @@ class ShenandoahBarrierSetC1 : public BarrierSetC1 { private: CodeBlob* _pre_barrier_c1_runtime_code_blob; CodeBlob* _load_reference_barrier_rt_code_blob; + CodeBlob* _load_reference_barrier_native_rt_code_blob; void pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, DecoratorSet decorators, LIR_Opr addr_opr, LIR_Opr pre_val); - LIR_Opr load_reference_barrier(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr); + LIR_Opr load_reference_barrier(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr, bool is_native); LIR_Opr storeval_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, DecoratorSet decorators); - LIR_Opr load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr); + LIR_Opr load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr, bool is_native); - LIR_Opr ensure_in_register(LIRGenerator* gen, LIR_Opr obj); + LIR_Opr ensure_in_register(LIRGenerator* gen, LIR_Opr obj, BasicType type); public: ShenandoahBarrierSetC1(); @@ -213,6 +215,10 @@ public: return _load_reference_barrier_rt_code_blob; } + CodeBlob* load_reference_barrier_native_rt_code_blob() { + assert(_load_reference_barrier_native_rt_code_blob != NULL, ""); + return _load_reference_barrier_native_rt_code_blob; + } protected: virtual void store_at_resolved(LIRAccess& access, LIR_Opr value); @@ -226,7 +232,6 @@ protected: public: virtual void generate_c1_runtime_stubs(BufferBlob* buffer_blob); - virtual const char* rtcall_name_for_address(address entry); }; #endif // SHARE_GC_SHENANDOAH_C1_SHENANDOAHBARRIERSETC1_HPP diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index e4e2e95772c..93392598f67 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -151,31 +151,6 @@ bool ShenandoahBarrierC2Support::has_safepoint_between(Node* start, Node* stop, return false; } -bool ShenandoahBarrierC2Support::try_common_gc_state_load(Node *n, PhaseIdealLoop *phase) { - assert(is_gc_state_load(n), "inconsistent"); - Node* addp = n->in(MemNode::Address); - Node* dominator = NULL; - for (DUIterator_Fast imax, i = addp->fast_outs(imax); i < imax; i++) { - Node* u = addp->fast_out(i); - assert(is_gc_state_load(u), "inconsistent"); - if (u != n && phase->is_dominator(u->in(0), n->in(0))) { - if (dominator == NULL) { - dominator = u; - } else { - if (phase->dom_depth(u->in(0)) < phase->dom_depth(dominator->in(0))) { - dominator = u; - } - } - } - } - if (dominator == NULL || has_safepoint_between(n->in(0), dominator->in(0), phase)) { - return false; - } - phase->igvn().replace_node(n, dominator); - - return true; -} - #ifdef ASSERT bool ShenandoahBarrierC2Support::verify_helper(Node* in, Node_Stack& phis, VectorSet& visited, verify_type t, bool trace, Unique_Node_List& barriers_used) { assert(phis.size() == 0, ""); @@ -1966,7 +1941,6 @@ IfNode* ShenandoahBarrierC2Support::find_unswitching_candidate(const IdealLoopTr void ShenandoahBarrierC2Support::optimize_after_expansion(VectorSet &visited, Node_Stack &stack, Node_List &old_new, PhaseIdealLoop* phase) { Node_List heap_stable_tests; - Node_List gc_state_loads; stack.push(phase->C->start(), 0); do { Node* n = stack.node(); @@ -1980,26 +1954,12 @@ void ShenandoahBarrierC2Support::optimize_after_expansion(VectorSet &visited, No } } else { stack.pop(); - if (ShenandoahCommonGCStateLoads && is_gc_state_load(n)) { - gc_state_loads.push(n); - } if (n->is_If() && is_heap_stable_test(n)) { heap_stable_tests.push(n); } } } while (stack.size() > 0); - bool progress; - do { - progress = false; - for (uint i = 0; i < gc_state_loads.size(); i++) { - Node* n = gc_state_loads.at(i); - if (n->outcnt() != 0) { - progress |= try_common_gc_state_load(n, phase); - } - } - } while (progress); - for (uint i = 0; i < heap_stable_tests.size(); i++) { Node* n = heap_stable_tests.at(i); assert(is_heap_stable_test(n), "only evacuation test"); diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp index c50237db478..3176e297731 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp @@ -54,7 +54,6 @@ private: static Node* dom_mem(Node* mem, Node* ctrl, int alias, Node*& mem_ctrl, PhaseIdealLoop* phase); static Node* no_branches(Node* c, Node* dom, bool allow_one_proj, PhaseIdealLoop* phase); static bool is_heap_state_test(Node* iff, int mask); - static bool try_common_gc_state_load(Node *n, PhaseIdealLoop *phase); static bool has_safepoint_between(Node* start, Node* stop, PhaseIdealLoop *phase); static Node* find_bottom_mem(Node* ctrl, PhaseIdealLoop* phase); static void follow_barrier_uses(Node* n, Node* ctrl, Unique_Node_List& uses, PhaseIdealLoop* phase); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp index 905c527ac36..7795df819f1 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp @@ -192,15 +192,6 @@ void ShenandoahArguments::initialize() { FLAG_SET_DEFAULT(TLABAllocationWeight, 90); } - // Shenandoah needs more C2 nodes to compile some methods with lots of barriers. - // NodeLimitFudgeFactor needs to stay the same relative to MaxNodeLimit. -#ifdef COMPILER2 - if (FLAG_IS_DEFAULT(MaxNodeLimit)) { - FLAG_SET_DEFAULT(MaxNodeLimit, MaxNodeLimit * 3); - FLAG_SET_DEFAULT(NodeLimitFudgeFactor, NodeLimitFudgeFactor * 3); - } -#endif - // Make sure safepoint deadlocks are failing predictably. This sets up VM to report // fatal error after 10 seconds of wait for safepoint syncronization (not the VM // operation itself). There is no good reason why Shenandoah would spend that diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp index 9620c89cd2a..0c2dc4300f8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp @@ -140,47 +140,12 @@ oop ShenandoahBarrierSet::load_reference_barrier_mutator_work(oop obj, T* load_a assert(ShenandoahLoadRefBarrier, "should be enabled"); shenandoah_assert_in_cset(load_addr, obj); - oop fwd = resolve_forwarded_not_null(obj); + oop fwd = resolve_forwarded_not_null_mutator(obj); if (obj == fwd) { assert(_heap->is_gc_in_progress_mask(ShenandoahHeap::EVACUATION | ShenandoahHeap::TRAVERSAL), "evac should be in progress"); - - ShenandoahEvacOOMScope oom_evac_scope; - - Thread* thread = Thread::current(); - oop res_oop = _heap->evacuate_object(obj, thread); - - // Since we are already here and paid the price of getting through runtime call adapters - // and acquiring oom-scope, it makes sense to try and evacuate more adjacent objects, - // thus amortizing the overhead. For sparsely live heaps, scan costs easily dominate - // total assist costs, and can introduce a lot of evacuation latency. This is why we - // only scan for _nearest_ N objects, regardless if they are eligible for evac or not. - // The scan itself should also avoid touching the non-marked objects below TAMS, because - // their metadata (notably, klasses) may be incorrect already. - - size_t max = ShenandoahEvacAssist; - if (max > 0) { - // Traversal is special: it uses incomplete marking context, because it coalesces evac with mark. - // Other code uses complete marking context, because evac happens after the mark. - ShenandoahMarkingContext* ctx = _heap->is_concurrent_traversal_in_progress() ? - _heap->marking_context() : _heap->complete_marking_context(); - - ShenandoahHeapRegion* r = _heap->heap_region_containing(obj); - assert(r->is_cset(), "sanity"); - - HeapWord* cur = cast_from_oop(obj) + obj->size(); - - size_t count = 0; - while ((cur < r->top()) && ctx->is_marked(oop(cur)) && (count++ < max)) { - oop cur_oop = oop(cur); - if (cur_oop == resolve_forwarded_not_null(cur_oop)) { - _heap->evacuate_object(cur_oop, thread); - } - cur = cur + cur_oop->size(); - } - } - - fwd = res_oop; + ShenandoahEvacOOMScope scope; + fwd = _heap->evacuate_object(obj, Thread::current()); } if (load_addr != NULL && fwd != obj) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp index d4f1b9dea30..f9886473a53 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp @@ -84,6 +84,7 @@ public: virtual void on_thread_detach(Thread* thread); static inline oop resolve_forwarded_not_null(oop p); + static inline oop resolve_forwarded_not_null_mutator(oop p); static inline oop resolve_forwarded(oop p); template diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp index c4b5a2b097c..38e472ff359 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp @@ -49,6 +49,10 @@ inline oop ShenandoahBarrierSet::resolve_forwarded(oop p) { } } +inline oop ShenandoahBarrierSet::resolve_forwarded_not_null_mutator(oop p) { + return ShenandoahForwarding::get_forwardee_mutator(p); +} + inline void ShenandoahBarrierSet::enqueue(oop obj) { shenandoah_assert_not_forwarded_if(NULL, obj, _heap->is_concurrent_traversal_in_progress()); assert(_satb_mark_queue_set.is_active(), "only get here when SATB active"); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp index 84e57c167b2..d5a06d1d0bc 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp @@ -34,6 +34,7 @@ #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "runtime/atomic.hpp" +#include "utilities/powerOfTwo.hpp" ShenandoahParallelCodeCacheIterator::ShenandoahParallelCodeCacheIterator(const GrowableArray* heaps) { _length = heaps->length(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp index d89ea948920..990d838bd95 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp @@ -404,7 +404,6 @@ void ShenandoahConcurrentMark::mark_from_roots() { task_queues()->reserve(nworkers); { - ShenandoahTerminationTracker term(ShenandoahPhaseTimings::conc_termination); TaskTerminator terminator(nworkers, task_queues()); ShenandoahConcurrentMarkingTask task(this, &terminator); workers->run_task(&task); @@ -435,10 +434,6 @@ void ShenandoahConcurrentMark::finish_mark_from_roots(bool full_gc) { ShenandoahIsAliveSelector is_alive; ReferenceProcessorIsAliveMutator fix_isalive(_heap->ref_processor(), is_alive.is_alive_closure()); - ShenandoahTerminationTracker termination_tracker(full_gc ? - ShenandoahPhaseTimings::full_gc_mark_termination : - ShenandoahPhaseTimings::termination); - StrongRootsScope scope(nworkers); TaskTerminator terminator(nworkers, task_queues()); ShenandoahFinalMarkingTask task(this, &terminator, ShenandoahStringDedup::is_enabled()); @@ -636,11 +631,6 @@ void ShenandoahConcurrentMark::weak_refs_work_doit(bool full_gc) { ShenandoahPhaseTimings::full_gc_weakrefs_process : ShenandoahPhaseTimings::weakrefs_process; - ShenandoahPhaseTimings::Phase phase_process_termination = - full_gc ? - ShenandoahPhaseTimings::full_gc_weakrefs_termination : - ShenandoahPhaseTimings::weakrefs_termination; - shenandoah_assert_rp_isalive_not_installed(); ShenandoahIsAliveSelector is_alive; ReferenceProcessorIsAliveMutator fix_isalive(rp, is_alive.is_alive_closure()); @@ -667,7 +657,6 @@ void ShenandoahConcurrentMark::weak_refs_work_doit(bool full_gc) { { ShenandoahGCPhase phase(phase_process); - ShenandoahTerminationTracker phase_term(phase_process_termination); if (_heap->has_forwarded_objects()) { ShenandoahCMKeepAliveUpdateClosure keep_alive(get_queue(serial_worker_id)); @@ -942,7 +931,6 @@ void ShenandoahConcurrentMark::mark_loop_work(T* cl, jushort* live_data, uint wo // No work encountered in current stride, try to terminate. // Need to leave the STS here otherwise it might block safepoints. ShenandoahSuspendibleThreadSetLeaver stsl(CANCELLABLE && ShenandoahSuspendibleWorkers); - ShenandoahTerminationTimingsTracker term_tracker(worker_id); ShenandoahTerminatorTerminator tt(heap); if (terminator->offer_termination(&tt)) return; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahForwarding.hpp b/src/hotspot/share/gc/shenandoah/shenandoahForwarding.hpp index f341b2f600f..80a51c63e69 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahForwarding.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahForwarding.hpp @@ -34,6 +34,10 @@ public: */ static inline oop get_forwardee(oop obj); + /* Gets forwardee from the given object. Only from mutator thread. + */ + static inline oop get_forwardee_mutator(oop obj); + /* Returns the raw value from forwardee slot. */ static inline HeapWord* get_forwardee_raw(oop obj); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahForwarding.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahForwarding.inline.hpp index e4cf3b46e87..85daeeb8df1 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahForwarding.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahForwarding.inline.hpp @@ -28,6 +28,7 @@ #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahForwarding.hpp" #include "oops/markWord.inline.hpp" +#include "runtime/thread.hpp" inline HeapWord* ShenandoahForwarding::get_forwardee_raw(oop obj) { shenandoah_assert_in_heap(NULL, obj); @@ -35,11 +36,32 @@ inline HeapWord* ShenandoahForwarding::get_forwardee_raw(oop obj) { } inline HeapWord* ShenandoahForwarding::get_forwardee_raw_unchecked(oop obj) { + // JVMTI and JFR code use mark words for marking objects for their needs. + // On this path, we can encounter the "marked" object, but with NULL + // fwdptr. That object is still not forwarded, and we need to return + // the object itself. markWord mark = obj->mark_raw(); if (mark.is_marked()) { - return (HeapWord*) mark.clear_lock_bits().to_pointer(); + HeapWord* fwdptr = (HeapWord*) mark.clear_lock_bits().to_pointer(); + if (fwdptr != NULL) { + return fwdptr; + } + } + return cast_from_oop(obj); +} + +inline oop ShenandoahForwarding::get_forwardee_mutator(oop obj) { + // Same as above, but mutator thread cannot ever see NULL forwardee. + shenandoah_assert_correct(NULL, obj); + assert(Thread::current()->is_Java_thread(), "Must be a mutator thread"); + + markWord mark = obj->mark_raw(); + if (mark.is_marked()) { + HeapWord* fwdptr = (HeapWord*) mark.clear_lock_bits().to_pointer(); + assert(fwdptr != NULL, "Forwarding pointer is never null here"); + return cast_to_oop(fwdptr); } else { - return cast_from_oop(obj); + return obj; } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index efe06b2f594..0c9ee624c2e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -80,6 +80,7 @@ #include "runtime/safepointMechanism.hpp" #include "runtime/vmThread.hpp" #include "services/mallocTracker.hpp" +#include "utilities/powerOfTwo.hpp" #ifdef ASSERT template @@ -360,10 +361,6 @@ jint ShenandoahHeap::initialize() { ShenandoahStringDedup::initialize(); ShenandoahCodeRoots::initialize(); - if (ShenandoahAllocationTrace) { - _alloc_tracker = new ShenandoahAllocTracker(); - } - if (ShenandoahPacing) { _pacer = new ShenandoahPacer(this); _pacer->setup_for_idle(); @@ -448,7 +445,6 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) : _full_gc(new ShenandoahMarkCompact()), _pacer(NULL), _verifier(NULL), - _alloc_tracker(NULL), _phase_timings(NULL), _monitoring_support(NULL), _memory_pool(NULL), @@ -796,8 +792,6 @@ ShenandoahHeap* ShenandoahHeap::heap_no_check() { } HeapWord* ShenandoahHeap::allocate_memory(ShenandoahAllocRequest& req) { - ShenandoahAllocTrace trace_alloc(req.size(), req.type()); - intptr_t pacer_epoch = 0; bool in_new_region = false; HeapWord* result = NULL; @@ -1201,13 +1195,6 @@ void ShenandoahHeap::print_tracing_info() const { ls.cr(); ls.cr(); - - if (ShenandoahAllocationTrace) { - assert(alloc_tracker() != NULL, "Must be"); - alloc_tracker()->print_on(&ls); - } else { - ls.print_cr(" Allocation tracing is disabled, use -XX:+ShenandoahAllocationTrace to enable."); - } } } @@ -1229,28 +1216,20 @@ class ObjectIterateScanRootClosure : public BasicOopIterateClosure { private: MarkBitMap* _bitmap; Stack* _oop_stack; + ShenandoahHeap* const _heap; + ShenandoahMarkingContext* const _marking_context; template void do_oop_work(T* p) { T o = RawAccess<>::oop_load(p); if (!CompressedOops::is_null(o)) { oop obj = CompressedOops::decode_not_null(o); - oop fwd = (oop) ShenandoahForwarding::get_forwardee_raw_unchecked(obj); - if (fwd == NULL) { - // There is an odd interaction with VM_HeapWalkOperation, see jvmtiTagMap.cpp. - // - // That operation walks the reachable objects on its own, storing the marking - // wavefront in the object marks. When it is done, it calls the CollectedHeap - // to iterate over all objects to clean up the mess. When it reaches here, - // the Shenandoah fwdptr resolution code encounters the marked objects with - // NULL forwardee. Trying to act on that would crash the VM. Or fail the - // asserts, should we go for resolve_forwarded_pointer(obj). - // - // Therefore, we have to dodge it by doing the raw access to forwardee, and - // assuming the object had no forwardee, if that thing is NULL. - } else { - obj = fwd; + if (_heap->is_concurrent_root_in_progress() && !_marking_context->is_marked(obj)) { + // There may be dead oops in weak roots in concurrent root phase, do not touch them. + return; } + obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); + assert(oopDesc::is_oop(obj), "must be a valid oop"); if (!_bitmap->is_marked(obj)) { _bitmap->mark(obj); @@ -1260,7 +1239,8 @@ private: } public: ObjectIterateScanRootClosure(MarkBitMap* bitmap, Stack* oop_stack) : - _bitmap(bitmap), _oop_stack(oop_stack) {} + _bitmap(bitmap), _oop_stack(oop_stack), _heap(ShenandoahHeap::heap()), + _marking_context(_heap->marking_context()) {} void do_oop(oop* p) { do_oop_work(p); } void do_oop(narrowOop* p) { do_oop_work(p); } }; @@ -1306,13 +1286,7 @@ void ShenandoahHeap::object_iterate(ObjectClosure* cl) { ShenandoahHeapIterationRootScanner rp; ObjectIterateScanRootClosure oops(&_aux_bit_map, &oop_stack); - // When concurrent root is in progress, weak roots may contain dead oops, they should not be used - // for root scanning. - if (is_concurrent_root_in_progress()) { - rp.strong_roots_do(&oops); - } else { - rp.roots_do(&oops); - } + rp.roots_do(&oops); // Work through the oop stack to traverse heap. while (! oop_stack.is_empty()) { @@ -1813,10 +1787,16 @@ void ShenandoahHeap::op_roots() { } void ShenandoahHeap::op_reset() { + if (ShenandoahPacing) { + pacer()->setup_for_reset(); + } reset_mark_bitmap(); } void ShenandoahHeap::op_preclean() { + if (ShenandoahPacing) { + pacer()->setup_for_preclean(); + } concurrent_mark()->preclean_weak_refs(); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index 1d70415ba06..a9be979f5fc 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -458,7 +458,6 @@ private: ShenandoahPacer* _pacer; ShenandoahVerifier* _verifier; - ShenandoahAllocTracker* _alloc_tracker; ShenandoahPhaseTimings* _phase_timings; ShenandoahControlThread* control_thread() { return _control_thread; } @@ -474,7 +473,6 @@ public: ShenandoahPacer* pacer() const { return _pacer; } ShenandoahPhaseTimings* phase_timings() const { return _phase_timings; } - ShenandoahAllocTracker* alloc_tracker() const { return _alloc_tracker; } ShenandoahVerifier* verifier(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp index eeb23e7b063..c692019f000 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp @@ -248,6 +248,7 @@ inline oop ShenandoahHeap::evacuate_object(oop p, Thread* thread) { } assert(ShenandoahThreadLocalData::is_evac_allowed(thread), "must be enclosed in oom-evac scope"); + assert(is_concurrent_traversal_in_progress() || !is_traversal_mode(), "Should not evacuate objects"); size_t size = p->size(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeuristics.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeuristics.cpp index 9bc148106ee..9bab0b561c0 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeuristics.cpp @@ -261,25 +261,45 @@ bool ShenandoahHeuristics::should_degenerate_cycle() { return _degenerated_cycles_in_a_row <= ShenandoahFullGCThreshold; } +void ShenandoahHeuristics::adjust_penalty(intx step) { + assert(0 <= _gc_time_penalties && _gc_time_penalties <= 100, + "In range before adjustment: " INTX_FORMAT, _gc_time_penalties); + + intx new_val = _gc_time_penalties + step; + if (new_val < 0) { + new_val = 0; + } + if (new_val > 100) { + new_val = 100; + } + _gc_time_penalties = new_val; + + assert(0 <= _gc_time_penalties && _gc_time_penalties <= 100, + "In range after adjustment: " INTX_FORMAT, _gc_time_penalties); +} + void ShenandoahHeuristics::record_success_concurrent() { _degenerated_cycles_in_a_row = 0; _successful_cycles_in_a_row++; _gc_time_history->add(time_since_last_gc()); _gc_times_learned++; - _gc_time_penalties -= MIN2(_gc_time_penalties, Concurrent_Adjust); + + adjust_penalty(Concurrent_Adjust); } void ShenandoahHeuristics::record_success_degenerated() { _degenerated_cycles_in_a_row++; _successful_cycles_in_a_row = 0; - _gc_time_penalties += Degenerated_Penalty; + + adjust_penalty(Degenerated_Penalty); } void ShenandoahHeuristics::record_success_full() { _degenerated_cycles_in_a_row = 0; _successful_cycles_in_a_row++; - _gc_time_penalties += Full_Penalty; + + adjust_penalty(Full_Penalty); } void ShenandoahHeuristics::record_allocation_failure_gc() { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeuristics.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeuristics.hpp index d04deac31a2..b653eabe633 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeuristics.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeuristics.hpp @@ -67,7 +67,7 @@ class ShenandoahCollectionSet; class ShenandoahHeapRegion; class ShenandoahHeuristics : public CHeapObj { - static const intx Concurrent_Adjust = 1; // recover from penalties + static const intx Concurrent_Adjust = -1; // recover from penalties static const intx Degenerated_Penalty = 10; // how much to penalize average GC duration history on Degenerated GC static const intx Full_Penalty = 20; // how much to penalize average GC duration history on Full GC @@ -93,7 +93,7 @@ protected: double _last_cycle_end; size_t _gc_times_learned; - size_t _gc_time_penalties; + intx _gc_time_penalties; TruncatedSeq* _gc_time_history; // There may be many threads that contend to set this flag @@ -110,6 +110,8 @@ protected: RegionData* data, size_t data_size, size_t free) = 0; + void adjust_penalty(intx step); + public: ShenandoahHeuristics(); virtual ~ShenandoahHeuristics(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahNMethod.cpp b/src/hotspot/share/gc/shenandoah/shenandoahNMethod.cpp index 11a5f6c525d..8439d5a5dce 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahNMethod.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahNMethod.cpp @@ -237,15 +237,37 @@ void ShenandoahNMethod::assert_same_oops(bool allow_dead) { GrowableArray* oops = detector.oops(); - assert(oops->length() == oop_count(), "Must match"); - + int count = _oops_count; for (int index = 0; index < _oops_count; index ++) { assert(oops->contains(_oops[index]), "Must contain this oop"); } for (oop* p = nm()->oops_begin(); p < nm()->oops_end(); p ++) { + if (*p == Universe::non_oop_word()) continue; + count++; assert(oops->contains(p), "Must contain this oop"); } + + if (oops->length() < count) { + stringStream debug_stream; + debug_stream.print_cr("detected locs: %d", oops->length()); + for (int i = 0; i < oops->length(); i++) { + debug_stream.print_cr("-> " PTR_FORMAT, p2i(oops->at(i))); + } + debug_stream.print_cr("recorded oops: %d", _oops_count); + for (int i = 0; i < _oops_count; i++) { + debug_stream.print_cr("-> " PTR_FORMAT, p2i(_oops[i])); + } + GrowableArray check; + bool non_immed; + detect_reloc_oops(nm(), check, non_immed); + debug_stream.print_cr("check oops: %d", check.length()); + for (int i = 0; i < check.length(); i++) { + debug_stream.print_cr("-> " PTR_FORMAT, p2i(check.at(i))); + } + fatal("Must match #detected: %d, #recorded: %d, #total: %d, begin: " PTR_FORMAT ", end: " PTR_FORMAT "\n%s", + oops->length(), _oops_count, count, p2i(nm()->oops_begin()), p2i(nm()->oops_end()), debug_stream.as_string()); + } } void ShenandoahNMethod::assert_no_oops(nmethod* nm, bool allow_dead) { @@ -277,6 +299,7 @@ void ShenandoahNMethodTable::register_nmethod(nmethod* nm) { if (data != NULL) { assert(contain(nm), "Must have been registered"); + assert(nm == data->nm(), "Must be same nmethod"); data->update(); } else { data = ShenandoahNMethod::for_nmethod(nm); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp b/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp index 808304269db..18af0a9e8ee 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp @@ -177,6 +177,31 @@ void ShenandoahPacer::setup_for_idle() { tax); } +/* + * There is no useful notion of progress for these operations. To avoid stalling + * the allocators unnecessarily, allow them to run unimpeded. + */ + +void ShenandoahPacer::setup_for_preclean() { + assert(ShenandoahPacing, "Only be here when pacing is enabled"); + + size_t initial = _heap->max_capacity(); + restart_with(initial, 1.0); + + log_info(gc, ergo)("Pacer for Precleaning. Non-Taxable: " SIZE_FORMAT "%s", + byte_size_in_proper_unit(initial), proper_unit_for_byte_size(initial)); +} + +void ShenandoahPacer::setup_for_reset() { + assert(ShenandoahPacing, "Only be here when pacing is enabled"); + + size_t initial = _heap->max_capacity(); + restart_with(initial, 1.0); + + log_info(gc, ergo)("Pacer for Reset. Non-Taxable: " SIZE_FORMAT "%s", + byte_size_in_proper_unit(initial), proper_unit_for_byte_size(initial)); +} + size_t ShenandoahPacer::update_and_get_progress_history() { if (_progress == -1) { // First initialization, report some prior diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPacer.hpp b/src/hotspot/share/gc/shenandoah/shenandoahPacer.hpp index 9413c184f4a..6a18ea5330e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPacer.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPacer.hpp @@ -74,6 +74,9 @@ public: void setup_for_updaterefs(); void setup_for_traversal(); + void setup_for_reset(); + void setup_for_preclean(); + inline void report_mark(size_t words); inline void report_evac(size_t words); inline void report_updaterefs(size_t words); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp index ac25eada40b..5c3882cbc46 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp @@ -44,7 +44,6 @@ const char* ShenandoahPhaseTimings::_phase_names[] = { ShenandoahPhaseTimings::ShenandoahPhaseTimings() : _policy(NULL) { uint max_workers = MAX2(ConcGCThreads, ParallelGCThreads); _worker_times = new ShenandoahWorkerTimings(max_workers); - _termination_times = new ShenandoahTerminationTimings(max_workers); _policy = ShenandoahHeap::heap()->shenandoah_policy(); assert(_policy != NULL, "Can not be NULL"); } @@ -165,30 +164,3 @@ void ShenandoahWorkerTimings::print() const { _gc_par_phases[i]->print_summary_on(tty); } } - - -ShenandoahTerminationTimings::ShenandoahTerminationTimings(uint max_gc_threads) { - _gc_termination_phase = new WorkerDataArray("Task Termination (ms):", max_gc_threads); -} - -void ShenandoahTerminationTimings::record_time_secs(uint worker_id, double secs) { - if (_gc_termination_phase->get(worker_id) == WorkerDataArray::uninitialized()) { - _gc_termination_phase->set(worker_id, secs); - } else { - // worker may re-enter termination phase - _gc_termination_phase->add(worker_id, secs); - } -} - -void ShenandoahTerminationTimings::print() const { - _gc_termination_phase->print_summary_on(tty); -} - -double ShenandoahTerminationTimings::average() const { - return _gc_termination_phase->average(); -} - -void ShenandoahTerminationTimings::reset() { - _gc_termination_phase->reset(); -} - diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp index 24193b75750..0caa1159be6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp @@ -31,7 +31,6 @@ class ShenandoahCollectorPolicy; class ShenandoahWorkerTimings; -class ShenandoahTerminationTimings; class outputStream; #define SHENANDOAH_GC_PHASE_DO(f) \ @@ -92,10 +91,8 @@ class outputStream; f(update_finish_queues, " U: Finish Queues") \ \ f(finish_queues, " Finish Queues") \ - f(termination, " Termination") \ f(weakrefs, " Weak References") \ f(weakrefs_process, " Process") \ - f(weakrefs_termination, " Termination") \ f(purge, " System Purge") \ f(purge_class_unload, " Unload Classes") \ f(purge_par, " Parallel Cleanup") \ @@ -244,7 +241,6 @@ class outputStream; f(final_traversal_gc_string_dedup_table_roots, " TF: Dedup Table Roots") \ f(final_traversal_gc_string_dedup_queue_roots, " TF: Dedup Queue Roots") \ f(final_traversal_gc_finish_queues, " TF: Finish Queues") \ - f(final_traversal_gc_termination, " TF: Termination") \ \ /* Per-thread timer block, should have "roots" counters in consistent order */ \ f(final_traversal_update_roots, " Update Roots") \ @@ -300,10 +296,8 @@ class outputStream; \ f(full_gc_mark, " Mark") \ f(full_gc_mark_finish_queues, " Finish Queues") \ - f(full_gc_mark_termination, " Termination") \ f(full_gc_weakrefs, " Weak References") \ f(full_gc_weakrefs_process, " Process") \ - f(full_gc_weakrefs_termination, " Termination") \ f(full_gc_purge, " System Purge") \ f(full_gc_purge_class_unload, " Unload Classes") \ f(full_gc_purge_par, " Parallel Cleanup") \ @@ -322,14 +316,12 @@ class outputStream; /* Longer concurrent phases at the end */ \ f(conc_reset, "Concurrent Reset") \ f(conc_mark, "Concurrent Marking") \ - f(conc_termination, " Termination") \ f(conc_preclean, "Concurrent Precleaning") \ f(conc_roots, "Concurrent Roots") \ f(conc_evac, "Concurrent Evacuation") \ f(conc_update_refs, "Concurrent Update Refs") \ f(conc_cleanup, "Concurrent Cleanup") \ f(conc_traversal, "Concurrent Traversal") \ - f(conc_traversal_termination, " Termination") \ \ f(conc_uncommit, "Concurrent Uncommit") \ \ @@ -390,7 +382,6 @@ private: static const char* _phase_names[_num_phases]; ShenandoahWorkerTimings* _worker_times; - ShenandoahTerminationTimings* _termination_times; ShenandoahCollectorPolicy* _policy; @@ -398,7 +389,6 @@ public: ShenandoahPhaseTimings(); ShenandoahWorkerTimings* const worker_times() const { return _worker_times; } - ShenandoahTerminationTimings* const termination_times() const { return _termination_times; } // record phase start void record_phase_start(Phase phase); @@ -438,19 +428,4 @@ public: void print() const; }; -class ShenandoahTerminationTimings : public CHeapObj { -private: - WorkerDataArray* _gc_termination_phase; -public: - ShenandoahTerminationTimings(uint max_gc_threads); - - // record the time a phase took in seconds - void record_time_secs(uint worker_i, double secs); - - double average() const; - void reset(); - - void print() const; -}; - #endif // SHARE_GC_SHENANDOAH_SHENANDOAHPHASETIMINGS_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp index a3f1b2388fd..696f534ca82 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp @@ -281,17 +281,3 @@ void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) { _weak_roots.oops_do(oops, 0); _dedup_roots.oops_do(&always_true, oops, 0); } - - void ShenandoahHeapIterationRootScanner::strong_roots_do(OopClosure* oops) { - assert(Thread::current()->is_VM_thread(), "Only by VM thread"); - // Must use _claim_none to avoid interfering with concurrent CLDG iteration - CLDToOopClosure clds(oops, ClassLoaderData::_claim_none); - MarkingCodeBlobClosure code(oops, !CodeBlobToOopClosure::FixRelocations); - ShenandoahParallelOopsDoThreadClosure tc_cl(oops, &code, NULL); - ResourceMark rm; - - _serial_roots.oops_do(oops, 0); - _vm_roots.oops_do(oops, 0); - _cld_roots.always_strong_cld_do(&clds, 0); - _thread_roots.threads_do(&tc_cl, 0); - } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp index 81db97910e0..d78e062667c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp @@ -273,7 +273,6 @@ public: ShenandoahHeapIterationRootScanner(); void roots_do(OopClosure* cl); - void strong_roots_do(OopClosure* cl); }; // Evacuate all roots at a safepoint diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTimingTracker.cpp b/src/hotspot/share/gc/shenandoah/shenandoahTimingTracker.cpp index 933c25b5875..4383c5d73cc 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahTimingTracker.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahTimingTracker.cpp @@ -31,8 +31,6 @@ #include "runtime/os.hpp" -ShenandoahPhaseTimings::Phase ShenandoahTerminationTracker::_current_termination_phase = ShenandoahPhaseTimings::_num_phases; - ShenandoahWorkerTimingsTracker::ShenandoahWorkerTimingsTracker(ShenandoahWorkerTimings* worker_times, ShenandoahPhaseTimings::GCParPhases phase, uint worker_id) : _phase(phase), _worker_times(worker_times), _worker_id(worker_id) { @@ -53,44 +51,3 @@ ShenandoahWorkerTimingsTracker::~ShenandoahWorkerTimingsTracker() { } } -ShenandoahTerminationTimingsTracker::ShenandoahTerminationTimingsTracker(uint worker_id) : - _worker_id(worker_id) { - if (ShenandoahTerminationTrace) { - _start_time = os::elapsedTime(); - } -} - -ShenandoahTerminationTimingsTracker::~ShenandoahTerminationTimingsTracker() { - if (ShenandoahTerminationTrace) { - ShenandoahHeap::heap()->phase_timings()->termination_times()->record_time_secs(_worker_id, os::elapsedTime() - _start_time); - } -} - -ShenandoahTerminationTracker::ShenandoahTerminationTracker(ShenandoahPhaseTimings::Phase phase) : _phase(phase) { - assert(_current_termination_phase == ShenandoahPhaseTimings::_num_phases, "Should be invalid"); - assert(phase == ShenandoahPhaseTimings::termination || - phase == ShenandoahPhaseTimings::final_traversal_gc_termination || - phase == ShenandoahPhaseTimings::full_gc_mark_termination || - phase == ShenandoahPhaseTimings::conc_termination || - phase == ShenandoahPhaseTimings::conc_traversal_termination || - phase == ShenandoahPhaseTimings::weakrefs_termination || - phase == ShenandoahPhaseTimings::full_gc_weakrefs_termination, - "Only these phases"); - - assert(!Thread::current()->is_Worker_thread() && - (Thread::current()->is_VM_thread() || - Thread::current()->is_ConcurrentGC_thread()), - "Called from wrong thread"); - - _current_termination_phase = phase; - ShenandoahHeap::heap()->phase_timings()->termination_times()->reset(); -} - -ShenandoahTerminationTracker::~ShenandoahTerminationTracker() { - assert(_phase == _current_termination_phase, "Can not change phase"); - ShenandoahPhaseTimings* phase_times = ShenandoahHeap::heap()->phase_timings(); - - double t = phase_times->termination_times()->average(); - phase_times->record_phase_time(_phase, t); - debug_only(_current_termination_phase = ShenandoahPhaseTimings::_num_phases;) -} diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTimingTracker.hpp b/src/hotspot/share/gc/shenandoah/shenandoahTimingTracker.hpp index bf78d506f49..3177e54f9f4 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahTimingTracker.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahTimingTracker.hpp @@ -42,28 +42,4 @@ public: ~ShenandoahWorkerTimingsTracker(); }; - -class ShenandoahTerminationTimingsTracker : public StackObj { -private: - double _start_time; - uint _worker_id; - -public: - ShenandoahTerminationTimingsTracker(uint worker_id); - ~ShenandoahTerminationTimingsTracker(); -}; - -// Tracking termination time in specific GC phase -class ShenandoahTerminationTracker : public StackObj { -private: - ShenandoahPhaseTimings::Phase _phase; - - static ShenandoahPhaseTimings::Phase _current_termination_phase; -public: - ShenandoahTerminationTracker(ShenandoahPhaseTimings::Phase phase); - ~ShenandoahTerminationTracker(); - - static ShenandoahPhaseTimings::Phase current_termination_phase() { return _current_termination_phase; } -}; - #endif // SHARE_GC_SHENANDOAH_SHENANDOAHTIMINGTRACKER_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp index 3f5f64e5e14..f80960048c8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp @@ -538,7 +538,6 @@ void ShenandoahTraversalGC::main_loop_work(T* cl, jushort* live_data, uint worke if (work == 0) { // No more work, try to terminate ShenandoahSuspendibleThreadSetLeaver stsl(sts_yield && ShenandoahSuspendibleWorkers); - ShenandoahTerminationTimingsTracker term_tracker(worker_id); ShenandoahTerminatorTerminator tt(_heap); if (terminator->offer_termination(&tt)) return; @@ -558,7 +557,6 @@ void ShenandoahTraversalGC::concurrent_traversal_collection() { if (!_heap->cancelled_gc()) { uint nworkers = _heap->workers()->active_workers(); task_queues()->reserve(nworkers); - ShenandoahTerminationTracker tracker(ShenandoahPhaseTimings::conc_traversal_termination); TaskTerminator terminator(nworkers, task_queues()); ShenandoahConcurrentTraversalCollectionTask task(&terminator); @@ -571,8 +569,6 @@ void ShenandoahTraversalGC::concurrent_traversal_collection() { } void ShenandoahTraversalGC::final_traversal_collection() { - _heap->make_parsable(true); - if (!_heap->cancelled_gc()) { #if COMPILER2_OR_JVMCI DerivedPointerTable::clear(); @@ -583,8 +579,6 @@ void ShenandoahTraversalGC::final_traversal_collection() { // Finish traversal ShenandoahAllRootScanner rp(nworkers, ShenandoahPhaseTimings::final_traversal_gc_work); - ShenandoahTerminationTracker term(ShenandoahPhaseTimings::final_traversal_gc_termination); - TaskTerminator terminator(nworkers, task_queues()); ShenandoahFinalTraversalCollectionTask task(&rp, &terminator); _heap->workers()->run_task(&task); @@ -606,6 +600,11 @@ void ShenandoahTraversalGC::final_traversal_collection() { _heap->set_concurrent_traversal_in_progress(false); _heap->mark_complete_marking_context(); + // A rare case, TLAB/GCLAB is initialized from an empty region without + // any live data, the region can be trashed and may be uncommitted in later code, + // that results the TLAB/GCLAB not usable. Retire them here. + _heap->make_parsable(true); + _heap->parallel_cleaning(false); fixup_roots(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp b/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp index 385bf8cc817..fe4e872c274 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp @@ -138,33 +138,6 @@ bool ShenandoahGCPhase::is_root_work_phase() { } } -ShenandoahAllocTrace::ShenandoahAllocTrace(size_t words_size, ShenandoahAllocRequest::Type alloc_type) { - if (ShenandoahAllocationTrace) { - _start = os::elapsedTime(); - _size = words_size; - _alloc_type = alloc_type; - } else { - _start = 0; - _size = 0; - _alloc_type = ShenandoahAllocRequest::Type(0); - } -} - -ShenandoahAllocTrace::~ShenandoahAllocTrace() { - if (ShenandoahAllocationTrace) { - double stop = os::elapsedTime(); - double duration_sec = stop - _start; - double duration_us = duration_sec * 1000000; - ShenandoahAllocTracker* tracker = ShenandoahHeap::heap()->alloc_tracker(); - assert(tracker != NULL, "Must be"); - tracker->record_alloc_latency(_size, _alloc_type, duration_us); - if (duration_us > ShenandoahAllocationStallThreshold) { - log_warning(gc)("Allocation stall: %.0f us (threshold: " INTX_FORMAT " us)", - duration_us, ShenandoahAllocationStallThreshold); - } - } -} - ShenandoahWorkerSession::ShenandoahWorkerSession(uint worker_id) : _worker_id(worker_id) { Thread* thr = Thread::current(); assert(ShenandoahThreadLocalData::worker_id(thr) == ShenandoahThreadLocalData::INVALID_WORKER_ID, "Already set"); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp index 77574708315..9ea3dcadcaa 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp @@ -87,16 +87,6 @@ public: ~ShenandoahGCPauseMark(); }; -class ShenandoahAllocTrace : public StackObj { -private: - double _start; - size_t _size; - ShenandoahAllocRequest::Type _alloc_type; -public: - ShenandoahAllocTrace(size_t words_size, ShenandoahAllocRequest::Type alloc_type); - ~ShenandoahAllocTrace(); -}; - class ShenandoahSafepoint : public AllStatic { public: // check if Shenandoah GC safepoint is in progress diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp index 690b0ea40ea..f94d8f3e1d2 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp @@ -235,20 +235,6 @@ "evacuation reserve/waste is incorrect, at the risk that " \ "application allocations run out of memory too early.") \ \ - diagnostic(bool, ShenandoahAllocationTrace, false, \ - "Trace allocation latencies and stalls. Can be expensive when " \ - "lots of allocations happen, and may introduce scalability " \ - "bottlenecks.") \ - \ - diagnostic(intx, ShenandoahAllocationStallThreshold, 10000, \ - "When allocation tracing is enabled, the allocation stalls " \ - "larger than this threshold would be reported as warnings. " \ - "Time is in microseconds.") \ - \ - experimental(uintx, ShenandoahEvacAssist, 10, \ - "How many objects to evacuate on LRB assist path. " \ - "Use zero to disable.") \ - \ experimental(bool, ShenandoahPacing, true, \ "Pace application allocations to give GC chance to start " \ "and complete before allocation failure is reached.") \ @@ -308,9 +294,6 @@ diagnostic(bool, ShenandoahAllocFailureALot, false, \ "Make lots of artificial allocation failures.") \ \ - diagnostic(bool, ShenandoahTerminationTrace, false, \ - "Tracing task termination timings") \ - \ diagnostic(bool, ShenandoahAlwaysPreTouch, false, \ "Pre-touch heap memory, overrides global AlwaysPreTouch") \ \ @@ -337,7 +320,7 @@ experimental(uint, ShenandoahParallelSafepointThreads, 4, \ "Number of parallel threads used for safepoint prolog/epilog") \ \ - experimental(bool, ShenandoahPreclean, true, \ + diagnostic(bool, ShenandoahPreclean, true, \ "Do concurrent preclean phase before final mark: process " \ "definitely alive references to avoid dealing with them during " \ "pause.") \ @@ -363,10 +346,10 @@ diagnostic(bool, ShenandoahLoadRefBarrier, true, \ "Turn on/off load-reference barriers in Shenandoah") \ \ - experimental(bool, ShenandoahConcurrentScanCodeRoots, true, \ + diagnostic(bool, ShenandoahConcurrentScanCodeRoots, true, \ "Scan code roots concurrently, instead of during a pause") \ \ - experimental(uintx, ShenandoahCodeRootsStyle, 2, \ + diagnostic(uintx, ShenandoahCodeRootsStyle, 2, \ "Use this style to scan code cache:" \ " 0 - sequential iterator;" \ " 1 - parallel iterator;" \ @@ -377,13 +360,10 @@ "Turn it off for maximum compatibility with reflection or JNI " \ "code that manipulates final fields.") \ \ - experimental(bool, ShenandoahCommonGCStateLoads, false, \ - "Enable commonming for GC state loads in generated code.") \ - \ develop(bool, ShenandoahVerifyOptoBarriers, false, \ "Verify no missing barriers in C2") \ \ - experimental(bool, ShenandoahLoopOptsAfterExpansion, true, \ + diagnostic(bool, ShenandoahLoopOptsAfterExpansion, true, \ "Attempt more loop opts after barrier expansion") \ \ diagnostic(bool, ShenandoahSelfFixing, true, \ diff --git a/src/hotspot/share/gc/z/zAddress.inline.hpp b/src/hotspot/share/gc/z/zAddress.inline.hpp index 06a0e71a110..a752c91088b 100644 --- a/src/hotspot/share/gc/z/zAddress.inline.hpp +++ b/src/hotspot/share/gc/z/zAddress.inline.hpp @@ -28,6 +28,7 @@ #include "gc/z/zGlobals.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" inline bool ZAddress::is_null(uintptr_t value) { return value == 0; diff --git a/src/hotspot/share/gc/z/zLiveMap.cpp b/src/hotspot/share/gc/z/zLiveMap.cpp index b3357d1edb3..7e04b7e8c37 100644 --- a/src/hotspot/share/gc/z/zLiveMap.cpp +++ b/src/hotspot/share/gc/z/zLiveMap.cpp @@ -29,6 +29,7 @@ #include "logging/log.hpp" #include "runtime/atomic.hpp" #include "utilities/debug.hpp" +#include "utilities/powerOfTwo.hpp" static const ZStatCounter ZCounterMarkSeqNumResetContention("Contention", "Mark SeqNum Reset Contention", ZStatUnitOpsPerSecond); static const ZStatCounter ZCounterMarkSegmentResetContention("Contention", "Mark Segment Reset Contention", ZStatUnitOpsPerSecond); diff --git a/src/hotspot/share/gc/z/zMarkCache.cpp b/src/hotspot/share/gc/z/zMarkCache.cpp index 91601ff8ad2..e41e3f3c3f4 100644 --- a/src/hotspot/share/gc/z/zMarkCache.cpp +++ b/src/hotspot/share/gc/z/zMarkCache.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc/z/zMarkCache.inline.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/powerOfTwo.hpp" ZMarkCacheEntry::ZMarkCacheEntry() : _page(NULL), diff --git a/src/hotspot/share/gc/z/zMarkStack.cpp b/src/hotspot/share/gc/z/zMarkStack.cpp index 9aacc46bdde..b99c89a119a 100644 --- a/src/hotspot/share/gc/z/zMarkStack.cpp +++ b/src/hotspot/share/gc/z/zMarkStack.cpp @@ -26,6 +26,7 @@ #include "gc/z/zMarkStackAllocator.hpp" #include "logging/log.hpp" #include "utilities/debug.hpp" +#include "utilities/powerOfTwo.hpp" ZMarkStripe::ZMarkStripe() : _published(), diff --git a/src/hotspot/share/gc/z/zNMethodTable.cpp b/src/hotspot/share/gc/z/zNMethodTable.cpp index 258cd8e8f78..2f8ccafa201 100644 --- a/src/hotspot/share/gc/z/zNMethodTable.cpp +++ b/src/hotspot/share/gc/z/zNMethodTable.cpp @@ -43,6 +43,7 @@ #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "utilities/debug.hpp" +#include "utilities/powerOfTwo.hpp" ZNMethodTableEntry* ZNMethodTable::_table = NULL; size_t ZNMethodTable::_size = 0; diff --git a/src/hotspot/share/gc/z/zRelocationSetSelector.cpp b/src/hotspot/share/gc/z/zRelocationSetSelector.cpp index 36b79ae2ece..9aa89d9a65d 100644 --- a/src/hotspot/share/gc/z/zRelocationSetSelector.cpp +++ b/src/hotspot/share/gc/z/zRelocationSetSelector.cpp @@ -29,6 +29,7 @@ #include "logging/log.hpp" #include "runtime/globals.hpp" #include "utilities/debug.hpp" +#include "utilities/powerOfTwo.hpp" ZRelocationSetSelectorGroupStats::ZRelocationSetSelectorGroupStats() : _npages(0), diff --git a/src/hotspot/share/gc/z/zVerify.cpp b/src/hotspot/share/gc/z/zVerify.cpp index d1cd2fde5c0..51f48893caf 100644 --- a/src/hotspot/share/gc/z/zVerify.cpp +++ b/src/hotspot/share/gc/z/zVerify.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ #define BAD_OOP_ARG(o, p) "Bad oop " PTR_FORMAT " found at " PTR_FORMAT, p2i(o), p2i(p) -static void verify_oop(oop* p) { +static void z_verify_oop(oop* p) { const oop o = RawAccess<>::oop_load(p); if (o != NULL) { const uintptr_t addr = ZOop::to_address(o); @@ -45,7 +45,7 @@ static void verify_oop(oop* p) { } } -static void verify_possibly_weak_oop(oop* p) { +static void z_verify_possibly_weak_oop(oop* p) { const oop o = RawAccess<>::oop_load(p); if (o != NULL) { const uintptr_t addr = ZOop::to_address(o); @@ -57,7 +57,7 @@ static void verify_possibly_weak_oop(oop* p) { class ZVerifyRootClosure : public ZRootsIteratorClosure { public: virtual void do_oop(oop* p) { - verify_oop(p); + z_verify_oop(p); } virtual void do_oop(narrowOop*) { @@ -76,11 +76,11 @@ public: virtual void do_oop(oop* p) { if (_verify_weaks) { - verify_possibly_weak_oop(p); + z_verify_possibly_weak_oop(p); } else { // We should never encounter finalizable oops through strong // paths. This assumes we have only visited strong roots. - verify_oop(p); + z_verify_oop(p); } } diff --git a/src/hotspot/share/gc/z/z_globals.hpp b/src/hotspot/share/gc/z/z_globals.hpp index 6a1fee8d540..7c8435d21cd 100644 --- a/src/hotspot/share/gc/z/z_globals.hpp +++ b/src/hotspot/share/gc/z/z_globals.hpp @@ -51,6 +51,9 @@ experimental(uint, ZCollectionInterval, 0, \ "Force GC at a fixed time interval (in seconds)") \ \ + experimental(bool, ZProactive, true, \ + "Enable proactive GC cycles") \ + \ experimental(bool, ZUncommit, true, \ "Uncommit unused memory") \ \ @@ -62,9 +65,6 @@ "Time between statistics print outs (in seconds)") \ range(1, (uint)-1) \ \ - diagnostic(bool, ZProactive, true, \ - "Enable proactive GC cycles") \ - \ diagnostic(bool, ZVerifyViews, false, \ "Verify heap view accesses") \ \ diff --git a/src/hotspot/share/include/cds.h b/src/hotspot/share/include/cds.h index f90423db230..9187445329d 100644 --- a/src/hotspot/share/include/cds.h +++ b/src/hotspot/share/include/cds.h @@ -36,7 +36,7 @@ #define NUM_CDS_REGIONS 8 // this must be the same as MetaspaceShared::n_regions #define CDS_ARCHIVE_MAGIC 0xf00baba2 #define CDS_DYNAMIC_ARCHIVE_MAGIC 0xf00baba8 -#define CURRENT_CDS_ARCHIVE_VERSION 9 +#define CURRENT_CDS_ARCHIVE_VERSION 10 #define INVALID_CDS_ARCHIVE_VERSION -1 struct CDSFileMapRegion { diff --git a/src/hotspot/share/interpreter/abstractInterpreter.cpp b/src/hotspot/share/interpreter/abstractInterpreter.cpp index 1b0f9b89df6..841b7e40417 100644 --- a/src/hotspot/share/interpreter/abstractInterpreter.cpp +++ b/src/hotspot/share/interpreter/abstractInterpreter.cpp @@ -62,9 +62,6 @@ void AbstractInterpreter::initialize() { if (CountBytecodes || TraceBytecodes || StopInterpreterAt) BytecodeCounter::reset(); if (PrintBytecodeHistogram) BytecodeHistogram::reset(); if (PrintBytecodePairHistogram) BytecodePairHistogram::reset(); - - InvocationCounter::reinitialize(); - } void AbstractInterpreter::print() { diff --git a/src/hotspot/share/interpreter/bytecodeInterpreter.cpp b/src/hotspot/share/interpreter/bytecodeInterpreter.cpp index 12542199b87..2cc37c80894 100644 --- a/src/hotspot/share/interpreter/bytecodeInterpreter.cpp +++ b/src/hotspot/share/interpreter/bytecodeInterpreter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2347,11 +2347,8 @@ run: case JVM_CONSTANT_Dynamic: { - oop result = constants->resolved_references()->obj_at(index); - if (result == NULL) { - CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception); - result = THREAD->vm_result(); - } + CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception); + oop result = THREAD->vm_result(); VERIFY_OOP(result); jvalue value; @@ -2391,11 +2388,8 @@ run: case JVM_CONSTANT_Dynamic: { - oop result = constants->resolved_references()->obj_at(index); - if (result == NULL) { - CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception); - result = THREAD->vm_result(); - } + CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception); + oop result = THREAD->vm_result(); VERIFY_OOP(result); jvalue value; diff --git a/src/hotspot/share/interpreter/invocationCounter.cpp b/src/hotspot/share/interpreter/invocationCounter.cpp index 92ee2515cd5..e5a5fd2c2d9 100644 --- a/src/hotspot/share/interpreter/invocationCounter.cpp +++ b/src/hotspot/share/interpreter/invocationCounter.cpp @@ -24,136 +24,88 @@ #include "precompiled.hpp" #include "interpreter/invocationCounter.hpp" -#include "runtime/frame.hpp" -#include "runtime/handles.inline.hpp" - - -// Implementation of InvocationCounter void InvocationCounter::init() { _counter = 0; // reset all the bits, including the sticky carry - reset(); } -void InvocationCounter::reset() { - // Only reset the state and don't make the method look like it's never - // been executed - set_state(wait_for_compile); +void InvocationCounter::set(uint count, uint flag) { + _counter = (count << number_of_noncount_bits) | (flag & carry_mask); } -void InvocationCounter::set_carry() { - set_carry_flag(); +void InvocationCounter::set(uint count) { + uint carry = (_counter & carry_mask); // the carry bit is sticky + _counter = (count << number_of_noncount_bits) | carry; +} + +void InvocationCounter::update(uint new_count) { + // Don't make the method look like it's never been executed + uint counter = raw_counter(); + uint c = extract_count(counter); + uint f = extract_carry(counter); + // prevent from going to zero, to distinguish from never-executed methods + if (c > 0 && new_count == 0) new_count = 1; + set(new_count, f); +} + +void InvocationCounter::set_carry_and_reduce() { + uint counter = raw_counter(); // The carry bit now indicates that this counter had achieved a very // large value. Now reduce the value, so that the method can be // executed many more times before re-entering the VM. - int old_count = count(); - int new_count = MIN2(old_count, (int) (CompileThreshold / 2)); + uint old_count = extract_count(counter); + uint new_count = MIN2(old_count, (uint)(CompileThreshold / 2)); // prevent from going to zero, to distinguish from never-executed methods if (new_count == 0) new_count = 1; - if (old_count != new_count) set(state(), new_count); + if (old_count != new_count) set(new_count, carry_mask); } -void InvocationCounter::set_state(State state) { - assert(0 <= state && state < number_of_states, "illegal state"); - int init = _init[state]; - // prevent from going to zero, to distinguish from never-executed methods - if (init == 0 && count() > 0) init = 1; - int carry = (_counter & carry_mask); // the carry bit is sticky - _counter = (init << number_of_noncount_bits) | carry | state; +void InvocationCounter::set_carry_on_overflow() { + if (!carry() && count() > InvocationCounter::count_limit / 2) { + set_carry(); + } } +void InvocationCounter::reset() { + update(0); +} + +void InvocationCounter::decay() { + update(count() >> 1); +} void InvocationCounter::print() { - tty->print_cr("invocation count: up = %d, limit = %d, carry = %s, state = %s", - count(), limit(), - carry() ? "true" : "false", - state_as_string(state())); + uint counter = raw_counter(); + tty->print_cr("invocation count: up = %d, limit = %d, carry = %s", + extract_count(counter), limit(), + extract_carry(counter) ? "true" : "false"); } -void InvocationCounter::print_short() { - tty->print(" [%d%s;%s]", count(), carry()?"+carry":"", state_as_short_string(state())); -} - -// Initialization - -int InvocationCounter::_init [InvocationCounter::number_of_states]; -InvocationCounter::Action InvocationCounter::_action[InvocationCounter::number_of_states]; - #ifdef CC_INTERP int InvocationCounter::InterpreterInvocationLimit; int InvocationCounter::InterpreterBackwardBranchLimit; #endif -const char* InvocationCounter::state_as_string(State state) { - switch (state) { - case wait_for_nothing : return "wait_for_nothing"; - case wait_for_compile : return "wait_for_compile"; - default: - ShouldNotReachHere(); - return NULL; - } -} - -const char* InvocationCounter::state_as_short_string(State state) { - switch (state) { - case wait_for_nothing : return "not comp."; - case wait_for_compile : return "compileable"; - default: - ShouldNotReachHere(); - return NULL; - } -} - - -static address do_nothing(const methodHandle& method, TRAPS) { - // dummy action for inactive invocation counters - MethodCounters* mcs = method->method_counters(); - assert(mcs != NULL, ""); - mcs->invocation_counter()->set_carry(); - mcs->invocation_counter()->set_state(InvocationCounter::wait_for_nothing); - return NULL; -} - - -static address do_decay(const methodHandle& method, TRAPS) { - // decay invocation counters so compilation gets delayed - MethodCounters* mcs = method->method_counters(); - assert(mcs != NULL, ""); - mcs->invocation_counter()->decay(); - return NULL; -} - - -void InvocationCounter::def(State state, int init, Action action) { - assert(0 <= state && state < number_of_states, "illegal state"); - assert(0 <= init && init < count_limit, "initial value out of range"); - _init [state] = init; - _action[state] = action; -} - -void InvocationCounter::reinitialize() { - // define states - guarantee((int)number_of_states <= (int)state_limit, "adjust number_of_state_bits"); - def(wait_for_nothing, 0, do_nothing); - def(wait_for_compile, 0, do_decay); - +void invocationCounter_init() { #ifdef CC_INTERP - InterpreterInvocationLimit = CompileThreshold << number_of_noncount_bits; + InvocationCounter::InterpreterInvocationLimit = + CompileThreshold << InvocationCounter::count_shift; // When methodData is collected, the backward branch limit is compared against a // methodData counter, rather than an InvocationCounter. In the former case, we // don't need the shift by number_of_noncount_bits, but we do need to adjust // the factor by which we scale the threshold. if (ProfileInterpreter) { - InterpreterBackwardBranchLimit = (int)((int64_t)CompileThreshold * (OnStackReplacePercentage - InterpreterProfilePercentage) / 100); + InvocationCounter::InterpreterBackwardBranchLimit = + (int)((int64_t)CompileThreshold + * (OnStackReplacePercentage - InterpreterProfilePercentage) / 100); } else { - InterpreterBackwardBranchLimit = (int)(((int64_t)CompileThreshold * OnStackReplacePercentage / 100) << number_of_noncount_bits); + InvocationCounter::InterpreterBackwardBranchLimit = + (int)(((int64_t)CompileThreshold * OnStackReplacePercentage / 100) + << InvocationCounter::count_shift); } - assert(0 <= InterpreterBackwardBranchLimit, "OSR threshold should be non-negative"); + assert(0 <= InvocationCounter::InterpreterBackwardBranchLimit, + "OSR threshold should be non-negative"); #endif } - -void invocationCounter_init() { - InvocationCounter::reinitialize(); -} diff --git a/src/hotspot/share/interpreter/invocationCounter.hpp b/src/hotspot/share/interpreter/invocationCounter.hpp index 2d462307d22..0cf35e851b6 100644 --- a/src/hotspot/share/interpreter/invocationCounter.hpp +++ b/src/hotspot/share/interpreter/invocationCounter.hpp @@ -29,36 +29,26 @@ #include "utilities/exceptions.hpp" // InvocationCounters are used to trigger actions when a limit (threshold) is reached. -// For different states, different limits and actions can be defined in the initialization -// routine of InvocationCounters. // -// Implementation notes: For space reasons, state & counter are both encoded in one word, -// The state is encoded using some of the least significant bits, the counter is using the -// more significant bits. The counter is incremented before a method is activated and an +// The counter is incremented before a method is activated and an // action is triggered when count() > limit(). class InvocationCounter { friend class VMStructs; friend class JVMCIVMStructs; friend class ciReplay; - private: // bit no: |31 3| 2 | 1 0 | - unsigned int _counter; // format: [count|carry|state] + private: // bit no: |31 1| 0 | + uint _counter; // format: [count|carry| enum PrivateConstants { - number_of_state_bits = 2, - number_of_carry_bits = 1, - number_of_noncount_bits = number_of_state_bits + number_of_carry_bits, - state_limit = nth_bit(number_of_state_bits), - count_grain = nth_bit(number_of_state_bits + number_of_carry_bits), - carry_mask = right_n_bits(number_of_carry_bits) << number_of_state_bits, - state_mask = right_n_bits(number_of_state_bits), - status_mask = right_n_bits(number_of_state_bits + number_of_carry_bits), - count_mask = ((int)(-1) ^ status_mask) + number_of_carry_bits = 1, + number_of_noncount_bits = number_of_carry_bits, + count_grain = nth_bit(number_of_carry_bits), + carry_mask = right_n_bits(number_of_carry_bits), + count_mask = ((int)(-1) ^ carry_mask) }; public: - typedef address (*Action)(const methodHandle& method, TRAPS); - enum PublicConstants { count_increment = count_grain, // use this value to increment the 32bit _counter word count_mask_value = count_mask, // use this value to mask the backedge counter @@ -67,30 +57,31 @@ class InvocationCounter { count_limit = nth_bit(number_of_count_bits - 1) }; - enum State { - wait_for_nothing, // do nothing when count() > limit() - wait_for_compile, // introduce nmethod when count() > limit() - number_of_states // must be <= state_limit - }; - // Manipulation - void reset(); // sets state to wait state - void init(); // sets state into original state - void set_state(State state); // sets state and initializes counter correspondingly - inline void set(State state, int count); // sets state and counter - inline void decay(); // decay counter (divide by two) - void set_carry(); // set the sticky carry bit - void set_carry_flag() { _counter |= carry_mask; } - - int raw_counter() { return _counter; } + void reset(); + void init(); + void decay(); // decay counter (divide by two) + void set_carry_and_reduce(); // set the sticky carry bit + void set_carry_on_overflow(); + void set(uint count); + void increment() { _counter += count_increment; } // Accessors - State state() const { return (State)(_counter & state_mask); } - bool carry() const { return (_counter & carry_mask) != 0; } - int limit() const { return CompileThreshold; } - Action action() const { return _action[state()]; } - int count() const { return _counter >> number_of_noncount_bits; } + bool carry() const { return (_counter & carry_mask) != 0; } + uint count() const { return _counter >> number_of_noncount_bits; } + uint limit() const { return CompileThreshold; } + uint raw_counter() const { return _counter; } + void print(); + +private: + void set_carry() { _counter |= carry_mask; } + uint extract_carry(uint raw) const { return (raw & carry_mask); } + uint extract_count(uint raw) const { return raw >> number_of_noncount_bits; } + void update(uint new_count); + void set(uint count, uint carry); + +public: #ifdef CC_INTERP static int InterpreterInvocationLimit; // CompileThreshold scaled for interpreter use static int InterpreterBackwardBranchLimit; // A separate threshold for on stack replacement @@ -100,47 +91,16 @@ class InvocationCounter { // Checks sum of invocation_counter and backedge_counter as the template interpreter does. bool reached_InvocationLimit(InvocationCounter *back_edge_count) const { return (_counter & count_mask) + (back_edge_count->_counter & count_mask) >= - (unsigned int) InterpreterInvocationLimit; + (uint) InterpreterInvocationLimit; } bool reached_BackwardBranchLimit(InvocationCounter *back_edge_count) const { return (_counter & count_mask) + (back_edge_count->_counter & count_mask) >= - (unsigned int) InterpreterBackwardBranchLimit; + (uint) InterpreterBackwardBranchLimit; } #endif // CC_INTERP - void increment() { _counter += count_increment; } - - - // Printing - void print(); - void print_short(); - // Miscellaneous static ByteSize counter_offset() { return byte_offset_of(InvocationCounter, _counter); } - static void reinitialize(); - - private: - static int _init [number_of_states]; // the counter limits - static Action _action[number_of_states]; // the actions - - static void def(State state, int init, Action action); - static const char* state_as_string(State state); - static const char* state_as_short_string(State state); }; -inline void InvocationCounter::set(State state, int count) { - assert(0 <= state && state < number_of_states, "illegal state"); - int carry = (_counter & carry_mask); // the carry bit is sticky - _counter = (count << number_of_noncount_bits) | carry | state; -} - -inline void InvocationCounter::decay() { - int c = count(); - int new_count = c >> 1; - // prevent from going to zero, to distinguish from never-executed methods - if (c > 0 && new_count == 0) new_count = 1; - set(state(), new_count); -} - - #endif // SHARE_INTERPRETER_INVOCATIONCOUNTER_HPP diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index 7c144df47c9..156725ab4b4 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -26,8 +26,9 @@ - - + + + @@ -101,6 +102,22 @@ + + + + + + + + + + + + + + + + @@ -1236,7 +1253,8 @@ - + + diff --git a/src/hotspot/share/jfr/metadata/metadata.xsd b/src/hotspot/share/jfr/metadata/metadata.xsd index 979dbf10998..bded74ce2e5 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xsd +++ b/src/hotspot/share/jfr/metadata/metadata.xsd @@ -45,7 +45,7 @@ - + diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp index 698c6922e90..c0b394b2016 100644 --- a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp +++ b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp @@ -56,7 +56,11 @@ JfrThreadLocal::JfrThreadLocal() : _stackdepth(0), _entering_suspend_flag(0), _excluded(false), - _dead(false) {} + _dead(false) { + + Thread* thread = Thread::current_or_null(); + _parent_trace_id = thread != NULL ? thread->jfr_thread_local()->trace_id() : (traceid)0; +} u8 JfrThreadLocal::add_data_lost(u8 value) { _data_lost += value; @@ -79,6 +83,7 @@ const JfrBlobHandle& JfrThreadLocal::thread_blob() const { static void send_java_thread_start_event(JavaThread* jt) { EventThreadStart event; event.set_thread(jt->jfr_thread_local()->thread_id()); + event.set_parentThread(jt->jfr_thread_local()->parent_thread_id()); event.commit(); } @@ -94,6 +99,9 @@ void JfrThreadLocal::on_start(Thread* t) { } } } + if (t->jfr_thread_local()->has_cached_stack_trace()) { + t->jfr_thread_local()->clear_cached_stack_trace(); + } } static void send_java_thread_end_events(traceid id, JavaThread* jt) { diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.hpp b/src/hotspot/share/jfr/support/jfrThreadLocal.hpp index 522cb615b10..fcbe3d0d0f3 100644 --- a/src/hotspot/share/jfr/support/jfrThreadLocal.hpp +++ b/src/hotspot/share/jfr/support/jfrThreadLocal.hpp @@ -52,6 +52,7 @@ class JfrThreadLocal { volatile jint _entering_suspend_flag; bool _excluded; bool _dead; + traceid _parent_trace_id; JfrBuffer* install_native_buffer() const; JfrBuffer* install_java_buffer() const; @@ -128,6 +129,10 @@ class JfrThreadLocal { _trace_id = thread_id; } + traceid parent_thread_id() const { + return _parent_trace_id; + } + void set_cached_stack_trace_id(traceid id, unsigned int hash = 0) { _stack_trace_id = id; _stack_trace_hash = hash; diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 22ff42ea65e..28a193a7653 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -534,7 +534,7 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, jcla } if (resolve) { - resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK_0); + resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK_NULL); if (resolved_klass == NULL) { JVMCI_THROW_MSG_NULL(ClassNotFoundException, str); } @@ -543,7 +543,7 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, jcla // This is a name from a signature. Strip off the trimmings. // Call recursive to keep scope of strippedsym. TempNewSymbol strippedsym = Signature::strip_envelope(class_name); - resolved_klass = SystemDictionary::find(strippedsym, class_loader, protection_domain, CHECK_0); + resolved_klass = SystemDictionary::find(strippedsym, class_loader, protection_domain, CHECK_NULL); } else if (Signature::is_array(class_name)) { SignatureStream ss(class_name, false); int ndim = ss.skip_array_prefix(); @@ -552,15 +552,15 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, jcla resolved_klass = SystemDictionary::find(strippedsym, class_loader, protection_domain, - CHECK_0); + CHECK_NULL); if (!resolved_klass.is_null()) { - resolved_klass = resolved_klass->array_klass(ndim, CHECK_0); + resolved_klass = resolved_klass->array_klass(ndim, CHECK_NULL); } } else { - resolved_klass = TypeArrayKlass::cast(Universe::typeArrayKlassObj(ss.type()))->array_klass(ndim, CHECK_0); + resolved_klass = TypeArrayKlass::cast(Universe::typeArrayKlassObj(ss.type()))->array_klass(ndim, CHECK_NULL); } } else { - resolved_klass = SystemDictionary::find(class_name, class_loader, protection_domain, CHECK_0); + resolved_klass = SystemDictionary::find(class_name, class_loader, protection_domain, CHECK_NULL); } } JVMCIObject result = JVMCIENV->get_jvmci_type(resolved_klass, JVMCI_CHECK_NULL); @@ -704,8 +704,8 @@ C2V_VMENTRY_NULL(jobject, resolveFieldInPool, (JNIEnv* env, jobject, jobject jvm Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF); fieldDescriptor fd; methodHandle mh(THREAD, (jvmci_method != NULL) ? JVMCIENV->asMethod(jvmci_method) : NULL); - LinkInfo link_info(cp, index, mh, CHECK_0); - LinkResolver::resolve_field(fd, link_info, Bytecodes::java_code(code), false, CHECK_0); + LinkInfo link_info(cp, index, mh, CHECK_NULL); + LinkResolver::resolve_field(fd, link_info, Bytecodes::java_code(code), false, CHECK_NULL); JVMCIPrimitiveArray info = JVMCIENV->wrap(info_handle); if (info.is_null() || JVMCIENV->get_length(info) != 3) { JVMCI_ERROR_NULL("info must not be null and have a length of 3"); @@ -1461,7 +1461,7 @@ C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv* env, jobject, jobject _hs_ JVMCIENV->HotSpotStackFrameReference_initialize(JVMCI_CHECK); // look for the given stack frame - StackFrameStream fst(thread); + StackFrameStream fst(thread, false); intptr_t* stack_pointer = (intptr_t*) JVMCIENV->get_HotSpotStackFrameReference_stackPointer(hs_frame); while (fst.current()->sp() != stack_pointer && !fst.is_done()) { fst.next(); @@ -1477,7 +1477,7 @@ C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv* env, jobject, jobject _hs_ assert(fst.current()->cb()->is_nmethod(), "nmethod expected"); ((nmethod*) fst.current()->cb())->make_not_entrant(); } - Deoptimization::deoptimize(thread, *fst.current(), fst.register_map(), Deoptimization::Reason_none); + Deoptimization::deoptimize(thread, *fst.current(), Deoptimization::Reason_none); // look for the frame again as it has been updated by deopt (pc, deopt state...) StackFrameStream fstAfterDeopt(thread); while (fstAfterDeopt.current()->sp() != stack_pointer && !fstAfterDeopt.is_done()) { @@ -1825,7 +1825,7 @@ C2V_VMENTRY_0(jboolean, isInternedString, (JNIEnv* env, jobject, jobject object) return false; } int len; - jchar* name = java_lang_String::as_unicode_string(str(), len, CHECK_0); + jchar* name = java_lang_String::as_unicode_string(str(), len, CHECK_false); return (StringTable::lookup(name, len) != NULL); C2V_END diff --git a/src/hotspot/share/libadt/dict.cpp b/src/hotspot/share/libadt/dict.cpp index ade158824cc..b5aded12761 100644 --- a/src/hotspot/share/libadt/dict.cpp +++ b/src/hotspot/share/libadt/dict.cpp @@ -35,9 +35,13 @@ //------------------------------data----------------------------------------- // String hash tables #define MAXID 20 -static uint8_t initflag = 0; // True after 1st initialization static const char shft[MAXID] = {1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6}; -static short xsum[MAXID]; +// Precomputed table of null character hashes +// xsum[0] = (1 << shft[0]) + 1; +// for(int i = 1; i < MAXID; i++) { +// xsum[i] = (1 << shft[i]) + 1 + xsum[i - 1]; +// } +static const short xsum[MAXID] = {3,8,17,34,67,132,261,264,269,278,295,328,393,522,525,530,539,556,589,654}; //------------------------------bucket--------------------------------------- class bucket : public ResourceObj { @@ -57,16 +61,6 @@ public: // doubling in size costs no more than a constant factor in speed. Dict::Dict(CmpKey initcmp, Hash inithash) : _arena(Thread::current()->resource_area()), _hash(inithash), _cmp(initcmp) { - int i; - - // Precompute table of null character hashes - if( !initflag ) { // Not initializated yet? - xsum[0] = (1<resource_a Dict::Dict(CmpKey initcmp, Hash inithash, Arena *arena, int size) : _arena(arena), _hash(inithash), _cmp(initcmp) { - int i; + // Size is a power of 2 + _size = MAX2(16, round_up_power_of_2(size)); - // Precompute table of null character hashes - if( !initflag ) { // Not initializated yet? - xsum[0] = (1<Amalloc_4(sizeof(bucket)*_size); memset((void*)_bin,0,sizeof(bucket)*_size); @@ -310,10 +294,10 @@ int hashstr(const void *t) { const char *s = (const char *)t; while( ((c = *s++) != '\0') && (k < MAXID-1) ) { // Get characters till null or MAXID-1 - c = (c<<1)+1; // Characters are always odd! - sum += c + (c<> 1); // Hash key, un-modulo'd table size + return (int)((sum + xsum[k]) >> 1); // Hash key, un-modulo'd table size } //------------------------------hashptr-------------------------------------- diff --git a/src/hotspot/share/logging/logTag.hpp b/src/hotspot/share/logging/logTag.hpp index e979fc0d739..cf3383bc7dd 100644 --- a/src/hotspot/share/logging/logTag.hpp +++ b/src/hotspot/share/logging/logTag.hpp @@ -89,6 +89,7 @@ LOG_TAG(jit) \ LOG_TAG(jni) \ LOG_TAG(jvmti) \ + LOG_TAG(library) \ LOG_TAG(liveness) \ LOG_TAG(load) /* Trace all classes loaded */ \ LOG_TAG(loader) \ diff --git a/src/hotspot/share/memory/arena.hpp b/src/hotspot/share/memory/arena.hpp index 05266014964..ceec3f2ea69 100644 --- a/src/hotspot/share/memory/arena.hpp +++ b/src/hotspot/share/memory/arena.hpp @@ -28,6 +28,7 @@ #include "memory/allocation.hpp" #include "runtime/globals.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/powerOfTwo.hpp" #include diff --git a/src/hotspot/share/memory/filemap.cpp b/src/hotspot/share/memory/filemap.cpp index 526abb5b4e5..8d4882923d3 100644 --- a/src/hotspot/share/memory/filemap.cpp +++ b/src/hotspot/share/memory/filemap.cpp @@ -210,6 +210,8 @@ void FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) { _narrow_oop_mode = CompressedOops::mode(); _narrow_oop_base = CompressedOops::base(); _narrow_oop_shift = CompressedOops::shift(); + _compressed_oops = UseCompressedOops; + _compressed_class_ptrs = UseCompressedClassPointers; _max_heap_size = MaxHeapSize; _narrow_klass_shift = CompressedKlassPointers::shift(); if (HeapShared::is_heap_object_archiving_allowed()) { @@ -1745,7 +1747,15 @@ void FileMapInfo::map_heap_regions() { bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first, int max, int* num, bool is_open_archive) { - MemRegion * regions = new MemRegion[max]; + MemRegion* regions = MemRegion::create_array(max, mtInternal); + + struct Cleanup { + MemRegion* _regions; + bool _aborted; + Cleanup(MemRegion* regions) : _regions(regions), _aborted(true) { } + ~Cleanup() { if (_aborted) { FREE_C_HEAP_ARRAY(MemRegion, _regions); } } + } cleanup(regions); + FileMapRegion* si; int region_num = 0; @@ -1805,6 +1815,7 @@ bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first, } } + cleanup._aborted = false; // the shared heap data is mapped successfully *heap_mem = regions; *num = region_num; @@ -2041,6 +2052,14 @@ bool FileMapHeader::validate() { "for testing purposes only and should not be used in a production environment"); } + log_info(cds)("Archive was created with UseCompressedOops = %d, UseCompressedClassPointers = %d", + compressed_oops(), compressed_class_pointers()); + if (compressed_oops() != UseCompressedOops || compressed_class_pointers() != UseCompressedClassPointers) { + FileMapInfo::fail_continue("Unable to use shared archive.\nThe saved state of UseCompressedOops and UseCompressedClassPointers is " + "different from runtime, CDS will be disabled."); + return false; + } + return true; } diff --git a/src/hotspot/share/memory/filemap.hpp b/src/hotspot/share/memory/filemap.hpp index 237a3e3529e..67b78408418 100644 --- a/src/hotspot/share/memory/filemap.hpp +++ b/src/hotspot/share/memory/filemap.hpp @@ -187,6 +187,8 @@ class FileMapHeader: private CDSFileMapHeaderBase { uintx _max_heap_size; // java max heap size during dumping CompressedOops::Mode _narrow_oop_mode; // compressed oop encoding mode int _narrow_klass_shift; // save narrow klass base and shift + bool _compressed_oops; // save the flag UseCompressedOops + bool _compressed_class_ptrs; // save the flag UseCompressedClassPointers size_t _cloned_vtables_offset; // The address of the first cloned vtable size_t _serialized_data_offset; // Data accessed using {ReadClosure,WriteClosure}::serialize() size_t _i2i_entry_code_buffers_offset; @@ -264,7 +266,8 @@ public: char* mapped_base_address() const { return _mapped_base_address; } bool has_platform_or_app_classes() const { return _has_platform_or_app_classes; } size_t ptrmap_size_in_bits() const { return _ptrmap_size_in_bits; } - + bool compressed_oops() const { return _compressed_oops; } + bool compressed_class_pointers() const { return _compressed_class_ptrs; } // FIXME: These should really return int jshort max_used_path_index() const { return _max_used_path_index; } jshort app_module_paths_start_index() const { return _app_module_paths_start_index; } diff --git a/src/hotspot/share/memory/heap.cpp b/src/hotspot/share/memory/heap.cpp index 31a6ee6f280..38157d69d4e 100644 --- a/src/hotspot/share/memory/heap.cpp +++ b/src/hotspot/share/memory/heap.cpp @@ -28,6 +28,7 @@ #include "runtime/os.hpp" #include "services/memTracker.hpp" #include "utilities/align.hpp" +#include "utilities/powerOfTwo.hpp" size_t CodeHeap::header_size() { return sizeof(HeapBlock); @@ -611,6 +612,9 @@ void CodeHeap::add_to_freelist(HeapBlock* a) { size_t bseg = segment_for(b); _freelist_length++; + _blob_count--; + assert(_blob_count >= 0, "sanity"); + assert(b != _freelist, "cannot be removed twice"); // Mark as free and update free space count diff --git a/src/hotspot/share/memory/memRegion.cpp b/src/hotspot/share/memory/memRegion.cpp index 2942bd59ab1..4dd0e208847 100644 --- a/src/hotspot/share/memory/memRegion.cpp +++ b/src/hotspot/share/memory/memRegion.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * 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,19 +102,10 @@ MemRegion MemRegion::minus(const MemRegion mr2) const { return MemRegion(); } -void* MemRegion::operator new(size_t size) throw() { - return (address)AllocateHeap(size, mtGC, CURRENT_PC, - AllocFailStrategy::RETURN_NULL); -} - -void* MemRegion::operator new [](size_t size) throw() { - return (address)AllocateHeap(size, mtGC, CURRENT_PC, - AllocFailStrategy::RETURN_NULL); -} -void MemRegion::operator delete(void* p) { - FreeHeap(p); -} - -void MemRegion::operator delete [](void* p) { - FreeHeap(p); +MemRegion* MemRegion::create_array(uint length, MEMFLAGS flags) { + MemRegion* result = NEW_C_HEAP_ARRAY(MemRegion, length, flags); + for (uint i = 0; i < length; i++) { + ::new (&result[i]) MemRegion(); + } + return result; } diff --git a/src/hotspot/share/memory/memRegion.hpp b/src/hotspot/share/memory/memRegion.hpp index d1268caea0a..e5d32442fe1 100644 --- a/src/hotspot/share/memory/memRegion.hpp +++ b/src/hotspot/share/memory/memRegion.hpp @@ -92,10 +92,9 @@ public: size_t word_size() const { return _word_size; } bool is_empty() const { return word_size() == 0; } - void* operator new(size_t size) throw(); - void* operator new [](size_t size) throw(); - void operator delete(void* p); - void operator delete [](void* p); + + // Creates and initializes an array of MemRegions of the given length. + static MemRegion* create_array(uint length, MEMFLAGS flags); }; // For iteration over MemRegion's. diff --git a/src/hotspot/share/memory/metaspaceShared.cpp b/src/hotspot/share/memory/metaspaceShared.cpp index 84843422375..73bd3ab335f 100644 --- a/src/hotspot/share/memory/metaspaceShared.cpp +++ b/src/hotspot/share/memory/metaspaceShared.cpp @@ -294,23 +294,21 @@ void MetaspaceShared::initialize_dumptime_shared_and_meta_spaces() { // ArchiveCompactor will copy the class metadata into this space, first the RW parts, // then the RO parts. - assert(UseCompressedOops && UseCompressedClassPointers, - "UseCompressedOops and UseCompressedClassPointers must be set"); - size_t max_archive_size = align_down(cds_total * 3 / 4, reserve_alignment); ReservedSpace tmp_class_space = _shared_rs.last_part(max_archive_size); CompressedClassSpaceSize = align_down(tmp_class_space.size(), reserve_alignment); _shared_rs = _shared_rs.first_part(max_archive_size); - // Set up compress class pointers. - CompressedKlassPointers::set_base((address)_shared_rs.base()); - // Set narrow_klass_shift to be LogKlassAlignmentInBytes. This is consistent - // with AOT. - CompressedKlassPointers::set_shift(LogKlassAlignmentInBytes); - // Set the range of klass addresses to 4GB. - CompressedKlassPointers::set_range(cds_total); - - Metaspace::initialize_class_space(tmp_class_space); + if (UseCompressedClassPointers) { + // Set up compress class pointers. + CompressedKlassPointers::set_base((address)_shared_rs.base()); + // Set narrow_klass_shift to be LogKlassAlignmentInBytes. This is consistent + // with AOT. + CompressedKlassPointers::set_shift(LogKlassAlignmentInBytes); + // Set the range of klass addresses to 4GB. + CompressedKlassPointers::set_range(cds_total); + Metaspace::initialize_class_space(tmp_class_space); + } log_info(cds)("narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d", p2i(CompressedKlassPointers::base()), CompressedKlassPointers::shift()); @@ -465,6 +463,9 @@ void MetaspaceShared::serialize(SerializeClosure* soc) { SystemDictionaryShared::serialize_dictionary_headers(soc); InstanceMirrorKlass::serialize_offsets(soc); + + // Dump/restore well known classes (pointers) + SystemDictionaryShared::serialize_well_known_klasses(soc); soc->do_tag(--tag); serialize_cloned_cpp_vtptrs(soc); @@ -2181,8 +2182,8 @@ MapArchiveResult MetaspaceShared::map_archives(FileMapInfo* static_mapinfo, File // map_heap_regions() compares the current narrow oop and klass encodings // with the archived ones, so it must be done after all encodings are determined. static_mapinfo->map_heap_regions(); + CompressedKlassPointers::set_range(CompressedClassSpaceSize); } - CompressedKlassPointers::set_range(CompressedClassSpaceSize); }); } else { unmap_archive(static_mapinfo); diff --git a/src/hotspot/share/memory/virtualspace.cpp b/src/hotspot/share/memory/virtualspace.cpp index ebf3efa6824..d8185889513 100644 --- a/src/hotspot/share/memory/virtualspace.cpp +++ b/src/hotspot/share/memory/virtualspace.cpp @@ -32,6 +32,7 @@ #include "runtime/os.inline.hpp" #include "services/memTracker.hpp" #include "utilities/align.hpp" +#include "utilities/powerOfTwo.hpp" // ReservedSpace diff --git a/src/hotspot/share/oops/arrayKlass.cpp b/src/hotspot/share/oops/arrayKlass.cpp index facf2baec04..9063b454115 100644 --- a/src/hotspot/share/oops/arrayKlass.cpp +++ b/src/hotspot/share/oops/arrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -124,12 +124,12 @@ GrowableArray* ArrayKlass::compute_secondary_supers(int num_extra_slots, } objArrayOop ArrayKlass::allocate_arrayArray(int n, int length, TRAPS) { - check_array_allocation_length(length, arrayOopDesc::max_array_length(T_ARRAY), CHECK_0); + check_array_allocation_length(length, arrayOopDesc::max_array_length(T_ARRAY), CHECK_NULL); int size = objArrayOopDesc::object_size(length); - Klass* k = array_klass(n+dimension(), CHECK_0); + Klass* k = array_klass(n+dimension(), CHECK_NULL); ArrayKlass* ak = ArrayKlass::cast(k); objArrayOop o = (objArrayOop)Universe::heap()->array_allocate(ak, size, length, - /* do_zero */ true, CHECK_0); + /* do_zero */ true, CHECK_NULL); // initialization to NULL not necessary, area already cleared return o; } diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 1127d7c07cd..848a8669aa1 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -1153,7 +1153,9 @@ int InstanceKlass::nof_implementors() const { // // The _implementor field only exists for interfaces. void InstanceKlass::add_implementor(Klass* k) { - assert_lock_strong(Compile_lock); + if (Universe::is_fully_initialized()) { + assert_lock_strong(Compile_lock); + } assert(is_interface(), "not interface"); // Filter out my subinterfaces. // (Note: Interfaces are never on the subklass list.) diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index 62e8a866cb5..2f2abe8e2ca 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -47,6 +47,7 @@ #include "runtime/atomic.hpp" #include "runtime/handles.inline.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #include "utilities/stack.inline.hpp" void Klass::set_java_mirror(Handle m) { @@ -412,7 +413,9 @@ void Klass::set_next_sibling(Klass* s) { } void Klass::append_to_sibling_list() { - assert_locked_or_safepoint(Compile_lock); + if (Universe::is_fully_initialized()) { + assert_locked_or_safepoint(Compile_lock); + } debug_only(verify();) // add ourselves to superklass' subklass list InstanceKlass* super = superklass(); diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index d2f32e0785e..0f3cad89493 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -811,7 +811,13 @@ objArrayHandle Method::resolved_checked_exceptions_impl(Method* method, TRAPS) { for (int i = 0; i < length; i++) { CheckedExceptionElement* table = h_this->checked_exceptions_start(); // recompute on each iteration, not gc safe Klass* k = h_this->constants()->klass_at(table[i].class_cp_index, CHECK_(objArrayHandle())); - assert(k->is_subclass_of(SystemDictionary::Throwable_klass()), "invalid exception class"); + if (log_is_enabled(Warning, exceptions) && + !k->is_subclass_of(SystemDictionary::Throwable_klass())) { + ResourceMark rm(THREAD); + log_warning(exceptions)( + "Class %s in throws clause of method %s is not a subtype of class java.lang.Throwable", + k->external_name(), method->external_name()); + } mirrors->obj_at_put(i, k->java_mirror()); } return mirrors; @@ -995,7 +1001,6 @@ void Method::set_not_compilable(const char* reason, int comp_level, bool report) if (is_c2_compile(comp_level)) set_not_c2_compilable(); } - CompilationPolicy::policy()->disable_compilation(this); assert(!CompilationPolicy::can_be_compiled(methodHandle(Thread::current(), this), comp_level), "sanity check"); } @@ -1022,7 +1027,6 @@ void Method::set_not_osr_compilable(const char* reason, int comp_level, bool rep if (is_c2_compile(comp_level)) set_not_c2_osr_compilable(); } - CompilationPolicy::policy()->disable_compilation(this); assert(!CompilationPolicy::can_be_osr_compiled(methodHandle(Thread::current(), this), comp_level), "sanity check"); } diff --git a/src/hotspot/share/oops/objArrayKlass.cpp b/src/hotspot/share/oops/objArrayKlass.cpp index 11867db3374..b4647fd380f 100644 --- a/src/hotspot/share/oops/objArrayKlass.cpp +++ b/src/hotspot/share/oops/objArrayKlass.cpp @@ -80,13 +80,13 @@ Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data, Klass* ek = NULL; { MutexUnlocker mu(MultiArray_lock); - super_klass = element_super->array_klass(CHECK_0); + super_klass = element_super->array_klass(CHECK_NULL); for( int i = element_supers->length()-1; i >= 0; i-- ) { Klass* elem_super = element_supers->at(i); - elem_super->array_klass(CHECK_0); + elem_super->array_klass(CHECK_NULL); } // Now retry from the beginning - ek = element_klass->array_klass(n, CHECK_0); + ek = element_klass->array_klass(n, CHECK_NULL); } // re-lock return ek; } @@ -124,13 +124,13 @@ Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data, } // Initialize instance variables - ObjArrayKlass* oak = ObjArrayKlass::allocate(loader_data, n, element_klass, name, CHECK_0); + ObjArrayKlass* oak = ObjArrayKlass::allocate(loader_data, n, element_klass, name, CHECK_NULL); ModuleEntry* module = oak->module(); assert(module != NULL, "No module entry for array"); // Call complete_create_array_klass after all instance variables has been initialized. - ArrayKlass::complete_create_array_klass(oak, super_klass, module, CHECK_0); + ArrayKlass::complete_create_array_klass(oak, super_klass, module, CHECK_NULL); // Add all classes to our internal class loader list here, // including classes in the bootstrap (NULL) class loader. @@ -171,7 +171,7 @@ int ObjArrayKlass::oop_size(oop obj) const { } objArrayOop ObjArrayKlass::allocate(int length, TRAPS) { - check_array_allocation_length(length, arrayOopDesc::max_array_length(T_OBJECT), CHECK_0); + check_array_allocation_length(length, arrayOopDesc::max_array_length(T_OBJECT), CHECK_NULL); int size = objArrayOopDesc::object_size(length); return (objArrayOop)Universe::heap()->array_allocate(this, size, length, /* do_zero */ true, THREAD); diff --git a/src/hotspot/share/oops/objArrayKlass.inline.hpp b/src/hotspot/share/oops/objArrayKlass.inline.hpp index 5dec0db8da8..6943aea468a 100644 --- a/src/hotspot/share/oops/objArrayKlass.inline.hpp +++ b/src/hotspot/share/oops/objArrayKlass.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,7 +101,7 @@ void ObjArrayKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, Me // for objArrayOops. template void ObjArrayKlass::oop_oop_iterate_range(objArrayOop a, OopClosureType* closure, int start, int end) { - T* low = start == 0 ? cast_from_oop(a) : a->obj_at_addr_raw(start); + T* low = (T*)a->base_raw() + start; T* high = (T*)a->base_raw() + end; oop_oop_iterate_elements_bounded(a, closure, low, high); diff --git a/src/hotspot/share/oops/symbol.cpp b/src/hotspot/share/oops/symbol.cpp index 0b4dea061b8..356d9bdf3b0 100644 --- a/src/hotspot/share/oops/symbol.cpp +++ b/src/hotspot/share/oops/symbol.cpp @@ -37,21 +37,18 @@ #include "runtime/os.hpp" #include "utilities/utf8.hpp" -uint32_t Symbol::pack_length_and_refcount(int length, int refcount) { - STATIC_ASSERT(max_symbol_length == ((1 << 16) - 1)); +uint32_t Symbol::pack_hash_and_refcount(short hash, int refcount) { STATIC_ASSERT(PERM_REFCOUNT == ((1 << 16) - 1)); - assert(length >= 0, "negative length"); - assert(length <= max_symbol_length, "too long symbol"); assert(refcount >= 0, "negative refcount"); assert(refcount <= PERM_REFCOUNT, "invalid refcount"); - uint32_t hi = length; + uint32_t hi = hash; uint32_t lo = refcount; return (hi << 16) | lo; } Symbol::Symbol(const u1* name, int length, int refcount) { - _length_and_refcount = pack_length_and_refcount(length, refcount); - _identity_hash = (short)os::random(); + _hash_and_refcount = pack_hash_and_refcount((short)os::random(), refcount); + _length = length; _body[0] = 0; // in case length == 0 for (int i = 0; i < length; i++) { byte_at_put(i, name[i]); @@ -78,35 +75,7 @@ void Symbol::operator delete(void *p) { void Symbol::set_permanent() { // This is called at a safepoint during dumping of a dynamic CDS archive. assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); - _length_and_refcount = pack_length_and_refcount(length(), PERM_REFCOUNT); -} - - -// ------------------------------------------------------------------ -// Symbol::contains_byte_at -// -// Tests if the symbol contains the given byte at the given position. -bool Symbol::contains_byte_at(int position, char code_byte) const { - if (position < 0) return false; // can happen with ends_with - if (position >= utf8_length()) return false; - return code_byte == char_at(position); -} - -// ------------------------------------------------------------------ -// Symbol::contains_utf8_at -// -// Tests if the symbol contains the given utf8 substring -// at the given byte position. -bool Symbol::contains_utf8_at(int position, const char* substring, int len) const { - assert(len >= 0 && substring != NULL, "substring must be valid"); - if (len <= 1) - return len == 0 || contains_byte_at(position, substring[0]); - if (position < 0) return false; // can happen with ends_with - if (position + len > utf8_length()) return false; - if (memcmp((char*)base() + position, substring, len) == 0) - return true; - else - return false; + _hash_and_refcount = pack_hash_and_refcount(extract_hash(_hash_and_refcount), PERM_REFCOUNT); } // ------------------------------------------------------------------ @@ -282,7 +251,7 @@ void Symbol::print_as_signature_external_parameters(outputStream *os) { // a thread could be concurrently removing the Symbol. This is used during SymbolTable // lookup to avoid reviving a dead Symbol. bool Symbol::try_increment_refcount() { - uint32_t found = _length_and_refcount; + uint32_t found = _hash_and_refcount; while (true) { uint32_t old_value = found; int refc = extract_refcount(old_value); @@ -291,7 +260,7 @@ bool Symbol::try_increment_refcount() { } else if (refc == 0) { return false; // dead, can't revive. } else { - found = Atomic::cmpxchg(&_length_and_refcount, old_value, old_value + 1); + found = Atomic::cmpxchg(&_hash_and_refcount, old_value, old_value + 1); if (found == old_value) { return true; // successfully updated. } @@ -321,7 +290,7 @@ void Symbol::increment_refcount() { // to check the value after attempting to decrement so that if another // thread increments to PERM_REFCOUNT the value is not decremented. void Symbol::decrement_refcount() { - uint32_t found = _length_and_refcount; + uint32_t found = _hash_and_refcount; while (true) { uint32_t old_value = found; int refc = extract_refcount(old_value); @@ -334,7 +303,7 @@ void Symbol::decrement_refcount() { #endif return; } else { - found = Atomic::cmpxchg(&_length_and_refcount, old_value, old_value - 1); + found = Atomic::cmpxchg(&_hash_and_refcount, old_value, old_value - 1); if (found == old_value) { return; // successfully updated. } @@ -344,7 +313,7 @@ void Symbol::decrement_refcount() { } void Symbol::make_permanent() { - uint32_t found = _length_and_refcount; + uint32_t found = _hash_and_refcount; while (true) { uint32_t old_value = found; int refc = extract_refcount(old_value); @@ -357,8 +326,8 @@ void Symbol::make_permanent() { #endif return; } else { - int len = extract_length(old_value); - found = Atomic::cmpxchg(&_length_and_refcount, old_value, pack_length_and_refcount(len, PERM_REFCOUNT)); + int hash = extract_hash(old_value); + found = Atomic::cmpxchg(&_hash_and_refcount, old_value, pack_hash_and_refcount(hash, PERM_REFCOUNT)); if (found == old_value) { return; // successfully updated. } diff --git a/src/hotspot/share/oops/symbol.hpp b/src/hotspot/share/oops/symbol.hpp index 676253f77c5..789214f8696 100644 --- a/src/hotspot/share/oops/symbol.hpp +++ b/src/hotspot/share/oops/symbol.hpp @@ -97,7 +97,7 @@ class ClassLoaderData; // Set _refcount to PERM_REFCOUNT to prevent the Symbol from being freed. #ifndef PERM_REFCOUNT -#define PERM_REFCOUNT ((1 << 16) - 1) +#define PERM_REFCOUNT 0xffff #endif class Symbol : public MetaspaceObj { @@ -106,15 +106,14 @@ class Symbol : public MetaspaceObj { private: - // This is an int because it needs atomic operation on the refcount. Mask length + // This is an int because it needs atomic operation on the refcount. Mask hash // in high half word. length is the number of UTF8 characters in the symbol - volatile uint32_t _length_and_refcount; - short _identity_hash; + volatile uint32_t _hash_and_refcount; + u2 _length; u1 _body[2]; enum { - // max_symbol_length must fit into the top 16 bits of _length_and_refcount - max_symbol_length = (1 << 16) -1 + max_symbol_length = 0xffff }; static int byte_size(int length) { @@ -137,11 +136,11 @@ class Symbol : public MetaspaceObj { void operator delete(void* p); - static int extract_length(uint32_t value) { return value >> 16; } + static short extract_hash(uint32_t value) { return (short)(value >> 16); } static int extract_refcount(uint32_t value) { return value & 0xffff; } - static uint32_t pack_length_and_refcount(int length, int refcount); + static uint32_t pack_hash_and_refcount(short hash, int refcount); - int length() const { return extract_length(_length_and_refcount); } + int length() const { return _length; } public: // Low-level access (used with care, since not GC-safe) @@ -157,16 +156,16 @@ class Symbol : public MetaspaceObj { static int max_length() { return max_symbol_length; } unsigned identity_hash() const { unsigned addr_bits = (unsigned)((uintptr_t)this >> (LogMinObjAlignmentInBytes + 3)); - return ((unsigned)_identity_hash & 0xffff) | + return ((unsigned)extract_hash(_hash_and_refcount) & 0xffff) | ((addr_bits ^ (length() << 8) ^ (( _body[0] << 8) | _body[1])) << 16); } // Reference counting. See comments above this class for when to use. - int refcount() const { return extract_refcount(_length_and_refcount); } + int refcount() const { return extract_refcount(_hash_and_refcount); } bool try_increment_refcount(); void increment_refcount(); void decrement_refcount(); - bool is_permanent() { + bool is_permanent() const { return (refcount() == PERM_REFCOUNT); } void set_permanent(); @@ -211,12 +210,24 @@ class Symbol : public MetaspaceObj { return ends_with(suffix, (int) strlen(suffix)); } bool ends_with(int suffix_char) const { - return contains_byte_at(utf8_length()-1, suffix_char); + return contains_byte_at(utf8_length() - 1, suffix_char); } + // Tests if the symbol contains the given utf8 substring - // or byte at the given byte position. - bool contains_utf8_at(int position, const char* substring, int len) const; - bool contains_byte_at(int position, char code_byte) const; + // at the given byte position. + bool contains_utf8_at(int position, const char* substring, int len) const { + assert(len >= 0 && substring != NULL, "substring must be valid"); + if (position < 0) return false; // can happen with ends_with + if (position + len > utf8_length()) return false; + return (memcmp((char*)base() + position, substring, len) == 0); + } + + // Tests if the symbol contains the given byte at the given position. + bool contains_byte_at(int position, char code_byte) const { + if (position < 0) return false; // can happen with ends_with + if (position >= utf8_length()) return false; + return code_byte == char_at(position); + } // Tests if the symbol starts with the given prefix. int index_of_at(int i, const char* str, int len) const; diff --git a/src/hotspot/share/opto/arraycopynode.cpp b/src/hotspot/share/opto/arraycopynode.cpp index 1370af872d4..73a140ac2f5 100644 --- a/src/hotspot/share/opto/arraycopynode.cpp +++ b/src/hotspot/share/opto/arraycopynode.cpp @@ -30,6 +30,7 @@ #include "opto/graphKit.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" ArrayCopyNode::ArrayCopyNode(Compile* C, bool alloc_tightly_coupled, bool has_negative_length_guard) : CallNode(arraycopy_type(), NULL, TypePtr::BOTTOM), diff --git a/src/hotspot/share/opto/block.hpp b/src/hotspot/share/opto/block.hpp index 9a6fccc5a1e..775b3076db7 100644 --- a/src/hotspot/share/opto/block.hpp +++ b/src/hotspot/share/opto/block.hpp @@ -28,6 +28,7 @@ #include "opto/multnode.hpp" #include "opto/node.hpp" #include "opto/phase.hpp" +#include "utilities/powerOfTwo.hpp" // Optimization - Graph Style @@ -499,7 +500,10 @@ class PhaseCFG : public Phase { CFGLoop* create_loop_tree(); bool is_dominator(Node* dom_node, Node* node); - + bool is_CFG(Node* n); + bool is_control_proj_or_safepoint(Node* n); + Block* find_block_for_node(Node* n); + bool is_dominating_control(Node* dom_ctrl, Node* n); #ifndef PRODUCT bool _trace_opto_pipelining; // tracing flag #endif diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index d605bdb7bd1..540678f08d7 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -611,12 +611,6 @@ develop(bool, ConvertFloat2IntClipping, true, \ "Convert float2int clipping idiom to integer clipping") \ \ - develop(bool, Use24BitFPMode, true, \ - "Set 24-bit FPU mode on a per-compile basis ") \ - \ - develop(bool, Use24BitFP, true, \ - "use FP instructions that produce 24-bit precise results") \ - \ develop(bool, MonomorphicArrayCheck, true, \ "Uncommon-trap array store checks that require full type check") \ \ @@ -752,6 +746,9 @@ range(0, max_juint) \ \ product(bool, UseProfiledLoopPredicate, true, \ - "move predicates out of loops based on profiling data") \ + "Move predicates out of loops based on profiling data") \ + \ + diagnostic(bool, ExpandSubTypeCheckAtParseTime, false, \ + "Do not use subtype check macro node") \ #endif // SHARE_OPTO_C2_GLOBALS_HPP diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index 3f215dcef83..f8ec757b821 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -42,6 +42,7 @@ #include "opto/regmask.hpp" #include "opto/rootnode.hpp" #include "opto/runtime.hpp" +#include "utilities/powerOfTwo.hpp" // Portions of code courtesy of Clifford Click diff --git a/src/hotspot/share/opto/classes.cpp b/src/hotspot/share/opto/classes.cpp index d1282ac78f1..0297125da9e 100644 --- a/src/hotspot/share/opto/classes.cpp +++ b/src/hotspot/share/opto/classes.cpp @@ -46,6 +46,7 @@ #include "opto/opaquenode.hpp" #include "opto/rootnode.hpp" #include "opto/subnode.hpp" +#include "opto/subtypenode.hpp" #include "opto/vectornode.hpp" #include "utilities/macros.hpp" #if INCLUDE_SHENANDOAHGC diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp index 2924bcab860..dc1c6c19cd9 100644 --- a/src/hotspot/share/opto/classes.hpp +++ b/src/hotspot/share/opto/classes.hpp @@ -250,6 +250,7 @@ macro(OverflowMulL) macro(PCTable) macro(Parm) macro(PartialSubtypeCheck) +macro(SubTypeCheck) macro(Phi) macro(PopCountI) macro(PopCountL) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 259bdd57c72..41f6a6ac024 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -1094,7 +1094,7 @@ void Compile::Init(int aliaslevel) { _matcher = NULL; // filled in later _cfg = NULL; // filled in later - set_24_bit_selection_and_mode(Use24BitFP, false); + IA32_ONLY( set_24_bit_selection_and_mode(true, false); ) _node_note_array = NULL; _default_node_notes = NULL; @@ -3713,14 +3713,16 @@ bool Compile::final_graph_reshaping() { } } +#ifdef IA32 // If original bytecodes contained a mixture of floats and doubles // check if the optimizer has made it homogenous, item (3). - if( Use24BitFPMode && Use24BitFP && UseSSE == 0 && + if (UseSSE == 0 && frc.get_float_count() > 32 && frc.get_double_count() == 0 && (10 * frc.get_call_count() < frc.get_float_count()) ) { - set_24_bit_selection_and_mode( false, true ); + set_24_bit_selection_and_mode(false, true); } +#endif // IA32 set_java_calls(frc.get_java_call_count()); set_inner_loops(frc.get_inner_loop_count()); @@ -4237,6 +4239,9 @@ int Compile::static_subtype_check(ciKlass* superk, ciKlass* subk) { // Add a dependency if there is a chance of a later subclass. dependencies()->assert_leaf_type(ik); } + if (ik->is_abstract()) { + return SSC_always_false; + } return SSC_easy_test; // (3) caller can do a simple ptr comparison } } else { diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 7e7701e4e5c..6698b6d4c06 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -582,8 +582,6 @@ class Compile : public Phase { private: // Matching, CFG layout, allocation, code generation PhaseCFG* _cfg; // Results of CFG finding - bool _select_24_bit_instr; // We selected an instruction with a 24-bit result - bool _in_24_bit_fp_mode; // We are emitting instructions with 24-bit results int _java_calls; // Number of java calls in the method int _inner_loops; // Number of inner loops in the method Matcher* _matcher; // Engine to map ideal to machine instructions @@ -1122,8 +1120,6 @@ class Compile : public Phase { // Matching, CFG layout, allocation, code generation PhaseCFG* cfg() { return _cfg; } - bool select_24_bit_instr() const { return _select_24_bit_instr; } - bool in_24_bit_fp_mode() const { return _in_24_bit_fp_mode; } bool has_java_calls() const { return _java_calls > 0; } int java_calls() const { return _java_calls; } int inner_loops() const { return _inner_loops; } @@ -1155,12 +1151,6 @@ class Compile : public Phase { void set_indexSet_arena(Arena* a) { _indexSet_arena = a; } void set_indexSet_free_block_list(void* p) { _indexSet_free_block_list = p; } - // Remember if this compilation changes hardware mode to 24-bit precision - void set_24_bit_selection_and_mode(bool selection, bool mode) { - _select_24_bit_instr = selection; - _in_24_bit_fp_mode = mode; - } - void set_java_calls(int z) { _java_calls = z; } void set_inner_loops(int z) { _inner_loops = z; } @@ -1413,6 +1403,22 @@ class Compile : public Phase { bool needs_clinit_barrier(ciField* ik, ciMethod* accessing_method); bool needs_clinit_barrier(ciMethod* ik, ciMethod* accessing_method); bool needs_clinit_barrier(ciInstanceKlass* ik, ciMethod* accessing_method); + +#ifdef IA32 + private: + bool _select_24_bit_instr; // We selected an instruction with a 24-bit result + bool _in_24_bit_fp_mode; // We are emitting instructions with 24-bit results + + // Remember if this compilation changes hardware mode to 24-bit precision. + void set_24_bit_selection_and_mode(bool selection, bool mode) { + _select_24_bit_instr = selection; + _in_24_bit_fp_mode = mode; + } + + public: + bool select_24_bit_instr() const { return _select_24_bit_instr; } + bool in_24_bit_fp_mode() const { return _in_24_bit_fp_mode; } +#endif // IA32 }; #endif // SHARE_OPTO_COMPILE_HPP diff --git a/src/hotspot/share/opto/divnode.cpp b/src/hotspot/share/opto/divnode.cpp index d56cf9a2f7a..968b1ddd5f3 100644 --- a/src/hotspot/share/opto/divnode.cpp +++ b/src/hotspot/share/opto/divnode.cpp @@ -34,6 +34,7 @@ #include "opto/mulnode.hpp" #include "opto/phaseX.hpp" #include "opto/subnode.hpp" +#include "utilities/powerOfTwo.hpp" // Portions of code courtesy of Clifford Click @@ -359,7 +360,7 @@ static Node *transform_long_divide( PhaseGVN *phase, Node *dividend, jlong divis // Just negate the value q = new SubLNode(phase->longcon(0), dividend); } - } else if ( is_power_of_2_long(d) ) { + } else if ( is_power_of_2(d) ) { // division by +/- a power of 2 @@ -377,7 +378,7 @@ static Node *transform_long_divide( PhaseGVN *phase, Node *dividend, jlong divis const TypeLong *andconl_t = phase->type( dividend->in(2) )->isa_long(); if( andconl_t && andconl_t->is_con() ) { jlong andconl = andconl_t->get_con(); - if( andconl < 0 && is_power_of_2_long(-andconl) && (-andconl) >= d ) { + if( andconl < 0 && is_power_of_2(-andconl) && (-andconl) >= d ) { if( (-andconl) == d ) // Remove AND if it clears bits which will be shifted dividend = dividend->in(1); needs_rounding = false; @@ -1044,7 +1045,7 @@ Node *ModLNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node *hook = new Node(1); // Expand mod - if( con >= 0 && con < max_jlong && is_power_of_2_long(con+1) ) { + if( con >= 0 && con < max_jlong && is_power_of_2(con+1) ) { uint k = exact_log2_long(con+1); // Extract k // Basic algorithm by David Detlefs. See fastmod_long.java for gory details. @@ -1108,7 +1109,7 @@ Node *ModLNode::Ideal(PhaseGVN *phase, bool can_reshape) { int log2_con = -1; // If this is a power of two, then maybe we can mask it - if( is_power_of_2_long(pos_con) ) { + if( is_power_of_2(pos_con) ) { log2_con = exact_log2_long(pos_con); const Type *dt = phase->type(in(1)); diff --git a/src/hotspot/share/opto/doCall.cpp b/src/hotspot/share/opto/doCall.cpp index 44ab387ac86..c26dc4b682d 100644 --- a/src/hotspot/share/opto/doCall.cpp +++ b/src/hotspot/share/opto/doCall.cpp @@ -150,8 +150,9 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool return cg; } - // Do not inline strict fp into non-strict code, or the reverse - if (caller->is_strict() ^ callee->is_strict()) { + // If explicit rounding is required, do not inline strict into non-strict code (or the reverse). + if (Matcher::strict_fp_requires_explicit_rounding && + caller->is_strict() != callee->is_strict()) { allow_inline = false; } diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index f425814cf9a..006c4509cb7 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -3199,6 +3199,7 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist, op == Op_FastLock || op == Op_AryEq || op == Op_StrComp || op == Op_HasNegatives || op == Op_StrCompressedCopy || op == Op_StrInflatedCopy || op == Op_StrEquals || op == Op_StrIndexOf || op == Op_StrIndexOfChar || + op == Op_SubTypeCheck || BarrierSet::barrier_set()->barrier_set_c2()->is_gc_barrier_node(use))) { n->dump(); use->dump(); diff --git a/src/hotspot/share/opto/gcm.cpp b/src/hotspot/share/opto/gcm.cpp index 68a7f507e12..aebf8f9ca14 100644 --- a/src/hotspot/share/opto/gcm.cpp +++ b/src/hotspot/share/opto/gcm.cpp @@ -103,11 +103,14 @@ void PhaseCFG::replace_block_proj_ctrl( Node *n ) { } bool PhaseCFG::is_dominator(Node* dom_node, Node* node) { + assert(is_CFG(node) && is_CFG(dom_node), "node and dom_node must be CFG nodes"); if (dom_node == node) { return true; } - Block* d = get_block_for_node(dom_node); - Block* n = get_block_for_node(node); + Block* d = find_block_for_node(dom_node); + Block* n = find_block_for_node(node); + assert(n != NULL && d != NULL, "blocks must exist"); + if (d == n) { if (dom_node->is_block_start()) { return true; @@ -121,21 +124,74 @@ bool PhaseCFG::is_dominator(Node* dom_node, Node* node) { if (node->is_block_proj()) { return true; } + + assert(is_control_proj_or_safepoint(node), "node must be control projection or safepoint"); + assert(is_control_proj_or_safepoint(dom_node), "dom_node must be control projection or safepoint"); + + // Neither 'node' nor 'dom_node' is a block start or block projection. + // Check if 'dom_node' is above 'node' in the control graph. + if (is_dominating_control(dom_node, node)) { + return true; + } + #ifdef ASSERT - node->dump(); - dom_node->dump(); + // If 'dom_node' does not dominate 'node' then 'node' has to dominate 'dom_node' + if (!is_dominating_control(node, dom_node)) { + node->dump(); + dom_node->dump(); + assert(false, "neither dom_node nor node dominates the other"); + } #endif - fatal("unhandled"); + return false; } return d->dom_lca(n) == d; } +bool PhaseCFG::is_CFG(Node* n) { + return n->is_block_proj() || n->is_block_start() || is_control_proj_or_safepoint(n); +} + +bool PhaseCFG::is_control_proj_or_safepoint(Node* n) { + bool result = (n->is_Mach() && n->as_Mach()->ideal_Opcode() == Op_SafePoint) || (n->is_Proj() && n->as_Proj()->bottom_type() == Type::CONTROL); + assert(!result || (n->is_Mach() && n->as_Mach()->ideal_Opcode() == Op_SafePoint) + || (n->is_Proj() && n->as_Proj()->_con == 0), "If control projection, it must be projection 0"); + return result; +} + +Block* PhaseCFG::find_block_for_node(Node* n) { + if (n->is_block_start() || n->is_block_proj()) { + return get_block_for_node(n); + } else { + // Walk the control graph up if 'n' is not a block start nor a block projection. In this case 'n' must be + // an unmatched control projection or a not yet matched safepoint precedence edge in the middle of a block. + assert(is_control_proj_or_safepoint(n), "must be control projection or safepoint"); + Node* ctrl = n->in(0); + while (!ctrl->is_block_start()) { + ctrl = ctrl->in(0); + } + return get_block_for_node(ctrl); + } +} + +// Walk up the control graph from 'n' and check if 'dom_ctrl' is found. +bool PhaseCFG::is_dominating_control(Node* dom_ctrl, Node* n) { + Node* ctrl = n->in(0); + while (!ctrl->is_block_start()) { + if (ctrl == dom_ctrl) { + return true; + } + ctrl = ctrl->in(0); + } + return false; +} + + //------------------------------schedule_pinned_nodes-------------------------- // Set the basic block for Nodes pinned into blocks void PhaseCFG::schedule_pinned_nodes(VectorSet &visited) { // Allocate node stack of size C->live_nodes()+8 to avoid frequent realloc - GrowableArray spstack(C->live_nodes() + 8); + GrowableArray spstack(C->live_nodes() + 8); spstack.push(_root); while (spstack.is_nonempty()) { Node* node = spstack.pop(); @@ -160,13 +216,9 @@ void PhaseCFG::schedule_pinned_nodes(VectorSet &visited) { for (uint i = node->len()-1; i >= node->req(); i--) { Node* m = node->in(i); if (m == NULL) continue; - // Skip the precedence edge if the test that guarded a CastPP: - // - was optimized out during escape analysis - // (OptimizePtrCompare): the CastPP's control isn't an end of - // block. - // - is moved in the branch of a dominating If: the control of - // the CastPP is then a Region. - if (m->is_block_proj() || m->is_block_start()) { + + // Only process precedence edges that are CFG nodes. Safepoints and control projections can be in the middle of a block + if (is_CFG(m)) { node->rm_prec(i); if (n == NULL) { n = m; @@ -174,6 +226,9 @@ void PhaseCFG::schedule_pinned_nodes(VectorSet &visited) { assert(is_dominator(n, m) || is_dominator(m, n), "one must dominate the other"); n = is_dominator(n, m) ? m : n; } + } else { + assert(node->is_Mach(), "sanity"); + assert(node->as_Mach()->ideal_Opcode() == Op_StoreCM, "must be StoreCM node"); } } if (n != NULL) { @@ -185,7 +240,7 @@ void PhaseCFG::schedule_pinned_nodes(VectorSet &visited) { } // process all inputs that are non NULL - for (int i = node->req() - 1; i >= 0; --i) { + for (int i = node->req()-1; i >= 0; --i) { if (node->in(i) != NULL) { spstack.push(node->in(i)); } @@ -1384,8 +1439,6 @@ void PhaseCFG::global_code_motion() { // ( visited.clear() called in schedule_late()->Node_Backward_Iterator() ) schedule_late(visited, stack); if (C->failing()) { - // schedule_late fails only when graph is incorrect. - assert(!VerifyGraphEdges, "verification should have failed"); return; } diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 697ac80f79d..321b3517bcc 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -41,9 +41,11 @@ #include "opto/parse.hpp" #include "opto/rootnode.hpp" #include "opto/runtime.hpp" +#include "opto/subtypenode.hpp" #include "runtime/deoptimization.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/bitMap.inline.hpp" +#include "utilities/powerOfTwo.hpp" //----------------------------GraphKit----------------------------------------- // Main utility constructor. @@ -2142,22 +2144,6 @@ Node* GraphKit::just_allocated_object(Node* current_control) { } -void GraphKit::round_double_arguments(ciMethod* dest_method) { - // (Note: TypeFunc::make has a cache that makes this fast.) - const TypeFunc* tf = TypeFunc::make(dest_method); - int nargs = tf->domain()->cnt() - TypeFunc::Parms; - for (int j = 0; j < nargs; j++) { - const Type *targ = tf->domain()->field_at(j + TypeFunc::Parms); - if( targ->basic_type() == T_DOUBLE ) { - // If any parameters are doubles, they must be rounded before - // the call, dstore_rounding does gvn.transform - Node *arg = argument(j); - arg = dstore_rounding(arg); - set_argument(j, arg); - } - } -} - /** * Record profiling data exact_kls for Node n with the type system so * that it can propagate it (speculation) @@ -2323,43 +2309,80 @@ void GraphKit::record_profiled_return_for_speculation() { } void GraphKit::round_double_result(ciMethod* dest_method) { - // A non-strict method may return a double value which has an extended - // exponent, but this must not be visible in a caller which is 'strict' - // If a strict caller invokes a non-strict callee, round a double result + if (Matcher::strict_fp_requires_explicit_rounding) { + // If a strict caller invokes a non-strict callee, round a double result. + // A non-strict method may return a double value which has an extended exponent, + // but this must not be visible in a caller which is strict. + BasicType result_type = dest_method->return_type()->basic_type(); + assert(method() != NULL, "must have caller context"); + if( result_type == T_DOUBLE && method()->is_strict() && !dest_method->is_strict() ) { + // Destination method's return value is on top of stack + // dstore_rounding() does gvn.transform + Node *result = pop_pair(); + result = dstore_rounding(result); + push_pair(result); + } + } +} - BasicType result_type = dest_method->return_type()->basic_type(); - assert( method() != NULL, "must have caller context"); - if( result_type == T_DOUBLE && method()->is_strict() && !dest_method->is_strict() ) { - // Destination method's return value is on top of stack - // dstore_rounding() does gvn.transform - Node *result = pop_pair(); - result = dstore_rounding(result); - push_pair(result); +void GraphKit::round_double_arguments(ciMethod* dest_method) { + if (Matcher::strict_fp_requires_explicit_rounding) { + // (Note: TypeFunc::make has a cache that makes this fast.) + const TypeFunc* tf = TypeFunc::make(dest_method); + int nargs = tf->domain()->cnt() - TypeFunc::Parms; + for (int j = 0; j < nargs; j++) { + const Type *targ = tf->domain()->field_at(j + TypeFunc::Parms); + if (targ->basic_type() == T_DOUBLE) { + // If any parameters are doubles, they must be rounded before + // the call, dstore_rounding does gvn.transform + Node *arg = argument(j); + arg = dstore_rounding(arg); + set_argument(j, arg); + } + } } } // rounding for strict float precision conformance Node* GraphKit::precision_rounding(Node* n) { - return UseStrictFP && _method->flags().is_strict() - && UseSSE == 0 && Matcher::strict_fp_requires_explicit_rounding - ? _gvn.transform( new RoundFloatNode(0, n) ) - : n; + if (Matcher::strict_fp_requires_explicit_rounding) { +#ifdef IA32 + if (_method->flags().is_strict() && UseSSE == 0) { + return _gvn.transform(new RoundFloatNode(0, n)); + } +#else + Unimplemented(); +#endif // IA32 + } + return n; } // rounding for strict double precision conformance Node* GraphKit::dprecision_rounding(Node *n) { - return UseStrictFP && _method->flags().is_strict() - && UseSSE <= 1 && Matcher::strict_fp_requires_explicit_rounding - ? _gvn.transform( new RoundDoubleNode(0, n) ) - : n; + if (Matcher::strict_fp_requires_explicit_rounding) { +#ifdef IA32 + if (_method->flags().is_strict() && UseSSE < 2) { + return _gvn.transform(new RoundDoubleNode(0, n)); + } +#else + Unimplemented(); +#endif // IA32 + } + return n; } // rounding for non-strict double stores Node* GraphKit::dstore_rounding(Node* n) { - return Matcher::strict_fp_requires_explicit_rounding - && UseSSE <= 1 - ? _gvn.transform( new RoundDoubleNode(0, n) ) - : n; + if (Matcher::strict_fp_requires_explicit_rounding) { +#ifdef IA32 + if (UseSSE < 2) { + return _gvn.transform(new RoundDoubleNode(0, n)); + } +#else + Unimplemented(); +#endif // IA32 + } + return n; } //============================================================================= @@ -2601,21 +2624,94 @@ void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool sep set_control(norm); } -static IfNode* gen_subtype_check_compare(Node* ctrl, Node* in1, Node* in2, BoolTest::mask test, float p, PhaseGVN* gvn, BasicType bt) { +static IfNode* gen_subtype_check_compare(Node* ctrl, Node* in1, Node* in2, BoolTest::mask test, float p, PhaseGVN& gvn, BasicType bt) { Node* cmp = NULL; switch(bt) { case T_INT: cmp = new CmpINode(in1, in2); break; case T_ADDRESS: cmp = new CmpPNode(in1, in2); break; default: fatal("unexpected comparison type %s", type2name(bt)); } - gvn->transform(cmp); - Node* bol = gvn->transform(new BoolNode(cmp, test)); + gvn.transform(cmp); + Node* bol = gvn.transform(new BoolNode(cmp, test)); IfNode* iff = new IfNode(ctrl, bol, p, COUNT_UNKNOWN); - gvn->transform(iff); - if (!bol->is_Con()) gvn->record_for_igvn(iff); + gvn.transform(iff); + if (!bol->is_Con()) gvn.record_for_igvn(iff); return iff; } +// Find the memory state for the secondary super type cache load when +// a subtype check is expanded at macro expansion time. That field is +// mutable so should not use immutable memory but +// PartialSubtypeCheckNode that might modify it doesn't produce a new +// memory state so bottom memory is the most accurate memory state to +// hook the load with. This follows the implementation used when the +// subtype check is expanded at parse time. +static Node* find_bottom_mem(Node* ctrl, Compile* C) { + const TypePtr* adr_type = TypeKlassPtr::make(TypePtr::NotNull, C->env()->Object_klass(), Type::OffsetBot); + Node_Stack stack(0); + VectorSet seen(Thread::current()->resource_area()); + + Node* c = ctrl; + Node* mem = NULL; + uint iter = 0; + do { + iter++; + assert(iter < C->live_nodes(), "infinite loop"); + if (c->is_Region()) { + for (DUIterator_Fast imax, i = c->fast_outs(imax); i < imax && mem == NULL; i++) { + Node* u = c->fast_out(i); + if (u->is_Phi() && u->bottom_type() == Type::MEMORY && + (u->adr_type() == TypePtr::BOTTOM || u->adr_type() == adr_type)) { + mem = u; + } + } + if (mem == NULL) { + if (!seen.test_set(c->_idx)) { + stack.push(c, 2); + c = c->in(1); + } else { + Node* phi = NULL; + uint idx = 0; + for (;;) { + phi = stack.node(); + idx = stack.index(); + if (idx < phi->req()) { + break; + } + stack.pop(); + } + c = phi->in(idx); + stack.set_index(idx+1); + } + } + } else if (c->is_Proj() && c->in(0)->adr_type() == TypePtr::BOTTOM) { + for (DUIterator_Fast imax, i = c->in(0)->fast_outs(imax); i < imax; i++) { + Node* u = c->in(0)->fast_out(i); + if (u->bottom_type() == Type::MEMORY && u->as_Proj()->_is_io_use == c->as_Proj()->_is_io_use) { + assert(mem == NULL, ""); + mem = u; + } + } + } else if (c->is_CatchProj() && c->in(0)->in(0)->in(0)->adr_type() == TypePtr::BOTTOM) { + Node* call = c->in(0)->in(0)->in(0); + assert(call->is_Call(), "CatchProj with no call?"); + CallProjections projs; + call->as_Call()->extract_projections(&projs, false, false); + if (projs.catchall_memproj == NULL) { + mem = projs.fallthrough_memproj; + } else if (c == projs.fallthrough_catchproj) { + mem = projs.fallthrough_memproj; + } else { + assert(c == projs.catchall_catchproj, "strange control"); + mem = projs.catchall_memproj; + } + } else { + assert(!c->is_Start(), "should stop before start"); + c = c->in(0); + } + } while (mem == NULL); + return mem; +} //-------------------------------gen_subtype_check----------------------------- // Generate a subtyping check. Takes as input the subtype and supertype. @@ -2625,9 +2721,8 @@ static IfNode* gen_subtype_check_compare(Node* ctrl, Node* in1, Node* in2, BoolT // but that's not exposed to the optimizer. This call also doesn't take in an // Object; if you wish to check an Object you need to load the Object's class // prior to coming here. -Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, MergeMemNode* mem, PhaseGVN* gvn) { - Compile* C = gvn->C; - +Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, Node* mem, PhaseGVN& gvn) { + Compile* C = gvn.C; if ((*ctrl)->is_top()) { return C->top(); } @@ -2638,9 +2733,9 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, Me if (subklass == superklass) return C->top(); // false path is dead; no test needed. - if (gvn->type(superklass)->singleton()) { - ciKlass* superk = gvn->type(superklass)->is_klassptr()->klass(); - ciKlass* subk = gvn->type(subklass)->is_klassptr()->klass(); + if (gvn.type(superklass)->singleton()) { + ciKlass* superk = gvn.type(superklass)->is_klassptr()->klass(); + ciKlass* subk = gvn.type(subklass)->is_klassptr()->klass(); // In the common case of an exact superklass, try to fold up the // test before generating code. You may ask, why not just generate @@ -2655,7 +2750,7 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, Me case Compile::SSC_always_false: { Node* always_fail = *ctrl; - *ctrl = gvn->C->top(); + *ctrl = gvn.C->top(); return always_fail; } case Compile::SSC_always_true: @@ -2664,8 +2759,8 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, Me { // Just do a direct pointer compare and be done. IfNode* iff = gen_subtype_check_compare(*ctrl, subklass, superklass, BoolTest::eq, PROB_STATIC_FREQUENT, gvn, T_ADDRESS); - *ctrl = gvn->transform(new IfTrueNode(iff)); - return gvn->transform(new IfFalseNode(iff)); + *ctrl = gvn.transform(new IfTrueNode(iff)); + return gvn.transform(new IfFalseNode(iff)); } case Compile::SSC_full_test: break; @@ -2679,11 +2774,11 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, Me // will always succeed. We could leave a dependency behind to ensure this. // First load the super-klass's check-offset - Node *p1 = gvn->transform(new AddPNode(superklass, superklass, gvn->MakeConX(in_bytes(Klass::super_check_offset_offset())))); - Node* m = mem->memory_at(C->get_alias_index(gvn->type(p1)->is_ptr())); - Node *chk_off = gvn->transform(new LoadINode(NULL, m, p1, gvn->type(p1)->is_ptr(), TypeInt::INT, MemNode::unordered)); + Node *p1 = gvn.transform(new AddPNode(superklass, superklass, gvn.MakeConX(in_bytes(Klass::super_check_offset_offset())))); + Node* m = C->immutable_memory(); + Node *chk_off = gvn.transform(new LoadINode(NULL, m, p1, gvn.type(p1)->is_ptr(), TypeInt::INT, MemNode::unordered)); int cacheoff_con = in_bytes(Klass::secondary_super_cache_offset()); - bool might_be_cache = (gvn->find_int_con(chk_off, cacheoff_con) == cacheoff_con); + bool might_be_cache = (gvn.find_int_con(chk_off, cacheoff_con) == cacheoff_con); // Load from the sub-klass's super-class display list, or a 1-word cache of // the secondary superclass list, or a failing value with a sentinel offset @@ -2693,15 +2788,22 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, Me // klass loads can never produce a NULL). Node *chk_off_X = chk_off; #ifdef _LP64 - chk_off_X = gvn->transform(new ConvI2LNode(chk_off_X)); + chk_off_X = gvn.transform(new ConvI2LNode(chk_off_X)); #endif - Node *p2 = gvn->transform(new AddPNode(subklass,subklass,chk_off_X)); + Node *p2 = gvn.transform(new AddPNode(subklass,subklass,chk_off_X)); // For some types like interfaces the following loadKlass is from a 1-word // cache which is mutable so can't use immutable memory. Other // types load from the super-class display table which is immutable. - m = mem->memory_at(C->get_alias_index(gvn->type(p2)->is_ptr())); - Node *kmem = might_be_cache ? m : C->immutable_memory(); - Node *nkls = gvn->transform(LoadKlassNode::make(*gvn, NULL, kmem, p2, gvn->type(p2)->is_ptr(), TypeKlassPtr::OBJECT_OR_NULL)); + Node *kmem = C->immutable_memory(); + if (might_be_cache) { + assert((C->get_alias_index(TypeKlassPtr::make(TypePtr::NotNull, C->env()->Object_klass(), Type::OffsetBot)) == + C->get_alias_index(gvn.type(p2)->is_ptr())), ""); + if (mem == NULL) { + mem = find_bottom_mem(*ctrl, C); + } + kmem = mem->is_MergeMem() ? mem->as_MergeMem()->memory_at(C->get_alias_index(gvn.type(p2)->is_ptr())) : mem; + } + Node *nkls = gvn.transform(LoadKlassNode::make(gvn, NULL, kmem, p2, gvn.type(p2)->is_ptr(), TypeKlassPtr::OBJECT_OR_NULL)); // Compile speed common case: ARE a subtype and we canNOT fail if( superklass == nkls ) @@ -2711,8 +2813,8 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, Me // time. Test to see if the value loaded just previously from the subklass // is exactly the superklass. IfNode *iff1 = gen_subtype_check_compare(*ctrl, superklass, nkls, BoolTest::eq, PROB_LIKELY(0.83f), gvn, T_ADDRESS); - Node *iftrue1 = gvn->transform( new IfTrueNode (iff1)); - *ctrl = gvn->transform(new IfFalseNode(iff1)); + Node *iftrue1 = gvn.transform( new IfTrueNode (iff1)); + *ctrl = gvn.transform(new IfFalseNode(iff1)); // Compile speed common case: Check for being deterministic right now. If // chk_off is a constant and not equal to cacheoff then we are NOT a @@ -2726,9 +2828,9 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, Me // Gather the various success & failures here RegionNode *r_ok_subtype = new RegionNode(4); - gvn->record_for_igvn(r_ok_subtype); + gvn.record_for_igvn(r_ok_subtype); RegionNode *r_not_subtype = new RegionNode(3); - gvn->record_for_igvn(r_not_subtype); + gvn.record_for_igvn(r_not_subtype); r_ok_subtype->init_req(1, iftrue1); @@ -2737,17 +2839,17 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, Me // check-offset points into the subklass display list or the 1-element // cache. If it points to the display (and NOT the cache) and the display // missed then it's not a subtype. - Node *cacheoff = gvn->intcon(cacheoff_con); + Node *cacheoff = gvn.intcon(cacheoff_con); IfNode *iff2 = gen_subtype_check_compare(*ctrl, chk_off, cacheoff, BoolTest::ne, PROB_LIKELY(0.63f), gvn, T_INT); - r_not_subtype->init_req(1, gvn->transform(new IfTrueNode (iff2))); - *ctrl = gvn->transform(new IfFalseNode(iff2)); + r_not_subtype->init_req(1, gvn.transform(new IfTrueNode (iff2))); + *ctrl = gvn.transform(new IfFalseNode(iff2)); // Check for self. Very rare to get here, but it is taken 1/3 the time. // No performance impact (too rare) but allows sharing of secondary arrays // which has some footprint reduction. IfNode *iff3 = gen_subtype_check_compare(*ctrl, subklass, superklass, BoolTest::eq, PROB_LIKELY(0.36f), gvn, T_ADDRESS); - r_ok_subtype->init_req(2, gvn->transform(new IfTrueNode(iff3))); - *ctrl = gvn->transform(new IfFalseNode(iff3)); + r_ok_subtype->init_req(2, gvn.transform(new IfTrueNode(iff3))); + *ctrl = gvn.transform(new IfFalseNode(iff3)); // -- Roads not taken here: -- // We could also have chosen to perform the self-check at the beginning @@ -2770,16 +2872,38 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, Me // out of line, and it can only improve I-cache density. // The decision to inline or out-of-line this final check is platform // dependent, and is found in the AD file definition of PartialSubtypeCheck. - Node* psc = gvn->transform( + Node* psc = gvn.transform( new PartialSubtypeCheckNode(*ctrl, subklass, superklass)); - IfNode *iff4 = gen_subtype_check_compare(*ctrl, psc, gvn->zerocon(T_OBJECT), BoolTest::ne, PROB_FAIR, gvn, T_ADDRESS); - r_not_subtype->init_req(2, gvn->transform(new IfTrueNode (iff4))); - r_ok_subtype ->init_req(3, gvn->transform(new IfFalseNode(iff4))); + IfNode *iff4 = gen_subtype_check_compare(*ctrl, psc, gvn.zerocon(T_OBJECT), BoolTest::ne, PROB_FAIR, gvn, T_ADDRESS); + r_not_subtype->init_req(2, gvn.transform(new IfTrueNode (iff4))); + r_ok_subtype ->init_req(3, gvn.transform(new IfFalseNode(iff4))); // Return false path; set default control to true path. - *ctrl = gvn->transform(r_ok_subtype); - return gvn->transform(r_not_subtype); + *ctrl = gvn.transform(r_ok_subtype); + return gvn.transform(r_not_subtype); +} + +Node* GraphKit::gen_subtype_check(Node* obj_or_subklass, Node* superklass) { + if (ExpandSubTypeCheckAtParseTime) { + MergeMemNode* mem = merged_memory(); + Node* ctrl = control(); + Node* subklass = obj_or_subklass; + if (!_gvn.type(obj_or_subklass)->isa_klassptr()) { + subklass = load_object_klass(obj_or_subklass); + } + + Node* n = Phase::gen_subtype_check(subklass, superklass, &ctrl, mem, _gvn); + set_control(ctrl); + return n; + } + + const TypePtr* adr_type = TypeKlassPtr::make(TypePtr::NotNull, C->env()->Object_klass(), Type::OffsetBot); + Node* check = _gvn.transform(new SubTypeCheckNode(C, obj_or_subklass, superklass)); + Node* bol = _gvn.transform(new BoolNode(check, BoolTest::eq)); + IfNode* iff = create_and_xform_if(control(), bol, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); + set_control(_gvn.transform(new IfTrueNode(iff))); + return _gvn.transform(new IfFalseNode(iff)); } // Profile-driven exact type check: @@ -2811,10 +2935,9 @@ Node* GraphKit::type_check_receiver(Node* receiver, ciKlass* klass, Node* GraphKit::subtype_check_receiver(Node* receiver, ciKlass* klass, Node** casted_receiver) { const TypeKlassPtr* tklass = TypeKlassPtr::make(klass); - Node* recv_klass = load_object_klass(receiver); Node* want_klass = makecon(tklass); - Node* slow_ctl = gen_subtype_check(recv_klass, want_klass); + Node* slow_ctl = gen_subtype_check(receiver, want_klass); // Cast receiver after successful check const TypeOopPtr* recv_type = tklass->cast_to_exactness(false)->is_klassptr()->as_instance_type(); @@ -3079,11 +3202,8 @@ Node* GraphKit::gen_instanceof(Node* obj, Node* superklass, bool safe_for_replac } } - // Load the object's klass - Node* obj_klass = load_object_klass(not_null_obj); - // Generate the subtype check - Node* not_subtype_ctrl = gen_subtype_check(obj_klass, superklass); + Node* not_subtype_ctrl = gen_subtype_check(not_null_obj, superklass); // Plug in the success path to the general merge in slot 1. region->init_req(_obj_path, control()); @@ -3206,11 +3326,8 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass, } if (cast_obj == NULL) { - // Load the object's klass - Node* obj_klass = load_object_klass(not_null_obj); - // Generate the subtype check - Node* not_subtype_ctrl = gen_subtype_check( obj_klass, superklass ); + Node* not_subtype_ctrl = gen_subtype_check(not_null_obj, superklass ); // Plug in success path into the merge cast_obj = _gvn.transform(new CheckCastPPNode(control(), not_null_obj, toop)); @@ -3219,7 +3336,7 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass, if (not_subtype_ctrl != top()) { // If failure is possible PreserveJVMState pjvms(this); set_control(not_subtype_ctrl); - builtin_throw(Deoptimization::Reason_class_check, obj_klass); + builtin_throw(Deoptimization::Reason_class_check, load_object_klass(not_null_obj)); } } else { (*failure_control) = not_subtype_ctrl; diff --git a/src/hotspot/share/opto/graphKit.hpp b/src/hotspot/share/opto/graphKit.hpp index 2d084554cba..28ef09f45af 100644 --- a/src/hotspot/share/opto/graphKit.hpp +++ b/src/hotspot/share/opto/graphKit.hpp @@ -825,13 +825,7 @@ class GraphKit : public Phase { Node* gen_checkcast( Node *subobj, Node* superkls, Node* *failure_control = NULL ); - Node* gen_subtype_check(Node* subklass, Node* superklass) { - MergeMemNode* mem = merged_memory(); - Node* ctrl = control(); - Node* n = Phase::gen_subtype_check(subklass, superklass, &ctrl, mem, &_gvn); - set_control(ctrl); - return n; - } + Node* gen_subtype_check(Node* obj, Node* superklass); // Exact type check used for predicted calls and casts. // Rewrites (*casted_receiver) to be casted to the stronger type. diff --git a/src/hotspot/share/opto/idealGraphPrinter.cpp b/src/hotspot/share/opto/idealGraphPrinter.cpp index 6a753b7d257..01afd1a914f 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.cpp +++ b/src/hotspot/share/opto/idealGraphPrinter.cpp @@ -664,7 +664,7 @@ void IdealGraphPrinter::print_method(const char *name, int level) { // Print current ideal graph void IdealGraphPrinter::print(const char *name, Node *node) { - if (!_current_method || !_should_send_method) return; + if (!_current_method || !_should_send_method || node == NULL) return; // Warning, unsafe cast? _chaitin = (PhaseChaitin *)C->regalloc(); diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index da5f22c32df..d23fc03f465 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -58,7 +58,7 @@ #include "runtime/objectMonitor.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/macros.hpp" - +#include "utilities/powerOfTwo.hpp" class LibraryIntrinsic : public InlineCallGenerator { // Extend the set of intrinsics known to the runtime: @@ -1785,8 +1785,15 @@ bool LibraryCallKit::inline_string_char_access(bool is_store) { //--------------------------round_double_node-------------------------------- // Round a double node if necessary. Node* LibraryCallKit::round_double_node(Node* n) { - if (Matcher::strict_fp_requires_explicit_rounding && UseSSE <= 1) - n = _gvn.transform(new RoundDoubleNode(0, n)); + if (Matcher::strict_fp_requires_explicit_rounding) { +#ifdef IA32 + if (UseSSE < 2) { + n = _gvn.transform(new RoundDoubleNode(NULL, n)); + } +#else + Unimplemented(); +#endif // IA32 + } return n; } @@ -3692,8 +3699,7 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { // Reason_class_check rather than Reason_intrinsic because we // want to intrinsify even if this traps. if (!too_many_traps(Deoptimization::Reason_class_check)) { - Node* not_subtype_ctrl = gen_subtype_check(load_object_klass(original), - klass_node); + Node* not_subtype_ctrl = gen_subtype_check(original, klass_node); if (not_subtype_ctrl != top()) { PreserveJVMState pjvms(this); @@ -4759,16 +4765,17 @@ bool LibraryCallKit::inline_arraycopy() { } // (9) each element of an oop array must be assignable - Node* src_klass = load_object_klass(src); Node* dest_klass = load_object_klass(dest); - Node* not_subtype_ctrl = gen_subtype_check(src_klass, dest_klass); + if (src != dest) { + Node* not_subtype_ctrl = gen_subtype_check(src, dest_klass); - if (not_subtype_ctrl != top()) { - PreserveJVMState pjvms(this); - set_control(not_subtype_ctrl); - uncommon_trap(Deoptimization::Reason_intrinsic, - Deoptimization::Action_make_not_entrant); - assert(stopped(), "Should be stopped"); + if (not_subtype_ctrl != top()) { + PreserveJVMState pjvms(this); + set_control(not_subtype_ctrl); + uncommon_trap(Deoptimization::Reason_intrinsic, + Deoptimization::Action_make_not_entrant); + assert(stopped(), "Should be stopped"); + } } { PreserveJVMState pjvms(this); @@ -4845,8 +4852,6 @@ LibraryCallKit::tightly_coupled_allocation(Node* ptr, // This arraycopy must unconditionally follow the allocation of the ptr. Node* alloc_ctl = ptr->in(0); - assert(just_allocated_object(alloc_ctl) == ptr, "most recent allo"); - Node* ctl = control(); while (ctl != alloc_ctl) { // There may be guards which feed into the slow_region. diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index ce122b32702..9e325b38c95 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -40,6 +40,7 @@ #include "opto/mulnode.hpp" #include "opto/rootnode.hpp" #include "opto/superword.hpp" +#include "utilities/powerOfTwo.hpp" //============================================================================= //--------------------------is_cloop_ind_var----------------------------------- @@ -4088,7 +4089,7 @@ Node *PhaseIdealLoop::get_late_ctrl( Node *n, Node *early ) { } } else { Node *sctrl = has_ctrl(s) ? get_ctrl(s) : s->in(0); - assert(sctrl != NULL || s->outcnt() == 0, "must have control"); + assert(sctrl != NULL || !s->is_reachable_from_root(), "must have control"); if (sctrl != NULL && !sctrl->is_top() && C->can_alias(s->adr_type(), load_alias_idx) && is_dominator(early, sctrl)) { LCA = dom_lca_for_get_late_ctrl(LCA, sctrl, n); } diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index 98c5d395e40..8f10f8d48a3 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -40,6 +40,7 @@ #include "opto/opaquenode.hpp" #include "opto/rootnode.hpp" #include "opto/subnode.hpp" +#include "opto/subtypenode.hpp" #include "utilities/macros.hpp" //============================================================================= @@ -656,6 +657,9 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) { } assert(bol->Opcode() == Op_Bool, "Unexpected node"); int cmp_op = bol->in(1)->Opcode(); + if (cmp_op == Op_SubTypeCheck) { // SubTypeCheck expansion expects an IfNode + return NULL; + } // It is expensive to generate flags from a float compare. // Avoid duplicated float compare. if (phis > 1 && (cmp_op == Op_CmpF || cmp_op == Op_CmpD)) return NULL; @@ -898,6 +902,7 @@ void PhaseIdealLoop::try_move_store_after_loop(Node* n) { // Move the store out of the loop if the LCA of all // users (except for the phi) is outside the loop. Node* hook = new Node(1); + hook->init_req(0, n_ctrl); // Add an input to prevent hook from being dead _igvn.rehash_node_delayed(phi); int count = phi->replace_edge(n, hook); assert(count > 0, "inconsistent phi"); diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index 0c4bc3fb4be..9e7a030a794 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -35,6 +35,7 @@ #include "opto/compile.hpp" #include "opto/convertnode.hpp" #include "opto/graphKit.hpp" +#include "opto/intrinsicnode.hpp" #include "opto/locknode.hpp" #include "opto/loopnode.hpp" #include "opto/macro.hpp" @@ -46,9 +47,11 @@ #include "opto/rootnode.hpp" #include "opto/runtime.hpp" #include "opto/subnode.hpp" +#include "opto/subtypenode.hpp" #include "opto/type.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #if INCLUDE_G1GC #include "gc/g1/g1ThreadLocalData.hpp" #endif // INCLUDE_G1GC @@ -1331,14 +1334,23 @@ void PhaseMacroExpand::expand_allocate_common( if (!allocation_has_use) { InitializeNode* init = alloc->initialization(); if (init != NULL) { - yank_initalize_node(init); - assert(init->outcnt() == 0, "all uses must be deleted"); - _igvn.remove_dead_node(init); + init->remove(&_igvn); } if (expand_fast_path && (initial_slow_test == NULL)) { // Remove allocation node and return. // Size is a non-negative constant -> no initial check needed -> directly to fast path. // Also, no usages -> empty fast path -> no fall out to slow path -> nothing left. +#ifndef PRODUCT + if (PrintEliminateAllocations) { + tty->print("NotUsed "); + Node* res = alloc->proj_out_or_null(TypeFunc::Parms); + if (res != NULL) { + res->dump(); + } else { + alloc->dump(); + } + } +#endif yank_alloc_node(alloc); return; } @@ -1576,6 +1588,16 @@ void PhaseMacroExpand::yank_alloc_node(AllocateNode* alloc) { Node* i_o = alloc->in(TypeFunc::I_O); extract_call_projections(alloc); + if (_resproj != NULL) { + for (DUIterator_Fast imax, i = _resproj->fast_outs(imax); i < imax; i++) { + Node* use = _resproj->fast_out(i); + use->isa_MemBar()->remove(&_igvn); + --imax; + --i; // back up iterator + } + assert(_resproj->outcnt() == 0, "all uses must be deleted"); + _igvn.remove_dead_node(_resproj); + } if (_fallthroughcatchproj != NULL) { migrate_outs(_fallthroughcatchproj, ctrl); _igvn.remove_dead_node(_fallthroughcatchproj); @@ -1605,6 +1627,15 @@ void PhaseMacroExpand::yank_alloc_node(AllocateNode* alloc) { _igvn.rehash_node_delayed(_ioproj_catchall); _ioproj_catchall->set_req(0, top()); } +#ifndef PRODUCT + if (PrintEliminateAllocations) { + if (alloc->is_AllocateArray()) { + tty->print_cr("++++ Eliminated: %d AllocateArray", alloc->_idx); + } else { + tty->print_cr("++++ Eliminated: %d Allocate", alloc->_idx); + } + } +#endif _igvn.remove_dead_node(alloc); } @@ -1709,26 +1740,6 @@ void PhaseMacroExpand::expand_dtrace_alloc_probe(AllocateNode* alloc, Node* oop, } } -// Remove InitializeNode without use -void PhaseMacroExpand::yank_initalize_node(InitializeNode* initnode) { - assert(initnode->proj_out_or_null(TypeFunc::Parms) == NULL, "No uses allowed"); - - Node* ctrl_out = initnode->proj_out_or_null(TypeFunc::Control); - Node* mem_out = initnode->proj_out_or_null(TypeFunc::Memory); - - // Move all uses of each to - if (ctrl_out != NULL ) { - migrate_outs(ctrl_out, initnode->in(TypeFunc::Control)); - _igvn.remove_dead_node(ctrl_out); - } - - // Move all uses of each to - if (mem_out != NULL ) { - migrate_outs(mem_out, initnode->in(TypeFunc::Memory)); - _igvn.remove_dead_node(mem_out); - } -} - // Helper for PhaseMacroExpand::expand_allocate_common. // Initializes the newly-allocated storage. Node* @@ -2532,6 +2543,43 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) { _igvn.replace_node(_memproj_fallthrough, mem_phi); } +void PhaseMacroExpand::expand_subtypecheck_node(SubTypeCheckNode *check) { + assert(check->in(SubTypeCheckNode::Control) == NULL, "should be pinned"); + Node* bol = check->unique_out(); + Node* obj_or_subklass = check->in(SubTypeCheckNode::ObjOrSubKlass); + Node* superklass = check->in(SubTypeCheckNode::SuperKlass); + assert(bol->is_Bool() && bol->as_Bool()->_test._test == BoolTest::ne, "unexpected bool node"); + + for (DUIterator_Last imin, i = bol->last_outs(imin); i >= imin; --i) { + Node* iff = bol->last_out(i); + assert(iff->is_If(), "where's the if?"); + + if (iff->in(0)->is_top()) { + _igvn.replace_input_of(iff, 1, C->top()); + continue; + } + + Node* iftrue = iff->as_If()->proj_out(1); + Node* iffalse = iff->as_If()->proj_out(0); + Node* ctrl = iff->in(0); + + Node* subklass = NULL; + if (_igvn.type(obj_or_subklass)->isa_klassptr()) { + subklass = obj_or_subklass; + } else { + Node* k_adr = basic_plus_adr(obj_or_subklass, oopDesc::klass_offset_in_bytes()); + subklass = _igvn.transform(LoadKlassNode::make(_igvn, NULL, C->immutable_memory(), k_adr, TypeInstPtr::KLASS)); + } + + Node* not_subtype_ctrl = Phase::gen_subtype_check(subklass, superklass, &ctrl, NULL, _igvn); + + _igvn.replace_input_of(iff, 0, C->top()); + _igvn.replace_node(iftrue, not_subtype_ctrl); + _igvn.replace_node(iffalse, ctrl); + } + _igvn.replace_node(check, C->top()); +} + //---------------------------eliminate_macro_nodes---------------------- // Eliminate scalar replaced allocations and associated locks. void PhaseMacroExpand::eliminate_macro_nodes() { @@ -2588,6 +2636,8 @@ void PhaseMacroExpand::eliminate_macro_nodes() { break; case Node::Class_OuterStripMinedLoop: break; + case Node::Class_SubTypeCheck: + break; default: assert(n->Opcode() == Op_LoopLimit || n->Opcode() == Op_Opaque1 || @@ -2694,6 +2744,10 @@ bool PhaseMacroExpand::expand_macro_nodes() { expand_arraycopy_node(n->as_ArrayCopy()); assert(C->macro_count() == (old_macro_count - 1), "expansion must have deleted one node from macro list"); break; + case Node::Class_SubTypeCheck: + expand_subtypecheck_node(n->as_SubTypeCheck()); + assert(C->macro_count() == (old_macro_count - 1), "expansion must have deleted one node from macro list"); + break; } if (C->failing()) return true; } diff --git a/src/hotspot/share/opto/macro.hpp b/src/hotspot/share/opto/macro.hpp index 4ac5d6ed244..7171c05c866 100644 --- a/src/hotspot/share/opto/macro.hpp +++ b/src/hotspot/share/opto/macro.hpp @@ -30,6 +30,7 @@ class AllocateNode; class AllocateArrayNode; class CallNode; +class SubTypeCheckNode; class Node; class PhaseIterGVN; @@ -183,6 +184,8 @@ private: void expand_arraycopy_node(ArrayCopyNode *ac); + void expand_subtypecheck_node(SubTypeCheckNode *check); + int replace_input(Node *use, Node *oldref, Node *newref); void migrate_outs(Node *old, Node *target); void copy_call_debug_info(CallNode *oldcall, CallNode * newcall); diff --git a/src/hotspot/share/opto/macroArrayCopy.cpp b/src/hotspot/share/opto/macroArrayCopy.cpp index 7eaedc6d6ca..8706563ff38 100644 --- a/src/hotspot/share/opto/macroArrayCopy.cpp +++ b/src/hotspot/share/opto/macroArrayCopy.cpp @@ -31,7 +31,7 @@ #include "opto/macro.hpp" #include "opto/runtime.hpp" #include "utilities/align.hpp" - +#include "utilities/powerOfTwo.hpp" void PhaseMacroExpand::insert_mem_bar(Node** ctrl, Node** mem, int opcode, Node* precedent) { MemBarNode* mb = MemBarNode::make(C, opcode, Compile::AliasIdxBot, precedent); @@ -524,7 +524,7 @@ Node* PhaseMacroExpand::generate_arraycopy(ArrayCopyNode *ac, AllocateArrayNode* // Test S[] against D[], not S against D, because (probably) // the secondary supertype cache is less busy for S[] than S. // This usually only matters when D is an interface. - Node* not_subtype_ctrl = Phase::gen_subtype_check(src_klass, dest_klass, ctrl, mem, &_igvn); + Node* not_subtype_ctrl = Phase::gen_subtype_check(src_klass, dest_klass, ctrl, mem, _igvn); // Plug failing path into checked_oop_disjoint_arraycopy if (not_subtype_ctrl != top()) { Node* local_ctrl = not_subtype_ctrl; diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index 5e89a5b3940..4ec6b3fb290 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -2010,6 +2010,15 @@ bool Matcher::is_bmi_pattern(Node *n, Node *m) { } #endif // X86 +bool Matcher::is_vshift_con_pattern(Node *n, Node *m) { + if (n != NULL && m != NULL) { + return VectorNode::is_vector_shift(n) && + VectorNode::is_vector_shift_count(m) && m->in(1)->is_Con(); + } + return false; +} + + bool Matcher::clone_base_plus_offset_address(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) { Node *off = m->in(AddPNode::Offset); if (off->is_Con()) { @@ -2090,6 +2099,10 @@ void Matcher::find_shared( Node *n ) { continue; } #endif + if (is_vshift_con_pattern(n, m)) { + mstack.push(m, Visit); + continue; + } // Clone addressing expressions as they are "free" in memory access instructions if (mem_op && i == mem_addr_idx && mop == Op_AddP && @@ -2525,22 +2538,16 @@ void Matcher::do_postselect_cleanup() { //---------------------------------------------------------------------- // Convert (leg)Vec to (leg)Vec[SDXYZ]. -MachOper* Matcher::specialize_vector_operand_helper(MachNode* m, uint opnd_idx, const Type* t) { +MachOper* Matcher::specialize_vector_operand_helper(MachNode* m, uint opnd_idx, const TypeVect* vt) { MachOper* original_opnd = m->_opnds[opnd_idx]; - uint ideal_reg = t->ideal_reg(); + uint ideal_reg = vt->ideal_reg(); // Handle special cases. - if (t->isa_vect()) { - // LShiftCntV/RShiftCntV report wide vector type, but Matcher::vector_shift_count_ideal_reg() as ideal register (see vectornode.hpp). - // Look for shift count use sites as well (at vector shift nodes). - int opc = m->ideal_Opcode(); - if ((VectorNode::is_shift_count(opc) && opnd_idx == 0) || // DEF operand of LShiftCntV/RShiftCntV - (VectorNode::is_vector_shift(opc) && opnd_idx == 2)) { // shift operand of a vector shift node - ideal_reg = Matcher::vector_shift_count_ideal_reg(t->is_vect()->length_in_bytes()); - } - } else { - // Chain instructions which convert scalar to vector (e.g., vshiftcntimm on x86) don't have vector type. - int size_in_bytes = 4 * type2size[t->basic_type()]; - ideal_reg = Matcher::vector_ideal_reg(size_in_bytes); + // LShiftCntV/RShiftCntV report wide vector type, but Matcher::vector_shift_count_ideal_reg() as ideal register (see vectornode.hpp). + // Look for shift count use sites as well (at vector shift nodes). + int opc = m->ideal_Opcode(); + if ((VectorNode::is_vector_shift_count(opc) && opnd_idx == 0) || // DEF operand of LShiftCntV/RShiftCntV + (VectorNode::is_vector_shift(opc) && opnd_idx == 2)) { // shift operand of a vector shift node + ideal_reg = Matcher::vector_shift_count_ideal_reg(vt->length_in_bytes()); } return Matcher::specialize_generic_vector_operand(original_opnd, ideal_reg, false); } @@ -2575,7 +2582,7 @@ MachOper* Matcher::specialize_vector_operand(MachNode* m, uint opnd_idx) { } } } - return specialize_vector_operand_helper(m, opnd_idx, def->bottom_type()); + return specialize_vector_operand_helper(m, opnd_idx, def->bottom_type()->is_vect()); } void Matcher::specialize_mach_node(MachNode* m) { diff --git a/src/hotspot/share/opto/matcher.hpp b/src/hotspot/share/opto/matcher.hpp index 1b6125021d2..aa94d674601 100644 --- a/src/hotspot/share/opto/matcher.hpp +++ b/src/hotspot/share/opto/matcher.hpp @@ -125,6 +125,8 @@ private: bool is_bmi_pattern(Node *n, Node *m); #endif + bool is_vshift_con_pattern(Node *n, Node *m); + // Debug and profile information for nodes in old space: GrowableArray* _old_node_note_array; @@ -517,7 +519,7 @@ public: void specialize_mach_node(MachNode* m); void specialize_temp_node(MachTempNode* tmp, MachNode* use, uint idx); MachOper* specialize_vector_operand(MachNode* m, uint opnd_idx); - MachOper* specialize_vector_operand_helper(MachNode* m, uint opnd_idx, const Type* t); + MachOper* specialize_vector_operand_helper(MachNode* m, uint opnd_idx, const TypeVect* vt); static MachOper* specialize_generic_vector_operand(MachOper* generic_opnd, uint ideal_reg, bool is_temp); @@ -534,8 +536,7 @@ public: // on windows95 to take care of some unusual register constraints. void pd_implicit_null_fixup(MachNode *load, uint idx); - // Advertise here if the CPU requires explicit rounding operations - // to implement the UseStrictFP mode. + // Advertise here if the CPU requires explicit rounding operations to implement strictfp mode. static const bool strict_fp_requires_explicit_rounding; // Are floats conerted to double when stored to stack during deoptimization? diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index c7b44a1b22d..3a308b279fc 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -48,6 +48,7 @@ #include "utilities/align.hpp" #include "utilities/copy.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #include "utilities/vmError.hpp" // Portions of code courtesy of Clifford Click @@ -1483,14 +1484,20 @@ Node *LoadNode::split_through_phi(PhaseGVN *phase) { for (uint i = 1; i < region->req(); i++) { Node* x; Node* the_clone = NULL; - if (region->in(i) == C->top()) { + Node* in = region->in(i); + if (region->is_CountedLoop() && region->as_Loop()->is_strip_mined() && i == LoopNode::EntryControl && + in != NULL && in->is_OuterStripMinedLoop()) { + // No node should go in the outer strip mined loop + in = in->in(LoopNode::EntryControl); + } + if (in == NULL || in == 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. // Alter data node to use pre-phi inputs if (this->in(0) == region) { - x->set_req(0, region->in(i)); + x->set_req(0, in); } else { x->set_req(0, NULL); } diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp index 691e0f5a8ef..441430c2504 100644 --- a/src/hotspot/share/opto/mulnode.cpp +++ b/src/hotspot/share/opto/mulnode.cpp @@ -31,6 +31,7 @@ #include "opto/mulnode.hpp" #include "opto/phaseX.hpp" #include "opto/subnode.hpp" +#include "utilities/powerOfTwo.hpp" // Portions of code courtesy of Clifford Click @@ -306,7 +307,7 @@ Node *MulLNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node *n2 = phase->transform(new LShiftLNode(in(1), phase->intcon(log2_long(bit2)))); res = new AddLNode(n2, n1); - } else if (is_power_of_2_long(abs_con+1)) { + } else if (is_power_of_2(abs_con+1)) { // Sleezy: power-of-2 -1. Next time be generic. julong temp = abs_con + 1; Node *n1 = phase->transform( new LShiftLNode(in(1), phase->intcon(log2_long(temp)))); @@ -1409,4 +1410,3 @@ const Type* FmaFNode::Value(PhaseGVN* phase) const { uint MulAddS2INode::hash() const { return (uintptr_t)in(1) + (uintptr_t)in(2) + (uintptr_t)in(3) + (uintptr_t)in(4) + Opcode(); } - diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp index eb1d4fbd161..06cb2761a8d 100644 --- a/src/hotspot/share/opto/node.cpp +++ b/src/hotspot/share/opto/node.cpp @@ -2123,7 +2123,8 @@ void Node::verify_edges(Unique_Node_List &visited) { } assert( cnt == 0,"Mismatched edge count."); } else if (n == NULL) { - assert(i >= req() || i == 0 || is_Region() || is_Phi(), "only regions or phis have null data edges"); + assert(i >= req() || i == 0 || is_Region() || is_Phi() || is_ArrayCopy() + || (is_Unlock() && i == req()-1), "only region, phi, arraycopy or unlock nodes have null data edges"); } else { assert(n->is_top(), "sanity"); // Nothing to check. @@ -2137,9 +2138,6 @@ void Node::verify_edges(Unique_Node_List &visited) { } } -//------------------------------verify_recur----------------------------------- -static const Node *unique_top = NULL; - void Node::verify_recur(const Node *n, int verify_depth, VectorSet &old_space, VectorSet &new_space) { if ( verify_depth == 0 ) return; diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index af0e8354787..6d05eefe62e 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -146,6 +146,7 @@ class StartNode; class State; class StoreNode; class SubNode; +class SubTypeCheckNode; class Type; class TypeNode; class UnlockNode; @@ -706,6 +707,7 @@ public: DEFINE_CLASS_ID(Cmp, Sub, 0) DEFINE_CLASS_ID(FastLock, Cmp, 0) DEFINE_CLASS_ID(FastUnlock, Cmp, 1) + DEFINE_CLASS_ID(SubTypeCheck,Cmp, 2) DEFINE_CLASS_ID(MergeMem, Node, 7) DEFINE_CLASS_ID(Bool, Node, 8) @@ -738,7 +740,8 @@ public: Flag_is_scheduled = Flag_is_reduction << 1, Flag_has_vector_mask_set = Flag_is_scheduled << 1, Flag_is_expensive = Flag_has_vector_mask_set << 1, - _max_flags = (Flag_is_expensive << 1) - 1 // allow flags combination + Flag_intel_jcc_erratum = Flag_is_expensive << 1, + _max_flags = (Flag_intel_jcc_erratum << 1) - 1 // allow flags combination }; private: @@ -750,11 +753,11 @@ protected: void init_class_id(jushort c) { _class_id = c; // cast out const } - void init_flags(jushort fl) { + void init_flags(uint fl) { assert(fl <= _max_flags, "invalid node flag"); _flags |= fl; } - void clear_flag(jushort fl) { + void clear_flag(uint fl) { assert(fl <= _max_flags, "invalid node flag"); _flags &= ~fl; } @@ -875,6 +878,7 @@ public: DEFINE_CLASS_QUERY(Start) DEFINE_CLASS_QUERY(Store) DEFINE_CLASS_QUERY(Sub) + DEFINE_CLASS_QUERY(SubTypeCheck) DEFINE_CLASS_QUERY(Type) DEFINE_CLASS_QUERY(Vector) DEFINE_CLASS_QUERY(LoadVector) diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp index 0205b1cc324..d0b39a098bf 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,12 @@ #include "opto/subnode.hpp" #include "opto/type.hpp" #include "runtime/handles.inline.hpp" +#include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #include "utilities/xmlstream.hpp" +#ifdef X86 +#include "c2_intelJccErratum_x86.hpp" +#endif #ifndef PRODUCT #define DEBUG_ARG(x) , x @@ -140,6 +145,13 @@ void Compile::Output() { BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); bs->late_barrier_analysis(); +#ifdef X86 + if (VM_Version::has_intel_jcc_erratum()) { + int extra_padding = IntelJccErratum::tag_affected_machnodes(this, _cfg, _regalloc); + buf_sizes._code += extra_padding; + } +#endif + // Complete sizing of codebuffer CodeBuffer* cb = init_buffer(buf_sizes); if (cb == NULL || failing()) { @@ -278,6 +290,13 @@ void Compile::shorten_branches(uint* blk_starts, BufferSizingData& buf_sizes) { if (nj->is_Mach()) { MachNode *mach = nj->as_Mach(); blk_size += (mach->alignment_required() - 1) * relocInfo::addr_unit(); // assume worst case padding +#ifdef X86 + if (VM_Version::has_intel_jcc_erratum() && IntelJccErratum::is_jcc_erratum_branch(block, mach, j)) { + // Conservatively add worst case padding + blk_size += IntelJccErratum::largest_jcc_size(); + } +#endif + reloc_size += mach->reloc(); if (mach->is_MachCall()) { // add size information for trampoline stub @@ -1222,6 +1241,12 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) { // Avoid back to back some instructions. padding = nop_size; } +#ifdef X86 + if (mach->flags() & Node::Flag_intel_jcc_erratum) { + assert(padding == 0, "can't have contradicting padding requirements"); + padding = IntelJccErratum::compute_padding(current_offset, mach, block, j, _regalloc); + } +#endif if (padding > 0) { assert((padding % nop_size) == 0, "padding is not a multiple of NOP size"); diff --git a/src/hotspot/share/opto/parse.hpp b/src/hotspot/share/opto/parse.hpp index ee27d4fb9a8..28e440f5861 100644 --- a/src/hotspot/share/opto/parse.hpp +++ b/src/hotspot/share/opto/parse.hpp @@ -480,7 +480,7 @@ class Parse : public GraphKit { // Helper function to generate array store void array_store(BasicType etype); // Helper function to compute array addressing - Node* array_addressing(BasicType type, int vals, const Type* *result2=NULL); + Node* array_addressing(BasicType type, int vals, const Type*& elemtype); void clinit_deopt(); diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp index f967a6ccb7a..962f962e81d 100644 --- a/src/hotspot/share/opto/parse2.cpp +++ b/src/hotspot/share/opto/parse2.cpp @@ -54,7 +54,7 @@ extern int explicit_null_checks_inserted, void Parse::array_load(BasicType bt) { const Type* elemtype = Type::TOP; bool big_val = bt == T_DOUBLE || bt == T_LONG; - Node* adr = array_addressing(bt, 0, &elemtype); + Node* adr = array_addressing(bt, 0, elemtype); if (stopped()) return; // guaranteed null or range check pop(); // index (already used) @@ -62,10 +62,7 @@ void Parse::array_load(BasicType bt) { if (elemtype == TypeInt::BOOL) { bt = T_BOOLEAN; - } else if (bt == T_OBJECT) { - elemtype = _gvn.type(array)->is_aryptr()->elem()->make_oopptr(); } - const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(bt); Node* ld = access_load_at(array, adr, adr_type, elemtype, bt, @@ -82,7 +79,7 @@ void Parse::array_load(BasicType bt) { void Parse::array_store(BasicType bt) { const Type* elemtype = Type::TOP; bool big_val = bt == T_DOUBLE || bt == T_LONG; - Node* adr = array_addressing(bt, big_val ? 2 : 1, &elemtype); + Node* adr = array_addressing(bt, big_val ? 2 : 1, elemtype); if (stopped()) return; // guaranteed null or range check if (bt == T_OBJECT) { array_store_check(); @@ -98,10 +95,7 @@ void Parse::array_store(BasicType bt) { if (elemtype == TypeInt::BOOL) { bt = T_BOOLEAN; - } else if (bt == T_OBJECT) { - elemtype = _gvn.type(array)->is_aryptr()->elem()->make_oopptr(); } - const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(bt); access_store_at(array, adr, adr_type, val, elemtype, bt, MO_UNORDERED | IN_HEAP | IS_ARRAY); @@ -110,7 +104,7 @@ void Parse::array_store(BasicType bt) { //------------------------------array_addressing------------------------------- // Pull array and index from the stack. Compute pointer-to-element. -Node* Parse::array_addressing(BasicType type, int vals, const Type* *result2) { +Node* Parse::array_addressing(BasicType type, int vals, const Type*& elemtype) { Node *idx = peek(0+vals); // Get from stack without popping Node *ary = peek(1+vals); // in case of exception @@ -121,9 +115,9 @@ Node* Parse::array_addressing(BasicType type, int vals, const Type* *result2) { const TypeAryPtr* arytype = _gvn.type(ary)->is_aryptr(); const TypeInt* sizetype = arytype->size(); - const Type* elemtype = arytype->elem(); + elemtype = arytype->elem(); - if (UseUniqueSubclasses && result2 != NULL) { + if (UseUniqueSubclasses) { const Type* el = elemtype->make_ptr(); if (el && el->isa_instptr()) { const TypeInstPtr* toop = el->is_instptr(); @@ -207,9 +201,6 @@ Node* Parse::array_addressing(BasicType type, int vals, const Type* *result2) { // Make array address computation control dependent to prevent it // from floating above the range check during loop optimizations. Node* ptr = array_element_address(ary, idx, type, sizetype, control()); - - if (result2 != NULL) *result2 = elemtype; - assert(ptr != top(), "top should go hand-in-hand with stopped"); return ptr; diff --git a/src/hotspot/share/opto/phase.hpp b/src/hotspot/share/opto/phase.hpp index 5285b0fef5b..e10a1030c53 100644 --- a/src/hotspot/share/opto/phase.hpp +++ b/src/hotspot/share/opto/phase.hpp @@ -132,7 +132,7 @@ protected: // Object; if you wish to check an Object you need to load the Object's // class prior to coming here. // Used in GraphKit and PhaseMacroExpand - static Node* gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, MergeMemNode* mem, PhaseGVN* gvn); + static Node* gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, Node* mem, PhaseGVN& gvn); public: Compile * C; diff --git a/src/hotspot/share/opto/regmask.cpp b/src/hotspot/share/opto/regmask.cpp index 94070721f58..5b2de6cf718 100644 --- a/src/hotspot/share/opto/regmask.cpp +++ b/src/hotspot/share/opto/regmask.cpp @@ -29,6 +29,7 @@ #include "opto/node.hpp" #include "opto/regmask.hpp" #include "utilities/population_count.hpp" +#include "utilities/powerOfTwo.hpp" #define RM_SIZE _RM_SIZE /* a constant private to the class RegMask */ diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index daafdcc18a0..c1234dd8a0d 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -1352,7 +1352,7 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node *cmp = in(1); if( !cmp->is_Sub() ) return NULL; int cop = cmp->Opcode(); - if( cop == Op_FastLock || cop == Op_FastUnlock) return NULL; + if( cop == Op_FastLock || cop == Op_FastUnlock || cmp->is_SubTypeCheck()) return NULL; Node *cmp1 = cmp->in(1); Node *cmp2 = cmp->in(2); if( !cmp1 ) return NULL; diff --git a/src/hotspot/share/opto/subtypenode.cpp b/src/hotspot/share/opto/subtypenode.cpp new file mode 100644 index 00000000000..dca77bc5db8 --- /dev/null +++ b/src/hotspot/share/opto/subtypenode.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "opto/addnode.hpp" +#include "opto/connode.hpp" +#include "opto/convertnode.hpp" +#include "opto/phaseX.hpp" +#include "opto/subnode.hpp" +#include "opto/subtypenode.hpp" + +const Type* SubTypeCheckNode::sub(const Type* sub_t, const Type* super_t) const { + ciKlass* superk = super_t->is_klassptr()->klass(); + ciKlass* subk = sub_t->isa_klassptr() ? sub_t->is_klassptr()->klass() : sub_t->is_oopptr()->klass(); + + bool xsuperk = super_t->is_klassptr()->klass_is_exact(); + bool xsubk = sub_t->isa_klassptr() ? sub_t->is_klassptr()->klass_is_exact() : sub_t->is_oopptr()->klass_is_exact(); + + // Similar to logic in CmpPNode::sub() + if (superk && subk && + superk->is_loaded() && !superk->is_interface() && + subk->is_loaded() && !subk->is_interface() && + (!superk->is_obj_array_klass() || + !superk->as_obj_array_klass()->base_element_klass()->is_interface()) && + (!subk->is_obj_array_klass() || + !subk->as_obj_array_klass()->base_element_klass()->is_interface() || + xsubk)) { + bool unrelated_classes = false; + if (superk->equals(subk)) { + // skip + } else if (superk->is_subtype_of(subk)) { + unrelated_classes = xsubk; + } else if (subk->is_subtype_of(superk)) { + // skip + } else { + unrelated_classes = true; + } + if (unrelated_classes) { + TypePtr::PTR jp = sub_t->is_ptr()->join_ptr(super_t->is_ptr()->_ptr); + if (jp != TypePtr::Null && jp != TypePtr::BotPTR) { + return TypeInt::CC_GT; + } + } + } + + if (super_t->singleton()) { + if (subk != NULL) { + switch (Compile::current()->static_subtype_check(superk, subk)) { + case Compile::SSC_always_false: + return TypeInt::CC_GT; + case Compile::SSC_always_true: + return TypeInt::CC_EQ; + case Compile::SSC_easy_test: + case Compile::SSC_full_test: + break; + default: + ShouldNotReachHere(); + } + } + } + + return bottom_type(); +} + +Node *SubTypeCheckNode::Ideal(PhaseGVN *phase, bool can_reshape) { + // Verify that optimizing the subtype check to a simple code pattern + // when possible would not constant fold better +#ifdef ASSERT + Node* obj_or_subklass = in(ObjOrSubKlass); + Node* superklass = in(SuperKlass); + + if (obj_or_subklass == NULL || + superklass == NULL) { + return NULL; + } + + const Type* sub_t = phase->type(obj_or_subklass); + const Type* super_t = phase->type(superklass); + + if (!super_t->isa_klassptr() || + (!sub_t->isa_klassptr() && !sub_t->isa_oopptr())) { + return NULL; + } + + + ciKlass* superk = super_t->is_klassptr()->klass(); + ciKlass* subk = sub_t->isa_klassptr() ? sub_t->is_klassptr()->klass() : sub_t->is_oopptr()->klass(); + + if (super_t->singleton() && subk != NULL && phase->C->static_subtype_check(superk, subk) == Compile::SSC_easy_test) { + Node* subklass = NULL; + if (sub_t->isa_oopptr()) { + Node* adr = phase->transform(new AddPNode(obj_or_subklass, obj_or_subklass, phase->MakeConX(oopDesc::klass_offset_in_bytes()))); + subklass = phase->transform(LoadKlassNode::make(*phase, NULL, phase->C->immutable_memory(), adr, TypeInstPtr::KLASS)); + } else { + subklass = obj_or_subklass; + } + Node* res = new CmpPNode(subklass, superklass); + const Type* t = phase->type(phase->transform(res)); + assert((Value(phase) == t) || (t != TypeInt::CC_GT && t != TypeInt::CC_EQ), "missing Value() optimization"); + if (phase->is_IterGVN()) { + phase->is_IterGVN()->_worklist.push(res); + } + return NULL; + } + + if (super_t->singleton() && subk != NULL && phase->C->static_subtype_check(superk, subk) == Compile::SSC_full_test) { + Node* subklass = NULL; + if (sub_t->isa_oopptr()) { + Node* adr = phase->transform(new AddPNode(obj_or_subklass, obj_or_subklass, phase->MakeConX(oopDesc::klass_offset_in_bytes()))); + subklass = phase->transform(LoadKlassNode::make(*phase, NULL, phase->C->immutable_memory(), adr, TypeInstPtr::KLASS)); + } else { + subklass = obj_or_subklass; + } + + Node *p1 = phase->transform(new AddPNode(superklass, superklass, phase->MakeConX(in_bytes(Klass::super_check_offset_offset())))); + Node* m = phase->C->immutable_memory(); + Node *chk_off = phase->transform(new LoadINode(NULL, m, p1, phase->type(p1)->is_ptr(), TypeInt::INT, MemNode::unordered)); + int cacheoff_con = in_bytes(Klass::secondary_super_cache_offset()); + bool might_be_cache = (phase->find_int_con(chk_off, cacheoff_con) == cacheoff_con); + + if (might_be_cache) { + return NULL; + } + + Node *chk_off_X = chk_off; +#ifdef _LP64 + chk_off_X = phase->transform(new ConvI2LNode(chk_off_X)); +#endif + Node *p2 = phase->transform(new AddPNode(subklass,subklass,chk_off_X)); + Node *kmem = phase->C->immutable_memory(); + Node *nkls = phase->transform(LoadKlassNode::make(*phase, NULL, kmem, p2, phase->type(p2)->is_ptr(), TypeKlassPtr::OBJECT_OR_NULL)); + + Node* res = new CmpPNode(superklass, nkls); + const Type* t = phase->type(phase->transform(res)); + assert((Value(phase) == t) || (t != TypeInt::CC_GT && t != TypeInt::CC_EQ), "missing Value() optimization"); + if (phase->is_IterGVN()) { + phase->is_IterGVN()->_worklist.push(res); + } + return NULL; + } +#endif + + return NULL; +} diff --git a/src/hotspot/share/opto/subtypenode.hpp b/src/hotspot/share/opto/subtypenode.hpp new file mode 100644 index 00000000000..02bb32459e3 --- /dev/null +++ b/src/hotspot/share/opto/subtypenode.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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_OPTO_SUBTYPENODE_HPP +#define SHARE_OPTO_SUBTYPENODE_HPP + +#include "opto/node.hpp" + +class SubTypeCheckNode : public CmpNode { +public: + enum { + Control, + ObjOrSubKlass, + SuperKlass + }; + + SubTypeCheckNode(Compile* C, Node* obj_or_subklass, Node* superklass) + : CmpNode(obj_or_subklass, superklass) { + init_class_id(Class_SubTypeCheck); + init_flags(Flag_is_macro); + C->add_macro_node(this); + } + + Node* Ideal(PhaseGVN *phase, bool can_reshape); + virtual const Type* sub(const Type*, const Type*) const; + Node* Identity(PhaseGVN* phase) { return this; } + + virtual int Opcode() const; + const Type* bottom_type() const { return TypeInt::CC; } + bool depends_only_on_test() const { return false; }; +}; + +#endif // SHARE_OPTO_SUBTYPENODE_HPP diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 38aa4a0db39..50a55e5d81d 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -39,6 +39,7 @@ #include "opto/superword.hpp" #include "opto/vectornode.hpp" #include "opto/movenode.hpp" +#include "utilities/powerOfTwo.hpp" // // S U P E R W O R D T R A N S F O R M @@ -2706,13 +2707,11 @@ Node* SuperWord::vector_opd(Node_List* p, int opd_idx) { NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("Should be int type only");}) return NULL; } - // Move non constant shift count into vector register. - cnt = VectorNode::shift_count(p0, cnt, vlen, velt_basic_type(p0)); - } - if (cnt != opd) { - _igvn.register_new_node_with_optimizer(cnt); - _phase->set_ctrl(cnt, _phase->get_ctrl(opd)); } + // Move shift count into vector register. + cnt = VectorNode::shift_count(p0, cnt, vlen, velt_basic_type(p0)); + _igvn.register_new_node_with_optimizer(cnt); + _phase->set_ctrl(cnt, _phase->get_ctrl(opd)); return cnt; } assert(!opd->is_StoreVector(), "such vector is not expected here"); diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 8d3cebc83c2..3eb919df05b 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -39,6 +39,7 @@ #include "opto/node.hpp" #include "opto/opcodes.hpp" #include "opto/type.hpp" +#include "utilities/powerOfTwo.hpp" // Portions of code courtesy of Clifford Click diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index 0b9d39124d3..85e3ac0450c 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -25,6 +25,7 @@ #include "memory/allocation.inline.hpp" #include "opto/connode.hpp" #include "opto/vectornode.hpp" +#include "utilities/powerOfTwo.hpp" //------------------------------VectorNode-------------------------------------- @@ -467,7 +468,7 @@ VectorNode* VectorNode::scalar2vector(Node* s, uint vlen, const Type* opd_t) { } VectorNode* VectorNode::shift_count(Node* shift, Node* cnt, uint vlen, BasicType bt) { - assert(VectorNode::is_shift(shift) && !cnt->is_Con(), "only variable shift count"); + assert(VectorNode::is_shift(shift), "sanity"); // Match shift count type with shift vector type. const TypeVect* vt = TypeVect::make(bt, vlen); switch (shift->Opcode()) { @@ -506,7 +507,7 @@ bool VectorNode::is_vector_shift(int opc) { } } -bool VectorNode::is_shift_count(int opc) { +bool VectorNode::is_vector_shift_count(int opc) { assert(opc > _last_machine_leaf && opc < _last_opcode, "invalid opcode"); switch (opc) { case Op_RShiftCntV: diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index b6ba207302a..b445711a706 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -76,7 +76,14 @@ class VectorNode : public TypeNode { static void vector_operands(Node* n, uint* start, uint* end); static bool is_vector_shift(int opc); - static bool is_shift_count(int opc); + static bool is_vector_shift_count(int opc); + + static bool is_vector_shift(Node* n) { + return is_vector_shift(n->Opcode()); + } + static bool is_vector_shift_count(Node* n) { + return is_vector_shift_count(n->Opcode()); + } }; //===========================Vector=ALU=Operations============================= diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp index 6a0e7997c21..ef7d60a49ea 100644 --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -2540,7 +2540,7 @@ JNI_ENTRY(Return, \ Return ret = NULL;\ DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\ \ - oop obj= oopFactory::Allocator(len, CHECK_0); \ + oop obj= oopFactory::Allocator(len, CHECK_NULL); \ ret = (Return) JNIHandles::make_local(env, obj); \ return ret;\ JNI_END @@ -3659,7 +3659,17 @@ static void post_thread_start_event(const JavaThread* jt) { EventThreadStart event; if (event.should_commit()) { event.set_thread(JFR_THREAD_ID(jt)); - event.commit(); + event.set_parentThread((traceid)0); +#if INCLUDE_JFR + if (EventThreadStart::is_stacktrace_enabled()) { + jt->jfr_thread_local()->set_cached_stack_trace_id((traceid)0); + event.commit(); + jt->jfr_thread_local()->clear_cached_stack_trace(); + } else +#endif + { + event.commit(); + } } } diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index ae607cf503d..7d95d693457 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -94,6 +94,7 @@ #endif #include +#include /* NOTE about use of any ctor or function call that can trigger a safepoint/GC: @@ -557,7 +558,7 @@ JVM_ENTRY(jstring, JVM_GetExtendedNPEMessage(JNIEnv *env, jthrowable throwable)) stringStream ss; bool ok = BytecodeUtils::get_NPE_message_at(&ss, method, bci); if (ok) { - oop result = java_lang_String::create_oop_from_str(ss.base(), CHECK_0); + oop result = java_lang_String::create_oop_from_str(ss.base(), CHECK_NULL); return (jstring) JNIHandles::make_local(env, result); } else { return NULL; @@ -2882,6 +2883,15 @@ JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) os::native_thread_creation_failed_msg()); } +#if INCLUDE_JFR + if (JfrRecorder::is_recording() && EventThreadStart::is_enabled() && + EventThreadStart::is_stacktrace_enabled()) { + JfrThreadLocal* tl = native_thread->jfr_thread_local(); + // skip Thread.start() and Thread.start0() + tl->set_cached_stack_trace_id(JfrStackTraceRepository::record(thread, 2)); + } +#endif + Thread::start(native_thread); JVM_END @@ -3371,6 +3381,7 @@ JVM_ENTRY_NO_ENV(void*, JVM_LoadLibrary(const char* name)) THROW_HANDLE_0(h_exception); } + log_info(library)("Loaded library %s, handle " INTPTR_FORMAT, name, p2i(load_result)); return load_result; JVM_END @@ -3378,12 +3389,17 @@ JVM_END JVM_LEAF(void, JVM_UnloadLibrary(void* handle)) JVMWrapper("JVM_UnloadLibrary"); os::dll_unload(handle); + log_info(library)("Unloaded library with handle " INTPTR_FORMAT, p2i(handle)); JVM_END JVM_LEAF(void*, JVM_FindLibraryEntry(void* handle, const char* name)) JVMWrapper("JVM_FindLibraryEntry"); - return os::dll_lookup(handle, name); + void* find_result = os::dll_lookup(handle, name); + log_info(library)("%s %s in library with handle " INTPTR_FORMAT, + find_result != NULL ? "Found" : "Failed to find", + name, p2i(handle)); + return find_result; JVM_END diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index f8f2f569f7d..2514a8b520d 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -31,6 +31,7 @@ #include "classfile/vmSymbols.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/interpreter.hpp" +#include "jfr/jfrEvents.hpp" #include "jvmtifiles/jvmtiEnv.hpp" #include "logging/log.hpp" #include "logging/logConfiguration.hpp" @@ -446,9 +447,16 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { } class_definitions[index].klass = jcls; } + EventRetransformClasses event; VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform); VMThread::execute(&op); - return (op.check_error()); + jvmtiError error = op.check_error(); + if (error == JVMTI_ERROR_NONE) { + event.set_classCount(class_count); + event.set_redefinitionId(op.id()); + event.commit(); + } + return error; } /* end RetransformClasses */ @@ -457,9 +465,16 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { jvmtiError JvmtiEnv::RedefineClasses(jint class_count, const jvmtiClassDefinition* class_definitions) { //TODO: add locking + EventRedefineClasses event; VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); VMThread::execute(&op); - return (op.check_error()); + jvmtiError error = op.check_error(); + if (error == JVMTI_ERROR_NONE) { + event.set_classCount(class_count); + event.set_redefinitionId(op.id()); + event.commit(); + } + return error; } /* end RedefineClasses */ diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index 4875562d9cb..4c189ddfb48 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ #include "compiler/compileBroker.hpp" #include "interpreter/oopMapCache.hpp" #include "interpreter/rewriter.hpp" +#include "jfr/jfrEvents.hpp" #include "logging/logStream.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceShared.hpp" @@ -51,6 +52,7 @@ #include "prims/jvmtiThreadState.inline.hpp" #include "prims/resolvedMethodTable.hpp" #include "prims/methodComparator.hpp" +#include "runtime/atomic.hpp" #include "runtime/deoptimization.hpp" #include "runtime/handles.inline.hpp" #include "runtime/jniHandles.inline.hpp" @@ -70,7 +72,7 @@ int VM_RedefineClasses::_deleted_methods_length = 0; int VM_RedefineClasses::_added_methods_length = 0; bool VM_RedefineClasses::_has_redefined_Object = false; bool VM_RedefineClasses::_has_null_class_loader = false; - +u8 VM_RedefineClasses::_id_counter = 0; VM_RedefineClasses::VM_RedefineClasses(jint class_count, const jvmtiClassDefinition *class_defs, @@ -83,6 +85,7 @@ VM_RedefineClasses::VM_RedefineClasses(jint class_count, _the_class = NULL; _has_redefined_Object = false; _has_null_class_loader = false; + _id = next_id(); } static inline InstanceKlass* get_ik(jclass def) { @@ -1479,19 +1482,19 @@ bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp, case JVM_CONSTANT_Long: // just copy the entry to *merge_cp_p, but double and long take // two constant pool entries - ConstantPool::copy_entry_to(old_cp, old_i, *merge_cp_p, old_i, CHECK_0); + ConstantPool::copy_entry_to(old_cp, old_i, *merge_cp_p, old_i, CHECK_false); old_i++; break; default: // just copy the entry to *merge_cp_p - ConstantPool::copy_entry_to(old_cp, old_i, *merge_cp_p, old_i, CHECK_0); + ConstantPool::copy_entry_to(old_cp, old_i, *merge_cp_p, old_i, CHECK_false); break; } } // end for each old_cp entry - ConstantPool::copy_operands(old_cp, *merge_cp_p, CHECK_0); - (*merge_cp_p)->extend_operands(scratch_cp, CHECK_0); + ConstantPool::copy_operands(old_cp, *merge_cp_p, CHECK_false); + (*merge_cp_p)->extend_operands(scratch_cp, CHECK_false); // We don't need to sanity check that *merge_cp_length_p is within // *merge_cp_p bounds since we have the minimum on-entry check above. @@ -1525,7 +1528,7 @@ bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp, } bool match = scratch_cp->compare_entry_to(scratch_i, *merge_cp_p, - scratch_i, CHECK_0); + scratch_i, CHECK_false); if (match) { // found a match at the same index so nothing more to do continue; @@ -1540,7 +1543,7 @@ bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp, } int found_i = scratch_cp->find_matching_entry(scratch_i, *merge_cp_p, - CHECK_0); + CHECK_false); if (found_i != 0) { guarantee(found_i != scratch_i, "compare_entry_to() and find_matching_entry() do not agree"); @@ -1561,7 +1564,7 @@ bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp, // No match found so we have to append this entry and any unique // referenced entries to *merge_cp_p. append_entry(scratch_cp, scratch_i, merge_cp_p, merge_cp_length_p, - CHECK_0); + CHECK_false); } } @@ -1589,7 +1592,7 @@ bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp, } int found_i = - scratch_cp->find_matching_entry(scratch_i, *merge_cp_p, CHECK_0); + scratch_cp->find_matching_entry(scratch_i, *merge_cp_p, CHECK_false); if (found_i != 0) { // Found a matching entry somewhere else in *merge_cp_p so // just need a mapping entry. @@ -1600,7 +1603,7 @@ bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp, // No match found so we have to append this entry and any unique // referenced entries to *merge_cp_p. append_entry(scratch_cp, scratch_i, merge_cp_p, merge_cp_length_p, - CHECK_0); + CHECK_false); } log_debug(redefine, class, constantpool) @@ -4294,6 +4297,15 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, } increment_class_counter((InstanceKlass *)the_class, THREAD); + + if (EventClassRedefinition::is_enabled()) { + EventClassRedefinition event; + event.set_classModificationCount(java_lang_Class::classRedefinedCount(the_class->java_mirror())); + event.set_redefinedClass(the_class); + event.set_redefinitionId(_id); + event.commit(); + } + { ResourceMark rm(THREAD); // increment the classRedefinedCount field in the_class and in any @@ -4307,6 +4319,7 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, } _timer_rsc_phase2.stop(); + } // end redefine_single_class() @@ -4393,6 +4406,16 @@ void VM_RedefineClasses::CheckClass::do_klass(Klass* k) { } } +u8 VM_RedefineClasses::next_id() { + while (true) { + u8 id = _id_counter; + u8 next_id = id + 1; + u8 result = Atomic::cmpxchg(&_id_counter, id, next_id); + if (result == id) { + return next_id; + } + } +} void VM_RedefineClasses::dump_methods() { int j; diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiRedefineClasses.hpp index c2ea36961eb..d69aac4a7e6 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.hpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -351,6 +351,9 @@ class VM_RedefineClasses: public VM_Operation { static bool _has_redefined_Object; static bool _has_null_class_loader; + // Used by JFR to group class redefininition events together. + static u8 _id_counter; + // The instance fields are used to pass information from // doit_prologue() to doit() and doit_epilogue(). Klass* _the_class; @@ -388,6 +391,9 @@ class VM_RedefineClasses: public VM_Operation { elapsedTimer _timer_rsc_phase2; elapsedTimer _timer_vm_op_prologue; + // Redefinition id used by JFR + u8 _id; + // These routines are roughly in call order unless otherwise noted. // Load the caller's new class definition(s) into _scratch_classes. @@ -503,6 +509,8 @@ class VM_RedefineClasses: public VM_Operation { void lock_classes(); void unlock_classes(); + u8 next_id(); + static void dump_methods(); // Check that there are no old or obsolete methods @@ -535,6 +543,7 @@ class VM_RedefineClasses: public VM_Operation { bool allow_nested_vm_operations() const { return true; } jvmtiError check_error() { return _res; } + u8 id() { return _id; } // Modifiable test must be shared between IsModifiableClass query // and redefine implementation diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 93c04976165..f8669d34a6c 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -821,6 +821,10 @@ static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobje return env->FromReflectedMethod(method); } +static CompLevel highestCompLevel() { + return TieredCompilation ? MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier) : CompLevel_highest_tier; +} + // Deoptimizes all compiled frames and makes nmethods not entrant if it's requested class VM_WhiteBoxDeoptimizeFrames : public VM_WhiteBoxOperation { private: @@ -834,11 +838,10 @@ class VM_WhiteBoxDeoptimizeFrames : public VM_WhiteBoxOperation { void doit() { for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { if (t->has_last_Java_frame()) { - for (StackFrameStream fst(t, UseBiasedLocking); !fst.is_done(); fst.next()) { + for (StackFrameStream fst(t, false); !fst.is_done(); fst.next()) { frame* f = fst.current(); if (f->can_be_deoptimized() && !f->is_deoptimized_frame()) { - RegisterMap* reg_map = fst.register_map(); - Deoptimization::deoptimize(t, *f, reg_map); + Deoptimization::deoptimize(t, *f); if (_make_not_entrant) { CompiledMethod* cm = CodeCache::find_compiled(f->pc()); assert(cm != NULL, "sanity check"); @@ -895,7 +898,7 @@ WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method, j WB_END WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr)) - if (method == NULL || comp_level > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier)) { + if (method == NULL || comp_level > highestCompLevel()) { return false; } jmethodID jmid = reflected_method_to_jmid(thread, env, method); @@ -918,7 +921,7 @@ WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobje WB_END WB_ENTRY(jboolean, WB_IsIntrinsicAvailable(JNIEnv* env, jobject o, jobject method, jobject compilation_context, jint compLevel)) - if (compLevel < CompLevel_none || compLevel > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier)) { + if (compLevel < CompLevel_none || compLevel > highestCompLevel()) { return false; // Intrinsic is not available on a non-existent compilation level. } jmethodID method_id, compilation_context_id; @@ -1004,7 +1007,7 @@ bool WhiteBox::compile_method(Method* method, int comp_level, int bci, Thread* T tty->print_cr("WB error: request to compile NULL method"); return false; } - if (comp_level > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier)) { + if (comp_level > highestCompLevel()) { tty->print_cr("WB error: invalid compilation level %d", comp_level); return false; } @@ -1131,8 +1134,8 @@ WB_ENTRY(void, WB_MarkMethodProfiled(JNIEnv* env, jobject o, jobject method)) InvocationCounter* icnt = mdo->invocation_counter(); InvocationCounter* bcnt = mdo->backedge_counter(); // set i-counter according to TieredThresholdPolicy::is_method_profiled - icnt->set(InvocationCounter::wait_for_compile, Tier4MinInvocationThreshold); - bcnt->set(InvocationCounter::wait_for_compile, Tier4CompileThreshold); + icnt->set(Tier4MinInvocationThreshold); + bcnt->set(Tier4CompileThreshold); WB_END WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method)) diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 675821ad302..0161b4e1383 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -54,6 +54,7 @@ #include "utilities/align.hpp" #include "utilities/defaultStream.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" #include "utilities/stringUtils.hpp" #if INCLUDE_JFR #include "jfr/jfr.hpp" @@ -3498,16 +3499,6 @@ void Arguments::set_shared_spaces_flags() { warning("Cannot dump shared archive while using shared archive"); } UseSharedSpaces = false; -#ifdef _LP64 - if (!UseCompressedOops || !UseCompressedClassPointers) { - vm_exit_during_initialization( - "Cannot dump shared archive when UseCompressedOops or UseCompressedClassPointers is off.", NULL); - } - } else { - if (!UseCompressedOops || !UseCompressedClassPointers) { - no_shared_spaces("UseCompressedOops and UseCompressedClassPointers must be on for UseSharedSpaces."); - } -#endif } } diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 862a8c5153a..2b7662ff38f 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -1516,7 +1516,7 @@ void Deoptimization::deoptimize_single_frame(JavaThread* thread, frame fr, Deopt fr.deoptimize(thread); } -void Deoptimization::deoptimize(JavaThread* thread, frame fr, RegisterMap *map, DeoptReason reason) { +void Deoptimization::deoptimize(JavaThread* thread, frame fr, DeoptReason reason) { // Deoptimize only if the frame comes from compile code. // Do not deoptimize the frame which is already patched // during the execution of the loops below. @@ -1534,15 +1534,15 @@ address Deoptimization::deoptimize_for_missing_exception_handler(CompiledMethod* cm->make_not_entrant(); // Use Deoptimization::deoptimize for all of its side-effects: - // revoking biases of monitors, gathering traps statistics, logging... + // gathering traps statistics, logging... // it also patches the return pc but we do not care about that // since we return a continuation to the deopt_blob below. JavaThread* thread = JavaThread::current(); - RegisterMap reg_map(thread, UseBiasedLocking); + RegisterMap reg_map(thread, false); frame runtime_frame = thread->last_frame(); frame caller_frame = runtime_frame.sender(®_map); assert(caller_frame.cb()->as_compiled_method_or_null() == cm, "expect top frame compiled method"); - Deoptimization::deoptimize(thread, caller_frame, ®_map, Deoptimization::Reason_not_compiled_exception_handler); + Deoptimization::deoptimize(thread, caller_frame, Deoptimization::Reason_not_compiled_exception_handler); MethodData* trap_mdo = get_method_data(thread, methodHandle(thread, cm->method()), true); if (trap_mdo != NULL) { @@ -1557,12 +1557,12 @@ void Deoptimization::deoptimize_frame_internal(JavaThread* thread, intptr_t* id, assert(thread == Thread::current() || SafepointSynchronize::is_at_safepoint(), "can only deoptimize other thread at a safepoint"); // Compute frame and register map based on thread and sp. - RegisterMap reg_map(thread, UseBiasedLocking); + RegisterMap reg_map(thread, false); frame fr = thread->last_frame(); while (fr.id() != id) { fr = fr.sender(®_map); } - deoptimize(thread, fr, ®_map, reason); + deoptimize(thread, fr, reason); } diff --git a/src/hotspot/share/runtime/deoptimization.hpp b/src/hotspot/share/runtime/deoptimization.hpp index 1cfff5394ee..b3e5265b419 100644 --- a/src/hotspot/share/runtime/deoptimization.hpp +++ b/src/hotspot/share/runtime/deoptimization.hpp @@ -148,8 +148,8 @@ class Deoptimization : AllStatic { static void revoke_from_deopt_handler(JavaThread* thread, frame fr, RegisterMap* map); public: - // Deoptimizes a frame lazily. nmethod gets patched deopt happens on return to the frame - static void deoptimize(JavaThread* thread, frame fr, RegisterMap *reg_map, DeoptReason reason = Reason_constraint); + // Deoptimizes a frame lazily. Deopt happens on return to the frame. + static void deoptimize(JavaThread* thread, frame fr, DeoptReason reason = Reason_constraint); #if INCLUDE_JVMCI static address deoptimize_for_missing_exception_handler(CompiledMethod* cm); diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp index 30537785587..04fc865e934 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp @@ -33,6 +33,7 @@ #include "runtime/flags/jvmFlagConstraintsCompiler.hpp" #include "runtime/globals.hpp" #include "runtime/globals_extension.hpp" +#include "utilities/powerOfTwo.hpp" JVMFlag::Error AliasLevelConstraintFunc(intx value, bool verbose) { if ((value <= 1) && (Arguments::mode() == Arguments::_comp || Arguments::mode() == Arguments::_mixed)) { diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp index 4603e75b425..61d58c53829 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp @@ -29,6 +29,7 @@ #include "runtime/globals.hpp" #include "runtime/safepointMechanism.hpp" #include "runtime/task.hpp" +#include "utilities/powerOfTwo.hpp" JVMFlag::Error ObjectAlignmentInBytesConstraintFunc(intx value, bool verbose) { if (!is_power_of_2(value)) { diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index 958539e750a..ccff62dabb8 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -231,8 +231,7 @@ JavaCallWrapper* frame::entry_frame_call_wrapper_if_safe(JavaThread* thread) con bool frame::is_entry_frame_valid(JavaThread* thread) const { // Validate the JavaCallWrapper an entry frame must have address jcw = (address)entry_frame_call_wrapper(); - bool jcw_safe = (jcw < thread->stack_base()) && (jcw > (address)fp()); // less than stack base - if (!jcw_safe) { + if (!thread->is_in_stack_range_excl(jcw, (address)fp())) { return false; } @@ -1284,17 +1283,17 @@ void FrameValues::print(JavaThread* thread) { intptr_t* v1 = _values.at(max_index).location; if (thread == Thread::current()) { - while (!thread->is_in_stack((address)v0)) { + while (!thread->is_in_live_stack((address)v0)) { v0 = _values.at(++min_index).location; } - while (!thread->is_in_stack((address)v1)) { + while (!thread->is_in_live_stack((address)v1)) { v1 = _values.at(--max_index).location; } } else { - while (!thread->on_local_stack((address)v0)) { + while (!thread->is_in_full_stack((address)v0)) { v0 = _values.at(++min_index).location; } - while (!thread->on_local_stack((address)v1)) { + while (!thread->is_in_full_stack((address)v1)) { v1 = _values.at(--max_index).location; } } diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index cbbcc9f2021..029a95bcbb3 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -994,9 +994,6 @@ const size_t minimumSymbolTableSize = 1024; "proper StackOverflow handling; disable only to measure cost " \ "of stackbanging)") \ \ - develop(bool, UseStrictFP, true, \ - "use strict fp if modifier strictfp is set") \ - \ develop(bool, GenerateSynchronizationCode, true, \ "generate locking/unlocking code for synchronized methods and " \ "monitors") \ diff --git a/src/hotspot/share/runtime/handles.cpp b/src/hotspot/share/runtime/handles.cpp index a91dcff8520..02fdada6296 100644 --- a/src/hotspot/share/runtime/handles.cpp +++ b/src/hotspot/share/runtime/handles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ name##Handle::name##Handle(const name##Handle &h) { \ } else { \ _thread = Thread::current(); \ } \ - assert (_thread->is_in_stack((address)this), "not on stack?"); \ + assert(_thread->is_in_live_stack((address)this), "not on stack?"); \ _thread->metadata_handles()->push((Metadata*)_value); \ } else { \ _thread = NULL; \ @@ -68,7 +68,7 @@ name##Handle& name##Handle::operator=(const name##Handle &s) { \ } else { \ _thread = Thread::current(); \ } \ - assert (_thread->is_in_stack((address)this), "not on stack?"); \ + assert(_thread->is_in_live_stack((address)this), "not on stack?"); \ _thread->metadata_handles()->push((Metadata*)_value); \ } else { \ _thread = NULL; \ diff --git a/src/hotspot/share/runtime/handles.inline.hpp b/src/hotspot/share/runtime/handles.inline.hpp index 67a6fe11ffe..98c050d4bd8 100644 --- a/src/hotspot/share/runtime/handles.inline.hpp +++ b/src/hotspot/share/runtime/handles.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ inline name##Handle::name##Handle(Thread* thread, type* obj) : _value(obj), _thr if (obj != NULL) { \ assert(((Metadata*)obj)->is_valid(), "obj is valid"); \ assert(_thread == Thread::current(), "thread must be current"); \ - assert (_thread->is_in_stack((address)this), "not on stack?"); \ + assert(_thread->is_in_live_stack((address)this), "not on stack?"); \ _thread->metadata_handles()->push((Metadata*)obj); \ } \ } \ diff --git a/src/hotspot/share/runtime/jniHandles.cpp b/src/hotspot/share/runtime/jniHandles.cpp index 2f349e36909..38804eddb32 100644 --- a/src/hotspot/share/runtime/jniHandles.cpp +++ b/src/hotspot/share/runtime/jniHandles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -265,8 +265,7 @@ bool JNIHandles::is_frame_handle(JavaThread* thr, jobject handle) { // as the java command executable, in which case, this type of handle // is not permitted. return (thr->has_last_Java_frame() && - (void*)handle < (void*)thr->stack_base() && - (void*)handle >= (void*)thr->last_Java_sp()); + thr->is_in_stack_range_incl((address)handle, (address)thr->last_Java_sp())); } diff --git a/src/hotspot/share/runtime/mutex.hpp b/src/hotspot/share/runtime/mutex.hpp index 78b5eb440b6..bad2c47d097 100644 --- a/src/hotspot/share/runtime/mutex.hpp +++ b/src/hotspot/share/runtime/mutex.hpp @@ -81,7 +81,7 @@ class Mutex : public CHeapObj { char _name[MUTEX_NAME_LEN]; // Name of mutex/monitor // Debugging fields for naming, deadlock detection, etc. (some only used in debug mode) -#ifdef ASSERT +#ifndef PRODUCT bool _allow_vm_block; int _rank; // rank (to avoid/detect potential deadlocks) Mutex* _next; // Used by a Thread to link up owned locks diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 37acfee3746..8e11bad096f 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1114,7 +1114,7 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) { } // If the addr is in the stack region for this thread then report that // and print thread info - if (thread->on_local_stack(addr)) { + if (thread->is_in_full_stack(addr)) { st->print_cr(INTPTR_FORMAT " is pointing into the stack for thread: " INTPTR_FORMAT, p2i(addr), p2i(thread)); if (verbose) thread->print_on(st); diff --git a/src/hotspot/share/runtime/signature.cpp b/src/hotspot/share/runtime/signature.cpp index c23cdfd73de..fb3beda7762 100644 --- a/src/hotspot/share/runtime/signature.cpp +++ b/src/hotspot/share/runtime/signature.cpp @@ -172,14 +172,14 @@ void Fingerprinter::compute_fingerprint_and_return_type(bool static_flag) { // Implementation of SignatureStream -static inline int decode_signature_char(int ch) { +static inline BasicType decode_signature_char(int ch) { switch (ch) { #define EACH_SIG(ch, bt, ignore) \ case ch: return bt; SIGNATURE_TYPES_DO(EACH_SIG, ignore) #undef EACH_SIG } - return 0; + return (BasicType)0; } SignatureStream::SignatureStream(const Symbol* signature, @@ -188,28 +188,29 @@ SignatureStream::SignatureStream(const Symbol* signature, "method signature required"); _signature = signature; _limit = signature->utf8_length(); - int oz = (is_method ? 1 : 0); + int oz = (is_method ? _s_method : _s_field); _state = oz; - assert(_state == (int)(is_method ? _s_method : _s_field), "signature state incorrectly set"); _begin = _end = oz; // skip first '(' in method signatures _array_prefix = 0; // just for definiteness - _previous_name = NULL; + + // assigning java/lang/Object to _previous_name means we can + // avoid a number of NULL checks in the parser + _previous_name = vmSymbols::java_lang_Object(); _names = NULL; next(); } SignatureStream::~SignatureStream() { // decrement refcount for names created during signature parsing + _previous_name->decrement_refcount(); if (_names != NULL) { for (int i = 0; i < _names->length(); i++) { _names->at(i)->decrement_refcount(); } - } else if (_previous_name != NULL && !_previous_name->is_permanent()) { - _previous_name->decrement_refcount(); } } -inline int SignatureStream::scan_non_primitive(BasicType type) { +inline int SignatureStream::scan_type(BasicType type) { const u1* base = _signature->bytes(); int end = _end; int limit = _limit; @@ -217,22 +218,24 @@ inline int SignatureStream::scan_non_primitive(BasicType type) { switch (type) { case T_OBJECT: tem = (const u1*) memchr(&base[end], JVM_SIGNATURE_ENDCLASS, limit - end); - end = (tem == NULL ? limit : tem+1 - base); - break; + return (tem == NULL ? limit : tem + 1 - base); case T_ARRAY: while ((end < limit) && ((char)base[end] == JVM_SIGNATURE_ARRAY)) { end++; } _array_prefix = end - _end; // number of '[' chars just skipped - if (Signature::has_envelope(base[end++])) { - tem = (const u1*) memchr(&base[end], JVM_SIGNATURE_ENDCLASS, limit - end); - end = (tem == NULL ? limit : tem+1 - base); - break; + if (Signature::has_envelope(base[end])) { + tem = (const u1 *) memchr(&base[end], JVM_SIGNATURE_ENDCLASS, limit - end); + return (tem == NULL ? limit : tem + 1 - base); } - break; + // Skipping over a single character for a primitive type. + assert(is_java_primitive(decode_signature_char(base[end])), "only primitives expected"); + return end + 1; - default : ShouldNotReachHere(); + default: + // Skipping over a single character for a primitive type (or void). + assert(!is_reference_type(type), "only primitives or void expected"); + return end + 1; } - return end; } void SignatureStream::next() { @@ -241,50 +244,33 @@ void SignatureStream::next() { if (_end >= len) { set_done(); return; } _begin = _end; int ch = sig->char_at(_begin); - int btcode = decode_signature_char(ch); - if (btcode == 0) { - guarantee(ch == JVM_SIGNATURE_ENDFUNC, "bad signature char %c/%d", ch, ch); + if (ch == JVM_SIGNATURE_ENDFUNC) { assert(_state == _s_method, "must be in method"); _state = _s_method_return; _begin = ++_end; if (_end >= len) { set_done(); return; } ch = sig->char_at(_begin); - btcode = decode_signature_char(ch); } - BasicType bt = (BasicType) btcode; + BasicType bt = decode_signature_char(ch); assert(ch == type2char(bt), "bad signature char %c/%d", ch, ch); _type = bt; - if (!is_reference_type(bt)) { - // Skip over a single character for a primitive type (or void). - _end++; - return; - } - _end = scan_non_primitive(bt); + _end = scan_type(bt); } -int SignatureStream::skip_array_prefix(int max_skip_length) { - if (_type != T_ARRAY) { - return 0; - } - if (_array_prefix > max_skip_length) { - // strip some but not all levels of T_ARRAY - _array_prefix -= max_skip_length; - _begin += max_skip_length; - return max_skip_length; - } +int SignatureStream::skip_whole_array_prefix() { + assert(_type == T_ARRAY, "must be"); + // we are stripping all levels of T_ARRAY, // so we must decode the next character int whole_array_prefix = _array_prefix; int new_begin = _begin + whole_array_prefix; _begin = new_begin; int ch = _signature->char_at(new_begin); - int btcode = decode_signature_char(ch); - BasicType bt = (BasicType) btcode; + BasicType bt = decode_signature_char(ch); assert(ch == type2char(bt), "bad signature char %c/%d", ch, ch); _type = bt; assert(bt != T_VOID && bt != T_ARRAY, "bad signature type"); - // Don't bother to call scan_non_primitive, since it won't - // change the value of _end. + // Don't bother to re-scan, since it won't change the value of _end. return whole_array_prefix; } @@ -317,9 +303,9 @@ bool Signature::is_valid_array_signature(const Symbol* sig) { } BasicType Signature::basic_type(int ch) { - int btcode = decode_signature_char(ch); + BasicType btcode = decode_signature_char(ch); if (btcode == 0) return T_ILLEGAL; - return (BasicType) btcode; + return btcode; } static const int jl_len = 10, object_len = 6, jl_object_len = jl_len + object_len; @@ -365,7 +351,7 @@ Symbol* SignatureStream::find_symbol() { } Symbol* name = _previous_name; - if (name != NULL && name->equals(symbol_chars, len)) { + if (name->equals(symbol_chars, len)) { return name; } @@ -375,18 +361,11 @@ Symbol* SignatureStream::find_symbol() { // Only allocate the GrowableArray for the _names buffer if more than // one name is being processed in the signature. - if (_previous_name != NULL && - !_previous_name->is_permanent() && - !name->is_permanent() && - _names == NULL) { - _names = new GrowableArray(10); - _names->push(_previous_name); - } - if (!name->is_permanent() && _previous_name != NULL) { + if (!_previous_name->is_permanent()) { if (_names == NULL) { _names = new GrowableArray(10); } - _names->push(name); // save new symbol for decrementing later + _names->push(_previous_name); } _previous_name = name; return name; diff --git a/src/hotspot/share/runtime/signature.hpp b/src/hotspot/share/runtime/signature.hpp index 4252202b4a1..59178ca46b0 100644 --- a/src/hotspot/share/runtime/signature.hpp +++ b/src/hotspot/share/runtime/signature.hpp @@ -232,7 +232,6 @@ class SignatureIterator: public ResourceObj { // bitfields from the fingerprint. Otherwise, the // symbol is parsed. template inline void do_parameters_on(T* callback); // iterates over parameters only - void skip_parameters(); // skips over parameters to find return type BasicType return_type(); // computes the value on the fly if necessary static bool fp_is_static(fingerprint_t fingerprint) { @@ -478,8 +477,6 @@ class SignatureStream : public StackObj { Symbol* _previous_name; // cache the previously looked up symbol to avoid lookups GrowableArray* _names; // symbols created while parsing that need to be dereferenced - inline int scan_non_primitive(BasicType type); - Symbol* find_symbol(); enum { _s_field = 0, _s_method = 1, _s_method_return = 3 }; @@ -487,9 +484,9 @@ class SignatureStream : public StackObj { _state |= -2; // preserve s_method bit assert(is_done(), "Unable to set state to done"); } + int scan_type(BasicType bt); public: - bool is_method_signature() const { return (_state & (int)_s_method) != 0; } bool at_return_type() const { return _state == (int)_s_method_return; } bool is_done() const { return _state < 0; } void next(); @@ -504,8 +501,6 @@ class SignatureStream : public StackObj { const u1* raw_bytes() const { return _signature->bytes() + _begin; } int raw_length() const { return _end - _begin; } - int raw_begin() const { return _begin; } - int raw_end() const { return _end; } int raw_symbol_begin() const { return _begin + (has_envelope() ? 1 : 0); } int raw_symbol_end() const { return _end - (has_envelope() ? 1 : 0); } char raw_char_at(int i) const { @@ -541,7 +536,27 @@ class SignatureStream : public StackObj { // (The argument is clipped to array_prefix_length(), // and if it ends up as zero this call is a nop. // The default is value skips all brackets '['.) - int skip_array_prefix(int prefix_length = 9999); + private: + int skip_whole_array_prefix(); + public: + int skip_array_prefix(int max_skip_length) { + if (_type != T_ARRAY) { + return 0; + } + if (_array_prefix > max_skip_length) { + // strip some but not all levels of T_ARRAY + _array_prefix -= max_skip_length; + _begin += max_skip_length; + return max_skip_length; + } + return skip_whole_array_prefix(); + } + int skip_array_prefix() { + if (_type != T_ARRAY) { + return 0; + } + return skip_whole_array_prefix(); + } // free-standing lookups (bring your own CL/PD pair) enum FailureMode { ReturnNull, NCDFError, CachedOrNull }; diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index 4a4fd5869fe..488b1acaf02 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -387,7 +387,7 @@ void Thread::call_run() { log_debug(os, thread)("Thread " UINTX_FORMAT " stack dimensions: " PTR_FORMAT "-" PTR_FORMAT " (" SIZE_FORMAT "k).", - os::current_thread_id(), p2i(stack_base() - stack_size()), + os::current_thread_id(), p2i(stack_end()), p2i(stack_base()), stack_size()/1024); // Perform initialization actions @@ -1018,31 +1018,13 @@ void Thread::check_for_valid_safepoint_state() { } #endif // ASSERT -bool Thread::is_in_stack(address adr) const { - assert(Thread::current() == this, "is_in_stack can only be called from current thread"); - address end = os::current_stack_pointer(); - // Allow non Java threads to call this without stack_base - if (_stack_base == NULL) return true; - if (stack_base() > adr && adr >= end) return true; - - return false; -} - -bool Thread::is_in_usable_stack(address adr) const { - size_t stack_guard_size = os::uses_stack_guard_pages() ? JavaThread::stack_guard_zone_size() : 0; - size_t usable_stack_size = _stack_size - stack_guard_size; - - return ((adr < stack_base()) && (adr >= stack_base() - usable_stack_size)); -} - - // We had to move these methods here, because vm threads get into ObjectSynchronizer::enter // However, there is a note in JavaThread::is_lock_owned() about the VM threads not being // used for compilation in the future. If that change is made, the need for these methods // should be revisited, and they should be removed if possible. bool Thread::is_lock_owned(address adr) const { - return on_local_stack(adr); + return is_in_full_stack(adr); } bool Thread::set_as_starting_thread() { @@ -1829,7 +1811,6 @@ bool JavaThread::reguard_stack(void) { return reguard_stack(os::current_stack_pointer()); } - void JavaThread::block_if_vm_exited() { if (_terminated == _vm_exited) { // _vm_exited is set at safepoint, and Threads_lock is never released @@ -2416,11 +2397,10 @@ void JavaThread::send_thread_stop(oop java_throwable) { if (has_last_Java_frame()) { frame f = last_frame(); if (f.is_runtime_frame() || f.is_safepoint_blob_frame()) { - // BiasedLocking needs an updated RegisterMap for the revoke monitors pass - RegisterMap reg_map(this, UseBiasedLocking); + RegisterMap reg_map(this, false); frame compiled_frame = f.sender(®_map); if (!StressCompiledExceptionHandlers && compiled_frame.can_be_deoptimized()) { - Deoptimization::deoptimize(this, compiled_frame, ®_map); + Deoptimization::deoptimize(this, compiled_frame); } } } @@ -2865,8 +2845,7 @@ void JavaThread::frames_do(void f(frame*, const RegisterMap* map)) { // Deoptimization // Function for testing deoptimization void JavaThread::deoptimize() { - // BiasedLocking needs an updated RegisterMap for the revoke monitors pass - StackFrameStream fst(this, UseBiasedLocking); + StackFrameStream fst(this, false); bool deopt = false; // Dump stack only if a deopt actually happens. bool only_at = strlen(DeoptimizeOnlyAt) > 0; // Iterate over all frames in the thread and deoptimize @@ -2903,7 +2882,7 @@ void JavaThread::deoptimize() { trace_frames(); trace_stack(); } - Deoptimization::deoptimize(this, *fst.current(), fst.register_map()); + Deoptimization::deoptimize(this, *fst.current()); } } @@ -2929,11 +2908,10 @@ void JavaThread::make_zombies() { void JavaThread::deoptimize_marked_methods() { if (!has_last_Java_frame()) return; - // BiasedLocking needs an updated RegisterMap for the revoke monitors pass - StackFrameStream fst(this, UseBiasedLocking); + StackFrameStream fst(this, false); for (; !fst.is_done(); fst.next()) { if (fst.current()->should_be_deoptimized()) { - Deoptimization::deoptimize(this, *fst.current(), fst.register_map()); + Deoptimization::deoptimize(this, *fst.current()); } } } diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index d8391559d14..9bcaa5ba9d0 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -684,15 +684,43 @@ class Thread: public ThreadShadow { // jvmtiRedefineClasses support void metadata_handles_do(void f(Metadata*)); + private: + // Check if address is within the given range of this thread's + // stack: stack_base() > adr >/>= limit + // The check is inclusive of limit if passed true, else exclusive. + bool is_in_stack_range(address adr, address limit, bool inclusive) const { + assert(stack_base() > limit && limit >= stack_end(), "limit is outside of stack"); + return stack_base() > adr && (inclusive ? adr >= limit : adr > limit); + } + + public: // Used by fast lock support virtual bool is_lock_owned(address adr) const; - // Check if address is in the stack of the thread (not just for locks). - // Warning: the method can only be used on the running thread - bool is_in_stack(address adr) const; - // Check if address is in the usable part of the stack (excludes protected - // guard pages) - bool is_in_usable_stack(address adr) const; + // Check if address is within the given range of this thread's + // stack: stack_base() > adr >= limit + bool is_in_stack_range_incl(address adr, address limit) const { + return is_in_stack_range(adr, limit, true); + } + + // Check if address is within the given range of this thread's + // stack: stack_base() > adr > limit + bool is_in_stack_range_excl(address adr, address limit) const { + return is_in_stack_range(adr, limit, false); + } + + // Check if address is in the stack mapped to this thread. Used mainly in + // error reporting (so has to include guard zone) and frame printing. + bool is_in_full_stack(address adr) const { + return is_in_stack_range_incl(adr, stack_end()); + } + + // Check if address is in the live stack of this thread (not just for locks). + // Warning: can only be called by the current thread on itself. + bool is_in_live_stack(address adr) const { + assert(Thread::current() == this, "is_in_live_stack can only be called from current thread"); + return is_in_stack_range_incl(adr, os::current_stack_pointer()); + } // Sets this thread as starting thread. Returns failure if thread // creation fails due to lack of memory, too many threads etc. @@ -728,11 +756,6 @@ protected: void record_stack_base_and_size(); void register_thread_stack_with_NMT() NOT_NMT_RETURN; - bool on_local_stack(address adr) const { - // QQQ this has knowledge of direction, ought to be a stack method - return (_stack_base > adr && adr >= stack_end()); - } - int lgrp_id() const { return _lgrp_id; } void set_lgrp_id(int value) { _lgrp_id = value; } @@ -1651,7 +1674,7 @@ class JavaThread: public Thread { assert(_stack_reserved_zone_size == 0, "This should be called only once."); _stack_reserved_zone_size = s; } - address stack_reserved_zone_base() { + address stack_reserved_zone_base() const { return (address)(stack_end() + (stack_red_zone_size() + stack_yellow_zone_size() + stack_reserved_zone_size())); } @@ -1732,6 +1755,13 @@ class JavaThread: public Thread { stack_end() + MAX2(JavaThread::stack_guard_zone_size(), JavaThread::stack_shadow_zone_size()); } + // Check if address is in the usable part of the stack (excludes protected + // guard pages). Can be applied to any thread and is an approximation for + // using is_in_live_stack when the query has to happen from another thread. + bool is_in_usable_stack(address adr) const { + return is_in_stack_range_incl(adr, stack_reserved_zone_base()); + } + // Misc. accessors/mutators void set_do_not_unlock(void) { _do_not_unlock_if_synchronized = true; } void clr_do_not_unlock(void) { _do_not_unlock_if_synchronized = false; } diff --git a/src/hotspot/share/runtime/unhandledOops.cpp b/src/hotspot/share/runtime/unhandledOops.cpp index 368c8fba6e2..b92e01d99a4 100644 --- a/src/hotspot/share/runtime/unhandledOops.cpp +++ b/src/hotspot/share/runtime/unhandledOops.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,8 +58,9 @@ void UnhandledOops::dump_oops(UnhandledOops *list) { static Thread* unhandled_oop_print = NULL; void UnhandledOops::register_unhandled_oop(oop* op, address pc) { - if (!_thread->is_in_stack((address)op)) + if (!_thread->is_in_live_stack((address)op)) { return; + } _level++; if (unhandled_oop_print == _thread) { @@ -96,7 +97,7 @@ void UnhandledOops::allow_unhandled_oop(oop* op) { // oop list. All oops given are assumed to be on the list. If not, // there's a bug in the unhandled oop detector. void UnhandledOops::unregister_unhandled_oop(oop* op) { - if (!_thread->is_in_stack((address)op)) return; + if (!_thread->is_in_live_stack((address)op)) return; if (unhandled_oop_print == _thread) { for (int i=0; i < _level; i++) tty->print(" "); @@ -117,7 +118,7 @@ void UnhandledOops::clear_unhandled_oops() { // If an entry is on the unhandled oop list but isn't on the stack // anymore, it must not have gotten unregistered properly and it's a bug // in the unhandled oop generator. - if(!_thread->is_in_stack((address)entry._oop_ptr)) { + if (!_thread->is_in_live_stack((address)entry._oop_ptr)) { tty->print_cr("oop_ptr is " INTPTR_FORMAT, p2i(entry._oop_ptr)); tty->print_cr("thread is " INTPTR_FORMAT " from pc " INTPTR_FORMAT, p2i(_thread), p2i(entry._pc)); diff --git a/src/hotspot/share/runtime/vmOperations.cpp b/src/hotspot/share/runtime/vmOperations.cpp index 2a550926d35..780ba8e8cef 100644 --- a/src/hotspot/share/runtime/vmOperations.cpp +++ b/src/hotspot/share/runtime/vmOperations.cpp @@ -134,12 +134,11 @@ void VM_DeoptimizeAll::doit() { tcount = 0; int fcount = 0; // Deoptimize some selected frames. - // Biased llocking wants a updated register map - for(StackFrameStream fst(thread, UseBiasedLocking); !fst.is_done(); fst.next()) { + for(StackFrameStream fst(thread, false); !fst.is_done(); fst.next()) { if (fst.current()->can_be_deoptimized()) { if (fcount++ == fnum) { fcount = 0; - Deoptimization::deoptimize(thread, *fst.current(), fst.register_map()); + Deoptimization::deoptimize(thread, *fst.current()); } } } diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 76e33249d24..e999f700e13 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -327,8 +327,8 @@ typedef HashtableEntry KlassHashtableEntry; nonstatic_field(ConstMethod, _size_of_parameters, u2) \ nonstatic_field(ObjArrayKlass, _element_klass, Klass*) \ nonstatic_field(ObjArrayKlass, _bottom_klass, Klass*) \ - volatile_nonstatic_field(Symbol, _length_and_refcount, unsigned int) \ - nonstatic_field(Symbol, _identity_hash, short) \ + volatile_nonstatic_field(Symbol, _hash_and_refcount, unsigned int) \ + nonstatic_field(Symbol, _length, u2) \ unchecked_nonstatic_field(Symbol, _body, sizeof(u1)) /* NOTE: no type */ \ nonstatic_field(Symbol, _body[0], u1) \ nonstatic_field(TypeArrayKlass, _max_length, jint) \ diff --git a/src/hotspot/share/services/management.cpp b/src/hotspot/share/services/management.cpp index 29083454a34..8f8b0d5090e 100644 --- a/src/hotspot/share/services/management.cpp +++ b/src/hotspot/share/services/management.cpp @@ -1356,7 +1356,7 @@ JVM_ENTRY(jboolean, jmm_ResetStatistic(JNIEnv *env, jvalue obj, jmmStatisticType THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE); } - GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(o, CHECK_0); + GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(o, CHECK_false); if (mgr != NULL) { mgr->reset_gc_stat(); return true; @@ -1402,7 +1402,7 @@ JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env)) int nFlags = (int) JVMFlag::numFlags - 1; // allocate a temp array objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), - nFlags, CHECK_0); + nFlags, CHECK_NULL); objArrayHandle flags_ah(THREAD, r); int num_entries = 0; for (int i = 0; i < nFlags; i++) { @@ -1413,7 +1413,7 @@ JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env)) } // Exclude the locked (experimental, diagnostic) flags if (flag->is_unlocked() || flag->is_unlocker()) { - Handle s = java_lang_String::create_from_str(flag->_name, CHECK_0); + Handle s = java_lang_String::create_from_str(flag->_name, CHECK_NULL); flags_ah->obj_at_put(num_entries, s()); num_entries++; } @@ -1421,7 +1421,7 @@ JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env)) if (num_entries < nFlags) { // Return array of right length - objArrayOop res = oopFactory::new_objArray(SystemDictionary::String_klass(), num_entries, CHECK_0); + objArrayOop res = oopFactory::new_objArray(SystemDictionary::String_klass(), num_entries, CHECK_NULL); for(int i = 0; i < num_entries; i++) { res->obj_at_put(i, flags_ah->obj_at(i)); } @@ -1754,7 +1754,7 @@ static Handle find_deadlocks(bool object_monitors_only, TRAPS) { // object_monitors_only - if true, only check object monitors // JVM_ENTRY(jobjectArray, jmm_FindDeadlockedThreads(JNIEnv *env, jboolean object_monitors_only)) - Handle result = find_deadlocks(object_monitors_only != 0, CHECK_0); + Handle result = find_deadlocks(object_monitors_only != 0, CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, result()); JVM_END @@ -1762,7 +1762,7 @@ JVM_END // Returns an array of Thread objects which are in deadlock, if any. // Otherwise, returns NULL. JVM_ENTRY(jobjectArray, jmm_FindMonitorDeadlockedThreads(JNIEnv *env)) - Handle result = find_deadlocks(true, CHECK_0); + Handle result = find_deadlocks(true, CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, result()); JVM_END @@ -1810,7 +1810,7 @@ static objArrayOop get_memory_usage_objArray(jobjectArray array, int length, TRA } // check if the element of array is of type MemoryUsage class - Klass* usage_klass = Management::java_lang_management_MemoryUsage_klass(CHECK_0); + Klass* usage_klass = Management::java_lang_management_MemoryUsage_klass(CHECK_NULL); Klass* element_klass = ObjArrayKlass::cast(array_h->klass())->element_klass(); if (element_klass != usage_klass) { THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), diff --git a/src/hotspot/share/services/memoryManager.cpp b/src/hotspot/share/services/memoryManager.cpp index c0e6553d983..61041f63509 100644 --- a/src/hotspot/share/services/memoryManager.cpp +++ b/src/hotspot/share/services/memoryManager.cpp @@ -69,9 +69,9 @@ instanceOop MemoryManager::get_memory_manager_instance(TRAPS) { if (mgr_obj == NULL) { // It's ok for more than one thread to execute the code up to the locked region. // Extra manager instances will just be gc'ed. - Klass* k = Management::sun_management_ManagementFactoryHelper_klass(CHECK_0); + Klass* k = Management::sun_management_ManagementFactoryHelper_klass(CHECK_NULL); - Handle mgr_name = java_lang_String::create_from_str(name(), CHECK_0); + Handle mgr_name = java_lang_String::create_from_str(name(), CHECK_NULL); JavaValue result(T_OBJECT); JavaCallArguments args; @@ -80,7 +80,7 @@ instanceOop MemoryManager::get_memory_manager_instance(TRAPS) { Symbol* method_name = NULL; Symbol* signature = NULL; if (is_gc_memory_manager()) { - Klass* extKlass = Management::com_sun_management_internal_GarbageCollectorExtImpl_klass(CHECK_0); + Klass* extKlass = Management::com_sun_management_internal_GarbageCollectorExtImpl_klass(CHECK_NULL); // com.sun.management.GarbageCollectorMXBean is in jdk.management module which may not be present. if (extKlass != NULL) { k = extKlass; @@ -102,7 +102,7 @@ instanceOop MemoryManager::get_memory_manager_instance(TRAPS) { method_name, signature, &args, - CHECK_0); + CHECK_NULL); instanceOop m = (instanceOop) result.get_jobject(); instanceHandle mgr(THREAD, m); diff --git a/src/hotspot/share/utilities/align.hpp b/src/hotspot/share/utilities/align.hpp index c139e3938c2..50c9808c7fa 100644 --- a/src/hotspot/share/utilities/align.hpp +++ b/src/hotspot/share/utilities/align.hpp @@ -26,6 +26,7 @@ #define SHARE_UTILITIES_ALIGN_HPP #include "utilities/globalDefinitions.hpp" +#include "utilities/powerOfTwo.hpp" // Signed variants of alignment helpers. There are two versions of each, a macro // for use in places like enum definitions that require compile-time constant @@ -46,17 +47,11 @@ #define is_aligned_(size, alignment) (((size) & align_mask(alignment)) == 0) -// Temporary declaration until this file has been restructured. -template -bool is_power_of_2_t(T x) { - return (x != T(0)) && ((x & (x - 1)) == T(0)); -} - // Helpers to align sizes and check for alignment template inline T align_up(T size, A alignment) { - assert(is_power_of_2_t(alignment), "must be a power of 2: " UINT64_FORMAT, (uint64_t)alignment); + assert(is_power_of_2(alignment), "must be a power of 2: " UINT64_FORMAT, (uint64_t)alignment); T ret = align_up_(size, alignment); assert(is_aligned_(ret, alignment), "must be aligned: " UINT64_FORMAT, (uint64_t)ret); @@ -66,7 +61,7 @@ inline T align_up(T size, A alignment) { template inline T align_down(T size, A alignment) { - assert(is_power_of_2_t(alignment), "must be a power of 2: " UINT64_FORMAT, (uint64_t)alignment); + assert(is_power_of_2(alignment), "must be a power of 2: " UINT64_FORMAT, (uint64_t)alignment); T ret = align_down_(size, alignment); assert(is_aligned_(ret, alignment), "must be aligned: " UINT64_FORMAT, (uint64_t)ret); @@ -76,7 +71,7 @@ inline T align_down(T size, A alignment) { template inline bool is_aligned(T size, A alignment) { - assert(is_power_of_2_t(alignment), "must be a power of 2: " UINT64_FORMAT, (uint64_t)alignment); + assert(is_power_of_2(alignment), "must be a power of 2: " UINT64_FORMAT, (uint64_t)alignment); return is_aligned_(size, alignment); } diff --git a/src/hotspot/share/utilities/globalDefinitions.cpp b/src/hotspot/share/utilities/globalDefinitions.cpp index b9fa8ade4bb..428919ee5ed 100644 --- a/src/hotspot/share/utilities/globalDefinitions.cpp +++ b/src/hotspot/share/utilities/globalDefinitions.cpp @@ -27,6 +27,7 @@ #include "runtime/os.hpp" #include "runtime/signature.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/powerOfTwo.hpp" // Basic error support diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index d27c4b6c674..1e952b2609d 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -988,16 +988,6 @@ inline T clamp(T value, T min, T max) { return MIN2(MAX2(value, min), max); } -// true if x is a power of 2, false otherwise -inline bool is_power_of_2(intptr_t x) { - return ((x != NoBits) && (mask_bits(x, x - 1) == NoBits)); -} - -// long version of is_power_of_2 -inline bool is_power_of_2_long(jlong x) { - return ((x != NoLongBits) && (mask_long_bits(x, x - 1) == NoLongBits)); -} - // Returns largest i such that 2^i <= x. // If x == 0, the function returns -1. inline int log2_intptr(uintptr_t x) { @@ -1051,18 +1041,6 @@ inline int log2_jlong(jlong x) { return log2_long((julong)x); } -//* the argument must be exactly a power of 2 -inline int exact_log2(intptr_t x) { - assert(is_power_of_2(x), "x must be a power of 2: " INTPTR_FORMAT, x); - return log2_intptr(x); -} - -//* the argument must be exactly a power of 2 -inline int exact_log2_long(jlong x) { - assert(is_power_of_2_long(x), "x must be a power of 2: " JLONG_FORMAT, x); - return log2_long(x); -} - inline bool is_odd (intx x) { return x & 1; } inline bool is_even(intx x) { return !is_odd(x); } diff --git a/src/hotspot/share/utilities/linkedlist.hpp b/src/hotspot/share/utilities/linkedlist.hpp index 6c130cbd69e..16ee6a844fa 100644 --- a/src/hotspot/share/utilities/linkedlist.hpp +++ b/src/hotspot/share/utilities/linkedlist.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,25 @@ template class LinkedListNode : public ResourceObj { E _data; // embedded content LinkedListNode* _next; // next entry + // Select member function 'bool U::equals(const U&) const' if 'U' is of class + // type. This works because of the "Substitution Failure Is Not An Error" + // (SFINAE) rule. Notice that this version of 'equal' will also be chosen for + // class types which don't define a corresponding 'equals()' method (and will + // result in a compilation error for them). It is not easily possible to + // specialize this 'equal()' function exclusively for class types which define + // the correct 'equals()' function because that function can be in a base + // class, a dependent base class or have a compatible but slightly different + // signature. + template + static bool equal(const U& a, const U& b, bool (U::*t)(const U&) const) { + return a.equals(b); + } + + template + static bool equal(const U& a, const U& b, ...) { + return a == b; + } + protected: LinkedListNode() : _next(NULL) { } @@ -51,6 +70,10 @@ template class LinkedListNode : public ResourceObj { E* data() { return &_data; } const E* peek() const { return &_data; } + + bool equals(const E& t) const { + return equal(_data, t, NULL); + } }; // A linked list interface. It does not specify @@ -59,9 +82,11 @@ template class LinkedListNode : public ResourceObj { template class LinkedList : public ResourceObj { protected: LinkedListNode* _head; + NONCOPYABLE(LinkedList); public: LinkedList() : _head(NULL) { } + virtual ~LinkedList() {} inline void set_head(LinkedListNode* h) { _head = h; } inline LinkedListNode* head() const { return _head; } @@ -182,7 +207,7 @@ template * find_node(const E& e) { LinkedListNode* p = this->head(); - while (p != NULL && !p->peek()->equals(e)) { + while (p != NULL && !p->equals(e)) { p = p->next(); } return p; @@ -229,7 +254,7 @@ template * prev = NULL; while (tmp != NULL) { - if (tmp->peek()->equals(e)) { + if (tmp->equals(e)) { return remove_after(prev); } prev = tmp; @@ -401,16 +426,21 @@ template class LinkedListIterator : public StackObj { private: - LinkedListNode* _p; - bool _is_empty; + mutable LinkedListNode* _p; + public: - LinkedListIterator(LinkedListNode* head) : _p(head) { - _is_empty = (head == NULL); + LinkedListIterator(LinkedListNode* head) : _p(head) {} + + bool is_empty() const { return _p == NULL; } + + E* next() { + if (_p == NULL) return NULL; + E* e = _p->data(); + _p = _p->next(); + return e; } - bool is_empty() const { return _is_empty; } - - const E* next() { + const E* next() const { if (_p == NULL) return NULL; const E* e = _p->peek(); _p = _p->next(); diff --git a/src/hotspot/share/utilities/powerOfTwo.hpp b/src/hotspot/share/utilities/powerOfTwo.hpp index 7d9a0bdfddc..e197935bd7b 100644 --- a/src/hotspot/share/utilities/powerOfTwo.hpp +++ b/src/hotspot/share/utilities/powerOfTwo.hpp @@ -34,6 +34,23 @@ // Power of two convenience library. +template +bool is_power_of_2(T x) { + return (x != T(0)) && ((x & (x - 1)) == T(0)); +} + +// Log2 of a power of 2 +inline int exact_log2(intptr_t x) { + assert(is_power_of_2(x), "x must be a power of 2: " INTPTR_FORMAT, x); + return log2_intptr(x); +} + +// Log2 of a power of 2 +inline int exact_log2_long(jlong x) { + assert(is_power_of_2(x), "x must be a power of 2: " JLONG_FORMAT, x); + return log2_long(x); +} + // Round down to the closest power of two greater to or equal to the given // value. diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index d74d71ff14e..9393f62b60f 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -251,7 +251,7 @@ void VMError::print_native_stack(outputStream* st, frame fr, Thread* t, char* bu if (t && t->is_Java_thread()) { // Catch very first native frame by using stack address. // For JavaThread stack_base and stack_size should be set. - if (!t->on_local_stack((address)(fr.real_fp() + 1))) { + if (!t->is_in_full_stack((address)(fr.real_fp() + 1))) { break; } if (fr.is_java_frame() || fr.is_native_frame() || fr.is_runtime_frame()) { diff --git a/src/java.base/linux/classes/jdk/internal/platform/CgroupInfo.java b/src/java.base/linux/classes/jdk/internal/platform/CgroupInfo.java new file mode 100644 index 00000000000..b436b625850 --- /dev/null +++ b/src/java.base/linux/classes/jdk/internal/platform/CgroupInfo.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020, Red Hat Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.platform; + +/** + * Data structure to hold info from /proc/self/cgroup + * + * man 7 cgroups + * + * @see CgroupSubsystemFactory + */ +class CgroupInfo { + + private final String name; + private final int hierarchyId; + private final boolean enabled; + + private CgroupInfo(String name, int hierarchyId, boolean enabled) { + this.name = name; + this.hierarchyId = hierarchyId; + this.enabled = enabled; + } + + String getName() { + return name; + } + + int getHierarchyId() { + return hierarchyId; + } + + boolean isEnabled() { + return enabled; + } + + static CgroupInfo fromCgroupsLine(String line) { + String[] tokens = line.split("\\s+"); + if (tokens.length != 4) { + return null; + } + // discard 3'rd field, num_cgroups + return new CgroupInfo(tokens[0] /* name */, + Integer.parseInt(tokens[1]) /* hierarchyId */, + (Integer.parseInt(tokens[3]) == 1) /* enabled */); + } + +} diff --git a/src/java.base/linux/classes/jdk/internal/platform/CgroupMetrics.java b/src/java.base/linux/classes/jdk/internal/platform/CgroupMetrics.java new file mode 100644 index 00000000000..fb42229f42c --- /dev/null +++ b/src/java.base/linux/classes/jdk/internal/platform/CgroupMetrics.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2020, Red Hat Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.platform; + +import java.util.Objects; + +public class CgroupMetrics implements Metrics { + + private final CgroupSubsystem subsystem; + + CgroupMetrics(CgroupSubsystem subsystem) { + this.subsystem = Objects.requireNonNull(subsystem); + } + + @Override + public String getProvider() { + return subsystem.getProvider(); + } + + @Override + public long getCpuUsage() { + return subsystem.getCpuUsage(); + } + + @Override + public long[] getPerCpuUsage() { + return subsystem.getPerCpuUsage(); + } + + @Override + public long getCpuUserUsage() { + return subsystem.getCpuUserUsage(); + } + + @Override + public long getCpuSystemUsage() { + return subsystem.getCpuSystemUsage(); + } + + @Override + public long getCpuPeriod() { + return subsystem.getCpuPeriod(); + } + + @Override + public long getCpuQuota() { + return subsystem.getCpuQuota(); + } + + @Override + public long getCpuShares() { + return subsystem.getCpuShares(); + } + + @Override + public long getCpuNumPeriods() { + return subsystem.getCpuNumPeriods(); + } + + @Override + public long getCpuNumThrottled() { + return subsystem.getCpuNumThrottled(); + } + + @Override + public long getCpuThrottledTime() { + return subsystem.getCpuThrottledTime(); + } + + @Override + public long getEffectiveCpuCount() { + return subsystem.getEffectiveCpuCount(); + } + + @Override + public int[] getCpuSetCpus() { + return subsystem.getCpuSetCpus(); + } + + @Override + public int[] getEffectiveCpuSetCpus() { + return subsystem.getEffectiveCpuSetCpus(); + } + + @Override + public int[] getCpuSetMems() { + return subsystem.getCpuSetMems(); + } + + @Override + public int[] getEffectiveCpuSetMems() { + return subsystem.getEffectiveCpuSetMems(); + } + + public long getMemoryFailCount() { + return subsystem.getMemoryFailCount(); + } + + @Override + public long getMemoryLimit() { + return subsystem.getMemoryLimit(); + } + + @Override + public long getMemoryUsage() { + return subsystem.getMemoryUsage(); + } + + @Override + public long getTcpMemoryUsage() { + return subsystem.getTcpMemoryUsage(); + } + + @Override + public long getMemoryAndSwapLimit() { + return subsystem.getMemoryAndSwapLimit(); + } + + @Override + public long getMemoryAndSwapUsage() { + return subsystem.getMemoryAndSwapUsage(); + } + + @Override + public long getMemorySoftLimit() { + return subsystem.getMemorySoftLimit(); + } + + @Override + public long getBlkIOServiceCount() { + return subsystem.getBlkIOServiceCount(); + } + + @Override + public long getBlkIOServiced() { + return subsystem.getBlkIOServiced(); + } + + public static Metrics getInstance() { + return CgroupSubsystemFactory.create(); + } + +} \ No newline at end of file diff --git a/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystem.java b/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystem.java new file mode 100644 index 00000000000..5013e9c378c --- /dev/null +++ b/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystem.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020, Red Hat Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.platform; + +/** + * Marker interface for cgroup-based metrics + * + */ +public interface CgroupSubsystem extends Metrics { + + /** + * Returned for metrics of type long if the underlying implementation + * has determined that no limit is being imposed. + */ + public static final long LONG_RETVAL_UNLIMITED = -1; + +} diff --git a/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemController.java b/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemController.java new file mode 100644 index 00000000000..0c2e54a2634 --- /dev/null +++ b/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemController.java @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2020, Red Hat Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.platform; + +import java.io.IOException; +import java.math.BigInteger; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Stream; + +/** + * Cgroup version agnostic controller logic + * + */ +public interface CgroupSubsystemController { + + public static final String EMPTY_STR = ""; + + public String path(); + + /** + * getStringValue + * + * Return the first line of the file "param" argument from the controller. + * + * TODO: Consider using weak references for caching BufferedReader object. + * + * @param controller + * @param param + * @return Returns the contents of the file specified by param or null if + * an error occurs. + */ + public static String getStringValue(CgroupSubsystemController controller, String param) { + if (controller == null) return null; + + try { + return CgroupUtil.readStringValue(controller, param); + } + catch (IOException e) { + return null; + } + + } + + /** + * Get an entry from file "param" within the "controller" directory path + * which matches string "match". Applies "conversion" to the matching line. + * + * @param controller + * @param param + * @param match + * @param conversion + * @param defaultRetval + * @return The long value as derived by applying "conversion" to the matching + * line or "defaultRetval" if there was an error or no match found. + */ + public static long getLongValueMatchingLine(CgroupSubsystemController controller, + String param, + String match, + Function conversion, + long defaultRetval) { + long retval = defaultRetval; + if (controller == null) { + return retval; + } + try { + Path filePath = Paths.get(controller.path(), param); + List lines = CgroupUtil.readAllLinesPrivileged(filePath); + for (String line : lines) { + if (line.startsWith(match)) { + retval = conversion.apply(line); + break; + } + } + } catch (IOException e) { + // Ignore. Default is unlimited. + } + return retval; + } + + /** + * Get a long value from directory "controller" and file "param", by + * applying "conversion" to the string value within the file. + * + * @param controller + * @param param + * @param conversion + * @param defaultRetval + * @return The converted long value or "defaultRetval" if there was an + * error. + */ + public static long getLongValue(CgroupSubsystemController controller, + String param, + Function conversion, + long defaultRetval) { + String strval = getStringValue(controller, param); + if (strval == null) return defaultRetval; + return conversion.apply(strval); + } + + /** + * Get a double value from file "param" within "controller". + * + * @param controller + * @param param + * @param defaultRetval + * @return The double value or "defaultRetval" if there was an error. + */ + public static double getDoubleValue(CgroupSubsystemController controller, String param, double defaultRetval) { + String strval = getStringValue(controller, param); + + if (strval == null) return defaultRetval; + + double retval = Double.parseDouble(strval); + + return retval; + } + + /** + * getLongEntry + * + * Return the long value from the line containing the string "entryname" + * within file "param" in the "controller". + * + * TODO: Consider using weak references for caching BufferedReader object. + * + * @param controller + * @param param + * @param entryname + * @return long value or "defaultRetval" if there was an error or no match + * was found. + */ + public static long getLongEntry(CgroupSubsystemController controller, String param, String entryname, long defaultRetval) { + if (controller == null) return defaultRetval; + + try (Stream lines = CgroupUtil.readFilePrivileged(Paths.get(controller.path(), param))) { + + Optional result = lines.map(line -> line.split(" ")) + .filter(line -> (line.length == 2 && + line[0].equals(entryname))) + .map(line -> line[1]) + .findFirst(); + + return result.isPresent() ? Long.parseLong(result.get()) : defaultRetval; + } + catch (IOException e) { + return defaultRetval; + } + } + + /** + * stringRangeToIntArray + * + * Convert a string in the form of 1,3-4,6 to an array of + * integers containing all the numbers in the range. + * + * @param range + * @return int[] containing a sorted list of numbers as represented by + * the string range. Returns null if there was an error or the input + * was an empty string. + */ + public static int[] stringRangeToIntArray(String range) { + if (range == null || EMPTY_STR.equals(range)) return null; + + ArrayList results = new ArrayList<>(); + String strs[] = range.split(","); + for (String str : strs) { + if (str.contains("-")) { + String lohi[] = str.split("-"); + // validate format + if (lohi.length != 2) { + continue; + } + int lo = Integer.parseInt(lohi[0]); + int hi = Integer.parseInt(lohi[1]); + for (int i = lo; i <= hi; i++) { + results.add(i); + } + } + else { + results.add(Integer.parseInt(str)); + } + } + + // sort results + results.sort(null); + + // convert ArrayList to primitive int array + int[] ints = new int[results.size()]; + int i = 0; + for (Integer n : results) { + ints[i++] = n; + } + + return ints; + } + + /** + * Convert a number from its string representation to a long. + * + * @param strval + * @param overflowRetval + * @param defaultRetval + * @return The converted long value. "overflowRetval" is returned if the + * string representation exceeds the range of type long. + * "defaultRetval" is returned if another type of error occurred + * during conversion. + */ + public static long convertStringToLong(String strval, long overflowRetval, long defaultRetval) { + long retval = defaultRetval; + if (strval == null) return retval; + + try { + retval = Long.parseLong(strval); + } catch (NumberFormatException e) { + // For some properties (e.g. memory.limit_in_bytes, cgroups v1) we may overflow + // the range of signed long. In this case, return overflowRetval + BigInteger b = new BigInteger(strval); + if (b.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { + return overflowRetval; + } + } + return retval; + } + +} diff --git a/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemFactory.java b/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemFactory.java new file mode 100644 index 00000000000..55fcbb1f40b --- /dev/null +++ b/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemFactory.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2020, Red Hat Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.platform; + +import java.io.IOException; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Stream; + +import jdk.internal.platform.cgroupv1.CgroupV1Subsystem; +import jdk.internal.platform.cgroupv2.CgroupV2Subsystem; + +public class CgroupSubsystemFactory { + + private static final String CPU_CTRL = "cpu"; + private static final String CPUACCT_CTRL = "cpuacct"; + private static final String CPUSET_CTRL = "cpuset"; + private static final String BLKIO_CTRL = "blkio"; + private static final String MEMORY_CTRL = "memory"; + + static CgroupMetrics create() { + Optional optResult = null; + try { + optResult = determineType("/proc/self/mountinfo", "/proc/cgroups"); + } catch (IOException e) { + return null; + } + + if (optResult.isEmpty()) { + return null; + } + CgroupTypeResult result = optResult.get(); + + // If no controller is enabled, return no metrics. + if (!result.isAnyControllersEnabled()) { + return null; + } + + // Warn about mixed cgroups v1 and cgroups v2 controllers. The code is + // not ready to deal with that on a per-controller basis. Return no metrics + // in that case + if (result.isAnyCgroupV1Controllers() && result.isAnyCgroupV2Controllers()) { + Logger logger = System.getLogger("jdk.internal.platform"); + logger.log(Level.DEBUG, "Mixed cgroupv1 and cgroupv2 not supported. Metrics disabled."); + return null; + } + + if (result.isCgroupV2()) { + CgroupSubsystem subsystem = CgroupV2Subsystem.getInstance(); + return subsystem != null ? new CgroupMetrics(subsystem) : null; + } else { + CgroupV1Subsystem subsystem = CgroupV1Subsystem.getInstance(); + return subsystem != null ? new CgroupV1MetricsImpl(subsystem) : null; + } + } + + public static Optional determineType(String mountInfo, String cgroups) throws IOException { + Map infos = new HashMap<>(); + List lines = CgroupUtil.readAllLinesPrivileged(Paths.get(cgroups)); + for (String line : lines) { + if (line.startsWith("#")) { + continue; + } + CgroupInfo info = CgroupInfo.fromCgroupsLine(line); + switch (info.getName()) { + case CPU_CTRL: infos.put(CPU_CTRL, info); break; + case CPUACCT_CTRL: infos.put(CPUACCT_CTRL, info); break; + case CPUSET_CTRL: infos.put(CPUSET_CTRL, info); break; + case MEMORY_CTRL: infos.put(MEMORY_CTRL, info); break; + case BLKIO_CTRL: infos.put(BLKIO_CTRL, info); break; + } + } + + // For cgroups v2 all controllers need to have zero hierarchy id + // and /proc/self/mountinfo needs to have at least one cgroup filesystem + // mounted. Note that hybrid hierarchy has controllers mounted via + // cgroup v1. In that case hierarchy id's will be non-zero. + boolean isCgroupsV2 = true; + boolean anyControllersEnabled = false; + boolean anyCgroupsV2Controller = false; + boolean anyCgroupsV1Controller = false; + for (CgroupInfo info: infos.values()) { + anyCgroupsV1Controller = anyCgroupsV1Controller || info.getHierarchyId() != 0; + anyCgroupsV2Controller = anyCgroupsV2Controller || info.getHierarchyId() == 0; + isCgroupsV2 = isCgroupsV2 && info.getHierarchyId() == 0; + anyControllersEnabled = anyControllersEnabled || info.isEnabled(); + } + + // If there are no mounted controllers in mountinfo, but we've only + // seen 0 hierarchy IDs in /proc/cgroups, we are on a cgroups v1 system. + // However, continuing in that case does not make sense as we'd need + // information from mountinfo for the mounted controller paths anyway. + try (Stream mntInfo = CgroupUtil.readFilePrivileged(Paths.get(mountInfo))) { + boolean anyCgroupMounted = mntInfo.anyMatch(line -> line.contains("cgroup")); + if (!anyCgroupMounted && isCgroupsV2) { + return Optional.empty(); + } + } + CgroupTypeResult result = new CgroupTypeResult(isCgroupsV2, anyControllersEnabled, anyCgroupsV2Controller, anyCgroupsV1Controller); + return Optional.of(result); + } + + public static final class CgroupTypeResult { + private final boolean isCgroupV2; + private final boolean anyControllersEnabled; + private final boolean anyCgroupV2Controllers; + private final boolean anyCgroupV1Controllers; + + private CgroupTypeResult(boolean isCgroupV2, + boolean anyControllersEnabled, + boolean anyCgroupV2Controllers, + boolean anyCgroupV1Controllers) { + this.isCgroupV2 = isCgroupV2; + this.anyControllersEnabled = anyControllersEnabled; + this.anyCgroupV1Controllers = anyCgroupV1Controllers; + this.anyCgroupV2Controllers = anyCgroupV2Controllers; + } + + public boolean isCgroupV2() { + return isCgroupV2; + } + + public boolean isAnyControllersEnabled() { + return anyControllersEnabled; + } + + public boolean isAnyCgroupV2Controllers() { + return anyCgroupV2Controllers; + } + + public boolean isAnyCgroupV1Controllers() { + return anyCgroupV1Controllers; + } + } +} diff --git a/src/java.base/linux/classes/jdk/internal/platform/CgroupUtil.java b/src/java.base/linux/classes/jdk/internal/platform/CgroupUtil.java new file mode 100644 index 00000000000..1e942c599c3 --- /dev/null +++ b/src/java.base/linux/classes/jdk/internal/platform/CgroupUtil.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2020, Red Hat Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.platform; + +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.List; +import java.util.stream.Stream; + +public final class CgroupUtil { + + public static Stream readFilePrivileged(Path path) throws IOException { + try { + PrivilegedExceptionAction> pea = () -> Files.lines(path); + return AccessController.doPrivileged(pea); + } catch (PrivilegedActionException e) { + unwrapIOExceptionAndRethrow(e); + throw new InternalError(e.getCause()); + } + } + + static void unwrapIOExceptionAndRethrow(PrivilegedActionException pae) throws IOException { + Throwable x = pae.getCause(); + if (x instanceof IOException) + throw (IOException) x; + if (x instanceof RuntimeException) + throw (RuntimeException) x; + if (x instanceof Error) + throw (Error) x; + } + + static String readStringValue(CgroupSubsystemController controller, String param) throws IOException { + PrivilegedExceptionAction pea = () -> + Files.newBufferedReader(Paths.get(controller.path(), param)); + try (BufferedReader bufferedReader = + AccessController.doPrivileged(pea)) { + String line = bufferedReader.readLine(); + return line; + } catch (PrivilegedActionException e) { + unwrapIOExceptionAndRethrow(e); + throw new InternalError(e.getCause()); + } + } + + public static List readAllLinesPrivileged(Path path) throws IOException { + try { + PrivilegedExceptionAction> pea = () -> Files.readAllLines(path); + return AccessController.doPrivileged(pea); + } catch (PrivilegedActionException e) { + unwrapIOExceptionAndRethrow(e); + throw new InternalError(e.getCause()); + } + } +} diff --git a/src/java.base/linux/classes/jdk/internal/platform/CgroupV1Metrics.java b/src/java.base/linux/classes/jdk/internal/platform/CgroupV1Metrics.java new file mode 100644 index 00000000000..cf8230b0bfc --- /dev/null +++ b/src/java.base/linux/classes/jdk/internal/platform/CgroupV1Metrics.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.platform; + +/** + * + * Cgroup v1 extensions to the Metrics interface. Linux, only. + * + */ +public interface CgroupV1Metrics extends Metrics { + + /** + * Returns the largest amount of physical memory, in bytes, that + * have been allocated in the Isolation Group. + * + * @return The largest amount of memory in bytes or -1 if this + * metric is not available. Returns -2 if this metric is not + * supported. + * + */ + public long getMemoryMaxUsage(); + + /** + * Returns the number of times that kernel memory requests in the + * Isolation Group have exceeded the kernel memory limit. + * + * @return The number of exceeded requests or -1 if metric + * is not available. + * + */ + public long getKernelMemoryFailCount(); + + /** + * Returns the maximum amount of kernel physical memory, in bytes, that + * can be allocated in the Isolation Group. + * + * @return The maximum amount of memory in bytes or -1 if + * there is no limit set. + * + */ + public long getKernelMemoryLimit(); + + /** + * Returns the largest amount of kernel physical memory, in bytes, that + * have been allocated in the Isolation Group. + * + * @return The largest amount of memory in bytes or -1 if this + * metric is not available. + * + */ + public long getKernelMemoryMaxUsage(); + + /** + * Returns the amount of kernel physical memory, in bytes, that + * is currently allocated in the current Isolation Group. + * + * @return The amount of memory in bytes allocated or -1 if this + * metric is not available. + * + */ + public long getKernelMemoryUsage(); + + /** + * Returns the number of times that networking memory requests in the + * Isolation Group have exceeded the kernel memory limit. + * + * @return The number of exceeded requests or -1 if the metric + * is not available. + * + */ + public long getTcpMemoryFailCount(); + + /** + * Returns the maximum amount of networking physical memory, in bytes, + * that can be allocated in the Isolation Group. + * + * @return The maximum amount of memory in bytes or -1 if + * there is no limit. + * + */ + public long getTcpMemoryLimit(); + + /** + * Returns the largest amount of networking physical memory, in bytes, + * that have been allocated in the Isolation Group. + * + * @return The largest amount of memory in bytes or -1 if this + * metric is not available. + * + */ + public long getTcpMemoryMaxUsage(); + + /** + * Returns the number of times that user memory requests in the + * Isolation Group have exceeded the memory + swap limit. + * + * @return The number of exceeded requests or -1 if the metric + * is not available. + * + */ + public long getMemoryAndSwapFailCount(); + + /** + * Returns the largest amount of physical memory and swap space, + * in bytes, that have been allocated in the Isolation Group. + * + * @return The largest amount of memory in bytes or -1 if this + * metric is not available. + * + */ + public long getMemoryAndSwapMaxUsage(); + + /** + * Returns the state of the Operating System Out of Memory termination + * policy. + * + * @return Returns true if operating system will terminate processes + * in the Isolation Group that exceed the amount of available + * memory, otherwise false. null will be returned if this + * capability is not available on the current operating system. + * + */ + public Boolean isMemoryOOMKillEnabled(); + + /** + * Returns the (attempts per second * 1000), if enabled, that the + * operating system tries to satisfy a memory request for any + * process in the current Isolation Group when no free memory is + * readily available. Use {@link #isCpuSetMemoryPressureEnabled()} to + * determine if this support is enabled. + * + * @return Memory pressure or 0 if not enabled or -1 if metric is not + * available. + * + */ + public double getCpuSetMemoryPressure(); + + /** + * Returns the state of the memory pressure detection support. + * + * @return true if support is available and enabled. false otherwise. + * + */ + public Boolean isCpuSetMemoryPressureEnabled(); +} diff --git a/src/java.base/linux/classes/jdk/internal/platform/CgroupV1MetricsImpl.java b/src/java.base/linux/classes/jdk/internal/platform/CgroupV1MetricsImpl.java new file mode 100644 index 00000000000..443b58f1f9d --- /dev/null +++ b/src/java.base/linux/classes/jdk/internal/platform/CgroupV1MetricsImpl.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2020, Red Hat Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.platform; + +/** + * Cgroup v1 Metrics extensions + * + */ +public class CgroupV1MetricsImpl extends CgroupMetrics implements CgroupV1Metrics { + + private final CgroupV1Metrics metrics; + + CgroupV1MetricsImpl(CgroupV1Metrics metrics) { + super((CgroupSubsystem)metrics); + this.metrics = metrics; + } + + @Override + public long getMemoryMaxUsage() { + return metrics.getMemoryMaxUsage(); + } + + @Override + public long getKernelMemoryFailCount() { + return metrics.getKernelMemoryFailCount(); + } + + @Override + public long getKernelMemoryLimit() { + return metrics.getKernelMemoryLimit(); + } + + @Override + public long getKernelMemoryMaxUsage() { + return metrics.getKernelMemoryMaxUsage(); + } + + @Override + public long getKernelMemoryUsage() { + return metrics.getKernelMemoryUsage(); + } + + @Override + public long getTcpMemoryFailCount() { + return metrics.getTcpMemoryFailCount(); + } + + @Override + public long getTcpMemoryLimit() { + return metrics.getTcpMemoryLimit(); + } + + @Override + public long getTcpMemoryMaxUsage() { + return metrics.getTcpMemoryMaxUsage(); + } + + @Override + public long getMemoryAndSwapFailCount() { + return metrics.getMemoryAndSwapFailCount(); + } + + @Override + public long getMemoryAndSwapMaxUsage() { + return metrics.getMemoryAndSwapMaxUsage(); + } + + @Override + public Boolean isMemoryOOMKillEnabled() { + return metrics.isMemoryOOMKillEnabled(); + } + + @Override + public double getCpuSetMemoryPressure() { + return metrics.getCpuSetMemoryPressure(); + } + + @Override + public Boolean isCpuSetMemoryPressureEnabled() { + return metrics.isCpuSetMemoryPressureEnabled(); + } + +} diff --git a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1MemorySubSystemController.java b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1MemorySubSystemController.java new file mode 100644 index 00000000000..6153d64efae --- /dev/null +++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1MemorySubSystemController.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020, Red Hat Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.platform.cgroupv1; + +public class CgroupV1MemorySubSystemController extends CgroupV1SubsystemController { + + private boolean hierarchical; + + public CgroupV1MemorySubSystemController(String root, String mountPoint) { + super(root, mountPoint); + } + + boolean isHierarchical() { + return hierarchical; + } + + void setHierarchical(boolean hierarchical) { + this.hierarchical = hierarchical; + } + +} \ No newline at end of file diff --git a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java similarity index 53% rename from src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java rename to src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java index 8a682f1ea04..fd1867d5cf2 100644 --- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java +++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,41 +26,37 @@ package jdk.internal.platform.cgroupv1; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.stream.Stream; -import jdk.internal.platform.cgroupv1.SubSystem.MemorySubSystem; +import jdk.internal.platform.CgroupSubsystem; +import jdk.internal.platform.CgroupSubsystemController; +import jdk.internal.platform.CgroupUtil; +import jdk.internal.platform.CgroupV1Metrics; -public class Metrics implements jdk.internal.platform.Metrics { - private MemorySubSystem memory; - private SubSystem cpu; - private SubSystem cpuacct; - private SubSystem cpuset; - private SubSystem blkio; +public class CgroupV1Subsystem implements CgroupSubsystem, CgroupV1Metrics { + private CgroupV1MemorySubSystemController memory; + private CgroupV1SubsystemController cpu; + private CgroupV1SubsystemController cpuacct; + private CgroupV1SubsystemController cpuset; + private CgroupV1SubsystemController blkio; private boolean activeSubSystems; - // Values returned larger than this number are unlimited. - static long unlimited_minimum = 0x7FFFFFFFFF000000L; - - private static final Metrics INSTANCE = initContainerSubSystems(); + private static final CgroupV1Subsystem INSTANCE = initSubSystem(); private static final String PROVIDER_NAME = "cgroupv1"; - private Metrics() { + private CgroupV1Subsystem() { activeSubSystems = false; } - public static Metrics getInstance() { + public static CgroupV1Subsystem getInstance() { return INSTANCE; } - private static Metrics initContainerSubSystems() { - Metrics metrics = new Metrics(); + private static CgroupV1Subsystem initSubSystem() { + CgroupV1Subsystem subsystem = new CgroupV1Subsystem(); /** * Find the cgroup mount points for subsystems @@ -73,11 +69,11 @@ public class Metrics implements jdk.internal.platform.Metrics { * 34 28 0:29 / /sys/fs/cgroup/MemorySubSystem rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,MemorySubSystem */ try (Stream lines = - readFilePrivileged(Paths.get("/proc/self/mountinfo"))) { + CgroupUtil.readFilePrivileged(Paths.get("/proc/self/mountinfo"))) { lines.filter(line -> line.contains(" - cgroup ")) .map(line -> line.split(" ")) - .forEach(entry -> createSubSystem(metrics, entry)); + .forEach(entry -> createSubSystemController(subsystem, entry)); } catch (IOException e) { return null; @@ -107,47 +103,28 @@ public class Metrics implements jdk.internal.platform.Metrics { * */ try (Stream lines = - readFilePrivileged(Paths.get("/proc/self/cgroup"))) { + CgroupUtil.readFilePrivileged(Paths.get("/proc/self/cgroup"))) { lines.map(line -> line.split(":")) .filter(line -> (line.length >= 3)) - .forEach(line -> setSubSystemPath(metrics, line)); + .forEach(line -> setSubSystemControllerPath(subsystem, line)); } catch (IOException e) { return null; } // Return Metrics object if we found any subsystems. - if (metrics.activeSubSystems()) { - return metrics; + if (subsystem.activeSubSystems()) { + return subsystem; } return null; } - static Stream readFilePrivileged(Path path) throws IOException { - try { - PrivilegedExceptionAction> pea = () -> Files.lines(path); - return AccessController.doPrivileged(pea); - } catch (PrivilegedActionException e) { - unwrapIOExceptionAndRethrow(e); - throw new InternalError(e.getCause()); - } - } - - static void unwrapIOExceptionAndRethrow(PrivilegedActionException pae) throws IOException { - Throwable x = pae.getCause(); - if (x instanceof IOException) - throw (IOException) x; - if (x instanceof RuntimeException) - throw (RuntimeException) x; - if (x instanceof Error) - throw (Error) x; - } /** * createSubSystem objects and initialize mount points */ - private static void createSubSystem(Metrics metric, String[] mountentry) { + private static void createSubSystemController(CgroupV1Subsystem subsystem, String[] mountentry) { if (mountentry.length < 5) return; Path p = Paths.get(mountentry[4]); @@ -156,19 +133,19 @@ public class Metrics implements jdk.internal.platform.Metrics { for (String subsystemName: subsystemNames) { switch (subsystemName) { case "memory": - metric.setMemorySubSystem(new MemorySubSystem(mountentry[3], mountentry[4])); + subsystem.setMemorySubSystem(new CgroupV1MemorySubSystemController(mountentry[3], mountentry[4])); break; case "cpuset": - metric.setCpuSetSubSystem(new SubSystem(mountentry[3], mountentry[4])); + subsystem.setCpuSetController(new CgroupV1SubsystemController(mountentry[3], mountentry[4])); break; case "cpuacct": - metric.setCpuAcctSubSystem(new SubSystem(mountentry[3], mountentry[4])); + subsystem.setCpuAcctController(new CgroupV1SubsystemController(mountentry[3], mountentry[4])); break; case "cpu": - metric.setCpuSubSystem(new SubSystem(mountentry[3], mountentry[4])); + subsystem.setCpuController(new CgroupV1SubsystemController(mountentry[3], mountentry[4])); break; case "blkio": - metric.setBlkIOSubSystem(new SubSystem(mountentry[3], mountentry[4])); + subsystem.setBlkIOController(new CgroupV1SubsystemController(mountentry[3], mountentry[4])); break; default: // Ignore subsystems that we don't support @@ -180,35 +157,35 @@ public class Metrics implements jdk.internal.platform.Metrics { /** * setSubSystemPath based on the contents of /proc/self/cgroup */ - private static void setSubSystemPath(Metrics metric, String[] entry) { - String controller; + private static void setSubSystemControllerPath(CgroupV1Subsystem subsystem, String[] entry) { + String controllerName; String base; - SubSystem subsystem = null; - SubSystem subsystem2 = null; + CgroupV1SubsystemController controller = null; + CgroupV1SubsystemController controller2 = null; - controller = entry[1]; + controllerName = entry[1]; base = entry[2]; - if (controller != null && base != null) { - switch (controller) { + if (controllerName != null && base != null) { + switch (controllerName) { case "memory": - subsystem = metric.MemorySubSystem(); + controller = subsystem.memoryController(); break; case "cpuset": - subsystem = metric.CpuSetSubSystem(); + controller = subsystem.cpuSetController(); break; case "cpu,cpuacct": case "cpuacct,cpu": - subsystem = metric.CpuSubSystem(); - subsystem2 = metric.CpuAcctSubSystem(); + controller = subsystem.cpuController(); + controller2 = subsystem.cpuAcctController(); break; case "cpuacct": - subsystem = metric.CpuAcctSubSystem(); + controller = subsystem.cpuAcctController(); break; case "cpu": - subsystem = metric.CpuSubSystem(); + controller = subsystem.cpuController(); break; case "blkio": - subsystem = metric.BlkIOSubSystem(); + controller = subsystem.blkIOController(); break; // Ignore subsystems that we don't support default: @@ -216,23 +193,23 @@ public class Metrics implements jdk.internal.platform.Metrics { } } - if (subsystem != null) { - subsystem.setPath(base); - if (subsystem instanceof MemorySubSystem) { - MemorySubSystem memorySubSystem = (MemorySubSystem)subsystem; + if (controller != null) { + controller.setPath(base); + if (controller instanceof CgroupV1MemorySubSystemController) { + CgroupV1MemorySubSystemController memorySubSystem = (CgroupV1MemorySubSystemController)controller; boolean isHierarchial = getHierarchical(memorySubSystem); memorySubSystem.setHierarchical(isHierarchial); } - metric.setActiveSubSystems(); + subsystem.setActiveSubSystems(); } - if (subsystem2 != null) { - subsystem2.setPath(base); + if (controller2 != null) { + controller2.setPath(base); } } - private static boolean getHierarchical(MemorySubSystem subsystem) { - long hierarchical = SubSystem.getLongValue(subsystem, "memory.use_hierarchy"); + private static boolean getHierarchical(CgroupV1MemorySubSystemController controller) { + long hierarchical = getLongValue(controller, "memory.use_hierarchy"); return hierarchical > 0; } @@ -244,46 +221,54 @@ public class Metrics implements jdk.internal.platform.Metrics { return activeSubSystems; } - private void setMemorySubSystem(MemorySubSystem memory) { + private void setMemorySubSystem(CgroupV1MemorySubSystemController memory) { this.memory = memory; } - private void setCpuSubSystem(SubSystem cpu) { + private void setCpuController(CgroupV1SubsystemController cpu) { this.cpu = cpu; } - private void setCpuAcctSubSystem(SubSystem cpuacct) { + private void setCpuAcctController(CgroupV1SubsystemController cpuacct) { this.cpuacct = cpuacct; } - private void setCpuSetSubSystem(SubSystem cpuset) { + private void setCpuSetController(CgroupV1SubsystemController cpuset) { this.cpuset = cpuset; } - private void setBlkIOSubSystem(SubSystem blkio) { + private void setBlkIOController(CgroupV1SubsystemController blkio) { this.blkio = blkio; } - private SubSystem MemorySubSystem() { + private CgroupV1SubsystemController memoryController() { return memory; } - private SubSystem CpuSubSystem() { + private CgroupV1SubsystemController cpuController() { return cpu; } - private SubSystem CpuAcctSubSystem() { + private CgroupV1SubsystemController cpuAcctController() { return cpuacct; } - private SubSystem CpuSetSubSystem() { + private CgroupV1SubsystemController cpuSetController() { return cpuset; } - private SubSystem BlkIOSubSystem() { + private CgroupV1SubsystemController blkIOController() { return blkio; } + private static long getLongValue(CgroupSubsystemController controller, + String parm) { + return CgroupSubsystemController.getLongValue(controller, + parm, + CgroupV1SubsystemController::convertStringToLong, + CgroupSubsystem.LONG_RETVAL_UNLIMITED); + } + public String getProvider() { return PROVIDER_NAME; } @@ -294,13 +279,13 @@ public class Metrics implements jdk.internal.platform.Metrics { public long getCpuUsage() { - return SubSystem.getLongValue(cpuacct, "cpuacct.usage"); + return getLongValue(cpuacct, "cpuacct.usage"); } public long[] getPerCpuUsage() { - String usagelist = SubSystem.getStringValue(cpuacct, "cpuacct.usage_percpu"); + String usagelist = CgroupSubsystemController.getStringValue(cpuacct, "cpuacct.usage_percpu"); if (usagelist == null) { - return new long[0]; + return null; } String list[] = usagelist.split(" "); @@ -312,11 +297,11 @@ public class Metrics implements jdk.internal.platform.Metrics { } public long getCpuUserUsage() { - return SubSystem.getLongEntry(cpuacct, "cpuacct.stat", "user"); + return CgroupV1SubsystemController.getLongEntry(cpuacct, "cpuacct.stat", "user"); } public long getCpuSystemUsage() { - return SubSystem.getLongEntry(cpuacct, "cpuacct.stat", "system"); + return CgroupV1SubsystemController.getLongEntry(cpuacct, "cpuacct.stat", "system"); } @@ -326,31 +311,31 @@ public class Metrics implements jdk.internal.platform.Metrics { public long getCpuPeriod() { - return SubSystem.getLongValue(cpu, "cpu.cfs_period_us"); + return getLongValue(cpu, "cpu.cfs_period_us"); } public long getCpuQuota() { - return SubSystem.getLongValue(cpu, "cpu.cfs_quota_us"); + return getLongValue(cpu, "cpu.cfs_quota_us"); } public long getCpuShares() { - long retval = SubSystem.getLongValue(cpu, "cpu.shares"); + long retval = getLongValue(cpu, "cpu.shares"); if (retval == 0 || retval == 1024) - return -1; + return CgroupSubsystem.LONG_RETVAL_UNLIMITED; else return retval; } public long getCpuNumPeriods() { - return SubSystem.getLongEntry(cpu, "cpu.stat", "nr_periods"); + return CgroupV1SubsystemController.getLongEntry(cpu, "cpu.stat", "nr_periods"); } public long getCpuNumThrottled() { - return SubSystem.getLongEntry(cpu, "cpu.stat", "nr_throttled"); + return CgroupV1SubsystemController.getLongEntry(cpu, "cpu.stat", "nr_throttled"); } public long getCpuThrottledTime() { - return SubSystem.getLongEntry(cpu, "cpu.stat", "throttled_time"); + return CgroupV1SubsystemController.getLongEntry(cpu, "cpu.stat", "throttled_time"); } public long getEffectiveCpuCount() { @@ -363,27 +348,27 @@ public class Metrics implements jdk.internal.platform.Metrics { ****************************************************************/ public int[] getCpuSetCpus() { - return SubSystem.StringRangeToIntArray(SubSystem.getStringValue(cpuset, "cpuset.cpus")); + return CgroupSubsystemController.stringRangeToIntArray(CgroupSubsystemController.getStringValue(cpuset, "cpuset.cpus")); } public int[] getEffectiveCpuSetCpus() { - return SubSystem.StringRangeToIntArray(SubSystem.getStringValue(cpuset, "cpuset.effective_cpus")); + return CgroupSubsystemController.stringRangeToIntArray(CgroupSubsystemController.getStringValue(cpuset, "cpuset.effective_cpus")); } public int[] getCpuSetMems() { - return SubSystem.StringRangeToIntArray(SubSystem.getStringValue(cpuset, "cpuset.mems")); + return CgroupSubsystemController.stringRangeToIntArray(CgroupSubsystemController.getStringValue(cpuset, "cpuset.mems")); } public int[] getEffectiveCpuSetMems() { - return SubSystem.StringRangeToIntArray(SubSystem.getStringValue(cpuset, "cpuset.effective_mems")); + return CgroupSubsystemController.stringRangeToIntArray(CgroupSubsystemController.getStringValue(cpuset, "cpuset.effective_mems")); } public double getCpuSetMemoryPressure() { - return SubSystem.getDoubleValue(cpuset, "cpuset.memory_pressure"); + return CgroupV1SubsystemController.getDoubleValue(cpuset, "cpuset.memory_pressure"); } - public boolean isCpuSetMemoryPressureEnabled() { - long val = SubSystem.getLongValue(cpuset, "cpuset.memory_pressure_enabled"); + public Boolean isCpuSetMemoryPressureEnabled() { + long val = getLongValue(cpuset, "cpuset.memory_pressure_enabled"); return (val == 1); } @@ -394,112 +379,98 @@ public class Metrics implements jdk.internal.platform.Metrics { public long getMemoryFailCount() { - return SubSystem.getLongValue(memory, "memory.failcnt"); + return getLongValue(memory, "memory.failcnt"); } public long getMemoryLimit() { - long retval = SubSystem.getLongValue(memory, "memory.limit_in_bytes"); - if (retval > unlimited_minimum) { + long retval = getLongValue(memory, "memory.limit_in_bytes"); + if (retval > CgroupV1SubsystemController.UNLIMITED_MIN) { if (memory.isHierarchical()) { // memory.limit_in_bytes returned unlimited, attempt // hierarchical memory limit String match = "hierarchical_memory_limit"; - retval = SubSystem.getLongValueMatchingLine(memory, + retval = CgroupV1SubsystemController.getLongValueMatchingLine(memory, "memory.stat", - match, - Metrics::convertHierachicalLimitLine); + match); } } - return retval > unlimited_minimum ? -1L : retval; - } - - public static long convertHierachicalLimitLine(String line) { - String[] tokens = line.split("\\s"); - if (tokens.length == 2) { - String strVal = tokens[1]; - return SubSystem.convertStringToLong(strVal); - } - return unlimited_minimum + 1; // unlimited + return CgroupV1SubsystemController.longValOrUnlimited(retval); } public long getMemoryMaxUsage() { - return SubSystem.getLongValue(memory, "memory.max_usage_in_bytes"); + return getLongValue(memory, "memory.max_usage_in_bytes"); } public long getMemoryUsage() { - return SubSystem.getLongValue(memory, "memory.usage_in_bytes"); + return getLongValue(memory, "memory.usage_in_bytes"); } public long getKernelMemoryFailCount() { - return SubSystem.getLongValue(memory, "memory.kmem.failcnt"); + return getLongValue(memory, "memory.kmem.failcnt"); } public long getKernelMemoryLimit() { - long retval = SubSystem.getLongValue(memory, "memory.kmem.limit_in_bytes"); - return retval > unlimited_minimum ? -1L : retval; + return CgroupV1SubsystemController.longValOrUnlimited(getLongValue(memory, "memory.kmem.limit_in_bytes")); } public long getKernelMemoryMaxUsage() { - return SubSystem.getLongValue(memory, "memory.kmem.max_usage_in_bytes"); + return getLongValue(memory, "memory.kmem.max_usage_in_bytes"); } public long getKernelMemoryUsage() { - return SubSystem.getLongValue(memory, "memory.kmem.usage_in_bytes"); + return getLongValue(memory, "memory.kmem.usage_in_bytes"); } public long getTcpMemoryFailCount() { - return SubSystem.getLongValue(memory, "memory.kmem.tcp.failcnt"); + return getLongValue(memory, "memory.kmem.tcp.failcnt"); } public long getTcpMemoryLimit() { - long retval = SubSystem.getLongValue(memory, "memory.kmem.tcp.limit_in_bytes"); - return retval > unlimited_minimum ? -1L : retval; + return CgroupV1SubsystemController.longValOrUnlimited(getLongValue(memory, "memory.kmem.tcp.limit_in_bytes")); } public long getTcpMemoryMaxUsage() { - return SubSystem.getLongValue(memory, "memory.kmem.tcp.max_usage_in_bytes"); + return getLongValue(memory, "memory.kmem.tcp.max_usage_in_bytes"); } public long getTcpMemoryUsage() { - return SubSystem.getLongValue(memory, "memory.kmem.tcp.usage_in_bytes"); + return getLongValue(memory, "memory.kmem.tcp.usage_in_bytes"); } public long getMemoryAndSwapFailCount() { - return SubSystem.getLongValue(memory, "memory.memsw.failcnt"); + return getLongValue(memory, "memory.memsw.failcnt"); } public long getMemoryAndSwapLimit() { - long retval = SubSystem.getLongValue(memory, "memory.memsw.limit_in_bytes"); - if (retval > unlimited_minimum) { + long retval = getLongValue(memory, "memory.memsw.limit_in_bytes"); + if (retval > CgroupV1SubsystemController.UNLIMITED_MIN) { if (memory.isHierarchical()) { // memory.memsw.limit_in_bytes returned unlimited, attempt // hierarchical memory limit String match = "hierarchical_memsw_limit"; - retval = SubSystem.getLongValueMatchingLine(memory, + retval = CgroupV1SubsystemController.getLongValueMatchingLine(memory, "memory.stat", - match, - Metrics::convertHierachicalLimitLine); + match); } } - return retval > unlimited_minimum ? -1L : retval; + return CgroupV1SubsystemController.longValOrUnlimited(retval); } public long getMemoryAndSwapMaxUsage() { - return SubSystem.getLongValue(memory, "memory.memsw.max_usage_in_bytes"); + return getLongValue(memory, "memory.memsw.max_usage_in_bytes"); } public long getMemoryAndSwapUsage() { - return SubSystem.getLongValue(memory, "memory.memsw.usage_in_bytes"); + return getLongValue(memory, "memory.memsw.usage_in_bytes"); } - public boolean isMemoryOOMKillEnabled() { - long val = SubSystem.getLongEntry(memory, "memory.oom_control", "oom_kill_disable"); + public Boolean isMemoryOOMKillEnabled() { + long val = CgroupV1SubsystemController.getLongEntry(memory, "memory.oom_control", "oom_kill_disable"); return (val == 0); } public long getMemorySoftLimit() { - long retval = SubSystem.getLongValue(memory, "memory.soft_limit_in_bytes"); - return retval > unlimited_minimum ? -1L : retval; + return CgroupV1SubsystemController.longValOrUnlimited(getLongValue(memory, "memory.soft_limit_in_bytes")); } @@ -509,11 +480,11 @@ public class Metrics implements jdk.internal.platform.Metrics { public long getBlkIOServiceCount() { - return SubSystem.getLongEntry(blkio, "blkio.throttle.io_service_bytes", "Total"); + return CgroupV1SubsystemController.getLongEntry(blkio, "blkio.throttle.io_service_bytes", "Total"); } public long getBlkIOServiced() { - return SubSystem.getLongEntry(blkio, "blkio.throttle.io_serviced", "Total"); + return CgroupV1SubsystemController.getLongEntry(blkio, "blkio.throttle.io_serviced", "Total"); } } diff --git a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1SubsystemController.java b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1SubsystemController.java new file mode 100644 index 00000000000..5bc3c297499 --- /dev/null +++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1SubsystemController.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.platform.cgroupv1; + +import jdk.internal.platform.CgroupSubsystem; +import jdk.internal.platform.CgroupSubsystemController; + +public class CgroupV1SubsystemController implements CgroupSubsystemController { + + private static final double DOUBLE_RETVAL_UNLIMITED = CgroupSubsystem.LONG_RETVAL_UNLIMITED; + // Values returned larger than this number are unlimited. + static long UNLIMITED_MIN = 0x7FFFFFFFFF000000L; + String root; + String mountPoint; + String path; + + public CgroupV1SubsystemController(String root, String mountPoint) { + this.root = root; + this.mountPoint = mountPoint; + } + + public void setPath(String cgroupPath) { + if (root != null && cgroupPath != null) { + if (root.equals("/")) { + if (!cgroupPath.equals("/")) { + path = mountPoint + cgroupPath; + } + else { + path = mountPoint; + } + } + else { + if (root.equals(cgroupPath)) { + path = mountPoint; + } + else { + if (cgroupPath.startsWith(root)) { + if (cgroupPath.length() > root.length()) { + String cgroupSubstr = cgroupPath.substring(root.length()); + path = mountPoint + cgroupSubstr; + } + } + } + } + } + } + + @Override + public String path() { + return path; + } + + public static long getLongEntry(CgroupSubsystemController controller, String param, String entryname) { + return CgroupSubsystemController.getLongEntry(controller, + param, + entryname, + CgroupSubsystem.LONG_RETVAL_UNLIMITED /* retval on error */); + } + + public static double getDoubleValue(CgroupSubsystemController controller, String parm) { + return CgroupSubsystemController.getDoubleValue(controller, + parm, + DOUBLE_RETVAL_UNLIMITED /* retval on error */); + } + + public static long convertStringToLong(String strval) { + return CgroupSubsystemController.convertStringToLong(strval, + Long.MAX_VALUE /* overflow value */, + CgroupSubsystem.LONG_RETVAL_UNLIMITED /* retval on error */); + } + + public static long longValOrUnlimited(long value) { + return value > UNLIMITED_MIN ? CgroupSubsystem.LONG_RETVAL_UNLIMITED : value; + } + + public static long getLongValueMatchingLine(CgroupSubsystemController controller, + String param, + String match) { + return CgroupSubsystemController.getLongValueMatchingLine(controller, + param, + match, + CgroupV1SubsystemController::convertHierachicalLimitLine, + CgroupSubsystem.LONG_RETVAL_UNLIMITED); + } + + public static long convertHierachicalLimitLine(String line) { + String[] tokens = line.split("\\s"); + if (tokens.length == 2) { + String strVal = tokens[1]; + return CgroupV1SubsystemController.convertStringToLong(strVal); + } + return CgroupV1SubsystemController.UNLIMITED_MIN + 1; // unlimited + } + +} diff --git a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java deleted file mode 100644 index ef8d8d1167d..00000000000 --- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.internal.platform.cgroupv1; - -import java.io.BufferedReader; -import java.io.IOException; -import java.math.BigInteger; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Stream; - -public class SubSystem { - String root; - String mountPoint; - String path; - - public SubSystem(String root, String mountPoint) { - this.root = root; - this.mountPoint = mountPoint; - } - - public void setPath(String cgroupPath) { - if (root != null && cgroupPath != null) { - if (root.equals("/")) { - if (!cgroupPath.equals("/")) { - path = mountPoint + cgroupPath; - } - else { - path = mountPoint; - } - } - else { - if (root.equals(cgroupPath)) { - path = mountPoint; - } - else { - if (cgroupPath.startsWith(root)) { - if (cgroupPath.length() > root.length()) { - String cgroupSubstr = cgroupPath.substring(root.length()); - path = mountPoint + cgroupSubstr; - } - } - } - } - } - } - - public String path() { - return path; - } - - /** - * getSubSystemStringValue - * - * Return the first line of the file "parm" argument from the subsystem. - * - * TODO: Consider using weak references for caching BufferedReader object. - * - * @param subsystem - * @param parm - * @return Returns the contents of the file specified by param. - */ - public static String getStringValue(SubSystem subsystem, String parm) { - if (subsystem == null) return null; - - try { - return subsystem.readStringValue(parm); - } catch (IOException e) { - return null; - } - } - - private String readStringValue(String param) throws IOException { - PrivilegedExceptionAction pea = () -> - Files.newBufferedReader(Paths.get(path(), param)); - try (BufferedReader bufferedReader = - AccessController.doPrivileged(pea)) { - String line = bufferedReader.readLine(); - return line; - } catch (PrivilegedActionException e) { - Metrics.unwrapIOExceptionAndRethrow(e); - throw new InternalError(e.getCause()); - } - } - - public static long getLongValueMatchingLine(SubSystem subsystem, - String param, - String match, - Function conversion) { - long retval = Metrics.unlimited_minimum + 1; // default unlimited - try { - List lines = subsystem.readMatchingLines(param); - for (String line : lines) { - if (line.startsWith(match)) { - retval = conversion.apply(line); - break; - } - } - } catch (IOException e) { - // Ignore. Default is unlimited. - } - return retval; - } - - private List readMatchingLines(String param) throws IOException { - try { - PrivilegedExceptionAction> pea = () -> - Files.readAllLines(Paths.get(path(), param)); - return AccessController.doPrivileged(pea); - } catch (PrivilegedActionException e) { - Metrics.unwrapIOExceptionAndRethrow(e); - throw new InternalError(e.getCause()); - } - } - - public static long getLongValue(SubSystem subsystem, String parm) { - String strval = getStringValue(subsystem, parm); - return convertStringToLong(strval); - } - - public static long convertStringToLong(String strval) { - long retval = 0; - if (strval == null) return 0L; - - try { - retval = Long.parseLong(strval); - } catch (NumberFormatException e) { - // For some properties (e.g. memory.limit_in_bytes) we may overflow the range of signed long. - // In this case, return Long.MAX_VALUE - BigInteger b = new BigInteger(strval); - if (b.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { - return Long.MAX_VALUE; - } - } - return retval; - } - - public static double getDoubleValue(SubSystem subsystem, String parm) { - String strval = getStringValue(subsystem, parm); - - if (strval == null) return 0L; - - double retval = Double.parseDouble(strval); - - return retval; - } - - /** - * getSubSystemlongEntry - * - * Return the long value from the line containing the string "entryname" - * within file "parm" in the "subsystem". - * - * TODO: Consider using weak references for caching BufferedReader object. - * - * @param subsystem - * @param parm - * @param entryname - * @return long value - */ - public static long getLongEntry(SubSystem subsystem, String parm, String entryname) { - String val = null; - - if (subsystem == null) return 0L; - - try (Stream lines = Metrics.readFilePrivileged(Paths.get(subsystem.path(), parm))) { - - Optional result = lines.map(line -> line.split(" ")) - .filter(line -> (line.length == 2 && - line[0].equals(entryname))) - .map(line -> line[1]) - .findFirst(); - - return result.isPresent() ? Long.parseLong(result.get()) : 0L; - } - catch (IOException e) { - return 0L; - } - } - - public static int getIntValue(SubSystem subsystem, String parm) { - String val = getStringValue(subsystem, parm); - - if (val == null) return 0; - - return Integer.parseInt(val); - } - - /** - * StringRangeToIntArray - * - * Convert a string in the form of 1,3-4,6 to an array of - * integers containing all the numbers in the range. - * - * @param range - * @return int[] containing a sorted list of processors or memory nodes - */ - public static int[] StringRangeToIntArray(String range) { - int[] ints = new int[0]; - - if (range == null) return ints; - - ArrayList results = new ArrayList<>(); - String strs[] = range.split(","); - for (String str : strs) { - if (str.contains("-")) { - String lohi[] = str.split("-"); - // validate format - if (lohi.length != 2) { - continue; - } - int lo = Integer.parseInt(lohi[0]); - int hi = Integer.parseInt(lohi[1]); - for (int i = lo; i <= hi; i++) { - results.add(i); - } - } - else { - results.add(Integer.parseInt(str)); - } - } - - // sort results - results.sort(null); - - // convert ArrayList to primitive int array - ints = new int[results.size()]; - int i = 0; - for (Integer n : results) { - ints[i++] = n; - } - - return ints; - } - - public static class MemorySubSystem extends SubSystem { - - private boolean hierarchical; - - public MemorySubSystem(String root, String mountPoint) { - super(root, mountPoint); - } - - boolean isHierarchical() { - return hierarchical; - } - - void setHierarchical(boolean hierarchical) { - this.hierarchical = hierarchical; - } - - } -} diff --git a/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2Subsystem.java b/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2Subsystem.java new file mode 100644 index 00000000000..15d5869794e --- /dev/null +++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2Subsystem.java @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2020, Red Hat Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.platform.cgroupv2; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import jdk.internal.platform.CgroupSubsystem; +import jdk.internal.platform.CgroupSubsystemController; +import jdk.internal.platform.CgroupUtil; + +public class CgroupV2Subsystem implements CgroupSubsystem { + + private static final CgroupV2Subsystem INSTANCE = initSubsystem(); + private static final long[] LONG_ARRAY_NOT_SUPPORTED = null; + private static final int[] INT_ARRAY_UNAVAILABLE = null; + private final CgroupSubsystemController unified; + private static final String PROVIDER_NAME = "cgroupv2"; + private static final int PER_CPU_SHARES = 1024; + private static final String MAX_VAL = "max"; + private static final Object EMPTY_STR = ""; + + private CgroupV2Subsystem(CgroupSubsystemController unified) { + this.unified = unified; + } + + private long getLongVal(String file) { + return CgroupSubsystemController.getLongValue(unified, + file, + CgroupV2SubsystemController::convertStringToLong, + CgroupSubsystem.LONG_RETVAL_UNLIMITED); + } + + private static CgroupV2Subsystem initSubsystem() { + // read mountinfo so as to determine root mount path + String mountPath = null; + try (Stream lines = + CgroupUtil.readFilePrivileged(Paths.get("/proc/self/mountinfo"))) { + + String l = lines.filter(line -> line.contains(" - cgroup2 ")) + .collect(Collectors.joining()); + String[] tokens = l.split(" "); + mountPath = tokens[4]; + } catch (IOException e) { + return null; + } + String cgroupPath = null; + try { + List lines = CgroupUtil.readAllLinesPrivileged(Paths.get("/proc/self/cgroup")); + for (String line: lines) { + String[] tokens = line.split(":"); + if (tokens.length != 3) { + return null; // something is not right. + } + if (!"0".equals(tokens[0])) { + // hierarchy must be zero for cgroups v2 + return null; + } + cgroupPath = tokens[2]; + break; + } + } catch (IOException e) { + return null; + } + CgroupSubsystemController unified = new CgroupV2SubsystemController( + mountPath, + cgroupPath); + return new CgroupV2Subsystem(unified); + } + + public static CgroupSubsystem getInstance() { + return INSTANCE; + } + + @Override + public String getProvider() { + return PROVIDER_NAME; + } + + @Override + public long getCpuUsage() { + long micros = CgroupV2SubsystemController.getLongEntry(unified, "cpu.stat", "usage_usec"); + if (micros < 0) { + return micros; + } + return TimeUnit.MICROSECONDS.toNanos(micros); + } + + @Override + public long[] getPerCpuUsage() { + return LONG_ARRAY_NOT_SUPPORTED; + } + + @Override + public long getCpuUserUsage() { + long micros = CgroupV2SubsystemController.getLongEntry(unified, "cpu.stat", "user_usec"); + if (micros < 0) { + return micros; + } + return TimeUnit.MICROSECONDS.toNanos(micros); + } + + @Override + public long getCpuSystemUsage() { + long micros = CgroupV2SubsystemController.getLongEntry(unified, "cpu.stat", "system_usec"); + if (micros < 0) { + return micros; + } + return TimeUnit.MICROSECONDS.toNanos(micros); + } + + @Override + public long getCpuPeriod() { + return getFromCpuMax(1 /* $PERIOD index */); + } + + @Override + public long getCpuQuota() { + return getFromCpuMax(0 /* $MAX index */); + } + + private long getFromCpuMax(int tokenIdx) { + String cpuMaxRaw = CgroupSubsystemController.getStringValue(unified, "cpu.max"); + if (cpuMaxRaw == null) { + // likely file not found + return CgroupSubsystem.LONG_RETVAL_UNLIMITED; + } + // $MAX $PERIOD + String[] tokens = cpuMaxRaw.split("\\s+"); + if (tokens.length != 2) { + return CgroupSubsystem.LONG_RETVAL_UNLIMITED; + } + String quota = tokens[tokenIdx]; + return limitFromString(quota); + } + + private long limitFromString(String strVal) { + if (strVal == null || MAX_VAL.equals(strVal)) { + return CgroupSubsystem.LONG_RETVAL_UNLIMITED; + } + return Long.parseLong(strVal); + } + + @Override + public long getCpuShares() { + long sharesRaw = getLongVal("cpu.weight"); + if (sharesRaw == 100 || sharesRaw <= 0) { + return CgroupSubsystem.LONG_RETVAL_UNLIMITED; + } + int shares = (int)sharesRaw; + // CPU shares (OCI) value needs to get translated into + // a proper Cgroups v2 value. See: + // https://github.com/containers/crun/blob/master/crun.1.md#cpu-controller + // + // Use the inverse of (x == OCI value, y == cgroupsv2 value): + // ((262142 * y - 1)/9999) + 2 = x + // + int x = 262142 * shares - 1; + double frac = x/9999.0; + x = ((int)frac) + 2; + if ( x <= PER_CPU_SHARES ) { + return PER_CPU_SHARES; // mimic cgroups v1 + } + int f = x/PER_CPU_SHARES; + int lower_multiple = f * PER_CPU_SHARES; + int upper_multiple = (f + 1) * PER_CPU_SHARES; + int distance_lower = Math.max(lower_multiple, x) - Math.min(lower_multiple, x); + int distance_upper = Math.max(upper_multiple, x) - Math.min(upper_multiple, x); + x = distance_lower <= distance_upper ? lower_multiple : upper_multiple; + return x; + } + + @Override + public long getCpuNumPeriods() { + return CgroupV2SubsystemController.getLongEntry(unified, "cpu.stat", "nr_periods"); + } + + @Override + public long getCpuNumThrottled() { + return CgroupV2SubsystemController.getLongEntry(unified, "cpu.stat", "nr_throttled"); + } + + @Override + public long getCpuThrottledTime() { + long micros = CgroupV2SubsystemController.getLongEntry(unified, "cpu.stat", "throttled_usec"); + if (micros < 0) { + return micros; + } + return TimeUnit.MICROSECONDS.toNanos(micros); + } + + @Override + public long getEffectiveCpuCount() { + return Runtime.getRuntime().availableProcessors(); + } + + @Override + public int[] getCpuSetCpus() { + String cpuSetVal = CgroupSubsystemController.getStringValue(unified, "cpuset.cpus"); + return getCpuSet(cpuSetVal); + } + + @Override + public int[] getEffectiveCpuSetCpus() { + String effCpuSetVal = CgroupSubsystemController.getStringValue(unified, "cpuset.cpus.effective"); + return getCpuSet(effCpuSetVal); + } + + @Override + public int[] getCpuSetMems() { + String cpuSetMems = CgroupSubsystemController.getStringValue(unified, "cpuset.mems"); + return getCpuSet(cpuSetMems); + } + + @Override + public int[] getEffectiveCpuSetMems() { + String effCpuSetMems = CgroupSubsystemController.getStringValue(unified, "cpuset.mems.effective"); + return getCpuSet(effCpuSetMems); + } + + private int[] getCpuSet(String cpuSetVal) { + if (cpuSetVal == null || EMPTY_STR.equals(cpuSetVal)) { + return INT_ARRAY_UNAVAILABLE; + } + return CgroupSubsystemController.stringRangeToIntArray(cpuSetVal); + } + + @Override + public long getMemoryFailCount() { + return CgroupV2SubsystemController.getLongEntry(unified, "memory.events", "max"); + } + + @Override + public long getMemoryLimit() { + String strVal = CgroupSubsystemController.getStringValue(unified, "memory.max"); + return limitFromString(strVal); + } + + @Override + public long getMemoryUsage() { + return getLongVal("memory.current"); + } + + @Override + public long getTcpMemoryUsage() { + return CgroupV2SubsystemController.getLongEntry(unified, "memory.stat", "sock"); + } + + @Override + public long getMemoryAndSwapLimit() { + String strVal = CgroupSubsystemController.getStringValue(unified, "memory.swap.max"); + return limitFromString(strVal); + } + + @Override + public long getMemoryAndSwapUsage() { + return getLongVal("memory.swap.current"); + } + + @Override + public long getMemorySoftLimit() { + String softLimitStr = CgroupSubsystemController.getStringValue(unified, "memory.high"); + return limitFromString(softLimitStr); + } + + @Override + public long getBlkIOServiceCount() { + return sumTokensIOStat(CgroupV2Subsystem::lineToRandWIOs); + } + + + @Override + public long getBlkIOServiced() { + return sumTokensIOStat(CgroupV2Subsystem::lineToRBytesAndWBytesIO); + } + + private long sumTokensIOStat(Function mapFunc) { + try { + return CgroupUtil.readFilePrivileged(Paths.get(unified.path(), "io.stat")) + .map(mapFunc) + .collect(Collectors.summingLong(e -> e)); + } catch (IOException e) { + return CgroupSubsystem.LONG_RETVAL_UNLIMITED; + } + } + + private static String[] getRWIOMatchTokenNames() { + return new String[] { "rios", "wios" }; + } + + private static String[] getRWBytesIOMatchTokenNames() { + return new String[] { "rbytes", "wbytes" }; + } + + public static Long lineToRandWIOs(String line) { + String[] matchNames = getRWIOMatchTokenNames(); + return ioStatLineToLong(line, matchNames); + } + + public static Long lineToRBytesAndWBytesIO(String line) { + String[] matchNames = getRWBytesIOMatchTokenNames(); + return ioStatLineToLong(line, matchNames); + } + + private static Long ioStatLineToLong(String line, String[] matchNames) { + if (line == null || EMPTY_STR.equals(line)) { + return Long.valueOf(0); + } + String[] tokens = line.split("\\s+"); + long retval = 0; + for (String t: tokens) { + String[] valKeys = t.split("="); + if (valKeys.length != 2) { + // ignore device ids $MAJ:$MIN + continue; + } + for (String match: matchNames) { + if (match.equals(valKeys[0])) { + retval += longOrZero(valKeys[1]); + } + } + } + return Long.valueOf(retval); + } + + private static long longOrZero(String val) { + long lVal = 0; + try { + lVal = Long.parseLong(val); + } catch (NumberFormatException e) { + // keep at 0 + } + return lVal; + } +} diff --git a/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2SubsystemController.java b/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2SubsystemController.java new file mode 100644 index 00000000000..c9a3ff4f96f --- /dev/null +++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2SubsystemController.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020, Red Hat Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.platform.cgroupv2; + +import java.nio.file.Paths; + +import jdk.internal.platform.CgroupSubsystem; +import jdk.internal.platform.CgroupSubsystemController; + +public class CgroupV2SubsystemController implements CgroupSubsystemController { + + private final String path; + + public CgroupV2SubsystemController(String mountPath, String cgroupPath) { + this.path = Paths.get(mountPath, cgroupPath).toString(); + } + + @Override + public String path() { + return path; + } + + public static long convertStringToLong(String strval) { + return CgroupSubsystemController.convertStringToLong(strval, + CgroupSubsystem.LONG_RETVAL_UNLIMITED /* overflow retval */, + CgroupSubsystem.LONG_RETVAL_UNLIMITED /* default retval on error */); + } + + public static long getLongEntry(CgroupSubsystemController controller, String param, String entryname) { + return CgroupSubsystemController.getLongEntry(controller, + param, + entryname, + CgroupSubsystem.LONG_RETVAL_UNLIMITED /* retval on error */); + } +} diff --git a/src/java.base/macosx/classes/apple/security/KeychainStore.java b/src/java.base/macosx/classes/apple/security/KeychainStore.java index a39be310117..81e02dc740b 100644 --- a/src/java.base/macosx/classes/apple/security/KeychainStore.java +++ b/src/java.base/macosx/classes/apple/security/KeychainStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,12 +89,13 @@ public final class KeychainStore extends KeyStoreSpi { private Hashtable entries = new Hashtable<>(); /** - * Algorithm identifiers and corresponding OIDs for the contents of the PKCS12 bag we get from the Keychain. + * Algorithm identifiers and corresponding OIDs for the contents of the + * PKCS12 bag we get from the Keychain. */ - private static final int keyBag[] = {1, 2, 840, 113549, 1, 12, 10, 1, 2}; - private static final int pbeWithSHAAnd3KeyTripleDESCBC[] = {1, 2, 840, 113549, 1, 12, 1, 3}; - private static ObjectIdentifier PKCS8ShroudedKeyBag_OID; - private static ObjectIdentifier pbeWithSHAAnd3KeyTripleDESCBC_OID; + private static ObjectIdentifier PKCS8ShroudedKeyBag_OID = + ObjectIdentifier.of("1.2.840.113549.1.12.10.1.2"); + private static ObjectIdentifier pbeWithSHAAnd3KeyTripleDESCBC_OID = + ObjectIdentifier.of("1.2.840.113549.1.12.1.3"); /** * Constnats used in PBE decryption. @@ -106,12 +107,6 @@ public final class KeychainStore extends KeyStoreSpi { static { jdk.internal.loader.BootLoader.loadLibrary("osxsecurity"); - try { - PKCS8ShroudedKeyBag_OID = new ObjectIdentifier(keyBag); - pbeWithSHAAnd3KeyTripleDESCBC_OID = new ObjectIdentifier(pbeWithSHAAnd3KeyTripleDESCBC); - } catch (IOException ioe) { - // should not happen - } } private static void permissionCheck() { diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DHPrivateKey.java b/src/java.base/share/classes/com/sun/crypto/provider/DHPrivateKey.java index 5b1f9bffb6c..24cbf949321 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/DHPrivateKey.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/DHPrivateKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,8 +72,6 @@ javax.crypto.interfaces.DHPrivateKey, Serializable { // the private-value length (optional) private int l; - private int DH_data[] = { 1, 2, 840, 113549, 1, 3, 1 }; - /** * Make a DH private key out of a private value x, a prime * modulus p, and a base generator g. @@ -220,7 +218,7 @@ javax.crypto.interfaces.DHPrivateKey, Serializable { DerOutputStream algid = new DerOutputStream(); // store OID - algid.putOID(new ObjectIdentifier(DH_data)); + algid.putOID(DHPublicKey.DH_OID); // encode parameters DerOutputStream params = new DerOutputStream(); params.putInteger(this.p); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DHPublicKey.java b/src/java.base/share/classes/com/sun/crypto/provider/DHPublicKey.java index 7f902525f53..7c54d7482b5 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/DHPublicKey.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/DHPublicKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * 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,9 @@ javax.crypto.interfaces.DHPublicKey, Serializable { // the private-value length (optional) private int l; - private int DH_data[] = { 1, 2, 840, 113549, 1, 3, 1 }; + // Note: this OID is used by DHPrivateKey as well. + static ObjectIdentifier DH_OID = + ObjectIdentifier.of("1.2.840.113549.1.3.1"); /** * Make a DH public key out of a public value y, a prime @@ -203,7 +205,7 @@ javax.crypto.interfaces.DHPublicKey, Serializable { DerOutputStream algid = new DerOutputStream(); // store oid in algid - algid.putOID(new ObjectIdentifier(DH_data)); + algid.putOID(DH_OID); // encode parameters DerOutputStream params = new DerOutputStream(); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java b/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java index e180935536a..ca2d70fe69a 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,24 +55,10 @@ public final class OAEPParameters extends AlgorithmParametersSpi { private String mdName; private MGF1ParameterSpec mgfSpec; private byte[] p; - private static ObjectIdentifier OID_MGF1; - private static ObjectIdentifier OID_PSpecified; - - static { - try { - OID_MGF1 = new ObjectIdentifier(new int[] {1,2,840,113549,1,1,8}); - } catch (IOException ioe) { - // should not happen - OID_MGF1 = null; - } - try { - OID_PSpecified = - new ObjectIdentifier(new int[] {1,2,840,113549,1,1,9}); - } catch (IOException ioe) { - // should not happen - OID_PSpecified = null; - } - } + private static ObjectIdentifier OID_MGF1 = + ObjectIdentifier.of("1.2.840.113549.1.1.8"); + private static ObjectIdentifier OID_PSpecified = + ObjectIdentifier.of("1.2.840.113549.1.1.9"); public OAEPParameters() { } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java b/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java index 968d591ac6c..0c2e420eedc 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,57 +90,28 @@ import sun.security.util.*; * * */ - abstract class PBES2Parameters extends AlgorithmParametersSpi { - private static final int pkcs5PBKDF2[] = - {1, 2, 840, 113549, 1, 5, 12}; - private static final int pkcs5PBES2[] = - {1, 2, 840, 113549, 1, 5, 13}; - private static final int hmacWithSHA1[] = - {1, 2, 840, 113549, 2, 7}; - private static final int hmacWithSHA224[] = - {1, 2, 840, 113549, 2, 8}; - private static final int hmacWithSHA256[] = - {1, 2, 840, 113549, 2, 9}; - private static final int hmacWithSHA384[] = - {1, 2, 840, 113549, 2, 10}; - private static final int hmacWithSHA512[] = - {1, 2, 840, 113549, 2, 11}; - private static final int aes128CBC[] = - {2, 16, 840, 1, 101, 3, 4, 1, 2}; - private static final int aes192CBC[] = - {2, 16, 840, 1, 101, 3, 4, 1, 22}; - private static final int aes256CBC[] = - {2, 16, 840, 1, 101, 3, 4, 1, 42}; - - private static ObjectIdentifier pkcs5PBKDF2_OID; - private static ObjectIdentifier pkcs5PBES2_OID; - private static ObjectIdentifier hmacWithSHA1_OID; - private static ObjectIdentifier hmacWithSHA224_OID; - private static ObjectIdentifier hmacWithSHA256_OID; - private static ObjectIdentifier hmacWithSHA384_OID; - private static ObjectIdentifier hmacWithSHA512_OID; - private static ObjectIdentifier aes128CBC_OID; - private static ObjectIdentifier aes192CBC_OID; - private static ObjectIdentifier aes256CBC_OID; - - static { - try { - pkcs5PBKDF2_OID = new ObjectIdentifier(pkcs5PBKDF2); - pkcs5PBES2_OID = new ObjectIdentifier(pkcs5PBES2); - hmacWithSHA1_OID = new ObjectIdentifier(hmacWithSHA1); - hmacWithSHA224_OID = new ObjectIdentifier(hmacWithSHA224); - hmacWithSHA256_OID = new ObjectIdentifier(hmacWithSHA256); - hmacWithSHA384_OID = new ObjectIdentifier(hmacWithSHA384); - hmacWithSHA512_OID = new ObjectIdentifier(hmacWithSHA512); - aes128CBC_OID = new ObjectIdentifier(aes128CBC); - aes192CBC_OID = new ObjectIdentifier(aes192CBC); - aes256CBC_OID = new ObjectIdentifier(aes256CBC); - } catch (IOException ioe) { - // should not happen - } - } + private static ObjectIdentifier pkcs5PBKDF2_OID = + ObjectIdentifier.of("1.2.840.113549.1.5.12"); + private static ObjectIdentifier pkcs5PBES2_OID = + ObjectIdentifier.of("1.2.840.113549.1.5.13"); + private static ObjectIdentifier hmacWithSHA1_OID = + ObjectIdentifier.of("1.2.840.113549.2.7"); + private static ObjectIdentifier hmacWithSHA224_OID = + ObjectIdentifier.of("1.2.840.113549.2.8"); + private static ObjectIdentifier hmacWithSHA256_OID = + ObjectIdentifier.of("1.2.840.113549.2.9"); + private static ObjectIdentifier hmacWithSHA384_OID = + ObjectIdentifier.of("1.2.840.113549.2.10"); + private static ObjectIdentifier hmacWithSHA512_OID = + ObjectIdentifier.of("1.2.840.113549.2.11"); + private static ObjectIdentifier aes128CBC_OID = + ObjectIdentifier.of("2.16.840.1.101.3.4.1.2"); + private static ObjectIdentifier aes192CBC_OID = + ObjectIdentifier.of("2.16.840.1.101.3.4.1.22"); + private static ObjectIdentifier aes256CBC_OID = + ObjectIdentifier.of("2.16.840.1.101.3.4.1.42"); // the PBES2 algorithm name private String pbes2AlgorithmName = null; diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index 0a320f657cb..3679038b8f1 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -374,15 +374,16 @@ public final class Class implements java.io.Serializable, * {@code Class.forName("Foo", true, this.getClass().getClassLoader())} * * - * Note that this method throws errors related to loading, linking or - * initializing as specified in Sections 12.2, 12.3 and 12.4 of The - * Java Language Specification. + * Note that this method throws errors related to loading, linking + * or initializing as specified in Sections {@jls 12.2}, {@jls + * 12.3}, and {@jls 12.4} of The Java Language + * Specification. * Note that this method does not check whether the requested class * is accessible to its caller. * * @param name fully qualified name of the desired class * @param initialize if {@code true} the class will be initialized (which implies linking). - * See Section 12.4 of The Java Language Specification. + * See Section {@jls 12.4} of The Java Language Specification. * @param loader class loader from which the class must be loaded * @return class object representing the desired class * @@ -660,7 +661,8 @@ public final class Class implements java.io.Serializable, * specified {@code Class} parameter can be converted to the type * represented by this {@code Class} object via an identity conversion * or via a widening reference conversion. See The Java Language - * Specification, sections 5.1.1 and 5.1.4 , for details. + * Specification, sections {@jls 5.1.1} and {@jls 5.1.4}, + * for details. * * @param cls the {@code Class} object to be checked * @return the {@code boolean} value indicating whether objects of the @@ -2399,7 +2401,7 @@ public final class Class implements java.io.Serializable, * object represents an interface, a primitive type, an array class, or * void. * - *

    See The Java Language Specification, section 8.2. + *

    See The Java Language Specification, section {@jls 8.2}. * * @return the array of {@code Constructor} objects representing all the * declared constructors of this class diff --git a/src/java.base/share/classes/java/lang/Enum.java b/src/java.base/share/classes/java/lang/Enum.java index c0f617d41e1..21cb3f5f6b3 100644 --- a/src/java.base/share/classes/java/lang/Enum.java +++ b/src/java.base/share/classes/java/lang/Enum.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,8 +44,8 @@ import static java.util.Objects.requireNonNull; * * More information about enums, including descriptions of the * implicitly declared methods synthesized by the compiler, can be - * found in section 8.9 of - * The Java™ Language Specification. + * found in section {@jls 8.9} of The Java™ Language + * Specification. * * Enumeration types are all serializable and receive special handling * by the serialization mechanism. The serialized representation used diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index 68aa207ce72..8fa853a7459 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1819,7 +1819,7 @@ public final class String * @param src the characters being searched. * @param srcCoder coder handles the mapping between bytes/chars * @param srcCount count of the source string. - * @param tgt the characters being searched for. + * @param tgtStr the characters being searched for. * @param fromIndex the index to begin searching from. */ static int lastIndexOf(byte[] src, byte srcCoder, int srcCount, @@ -1900,10 +1900,10 @@ public final class String public String substring(int beginIndex, int endIndex) { int length = length(); checkBoundsBeginEnd(beginIndex, endIndex, length); - int subLen = endIndex - beginIndex; if (beginIndex == 0 && endIndex == length) { return this; } + int subLen = endIndex - beginIndex; return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen) : StringUTF16.newString(value, beginIndex, subLen); } diff --git a/src/java.base/share/classes/java/lang/StringLatin1.java b/src/java.base/share/classes/java/lang/StringLatin1.java index 854c912a24a..ca558c27bec 100644 --- a/src/java.base/share/classes/java/lang/StringLatin1.java +++ b/src/java.base/share/classes/java/lang/StringLatin1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -630,17 +630,11 @@ final class StringLatin1 { public static String stripLeading(byte[] value) { int left = indexOfNonWhitespace(value); - if (left == value.length) { - return ""; - } return (left != 0) ? newString(value, left, value.length - left) : null; } public static String stripTrailing(byte[] value) { int right = lastIndexOfNonWhitespace(value); - if (right == 0) { - return ""; - } return (right != value.length) ? newString(value, 0, right) : null; } @@ -764,6 +758,9 @@ final class StringLatin1 { } public static String newString(byte[] val, int index, int len) { + if (len == 0) { + return ""; + } return new String(Arrays.copyOfRange(val, index, index + len), LATIN1); } diff --git a/src/java.base/share/classes/java/lang/StringUTF16.java b/src/java.base/share/classes/java/lang/StringUTF16.java index ca27d9dde95..a923070a86f 100644 --- a/src/java.base/share/classes/java/lang/StringUTF16.java +++ b/src/java.base/share/classes/java/lang/StringUTF16.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1016,18 +1016,12 @@ final class StringUTF16 { public static String stripLeading(byte[] value) { int length = value.length >>> 1; int left = indexOfNonWhitespace(value); - if (left == length) { - return ""; - } return (left != 0) ? newString(value, left, length - left) : null; } public static String stripTrailing(byte[] value) { int length = value.length >>> 1; int right = lastIndexOfNonWhitespace(value); - if (right == 0) { - return ""; - } return (right != length) ? newString(value, 0, right) : null; } @@ -1132,6 +1126,9 @@ final class StringUTF16 { } public static String newString(byte[] val, int index, int len) { + if (len == 0) { + return ""; + } if (String.COMPACT_STRINGS) { byte[] buf = compress(val, index, len); if (buf != null) { diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java index 2fcabb80a8f..a0598839d1b 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -222,8 +222,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; * refers directly to an associated {@code CONSTANT_Methodref}, * {@code CONSTANT_InterfaceMethodref}, or {@code CONSTANT_Fieldref} * constant pool entry. - * (For full details on method handle constants, - * see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.) + * (For full details on method handle constants, see sections {@jvms + * 4.4.8} and {@jvms 5.4.3.5} of the Java Virtual Machine + * Specification.) *

    * Method handles produced by lookups or constant loads from methods or * constructors with the variable arity modifier bit ({@code 0x0080}) diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleInfo.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleInfo.java index c18f27f0fcb..159af85dec0 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleInfo.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,8 @@ import static java.lang.invoke.MethodHandleStatics.*; * Direct method handles may be obtained in any of these ways: *

      *
    • By executing an {@code ldc} instruction on a {@code CONSTANT_MethodHandle} constant. - * (See the Java Virtual Machine Specification, sections 4.4.8 and 5.4.3.) + * (See the Java Virtual Machine Specification, sections {@jvms + * 4.4.8} and {@jvms 5.4.3}.) *
    • By calling one of the Lookup Factory Methods, * such as {@link Lookup#findVirtual Lookup.findVirtual}, * to resolve a symbolic reference into a method handle. diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index d4b4ceb7f72..2ee93e561a8 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -318,7 +318,8 @@ public class MethodHandles { * use cases for methods, constructors, and fields. * Each method handle created by a factory method is the functional * equivalent of a particular bytecode behavior. - * (Bytecode behaviors are described in section 5.4.3.5 of the Java Virtual Machine Specification.) + * (Bytecode behaviors are described in section {@jvms 5.4.3.5} of + * the Java Virtual Machine Specification.) * Here is a summary of the correspondence between these factory methods and * the behavior of the resulting method handles: * @@ -502,7 +503,8 @@ public class MethodHandles { * If the desired member is {@code protected}, the usual JVM rules apply, * including the requirement that the lookup class must either be in the * same package as the desired member, or must inherit that member. - * (See the Java Virtual Machine Specification, sections 4.9.2, 5.4.3.5, and 6.4.) + * (See the Java Virtual Machine Specification, sections {@jvms + * 4.9.2}, {@jvms 5.4.3.5}, and {@jvms 6.4}.) * In addition, if the desired member is a non-static field or method * in a different package, the resulting method handle may only be applied * to objects of the lookup class or one of its subclasses. @@ -515,7 +517,7 @@ public class MethodHandles { * that the receiver argument must match both the resolved method and * the current class. Again, this requirement is enforced by narrowing the * type of the leading parameter to the resulting method handle. - * (See the Java Virtual Machine Specification, section 4.10.1.9.) + * (See the Java Virtual Machine Specification, section {@jmvs 4.10.1.9}.) *

      * The JVM represents constructors and static initializer blocks as internal methods * with special names ({@code ""} and {@code ""}). @@ -525,7 +527,8 @@ public class MethodHandles { *

      * If the relationship between nested types is expressed directly through the * {@code NestHost} and {@code NestMembers} attributes - * (see the Java Virtual Machine Specification, sections 4.7.28 and 4.7.29), + * (see the Java Virtual Machine Specification, sections {@jvms + * 4.7.28} and {@jvms 4.7.29}), * then the associated {@code Lookup} object provides direct access to * the lookup class and all of its nestmates * (see {@link java.lang.Class#getNestHost Class.getNestHost}). diff --git a/src/java.base/share/classes/java/lang/invoke/MethodType.java b/src/java.base/share/classes/java/lang/invoke/MethodType.java index 37e017bf722..cf9dfb36060 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodType.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,8 +91,9 @@ import static java.lang.invoke.MethodType.fromDescriptor; * A method type may be loaded by an {@code ldc} instruction which refers * to a suitable {@code CONSTANT_MethodType} constant pool entry. * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string. - * (For full details on method type constants, - * see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.) + * (For full details on method type constants, see sections {@jvms + * 4.4.8} and {@jvms 5.4.3.5} of the Java Virtual Machine + * Specification.) *

      * When the JVM materializes a {@code MethodType} from a descriptor string, * all classes named in the descriptor must be accessible, and will be loaded. diff --git a/src/java.base/share/classes/java/lang/reflect/Method.java b/src/java.base/share/classes/java/lang/reflect/Method.java index 22446e9ce79..84005541ec4 100644 --- a/src/java.base/share/classes/java/lang/reflect/Method.java +++ b/src/java.base/share/classes/java/lang/reflect/Method.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -503,7 +503,7 @@ public final class Method extends Executable { * *

      If the underlying method is an instance method, it is invoked * using dynamic method lookup as documented in The Java Language - * Specification, section 15.12.4.4; in particular, + * Specification, section {@jls 15.12.4.4}; in particular, * overriding based on the runtime type of the target object may occur. * *

      If the underlying method is static, the class that declared diff --git a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java index d2aaa8b6f08..2ae0911a4bb 100644 --- a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java +++ b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -383,7 +383,7 @@ final class ProxyGenerator extends ClassWriter { * separator, the external representation used by the Java language * and APIs, to a fully qualified class name that uses '/' as the * package separator, the representation used in the class file - * format (see JVMS section 4.2). + * format (see JVMS section {@jvms 4.2}). */ private static String dotToSlash(String name) { return name.replace('.', '/'); diff --git a/src/java.base/share/classes/java/security/cert/X509CertSelector.java b/src/java.base/share/classes/java/security/cert/X509CertSelector.java index 70c77258ad0..6314a5ae1ad 100644 --- a/src/java.base/share/classes/java/security/cert/X509CertSelector.java +++ b/src/java.base/share/classes/java/security/cert/X509CertSelector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,7 +88,7 @@ public class X509CertSelector implements CertSelector { private static final Debug debug = Debug.getInstance("certpath"); private static final ObjectIdentifier ANY_EXTENDED_KEY_USAGE = - ObjectIdentifier.newInternal(new int[] {2, 5, 29, 37, 0}); + ObjectIdentifier.of("2.5.29.37.0"); static { CertPathHelperImpl.initialize(); diff --git a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java index 69c8ee21008..c7a09e56232 100644 --- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -4260,9 +4260,15 @@ public final class DateTimeFormatterBuilder { char nextNextChar = text.charAt(position + 1); if (context.charEquals(nextChar, 'U') && context.charEquals(nextNextChar, 'T')) { if (length >= position + 3 && context.charEquals(text.charAt(position + 2), 'C')) { - return parseOffsetBased(context, text, position, position + 3, OffsetIdPrinterParser.INSTANCE_ID_ZERO); + // There are localized zone texts that start with "UTC", e.g. + // "UTC\u221210:00" (MINUS SIGN instead of HYPHEN-MINUS) in French. + // Exclude those ZoneText cases. + if (!(this instanceof ZoneTextPrinterParser)) { + return parseOffsetBased(context, text, position, position + 3, OffsetIdPrinterParser.INSTANCE_ID_ZERO); + } + } else { + return parseOffsetBased(context, text, position, position + 2, OffsetIdPrinterParser.INSTANCE_ID_ZERO); } - return parseOffsetBased(context, text, position, position + 2, OffsetIdPrinterParser.INSTANCE_ID_ZERO); } else if (context.charEquals(nextChar, 'G') && length >= position + 3 && context.charEquals(nextNextChar, 'M') && context.charEquals(text.charAt(position + 2), 'T')) { if (length >= position + 4 && context.charEquals(text.charAt(position + 3), '0')) { diff --git a/src/java.base/share/classes/java/time/temporal/ValueRange.java b/src/java.base/share/classes/java/time/temporal/ValueRange.java index 8c077014c0a..79946eafcb6 100644 --- a/src/java.base/share/classes/java/time/temporal/ValueRange.java +++ b/src/java.base/share/classes/java/time/temporal/ValueRange.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -145,6 +145,9 @@ public final class ValueRange implements Serializable { * or the smallest maximum is greater than the largest maximum */ public static ValueRange of(long min, long maxSmallest, long maxLargest) { + if (min > maxSmallest) { + throw new IllegalArgumentException("Minimum value must be less than smallest maximum value"); + } return of(min, min, maxSmallest, maxLargest); } @@ -160,8 +163,9 @@ public final class ValueRange implements Serializable { * @return the ValueRange for smallest min, largest min, smallest max, largest max, not null * @throws IllegalArgumentException if * the smallest minimum is greater than the smallest maximum, - * or the smallest maximum is greater than the largest maximum - * or the largest minimum is greater than the largest maximum + * or the smallest maximum is greater than the largest maximum, + * or the largest minimum is greater than the largest maximum, + * or the smallest minimum is greater than the largest minimum */ public static ValueRange of(long minSmallest, long minLargest, long maxSmallest, long maxLargest) { if (minSmallest > minLargest) { @@ -171,7 +175,10 @@ public final class ValueRange implements Serializable { throw new IllegalArgumentException("Smallest maximum value must be less than largest maximum value"); } if (minLargest > maxLargest) { - throw new IllegalArgumentException("Minimum value must be less than maximum value"); + throw new IllegalArgumentException("Largest minimum value must be less than largest maximum value"); + } + if (minSmallest > maxSmallest) { + throw new IllegalArgumentException("Smallest minimum value must be less than smallest maximum value"); } return new ValueRange(minSmallest, minLargest, maxSmallest, maxLargest); } diff --git a/src/java.base/share/classes/java/time/zone/ZoneOffsetTransitionRule.java b/src/java.base/share/classes/java/time/zone/ZoneOffsetTransitionRule.java index 25f65efaf5a..9b622feaa06 100644 --- a/src/java.base/share/classes/java/time/zone/ZoneOffsetTransitionRule.java +++ b/src/java.base/share/classes/java/time/zone/ZoneOffsetTransitionRule.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -160,7 +160,7 @@ public final class ZoneOffsetTransitionRule implements Serializable { * @param dayOfWeek the required day-of-week, null if the month-day should not be changed * @param time the cutover time in the 'before' offset, not null * @param timeEndOfDay whether the time is midnight at the end of day - * @param timeDefnition how to interpret the cutover + * @param timeDefinition how to interpret the cutover * @param standardOffset the standard offset in force at the cutover, not null * @param offsetBefore the offset before the cutover, not null * @param offsetAfter the offset after the cutover, not null @@ -175,13 +175,13 @@ public final class ZoneOffsetTransitionRule implements Serializable { DayOfWeek dayOfWeek, LocalTime time, boolean timeEndOfDay, - TimeDefinition timeDefnition, + TimeDefinition timeDefinition, ZoneOffset standardOffset, ZoneOffset offsetBefore, ZoneOffset offsetAfter) { Objects.requireNonNull(month, "month"); Objects.requireNonNull(time, "time"); - Objects.requireNonNull(timeDefnition, "timeDefnition"); + Objects.requireNonNull(timeDefinition, "timeDefinition"); Objects.requireNonNull(standardOffset, "standardOffset"); Objects.requireNonNull(offsetBefore, "offsetBefore"); Objects.requireNonNull(offsetAfter, "offsetAfter"); @@ -194,7 +194,7 @@ public final class ZoneOffsetTransitionRule implements Serializable { if (time.getNano() != 0) { throw new IllegalArgumentException("Time's nano-of-second must be zero"); } - return new ZoneOffsetTransitionRule(month, dayOfMonthIndicator, dayOfWeek, time, timeEndOfDay, timeDefnition, standardOffset, offsetBefore, offsetAfter); + return new ZoneOffsetTransitionRule(month, dayOfMonthIndicator, dayOfWeek, time, timeEndOfDay, timeDefinition, standardOffset, offsetBefore, offsetAfter); } /** @@ -207,7 +207,7 @@ public final class ZoneOffsetTransitionRule implements Serializable { * @param dayOfWeek the required day-of-week, null if the month-day should not be changed * @param time the cutover time in the 'before' offset, not null * @param timeEndOfDay whether the time is midnight at the end of day - * @param timeDefnition how to interpret the cutover + * @param timeDefinition how to interpret the cutover * @param standardOffset the standard offset in force at the cutover, not null * @param offsetBefore the offset before the cutover, not null * @param offsetAfter the offset after the cutover, not null @@ -220,7 +220,7 @@ public final class ZoneOffsetTransitionRule implements Serializable { DayOfWeek dayOfWeek, LocalTime time, boolean timeEndOfDay, - TimeDefinition timeDefnition, + TimeDefinition timeDefinition, ZoneOffset standardOffset, ZoneOffset offsetBefore, ZoneOffset offsetAfter) { @@ -230,7 +230,7 @@ public final class ZoneOffsetTransitionRule implements Serializable { this.dow = dayOfWeek; this.time = time; this.timeEndOfDay = timeEndOfDay; - this.timeDefinition = timeDefnition; + this.timeDefinition = timeDefinition; this.standardOffset = standardOffset; this.offsetBefore = offsetBefore; this.offsetAfter = offsetAfter; diff --git a/src/java.base/share/classes/java/util/IdentityHashMap.java b/src/java.base/share/classes/java/util/IdentityHashMap.java index ac1d416ebcd..e7704d39281 100644 --- a/src/java.base/share/classes/java/util/IdentityHashMap.java +++ b/src/java.base/share/classes/java/util/IdentityHashMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -115,17 +115,19 @@ import jdk.internal.access.SharedSecrets; * exception for its correctness: fail-fast iterators should be used only * to detect bugs. * - *

      Implementation note: This is a simple linear-probe hash table, - * as described for example in texts by Sedgewick and Knuth. The array - * alternates holding keys and values. (This has better locality for large - * tables than does using separate arrays.) For many JRE implementations - * and operation mixes, this class will yield better performance than - * {@link HashMap} (which uses chaining rather than linear-probing). - * *

      This class is a member of the * * Java Collections Framework. * + * @implNote + *

      This is a simple linear-probe hash table, + * as described for example in texts by Sedgewick and Knuth. The array + * contains alternating keys and values, with keys at even indexes and values + * at odd indexes. (This arrangement has better locality for large + * tables than does using separate arrays.) For many Java implementations + * and operation mixes, this class will yield better performance than + * {@link HashMap}, which uses chaining rather than linear-probing. + * * @see System#identityHashCode(Object) * @see Object#hashCode() * @see Collection @@ -293,7 +295,7 @@ public class IdentityHashMap */ private static int hash(Object x, int length) { int h = System.identityHashCode(x); - // Multiply by -127, and left-shift to use least bit as part of hash + // Multiply by -254 to use the hash LSB and to ensure index is even return ((h << 1) - (h << 8)) & (length - 1); } diff --git a/src/java.base/share/classes/java/util/stream/package-info.java b/src/java.base/share/classes/java/util/stream/package-info.java index e2109b9e9d7..ccdea31570f 100644 --- a/src/java.base/share/classes/java/util/stream/package-info.java +++ b/src/java.base/share/classes/java/util/stream/package-info.java @@ -43,7 +43,7 @@ *

      The key abstraction introduced in this package is stream. The * classes {@link java.util.stream.Stream}, {@link java.util.stream.IntStream}, * {@link java.util.stream.LongStream}, and {@link java.util.stream.DoubleStream} - * are streams over objects and the primitive {@code int}, {@code long} and + * are streams over objects and the primitive {@code int}, {@code long}, and * {@code double} types. Streams differ from collections in several ways: * *

        @@ -176,7 +176,7 @@ * do: * *
        {@code
        - *     int sumOfWeights = widgets.parallelStream()
        + *     int sumOfWeights = widgets.parallelStream()
          *                               .filter(b -> b.getColor() == RED)
          *                               .mapToInt(b -> b.getWeight())
          *                               .sum();
        @@ -242,7 +242,7 @@
          *     String s = sl.collect(joining(" "));
          * }
        * - * First a list is created consisting of two strings: "one"; and "two". Then a + * First a list is created consisting of two strings: "one" and "two". Then a * stream is created from that list. Next the list is modified by adding a third * string: "three". Finally the elements of the stream are collected and joined * together. Since the list was modified before the terminal {@code collect} @@ -344,7 +344,7 @@ * parallelization: * *
        {@code
        - *     Listresults =
        + *     List results =
          *         stream.filter(s -> pattern.matcher(s).matches())
          *               .collect(Collectors.toList());  // No side-effects!
          * }
        diff --git a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java index 2f0ea84899a..9b5b28a4d32 100644 --- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java +++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -40,7 +40,7 @@ import static jdk.internal.misc.UnsafeConstants.*; * Although the class and all methods are public, use of this class is * limited because only trusted code can obtain instances of it. * - * Note: It is the resposibility of the caller to make sure + * Note: It is the responsibility of the caller to make sure * arguments are checked before methods of this class are * called. While some rudimentary checks are performed on the input, * the checks are best effort and when performance is an overriding @@ -425,7 +425,7 @@ public final class Unsafe { /** * Create an exception reflecting that some of the input was invalid * - * Note: It is the resposibility of the caller to make + * Note: It is the responsibility of the caller to make * sure arguments are checked before the methods are called. While * some rudimentary checks are performed on the input, the checks * are best effort and when performance is an overriding priority, @@ -601,7 +601,7 @@ public final class Unsafe { * aligned for all value types. Dispose of this memory by calling {@link * #freeMemory}, or resize it with {@link #reallocateMemory}. * - * Note: It is the resposibility of the caller to make + * Note: It is the responsibility of the caller to make * sure arguments are checked before the methods are called. While * some rudimentary checks are performed on the input, the checks * are best effort and when performance is an overriding priority, @@ -657,7 +657,7 @@ public final class Unsafe { * #reallocateMemory}. The address passed to this method may be null, in * which case an allocation will be performed. * - * Note: It is the resposibility of the caller to make + * Note: It is the responsibility of the caller to make * sure arguments are checked before the methods are called. While * some rudimentary checks are performed on the input, the checks * are best effort and when performance is an overriding priority, @@ -719,7 +719,7 @@ public final class Unsafe { * If the effective address and length are (resp.) even modulo 4 or 2, * the stores take place in units of 'int' or 'short'. * - * Note: It is the resposibility of the caller to make + * Note: It is the responsibility of the caller to make * sure arguments are checked before the methods are called. While * some rudimentary checks are performed on the input, the checks * are best effort and when performance is an overriding priority, @@ -781,7 +781,7 @@ public final class Unsafe { * If the effective addresses and length are (resp.) even modulo 4 or 2, * the transfer takes place in units of 'int' or 'short'. * - * Note: It is the resposibility of the caller to make + * Note: It is the responsibility of the caller to make * sure arguments are checked before the methods are called. While * some rudimentary checks are performed on the input, the checks * are best effort and when performance is an overriding priority, @@ -842,7 +842,7 @@ public final class Unsafe { * as discussed in {@link #getInt(Object,long)}. When the object reference is null, * the offset supplies an absolute base address. * - * Note: It is the resposibility of the caller to make + * Note: It is the responsibility of the caller to make * sure arguments are checked before the methods are called. While * some rudimentary checks are performed on the input, the checks * are best effort and when performance is an overriding priority, @@ -901,7 +901,7 @@ public final class Unsafe { * #allocateMemory} or {@link #reallocateMemory}. The address passed to * this method may be null, in which case no action is taken. * - * Note: It is the resposibility of the caller to make + * Note: It is the responsibility of the caller to make * sure arguments are checked before the methods are called. While * some rudimentary checks are performed on the input, the checks * are best effort and when performance is an overriding priority, diff --git a/src/java.base/share/classes/jdk/internal/platform/Metrics.java b/src/java.base/share/classes/jdk/internal/platform/Metrics.java index a7cfea98598..814771bc6f4 100644 --- a/src/java.base/share/classes/jdk/internal/platform/Metrics.java +++ b/src/java.base/share/classes/jdk/internal/platform/Metrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,9 +56,7 @@ public interface Metrics { */ public static Metrics systemMetrics() { try { - // We currently only support cgroupv1 - Class c = Class.forName("jdk.internal.platform.cgroupv1.Metrics"); - @SuppressWarnings("unchecked") + Class c = Class.forName("jdk.internal.platform.CgroupMetrics"); Method m = c.getMethod("getInstance"); return (Metrics) m.invoke(null); } catch (ClassNotFoundException e) { @@ -74,7 +72,7 @@ public interface Metrics { * * @implNote * Metrics are currently only supported Linux. - * The provider for Linux is cgroupsv1. + * The provider for Linux is cgroups (version 1 or 2). * * @return The name of the provider. * @@ -90,7 +88,8 @@ public interface Metrics { * Returns the aggregate time, in nanoseconds, consumed by all * tasks in the Isolation Group. * - * @return Time in nanoseconds or 0L if metric is not available. + * @return Time in nanoseconds, -1 if unknown or + * -2 if the metric is not supported. * */ public long getCpuUsage(); @@ -106,7 +105,7 @@ public interface Metrics { * * @return long array of time values. The size of the array is equal * to the total number of physical processors in the system. If - * this metric is not available, a zero length array will be + * this metric is not supported or not available, null will be * returned. * */ @@ -116,7 +115,8 @@ public interface Metrics { * Returns the aggregate user time, in nanoseconds, consumed by all * tasks in the Isolation Group. * - * @return User time in nanoseconds or 0L if metric is not available. + * @return User time in nanoseconds, -1 if the metric is not available or + * -2 if the metric is not supported. * */ public long getCpuUserUsage(); @@ -125,7 +125,8 @@ public interface Metrics { * Returns the aggregate system time, in nanoseconds, consumed by * all tasks in the Isolation Group. * - * @return System time in nanoseconds or 0L if metric is not available. + * @return System time in nanoseconds, -1 if the metric is not available or + * -2 if the metric is not supported. * */ public long getCpuSystemUsage(); @@ -138,7 +139,8 @@ public interface Metrics { * Returns the length of the scheduling period, in * microseconds, for processes within the Isolation Group. * - * @return time in microseconds or 0L if metric is not available. + * @return time in microseconds, -1 if the metric is not available or + * -2 if the metric is not supported. * */ public long getCpuPeriod(); @@ -148,7 +150,8 @@ public interface Metrics { * during each scheduling period for all tasks in the Isolation * Group. * - * @return time in microseconds or -1 if the quota is unlimited. + * @return time in microseconds, -1 if the quota is unlimited or + * -2 if not supported. * */ public long getCpuQuota(); @@ -167,17 +170,18 @@ public interface Metrics { * each process. To request 2 CPUS worth of execution time, CPU shares * would be set to 2048. * - * @return shares value or -1 if no share set. + * @return shares value, -1 if the metric is not available or + * -2 if cpu shares are not supported. * */ public long getCpuShares(); /** * Returns the number of time-slice periods that have elapsed if - * a CPU quota has been setup for the Isolation Group; otherwise - * returns 0. + * a CPU quota has been setup for the Isolation Group * - * @return count of elapsed periods or 0 if the quota is unlimited. + * @return count of elapsed periods, -1 if the metric is not available + * or -2 if the metric is not supported. * */ public long getCpuNumPeriods(); @@ -187,7 +191,8 @@ public interface Metrics { * been throttled or limited due to the group exceeding its quota * if a CPU quota has been setup for the Isolation Group. * - * @return count of throttled periods or 0 if the quota is unlimited. + * @return count of throttled periods, -1 if the metric is not available or + * -2 if it is not supported. * */ public long getCpuNumThrottled(); @@ -197,7 +202,8 @@ public interface Metrics { * group has been throttled or limited due to the group exceeding * its quota if a CPU quota has been setup for the Isolation Group. * - * @return Throttled time in nanoseconds or 0 if the quota is unlimited. + * @return Throttled time in nanoseconds, -1 if the metric is not available + * or -2 if it is not supported. * */ public long getCpuThrottledTime(); @@ -229,8 +235,8 @@ public interface Metrics { * may be offline. To get the current online CPUs, use * {@link getEffectiveCpuSetCpus()}. * - * @return An array of available CPUs or a zero length array - * if the metric is not available. + * @return An array of available CPUs. Returns null if the metric is not + * available or the metric is not supported. * */ public int[] getCpuSetCpus(); @@ -241,8 +247,8 @@ public interface Metrics { * array is equal to the total number of CPUs and the elements in * the array are the physical CPU numbers. * - * @return An array of available and online CPUs or a zero length - * array if the metric is not available. + * @return An array of available and online CPUs. Returns null + * if the metric is not available or the metric is not supported. * */ public int[] getEffectiveCpuSetCpus(); @@ -255,8 +261,8 @@ public interface Metrics { * may be offline. To get the current online memory nodes, use * {@link getEffectiveCpuSetMems()}. * - * @return An array of available memory nodes or a zero length array - * if the metric is not available. + * @return An array of available memory nodes or null + * if the metric is not available or is not supported. * */ public int[] getCpuSetMems(); @@ -267,33 +273,12 @@ public interface Metrics { * array is equal to the total number of nodes and the elements in * the array are the physical node numbers. * - * @return An array of available and online nodes or a zero length - * array if the metric is not available. + * @return An array of available and online nodes or null + * if the metric is not available or is not supported. * */ public int[] getEffectiveCpuSetMems(); - /** - * Returns the (attempts per second * 1000), if enabled, that the - * operating system tries to satisfy a memory request for any - * process in the current Isolation Group when no free memory is - * readily available. Use {@link #isCpuSetMemoryPressureEnabled()} to - * determine if this support is enabled. - * - * @return Memory pressure or 0 if not enabled or metric is not - * available. - * - */ - public double getCpuSetMemoryPressure(); - - /** - * Returns the state of the memory pressure detection support. - * - * @return true if the support is available and enabled, otherwise false. - * - */ - public boolean isCpuSetMemoryPressureEnabled(); - /***************************************************************** * Memory Subsystem ****************************************************************/ @@ -302,8 +287,9 @@ public interface Metrics { * Returns the number of times that user memory requests in the * Isolation Group have exceeded the memory limit. * - * @return The number of exceeded requests or 0 if none or metric - * is not available. + * @return The number of exceeded requests or -1 if the metric + * is not available. Returns -2 if the metric is not + * supported. * */ public long getMemoryFailCount(); @@ -312,164 +298,54 @@ public interface Metrics { * Returns the maximum amount of physical memory, in bytes, that * can be allocated in the Isolation Group. * - * @return The maximum amount of memory in bytes or -1 if either - * there is no limit set or this metric is not available. + * @return The maximum amount of memory in bytes or -1 if + * there is no limit or -2 if this metric is not supported. * */ public long getMemoryLimit(); - /** - * Returns the largest amount of physical memory, in bytes, that - * have been allocated in the Isolation Group. - * - * @return The largest amount of memory in bytes or 0 if this - * metric is not available. - * - */ - public long getMemoryMaxUsage(); - /** * Returns the amount of physical memory, in bytes, that is currently * allocated in the current Isolation Group. * - * @return The amount of memory in bytes allocated or 0 if this - * metric is not available. + * @return The amount of memory in bytes allocated or -1 if + * the metric is not available or -2 if the metric is not + * supported. * */ public long getMemoryUsage(); - /** - * Returns the number of times that kernel memory requests in the - * Isolation Group have exceeded the kernel memory limit. - * - * @return The number of exceeded requests or 0 if none or metric - * is not available. - * - */ - public long getKernelMemoryFailCount(); - - /** - * Returns the maximum amount of kernel physical memory, in bytes, that - * can be allocated in the Isolation Group. - * - * @return The maximum amount of memory in bytes or -1 if either - * there is no limit set or this metric is not available. - * - */ - public long getKernelMemoryLimit(); - - /** - * Returns the largest amount of kernel physical memory, in bytes, that - * have been allocated in the Isolation Group. - * - * @return The largest amount of memory in bytes or 0 if this - * metric is not available. - * - */ - public long getKernelMemoryMaxUsage(); - - /** - * Returns the amount of kernel physical memory, in bytes, that - * is currently allocated in the current Isolation Group. - * - * @return The amount of memory in bytes allocated or 0 if this - * metric is not available. - * - */ - public long getKernelMemoryUsage(); - - /** - * Returns the number of times that networking memory requests in the - * Isolation Group have exceeded the kernel memory limit. - * - * @return The number of exceeded requests or 0 if none or metric - * is not available. - * - */ - public long getTcpMemoryFailCount(); - - /** - * Returns the maximum amount of networking physical memory, in bytes, - * that can be allocated in the Isolation Group. - * - * @return The maximum amount of memory in bytes or -1 if either - * there is no limit set or this metric is not available. - * - */ - public long getTcpMemoryLimit(); - - /** - * Returns the largest amount of networking physical memory, in bytes, - * that have been allocated in the Isolation Group. - * - * @return The largest amount of memory in bytes or 0 if this - * metric is not available. - * - */ - public long getTcpMemoryMaxUsage(); - /** * Returns the amount of networking physical memory, in bytes, that * is currently allocated in the current Isolation Group. * - * @return The amount of memory in bytes allocated or 0 if this - * metric is not available. + * @return The amount of memory in bytes allocated or -1 if the metric + * is not available. Returns -2 if this metric is not supported. * */ public long getTcpMemoryUsage(); - /** - * Returns the number of times that user memory requests in the - * Isolation Group have exceeded the memory + swap limit. - * - * @return The number of exceeded requests or 0 if none or metric - * is not available. - * - */ - public long getMemoryAndSwapFailCount(); - /** * Returns the maximum amount of physical memory and swap space, * in bytes, that can be allocated in the Isolation Group. * - * @return The maximum amount of memory in bytes or -1 if either - * there is no limit set or this metric is not available. + * @return The maximum amount of memory in bytes or -1 if + * there is no limit set or -2 if this metric is not supported. * */ public long getMemoryAndSwapLimit(); - /** - * Returns the largest amount of physical memory and swap space, - * in bytes, that have been allocated in the Isolation Group. - * - * @return The largest amount of memory in bytes or 0 if this - * metric is not available. - * - */ - public long getMemoryAndSwapMaxUsage(); - /** * Returns the amount of physical memory and swap space, in bytes, * that is currently allocated in the current Isolation Group. * - * @return The amount of memory in bytes allocated or 0 if this - * metric is not available. + * @return The amount of memory in bytes allocated or -1 if + * the metric is not available. Returns -2 if this metric is not + * supported. * */ public long getMemoryAndSwapUsage(); - /** - * Returns the state of the Operating System Out of Memory termination - * policy. - * - * @return Returns true if operating system will terminate processes - * in the Isolation Group that exceed the amount of available - * memory, otherwise false. Flase will be returned if this - * capability is not available on the current operating system. - * - */ - public boolean isMemoryOOMKillEnabled(); - /** * Returns the hint to the operating system that allows groups * to specify the minimum amount of physical memory that they need to @@ -478,8 +354,8 @@ public interface Metrics { * * @return The minimum amount of physical memory, in bytes, that the * operating system will try to maintain under low memory - * conditions. If this metric is not available, 0 will be - * returned. + * conditions. If this metric is not available, -1 will be + * returned. Returns -2 if the metric is not supported. * */ public long getMemorySoftLimit(); @@ -492,7 +368,8 @@ public interface Metrics { * Returns the number of block I/O requests to the disk that have been * issued by the Isolation Group. * - * @return The count of requests or 0 if this metric is not available. + * @return The count of requests or -1 if the metric is not available. + * Returns -2 if this metric is not supported. * */ public long getBlkIOServiceCount(); @@ -501,7 +378,8 @@ public interface Metrics { * Returns the number of block I/O bytes that have been transferred * to/from the disk by the Isolation Group. * - * @return The number of bytes transferred or 0 if this metric is not available. + * @return The number of bytes transferred or -1 if the metric is not + * available. Returns -2 if this metric is not supported. * */ public long getBlkIOServiced(); diff --git a/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/src/java.base/share/classes/sun/launcher/LauncherHelper.java index 4834a72e2ad..b6f32b6bad0 100644 --- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java +++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,10 +45,10 @@ import java.io.PrintStream; import java.io.UnsupportedEncodingException; import java.lang.module.Configuration; import java.lang.module.ModuleDescriptor; -import java.lang.module.ModuleDescriptor.Requires; import java.lang.module.ModuleDescriptor.Exports; import java.lang.module.ModuleDescriptor.Opens; import java.lang.module.ModuleDescriptor.Provides; +import java.lang.module.ModuleDescriptor.Requires; import java.lang.module.ModuleFinder; import java.lang.module.ModuleReference; import java.lang.module.ResolvedModule; @@ -62,8 +62,8 @@ import java.nio.charset.Charset; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; -import java.text.Normalizer; import java.text.MessageFormat; +import java.text.Normalizer; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -119,6 +119,7 @@ public final class LauncherHelper { private static final String defaultBundleName = "sun.launcher.resources.launcher"; + private static class ResourceBundleHolder { private static final ResourceBundle RB = ResourceBundle.getBundle(defaultBundleName); @@ -323,91 +324,110 @@ public final class LauncherHelper { return; } + final long longRetvalNotSupported = -2; + ostream.println(INDENT + "Provider: " + c.getProvider()); ostream.println(INDENT + "Effective CPU Count: " + c.getEffectiveCpuCount()); - ostream.println(INDENT + "CPU Period: " + c.getCpuPeriod() + - (c.getCpuPeriod() == -1 ? "" : "us")); - ostream.println(INDENT + "CPU Quota: " + c.getCpuQuota() + - (c.getCpuQuota() == -1 ? "" : "us")); - ostream.println(INDENT + "CPU Shares: " + c.getCpuShares()); + ostream.println(formatCpuVal(c.getCpuPeriod(), INDENT + "CPU Period: ", longRetvalNotSupported)); + ostream.println(formatCpuVal(c.getCpuQuota(), INDENT + "CPU Quota: ", longRetvalNotSupported)); + ostream.println(formatCpuVal(c.getCpuShares(), INDENT + "CPU Shares: ", longRetvalNotSupported)); int cpus[] = c.getCpuSetCpus(); - ostream.println(INDENT + "List of Processors, " - + cpus.length + " total: "); + if (cpus != null) { + ostream.println(INDENT + "List of Processors, " + + cpus.length + " total: "); - ostream.print(INDENT); - for (int i = 0; i < cpus.length; i++) { - ostream.print(cpus[i] + " "); - } - if (cpus.length > 0) { - ostream.println(""); + ostream.print(INDENT); + for (int i = 0; i < cpus.length; i++) { + ostream.print(cpus[i] + " "); + } + if (cpus.length > 0) { + ostream.println(""); + } + } else { + ostream.println(INDENT + "List of Processors: N/A"); } cpus = c.getEffectiveCpuSetCpus(); - ostream.println(INDENT + "List of Effective Processors, " - + cpus.length + " total: "); + if (cpus != null) { + ostream.println(INDENT + "List of Effective Processors, " + + cpus.length + " total: "); - ostream.print(INDENT); - for (int i = 0; i < cpus.length; i++) { - ostream.print(cpus[i] + " "); - } - if (cpus.length > 0) { - ostream.println(""); + ostream.print(INDENT); + for (int i = 0; i < cpus.length; i++) { + ostream.print(cpus[i] + " "); + } + if (cpus.length > 0) { + ostream.println(""); + } + } else { + ostream.println(INDENT + "List of Effective Processors: N/A"); } int mems[] = c.getCpuSetMems(); - ostream.println(INDENT + "List of Memory Nodes, " - + mems.length + " total: "); + if (mems != null) { + ostream.println(INDENT + "List of Memory Nodes, " + + mems.length + " total: "); - ostream.print(INDENT); - for (int i = 0; i < mems.length; i++) { - ostream.print(mems[i] + " "); - } - if (mems.length > 0) { - ostream.println(""); + ostream.print(INDENT); + for (int i = 0; i < mems.length; i++) { + ostream.print(mems[i] + " "); + } + if (mems.length > 0) { + ostream.println(""); + } + } else { + ostream.println(INDENT + "List of Memory Nodes: N/A"); } mems = c.getEffectiveCpuSetMems(); - ostream.println(INDENT + "List of Available Memory Nodes, " - + mems.length + " total: "); + if (mems != null) { + ostream.println(INDENT + "List of Available Memory Nodes, " + + mems.length + " total: "); - ostream.print(INDENT); - for (int i = 0; i < mems.length; i++) { - ostream.print(mems[i] + " "); + ostream.print(INDENT); + for (int i = 0; i < mems.length; i++) { + ostream.print(mems[i] + " "); + } + if (mems.length > 0) { + ostream.println(""); + } + } else { + ostream.println(INDENT + "List of Available Memory Nodes: N/A"); } - if (mems.length > 0) { - ostream.println(""); - } - - ostream.println(INDENT + "CPUSet Memory Pressure Enabled: " - + c.isCpuSetMemoryPressureEnabled()); long limit = c.getMemoryLimit(); - ostream.println(INDENT + "Memory Limit: " + - ((limit >= 0) ? SizePrefix.scaleValue(limit) : "Unlimited")); + ostream.println(formatLimitString(limit, INDENT + "Memory Limit: ", longRetvalNotSupported)); limit = c.getMemorySoftLimit(); - ostream.println(INDENT + "Memory Soft Limit: " + - ((limit >= 0) ? SizePrefix.scaleValue(limit) : "Unlimited")); + ostream.println(formatLimitString(limit, INDENT + "Memory Soft Limit: ", longRetvalNotSupported)); limit = c.getMemoryAndSwapLimit(); - ostream.println(INDENT + "Memory & Swap Limit: " + - ((limit >= 0) ? SizePrefix.scaleValue(limit) : "Unlimited")); - - limit = c.getKernelMemoryLimit(); - ostream.println(INDENT + "Kernel Memory Limit: " + - ((limit >= 0) ? SizePrefix.scaleValue(limit) : "Unlimited")); - - limit = c.getTcpMemoryLimit(); - ostream.println(INDENT + "TCP Memory Limit: " + - ((limit >= 0) ? SizePrefix.scaleValue(limit) : "Unlimited")); - - ostream.println(INDENT + "Out Of Memory Killer Enabled: " - + c.isMemoryOOMKillEnabled()); + ostream.println(formatLimitString(limit, INDENT + "Memory & Swap Limit: ", longRetvalNotSupported)); ostream.println(""); } + private static String formatLimitString(long limit, String prefix, long unavailable) { + if (limit >= 0) { + return prefix + SizePrefix.scaleValue(limit); + } else if (limit == unavailable) { + return prefix + "N/A"; + } else { + return prefix + "Unlimited"; + } + } + + private static String formatCpuVal(long cpuVal, String prefix, long unavailable) { + if (cpuVal >= 0) { + return prefix + cpuVal + "us"; + } else if (cpuVal == unavailable) { + return prefix + "N/A"; + } else { + return prefix + cpuVal; + } + } + private enum SizePrefix { KILO(1024, "K"), diff --git a/src/java.base/share/classes/sun/security/pkcs/ContentInfo.java b/src/java.base/share/classes/sun/security/pkcs/ContentInfo.java index 47a64dbfb79..00abc8d2d0c 100644 --- a/src/java.base/share/classes/sun/security/pkcs/ContentInfo.java +++ b/src/java.base/share/classes/sun/security/pkcs/ContentInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,50 +38,36 @@ import sun.security.util.*; public class ContentInfo { // pkcs7 pre-defined content types - private static int[] pkcs7 = {1, 2, 840, 113549, 1, 7}; - private static int[] data = {1, 2, 840, 113549, 1, 7, 1}; - private static int[] sdata = {1, 2, 840, 113549, 1, 7, 2}; - private static int[] edata = {1, 2, 840, 113549, 1, 7, 3}; - private static int[] sedata = {1, 2, 840, 113549, 1, 7, 4}; - private static int[] ddata = {1, 2, 840, 113549, 1, 7, 5}; - private static int[] crdata = {1, 2, 840, 113549, 1, 7, 6}; - private static int[] nsdata = {2, 16, 840, 1, 113730, 2, 5}; - // timestamp token (id-ct-TSTInfo) from RFC 3161 - private static int[] tstInfo = {1, 2, 840, 113549, 1, 9, 16, 1, 4}; - // this is for backwards-compatibility with JDK 1.1.x - private static final int[] OLD_SDATA = {1, 2, 840, 1113549, 1, 7, 2}; - private static final int[] OLD_DATA = {1, 2, 840, 1113549, 1, 7, 1}; - public static ObjectIdentifier PKCS7_OID; - public static ObjectIdentifier DATA_OID; - public static ObjectIdentifier SIGNED_DATA_OID; - public static ObjectIdentifier ENVELOPED_DATA_OID; - public static ObjectIdentifier SIGNED_AND_ENVELOPED_DATA_OID; - public static ObjectIdentifier DIGESTED_DATA_OID; - public static ObjectIdentifier ENCRYPTED_DATA_OID; - public static ObjectIdentifier OLD_SIGNED_DATA_OID; - public static ObjectIdentifier OLD_DATA_OID; - public static ObjectIdentifier NETSCAPE_CERT_SEQUENCE_OID; - public static ObjectIdentifier TIMESTAMP_TOKEN_INFO_OID; + public static ObjectIdentifier PKCS7_OID = + ObjectIdentifier.of("1.2.840.113549.1.7"); + public static ObjectIdentifier DATA_OID = + ObjectIdentifier.of("1.2.840.113549.1.7.1"); + public static ObjectIdentifier SIGNED_DATA_OID = + ObjectIdentifier.of("1.2.840.113549.1.7.2"); + public static ObjectIdentifier ENVELOPED_DATA_OID = + ObjectIdentifier.of("1.2.840.113549.1.7.3"); + public static ObjectIdentifier SIGNED_AND_ENVELOPED_DATA_OID = + ObjectIdentifier.of("1.2.840.113549.1.7.4"); + public static ObjectIdentifier DIGESTED_DATA_OID = + ObjectIdentifier.of("1.2.840.113549.1.7.5"); + public static ObjectIdentifier ENCRYPTED_DATA_OID = + ObjectIdentifier.of("1.2.840.113549.1.7.6"); - static { - PKCS7_OID = ObjectIdentifier.newInternal(pkcs7); - DATA_OID = ObjectIdentifier.newInternal(data); - SIGNED_DATA_OID = ObjectIdentifier.newInternal(sdata); - ENVELOPED_DATA_OID = ObjectIdentifier.newInternal(edata); - SIGNED_AND_ENVELOPED_DATA_OID = ObjectIdentifier.newInternal(sedata); - DIGESTED_DATA_OID = ObjectIdentifier.newInternal(ddata); - ENCRYPTED_DATA_OID = ObjectIdentifier.newInternal(crdata); - OLD_SIGNED_DATA_OID = ObjectIdentifier.newInternal(OLD_SDATA); - OLD_DATA_OID = ObjectIdentifier.newInternal(OLD_DATA); - /** - * The ASN.1 systax for the Netscape Certificate Sequence - * data type is defined - * - * here. - */ - NETSCAPE_CERT_SEQUENCE_OID = ObjectIdentifier.newInternal(nsdata); - TIMESTAMP_TOKEN_INFO_OID = ObjectIdentifier.newInternal(tstInfo); - } + // this is for backwards-compatibility with JDK 1.1.x + public static ObjectIdentifier OLD_SIGNED_DATA_OID = + ObjectIdentifier.of("1.2.840.1113549.1.7.2"); + public static ObjectIdentifier OLD_DATA_OID = + ObjectIdentifier.of("1.2.840.1113549.1.7.1"); + + // The ASN.1 systax for the Netscape Certificate Sequence data type is + // defined at: + // http://wp.netscape.com/eng/security/comm4-cert-download.html + public static ObjectIdentifier NETSCAPE_CERT_SEQUENCE_OID = + ObjectIdentifier.of("2.16.840.1.113730.2.5"); + + // timestamp token (id-ct-TSTInfo) from RFC 3161 + public static ObjectIdentifier TIMESTAMP_TOKEN_INFO_OID = + ObjectIdentifier.of("1.2.840.113549.1.9.16.1.4"); ObjectIdentifier contentType; DerValue content; // OPTIONAL diff --git a/src/java.base/share/classes/sun/security/pkcs/PKCS9Attribute.java b/src/java.base/share/classes/sun/security/pkcs/PKCS9Attribute.java index 463fbd74056..d66878182f5 100644 --- a/src/java.base/share/classes/sun/security/pkcs/PKCS9Attribute.java +++ b/src/java.base/share/classes/sun/security/pkcs/PKCS9Attribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * 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 @@ import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Locale; import java.util.Date; -import java.util.Hashtable; +import java.util.HashMap; import sun.security.x509.CertificateExtensions; import sun.security.util.Debug; import sun.security.util.DerEncoder; @@ -190,15 +190,14 @@ public class PKCS9Attribute implements DerEncoder { static { // static initializer for PKCS9_OIDS for (int i = 1; i < PKCS9_OIDS.length - 2; i++) { - PKCS9_OIDS[i] = - ObjectIdentifier.newInternal(new int[]{1,2,840,113549,1,9,i}); + PKCS9_OIDS[i] = ObjectIdentifier.of("1.2.840.113549.1.9." + i); } // Initialize SigningCertificate and SignatureTimestampToken // separately (because their values are out of sequence) PKCS9_OIDS[PKCS9_OIDS.length - 2] = - ObjectIdentifier.newInternal(new int[]{1,2,840,113549,1,9,16,2,12}); + ObjectIdentifier.of("1.2.840.113549.1.9.16.2.12"); PKCS9_OIDS[PKCS9_OIDS.length - 1] = - ObjectIdentifier.newInternal(new int[]{1,2,840,113549,1,9,16,2,14}); + ObjectIdentifier.of("1.2.840.113549.1.9.16.2.14"); try { BYTE_ARRAY_CLASS = Class.forName("[B"); @@ -248,12 +247,12 @@ public class PKCS9Attribute implements DerEncoder { "SignatureTimestampToken"; /** - * Hashtable mapping names and variant names of supported + * HashMap mapping names and variant names of supported * attributes to their OIDs. This table contains all name forms * that occur in PKCS9, in lower case. */ - private static final Hashtable NAME_OID_TABLE = - new Hashtable(18); + private static final HashMap NAME_OID_TABLE = + new HashMap(17); static { // static initializer for PCKS9_NAMES NAME_OID_TABLE.put("emailaddress", PKCS9_OIDS[1]); @@ -276,11 +275,11 @@ public class PKCS9Attribute implements DerEncoder { }; /** - * Hashtable mapping attribute OIDs defined in PKCS9 to the + * HashMap mapping attribute OIDs defined in PKCS9 to the * corresponding attribute value type. */ - private static final Hashtable OID_NAME_TABLE = - new Hashtable(16); + private static final HashMap OID_NAME_TABLE = + new HashMap(17); static { OID_NAME_TABLE.put(PKCS9_OIDS[1], EMAIL_ADDRESS_STR); OID_NAME_TABLE.put(PKCS9_OIDS[2], UNSTRUCTURED_NAME_STR); @@ -316,7 +315,10 @@ public class PKCS9Attribute implements DerEncoder { {DerValue.tag_UtcTime}, // SigningTime {DerValue.tag_Sequence}, // Countersignature {DerValue.tag_PrintableString, - DerValue.tag_T61String}, // ChallengePassword + DerValue.tag_T61String, + DerValue.tag_BMPString, + DerValue.tag_UniversalString, + DerValue.tag_UTF8String}, // ChallengePassword {DerValue.tag_PrintableString, DerValue.tag_T61String}, // UnstructuredAddress {DerValue.tag_SetOf}, // ExtendedCertificateAttributes @@ -509,9 +511,8 @@ public class PKCS9Attribute implements DerEncoder { // check for illegal element tags Byte tag; - for (int i=0; i < elems.length; i++) { - tag = elems[i].tag; - + for (DerValue elem : elems) { + tag = elem.tag; if (indexOf(tag, PKCS9_VALUE_TAGS[index], 0) == -1) throwTagException(tag); } @@ -600,6 +601,7 @@ public class PKCS9Attribute implements DerEncoder { * PrintableStrings, without checking whether they * should be encoded as T61Strings. */ + @Override public void derEncode(OutputStream out) throws IOException { DerOutputStream temp = new DerOutputStream(); temp.putOID(oid); @@ -788,6 +790,7 @@ public class PKCS9Attribute implements DerEncoder { /** * Returns a string representation of this attribute. */ + @Override public String toString() { StringBuilder sb = new StringBuilder(100); @@ -813,13 +816,12 @@ public class PKCS9Attribute implements DerEncoder { boolean first = true; Object[] values = (Object[]) value; - for (int j=0; j < values.length; j++) { + for (Object curVal : values) { if (first) first = false; else sb.append(", "); - - sb.append(values[j].toString()); + sb.append(curVal.toString()); } return sb.toString(); } diff --git a/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java b/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java index ba586b49a4f..ae9b5a7a217 100644 --- a/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java +++ b/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -157,34 +157,34 @@ public final class PKCS12KeyStore extends KeyStoreSpi { private static final Debug debug = Debug.getInstance("pkcs12"); - private static final int[] keyBag = {1, 2, 840, 113549, 1, 12, 10, 1, 2}; - private static final int[] certBag = {1, 2, 840, 113549, 1, 12, 10, 1, 3}; - private static final int[] secretBag = {1, 2, 840, 113549, 1, 12, 10, 1, 5}; + private static final ObjectIdentifier PKCS8ShroudedKeyBag_OID = + ObjectIdentifier.of("1.2.840.113549.1.12.10.1.2"); + private static final ObjectIdentifier CertBag_OID = + ObjectIdentifier.of("1.2.840.113549.1.12.10.1.3"); + private static final ObjectIdentifier SecretBag_OID = + ObjectIdentifier.of("1.2.840.113549.1.12.10.1.5"); + private static final ObjectIdentifier PKCS9FriendlyName_OID = + ObjectIdentifier.of("1.2.840.113549.1.9.20"); + private static final ObjectIdentifier PKCS9LocalKeyId_OID = + ObjectIdentifier.of("1.2.840.113549.1.9.21"); + private static final ObjectIdentifier PKCS9CertType_OID = + ObjectIdentifier.of("1.2.840.113549.1.9.22.1"); + private static final ObjectIdentifier pbes2_OID = + ObjectIdentifier.of("1.2.840.113549.1.5.13"); - private static final int[] pkcs9Name = {1, 2, 840, 113549, 1, 9, 20}; - private static final int[] pkcs9KeyId = {1, 2, 840, 113549, 1, 9, 21}; - - private static final int[] pkcs9certType = {1, 2, 840, 113549, 1, 9, 22, 1}; - - private static final int[] pbes2 = {1, 2, 840, 113549, 1, 5, 13}; - // TODO: temporary Oracle OID /* - * { joint-iso-itu-t(2) country(16) us(840) organization(1) oracle(113894) - * jdk(746875) crypto(1) id-at-trustedKeyUsage(1) } + * Temporary Oracle OID + * + * {joint-iso-itu-t(2) country(16) us(840) organization(1) + * oracle(113894) jdk(746875) crypto(1) id-at-trustedKeyUsage(1)} */ - private static final int[] TrustedKeyUsage = - {2, 16, 840, 1, 113894, 746875, 1, 1}; - private static final int[] AnyExtendedKeyUsage = {2, 5, 29, 37, 0}; + private static final ObjectIdentifier TrustedKeyUsage_OID = + ObjectIdentifier.of("2.16.840.1.113894.746875.1.1"); - private static final ObjectIdentifier PKCS8ShroudedKeyBag_OID; - private static final ObjectIdentifier CertBag_OID; - private static final ObjectIdentifier SecretBag_OID; - private static final ObjectIdentifier PKCS9FriendlyName_OID; - private static final ObjectIdentifier PKCS9LocalKeyId_OID; - private static final ObjectIdentifier PKCS9CertType_OID; - private static final ObjectIdentifier pbes2_OID; - private static final ObjectIdentifier TrustedKeyUsage_OID; - private static final ObjectIdentifier[] AnyUsage; + private static final ObjectIdentifier[] AnyUsage = new ObjectIdentifier[] { + // AnyExtendedKeyUsage + ObjectIdentifier.of("2.5.29.37.0") + }; private int counter = 0; @@ -213,23 +213,6 @@ public final class PKCS12KeyStore extends KeyStoreSpi { // the source of randomness private SecureRandom random; - static { - try { - PKCS8ShroudedKeyBag_OID = new ObjectIdentifier(keyBag); - CertBag_OID = new ObjectIdentifier(certBag); - SecretBag_OID = new ObjectIdentifier(secretBag); - PKCS9FriendlyName_OID = new ObjectIdentifier(pkcs9Name); - PKCS9LocalKeyId_OID = new ObjectIdentifier(pkcs9KeyId); - PKCS9CertType_OID = new ObjectIdentifier(pkcs9certType); - pbes2_OID = new ObjectIdentifier(pbes2); - TrustedKeyUsage_OID = new ObjectIdentifier(TrustedKeyUsage); - AnyUsage = new ObjectIdentifier[]{ - new ObjectIdentifier(AnyExtendedKeyUsage)}; - } catch (IOException ioe) { - throw new AssertionError("OID not initialized", ioe); - } - } - // A keystore entry and associated attributes private static class Entry { Date date; // the creation date of this entry diff --git a/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java b/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java index 34a8fcd3e7d..9747835f870 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java @@ -135,7 +135,7 @@ public final class OCSPResponse { private static final Debug debug = Debug.getInstance("certpath"); private static final boolean dump = debug != null && Debug.isOn("ocsp"); private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID = - ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 1}); + ObjectIdentifier.of("1.3.6.1.5.5.7.48.1.1"); private static final int CERT_STATUS_GOOD = 0; private static final int CERT_STATUS_REVOKED = 1; private static final int CERT_STATUS_UNKNOWN = 2; diff --git a/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java b/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java index 40222f22c3b..e95408b9f62 100644 --- a/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java +++ b/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -304,11 +304,11 @@ public class RSAPSSSignature extends SignatureSpi { private static void checkKeyLength(RSAKey key, int digestLen, int saltLen) throws SignatureException { if (key != null) { - int keyLength = getKeyLengthInBits(key) >> 3; + int keyLength = (getKeyLengthInBits(key) + 7) >> 3; int minLength = Math.addExact(Math.addExact(digestLen, saltLen), 2); if (keyLength < minLength) { throw new SignatureException - ("Key is too short, need min " + minLength); + ("Key is too short, need min " + minLength + " bytes"); } } } @@ -429,7 +429,7 @@ public class RSAPSSSignature extends SignatureSpi { } try { int emBits = getKeyLengthInBits(this.privKey) - 1; - int emLen =(emBits + 7) >> 3; + int emLen = (emBits + 7) >> 3; int hLen = this.md.getDigestLength(); int dbLen = emLen - hLen - 1; int sLen = this.sigParams.getSaltLength(); @@ -472,6 +472,7 @@ public class RSAPSSSignature extends SignatureSpi { // step11: set the leftmost (8emLen - emBits) bits of the leftmost // octet to 0 int numZeroBits = (emLen << 3) - emBits; + if (numZeroBits != 0) { byte MASK = (byte) (0xff >>> numZeroBits); em[0] = (byte) (em[0] & MASK); @@ -485,15 +486,22 @@ public class RSAPSSSignature extends SignatureSpi { } /** - * Decode the signature data. Verify that the object identifier matches - * and return the message digest. + * Decode the signature data as under RFC8017 sec9.1.2 EMSA-PSS-VERIFY */ private boolean decodeSignature(byte[] mHash, byte[] em) throws IOException { int hLen = mHash.length; int sLen = this.sigParams.getSaltLength(); - int emLen = em.length; int emBits = getKeyLengthInBits(this.pubKey) - 1; + int emLen = (emBits + 7) >> 3; + + // When key length is 8N+1 bits (N+1 bytes), emBits = 8N, + // emLen = N which is one byte shorter than em.length. + // Otherwise, emLen should be same as em.length + int emOfs = em.length - emLen; + if ((emOfs == 1) && (em[0] != 0)) { + return false; + } // step3 if (emLen < (hLen + sLen + 2)) { @@ -501,16 +509,17 @@ public class RSAPSSSignature extends SignatureSpi { } // step4 - if (em[emLen - 1] != (byte) 0xBC) { + if (em[emOfs + emLen - 1] != (byte) 0xBC) { return false; } // step6: check if the leftmost (8emLen - emBits) bits of the leftmost // octet are 0 int numZeroBits = (emLen << 3) - emBits; + if (numZeroBits != 0) { byte MASK = (byte) (0xff << (8 - numZeroBits)); - if ((em[0] & MASK) != 0) { + if ((em[emOfs] & MASK) != 0) { return false; } } @@ -526,7 +535,8 @@ public class RSAPSSSignature extends SignatureSpi { int dbLen = emLen - hLen - 1; try { MGF1 mgf1 = new MGF1(mgfDigestAlgo); - mgf1.generateAndXor(em, dbLen, hLen, dbLen, em, 0); + mgf1.generateAndXor(em, emOfs + dbLen, hLen, dbLen, + em, emOfs); } catch (NoSuchAlgorithmException nsae) { throw new IOException(nsae.toString()); } @@ -535,12 +545,12 @@ public class RSAPSSSignature extends SignatureSpi { // octet to 0 if (numZeroBits != 0) { byte MASK = (byte) (0xff >>> numZeroBits); - em[0] = (byte) (em[0] & MASK); + em[emOfs] = (byte) (em[emOfs] & MASK); } // step10 - int i = 0; - for (; i < dbLen - sLen - 1; i++) { + int i = emOfs; + for (; i < emOfs + (dbLen - sLen - 1); i++) { if (em[i] != 0) { return false; } @@ -553,13 +563,14 @@ public class RSAPSSSignature extends SignatureSpi { digestReset = false; this.md.update(mHash); if (sLen > 0) { - this.md.update(em, (dbLen - sLen), sLen); + this.md.update(em, emOfs + (dbLen - sLen), sLen); } byte[] digest2 = this.md.digest(); digestReset = true; // step14 - byte[] digestInEM = Arrays.copyOfRange(em, dbLen, emLen - 1); + byte[] digestInEM = Arrays.copyOfRange(em, emOfs + dbLen, + emOfs + emLen - 1); return MessageDigest.isEqual(digest2, digestInEM); } diff --git a/src/java.base/share/classes/sun/security/util/ECUtil.java b/src/java.base/share/classes/sun/security/util/ECUtil.java index 8fc44bb029a..739f3648dfd 100644 --- a/src/java.base/share/classes/sun/security/util/ECUtil.java +++ b/src/java.base/share/classes/sun/security/util/ECUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,17 @@ import java.util.Arrays; public final class ECUtil { + // Used by SunEC + public static byte[] sArray(BigInteger s, ECParameterSpec params) { + byte[] arr = s.toByteArray(); + ArrayUtil.reverse(arr); + int byteLength = (params.getOrder().bitLength() + 7) / 8; + byte[] arrayS = new byte[byteLength]; + int length = Math.min(byteLength, arr.length); + System.arraycopy(arr, 0, arrayS, 0, length); + return arrayS; + } + // Used by SunPKCS11 and SunJSSE. public static ECPoint decodePoint(byte[] data, EllipticCurve curve) throws IOException { diff --git a/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java b/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java index f28a02a9487..224cc12a477 100644 --- a/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java +++ b/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,9 +50,7 @@ import java.util.Arrays; * @author Hemma Prafullchandra */ -public final -class ObjectIdentifier implements Serializable -{ +public final class ObjectIdentifier implements Serializable { /** * We use the DER value (no tag, no length) as the internal format * @serial @@ -100,6 +98,7 @@ class ObjectIdentifier implements Serializable */ @SuppressWarnings("serial") // Not statically typed as Serializable private Object components = null; // path from root + /** * @serial */ @@ -141,15 +140,15 @@ class ObjectIdentifier implements Serializable static class HugeOidNotSupportedByOldJDK implements Serializable { @java.io.Serial private static final long serialVersionUID = 1L; - static HugeOidNotSupportedByOldJDK theOne = new HugeOidNotSupportedByOldJDK(); + static HugeOidNotSupportedByOldJDK theOne = + new HugeOidNotSupportedByOldJDK(); } /** * Constructs, from a string. This string should be of the form 1.23.56. * Validity check included. */ - public ObjectIdentifier (String oid) throws IOException - { + public ObjectIdentifier(String oid) throws IOException { int ch = '.'; int start = 0; int end = 0; @@ -217,20 +216,6 @@ class ObjectIdentifier implements Serializable } } - /** - * Constructor, from an array of integers. - * Validity check included. - */ - public ObjectIdentifier(int[] values) throws IOException - { - checkCount(values.length); - checkFirstComponent(values[0]); - checkSecondComponent(values[0], values[1]); - for (int i=2; i 4) { - BigInteger big = new BigInteger(pack(encoding, fromPos, i-fromPos+1, 7, 8)); + BigInteger big = new BigInteger(pack(encoding, + fromPos, i-fromPos+1, 7, 8)); if (fromPos == 0) { result[which++] = 2; - BigInteger second = big.subtract(BigInteger.valueOf(80)); - if (second.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 1) { + BigInteger second = + big.subtract(BigInteger.valueOf(80)); + if (second.compareTo( + BigInteger.valueOf(Integer.MAX_VALUE)) == 1) { return null; } else { result[which++] = second.intValue(); } } else { - if (big.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 1) { + if (big.compareTo( + BigInteger.valueOf(Integer.MAX_VALUE)) == 1) { return null; } else { result[which++] = big.intValue(); @@ -435,7 +417,8 @@ class ObjectIdentifier implements Serializable sb.append('.'); } if (i - fromPos + 1 > 4) { // maybe big integer - BigInteger big = new BigInteger(pack(encoding, fromPos, i-fromPos+1, 7, 8)); + BigInteger big = new BigInteger( + pack(encoding, fromPos, i-fromPos+1, 7, 8)); if (fromPos == 0) { // first section encoded with more than 4 bytes, // must be 2.something @@ -476,7 +459,7 @@ class ObjectIdentifier implements Serializable /** * Repack all bits from input to output. On the both sides, only a portion * (from the least significant bit) of the 8 bits in a byte is used. This - * number is defined as the number of useful bits (NUB) for the array. All the + * number is defined as the number of useful bits (NUB) for the array. All * used bits from the input byte array and repacked into the output in the * exactly same order. The output bits are aligned so that the final bit of * the input (the least significant bit in the last byte), when repacked as @@ -498,7 +481,8 @@ class ObjectIdentifier implements Serializable * @param ow NUB for output * @return the repacked bytes */ - private static byte[] pack(byte[] in, int ioffset, int ilength, int iw, int ow) { + private static byte[] pack(byte[] in, + int ioffset, int ilength, int iw, int ow) { assert (iw > 0 && iw <= 8): "input NUB must be between 1 and 8"; assert (ow > 0 && ow <= 8): "output NUB must be between 1 and 8"; @@ -520,12 +504,13 @@ class ObjectIdentifier implements Serializable if (count > ow - opos%ow) { // free space available in output byte count = ow - opos%ow; // choose the smaller number } + // and move them! - out[opos/ow] |= // paste! - (((in[ioffset+ipos/iw]+256) // locate the byte (+256 so that it's never negative) - >> (iw-ipos%iw-count)) // move to the end of a byte - & ((1 << (count))-1)) // zero out all other bits - << (ow-opos%ow-count); // move to the output position + out[opos/ow] |= // paste! + (((in[ioffset+ipos/iw]+256) // locate the byte (+256 so that it's never negative) + >> (iw-ipos%iw-count)) & // move to the end of a byte + ((1 << (count))-1)) // zero out all other bits + << (ow-opos%ow-count); // move to the output position ipos += count; // advance opos += count; // advance } @@ -541,7 +526,8 @@ class ObjectIdentifier implements Serializable * @param ooffset the starting position to paste * @return the number of bytes pasted */ - private static int pack7Oid(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) { + private static int pack7Oid(byte[] in, + int ioffset, int ilength, byte[] out, int ooffset) { byte[] pack = pack(in, ioffset, ilength, 8, 7); int firstNonZero = pack.length-1; // paste at least one byte for (int i=pack.length-2; i>=0; i--) { @@ -550,7 +536,8 @@ class ObjectIdentifier implements Serializable } pack[i] |= 0x80; } - System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero); + System.arraycopy(pack, firstNonZero, + out, ooffset, pack.length-firstNonZero); return pack.length-firstNonZero; } @@ -561,7 +548,8 @@ class ObjectIdentifier implements Serializable * @param ooffset the starting position to paste * @return the number of bytes pasted */ - private static int pack8(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) { + private static int pack8(byte[] in, + int ioffset, int ilength, byte[] out, int ooffset) { byte[] pack = pack(in, ioffset, ilength, 7, 8); int firstNonZero = pack.length-1; // paste at least one byte for (int i=pack.length-2; i>=0; i--) { @@ -569,7 +557,8 @@ class ObjectIdentifier implements Serializable firstNonZero = i; } } - System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero); + System.arraycopy(pack, firstNonZero, + out, ooffset, pack.length-firstNonZero); return pack.length-firstNonZero; } @@ -621,31 +610,39 @@ class ObjectIdentifier implements Serializable } } } + private static void checkCount(int count) throws IOException { if (count < 2) { throw new IOException("ObjectIdentifier() -- " + "Must be at least two oid components "); } } + private static void checkFirstComponent(int first) throws IOException { if (first < 0 || first > 2) { throw new IOException("ObjectIdentifier() -- " + "First oid component is invalid "); } } - private static void checkFirstComponent(BigInteger first) throws IOException { + + private static void checkFirstComponent( + BigInteger first) throws IOException { if (first.signum() == -1 || first.compareTo(BigInteger.TWO) > 0) { throw new IOException("ObjectIdentifier() -- " + "First oid component is invalid "); } } - private static void checkSecondComponent(int first, int second) throws IOException { + + private static void checkSecondComponent( + int first, int second) throws IOException { if (second < 0 || first != 2 && second > 39) { throw new IOException("ObjectIdentifier() -- " + "Second oid component is invalid "); } } - private static void checkSecondComponent(int first, BigInteger second) throws IOException { + + private static void checkSecondComponent( + int first, BigInteger second) throws IOException { if (second.signum() == -1 || first != 2 && second.compareTo(BigInteger.valueOf(39)) == 1) { @@ -653,13 +650,16 @@ class ObjectIdentifier implements Serializable "Second oid component is invalid "); } } + private static void checkOtherComponent(int i, int num) throws IOException { if (num < 0) { throw new IOException("ObjectIdentifier() -- " + "oid component #" + (i+1) + " must be non-negative "); } } - private static void checkOtherComponent(int i, BigInteger num) throws IOException { + + private static void checkOtherComponent( + int i, BigInteger num) throws IOException { if (num.signum() == -1) { throw new IOException("ObjectIdentifier() -- " + "oid component #" + (i+1) + " must be non-negative "); diff --git a/src/java.base/share/classes/sun/security/x509/AccessDescription.java b/src/java.base/share/classes/sun/security/x509/AccessDescription.java index 45fa695e88c..62389d52f80 100644 --- a/src/java.base/share/classes/sun/security/x509/AccessDescription.java +++ b/src/java.base/share/classes/sun/security/x509/AccessDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,16 +42,16 @@ public final class AccessDescription { private GeneralName accessLocation; public static final ObjectIdentifier Ad_OCSP_Id = - ObjectIdentifier.newInternal(new int[] {1, 3, 6, 1, 5, 5, 7, 48, 1}); + ObjectIdentifier.of("1.3.6.1.5.5.7.48.1"); public static final ObjectIdentifier Ad_CAISSUERS_Id = - ObjectIdentifier.newInternal(new int[] {1, 3, 6, 1, 5, 5, 7, 48, 2}); + ObjectIdentifier.of("1.3.6.1.5.5.7.48.2"); public static final ObjectIdentifier Ad_TIMESTAMPING_Id = - ObjectIdentifier.newInternal(new int[] {1, 3, 6, 1, 5, 5, 7, 48, 3}); + ObjectIdentifier.of("1.3.6.1.5.5.7.48.3"); public static final ObjectIdentifier Ad_CAREPOSITORY_Id = - ObjectIdentifier.newInternal(new int[] {1, 3, 6, 1, 5, 5, 7, 48, 5}); + ObjectIdentifier.of("1.3.6.1.5.5.7.48.5"); public AccessDescription(ObjectIdentifier accessMethod, GeneralName accessLocation) { this.accessMethod = accessMethod; diff --git a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java index 06c905a9d05..f24a7e6559e 100644 --- a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java +++ b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -591,10 +591,6 @@ public class AlgorithmId implements Serializable, DerEncoder { return oidTable().get(name.toUpperCase(Locale.ENGLISH)); } - private static ObjectIdentifier oid(int ... values) { - return ObjectIdentifier.newInternal(values); - } - private static volatile Map oidTable; private static final Map nameTable; @@ -654,14 +650,14 @@ public class AlgorithmId implements Serializable, DerEncoder { * OID = 1.2.840.113549.2.2 */ public static final ObjectIdentifier MD2_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 2, 2}); + ObjectIdentifier.of("1.2.840.113549.2.2"); /** * Algorithm ID for the MD5 Message Digest Algorthm, from RFC 1321. * OID = 1.2.840.113549.2.5 */ public static final ObjectIdentifier MD5_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 2, 5}); + ObjectIdentifier.of("1.2.840.113549.2.5"); /** * Algorithm ID for the SHA1 Message Digest Algorithm, from FIPS 180-1. @@ -670,142 +666,29 @@ public class AlgorithmId implements Serializable, DerEncoder { * OID = 1.3.14.3.2.26. Old SHA-0 OID: 1.3.14.3.2.18. */ public static final ObjectIdentifier SHA_oid = - ObjectIdentifier.newInternal(new int[] {1, 3, 14, 3, 2, 26}); + ObjectIdentifier.of("1.3.14.3.2.26"); public static final ObjectIdentifier SHA224_oid = - ObjectIdentifier.newInternal(new int[] {2, 16, 840, 1, 101, 3, 4, 2, 4}); + ObjectIdentifier.of("2.16.840.1.101.3.4.2.4"); public static final ObjectIdentifier SHA256_oid = - ObjectIdentifier.newInternal(new int[] {2, 16, 840, 1, 101, 3, 4, 2, 1}); + ObjectIdentifier.of("2.16.840.1.101.3.4.2.1"); public static final ObjectIdentifier SHA384_oid = - ObjectIdentifier.newInternal(new int[] {2, 16, 840, 1, 101, 3, 4, 2, 2}); + ObjectIdentifier.of("2.16.840.1.101.3.4.2.2"); public static final ObjectIdentifier SHA512_oid = - ObjectIdentifier.newInternal(new int[] {2, 16, 840, 1, 101, 3, 4, 2, 3}); + ObjectIdentifier.of("2.16.840.1.101.3.4.2.3"); public static final ObjectIdentifier SHA512_224_oid = - ObjectIdentifier.newInternal(new int[] {2, 16, 840, 1, 101, 3, 4, 2, 5}); + ObjectIdentifier.of("2.16.840.1.101.3.4.2.5"); public static final ObjectIdentifier SHA512_256_oid = - ObjectIdentifier.newInternal(new int[] {2, 16, 840, 1, 101, 3, 4, 2, 6}); + ObjectIdentifier.of("2.16.840.1.101.3.4.2.6"); /* * COMMON PUBLIC KEY TYPES */ - private static final int[] DH_data = { 1, 2, 840, 113549, 1, 3, 1 }; - private static final int[] DH_PKIX_data = { 1, 2, 840, 10046, 2, 1 }; - private static final int[] DSA_OIW_data = { 1, 3, 14, 3, 2, 12 }; - private static final int[] DSA_PKIX_data = { 1, 2, 840, 10040, 4, 1 }; - private static final int[] RSA_data = { 2, 5, 8, 1, 1 }; - - public static final ObjectIdentifier DH_oid; - public static final ObjectIdentifier DH_PKIX_oid; - public static final ObjectIdentifier DSA_oid; - public static final ObjectIdentifier DSA_OIW_oid; - public static final ObjectIdentifier EC_oid = oid(1, 2, 840, 10045, 2, 1); - public static final ObjectIdentifier ECDH_oid = oid(1, 3, 132, 1, 12); - public static final ObjectIdentifier RSA_oid; - public static final ObjectIdentifier RSAEncryption_oid = - oid(1, 2, 840, 113549, 1, 1, 1); - public static final ObjectIdentifier RSAES_OAEP_oid = - oid(1, 2, 840, 113549, 1, 1, 7); - public static final ObjectIdentifier mgf1_oid = - oid(1, 2, 840, 113549, 1, 1, 8); - public static final ObjectIdentifier RSASSA_PSS_oid = - oid(1, 2, 840, 113549, 1, 1, 10); - - /* - * COMMON SECRET KEY TYPES - */ - public static final ObjectIdentifier AES_oid = - oid(2, 16, 840, 1, 101, 3, 4, 1); - - /* - * COMMON SIGNATURE ALGORITHMS - */ - private static final int[] md2WithRSAEncryption_data = - { 1, 2, 840, 113549, 1, 1, 2 }; - private static final int[] md5WithRSAEncryption_data = - { 1, 2, 840, 113549, 1, 1, 4 }; - private static final int[] sha1WithRSAEncryption_data = - { 1, 2, 840, 113549, 1, 1, 5 }; - private static final int[] sha1WithRSAEncryption_OIW_data = - { 1, 3, 14, 3, 2, 29 }; - private static final int[] sha224WithRSAEncryption_data = - { 1, 2, 840, 113549, 1, 1, 14 }; - private static final int[] sha256WithRSAEncryption_data = - { 1, 2, 840, 113549, 1, 1, 11 }; - private static final int[] sha384WithRSAEncryption_data = - { 1, 2, 840, 113549, 1, 1, 12 }; - private static final int[] sha512WithRSAEncryption_data = - { 1, 2, 840, 113549, 1, 1, 13 }; - - private static final int[] shaWithDSA_OIW_data = - { 1, 3, 14, 3, 2, 13 }; - private static final int[] sha1WithDSA_OIW_data = - { 1, 3, 14, 3, 2, 27 }; - private static final int[] dsaWithSHA1_PKIX_data = - { 1, 2, 840, 10040, 4, 3 }; - - public static final ObjectIdentifier md2WithRSAEncryption_oid; - public static final ObjectIdentifier md5WithRSAEncryption_oid; - public static final ObjectIdentifier sha1WithRSAEncryption_oid; - public static final ObjectIdentifier sha1WithRSAEncryption_OIW_oid; - public static final ObjectIdentifier sha224WithRSAEncryption_oid; - public static final ObjectIdentifier sha256WithRSAEncryption_oid; - public static final ObjectIdentifier sha384WithRSAEncryption_oid; - public static final ObjectIdentifier sha512WithRSAEncryption_oid; - public static final ObjectIdentifier sha512_224WithRSAEncryption_oid = - oid(1, 2, 840, 113549, 1, 1, 15); - public static final ObjectIdentifier sha512_256WithRSAEncryption_oid = - oid(1, 2, 840, 113549, 1, 1, 16);; - - public static final ObjectIdentifier shaWithDSA_OIW_oid; - public static final ObjectIdentifier sha1WithDSA_OIW_oid; - public static final ObjectIdentifier sha1WithDSA_oid; - public static final ObjectIdentifier sha224WithDSA_oid = - oid(2, 16, 840, 1, 101, 3, 4, 3, 1); - public static final ObjectIdentifier sha256WithDSA_oid = - oid(2, 16, 840, 1, 101, 3, 4, 3, 2); - - public static final ObjectIdentifier sha1WithECDSA_oid = - oid(1, 2, 840, 10045, 4, 1); - public static final ObjectIdentifier sha224WithECDSA_oid = - oid(1, 2, 840, 10045, 4, 3, 1); - public static final ObjectIdentifier sha256WithECDSA_oid = - oid(1, 2, 840, 10045, 4, 3, 2); - public static final ObjectIdentifier sha384WithECDSA_oid = - oid(1, 2, 840, 10045, 4, 3, 3); - public static final ObjectIdentifier sha512WithECDSA_oid = - oid(1, 2, 840, 10045, 4, 3, 4); - public static final ObjectIdentifier specifiedWithECDSA_oid = - oid(1, 2, 840, 10045, 4, 3); - - /** - * Algorithm ID for the PBE encryption algorithms from PKCS#5 and - * PKCS#12. - */ - public static final ObjectIdentifier pbeWithMD5AndDES_oid = - ObjectIdentifier.newInternal(new int[]{1, 2, 840, 113549, 1, 5, 3}); - public static final ObjectIdentifier pbeWithMD5AndRC2_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 5, 6}); - public static final ObjectIdentifier pbeWithSHA1AndDES_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 5, 10}); - public static final ObjectIdentifier pbeWithSHA1AndRC2_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 5, 11}); - public static ObjectIdentifier pbeWithSHA1AndRC4_128_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 12, 1, 1}); - public static ObjectIdentifier pbeWithSHA1AndRC4_40_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 12, 1, 2}); - public static ObjectIdentifier pbeWithSHA1AndDESede_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 12, 1, 3}); - public static ObjectIdentifier pbeWithSHA1AndRC2_128_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 12, 1, 5}); - public static ObjectIdentifier pbeWithSHA1AndRC2_40_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 12, 1, 6}); - - static { /* * Note the preferred OIDs are named simply with no "OIW" or * "PKIX" in them, even though they may point to data from these @@ -819,14 +702,16 @@ public class AlgorithmId implements Serializable, DerEncoder { * certificate. * OID = 1.2.840.113549.1.3.1 */ - DH_oid = ObjectIdentifier.newInternal(DH_data); + public static final ObjectIdentifier DH_oid = + ObjectIdentifier.of("1.2.840.113549.1.3.1"); /** * Algorithm ID for the Diffie Hellman Key Agreement (DH), from RFC 3279. * Parameters may include public values P and G. * OID = 1.2.840.10046.2.1 */ - DH_PKIX_oid = ObjectIdentifier.newInternal(DH_PKIX_data); + public static final ObjectIdentifier DH_PKIX_oid = + ObjectIdentifier.of("1.2.840.10046.2.1"); /** * Algorithm ID for the Digital Signing Algorithm (DSA), from the @@ -836,7 +721,8 @@ public class AlgorithmId implements Serializable, DerEncoder { * another source such as a Certificate Authority's certificate. * OID = 1.3.14.3.2.12 */ - DSA_OIW_oid = ObjectIdentifier.newInternal(DSA_OIW_data); + public static final ObjectIdentifier DSA_OIW_oid = + ObjectIdentifier.of("1.3.14.3.2.12"); /** * Algorithm ID for the Digital Signing Algorithm (DSA), from RFC 3279. @@ -845,7 +731,8 @@ public class AlgorithmId implements Serializable, DerEncoder { * certificate. * OID = 1.2.840.10040.4.1 */ - DSA_oid = ObjectIdentifier.newInternal(DSA_PKIX_data); + public static final ObjectIdentifier DSA_oid = + ObjectIdentifier.of("1.2.840.10040.4.1"); /** * Algorithm ID for RSA keys used for any purpose, as defined in X.509. @@ -853,72 +740,95 @@ public class AlgorithmId implements Serializable, DerEncoder { * public modulus. * OID = 2.5.8.1.1 */ - RSA_oid = ObjectIdentifier.newInternal(RSA_data); + public static final ObjectIdentifier RSA_oid = + ObjectIdentifier.of("2.5.8.1.1"); + public static final ObjectIdentifier EC_oid = + ObjectIdentifier.of("1.2.840.10045.2.1"); + public static final ObjectIdentifier ECDH_oid = + ObjectIdentifier.of("1.3.132.1.12"); + public static final ObjectIdentifier RSAEncryption_oid = + ObjectIdentifier.of("1.2.840.113549.1.1.1"); + public static final ObjectIdentifier RSAES_OAEP_oid = + ObjectIdentifier.of("1.2.840.113549.1.1.7"); + public static final ObjectIdentifier mgf1_oid = + ObjectIdentifier.of("1.2.840.113549.1.1.8"); + public static final ObjectIdentifier RSASSA_PSS_oid = + ObjectIdentifier.of("1.2.840.113549.1.1.10"); + + /* + * COMMON SECRET KEY TYPES + */ + public static final ObjectIdentifier AES_oid = + ObjectIdentifier.of("2.16.840.1.101.3.4.1"); + + /* + * COMMON SIGNATURE ALGORITHMS + */ /** * Identifies a signing algorithm where an MD2 digest is encrypted * using an RSA private key; defined in PKCS #1. Use of this * signing algorithm is discouraged due to MD2 vulnerabilities. * OID = 1.2.840.113549.1.1.2 */ - md2WithRSAEncryption_oid = - ObjectIdentifier.newInternal(md2WithRSAEncryption_data); + public static final ObjectIdentifier md2WithRSAEncryption_oid = + ObjectIdentifier.of("1.2.840.113549.1.1.2"); /** * Identifies a signing algorithm where an MD5 digest is * encrypted using an RSA private key; defined in PKCS #1. * OID = 1.2.840.113549.1.1.4 */ - md5WithRSAEncryption_oid = - ObjectIdentifier.newInternal(md5WithRSAEncryption_data); + public static final ObjectIdentifier md5WithRSAEncryption_oid = + ObjectIdentifier.of("1.2.840.113549.1.1.4"); /** * Identifies a signing algorithm where a SHA1 digest is * encrypted using an RSA private key; defined by RSA DSI. * OID = 1.2.840.113549.1.1.5 */ - sha1WithRSAEncryption_oid = - ObjectIdentifier.newInternal(sha1WithRSAEncryption_data); + public static final ObjectIdentifier sha1WithRSAEncryption_oid = + ObjectIdentifier.of("1.2.840.113549.1.1.5"); /** * Identifies a signing algorithm where a SHA1 digest is * encrypted using an RSA private key; defined in NIST OIW. * OID = 1.3.14.3.2.29 */ - sha1WithRSAEncryption_OIW_oid = - ObjectIdentifier.newInternal(sha1WithRSAEncryption_OIW_data); + public static final ObjectIdentifier sha1WithRSAEncryption_OIW_oid = + ObjectIdentifier.of("1.3.14.3.2.29"); /** * Identifies a signing algorithm where a SHA224 digest is * encrypted using an RSA private key; defined by PKCS #1. * OID = 1.2.840.113549.1.1.14 */ - sha224WithRSAEncryption_oid = - ObjectIdentifier.newInternal(sha224WithRSAEncryption_data); + public static final ObjectIdentifier sha224WithRSAEncryption_oid = + ObjectIdentifier.of("1.2.840.113549.1.1.14"); /** * Identifies a signing algorithm where a SHA256 digest is * encrypted using an RSA private key; defined by PKCS #1. * OID = 1.2.840.113549.1.1.11 */ - sha256WithRSAEncryption_oid = - ObjectIdentifier.newInternal(sha256WithRSAEncryption_data); + public static final ObjectIdentifier sha256WithRSAEncryption_oid = + ObjectIdentifier.of("1.2.840.113549.1.1.11"); /** * Identifies a signing algorithm where a SHA384 digest is * encrypted using an RSA private key; defined by PKCS #1. * OID = 1.2.840.113549.1.1.12 */ - sha384WithRSAEncryption_oid = - ObjectIdentifier.newInternal(sha384WithRSAEncryption_data); + public static final ObjectIdentifier sha384WithRSAEncryption_oid = + ObjectIdentifier.of("1.2.840.113549.1.1.12"); /** * Identifies a signing algorithm where a SHA512 digest is * encrypted using an RSA private key; defined by PKCS #1. * OID = 1.2.840.113549.1.1.13 */ - sha512WithRSAEncryption_oid = - ObjectIdentifier.newInternal(sha512WithRSAEncryption_data); + public static final ObjectIdentifier sha512WithRSAEncryption_oid = + ObjectIdentifier.of("1.2.840.113549.1.1.13"); /** * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a @@ -926,22 +836,72 @@ public class AlgorithmId implements Serializable, DerEncoder { * This should not be used. * OID = 1.3.14.3.2.13 */ - shaWithDSA_OIW_oid = ObjectIdentifier.newInternal(shaWithDSA_OIW_data); + public static final ObjectIdentifier shaWithDSA_OIW_oid = + ObjectIdentifier.of("1.3.14.3.2.13"); /** * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a * SHA1 digest is signed using the Digital Signing Algorithm (DSA). * OID = 1.3.14.3.2.27 */ - sha1WithDSA_OIW_oid = ObjectIdentifier.newInternal(sha1WithDSA_OIW_data); + public static final ObjectIdentifier sha1WithDSA_OIW_oid = + ObjectIdentifier.of("1.3.14.3.2.27"); /** * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a * SHA1 digest is signed using the Digital Signing Algorithm (DSA). * OID = 1.2.840.10040.4.3 */ - sha1WithDSA_oid = ObjectIdentifier.newInternal(dsaWithSHA1_PKIX_data); + public static final ObjectIdentifier sha1WithDSA_oid = + ObjectIdentifier.of("1.2.840.10040.4.3"); + public static final ObjectIdentifier sha512_224WithRSAEncryption_oid = + ObjectIdentifier.of("1.2.840.113549.1.1.15"); + public static final ObjectIdentifier sha512_256WithRSAEncryption_oid = + ObjectIdentifier.of("1.2.840.113549.1.1.16"); + + public static final ObjectIdentifier sha224WithDSA_oid = + ObjectIdentifier.of("2.16.840.1.101.3.4.3.1"); + public static final ObjectIdentifier sha256WithDSA_oid = + ObjectIdentifier.of("2.16.840.1.101.3.4.3.2"); + + public static final ObjectIdentifier sha1WithECDSA_oid = + ObjectIdentifier.of("1.2.840.10045.4.1"); + public static final ObjectIdentifier sha224WithECDSA_oid = + ObjectIdentifier.of("1.2.840.10045.4.3.1"); + public static final ObjectIdentifier sha256WithECDSA_oid = + ObjectIdentifier.of("1.2.840.10045.4.3.2"); + public static final ObjectIdentifier sha384WithECDSA_oid = + ObjectIdentifier.of("1.2.840.10045.4.3.3"); + public static final ObjectIdentifier sha512WithECDSA_oid = + ObjectIdentifier.of("1.2.840.10045.4.3.4"); + public static final ObjectIdentifier specifiedWithECDSA_oid = + ObjectIdentifier.of("1.2.840.10045.4.3"); + + /** + * Algorithm ID for the PBE encryption algorithms from PKCS#5 and + * PKCS#12. + */ + public static final ObjectIdentifier pbeWithMD5AndDES_oid = + ObjectIdentifier.of("1.2.840.113549.1.5.3"); + public static final ObjectIdentifier pbeWithMD5AndRC2_oid = + ObjectIdentifier.of("1.2.840.113549.1.5.6"); + public static final ObjectIdentifier pbeWithSHA1AndDES_oid = + ObjectIdentifier.of("1.2.840.113549.1.5.10"); + public static final ObjectIdentifier pbeWithSHA1AndRC2_oid = + ObjectIdentifier.of("1.2.840.113549.1.5.11"); + public static final ObjectIdentifier pbeWithSHA1AndRC4_128_oid = + ObjectIdentifier.of("1.2.840.113549.1.12.1.1"); + public static final ObjectIdentifier pbeWithSHA1AndRC4_40_oid = + ObjectIdentifier.of("1.2.840.113549.1.12.1.2"); + public static final ObjectIdentifier pbeWithSHA1AndDESede_oid = + ObjectIdentifier.of("1.2.840.113549.1.12.1.3"); + public static final ObjectIdentifier pbeWithSHA1AndRC2_128_oid = + ObjectIdentifier.of("1.2.840.113549.1.12.1.5"); + public static final ObjectIdentifier pbeWithSHA1AndRC2_40_oid = + ObjectIdentifier.of("1.2.840.113549.1.12.1.6"); + + static { nameTable = new HashMap<>(); nameTable.put(MD5_oid, "MD5"); nameTable.put(MD2_oid, "MD2"); diff --git a/src/java.base/share/classes/sun/security/x509/CertificateValidity.java b/src/java.base/share/classes/sun/security/x509/CertificateValidity.java index 29852d35e28..a5cff7d4bfa 100644 --- a/src/java.base/share/classes/sun/security/x509/CertificateValidity.java +++ b/src/java.base/share/classes/sun/security/x509/CertificateValidity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,10 @@ public class CertificateValidity implements CertAttrSet { public static final String NAME = "validity"; public static final String NOT_BEFORE = "notBefore"; public static final String NOT_AFTER = "notAfter"; - private static final long YR_2050 = 2524636800000L; + /** + * YR_2050 date and time set to Jan01 00:00 2050 GMT + */ + static final long YR_2050 = 2524608000000L; // Private data members private Date notBefore; diff --git a/src/java.base/share/classes/sun/security/x509/ExtendedKeyUsageExtension.java b/src/java.base/share/classes/sun/security/x509/ExtendedKeyUsageExtension.java index c8968448c7f..32691d1d759 100644 --- a/src/java.base/share/classes/sun/security/x509/ExtendedKeyUsageExtension.java +++ b/src/java.base/share/classes/sun/security/x509/ExtendedKeyUsageExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,30 +97,19 @@ implements CertAttrSet { // OID defined in RFC 5280 Sections 4.2.1.12 // more from http://www.alvestrand.no/objectid/1.3.6.1.5.5.7.3.html private static final Map map = - new HashMap (); - - private static final int[] anyExtendedKeyUsageOidData = {2, 5, 29, 37, 0}; - private static final int[] serverAuthOidData = {1, 3, 6, 1, 5, 5, 7, 3, 1}; - private static final int[] clientAuthOidData = {1, 3, 6, 1, 5, 5, 7, 3, 2}; - private static final int[] codeSigningOidData = {1, 3, 6, 1, 5, 5, 7, 3, 3}; - private static final int[] emailProtectionOidData = {1, 3, 6, 1, 5, 5, 7, 3, 4}; - private static final int[] ipsecEndSystemOidData = {1, 3, 6, 1, 5, 5, 7, 3, 5}; - private static final int[] ipsecTunnelOidData = {1, 3, 6, 1, 5, 5, 7, 3, 6}; - private static final int[] ipsecUserOidData = {1, 3, 6, 1, 5, 5, 7, 3, 7}; - private static final int[] timeStampingOidData = {1, 3, 6, 1, 5, 5, 7, 3, 8}; - private static final int[] OCSPSigningOidData = {1, 3, 6, 1, 5, 5, 7, 3, 9}; + new HashMap(); static { - map.put(ObjectIdentifier.newInternal(anyExtendedKeyUsageOidData), "anyExtendedKeyUsage"); - map.put(ObjectIdentifier.newInternal(serverAuthOidData), "serverAuth"); - map.put(ObjectIdentifier.newInternal(clientAuthOidData), "clientAuth"); - map.put(ObjectIdentifier.newInternal(codeSigningOidData), "codeSigning"); - map.put(ObjectIdentifier.newInternal(emailProtectionOidData), "emailProtection"); - map.put(ObjectIdentifier.newInternal(ipsecEndSystemOidData), "ipsecEndSystem"); - map.put(ObjectIdentifier.newInternal(ipsecTunnelOidData), "ipsecTunnel"); - map.put(ObjectIdentifier.newInternal(ipsecUserOidData), "ipsecUser"); - map.put(ObjectIdentifier.newInternal(timeStampingOidData), "timeStamping"); - map.put(ObjectIdentifier.newInternal(OCSPSigningOidData), "OCSPSigning"); + map.put(ObjectIdentifier.of("2.5.29.37.0"), "anyExtendedKeyUsage"); + map.put(ObjectIdentifier.of("1.3.6.1.5.5.7.3.1"), "serverAuth"); + map.put(ObjectIdentifier.of("1.3.6.1.5.5.7.3.2"), "clientAuth"); + map.put(ObjectIdentifier.of("1.3.6.1.5.5.7.3.3"), "codeSigning"); + map.put(ObjectIdentifier.of("1.3.6.1.5.5.7.3.4"), "emailProtection"); + map.put(ObjectIdentifier.of("1.3.6.1.5.5.7.3.5"), "ipsecEndSystem"); + map.put(ObjectIdentifier.of("1.3.6.1.5.5.7.3.6"), "ipsecTunnel"); + map.put(ObjectIdentifier.of("1.3.6.1.5.5.7.3.7"), "ipsecUser"); + map.put(ObjectIdentifier.of("1.3.6.1.5.5.7.3.8"), "timeStamping"); + map.put(ObjectIdentifier.of("1.3.6.1.5.5.7.3.9"), "OCSPSigning"); }; /** diff --git a/src/java.base/share/classes/sun/security/x509/GeneralSubtrees.java b/src/java.base/share/classes/sun/security/x509/GeneralSubtrees.java index 847f56aba86..8adafe20344 100644 --- a/src/java.base/share/classes/sun/security/x509/GeneralSubtrees.java +++ b/src/java.base/share/classes/sun/security/x509/GeneralSubtrees.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -270,8 +270,7 @@ public class GeneralSubtrees implements Cloneable { newName = new GeneralName(new IPAddressName((byte[])null)); break; case GeneralNameInterface.NAME_OID: - newName = new GeneralName - (new OIDName(new ObjectIdentifier((int[])null))); + newName = new GeneralName(new OIDName("")); break; default: throw new IOException diff --git a/src/java.base/share/classes/sun/security/x509/InhibitAnyPolicyExtension.java b/src/java.base/share/classes/sun/security/x509/InhibitAnyPolicyExtension.java index a20a1f55803..b21af10cc55 100644 --- a/src/java.base/share/classes/sun/security/x509/InhibitAnyPolicyExtension.java +++ b/src/java.base/share/classes/sun/security/x509/InhibitAnyPolicyExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,14 +75,8 @@ implements CertAttrSet { /** * Object identifier for "any-policy" */ - public static ObjectIdentifier AnyPolicy_Id; - static { - try { - AnyPolicy_Id = new ObjectIdentifier("2.5.29.32.0"); - } catch (IOException ioe) { - // Should not happen - } - } + public static ObjectIdentifier AnyPolicy_Id = + ObjectIdentifier.of("2.5.29.32.0"); /** * Attribute names. diff --git a/src/java.base/share/classes/sun/security/x509/NetscapeCertTypeExtension.java b/src/java.base/share/classes/sun/security/x509/NetscapeCertTypeExtension.java index ca4dc3c53c3..c5577bbf2ec 100644 --- a/src/java.base/share/classes/sun/security/x509/NetscapeCertTypeExtension.java +++ b/src/java.base/share/classes/sun/security/x509/NetscapeCertTypeExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. * 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,20 +69,11 @@ implements CertAttrSet { public static final String S_MIME_CA = "s_mime_ca"; public static final String OBJECT_SIGNING_CA = "object_signing_ca"; - private static final int[] CertType_data = { 2, 16, 840, 1, 113730, 1, 1 }; - /** * Object identifier for the Netscape-Cert-Type extension. */ - public static ObjectIdentifier NetscapeCertType_Id; - - static { - try { - NetscapeCertType_Id = new ObjectIdentifier(CertType_data); - } catch (IOException ioe) { - // should not happen - } - } + public static ObjectIdentifier NetscapeCertType_Id = + ObjectIdentifier.of("2.16.840.1.113730.1.1"); private boolean[] bitString; diff --git a/src/java.base/share/classes/sun/security/x509/OIDMap.java b/src/java.base/share/classes/sun/security/x509/OIDMap.java index a39493e279a..472de53e171 100644 --- a/src/java.base/share/classes/sun/security/x509/OIDMap.java +++ b/src/java.base/share/classes/sun/security/x509/OIDMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * 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,9 +102,6 @@ public class OIDMap { private static final String OCSPNOCHECK = ROOT + "." + OCSPNoCheckExtension.NAME; - private static final int[] NetscapeCertType_data = - { 2, 16, 840, 1, 113730, 1, 1 }; - /** Map ObjectIdentifier(oid) -> OIDInfo(info) */ private static final Map oidMap; @@ -138,8 +135,8 @@ public class OIDMap { "sun.security.x509.AuthorityKeyIdentifierExtension"); addInternal(POLICY_CONSTRAINTS, PKIXExtensions.PolicyConstraints_Id, "sun.security.x509.PolicyConstraintsExtension"); - addInternal(NETSCAPE_CERT, ObjectIdentifier.newInternal - (new int[] {2,16,840,1,113730,1,1}), + addInternal(NETSCAPE_CERT, + ObjectIdentifier.of("2.16.840.1.113730.1.1"), "sun.security.x509.NetscapeCertTypeExtension"); addInternal(CERT_POLICIES, PKIXExtensions.CertificatePolicies_Id, "sun.security.x509.CertificatePoliciesExtension"); diff --git a/src/java.base/share/classes/sun/security/x509/PKIXExtensions.java b/src/java.base/share/classes/sun/security/x509/PKIXExtensions.java index bf4f8fdf80c..af182f57663 100644 --- a/src/java.base/share/classes/sun/security/x509/PKIXExtensions.java +++ b/src/java.base/share/classes/sun/security/x509/PKIXExtensions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package sun.security.x509; -import java.io.*; import sun.security.util.*; @@ -48,163 +47,151 @@ import sun.security.util.*; * @author Hemma Prafullchandra */ public class PKIXExtensions { - // The object identifiers - private static final int[] AuthorityKey_data = { 2, 5, 29, 35 }; - private static final int[] SubjectKey_data = { 2, 5, 29, 14 }; - private static final int[] KeyUsage_data = { 2, 5, 29, 15 }; - private static final int[] PrivateKeyUsage_data = { 2, 5, 29, 16 }; - private static final int[] CertificatePolicies_data = { 2, 5, 29, 32 }; - private static final int[] PolicyMappings_data = { 2, 5, 29, 33 }; - private static final int[] SubjectAlternativeName_data = { 2, 5, 29, 17 }; - private static final int[] IssuerAlternativeName_data = { 2, 5, 29, 18 }; - private static final int[] SubjectDirectoryAttributes_data = { 2, 5, 29, 9 }; - private static final int[] BasicConstraints_data = { 2, 5, 29, 19 }; - private static final int[] NameConstraints_data = { 2, 5, 29, 30 }; - private static final int[] PolicyConstraints_data = { 2, 5, 29, 36 }; - private static final int[] CRLDistributionPoints_data = { 2, 5, 29, 31 }; - private static final int[] CRLNumber_data = { 2, 5, 29, 20 }; - private static final int[] IssuingDistributionPoint_data = { 2, 5, 29, 28 }; - private static final int[] DeltaCRLIndicator_data = { 2, 5, 29, 27 }; - private static final int[] ReasonCode_data = { 2, 5, 29, 21 }; - private static final int[] HoldInstructionCode_data = { 2, 5, 29, 23 }; - private static final int[] InvalidityDate_data = { 2, 5, 29, 24 }; - private static final int[] ExtendedKeyUsage_data = { 2, 5, 29, 37 }; - private static final int[] InhibitAnyPolicy_data = { 2, 5, 29, 54 }; - private static final int[] CertificateIssuer_data = { 2, 5, 29, 29 }; - private static final int[] AuthInfoAccess_data = { 1, 3, 6, 1, 5, 5, 7, 1, 1}; - private static final int[] SubjectInfoAccess_data = { 1, 3, 6, 1, 5, 5, 7, 1, 11}; - private static final int[] FreshestCRL_data = { 2, 5, 29, 46 }; - private static final int[] OCSPNoCheck_data = { 1, 3, 6, 1, 5, 5, 7, - 48, 1, 5}; - - // Additional extensions under the PKIX arc that are not necessarily - // used in X.509 Certificates or CRLs. - private static final int OCSPNonce_data [] = { 1, 3, 6, 1, 5, 5, 7, - 48, 1, 2}; - /** * Identifies the particular public key used to sign the certificate. */ - public static final ObjectIdentifier AuthorityKey_Id; + public static final ObjectIdentifier AuthorityKey_Id = + ObjectIdentifier.of("2.5.29.35"); /** * Identifies the particular public key used in an application. */ - public static final ObjectIdentifier SubjectKey_Id; + public static final ObjectIdentifier SubjectKey_Id = + ObjectIdentifier.of("2.5.29.14"); /** * Defines the purpose of the key contained in the certificate. */ - public static final ObjectIdentifier KeyUsage_Id; + public static final ObjectIdentifier KeyUsage_Id = + ObjectIdentifier.of("2.5.29.15"); /** * Allows the certificate issuer to specify a different validity period * for the private key than the certificate. */ - public static final ObjectIdentifier PrivateKeyUsage_Id; + public static final ObjectIdentifier PrivateKeyUsage_Id = + ObjectIdentifier.of("2.5.29.16"); /** * Contains the sequence of policy information terms. */ - public static final ObjectIdentifier CertificatePolicies_Id; + public static final ObjectIdentifier CertificatePolicies_Id = + ObjectIdentifier.of("2.5.29.32"); /** * Lists pairs of object identifiers of policies considered equivalent by * the issuing CA to the subject CA. */ - public static final ObjectIdentifier PolicyMappings_Id; + public static final ObjectIdentifier PolicyMappings_Id = + ObjectIdentifier.of("2.5.29.33"); /** * Allows additional identities to be bound to the subject of the * certificate. */ - public static final ObjectIdentifier SubjectAlternativeName_Id; + public static final ObjectIdentifier SubjectAlternativeName_Id = + ObjectIdentifier.of("2.5.29.17"); /** * Allows additional identities to be associated with the certificate * issuer. */ - public static final ObjectIdentifier IssuerAlternativeName_Id; + public static final ObjectIdentifier IssuerAlternativeName_Id = + ObjectIdentifier.of("2.5.29.18"); /** * Identifies additional directory attributes. * This extension is always non-critical. */ - public static final ObjectIdentifier SubjectDirectoryAttributes_Id; + public static final ObjectIdentifier SubjectDirectoryAttributes_Id = + ObjectIdentifier.of("2.5.29.9"); /** * Identifies whether the subject of the certificate is a CA and how deep * a certification path may exist through that CA. */ - public static final ObjectIdentifier BasicConstraints_Id; + public static final ObjectIdentifier BasicConstraints_Id = + ObjectIdentifier.of("2.5.29.19"); /** * Provides for permitted and excluded subtrees that place restrictions * on names that may be included within a certificate issued by a given CA. */ - public static final ObjectIdentifier NameConstraints_Id; + public static final ObjectIdentifier NameConstraints_Id = + ObjectIdentifier.of("2.5.29.30"); /** * Used to either prohibit policy mapping or limit the set of policies * that can be in subsequent certificates. */ - public static final ObjectIdentifier PolicyConstraints_Id; + public static final ObjectIdentifier PolicyConstraints_Id = + ObjectIdentifier.of("2.5.29.36"); /** * Identifies how CRL information is obtained. */ - public static final ObjectIdentifier CRLDistributionPoints_Id; + public static final ObjectIdentifier CRLDistributionPoints_Id = + ObjectIdentifier.of("2.5.29.31"); /** * Conveys a monotonically increasing sequence number for each CRL * issued by a given CA. */ - public static final ObjectIdentifier CRLNumber_Id; + public static final ObjectIdentifier CRLNumber_Id = + ObjectIdentifier.of("2.5.29.20"); /** * Identifies the CRL distribution point for a particular CRL. */ - public static final ObjectIdentifier IssuingDistributionPoint_Id; + public static final ObjectIdentifier IssuingDistributionPoint_Id = + ObjectIdentifier.of("2.5.29.28"); /** * Identifies the delta CRL. */ - public static final ObjectIdentifier DeltaCRLIndicator_Id; + public static final ObjectIdentifier DeltaCRLIndicator_Id = + ObjectIdentifier.of("2.5.29.27"); /** * Identifies the reason for the certificate revocation. */ - public static final ObjectIdentifier ReasonCode_Id; + public static final ObjectIdentifier ReasonCode_Id = + ObjectIdentifier.of("2.5.29.21"); /** * This extension provides a registered instruction identifier indicating * the action to be taken, after encountering a certificate that has been * placed on hold. */ - public static final ObjectIdentifier HoldInstructionCode_Id; + public static final ObjectIdentifier HoldInstructionCode_Id = + ObjectIdentifier.of("2.5.29.23"); /** * Identifies the date on which it is known or suspected that the private * key was compromised or that the certificate otherwise became invalid. */ - public static final ObjectIdentifier InvalidityDate_Id; + public static final ObjectIdentifier InvalidityDate_Id = + ObjectIdentifier.of("2.5.29.24"); /** * Identifies one or more purposes for which the certified public key * may be used, in addition to or in place of the basic purposes * indicated in the key usage extension field. */ - public static final ObjectIdentifier ExtendedKeyUsage_Id; + public static final ObjectIdentifier ExtendedKeyUsage_Id = + ObjectIdentifier.of("2.5.29.37"); /** * Specifies whether any-policy policy OID is permitted */ - public static final ObjectIdentifier InhibitAnyPolicy_Id; + public static final ObjectIdentifier InhibitAnyPolicy_Id = + ObjectIdentifier.of("2.5.29.54"); /** * Identifies the certificate issuer associated with an entry in an * indirect CRL. */ - public static final ObjectIdentifier CertificateIssuer_Id; + public static final ObjectIdentifier CertificateIssuer_Id = + ObjectIdentifier.of("2.5.29.29"); /** * This extension indicates how to access CA information and services for @@ -212,73 +199,33 @@ public class PKIXExtensions { * This information may be used for on-line certification validation * services. */ - public static final ObjectIdentifier AuthInfoAccess_Id; + public static final ObjectIdentifier AuthInfoAccess_Id = + ObjectIdentifier.of("1.3.6.1.5.5.7.1.1"); /** * This extension indicates how to access CA information and services for * the subject of the certificate in which the extension appears. */ - public static final ObjectIdentifier SubjectInfoAccess_Id; + public static final ObjectIdentifier SubjectInfoAccess_Id = + ObjectIdentifier.of("1.3.6.1.5.5.7.1.11"); /** * Identifies how delta CRL information is obtained. */ - public static final ObjectIdentifier FreshestCRL_Id; + public static final ObjectIdentifier FreshestCRL_Id = + ObjectIdentifier.of("2.5.29.46"); /** * Identifies the OCSP client can trust the responder for the * lifetime of the responder's certificate. */ - public static final ObjectIdentifier OCSPNoCheck_Id; + public static final ObjectIdentifier OCSPNoCheck_Id = + ObjectIdentifier.of("1.3.6.1.5.5.7.48.1.5"); /** * This extension is used to provide nonce data for OCSP requests * or responses. */ - public static final ObjectIdentifier OCSPNonce_Id; - - static { - AuthorityKey_Id = ObjectIdentifier.newInternal(AuthorityKey_data); - SubjectKey_Id = ObjectIdentifier.newInternal(SubjectKey_data); - KeyUsage_Id = ObjectIdentifier.newInternal(KeyUsage_data); - PrivateKeyUsage_Id = ObjectIdentifier.newInternal(PrivateKeyUsage_data); - CertificatePolicies_Id = - ObjectIdentifier.newInternal(CertificatePolicies_data); - PolicyMappings_Id = ObjectIdentifier.newInternal(PolicyMappings_data); - SubjectAlternativeName_Id = - ObjectIdentifier.newInternal(SubjectAlternativeName_data); - IssuerAlternativeName_Id = - ObjectIdentifier.newInternal(IssuerAlternativeName_data); - ExtendedKeyUsage_Id = ObjectIdentifier.newInternal(ExtendedKeyUsage_data); - InhibitAnyPolicy_Id = ObjectIdentifier.newInternal(InhibitAnyPolicy_data); - SubjectDirectoryAttributes_Id = - ObjectIdentifier.newInternal(SubjectDirectoryAttributes_data); - BasicConstraints_Id = - ObjectIdentifier.newInternal(BasicConstraints_data); - ReasonCode_Id = ObjectIdentifier.newInternal(ReasonCode_data); - HoldInstructionCode_Id = - ObjectIdentifier.newInternal(HoldInstructionCode_data); - InvalidityDate_Id = ObjectIdentifier.newInternal(InvalidityDate_data); - - NameConstraints_Id = ObjectIdentifier.newInternal(NameConstraints_data); - PolicyConstraints_Id = - ObjectIdentifier.newInternal(PolicyConstraints_data); - CRLDistributionPoints_Id = - ObjectIdentifier.newInternal(CRLDistributionPoints_data); - CRLNumber_Id = - ObjectIdentifier.newInternal(CRLNumber_data); - IssuingDistributionPoint_Id = - ObjectIdentifier.newInternal(IssuingDistributionPoint_data); - DeltaCRLIndicator_Id = - ObjectIdentifier.newInternal(DeltaCRLIndicator_data); - CertificateIssuer_Id = - ObjectIdentifier.newInternal(CertificateIssuer_data); - AuthInfoAccess_Id = - ObjectIdentifier.newInternal(AuthInfoAccess_data); - SubjectInfoAccess_Id = - ObjectIdentifier.newInternal(SubjectInfoAccess_data); - FreshestCRL_Id = ObjectIdentifier.newInternal(FreshestCRL_data); - OCSPNoCheck_Id = ObjectIdentifier.newInternal(OCSPNoCheck_data); - OCSPNonce_Id = ObjectIdentifier.newInternal(OCSPNonce_data); - } + public static final ObjectIdentifier OCSPNonce_Id = + ObjectIdentifier.of("1.3.6.1.5.5.7.48.1.2"); } diff --git a/src/java.base/share/classes/sun/security/x509/X500Name.java b/src/java.base/share/classes/sun/security/x509/X500Name.java index 9bf9c55fb61..ed265524151 100644 --- a/src/java.base/share/classes/sun/security/x509/X500Name.java +++ b/src/java.base/share/classes/sun/security/x509/X500Name.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1102,104 +1102,83 @@ public class X500Name implements GeneralNameInterface, Principal { * Includes all those specified in RFC 5280 as MUST or SHOULD * be recognized */ - private static final int[] commonName_data = { 2, 5, 4, 3 }; - private static final int[] SURNAME_DATA = { 2, 5, 4, 4 }; - private static final int[] SERIALNUMBER_DATA = { 2, 5, 4, 5 }; - private static final int[] countryName_data = { 2, 5, 4, 6 }; - private static final int[] localityName_data = { 2, 5, 4, 7 }; - private static final int[] stateName_data = { 2, 5, 4, 8 }; - private static final int[] streetAddress_data = { 2, 5, 4, 9 }; - private static final int[] orgName_data = { 2, 5, 4, 10 }; - private static final int[] orgUnitName_data = { 2, 5, 4, 11 }; - private static final int[] title_data = { 2, 5, 4, 12 }; - private static final int[] GIVENNAME_DATA = { 2, 5, 4, 42 }; - private static final int[] INITIALS_DATA = { 2, 5, 4, 43 }; - private static final int[] GENERATIONQUALIFIER_DATA = { 2, 5, 4, 44 }; - private static final int[] DNQUALIFIER_DATA = { 2, 5, 4, 46 }; - - private static final int[] ipAddress_data = { 1, 3, 6, 1, 4, 1, 42, 2, 11, 2, 1 }; - private static final int[] DOMAIN_COMPONENT_DATA = - { 0, 9, 2342, 19200300, 100, 1, 25 }; - private static final int[] userid_data = - { 0, 9, 2342, 19200300, 100, 1, 1 }; - // OID for the "CN=" attribute, denoting a person's common name. public static final ObjectIdentifier commonName_oid = - ObjectIdentifier.newInternal(commonName_data); + ObjectIdentifier.of("2.5.4.3"); + + // OID for the "SURNAME=" attribute, denoting a person's surname. + public static final ObjectIdentifier SURNAME_OID = + ObjectIdentifier.of("2.5.4.4"); // OID for the "SERIALNUMBER=" attribute, denoting a serial number for. // a name. Do not confuse with PKCS#9 issuerAndSerialNumber or the // certificate serial number. public static final ObjectIdentifier SERIALNUMBER_OID = - ObjectIdentifier.newInternal(SERIALNUMBER_DATA); + ObjectIdentifier.of("2.5.4.5"); // OID for the "C=" attribute, denoting a country. public static final ObjectIdentifier countryName_oid = - ObjectIdentifier.newInternal(countryName_data); + ObjectIdentifier.of("2.5.4.6"); // OID for the "L=" attribute, denoting a locality (such as a city). public static final ObjectIdentifier localityName_oid = - ObjectIdentifier.newInternal(localityName_data); - - // OID for the "O=" attribute, denoting an organization name. - public static final ObjectIdentifier orgName_oid = - ObjectIdentifier.newInternal(orgName_data); - - // OID for the "OU=" attribute, denoting an organizational unit name. - public static final ObjectIdentifier orgUnitName_oid = - ObjectIdentifier.newInternal(orgUnitName_data); + ObjectIdentifier.of("2.5.4.7"); // OID for the "S=" attribute, denoting a state (such as Delaware). public static final ObjectIdentifier stateName_oid = - ObjectIdentifier.newInternal(stateName_data); + ObjectIdentifier.of("2.5.4.8"); // OID for the "STREET=" attribute, denoting a street address. public static final ObjectIdentifier streetAddress_oid = - ObjectIdentifier.newInternal(streetAddress_data); + ObjectIdentifier.of("2.5.4.9"); + + // OID for the "O=" attribute, denoting an organization name. + public static final ObjectIdentifier orgName_oid = + ObjectIdentifier.of("2.5.4.10"); + + // OID for the "OU=" attribute, denoting an organizational unit name. + public static final ObjectIdentifier orgUnitName_oid = + ObjectIdentifier.of("2.5.4.11"); // OID for the "T=" attribute, denoting a person's title. public static final ObjectIdentifier title_oid = - ObjectIdentifier.newInternal(title_data); + ObjectIdentifier.of("2.5.4.12"); + + // OID for the "GIVENNAME=" attribute, denoting a person's given name. + public static final ObjectIdentifier GIVENNAME_OID = + ObjectIdentifier.of("2.5.4.42"); + + // OID for the "INITIALS=" attribute, denoting a person's initials. + public static final ObjectIdentifier INITIALS_OID = + ObjectIdentifier.of("2.5.4.43"); + + // OID for the "GENERATION=" attribute, denoting Jr., II, etc. + public static final ObjectIdentifier GENERATIONQUALIFIER_OID = + ObjectIdentifier.of("2.5.4.44"); // OID for the "DNQUALIFIER=" or "DNQ=" attribute, denoting DN // disambiguating information. public static final ObjectIdentifier DNQUALIFIER_OID = - ObjectIdentifier.newInternal(DNQUALIFIER_DATA); - - // OID for the "SURNAME=" attribute, denoting a person's surname. - public static final ObjectIdentifier SURNAME_OID = - ObjectIdentifier.newInternal(SURNAME_DATA); - - // OID for the "GIVENNAME=" attribute, denoting a person's given name. - public static final ObjectIdentifier GIVENNAME_OID = - ObjectIdentifier.newInternal(GIVENNAME_DATA); - - // OID for the "INITIALS=" attribute, denoting a person's initials. - public static final ObjectIdentifier INITIALS_OID = - ObjectIdentifier.newInternal(INITIALS_DATA); - - // OID for the "GENERATION=" attribute, denoting Jr., II, etc. - public static final ObjectIdentifier GENERATIONQUALIFIER_OID = - ObjectIdentifier.newInternal(GENERATIONQUALIFIER_DATA); + ObjectIdentifier.of("2.5.4.46"); // OIDs from other sources which show up in X.500 names we // expect to deal with often. // // OID for "IP=" IP address attributes, used with SKIP. public static final ObjectIdentifier ipAddress_oid = - ObjectIdentifier.newInternal(ipAddress_data); + ObjectIdentifier.of("1.3.6.1.4.1.42.2.11.2.1"); // Domain component OID from RFC 1274, RFC 2247, RFC 5280. // - // OID for "DC=" domain component attributes, used with DNSNames in DN + // OID for "DC=" domain component attributes.used with DNSNames in DN // format. public static final ObjectIdentifier DOMAIN_COMPONENT_OID = - ObjectIdentifier.newInternal(DOMAIN_COMPONENT_DATA); + ObjectIdentifier.of("0.9.2342.19200300.100.1.25"); // OID for "UID=" denoting a user id, defined in RFCs 1274 & 2798. public static final ObjectIdentifier userid_oid = - ObjectIdentifier.newInternal(userid_data); + ObjectIdentifier.of("0.9.2342.19200300.100.1.1"); /** * Return constraint type:
      \n" + "\n"); checkOutput("type-search-index.js", true, - "{\"l\":\"All Classes\",\"url\":\"allclasses-index.html\"}"); + "{\"l\":\"All Classes\",\"u\":\"allclasses-index.html\"}"); checkOutput("package-search-index.js", true, - "{\"l\":\"All Packages\",\"url\":\"allpackages-index.html\"}"); + "{\"l\":\"All Packages\",\"u\":\"allpackages-index.html\"}"); checkOutput("index-all.html", true, "
      All Classes" + "|" diff --git a/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java b/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java index ece88253e58..25505a62f71 100644 --- a/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8017191 8182765 8200432 + * @bug 8017191 8182765 8200432 8239804 * @summary Javadoc is confused by at-link to imported classes outside of the set of generated packages * @library ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -49,8 +49,8 @@ public class TestSeeTag extends JavadocTester { checkOutput("pkg/Test.html", true, "List", - "
      \n" - + "
      See Also:
      \n" + "
      \n" + + "
      See Also:
      \n" + "
      Test.InnerOne.foo(), \n" + "Test.InnerOne.bar(Object), \n" + "Javadoc, \n" @@ -75,8 +75,8 @@ public class TestSeeTag extends JavadocTester { checkExit(Exit.ERROR); checkOutput("badref/Test.html", true, - "
      \n" - + "
      See Also:
      \n" + "
      \n" + + "
      See Also:
      \n" + "
      Object, \n" + "Foo
      \n" + "
      "); diff --git a/test/langtools/jdk/javadoc/doclet/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java b/test/langtools/jdk/javadoc/doclet/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java index c5aba41fccc..8b3d1d8e0e7 100644 --- a/test/langtools/jdk/javadoc/doclet/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java +++ b/test/langtools/jdk/javadoc/doclet/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,11 +91,11 @@ public class TestSerializedFormDeprecationInfo extends JavadocTester { // display the inline comments, tags and deprecation information if any. void checkCommentDeprecated(boolean expectFound) { checkOutput("serialized-form.html", expectFound, - "
      \n" - + "
      Throws:
      \n" + "
      \n" + + "
      Throws:
      \n" + "
      " + "java.io.IOException - on error
      \n" - + "
      See Also:" + + "
      See Also:" + "
      \n" + "
      " + "C1.setUndecorated(boolean)
      \n" @@ -108,10 +108,10 @@ public class TestSerializedFormDeprecationInfo extends JavadocTester { + "
      This field indicates whether the C1 " + "is undecorated.
      \n" + " \n" - + "
      \n" - + "
      Since:
      \n" + + "
      \n" + + "
      Since:
      \n" + "
      1.4
      \n" - + "
      See Also:" + + "
      See Also:" + "
      \n" + "
      " + "C1.setUndecorated(boolean)
      \n" @@ -122,8 +122,8 @@ public class TestSerializedFormDeprecationInfo extends JavadocTester { + "setUndecorated(boolean).\n" + "\n" + "
      Reads the object stream.
      \n" - + "
      \n" - + "
      Throws:
      \n" + + "
      \n" + + "
      Throws:
      \n" + "
      java.io.IOException - on error
      \n" + "
      ", "Deprecated." diff --git a/test/langtools/jdk/javadoc/doclet/testSimpleTag/TestSimpleTag.java b/test/langtools/jdk/javadoc/doclet/testSimpleTag/TestSimpleTag.java index 6ba7f273c7b..58dc010c845 100644 --- a/test/langtools/jdk/javadoc/doclet/testSimpleTag/TestSimpleTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSimpleTag/TestSimpleTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4695326 4750173 4920381 8078320 8071982 + * @bug 4695326 4750173 4920381 8078320 8071982 8239804 * @summary Test the declaration of simple tags using -tag. Verify that * "-tag name" is a shortcut for "-tag name:a:Name:". Also verity that * you can escape the ":" character with a back slash so that it is not @@ -56,11 +56,12 @@ public class TestSimpleTag extends JavadocTester { checkExit(Exit.OK); checkOutput("C.html", true, - "Todo:", - "EJB Beans:", - "Regular Tag:", - "Tag-With-Hyphens:", - "
      Parameters:
      \n" + "
      ", + "
      Todo:
      ", + "
      EJB Beans:
      ", + "
      Regular Tag:
      ", + "
      Tag-With-Hyphens:
      ", + "
      Parameters:
      \n" + "
      arg - this is an int argument.
      "); } } diff --git a/test/langtools/jdk/javadoc/doclet/testSimpleTagInherit/TestSimpleTagInherit.java b/test/langtools/jdk/javadoc/doclet/testSimpleTagInherit/TestSimpleTagInherit.java index 14976105230..8e13a17d638 100644 --- a/test/langtools/jdk/javadoc/doclet/testSimpleTagInherit/TestSimpleTagInherit.java +++ b/test/langtools/jdk/javadoc/doclet/testSimpleTagInherit/TestSimpleTagInherit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,9 +59,9 @@ public class TestSimpleTagInherit extends JavadocTester { checkExit(Exit.OK); checkOutput("p/TestClass.html", true, - "
      Custom:
      \n" + "
      Custom:
      \n" + "
      doc for BaseClass class
      ", - "
      Custom:
      \n" + "
      Custom:
      \n" + "
      doc for BaseClass method
      "); } } diff --git a/test/langtools/jdk/javadoc/doclet/testSinceTag/TestSinceTag.java b/test/langtools/jdk/javadoc/doclet/testSinceTag/TestSinceTag.java index 6b8cdf66435..f41a067f664 100644 --- a/test/langtools/jdk/javadoc/doclet/testSinceTag/TestSinceTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSinceTag/TestSinceTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 7180906 8026567 + * @bug 7180906 8026567 8239804 * @summary Test to make sure that the since tag works correctly * @library ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -64,13 +64,13 @@ public class TestSinceTag extends JavadocTester { void checkSince(boolean on) { checkOutput("pkg1/C1.html", on, - "
      \n" - + "
      Since:
      \n" + "
      \n" + + "
      Since:
      \n" + "
      JDK1.0
      "); checkOutput("serialized-form.html", on, - "
      \n" - + "
      Since:
      \n" + "
      \n" + + "
      Since:
      \n" + "
      1.4
      "); } } diff --git a/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java b/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java index 16d75d87e26..5ca3db515c0 100644 --- a/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,7 @@ public class TestSummaryTag extends JavadocTester { checkExit(Exit.OK); checkOutput("index-all.html", true, - "
      \n" + "
      \n" + "
      m()" + " - Method in class p1.A
      \n" + "
      \n" diff --git a/test/langtools/jdk/javadoc/doclet/testThrowsHead/TestThrowsHead.java b/test/langtools/jdk/javadoc/doclet/testThrowsHead/TestThrowsHead.java index 7846c2a663e..378f297bd53 100644 --- a/test/langtools/jdk/javadoc/doclet/testThrowsHead/TestThrowsHead.java +++ b/test/langtools/jdk/javadoc/doclet/testThrowsHead/TestThrowsHead.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4530727 8026567 + * @bug 4530727 8026567 8239804 * @summary When an exception is declared in the method signature but * not documented with a throws tag, we generate a link to it in the * throws section. Make sure that the link is below a Throws heading. @@ -49,6 +49,6 @@ public class TestThrowsHead extends JavadocTester { checkExit(Exit.OK); checkOutput("C.html", true, - "
      Throws:"); + "
      Throws:
      "); } } diff --git a/test/langtools/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java b/test/langtools/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java index 7812b609a50..5e640386da8 100644 --- a/test/langtools/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java +++ b/test/langtools/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ public class TestTitleInHref extends JavadocTester { //Test to make sure that the title shows up in an interface link. "", //Test to make sure that the title shows up in cross link shows up - "" + "This is a cross link to class File"); } diff --git a/test/langtools/jdk/javadoc/doclet/testUnnamedPackage/TestUnnamedPackage.java b/test/langtools/jdk/javadoc/doclet/testUnnamedPackage/TestUnnamedPackage.java index 999901e96b5..1d6e06b7b18 100644 --- a/test/langtools/jdk/javadoc/doclet/testUnnamedPackage/TestUnnamedPackage.java +++ b/test/langtools/jdk/javadoc/doclet/testUnnamedPackage/TestUnnamedPackage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -104,10 +104,10 @@ public class TestUnnamedPackage extends JavadocTester { + "
      Description
      "); checkOutput("type-search-index.js", true, - "{\"l\":\"All Classes\",\"url\":\"allclasses-index.html\"}"); + "{\"l\":\"All Classes\",\"u\":\"allclasses-index.html\"}"); checkOutput("package-search-index.js", true, - "{\"l\":\"All Packages\",\"url\":\"allpackages-index.html\"}"); + "{\"l\":\"All Packages\",\"u\":\"allpackages-index.html\"}"); checkOutput("index-all.html", true, "
      All Classes" diff --git a/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueTag.java b/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueTag.java index b54998c70f3..da4cc748e1d 100644 --- a/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueTag.java +++ b/test/langtools/jdk/javadoc/doclet/testValueTag/TestValueTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4764045 8004825 8026567 8191030 8204330 + * @bug 4764045 8004825 8026567 8191030 8204330 8239804 * @summary This test ensures that the value tag works in all * use cases, the tests are explained below. * @library ../../lib @@ -85,7 +85,7 @@ public class TestValueTag extends JavadocTester { checkOutput("pkg1/CustomTagUsage.html", true, // Test @value tag used with custom tag. - "
      Todo:
      \n" + + "
      Todo:
      \n" + "
      the value of this constant is 55.
      "); checkOutput(Output.OUT, true, diff --git a/test/langtools/jdk/javadoc/doclet/testVersionTag/TestVersionTag.java b/test/langtools/jdk/javadoc/doclet/testVersionTag/TestVersionTag.java index 1427f69b339..d7644e2fefb 100644 --- a/test/langtools/jdk/javadoc/doclet/testVersionTag/TestVersionTag.java +++ b/test/langtools/jdk/javadoc/doclet/testVersionTag/TestVersionTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8202947 + * @bug 8202947 8239804 * @summary test the at-version tag, and corresponding option * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -81,8 +81,8 @@ public class TestVersionTag extends JavadocTester { void checkVersion(boolean on) { checkOutput("pkg/Test.html", on, - "
      \n" - + "
      Version:
      \n" + "
      \n" + + "
      Version:
      \n" + "
      1.2.3
      \n" + "
      "); } diff --git a/test/langtools/jdk/javadoc/tool/api/basic/APITest.java b/test/langtools/jdk/javadoc/tool/api/basic/APITest.java index 54ec047c390..71a1b90a132 100644 --- a/test/langtools/jdk/javadoc/tool/api/basic/APITest.java +++ b/test/langtools/jdk/javadoc/tool/api/basic/APITest.java @@ -204,12 +204,6 @@ class APITest { "script-dir/jquery-ui.min.css", "script-dir/jquery-ui.structure.min.css", "script-dir/jquery-ui.structure.css", - "script-dir/jszip/dist/jszip.js", - "script-dir/jszip/dist/jszip.min.js", - "script-dir/jszip-utils/dist/jszip-utils.js", - "script-dir/jszip-utils/dist/jszip-utils.min.js", - "script-dir/jszip-utils/dist/jszip-utils-ie.js", - "script-dir/jszip-utils/dist/jszip-utils-ie.min.js", "script-dir/images/ui-bg_glass_65_dadada_1x400.png", "script-dir/images/ui-icons_454545_256x240.png", "script-dir/images/ui-bg_glass_95_fef1ec_1x400.png", @@ -222,11 +216,9 @@ class APITest { "script-dir/images/ui-icons_222222_256x240.png", "script-dir/images/ui-bg_glass_75_e6e6e6_1x400.png", "member-search-index.js", - "member-search-index.zip", "overview-tree.html", "element-list", "package-search-index.js", - "package-search-index.zip", "pkg/C.html", "pkg/package-summary.html", "pkg/package-tree.html", @@ -236,12 +228,11 @@ class APITest { "search.js", "stylesheet.css", "system-properties.html", - "type-search-index.js", - "type-search-index.zip" + "type-search-index.js" )); protected static Set noIndexFiles = standardExpectFiles.stream() - .filter(s -> !s.startsWith("script-dir") && !s.startsWith("resources") && !s.endsWith("zip") + .filter(s -> !s.startsWith("script-dir") && !s.startsWith("resources") && !s.equals("index-all.html") && !s.equals("search.js") && !s.endsWith("-search-index.js") && !s.equals("allclasses-index.html") && !s.equals("allpackages-index.html") && !s.equals("system-properties.html")) diff --git a/test/langtools/jdk/jshell/ToolSimpleTest.java b/test/langtools/jdk/jshell/ToolSimpleTest.java index 0ef66643180..dc840d1445d 100644 --- a/test/langtools/jdk/jshell/ToolSimpleTest.java +++ b/test/langtools/jdk/jshell/ToolSimpleTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466 8172154 8192979 8191842 8198573 8198801 8210596 8210959 8215099 8199623 8236715 + * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466 8172154 8192979 8191842 8198573 8198801 8210596 8210959 8215099 8199623 8236715 8239536 * @summary Simple jshell tool tests * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main @@ -912,4 +912,20 @@ public class ToolSimpleTest extends ReplToolTesting { "| attempted to use record R which cannot be instantiated or its methods invoked until variable j is declared") ); } + + @Test + public void testImportChange() { + for (String feedback : new String[] {"verbose", "normal"}) { + test( + (a) -> assertCommandOutputContains(a, "/set feedback " + feedback, "| Feedback mode: " + feedback), + (a) -> assertCommand(a, "import java.util.*", ""), + (a) -> assertCommandOutputContains(a, "var v1 = List.of(1);", "v1 ==> [1]"), + (a) -> assertCommandOutputContains(a, "import java.awt.List;", + "| update replaced variable v1 which cannot be referenced until this error is corrected:"), + (a) -> assertCommandOutputContains(a, "var b = java.util.List.of(\"bb\")", + "b ==> [bb]"), + (a) -> assertCommandOutputContains(a, "b", "b ==> [bb]") + ); + } + } } diff --git a/test/langtools/jdk/jshell/VariablesTest.java b/test/langtools/jdk/jshell/VariablesTest.java index 695aca7ce55..16a4903bc26 100644 --- a/test/langtools/jdk/jshell/VariablesTest.java +++ b/test/langtools/jdk/jshell/VariablesTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8144903 8177466 8191842 8211694 8213725 + * @bug 8144903 8177466 8191842 8211694 8213725 8239536 * @summary Tests for EvaluationState.variables * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -466,6 +466,15 @@ public class VariablesTest extends KullaTesting { assertVarDisplayName("var v6 = new Runnable() { public void run() { } };", ""); } + public void varType() { + assertEval("import java.util.*;"); + var firstVar = varKey(assertEval("var v1 = List.of(1);", added(VALID))); + assertEval("import list.List;", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), + ste(firstVar, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET)); + assertEval("var v2 = java.util.List.of(1);", added(VALID)); + assertEval("v2", "[1]"); + } + public void varDeclNoInit() { assertVarDeclNoInit("byte", "b", "0"); assertVarDeclNoInit("short", "h", "0"); @@ -579,6 +588,10 @@ public class VariablesTest extends KullaTesting { "\n" + "public interface J {\n" + " public List get();\n" + + "}\n", + "package list;\n" + + "\n" + + "public class List {\n" + "}\n"); String tpath = compiler.getPath(path).toString(); setUp(b -> b diff --git a/test/langtools/tools/javac/diags/examples/RedundantTypesWithWildcardProc/processors/AnnoProc.java b/test/langtools/tools/javac/diags/examples/RedundantTypesWithWildcardProc/processors/AnnoProc.java index a9206cac4cc..fe636f47230 100644 --- a/test/langtools/tools/javac/diags/examples/RedundantTypesWithWildcardProc/processors/AnnoProc.java +++ b/test/langtools/tools/javac/diags/examples/RedundantTypesWithWildcardProc/processors/AnnoProc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ import javax.annotation.processing.*; import javax.lang.model.*; import javax.lang.model.element.*; -@SupportedAnnotationTypes({"java.lang.SuppressWarnings", "*"}) +@SupportedAnnotationTypes({"java.base/java.lang.SuppressWarnings", "*"}) public class AnnoProc extends AbstractProcessor { public boolean process(Set elems, RoundEnvironment renv) { return true; diff --git a/test/langtools/tools/javac/records/RecordCompilationTests.java b/test/langtools/tools/javac/records/RecordCompilationTests.java index 360f181d413..758f1266ac6 100644 --- a/test/langtools/tools/javac/records/RecordCompilationTests.java +++ b/test/langtools/tools/javac/records/RecordCompilationTests.java @@ -309,16 +309,26 @@ public class RecordCompilationTests extends CompilationTestCase { "record R(List list) { # }", "R(List list) { this.list = list; }"); - // ctor should not add checked exceptions + // canonical ctor should not throw checked exceptions assertFail("compiler.err.invalid.canonical.constructor.in.record", "record R() { # }", "public R() throws Exception { }"); - // not even checked exceptions + // same for compact + assertFail("compiler.err.invalid.canonical.constructor.in.record", + "record R() { # }", + "public R throws Exception { }"); + + // not even unchecked exceptions assertFail("compiler.err.invalid.canonical.constructor.in.record", "record R() { # }", "public R() throws IllegalArgumentException { }"); + // ditto + assertFail("compiler.err.invalid.canonical.constructor.in.record", + "record R() { # }", + "public R throws IllegalArgumentException { }"); + // If types match, names must match assertFail("compiler.err.invalid.canonical.constructor.in.record", "record R(int x, int y) { public R(int y, int x) { this.x = this.y = 0; }}"); diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java index 4327f1bc2bb..d29ac66dea3 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -24,10 +24,12 @@ package jdk.test.lib; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; import java.security.AccessController; import java.security.PrivilegedAction; @@ -231,6 +233,59 @@ public class Platform { return true; } + /** + * Return true if the test JDK is signed, otherwise false. Only valid on OSX. + */ + public static boolean isSignedOSX() throws IOException { + // We only care about signed binaries for 10.14 and later (actually 10.14.5, but + // for simplicity we'll also include earlier 10.14 versions). + if (getOsVersionMajor() == 10 && getOsVersionMinor() < 14) { + return false; // assume not signed + } + + // Find the path to the java binary. + String jdkPath = System.getProperty("java.home"); + Path javaPath = Paths.get(jdkPath + "/bin/java"); + String javaFileName = javaPath.toAbsolutePath().toString(); + if (!javaPath.toFile().exists()) { + throw new FileNotFoundException("Could not find file " + javaFileName); + } + + // Run codesign on the java binary. + ProcessBuilder pb = new ProcessBuilder("codesign", "-d", "-v", javaFileName); + pb.redirectError(ProcessBuilder.Redirect.DISCARD); + pb.redirectOutput(ProcessBuilder.Redirect.DISCARD); + Process codesignProcess = pb.start(); + try { + if (codesignProcess.waitFor(10, TimeUnit.SECONDS) == false) { + System.err.println("Timed out waiting for the codesign process to complete. Assuming not signed."); + codesignProcess.destroyForcibly(); + return false; // assume not signed + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + // Check codesign result to see if java binary is signed. Here are the + // exit code meanings: + // 0: signed + // 1: not signed + // 2: invalid arguments + // 3: only has meaning with the -R argument. + // So we should always get 0 or 1 as an exit value. + if (codesignProcess.exitValue() == 0) { + System.out.println("Target JDK is signed. Some tests may be skipped."); + return true; // signed + } else if (codesignProcess.exitValue() == 1) { + System.out.println("Target JDK is not signed."); + return false; // not signed + } else { + System.err.println("Executing codesign failed. Assuming unsigned: " + + codesignProcess.exitValue()); + return false; // not signed + } + } + /** * Return a boolean for whether we expect to be able to attach * the SA to our own processes on this system. This requires @@ -241,7 +296,7 @@ public class Platform { if (isLinux()) { return canPtraceAttachLinux(); } else if (isOSX()) { - return canAttachOSX(); + return canAttachOSX() && !isSignedOSX(); } else { // Other platforms expected to work: return true; diff --git a/test/lib/jdk/test/lib/apps/LingeredApp.java b/test/lib/jdk/test/lib/apps/LingeredApp.java index 0a0e283d387..2ad08bfd769 100644 --- a/test/lib/jdk/test/lib/apps/LingeredApp.java +++ b/test/lib/jdk/test/lib/apps/LingeredApp.java @@ -357,13 +357,15 @@ public class LingeredApp { } private void finishApp() { - OutputBuffer output = getOutput(); - String msg = - " LingeredApp stdout: [" + output.getStdout() + "];\n" + - " LingeredApp stderr: [" + output.getStderr() + "]\n" + - " LingeredApp exitValue = " + appProcess.exitValue(); + if (appProcess != null) { + OutputBuffer output = getOutput(); + String msg = + " LingeredApp stdout: [" + output.getStdout() + "];\n" + + " LingeredApp stderr: [" + output.getStderr() + "]\n" + + " LingeredApp exitValue = " + appProcess.exitValue(); - System.err.println(msg); + System.err.println(msg); + } } /** @@ -377,12 +379,14 @@ public class LingeredApp { // an exception before the LA actually starts if (appProcess != null) { waitAppTerminate(); + + finishApp(); + int exitcode = appProcess.exitValue(); if (exitcode != 0) { throw new IOException("LingeredApp terminated with non-zero exit code " + exitcode); } } - finishApp(); } /** diff --git a/test/lib/jdk/test/lib/artifacts/DefaultArtifactManager.java b/test/lib/jdk/test/lib/artifacts/DefaultArtifactManager.java index e739b31efd0..db570599239 100644 --- a/test/lib/jdk/test/lib/artifacts/DefaultArtifactManager.java +++ b/test/lib/jdk/test/lib/artifacts/DefaultArtifactManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,23 +23,23 @@ package jdk.test.lib.artifacts; -import java.io.FileNotFoundException; import java.nio.file.Path; import java.nio.file.Paths; public class DefaultArtifactManager implements ArtifactManager { @Override public Path resolve(Artifact artifact) throws ArtifactResolverException { - String name = artifact.name(); + return resolve(artifact.name()); + } + + public Path resolve(String name) throws ArtifactResolverException { String location = System.getProperty(artifactProperty(name)); if (location == null) { - throw new ArtifactResolverException("Couldn't automatically resolve dependency for " + name - + " , revision " + artifact.revision() + "\n" + + throw new ArtifactResolverException("Couldn't automatically resolve dependency for " + name + "\n" + "Please specify the location using " + artifactProperty(name)); } return Paths.get(location); } - private static String artifactProperty(String name) { return "jdk.test.lib.artifacts." + name; } diff --git a/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java b/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java index 0f08e087807..a66be9b4826 100644 --- a/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java +++ b/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java @@ -88,16 +88,16 @@ public class JibArtifactManager implements ArtifactManager { } } - private Path download(String jibVersion, HashMap artifactDescription) throws Exception { + private Path download(String jibVersion, Map artifactDescription) throws Exception { return invokeInstallerMethod("download", jibVersion, artifactDescription); } - private Path install(String jibVersion, HashMap artifactDescription) throws Exception { + private Path install(String jibVersion, Map artifactDescription) throws Exception { return invokeInstallerMethod("install", jibVersion, artifactDescription); } private Path invokeInstallerMethod(String methodName, String jibVersion, - HashMap artifactDescription) throws Exception { + Map artifactDescription) throws Exception { // Temporarily replace the context classLoader Thread currentThread = Thread.currentThread(); ClassLoader oldContextLoader = currentThread.getContextClassLoader(); @@ -113,29 +113,33 @@ public class JibArtifactManager implements ArtifactManager { @Override public Path resolve(Artifact artifact) throws ArtifactResolverException { + HashMap artifactDescription = new HashMap<>(); + artifactDescription.put("module", artifact.name()); + artifactDescription.put("organization", artifact.organization()); + artifactDescription.put("ext", artifact.extension()); + artifactDescription.put("revision", artifact.revision()); + if (artifact.classifier().length() > 0) { + artifactDescription.put("classifier", artifact.classifier()); + } + return resolve(artifact.name(), artifactDescription, artifact.unpack()); + } + + public Path resolve(String name, Map artifactDescription, boolean unpack) + throws ArtifactResolverException { Path path; // Use the DefaultArtifactManager to enable users to override locations try { - ArtifactManager manager = new DefaultArtifactManager(); - path = manager.resolve(artifact); + DefaultArtifactManager manager = new DefaultArtifactManager(); + path = manager.resolve(name); } catch (ArtifactResolverException e) { // Location hasn't been overridden, continue to automatically try to resolve the dependency try { - HashMap artifactDescription = new HashMap<>(); - artifactDescription.put("module", artifact.name()); - artifactDescription.put("organization", artifact.organization()); - artifactDescription.put("ext", artifact.extension()); - artifactDescription.put("revision", artifact.revision()); - if (artifact.classifier().length() > 0) { - artifactDescription.put("classifier", artifact.classifier()); - } - path = download(jibVersion, artifactDescription); - if (artifact.unpack()) { + if (unpack) { path = install(jibVersion, artifactDescription); } } catch (Exception e2) { - throw new ArtifactResolverException("Failed to resolve the artifact " + artifact, e2); + throw new ArtifactResolverException("Failed to resolve the artifact " + name, e2); } } return path; diff --git a/test/lib/jdk/test/lib/cds/CDSTestUtils.java b/test/lib/jdk/test/lib/cds/CDSTestUtils.java index 2db3438a002..7968071ec53 100644 --- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java +++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java @@ -40,8 +40,6 @@ public class CDSTestUtils { "UseSharedSpaces: Unable to allocate region, range is not within java heap."; public static final String MSG_RANGE_ALREADT_IN_USE = "Unable to allocate region, java heap range is already in use."; - public static final String MSG_COMPRESSION_MUST_BE_USED = - "Unable to use shared archive: UseCompressedOops and UseCompressedClassPointers must be on for UseSharedSpaces."; public static final boolean DYNAMIC_DUMP = Boolean.getBoolean("test.dynamic.cds.archive"); diff --git a/test/lib/jdk/test/lib/containers/cgroup/CPUSetsReader.java b/test/lib/jdk/test/lib/containers/cgroup/CPUSetsReader.java index 5e0f6f0b686..c4e6e628236 100644 --- a/test/lib/jdk/test/lib/containers/cgroup/CPUSetsReader.java +++ b/test/lib/jdk/test/lib/containers/cgroup/CPUSetsReader.java @@ -32,6 +32,7 @@ import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; + import jdk.test.lib.Asserts; @@ -54,8 +55,7 @@ public class CPUSetsReader { public static int getNumCpus() { String path = "/proc/cpuinfo"; - try { - Stream stream = Files.lines(Paths.get(path)); + try (Stream stream = Files.lines(Paths.get(path))) { return (int) stream.filter(line -> line.startsWith("processor")).count(); } catch (IOException e) { return 0; diff --git a/test/lib/jdk/test/lib/containers/cgroup/CgroupMetricsTester.java b/test/lib/jdk/test/lib/containers/cgroup/CgroupMetricsTester.java new file mode 100644 index 00000000000..85e67628c6e --- /dev/null +++ b/test/lib/jdk/test/lib/containers/cgroup/CgroupMetricsTester.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2020, Red Hat Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.containers.cgroup; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +interface CgroupMetricsTester { + + public static final double ERROR_MARGIN = 0.25; + public static final String EMPTY_STR = ""; + + public void testMemorySubsystem(); + public void testCpuAccounting(); + public void testCpuSchedulingMetrics(); + public void testCpuSets(); + public void testCpuConsumption() throws IOException, InterruptedException; + public void testMemoryUsage() throws Exception; + public void testMisc(); + + public static long convertStringToLong(String strval, long overflowRetval) { + long retval = 0; + if (strval == null) return 0L; + + try { + retval = Long.parseLong(strval); + } catch (NumberFormatException e) { + // For some properties (e.g. memory.limit_in_bytes) we may overflow the range of signed long. + // In this case, return Long.MAX_VALUE + BigInteger b = new BigInteger(strval); + if (b.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { + return overflowRetval; + } + } + return retval; + } + + public static boolean compareWithErrorMargin(long oldVal, long newVal) { + return Math.abs(oldVal - newVal) <= Math.abs(oldVal * ERROR_MARGIN); + } + + public static boolean compareWithErrorMargin(double oldVal, double newVal) { + return Math.abs(oldVal - newVal) <= Math.abs(oldVal * ERROR_MARGIN); + } + + public static void fail(String controller, String metric, long oldVal, long testVal) { + throw new RuntimeException("Test failed for - " + controller + ":" + + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); + } + + public static void fail(String controller, String metric, String oldVal, String testVal) { + throw new RuntimeException("Test failed for - " + controller + ":" + + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); + } + + public static void fail(String controller, String metric, double oldVal, double testVal) { + throw new RuntimeException("Test failed for - " + controller + ":" + + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); + } + + public static void fail(String controller, String metric, boolean oldVal, boolean testVal) { + throw new RuntimeException("Test failed for - " + controller + ":" + + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); + } + + public static void warn(String controller, String metric, long oldVal, long testVal) { + System.err.println("Warning - " + controller + ":" + metric + + ", expected [" + oldVal + "], got [" + testVal + "]"); + } + + public static Integer[] convertCpuSetsToArray(String cpusstr) { + if (cpusstr == null || EMPTY_STR.equals(cpusstr)) { + return new Integer[0]; + } + // Parse range string in the format 1,2-6,7 + Integer[] cpuSets = Stream.of(cpusstr.split(",")).flatMap(a -> { + if (a.contains("-")) { + String[] range = a.split("-"); + return IntStream.rangeClosed(Integer.parseInt(range[0]), + Integer.parseInt(range[1])).boxed(); + } else { + return Stream.of(Integer.parseInt(a)); + } + }).toArray(Integer[]::new); + return cpuSets; + } + +} diff --git a/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java b/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java index 5450a551d87..168f5bb29c6 100644 --- a/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java +++ b/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,609 +21,58 @@ * questions. */ + package jdk.test.lib.containers.cgroup; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.math.BigInteger; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Scanner; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.LongStream; -import java.util.stream.Stream; +import java.util.Objects; + import jdk.internal.platform.Metrics; +/** + * Cgroup version agnostic metrics tester + * + */ public class MetricsTester { - private static final double ERROR_MARGIN = 0.1; - private static long unlimited_minimum = 0x7FFFFFFFFF000000L; - long startSysVal; - long startUserVal; - long startUsage; - long startPerCpu[]; + private static final String CGROUP_V1 = "cgroupv1"; + private static final String CGROUP_V2 = "cgroupv2"; - enum SubSystem { - MEMORY("memory"), - CPUSET("cpuset"), - CPU("cpu"), - CPUACCT("cpuacct"), - BLKIO("blkio"); - - private String value; - - SubSystem(String value) { - this.value = value; - } - - public String value() { - return value; + private static CgroupMetricsTester createInstance(Metrics m) { + Objects.requireNonNull(m); + if (CGROUP_V1.equals(m.getProvider())) { + MetricsTesterCgroupV1 t = new MetricsTesterCgroupV1(); + t.setup(); + return t; + } else if (CGROUP_V2.equals(m.getProvider())) { + return new MetricsTesterCgroupV2(); + } else { + System.err.println("WARNING: Metrics provider, '" + m.getProvider() + + "' is unknown!"); + return null; } } - private static final Set allowedSubSystems = - Stream.of(SubSystem.values()).map(SubSystem::value).collect(Collectors.toSet()); - - private static final Map subSystemPaths = new HashMap<>(); - - private static void setPath(String[] line) { - String cgroupPath = line[2]; - String[] subSystems = line[1].split(","); - - for (String subSystem : subSystems) { - if (allowedSubSystems.contains(subSystem)) { - String[] paths = subSystemPaths.get(subSystem); - String finalPath = ""; - String root = paths[0]; - String mountPoint = paths[1]; - if (root != null && cgroupPath != null) { - if (root.equals("/")) { - if (!cgroupPath.equals("/")) { - finalPath = mountPoint + cgroupPath; - } else { - finalPath = mountPoint; - } - } else { - if (root.equals(cgroupPath)) { - finalPath = mountPoint; - } else { - if (cgroupPath.startsWith(root)) { - if (cgroupPath.length() > root.length()) { - String cgroupSubstr = cgroupPath.substring(root.length()); - finalPath = mountPoint + cgroupSubstr; - } - } - } - } - } - subSystemPaths.put(subSystem, new String[]{finalPath, mountPoint}); - } - } - } - - private static void createSubsystems(String[] line) { - if (line.length < 5) return; - Path p = Paths.get(line[4]); - String subsystemName = p.getFileName().toString(); - if (subsystemName != null) { - for (String subSystem : subsystemName.split(",")) { - if (allowedSubSystems.contains(subSystem)) { - subSystemPaths.put(subSystem, new String[]{line[3], line[4]}); - } - } - } - } - - public void setup() { - Metrics metrics = Metrics.systemMetrics(); - // Initialize CPU usage metrics before we do any testing. - startSysVal = metrics.getCpuSystemUsage(); - startUserVal = metrics.getCpuUserUsage(); - startUsage = metrics.getCpuUsage(); - startPerCpu = metrics.getPerCpuUsage(); - - try { - Stream lines = Files.lines(Paths.get("/proc/self/mountinfo")); - lines.filter(line -> line.contains(" - cgroup cgroup ")) - .map(line -> line.split(" ")) - .forEach(MetricsTester::createSubsystems); - lines.close(); - - lines = Files.lines(Paths.get("/proc/self/cgroup")); - lines.map(line -> line.split(":")) - .filter(line -> (line.length >= 3)) - .forEach(MetricsTester::setPath); - lines.close(); - } catch (IOException e) { - } - } - - private static String getFileContents(SubSystem subSystem, String fileName) { - String fname = subSystemPaths.get(subSystem.value())[0] + File.separator + fileName; - try { - return new Scanner(new File(fname)).useDelimiter("\\Z").next(); - } catch (FileNotFoundException e) { - System.err.println("Unable to open : " + fname); - return ""; - } - } - - private static long getLongValueFromFile(SubSystem subSystem, String fileName) { - String data = getFileContents(subSystem, fileName); - return data.isEmpty() ? 0L : convertStringToLong(data); - } - - private static long convertStringToLong(String strval) { - long retval = 0; - if (strval == null) return 0L; - - try { - retval = Long.parseLong(strval); - } catch (NumberFormatException e) { - // For some properties (e.g. memory.limit_in_bytes) we may overflow the range of signed long. - // In this case, return Long.MAX_VALUE - BigInteger b = new BigInteger(strval); - if (b.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { - return Long.MAX_VALUE; - } - } - return retval; - } - - private static long getLongValueFromFile(SubSystem subSystem, String metric, String subMetric) { - String stats = getFileContents(subSystem, metric); - String[] tokens = stats.split("[\\r\\n]+"); - for (int i = 0; i < tokens.length; i++) { - if (tokens[i].startsWith(subMetric)) { - String strval = tokens[i].split("\\s+")[1]; - return convertStringToLong(strval); - } - } - return 0L; - } - - private static double getDoubleValueFromFile(SubSystem subSystem, String fileName) { - String data = getFileContents(subSystem, fileName); - return data.isEmpty() ? 0.0 : Double.parseDouble(data); - } - - private boolean compareWithErrorMargin(long oldVal, long newVal) { - return Math.abs(oldVal - newVal) <= Math.abs(oldVal * ERROR_MARGIN); - } - - private boolean compareWithErrorMargin(double oldVal, double newVal) { - return Math.abs(oldVal - newVal) <= Math.abs(oldVal * ERROR_MARGIN); - } - - private static void fail(SubSystem system, String metric, long oldVal, long testVal) { - throw new RuntimeException("Test failed for - " + system.value + ":" - + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); - } - - private static void fail(SubSystem system, String metric, String oldVal, String testVal) { - throw new RuntimeException("Test failed for - " + system.value + ":" - + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); - } - - private static void fail(SubSystem system, String metric, double oldVal, double testVal) { - throw new RuntimeException("Test failed for - " + system.value + ":" - + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); - } - - private static void fail(SubSystem system, String metric, boolean oldVal, boolean testVal) { - throw new RuntimeException("Test failed for - " + system.value + ":" - + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); - } - - private static void warn(SubSystem system, String metric, long oldVal, long testVal) { - System.err.println("Warning - " + system.value + ":" + metric - + ", expected [" + oldVal + "], got [" + testVal + "]"); - } - - public void testMemorySubsystem() { - Metrics metrics = Metrics.systemMetrics(); - - // User Memory - long oldVal = metrics.getMemoryFailCount(); - long newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.failcnt"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.failcnt", oldVal, newVal); - } - - oldVal = metrics.getMemoryLimit(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.limit_in_bytes"); - newVal = newVal > unlimited_minimum ? -1L : newVal; - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.limit_in_bytes", oldVal, newVal); - } - - oldVal = metrics.getMemoryMaxUsage(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.max_usage_in_bytes"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.max_usage_in_bytes", oldVal, newVal); - } - - oldVal = metrics.getMemoryUsage(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.usage_in_bytes"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.usage_in_bytes", oldVal, newVal); - } - - // Kernel memory - oldVal = metrics.getKernelMemoryFailCount(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.failcnt"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.kmem.failcnt", oldVal, newVal); - } - - oldVal = metrics.getKernelMemoryLimit(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.limit_in_bytes"); - newVal = newVal > unlimited_minimum ? -1L : newVal; - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.kmem.limit_in_bytes", oldVal, newVal); - } - - oldVal = metrics.getKernelMemoryMaxUsage(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.max_usage_in_bytes"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.kmem.max_usage_in_bytes", oldVal, newVal); - } - - oldVal = metrics.getKernelMemoryUsage(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.usage_in_bytes"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.kmem.usage_in_bytes", oldVal, newVal); - } - - //TCP Memory - oldVal = metrics.getTcpMemoryFailCount(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.tcp.failcnt"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.kmem.tcp.failcnt", oldVal, newVal); - } - - oldVal = metrics.getTcpMemoryLimit(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.tcp.limit_in_bytes"); - newVal = newVal > unlimited_minimum ? -1L : newVal; - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.kmem.tcp.limit_in_bytes", oldVal, newVal); - } - - oldVal = metrics.getTcpMemoryMaxUsage(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.tcp.max_usage_in_bytes"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.kmem.tcp.max_usage_in_bytes", oldVal, newVal); - } - - oldVal = metrics.getTcpMemoryUsage(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.tcp.usage_in_bytes"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.kmem.tcp.usage_in_bytes", oldVal, newVal); - } - - // Memory and Swap - oldVal = metrics.getMemoryAndSwapFailCount(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.failcnt"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.memsw.failcnt", oldVal, newVal); - } - - oldVal = metrics.getMemoryAndSwapLimit(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.limit_in_bytes"); - newVal = newVal > unlimited_minimum ? -1L : newVal; - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.memsw.limit_in_bytes", oldVal, newVal); - } - - oldVal = metrics.getMemoryAndSwapMaxUsage(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.max_usage_in_bytes"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.memsw.max_usage_in_bytes", oldVal, newVal); - } - - oldVal = metrics.getMemoryAndSwapUsage(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.usage_in_bytes"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.memsw.usage_in_bytes", oldVal, newVal); - } - - oldVal = metrics.getMemorySoftLimit(); - newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.soft_limit_in_bytes"); - newVal = newVal > unlimited_minimum ? -1L : newVal; - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.MEMORY, "memory.soft_limit_in_bytes", oldVal, newVal); - } - - boolean oomKillEnabled = metrics.isMemoryOOMKillEnabled(); - boolean newOomKillEnabled = getLongValueFromFile(SubSystem.MEMORY, - "memory.oom_control", "oom_kill_disable") == 0L ? true : false; - if (oomKillEnabled != newOomKillEnabled) { - throw new RuntimeException("Test failed for - " + SubSystem.MEMORY.value + ":" - + "memory.oom_control:oom_kill_disable" + ", expected [" - + oomKillEnabled + "], got [" + newOomKillEnabled + "]"); - } - } - - public void testCpuAccounting() { - Metrics metrics = Metrics.systemMetrics(); - long oldVal = metrics.getCpuUsage(); - long newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpuacct.usage"); - - if (!compareWithErrorMargin(oldVal, newVal)) { - warn(SubSystem.CPUACCT, "cpuacct.usage", oldVal, newVal); - } - - Long[] newVals = Stream.of(getFileContents(SubSystem.CPUACCT, "cpuacct.usage_percpu") - .split("\\s+")) - .map(Long::parseLong) - .toArray(Long[]::new); - Long[] oldVals = LongStream.of(metrics.getPerCpuUsage()).boxed().toArray(Long[]::new); - for (int i = 0; i < oldVals.length; i++) { - if (!compareWithErrorMargin(oldVals[i], newVals[i])) { - warn(SubSystem.CPUACCT, "cpuacct.usage_percpu", oldVals[i], newVals[i]); - } - } - - oldVal = metrics.getCpuUserUsage(); - newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpuacct.stat", "user"); - if (!compareWithErrorMargin(oldVal, newVal)) { - warn(SubSystem.CPUACCT, "cpuacct.usage - user", oldVal, newVal); - } - - oldVal = metrics.getCpuSystemUsage(); - newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpuacct.stat", "system"); - if (!compareWithErrorMargin(oldVal, newVal)) { - warn(SubSystem.CPUACCT, "cpuacct.usage - system", oldVal, newVal); - } - } - - public void testCpuSchedulingMetrics() { - Metrics metrics = Metrics.systemMetrics(); - long oldVal = metrics.getCpuPeriod(); - long newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.cfs_period_us"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.CPUACCT, "cpu.cfs_period_us", oldVal, newVal); - } - - oldVal = metrics.getCpuQuota(); - newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.cfs_quota_us"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.CPUACCT, "cpu.cfs_quota_us", oldVal, newVal); - } - - oldVal = metrics.getCpuShares(); - newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.shares"); - if (newVal == 0 || newVal == 1024) newVal = -1; - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.CPUACCT, "cpu.shares", oldVal, newVal); - } - - oldVal = metrics.getCpuNumPeriods(); - newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.stat", "nr_periods"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.CPUACCT, "cpu.stat - nr_periods", oldVal, newVal); - } - - oldVal = metrics.getCpuNumThrottled(); - newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.stat", "nr_throttled"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.CPUACCT, "cpu.stat - nr_throttled", oldVal, newVal); - } - - oldVal = metrics.getCpuThrottledTime(); - newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.stat", "throttled_time"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.CPUACCT, "cpu.stat - throttled_time", oldVal, newVal); - } - } - - public void testCpuSets() { - Metrics metrics = Metrics.systemMetrics(); - Integer[] oldVal = Arrays.stream(metrics.getCpuSetCpus()).boxed().toArray(Integer[]::new); - Arrays.sort(oldVal); - - String cpusstr = getFileContents(SubSystem.CPUSET, "cpuset.cpus"); - // Parse range string in the format 1,2-6,7 - Integer[] newVal = Stream.of(cpusstr.split(",")).flatMap(a -> { - if (a.contains("-")) { - String[] range = a.split("-"); - return IntStream.rangeClosed(Integer.parseInt(range[0]), - Integer.parseInt(range[1])).boxed(); - } else { - return Stream.of(Integer.parseInt(a)); - } - }).toArray(Integer[]::new); - Arrays.sort(newVal); - if (Arrays.compare(oldVal, newVal) != 0) { - fail(SubSystem.CPUSET, "cpuset.cpus", Arrays.toString(oldVal), - Arrays.toString(newVal)); - } - - int [] cpuSets = metrics.getEffectiveCpuSetCpus(); - - // Skip this test if this metric is supported on this platform - if (cpuSets.length != 0) { - oldVal = Arrays.stream(cpuSets).boxed().toArray(Integer[]::new); - Arrays.sort(oldVal); - cpusstr = getFileContents(SubSystem.CPUSET, "cpuset.effective_cpus"); - newVal = Stream.of(cpusstr.split(",")).flatMap(a -> { - if (a.contains("-")) { - String[] range = a.split("-"); - return IntStream.rangeClosed(Integer.parseInt(range[0]), - Integer.parseInt(range[1])).boxed(); - } else { - return Stream.of(Integer.parseInt(a)); - } - }).toArray(Integer[]::new); - Arrays.sort(newVal); - if (Arrays.compare(oldVal, newVal) != 0) { - fail(SubSystem.CPUSET, "cpuset.effective_cpus", Arrays.toString(oldVal), - Arrays.toString(newVal)); - } - } - - oldVal = Arrays.stream(metrics.getCpuSetMems()).boxed().toArray(Integer[]::new); - Arrays.sort(oldVal); - cpusstr = getFileContents(SubSystem.CPUSET, "cpuset.mems"); - newVal = Stream.of(cpusstr.split(",")).flatMap(a -> { - if (a.contains("-")) { - String[] range = a.split("-"); - return IntStream.rangeClosed(Integer.parseInt(range[0]), - Integer.parseInt(range[1])).boxed(); - } else { - return Stream.of(Integer.parseInt(a)); - } - }).toArray(Integer[]::new); - Arrays.sort(newVal); - if (Arrays.compare(oldVal, newVal) != 0) { - fail(SubSystem.CPUSET, "cpuset.mems", Arrays.toString(oldVal), - Arrays.toString(newVal)); - } - - int [] cpuSetMems = metrics.getEffectiveCpuSetMems(); - - // Skip this test if this metric is supported on this platform - if (cpuSetMems.length != 0) { - oldVal = Arrays.stream(cpuSetMems).boxed().toArray(Integer[]::new); - Arrays.sort(oldVal); - cpusstr = getFileContents(SubSystem.CPUSET, "cpuset.effective_mems"); - newVal = Stream.of(cpusstr.split(",")).flatMap(a -> { - if (a.contains("-")) { - String[] range = a.split("-"); - return IntStream.rangeClosed(Integer.parseInt(range[0]), - Integer.parseInt(range[1])).boxed(); - } else { - return Stream.of(Integer.parseInt(a)); - } - }).toArray(Integer[]::new); - Arrays.sort(newVal); - if (Arrays.compare(oldVal, newVal) != 0) { - fail(SubSystem.CPUSET, "cpuset.effective_mems", Arrays.toString(oldVal), - Arrays.toString(newVal)); - } - } - - double oldValue = metrics.getCpuSetMemoryPressure(); - double newValue = getDoubleValueFromFile(SubSystem.CPUSET, "cpuset.memory_pressure"); - if (!compareWithErrorMargin(oldValue, newValue)) { - fail(SubSystem.CPUSET, "cpuset.memory_pressure", oldValue, newValue); - } - - boolean oldV = metrics.isCpuSetMemoryPressureEnabled(); - boolean newV = getLongValueFromFile(SubSystem.CPUSET, - "cpuset.memory_pressure_enabled") == 1 ? true : false; - if (oldV != newV) { - fail(SubSystem.CPUSET, "cpuset.memory_pressure_enabled", oldV, newV); - } - } - - public void testBlkIO() { - Metrics metrics = Metrics.systemMetrics(); - long oldVal = metrics.getBlkIOServiceCount(); - long newVal = getLongValueFromFile(SubSystem.BLKIO, - "blkio.throttle.io_service_bytes", "Total"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.BLKIO, "blkio.throttle.io_service_bytes - Total", - oldVal, newVal); - } - - oldVal = metrics.getBlkIOServiced(); - newVal = getLongValueFromFile(SubSystem.BLKIO, "blkio.throttle.io_serviced", "Total"); - if (!compareWithErrorMargin(oldVal, newVal)) { - fail(SubSystem.BLKIO, "blkio.throttle.io_serviced - Total", oldVal, newVal); - } - } - - public void testCpuConsumption() throws IOException, InterruptedException { - Metrics metrics = Metrics.systemMetrics(); - // make system call - long newSysVal = metrics.getCpuSystemUsage(); - long newUserVal = metrics.getCpuUserUsage(); - long newUsage = metrics.getCpuUsage(); - long[] newPerCpu = metrics.getPerCpuUsage(); - - // system/user CPU usage counters may be slowly increasing. - // allow for equal values for a pass - if (newSysVal < startSysVal) { - fail(SubSystem.CPU, "getCpuSystemUsage", newSysVal, startSysVal); - } - - // system/user CPU usage counters may be slowly increasing. - // allow for equal values for a pass - if (newUserVal < startUserVal) { - fail(SubSystem.CPU, "getCpuUserUsage", newUserVal, startUserVal); - } - - if (newUsage <= startUsage) { - fail(SubSystem.CPU, "getCpuUsage", newUsage, startUsage); - } - - boolean success = false; - for (int i = 0; i < startPerCpu.length; i++) { - if (newPerCpu[i] > startPerCpu[i]) { - success = true; - break; - } - } - - if(!success) fail(SubSystem.CPU, "getPerCpuUsage", Arrays.toString(newPerCpu), - Arrays.toString(startPerCpu)); - } - - public void testMemoryUsage() throws Exception { - Metrics metrics = Metrics.systemMetrics(); - long memoryMaxUsage = metrics.getMemoryMaxUsage(); - long memoryUsage = metrics.getMemoryUsage(); - long newMemoryMaxUsage = 0, newMemoryUsage = 0; - - // allocate memory in a loop and check more than once for new values - // otherwise we might see seldom the effect of decreasing new memory values - // e.g. because the system could free up memory - byte[][] bytes = new byte[32][]; - for (int i = 0; i < 32; i++) { - bytes[i] = new byte[8*1024*1024]; - newMemoryUsage = metrics.getMemoryUsage(); - if (newMemoryUsage > memoryUsage) { - break; - } - } - newMemoryMaxUsage = metrics.getMemoryMaxUsage(); - - if (newMemoryMaxUsage < memoryMaxUsage) { - fail(SubSystem.MEMORY, "getMemoryMaxUsage", memoryMaxUsage, - newMemoryMaxUsage); - } - - if (newMemoryUsage < memoryUsage) { - fail(SubSystem.MEMORY, "getMemoryUsage", memoryUsage, newMemoryUsage); - } + public void testAll(Metrics m) throws Exception { + CgroupMetricsTester tester = createInstance(m); + tester.testCpuAccounting(); + tester.testCpuConsumption(); + tester.testCpuSchedulingMetrics(); + tester.testCpuSets(); + tester.testMemorySubsystem(); + tester.testMemoryUsage(); + tester.testMisc(); } public static void main(String[] args) throws Exception { + Metrics m = Metrics.systemMetrics(); // If cgroups is not configured, report success - Metrics metrics = Metrics.systemMetrics(); - if (metrics == null) { + if (m == null) { System.out.println("TEST PASSED!!!"); return; } MetricsTester metricsTester = new MetricsTester(); - metricsTester.setup(); - metricsTester.testCpuAccounting(); - metricsTester.testCpuSchedulingMetrics(); - metricsTester.testCpuSets(); - metricsTester.testMemorySubsystem(); - metricsTester.testBlkIO(); - metricsTester.testCpuConsumption(); - metricsTester.testMemoryUsage(); + metricsTester.testAll(m); System.out.println("TEST PASSED!!!"); } } diff --git a/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV1.java b/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV1.java new file mode 100644 index 00000000000..e5fd6282496 --- /dev/null +++ b/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV1.java @@ -0,0 +1,566 @@ +/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.containers.cgroup; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.LongStream; +import java.util.stream.Stream; + +import jdk.internal.platform.Metrics; +import jdk.internal.platform.CgroupV1Metrics; + +public class MetricsTesterCgroupV1 implements CgroupMetricsTester { + + private static long unlimited_minimum = 0x7FFFFFFFFF000000L; + long startSysVal; + long startUserVal; + long startUsage; + long startPerCpu[]; + + enum Controller { + MEMORY("memory"), + CPUSET("cpuset"), + CPU("cpu"), + CPUACCT("cpuacct"), + BLKIO("blkio"); + + private String value; + + Controller(String value) { + this.value = value; + } + + public String value() { + return value; + } + } + + private static final Set allowedSubSystems = + Stream.of(Controller.values()).map(Controller::value).collect(Collectors.toSet()); + + private static final Map subSystemPaths = new HashMap<>(); + + private static void setPath(String[] line) { + String cgroupPath = line[2]; + String[] subSystems = line[1].split(","); + + for (String subSystem : subSystems) { + if (allowedSubSystems.contains(subSystem)) { + String[] paths = subSystemPaths.get(subSystem); + String finalPath = ""; + String root = paths[0]; + String mountPoint = paths[1]; + if (root != null && cgroupPath != null) { + if (root.equals("/")) { + if (!cgroupPath.equals("/")) { + finalPath = mountPoint + cgroupPath; + } else { + finalPath = mountPoint; + } + } else { + if (root.equals(cgroupPath)) { + finalPath = mountPoint; + } else { + if (cgroupPath.startsWith(root)) { + if (cgroupPath.length() > root.length()) { + String cgroupSubstr = cgroupPath.substring(root.length()); + finalPath = mountPoint + cgroupSubstr; + } + } + } + } + } + subSystemPaths.put(subSystem, new String[]{finalPath, mountPoint}); + } + } + } + + private static void createSubsystems(String[] line) { + if (line.length < 5) return; + Path p = Paths.get(line[4]); + String subsystemName = p.getFileName().toString(); + if (subsystemName != null) { + for (String subSystem : subsystemName.split(",")) { + if (allowedSubSystems.contains(subSystem)) { + subSystemPaths.put(subSystem, new String[]{line[3], line[4]}); + } + } + } + } + + public void setup() { + Metrics metrics = Metrics.systemMetrics(); + // Initialize CPU usage metrics before we do any testing. + startSysVal = metrics.getCpuSystemUsage(); + startUserVal = metrics.getCpuUserUsage(); + startUsage = metrics.getCpuUsage(); + startPerCpu = metrics.getPerCpuUsage(); + if (startPerCpu == null) { + startPerCpu = new long[0]; + } + + try { + Stream lines = Files.lines(Paths.get("/proc/self/mountinfo")); + lines.filter(line -> line.contains(" - cgroup cgroup ")) + .map(line -> line.split(" ")) + .forEach(MetricsTesterCgroupV1::createSubsystems); + lines.close(); + + lines = Files.lines(Paths.get("/proc/self/cgroup")); + lines.map(line -> line.split(":")) + .filter(line -> (line.length >= 3)) + .forEach(MetricsTesterCgroupV1::setPath); + lines.close(); + } catch (IOException e) { + } + } + + private static String getFileContents(Controller subSystem, String fileName) { + String fname = subSystemPaths.get(subSystem.value())[0] + File.separator + fileName; + try { + return new Scanner(new File(fname)).useDelimiter("\\Z").next(); + } catch (FileNotFoundException e) { + System.err.println("Unable to open : " + fname); + return null; + } + } + + private static long getLongValueFromFile(Controller subSystem, String fileName) { + String data = getFileContents(subSystem, fileName); + return (data == null || data.isEmpty()) ? 0L : convertStringToLong(data); + } + + private static long convertStringToLong(String strval) { + return CgroupMetricsTester.convertStringToLong(strval, Long.MAX_VALUE); + } + + private static long getLongValueFromFile(Controller subSystem, String metric, String subMetric) { + String stats = getFileContents(subSystem, metric); + String[] tokens = stats.split("[\\r\\n]+"); + for (int i = 0; i < tokens.length; i++) { + if (tokens[i].startsWith(subMetric)) { + String strval = tokens[i].split("\\s+")[1]; + return convertStringToLong(strval); + } + } + return 0L; + } + + private static double getDoubleValueFromFile(Controller subSystem, String fileName) { + String data = getFileContents(subSystem, fileName); + return data.isEmpty() ? 0.0 : Double.parseDouble(data); + } + + private static void fail(Controller system, String metric, long oldVal, long testVal) { + CgroupMetricsTester.fail(system.value, metric, oldVal, testVal); + } + + private static void fail(Controller system, String metric, String oldVal, String testVal) { + CgroupMetricsTester.fail(system.value, metric, oldVal, testVal); + } + + private static void fail(Controller system, String metric, double oldVal, double testVal) { + CgroupMetricsTester.fail(system.value, metric, oldVal, testVal); + } + + private static void fail(Controller system, String metric, boolean oldVal, boolean testVal) { + CgroupMetricsTester.fail(system.value, metric, oldVal, testVal); + } + + private static void warn(Controller system, String metric, long oldVal, long testVal) { + CgroupMetricsTester.warn(system.value, metric, oldVal, testVal); + } + + public void testMemorySubsystem() { + CgroupV1Metrics metrics = (CgroupV1Metrics)Metrics.systemMetrics(); + + // User Memory + long oldVal = metrics.getMemoryFailCount(); + long newVal = getLongValueFromFile(Controller.MEMORY, "memory.failcnt"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.failcnt", oldVal, newVal); + } + + oldVal = metrics.getMemoryLimit(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.limit_in_bytes"); + newVal = newVal > unlimited_minimum ? -1L : newVal; + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.limit_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getMemoryMaxUsage(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.max_usage_in_bytes"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.max_usage_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getMemoryUsage(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.usage_in_bytes"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.usage_in_bytes", oldVal, newVal); + } + + // Kernel memory + oldVal = metrics.getKernelMemoryFailCount(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.kmem.failcnt"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.kmem.failcnt", oldVal, newVal); + } + + oldVal = metrics.getKernelMemoryLimit(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.kmem.limit_in_bytes"); + newVal = newVal > unlimited_minimum ? -1L : newVal; + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.kmem.limit_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getKernelMemoryMaxUsage(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.kmem.max_usage_in_bytes"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.kmem.max_usage_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getKernelMemoryUsage(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.kmem.usage_in_bytes"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.kmem.usage_in_bytes", oldVal, newVal); + } + + //TCP Memory + oldVal = metrics.getTcpMemoryFailCount(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.kmem.tcp.failcnt"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.kmem.tcp.failcnt", oldVal, newVal); + } + + oldVal = metrics.getTcpMemoryLimit(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.kmem.tcp.limit_in_bytes"); + newVal = newVal > unlimited_minimum ? -1L : newVal; + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.kmem.tcp.limit_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getTcpMemoryMaxUsage(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.kmem.tcp.max_usage_in_bytes"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.kmem.tcp.max_usage_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getTcpMemoryUsage(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.kmem.tcp.usage_in_bytes"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.kmem.tcp.usage_in_bytes", oldVal, newVal); + } + + // Memory and Swap + oldVal = metrics.getMemoryAndSwapFailCount(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.failcnt"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.memsw.failcnt", oldVal, newVal); + } + + oldVal = metrics.getMemoryAndSwapLimit(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.limit_in_bytes"); + newVal = newVal > unlimited_minimum ? -1L : newVal; + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.memsw.limit_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getMemoryAndSwapMaxUsage(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.max_usage_in_bytes"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.memsw.max_usage_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getMemoryAndSwapUsage(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.usage_in_bytes"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.memsw.usage_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getMemorySoftLimit(); + newVal = getLongValueFromFile(Controller.MEMORY, "memory.soft_limit_in_bytes"); + newVal = newVal > unlimited_minimum ? -1L : newVal; + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.MEMORY, "memory.soft_limit_in_bytes", oldVal, newVal); + } + + boolean oomKillEnabled = metrics.isMemoryOOMKillEnabled(); + boolean newOomKillEnabled = getLongValueFromFile(Controller.MEMORY, + "memory.oom_control", "oom_kill_disable") == 0L ? true : false; + if (oomKillEnabled != newOomKillEnabled) { + throw new RuntimeException("Test failed for - " + Controller.MEMORY.value + ":" + + "memory.oom_control:oom_kill_disable" + ", expected [" + + oomKillEnabled + "], got [" + newOomKillEnabled + "]"); + } + } + + public void testCpuAccounting() { + CgroupV1Metrics metrics = (CgroupV1Metrics)Metrics.systemMetrics(); + long oldVal = metrics.getCpuUsage(); + long newVal = getLongValueFromFile(Controller.CPUACCT, "cpuacct.usage"); + + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + warn(Controller.CPUACCT, "cpuacct.usage", oldVal, newVal); + } + + String newValsStr = getFileContents(Controller.CPUACCT, "cpuacct.usage_percpu"); + Long[] newVals = new Long[0]; + if (newValsStr != null) { + newVals = Stream.of(newValsStr + .split("\\s+")) + .map(Long::parseLong) + .toArray(Long[]::new); + } + long[] oldValsPrim = metrics.getPerCpuUsage(); + Long[] oldVals = LongStream.of(oldValsPrim == null ? new long[0] : oldValsPrim) + .boxed().toArray(Long[]::new); + for (int i = 0; i < oldVals.length; i++) { + if (!CgroupMetricsTester.compareWithErrorMargin(oldVals[i], newVals[i])) { + warn(Controller.CPUACCT, "cpuacct.usage_percpu", oldVals[i], newVals[i]); + } + } + + oldVal = metrics.getCpuUserUsage(); + newVal = getLongValueFromFile(Controller.CPUACCT, "cpuacct.stat", "user"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + warn(Controller.CPUACCT, "cpuacct.usage - user", oldVal, newVal); + } + + oldVal = metrics.getCpuSystemUsage(); + newVal = getLongValueFromFile(Controller.CPUACCT, "cpuacct.stat", "system"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + warn(Controller.CPUACCT, "cpuacct.usage - system", oldVal, newVal); + } + } + + public void testCpuSchedulingMetrics() { + CgroupV1Metrics metrics = (CgroupV1Metrics)Metrics.systemMetrics(); + long oldVal = metrics.getCpuPeriod(); + long newVal = getLongValueFromFile(Controller.CPUACCT, "cpu.cfs_period_us"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.CPUACCT, "cpu.cfs_period_us", oldVal, newVal); + } + + oldVal = metrics.getCpuQuota(); + newVal = getLongValueFromFile(Controller.CPUACCT, "cpu.cfs_quota_us"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.CPUACCT, "cpu.cfs_quota_us", oldVal, newVal); + } + + oldVal = metrics.getCpuShares(); + newVal = getLongValueFromFile(Controller.CPUACCT, "cpu.shares"); + if (newVal == 0 || newVal == 1024) newVal = -1; + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.CPUACCT, "cpu.shares", oldVal, newVal); + } + + oldVal = metrics.getCpuNumPeriods(); + newVal = getLongValueFromFile(Controller.CPUACCT, "cpu.stat", "nr_periods"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.CPUACCT, "cpu.stat - nr_periods", oldVal, newVal); + } + + oldVal = metrics.getCpuNumThrottled(); + newVal = getLongValueFromFile(Controller.CPUACCT, "cpu.stat", "nr_throttled"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.CPUACCT, "cpu.stat - nr_throttled", oldVal, newVal); + } + + oldVal = metrics.getCpuThrottledTime(); + newVal = getLongValueFromFile(Controller.CPUACCT, "cpu.stat", "throttled_time"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.CPUACCT, "cpu.stat - throttled_time", oldVal, newVal); + } + } + + public void testCpuSets() { + CgroupV1Metrics metrics = (CgroupV1Metrics)Metrics.systemMetrics(); + Integer[] oldVal = Arrays.stream(metrics.getCpuSetCpus()).boxed().toArray(Integer[]::new); + Arrays.sort(oldVal); + + String cpusstr = getFileContents(Controller.CPUSET, "cpuset.cpus"); + // Parse range string in the format 1,2-6,7 + Integer[] newVal = CgroupMetricsTester.convertCpuSetsToArray(cpusstr); + Arrays.sort(newVal); + if (Arrays.compare(oldVal, newVal) != 0) { + fail(Controller.CPUSET, "cpuset.cpus", Arrays.toString(oldVal), + Arrays.toString(newVal)); + } + + int [] cpuSets = metrics.getEffectiveCpuSetCpus(); + + // Skip this test if this metric is not supported on this platform + if (cpuSets.length != 0) { + oldVal = Arrays.stream(cpuSets).boxed().toArray(Integer[]::new); + Arrays.sort(oldVal); + cpusstr = getFileContents(Controller.CPUSET, "cpuset.effective_cpus"); + newVal = CgroupMetricsTester.convertCpuSetsToArray(cpusstr); + Arrays.sort(newVal); + if (Arrays.compare(oldVal, newVal) != 0) { + fail(Controller.CPUSET, "cpuset.effective_cpus", Arrays.toString(oldVal), + Arrays.toString(newVal)); + } + } + + oldVal = Arrays.stream(metrics.getCpuSetMems()).boxed().toArray(Integer[]::new); + Arrays.sort(oldVal); + cpusstr = getFileContents(Controller.CPUSET, "cpuset.mems"); + newVal = CgroupMetricsTester.convertCpuSetsToArray(cpusstr); + Arrays.sort(newVal); + if (Arrays.compare(oldVal, newVal) != 0) { + fail(Controller.CPUSET, "cpuset.mems", Arrays.toString(oldVal), + Arrays.toString(newVal)); + } + + int [] cpuSetMems = metrics.getEffectiveCpuSetMems(); + + // Skip this test if this metric is not supported on this platform + if (cpuSetMems.length != 0) { + oldVal = Arrays.stream(cpuSetMems).boxed().toArray(Integer[]::new); + Arrays.sort(oldVal); + cpusstr = getFileContents(Controller.CPUSET, "cpuset.effective_mems"); + newVal = CgroupMetricsTester.convertCpuSetsToArray(cpusstr); + Arrays.sort(newVal); + if (Arrays.compare(oldVal, newVal) != 0) { + fail(Controller.CPUSET, "cpuset.effective_mems", Arrays.toString(oldVal), + Arrays.toString(newVal)); + } + } + + double oldValue = metrics.getCpuSetMemoryPressure(); + double newValue = getDoubleValueFromFile(Controller.CPUSET, "cpuset.memory_pressure"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldValue, newValue)) { + fail(Controller.CPUSET, "cpuset.memory_pressure", oldValue, newValue); + } + + boolean oldV = metrics.isCpuSetMemoryPressureEnabled(); + boolean newV = getLongValueFromFile(Controller.CPUSET, + "cpuset.memory_pressure_enabled") == 1 ? true : false; + if (oldV != newV) { + fail(Controller.CPUSET, "cpuset.memory_pressure_enabled", oldV, newV); + } + } + + private void testBlkIO() { + CgroupV1Metrics metrics = (CgroupV1Metrics)Metrics.systemMetrics(); + long oldVal = metrics.getBlkIOServiceCount(); + long newVal = getLongValueFromFile(Controller.BLKIO, + "blkio.throttle.io_service_bytes", "Total"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.BLKIO, "blkio.throttle.io_service_bytes - Total", + oldVal, newVal); + } + + oldVal = metrics.getBlkIOServiced(); + newVal = getLongValueFromFile(Controller.BLKIO, "blkio.throttle.io_serviced", "Total"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail(Controller.BLKIO, "blkio.throttle.io_serviced - Total", oldVal, newVal); + } + } + + public void testCpuConsumption() throws IOException, InterruptedException { + CgroupV1Metrics metrics = (CgroupV1Metrics)Metrics.systemMetrics(); + // make system call + long newSysVal = metrics.getCpuSystemUsage(); + long newUserVal = metrics.getCpuUserUsage(); + long newUsage = metrics.getCpuUsage(); + long[] newPerCpu = metrics.getPerCpuUsage(); + if (newPerCpu == null) { + newPerCpu = new long[0]; + } + + // system/user CPU usage counters may be slowly increasing. + // allow for equal values for a pass + if (newSysVal < startSysVal) { + fail(Controller.CPU, "getCpuSystemUsage", newSysVal, startSysVal); + } + + // system/user CPU usage counters may be slowly increasing. + // allow for equal values for a pass + if (newUserVal < startUserVal) { + fail(Controller.CPU, "getCpuUserUsage", newUserVal, startUserVal); + } + + if (newUsage <= startUsage) { + fail(Controller.CPU, "getCpuUsage", newUsage, startUsage); + } + + boolean success = false; + for (int i = 0; i < startPerCpu.length; i++) { + if (newPerCpu[i] > startPerCpu[i]) { + success = true; + break; + } + } + + if(!success) fail(Controller.CPU, "getPerCpuUsage", Arrays.toString(newPerCpu), + Arrays.toString(startPerCpu)); + } + + public void testMemoryUsage() throws Exception { + CgroupV1Metrics metrics = (CgroupV1Metrics)Metrics.systemMetrics(); + long memoryMaxUsage = metrics.getMemoryMaxUsage(); + long memoryUsage = metrics.getMemoryUsage(); + long newMemoryMaxUsage = 0, newMemoryUsage = 0; + + // allocate memory in a loop and check more than once for new values + // otherwise we might see seldom the effect of decreasing new memory values + // e.g. because the system could free up memory + byte[][] bytes = new byte[32][]; + for (int i = 0; i < 32; i++) { + bytes[i] = new byte[8*1024*1024]; + newMemoryUsage = metrics.getMemoryUsage(); + if (newMemoryUsage > memoryUsage) { + break; + } + } + newMemoryMaxUsage = metrics.getMemoryMaxUsage(); + + if (newMemoryMaxUsage < memoryMaxUsage) { + fail(Controller.MEMORY, "getMemoryMaxUsage", memoryMaxUsage, + newMemoryMaxUsage); + } + + if (newMemoryUsage < memoryUsage) { + fail(Controller.MEMORY, "getMemoryUsage", memoryUsage, newMemoryUsage); + } + } + + @Override + public void testMisc() { + testBlkIO(); + } +} diff --git a/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java b/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java new file mode 100644 index 00000000000..875448d3eda --- /dev/null +++ b/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java @@ -0,0 +1,468 @@ +/* + * Copyright (c) 2020, Red Hat Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.containers.cgroup; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import jdk.internal.platform.CgroupSubsystem; +import jdk.internal.platform.Metrics; + +public class MetricsTesterCgroupV2 implements CgroupMetricsTester { + + private static final long UNLIMITED = -1; + private static final UnifiedController UNIFIED = new UnifiedController(); + private static final String MAX = "max"; + private static final int PER_CPU_SHARES = 1024; + + private final long startSysVal; + private final long startUserVal; + private final long startUsage; + + static class UnifiedController { + + private static final String NAME = "unified"; + private final String path; + + UnifiedController() { + path = constructPath(); + } + + String getPath() { + return path; + } + + private static String constructPath() { + String mountPath; + String cgroupPath; + try { + List fifthTokens = Files.lines(Paths.get("/proc/self/mountinfo")) + .filter( l -> l.contains("- cgroup2")) + .map(UnifiedController::splitAndMountPath) + .collect(Collectors.toList()); + if (fifthTokens.size() != 1) { + throw new AssertionError("Expected only one cgroup2 line"); + } + mountPath = fifthTokens.get(0); + + List cgroupPaths = Files.lines(Paths.get("/proc/self/cgroup")) + .filter( l -> l.startsWith("0:")) + .map(UnifiedController::splitAndCgroupPath) + .collect(Collectors.toList()); + if (cgroupPaths.size() != 1) { + throw new AssertionError("Expected only one unified controller line"); + } + cgroupPath = cgroupPaths.get(0); + return Paths.get(mountPath, cgroupPath).toString(); + } catch (IOException e) { + return null; + } + } + + public static String splitAndMountPath(String input) { + String[] tokens = input.split("\\s+"); + return tokens[4]; // fifth entry is the mount path + } + + public static String splitAndCgroupPath(String input) { + String[] tokens = input.split(":"); + return tokens[2]; + } + } + + private long getLongLimitValueFromFile(String file) { + String strVal = getStringVal(file); + if (MAX.equals(strVal)) { + return UNLIMITED; + } + return convertStringToLong(strVal); + } + + public MetricsTesterCgroupV2() { + Metrics metrics = Metrics.systemMetrics(); + // Initialize CPU usage metrics before we do any testing. + startSysVal = metrics.getCpuSystemUsage(); + startUserVal = metrics.getCpuUserUsage(); + startUsage = metrics.getCpuUsage(); + } + + private long getLongValueFromFile(String file) { + return convertStringToLong(getStringVal(file)); + } + + private long getLongValueEntryFromFile(String file, String metric) { + Path filePath = Paths.get(UNIFIED.getPath(), file); + try { + String strVal = Files.lines(filePath).filter(l -> l.startsWith(metric)).collect(Collectors.joining()); + String[] keyValues = strVal.split("\\s+"); + String value = keyValues[1]; + return convertStringToLong(value); + } catch (IOException e) { + return 0; + } + } + + private String getStringVal(String file) { + Path filePath = Paths.get(UNIFIED.getPath(), file); + try { + return Files.lines(filePath).collect(Collectors.joining()); + } catch (IOException e) { + return null; + } + } + + private void fail(String metric, long oldVal, long newVal) { + CgroupMetricsTester.fail(UnifiedController.NAME, metric, oldVal, newVal); + } + + private void fail(String metric, String oldVal, String newVal) { + CgroupMetricsTester.fail(UnifiedController.NAME, metric, oldVal, newVal); + } + + private void warn(String metric, long oldVal, long newVal) { + CgroupMetricsTester.warn(UnifiedController.NAME, metric, oldVal, newVal); + } + + private long getCpuShares(String file) { + long rawVal = getLongValueFromFile(file); + if (rawVal == 0 || rawVal == 100) { + return UNLIMITED; + } + int shares = (int)rawVal; + // CPU shares (OCI) value needs to get translated into + // a proper Cgroups v2 value. See: + // https://github.com/containers/crun/blob/master/crun.1.md#cpu-controller + // + // Use the inverse of (x == OCI value, y == cgroupsv2 value): + // ((262142 * y - 1)/9999) + 2 = x + // + int x = 262142 * shares - 1; + double frac = x/9999.0; + x = ((int)frac) + 2; + if ( x <= PER_CPU_SHARES ) { + return PER_CPU_SHARES; // mimic cgroups v1 + } + int f = x/PER_CPU_SHARES; + int lower_multiple = f * PER_CPU_SHARES; + int upper_multiple = (f + 1) * PER_CPU_SHARES; + int distance_lower = Math.max(lower_multiple, x) - Math.min(lower_multiple, x); + int distance_upper = Math.max(upper_multiple, x) - Math.min(upper_multiple, x); + x = distance_lower <= distance_upper ? lower_multiple : upper_multiple; + return x; + } + + private long getCpuMaxValueFromFile(String file) { + return getCpuValueFromFile(file, 0 /* $MAX index */); + } + + private long getCpuPeriodValueFromFile(String file) { + return getCpuValueFromFile(file, 1 /* $PERIOD index */); + } + + private long getCpuValueFromFile(String file, int index) { + String maxPeriod = getStringVal(file); + if (maxPeriod == null) { + return UNLIMITED; + } + String[] tokens = maxPeriod.split("\\s+"); + String val = tokens[index]; + if (MAX.equals(val)) { + return UNLIMITED; + } + return convertStringToLong(val); + } + + private long convertStringToLong(String val) { + return CgroupMetricsTester.convertStringToLong(val, UNLIMITED); + } + + @Override + public void testMemorySubsystem() { + Metrics metrics = Metrics.systemMetrics(); + + // User Memory + long oldVal = metrics.getMemoryFailCount(); + long newVal = getLongValueEntryFromFile("memory.events", "max"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("memory.events[max]", oldVal, newVal); + } + + oldVal = metrics.getMemoryLimit(); + newVal = getLongLimitValueFromFile("memory.max"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("memory.max", oldVal, newVal); + } + + oldVal = metrics.getMemoryUsage(); + newVal = getLongValueFromFile("memory.current"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("memory.current", oldVal, newVal); + } + + oldVal = metrics.getTcpMemoryUsage(); + newVal = getLongValueEntryFromFile("memory.stat", "sock"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("memory.stat[sock]", oldVal, newVal); + } + + oldVal = metrics.getMemoryAndSwapLimit(); + newVal = getLongLimitValueFromFile("memory.swap.max"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("memory.swap.max", oldVal, newVal); + } + + oldVal = metrics.getMemoryAndSwapUsage(); + newVal = getLongValueFromFile("memory.swap.current"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("memory.swap.current", oldVal, newVal); + } + + oldVal = metrics.getMemorySoftLimit(); + newVal = getLongLimitValueFromFile("memory.high"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("memory.high", oldVal, newVal); + } + + } + + @Override + public void testCpuAccounting() { + Metrics metrics = Metrics.systemMetrics(); + long oldVal = metrics.getCpuUsage(); + long newVal = TimeUnit.MICROSECONDS.toNanos(getLongValueEntryFromFile("cpu.stat", "usage_usec")); + + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + warn("cpu.stat[usage_usec]", oldVal, newVal); + } + + oldVal = metrics.getCpuUserUsage(); + newVal = TimeUnit.MICROSECONDS.toNanos(getLongValueEntryFromFile("cpu.stat", "user_usec")); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + warn("cpu.stat[user_usec]", oldVal, newVal); + } + + oldVal = metrics.getCpuSystemUsage(); + newVal = TimeUnit.MICROSECONDS.toNanos(getLongValueEntryFromFile("cpu.stat", "system_usec")); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + warn("cpu.stat[system_usec]", oldVal, newVal); + } + } + + @Override + public void testCpuSchedulingMetrics() { + Metrics metrics = Metrics.systemMetrics(); + long oldVal = metrics.getCpuPeriod(); + long newVal = getCpuPeriodValueFromFile("cpu.max"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("cpu.max[$PERIOD]", oldVal, newVal); + } + + oldVal = metrics.getCpuQuota(); + newVal = getCpuMaxValueFromFile("cpu.max"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("cpu.max[$MAX]", oldVal, newVal); + } + + oldVal = metrics.getCpuShares(); + newVal = getCpuShares("cpu.weight"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("cpu.weight", oldVal, newVal); + } + + oldVal = metrics.getCpuNumPeriods(); + newVal = getLongValueEntryFromFile("cpu.stat", "nr_periods"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("cpu.stat[nr_periods]", oldVal, newVal); + } + + oldVal = metrics.getCpuNumThrottled(); + newVal = getLongValueEntryFromFile("cpu.stat", "nr_throttled"); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("cpu.stat[nr_throttled]", oldVal, newVal); + } + + oldVal = metrics.getCpuThrottledTime(); + newVal = TimeUnit.MICROSECONDS.toNanos(getLongValueEntryFromFile("cpu.stat", "throttled_usec")); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("cpu.stat[throttled_usec]", oldVal, newVal); + } + } + + @Override + public void testCpuSets() { + Metrics metrics = Metrics.systemMetrics(); + int[] cpus = mapNullToEmpty(metrics.getCpuSetCpus()); + Integer[] oldVal = Arrays.stream(cpus).boxed().toArray(Integer[]::new); + Arrays.sort(oldVal); + + String cpusstr = getStringVal("cpuset.cpus"); + // Parse range string in the format 1,2-6,7 + Integer[] newVal = CgroupMetricsTester.convertCpuSetsToArray(cpusstr); + Arrays.sort(newVal); + if (Arrays.compare(oldVal, newVal) != 0) { + fail("cpuset.cpus", Arrays.toString(oldVal), + Arrays.toString(newVal)); + } + + cpus = mapNullToEmpty(metrics.getEffectiveCpuSetCpus()); + oldVal = Arrays.stream(cpus).boxed().toArray(Integer[]::new); + Arrays.sort(oldVal); + cpusstr = getStringVal("cpuset.cpus.effective"); + newVal = CgroupMetricsTester.convertCpuSetsToArray(cpusstr); + Arrays.sort(newVal); + if (Arrays.compare(oldVal, newVal) != 0) { + fail("cpuset.cpus.effective", Arrays.toString(oldVal), + Arrays.toString(newVal)); + } + + cpus = mapNullToEmpty(metrics.getCpuSetMems()); + oldVal = Arrays.stream(cpus).boxed().toArray(Integer[]::new); + Arrays.sort(oldVal); + cpusstr = getStringVal("cpuset.mems"); + newVal = CgroupMetricsTester.convertCpuSetsToArray(cpusstr); + Arrays.sort(newVal); + if (Arrays.compare(oldVal, newVal) != 0) { + fail("cpuset.mems", Arrays.toString(oldVal), + Arrays.toString(newVal)); + } + + cpus = mapNullToEmpty(metrics.getEffectiveCpuSetMems()); + oldVal = Arrays.stream(cpus).boxed().toArray(Integer[]::new); + Arrays.sort(oldVal); + cpusstr = getStringVal("cpuset.mems.effective"); + newVal = CgroupMetricsTester.convertCpuSetsToArray(cpusstr); + Arrays.sort(newVal); + if (Arrays.compare(oldVal, newVal) != 0) { + fail("cpuset.mems.effective", Arrays.toString(oldVal), + Arrays.toString(newVal)); + } + } + + private int[] mapNullToEmpty(int[] cpus) { + if (cpus == null) { + // Not available. For sake of testing continue with an + // empty array. + cpus = new int[0]; + } + return cpus; + } + + @Override + public void testCpuConsumption() { + Metrics metrics = Metrics.systemMetrics(); + // make system call + long newSysVal = metrics.getCpuSystemUsage(); + long newUserVal = metrics.getCpuUserUsage(); + long newUsage = metrics.getCpuUsage(); + + // system/user CPU usage counters may be slowly increasing. + // allow for equal values for a pass + if (newSysVal < startSysVal) { + fail("getCpuSystemUsage", newSysVal, startSysVal); + } + + // system/user CPU usage counters may be slowly increasing. + // allow for equal values for a pass + if (newUserVal < startUserVal) { + fail("getCpuUserUsage", newUserVal, startUserVal); + } + + if (newUsage <= startUsage) { + fail("getCpuUsage", newUsage, startUsage); + } + } + + @Override + public void testMemoryUsage() { + Metrics metrics = Metrics.systemMetrics(); + long memoryUsage = metrics.getMemoryUsage(); + long newMemoryUsage = 0; + + // allocate memory in a loop and check more than once for new values + // otherwise we might occasionally see the effect of decreasing new memory + // values. For example because the system could free up memory + byte[][] bytes = new byte[32][]; + for (int i = 0; i < 32; i++) { + bytes[i] = new byte[8*1024*1024]; + newMemoryUsage = metrics.getMemoryUsage(); + if (newMemoryUsage > memoryUsage) { + break; + } + } + + if (newMemoryUsage < memoryUsage) { + fail("getMemoryUsage", memoryUsage, newMemoryUsage); + } + } + + @Override + public void testMisc() { + testIOStat(); + } + + private void testIOStat() { + Metrics metrics = Metrics.systemMetrics(); + long oldVal = metrics.getBlkIOServiceCount(); + long newVal = getIoStatAccumulate(new String[] { "rios", "wios" }); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("io.stat->rios/wios: ", oldVal, newVal); + } + + oldVal = metrics.getBlkIOServiced(); + newVal = getIoStatAccumulate(new String[] { "rbytes", "wbytes" }); + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + fail("io.stat->rbytes/wbytes: ", oldVal, newVal); + } + } + + private long getIoStatAccumulate(String[] matchNames) { + try { + return Files.lines(Paths.get(UNIFIED.getPath(), "io.stat")) + .map(line -> { + long accumulator = 0; + String[] tokens = line.split("\\s+"); + for (String t: tokens) { + String[] keyVal = t.split("="); + if (keyVal.length != 2) { + continue; + } + for (String match: matchNames) { + if (match.equals(keyVal[0])) { + accumulator += Long.parseLong(keyVal[1]); + } + } + } + return accumulator; + }).collect(Collectors.summingLong(e -> e)); + } catch (IOException e) { + return CgroupSubsystem.LONG_RETVAL_UNLIMITED; + } + } +} diff --git a/test/lib/jdk/test/lib/jfr/EventNames.java b/test/lib/jdk/test/lib/jfr/EventNames.java index 7413950eb10..541d0c8f0de 100644 --- a/test/lib/jdk/test/lib/jfr/EventNames.java +++ b/test/lib/jdk/test/lib/jfr/EventNames.java @@ -87,6 +87,10 @@ public class EventNames { public final static String PlaceholderTableStatistics = PREFIX + "PlaceholderTableStatistics"; public final static String LoaderConstraintsTableStatistics = PREFIX + "LoaderConstraintsTableStatistics"; public final static String ProtectionDomainCacheTableStatistics = PREFIX + "ProtectionDomainCacheTableStatistics"; + public static final String RedefineClasses = PREFIX + "RedefineClasses"; + public static final String RetransformClasses = PREFIX + "RetransformClasses"; + public static final String ClassRedefinition = PREFIX + "ClassRedefinition"; + // This event is hard to test public final static String ReservedStackActivation = PREFIX + "ReservedStackActivation"; diff --git a/test/lib/jdk/test/lib/jfr/Events.java b/test/lib/jdk/test/lib/jfr/Events.java index 6e275d94045..47813c5db78 100644 --- a/test/lib/jdk/test/lib/jfr/Events.java +++ b/test/lib/jdk/test/lib/jfr/Events.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,10 @@ import jdk.jfr.consumer.RecordingFile; import jdk.test.lib.Asserts; import jdk.jfr.consumer.RecordedClass; import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedFrame; +import jdk.jfr.consumer.RecordedMethod; import jdk.jfr.consumer.RecordedObject; +import jdk.jfr.consumer.RecordedStackTrace; import jdk.jfr.consumer.RecordedThread; import jdk.jfr.consumer.RecordedThreadGroup; @@ -363,4 +366,21 @@ public class Events { } return false; } + + public static void assertFrame(RecordedEvent event, Class expectedClass, String expectedMethodName) { + RecordedStackTrace stackTrace = event.getStackTrace(); + Asserts.assertNotNull(stackTrace, "Missing stack trace"); + for (RecordedFrame frame : stackTrace.getFrames()) { + if (frame.isJavaFrame()) { + RecordedMethod method = frame.getMethod(); + RecordedClass type = method.getType(); + if (expectedClass.getName().equals(type.getName())) { + if (expectedMethodName.equals(method.getName())) { + return; + } + } + } + } + Asserts.fail("Expected " + expectedClass.getName() + "::"+ expectedMethodName + " in stack trace"); + } } diff --git a/test/lib/jdk/test/lib/util/JavaAgentBuilder.java b/test/lib/jdk/test/lib/util/JavaAgentBuilder.java index 22b7304d8b4..e5fe0cb9bbb 100644 --- a/test/lib/jdk/test/lib/util/JavaAgentBuilder.java +++ b/test/lib/jdk/test/lib/util/JavaAgentBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,8 @@ import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; import java.util.jar.Attributes; import java.util.jar.Manifest; @@ -53,11 +55,24 @@ public class JavaAgentBuilder { * @param args[1] file name of the agent jar to be created * @throws IOException */ - public static void main(String... args) throws IOException { + public static void main(String... args) throws Exception { String agentClass = args[0]; String agentJar = args[1]; System.out.println("Building " + agentJar + " with agent class " + agentClass); - build(agentClass, agentJar); + + build(agentClass, agentJar, parseExtraAttrs(args)); + } + + private static Map parseExtraAttrs(String[] args) throws Exception { + Map attrs = new HashMap<>(); + for (int i = 2; i < args.length; i++) { + String[] parts = args[i].split(":"); + if (parts.length != 2) { + throw new IllegalArgumentException("Extra attributes should be of format 'key:value'"); + } + attrs.put(parts[0],parts[1]); + } + return attrs; } /** @@ -70,12 +85,31 @@ public class JavaAgentBuilder { * @throws IOException */ public static void build(String agentClass, String agentJar) throws IOException { + build(agentClass, agentJar, new HashMap()); + } + + /** + * Build a java agent jar file with a given agent class. + * The agent class will be added as both premain class and agent class. + * + * @param agentClass fully qualified name of an agent class + * @param agentJar file name of the agent jar to be created + * the file will be placed in a current work directory + * @param extraAttrs additional manifest attributes + * @throws IOException + */ + public static void build(String agentClass, String agentJar, + Map extraAttrs) throws IOException { Manifest mf = new Manifest(); Attributes attrs = mf.getMainAttributes(); attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0"); + attrs.putValue("Can-Redefine-Classes", "true"); + attrs.putValue("Can-Retransform-Classes", "true"); attrs.putValue("Premain-Class", agentClass); attrs.putValue("Agent-Class", agentClass); + extraAttrs.forEach( (k,v) -> attrs.putValue(k,v)); + Path jarFile = Paths.get(".", agentJar); String testClasses = Utils.TEST_CLASSES; String agentPath = agentClass.replace(".", File.separator) + ".class"; diff --git a/test/make/TestMake.gmk b/test/make/TestMake.gmk index 4a6a5f66214..669fa6e30a8 100644 --- a/test/make/TestMake.gmk +++ b/test/make/TestMake.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,11 @@ idea: compile-commands: +$(MAKE) -f TestCompileCommands.gmk $(TEST_SUBTARGET) -TARGETS += make-base java-compilation copy-files idea compile-commands +configure: + $(BASH) $(TOPDIR)/test/make/autoconf/test-configure.sh \ + "$(AUTOCONF)" "$(TOPDIR)" "$(TEST_SUPPORT_DIR)" + +TARGETS += make-base java-compilation copy-files idea compile-commands configure all: $(TARGETS) diff --git a/test/make/autoconf/test-configure.sh b/test/make/autoconf/test-configure.sh new file mode 100644 index 00000000000..1dec38b8702 --- /dev/null +++ b/test/make/autoconf/test-configure.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# +# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute 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. +# + +# Arguments passed to us from makefile. +AUTOCONF="$1" +TOPDIR="$2" +TEST_SUPPORT_DIR="$3" + +mkdir -p $TEST_SUPPORT_DIR/test-conf +cd $TEST_SUPPORT_DIR/test-conf + +conf_script_dir="$TOPDIR/make/autoconf" +generated_script="$TEST_SUPPORT_DIR/generated-test-configure.sh" + +# Generate configure script with test hooks compiled in. +echo "Generating test-configure script at $generated_script" +cat $conf_script_dir/configure.ac | + sed -e "s|#CUSTOM_AUTOCONF_INCLUDE|m4_include([test.m4])|" | \ + ${AUTOCONF} -W all -I$TOPDIR/test/make/autoconf -I$conf_script_dir - \ + > $generated_script +rm -rf autom4te.cache + +# Sanity check +if test ! -s $generated_script; then + echo "Error: Failed to generate test-configure script" 1>&2 + rm -f $generated_script + exit 1 +fi + +# Make sure all shell commands are executed with the C locale +export LC_ALL=C + +# Export our null command line +CONFIGURE_COMMAND_LINE="" + +# Force autoconf to use bash. This also means we must disable autoconf re-exec. +export CONFIG_SHELL=$BASH +export _as_can_reexec=no + +# Now transfer control to the script generated by autoconf. This is where the +# main work is done. + +RCDIR=`mktemp -dt jdk-build-configure.tmp.XXXXXX` || exit $? +trap "rm -rf \"$RCDIR\"" EXIT +conf_logfile=./configure.log +(exec 3>&1 ; ((. $generated_script --enable-option-checking=fatal 2>&1 1>&3 ) \ + ; echo $? > "$RCDIR/rc" ) \ + | tee -a $conf_logfile 1>&2 ; exec 3>&-) | tee -a $conf_logfile + +conf_result_code=`cat "$RCDIR/rc"` + +if test $conf_result_code -ne 0; then + echo "==============================" + echo "Configure tests finished with failure. Result code: $conf_result_code" +fi + +exit $conf_result_code diff --git a/make/CopyInterimCLDRConverter.gmk b/test/make/autoconf/test.m4 similarity index 54% rename from make/CopyInterimCLDRConverter.gmk rename to test/make/autoconf/test.m4 index 52cca56d5c0..056ab0fa646 100644 --- a/make/CopyInterimCLDRConverter.gmk +++ b/test/make/autoconf/test.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,30 +23,39 @@ # questions. # -default: all -include $(SPEC) -include MakeBase.gmk +############################################################################### +# +# Unit tests for the configure script +# +############################################################################### -########################################################################################## +AC_DEFUN([TEST_STRING_OPS], +[ + FEW="ninja banan pepparkaka" + MANY="banan antarktis pepparkaka ninjamask bana" -### CLDRConverter needs the JRE time zone names from the java.base source. + EXPECTED_NON_MATCHING="antarktis ninjamask bana" + UTIL_GET_NON_MATCHING_VALUES(ACTUAL, $MANY, $FEW) + UTIL_ASSERT_STRING_EQUALS($ACTUAL, $EXPECTED_NON_MATCHING, \ + [UTIL_GET_NON_MATCHING_VALUES failed]) -define cldrconverter_copytznames - $(call MakeTargetDir) - $(RM) '$@' - $(SED) -e "s/package sun.util.resources/package build.tools.cldrconverter/" \ - -e "s/extends TimeZoneNamesBundle//" \ - -e "s/protected final/static final/" \ - < $(<) > $@ -endef + EXPECTED_MATCHING="banan pepparkaka" + UTIL_GET_MATCHING_VALUES(ACTUAL, $FEW, $MANY) + UTIL_ASSERT_STRING_EQUALS($ACTUAL, $EXPECTED_MATCHING, \ + [UTIL_GET_MATCHING_VALUES failed]) +]) -$(eval $(call SetupCopyFiles,COPY_INTERIM_CLDRCONVERTER, \ - SRC := $(TOPDIR)/src/java.base/share/classes/sun/util/resources, \ - DEST := $(BUILDTOOLS_OUTPUTDIR)/interim_cldrconverter_classes/build/tools/cldrconverter, \ - FILES := TimeZoneNames.java, \ - MACRO := cldrconverter_copytznames)) +# Use the CUSTOM_EARLY_HOOK to inject our test after basic init is done. +AC_DEFUN_ONCE([CUSTOM_EARLY_HOOK], +[ + $PRINTF "\nStarting configure tests\n" + $PRINTF "==============================\n" -########################################################################################## + TEST_STRING_OPS -all: $(COPY_INTERIM_CLDRCONVERTER) + # If no assertions failed, report success + $PRINTF "==============================\n" + $PRINTF "Configure tests finished successfully\n\n" + exit 0 +]) diff --git a/test/micro/org/openjdk/bench/java/lang/StringSubstring.java b/test/micro/org/openjdk/bench/java/lang/StringSubstring.java index 75208b858c8..c0bbfbc7320 100644 --- a/test/micro/org/openjdk/bench/java/lang/StringSubstring.java +++ b/test/micro/org/openjdk/bench/java/lang/StringSubstring.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,9 @@ import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(value = 3) +@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) @State(Scope.Benchmark) public class StringSubstring { @@ -42,4 +45,12 @@ public class StringSubstring { public String from26toEnd1() { return s.substring(26, s.length()); } + + /** + * An empty substring should not allocate a new String + */ + @Benchmark + public String empty() { + return s.substring(17, 17); + } } diff --git a/test/micro/org/openjdk/bench/java/net/DatagramSocketSendReceive.java b/test/micro/org/openjdk/bench/java/net/DatagramSocketSendReceive.java new file mode 100644 index 00000000000..de925d100a4 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/net/DatagramSocketSendReceive.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.net; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +import java.util.concurrent.TimeUnit; +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; + +/** + * Benchmark DatagramSocket send/receive. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Thread) +public class DatagramSocketSendReceive { + private int counter = 0; + + private DatagramSocket socket1, socket2, connectedSendSocket, + connectedReceiveSocket, multipleRecieveSocket, multipleSendSocket; + private DatagramPacket sendPkt1, sendPkt2, connectedSendPkt, multipleSendPkt, + receivePkt; + + private DatagramSocket[] dsa; + private DatagramPacket[] pkts; + + @Param({"128", "512", "2048", "8192", "32768"}) + public int size; + + @Param({"4"}) + public int socketCount; + + @Setup + public void setUp() throws IOException { + byte[] buf = new byte[size]; + InetAddress addr = InetAddress.getLocalHost(); + + receivePkt = new DatagramPacket(buf, buf.length); + + // single send - same socket; different sockets + socket1 = new DatagramSocket(0, addr); + socket2 = new DatagramSocket(0, addr); + sendPkt1 = new DatagramPacket(buf, buf.length, addr, + socket1.getLocalPort()); + sendPkt2 = new DatagramPacket(buf, buf.length, addr, + socket2.getLocalPort()); + + // connected send/receive + connectedSendSocket = new DatagramSocket(0, addr); + connectedReceiveSocket = new DatagramSocket(0, addr); + connectedSendSocket.connect(addr, connectedReceiveSocket.getLocalPort()); + connectedReceiveSocket.connect(addr, connectedSendSocket.getLocalPort()); + connectedSendPkt = new DatagramPacket(buf, buf.length); + + // multiple senders / multiple receivers + dsa = new DatagramSocket[socketCount]; + pkts = new DatagramPacket[socketCount]; + for (int i = 0; i < dsa.length; i++) { + dsa[i] = new DatagramSocket(0, addr); + pkts[i] = new DatagramPacket(buf, buf.length, + addr, dsa[i].getLocalPort()); + } + multipleRecieveSocket = new DatagramSocket(0, addr); + multipleSendSocket = new DatagramSocket(0, addr); + multipleSendPkt = new DatagramPacket(buf, buf.length, addr, + multipleRecieveSocket.getLocalPort()); + } + + // same sender receiver + @Benchmark + public void sendReceiveSingleSocket() throws IOException { + socket1.send(sendPkt1); + socket1.receive(receivePkt); + } + + // single sender, single receiver + @Benchmark + public void sendReceive() throws IOException { + socket1.send(sendPkt2); + socket2.receive(receivePkt); + } + + // connected sender receiver + @Benchmark + public void sendReceiveConnected() throws IOException { + connectedSendSocket.send(connectedSendPkt); + connectedReceiveSocket.receive(receivePkt); + } + + // multiple senders, single receiver + @Benchmark + public void sendMultiple() throws IOException { + int i = counter; + dsa[i].send(multipleSendPkt); + multipleRecieveSocket.receive(receivePkt); + counter = ++i % dsa.length; + } + + // single sender, multiple receivers + @Benchmark + public void receiveMultiple() throws IOException { + int i = counter; + multipleSendSocket.send(pkts[i]); + dsa[i].receive(receivePkt); + counter = ++i % dsa.length; + } + + @TearDown + public void tearDown() { + socket1.close(); + socket2.close(); + connectedSendSocket.close(); + connectedReceiveSocket.close(); + + multipleRecieveSocket.close(); + multipleSendSocket.close(); + for (DatagramSocket ds : dsa) { + ds.close(); + } + } +} diff --git a/test/nashorn/TEST.ROOT b/test/nashorn/TEST.ROOT index 8f0581d575b..5980702f0d4 100644 --- a/test/nashorn/TEST.ROOT +++ b/test/nashorn/TEST.ROOT @@ -8,7 +8,7 @@ keys=intermittent randomness groups=TEST.groups # Minimum jtreg version -requiredVersion=4.2 b16 +requiredVersion=5.0 b1 # Use new module options useNewOptions=true