OpenJDK / jdk / jdk
changeset 52257:30d5f10ace94
Merge
author | jdv |
---|---|
date | Tue, 16 Oct 2018 14:26:22 +0530 |
parents | 8e408bf62635 6a297371a9b4 |
children | 02e4b0ab0f97 |
files | test/hotspot/jtreg/ProblemList-cds-mode.txt test/jdk/com/sun/jdi/DeferredStepTest.sh test/jdk/com/sun/jdi/ShellScaffold.sh test/jdk/com/sun/jdi/ZZZcleanup.sh test/jdk/lib/security/CheckBlacklistedCerts.java test/jdk/lib/security/cacerts/VerifyCACerts.java test/jdk/lib/testlibrary/ModuleTargetHelper.java test/jdk/lib/testlibrary/ModuleUtils.java test/jdk/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java test/jdk/lib/testlibrary/jdk/testlibrary/testkeys |
diffstat | 873 files changed, 13983 insertions(+), 12711 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Mon Oct 15 10:29:06 2018 +0530 +++ b/.hgtags Tue Oct 16 14:26:22 2018 +0530 @@ -515,3 +515,6 @@ 15094d12a632f452a2064318a4e416d0c7a9ce0c jdk-12+12 511a9946f83e3e3c7b9dbe1840367063fb39b4e1 jdk-12+13 8897e41b327c0a5601c6ba2bba5d07f15a3ffc91 jdk-12+14 +8897e41b327c0a5601c6ba2bba5d07f15a3ffc91 jdk-12+14 +6f04692c7d5137ee34a6bd94c0c8a6c9219cb127 jdk-12+14 +f8626bcc169813a4b2a15880386b952719d1d6d1 jdk-12+15
--- a/make/BuildStatic.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/BuildStatic.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -42,7 +42,7 @@ $(GLOBAL_SYMBOLS_FILE): $(MODULES_SYMBOLS_FILES) $(call LogInfo, Generating global exported.symbols file) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(CAT) $^ > $@ TARGETS += $(GLOBAL_SYMBOLS_FILE)
--- a/make/Bundles.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/Bundles.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -70,6 +70,7 @@ $$(call SetIfEmpty, $1_UNZIP_DEBUGINFO, false) $(BUNDLES_OUTPUTDIR)/$$($1_BUNDLE_NAME): $$($1_FILES) + $$(call MakeTargetDir) # If any of the files contain a space in the file name, CacheFind # will have replaced it with ?. Tar does not accept that so need to # switch it back. @@ -79,7 +80,6 @@ $$(CAT) $$($1_$$d_LIST_FILE) | $$(TR) '?' ' ' > $$($1_$$d_LIST_FILE).tmp \ && $(MV) $$($1_$$d_LIST_FILE).tmp $$($1_$$d_LIST_FILE) $$(NEWLINE) \ ) - $$(call MakeDir, $$(@D)) ifneq ($$($1_SPECIAL_INCLUDES), ) $$(foreach i, $$($1_SPECIAL_INCLUDES), \ $$(foreach d, $$($1_BASE_DIRS), \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/CompileCommands.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -0,0 +1,60 @@ +# +# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +default: all + +include $(SPEC) +include MakeBase.gmk + +# When FIXPATH is set, let it process the file to make sure all paths are usable +# by system native tools. The FIXPATH tool assumes arguments preceeded by an @ +# character points to a text file containing further arguments (similar to a +# linker). It replaces any such arguments with a different temporary filename, +# whose contents has been processed to make any paths native. To obtain a +# properly processed compile_commands.json, FIXPATH is then made to invoke an +# AWK script with the unprocessed json file as the only argument, prepended with +# an @ character. The AWK script simply copies the contents of this processed +# file. +# +# The sed command encloses the fragments inside brackets and removes the final +# trailing comma. +$(OUTPUTDIR)/compile_commands.json: $(wildcard $(MAKESUPPORT_OUTPUTDIR)/compile-commands/*.json) + $(call LogWarn, Updating compile_commands.json) + $(RM) $@ + $(FIND) $(MAKESUPPORT_OUTPUTDIR)/compile-commands/ -name \*.json | \ + $(SORT) | $(XARGS) $(CAT) >> $@.tmp + $(if $(FIXPATH),$(FIXPATH) $(AWK) 'BEGIN { \ + tmpfile = substr(ARGV[2],2); \ + cmd = "$(CP) " "\047" tmpfile "\047" " $@.tmp"; \ + system(cmd); \ + }' -- @$@.tmp) + $(SED) -e '1s/^/[\$(NEWLINE)/' -e '$(DOLLAR)s/,\s\{0,\}$(DOLLAR)/\$(NEWLINE)]/' $@.tmp > $@ + $(RM) $@.tmp + +TARGETS += $(OUTPUTDIR)/compile_commands.json + +all: $(TARGETS) + +.PHONY: all
--- a/make/CopyInterimCLDRConverter.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/CopyInterimCLDRConverter.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -33,7 +33,7 @@ ### CLDRConverter needs the JRE time zone names from the java.base source. define cldrconverter_copytznames - $(MKDIR) -p '$(@D)' + $(call MakeTargetDir) $(RM) '$@' $(SED) -e "s/package sun.util.resources/package build.tools.cldrconverter/" \ -e "s/extends TimeZoneNamesBundle//" \ @@ -46,7 +46,7 @@ DEST := $(BUILDTOOLS_OUTPUTDIR)/interim_cldrconverter_classes/build/tools/cldrconverter, \ FILES := TimeZoneNames.java, \ MACRO := cldrconverter_copytznames)) - + ########################################################################################## all: $(COPY_INTERIM_CLDRCONVERTER)
--- a/make/CreateBuildJdkCopy.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/CreateBuildJdkCopy.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -41,7 +41,7 @@ $(COPY_CLASSES_TARGET): $(call CacheFind, $(wildcard \ $(addprefix $(JDK_OUTPUTDIR)/modules/, $(MODULES_TO_COPY)))) - $(ECHO) $(LOG_INFO) "Copying java modules to buildjdk: $(MODULES_TO_COPY)" + $(call LogInfo, Copying java modules to buildjdk: $(MODULES_TO_COPY)) $(RM) -r $(BUILDJDK_OUTPUTDIR)/jdk/modules $(MKDIR) -p $(BUILDJDK_OUTPUTDIR)/jdk/modules $(foreach m, $(MODULES_TO_COPY), \
--- a/make/GenerateModuleSummary.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/GenerateModuleSummary.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -35,18 +35,18 @@ TOOLS_MODULE_SRCDIR := $(TOPDIR)/make/jdk/src/classes/build/tools/jigsaw $(GENGRAPHS_DIR)/jdk.dot: $(BUILD_JIGSAW_TOOLS) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(TOOL_GENGRAPHS) --output $(GENGRAPHS_DIR) $(SPEC_DOTFILES_DIR)/java.se.dot: $(BUILD_JIGSAW_TOOLS) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(TOOL_GENGRAPHS) --spec --output $(SPEC_DOTFILES_DIR) $(GENGRAPHS_DIR)/technology-summary.html: $(TOOLS_MODULE_SRCDIR)/technology-summary.html $(install-file) $(GENGRAPHS_DIR)/module-summary.html: $(BUILD_JIGSAW_TOOLS) $(GENGRAPHS_DIR)/technology-summary.html - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(TOOL_MODULESUMMARY) -o $@ --module-path $(IMAGES_OUTPUTDIR)/jmods all: $(GENGRAPHS_DIR)/jdk.dot $(GENGRAPHS_DIR)/module-summary.html $(SPEC_DOTFILES_DIR)/java.se.dot
--- a/make/GensrcModuleInfo.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/GensrcModuleInfo.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -79,7 +79,7 @@ $(BUILD_TOOLS_JDK) \ $(MOD_FILES) \ $(call DependOnVariable, ALL_MODULES) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(RM) $@ $@.tmp $(TOOL_GENMODULEINFOSOURCE) -o $@.tmp \ --source-file $< \
--- a/make/Help.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/Help.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -119,7 +119,7 @@ run-test-prebuilt: @( cd $(topdir) && \ $(MAKE) --no-print-directory -r -R -I make/common/ -f make/RunTestsPrebuilt.gmk \ - run-test-prebuilt TEST="$(TEST)" ) + run-test-prebuilt CUSTOM_MAKE_DIR=$(CUSTOM_MAKE_DIR) TEST="$(TEST)" ) ALL_GLOBAL_TARGETS := help print-configurations run-test-prebuilt
--- a/make/Images.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/Images.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -90,24 +90,32 @@ $(JDK_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \ $(call DependOnVariable, JDK_MODULES_LIST) $(BASE_RELEASE_FILE) - $(ECHO) Creating jdk image + $(call LogWarn, Creating jdk image) $(RM) -r $(JDK_IMAGE_DIR) $(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/images/jdk, \ $(JLINK_TOOL) --add-modules $(JDK_MODULES_LIST) \ $(JLINK_JDK_EXTRA_OPTS) \ --output $(JDK_IMAGE_DIR) \ ) + ifeq ($(BUILD_CDS_ARCHIVE), true) + $(call LogWarn, Creating CDS archive for jdk image) + $(JDK_IMAGE_DIR)/bin/java -Xshare:dump -Xmx128M -Xms128M $(LOG_INFO) + endif $(TOUCH) $@ $(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \ $(call DependOnVariable, JRE_MODULES_LIST) $(BASE_RELEASE_FILE) - $(ECHO) Creating legacy jre image + $(call LogWarn, Creating legacy jre image) $(RM) -r $(JRE_IMAGE_DIR) $(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/images/jre, \ $(JLINK_TOOL) --add-modules $(JRE_MODULES_LIST) \ $(JLINK_JRE_EXTRA_OPTS) \ --output $(JRE_IMAGE_DIR) \ ) + ifeq ($(BUILD_CDS_ARCHIVE), true) + $(call LogWarn, Creating CDS archive for jre image) + $(JRE_IMAGE_DIR)/bin/java -Xshare:dump -Xmx128M -Xms128M $(LOG_INFO) + endif $(TOUCH) $@ TOOL_JRE_TARGETS := $(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE)
--- a/make/MacBundles.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/MacBundles.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -63,13 +63,13 @@ $(JDK_MACOSX_CONTENTS_DIR)/MacOS/libjli.dylib: $(call LogInfo, Creating link $(patsubst $(OUTPUTDIR)/%,%,$@)) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(RM) $@ $(LN) -s ../Home/lib/libjli.dylib $@ $(JRE_MACOSX_CONTENTS_DIR)/MacOS/libjli.dylib: $(call LogInfo, Creating link $(patsubst $(OUTPUTDIR)/%,%,$@)) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(RM) $@ $(LN) -s ../Home/lib/libjli.dylib $@
--- a/make/Main.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/Main.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -263,6 +263,31 @@ $(HOTSPOT_VARIANT_LIBS_TARGETS) hotspot-ide-project ################################################################################ +# Generate libs and launcher targets for creating compile_commands.json fragments +define DeclareCompileCommandsRecipe + $1-compile-commands: + $$(call LogInfo, Generating compile_commands.json fragments for $1) + +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f Main.gmk $1-only \ + GENERATE_COMPILE_COMMANDS_ONLY=true) + + COMPILE_COMMANDS_TARGETS_$2 += $1-compile-commands +endef + +$(foreach t, $(HOTSPOT_VARIANT_LIBS_TARGETS), \ + $(eval $(call DeclareCompileCommandsRecipe,$t,HOTSPOT)) \ +) + +$(foreach t, $(LIBS_TARGETS) $(LAUNCHER_TARGETS), \ + $(eval $(call DeclareCompileCommandsRecipe,$t,JDK)) \ +) + +compile-commands compile-commands-hotspot: + +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f CompileCommands.gmk) + +ALL_TARGETS += $(COMPILE_COMMANDS_TARGETS_HOTSPOT) $(COMPILE_COMMANDS_TARGETS_JDK) +ALL_TARGETS += compile-commands compile-commands-hotspot + +################################################################################ # Build demos targets demos-jdk: @@ -559,8 +584,12 @@ test-make: ($(CD) $(TOPDIR)/test/make && $(MAKE) $(MAKE_ARGS) -f TestMake.gmk $(TEST_TARGET)) +test-compile-commands: + ($(CD) $(TOPDIR)/test/make && $(MAKE) $(MAKE_ARGS) -f TestMake.gmk test-compile-commands) + ALL_TARGETS += test test-hotspot-jtreg test-hotspot-jtreg-native \ - test-hotspot-internal test-hotspot-gtest test-jdk-jtreg-native test-make + test-hotspot-internal test-hotspot-gtest test-jdk-jtreg-native test-make \ + test-compile-commands ################################################################################ # Bundles @@ -735,6 +764,20 @@ $(foreach m, $(ALL_MODULES), $(eval $m-jmod: $($(m)_JMOD_DEPS))) $(foreach m, $(INTERIM_IMAGE_MODULES), $(eval $m-interim-jmod: $($(m)_JMOD_DEPS))) + # Setup the minimal set of generated native source dependencies for hotspot + $(foreach v, $(JVM_VARIANTS), \ + $(eval hotspot-$v-libs-compile-commands: hotspot-$v-gensrc) \ + $(foreach m, $(filter java.desktop jdk.hotspot.agent, $(GENSRC_MODULES)), \ + $(eval hotspot-$v-libs-compile-commands: $m-gensrc)) \ + ) + + # For the full JDK compile commands, create all possible generated sources + $(foreach m, $(GENSRC_MODULES), $(eval $m-libs-compile-commands: $m-gensrc)) + $(foreach m, $(filter $(JAVA_MODULES), $(LIBS_MODULES)), $(eval $m-libs-compile-commands: $m-java)) + + compile-commands-hotspot: $(COMPILE_COMMANDS_TARGETS_HOTSPOT) + compile-commands: $(COMPILE_COMMANDS_TARGETS_HOTSPOT) $(COMPILE_COMMANDS_TARGETS_JDK) + # Jmods cannot be created until we have the jmod tool ready to run. During # a normal build we run it from the exploded image, but when cross compiling # it's run from the buildjdk, which is either created at build time or user @@ -849,6 +892,8 @@ test-make: clean-test-make + test-compile-commands: compile-commands + build-test-lib: exploded-image-optimize build-test-failure-handler: interim-langtools @@ -1071,7 +1116,7 @@ # Remove everything, except the output from configure. clean: $(CLEAN_DIR_TARGETS) - ($(CD) $(OUTPUTDIR) && $(RM) -r build*.log*) + ($(CD) $(OUTPUTDIR) && $(RM) -r build*.log* compile_commands.json) $(ECHO) Cleaned all build artifacts. clean-docs:
--- a/make/ModuleWrapper.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/ModuleWrapper.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -100,5 +100,9 @@ $(TARGETS)), \ )) -all: $(TARGETS) $(COPY_LIBS_TO_BIN) $(COPY_LIBS_TO_LIB) \ - $(COPY_INCLUDE) $(COPY_CMDS) $(COPY_CONF) $(LINK_LIBS_TO_LIB) +ifeq ($(GENERATE_COMPILE_COMMANDS_ONLY), true) + all: $(filter $(MAKESUPPORT_OUTPUTDIR)/compile-commands/%, $(TARGETS)) +else + all: $(TARGETS) $(COPY_LIBS_TO_BIN) $(COPY_LIBS_TO_LIB) \ + $(COPY_INCLUDE) $(COPY_CMDS) $(COPY_CONF) $(LINK_LIBS_TO_LIB) +endif
--- a/make/RunTests.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/RunTests.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -45,8 +45,8 @@ endif $(eval $(call ParseKeywordVariable, TEST_OPTS, \ - KEYWORDS := JOBS TIMEOUT, \ - STRING_KEYWORDS := VM_OPTIONS, \ + SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR, \ + STRING_KEYWORDS := VM_OPTIONS JAVA_OPTIONS, \ )) # Helper function to propagate TEST_OPTS values. @@ -104,22 +104,50 @@ GTEST_VARIANTS := $(strip $(patsubst $(TEST_IMAGE_DIR)/hotspot/gtest/%, %, $(GTEST_LAUNCHER_DIRS))) ################################################################################ +# Setup global test running parameters +################################################################################ + +# Each factor variable comes in 3 variants. The first one is reserved for users +# to use on command line. The other two are for predifined configurations in JDL +# and for machine specific configurations respectively. +TEST_JOBS_FACTOR ?= 1 +TEST_JOBS_FACTOR_JDL ?= 1 +TEST_JOBS_FACTOR_MACHINE ?= 1 + +ifeq ($(TEST_JOBS), 0) + # Concurrency based on min(cores / 2, 12) * TEST_JOBS_FACTOR + TEST_JOBS := $(shell $(AWK) \ + 'BEGIN { \ + c = $(NUM_CORES) / 2; \ + if (c > 12) c = 12; \ + c = c * $(TEST_JOBS_FACTOR); \ + c = c * $(TEST_JOBS_FACTOR_JDL); \ + c = c * $(TEST_JOBS_FACTOR_MACHINE); \ + if (c < 1) c = 1; \ + printf "%.0f", c; \ + }') +endif + +################################################################################ # Parse control variables ################################################################################ ifneq ($(TEST_OPTS), ) # Inform the user $(info Running tests using TEST_OPTS control variable '$(TEST_OPTS)') - - $(eval $(call SetTestOpt,VM_OPTIONS,JTREG)) - $(eval $(call SetTestOpt,VM_OPTIONS,GTEST)) - - $(eval $(call SetTestOpt,JOBS,JTREG)) - $(eval $(call SetTestOpt,TIMEOUT,JTREG)) endif +$(eval $(call SetTestOpt,VM_OPTIONS,JTREG)) +$(eval $(call SetTestOpt,JAVA_OPTIONS,JTREG)) +$(eval $(call SetTestOpt,VM_OPTIONS,GTEST)) +$(eval $(call SetTestOpt,JAVA_OPTIONS,GTEST)) + +$(eval $(call SetTestOpt,JOBS,JTREG)) +$(eval $(call SetTestOpt,TIMEOUT_FACTOR,JTREG)) + $(eval $(call ParseKeywordVariable, JTREG, \ - KEYWORDS := JOBS TIMEOUT TEST_MODE ASSERT VERBOSE RETAIN MAX_MEM, \ + SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR TEST_MODE ASSERT VERBOSE RETAIN MAX_MEM \ + EXTRA_PROBLEM_LISTS KEYWORDS, \ STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS, \ )) @@ -129,8 +157,8 @@ endif $(eval $(call ParseKeywordVariable, GTEST, \ - KEYWORDS := REPEAT, \ - STRING_KEYWORDS := OPTIONS VM_OPTIONS, \ + SINGLE_KEYWORDS := REPEAT, \ + STRING_KEYWORDS := OPTIONS VM_OPTIONS JAVA_OPTIONS, \ )) ifneq ($(GTEST), ) @@ -143,17 +171,6 @@ # Component-specific Jtreg settings ################################################################################ -ifeq ($(TEST_JOBS), 0) - # If TEST_JOBS is not specified, hotspot fallback default is - # min(num_cores / 2, 12). - hotspot_JTREG_JOBS := $(shell $(EXPR) $(NUM_CORES) / 2) - ifeq ($(hotspot_JTREG_JOBS), 0) - hotspot_JTREG_JOBS := 1 - else ifeq ($(shell $(EXPR) $(hotspot_JTREG_JOBS) \> 12), 1) - hotspot_JTREG_JOBS := 12 - endif -endif - hotspot_JTREG_MAX_MEM := 0 hotspot_JTREG_ASSERT := false hotspot_JTREG_NATIVEPATH := $(TEST_IMAGE_DIR)/hotspot/jtreg/native @@ -165,6 +182,8 @@ nashorn_JTREG_PROBLEM_LIST += $(TOPDIR)/test/nashorn/ProblemList.txt hotspot_JTREG_PROBLEM_LIST += $(TOPDIR)/test/hotspot/jtreg/ProblemList.txt +langtools_JTREG_MAX_MEM := 768m + ################################################################################ # Parse test selection # @@ -368,15 +387,16 @@ $1_GTEST_REPEAT :=--gtest_repeat=$$(GTEST_REPEAT) endif - run-test-$1: + run-test-$1: $(TEST_PREREQS) $$(call LogWarn) $$(call LogWarn, Running test '$$($1_TEST)') $$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR)) $$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/gtest, \ $$(FIXPATH) $$(TEST_IMAGE_DIR)/hotspot/gtest/$$($1_VARIANT)/gtestLauncher \ - -jdk $(JDK_IMAGE_DIR) $$($1_GTEST_FILTER) \ - --gtest_output=xml:$$($1_TEST_RESULTS_DIR)/gtest.xml \ - $$($1_GTEST_REPEAT) $$(GTEST_OPTIONS) $$(GTEST_VM_OPTIONS) \ + -jdk $(JDK_IMAGE_DIR) $$($1_GTEST_FILTER) \ + --gtest_output=xml:$$($1_TEST_RESULTS_DIR)/gtest.xml \ + $$($1_GTEST_REPEAT) $$(GTEST_OPTIONS) $$(GTEST_VM_OPTIONS) \ + $$($1_GTEST_JAVA_OPTIONS) \ > >($(TEE) $$($1_TEST_RESULTS_DIR)/gtest.txt) \ && $$(ECHO) $$$$? > $$($1_EXITCODE) \ || $$(ECHO) $$$$? > $$($1_EXITCODE) \ @@ -447,12 +467,11 @@ $1_TEST_NAME := $$(strip $$(patsubst jtreg:%, %, $$($1_TEST))) - $1_COMPONENT := \ + $1_TEST_ROOT := \ $$(strip $$(foreach root, $$(JTREG_TESTROOTS), \ - $$(if $$(filter $$(root)%, $$(JTREG_TOPDIR)/$$($1_TEST_NAME)), \ - $$(lastword $$(subst /, $$(SPACE), $$(root))) \ - ) \ + $$(if $$(filter $$(root)%, $$(JTREG_TOPDIR)/$$($1_TEST_NAME)), $$(root)) \ )) + $1_COMPONENT := $$(lastword $$(subst /, $$(SPACE), $$($1_TEST_ROOT))) # This will work only as long as just hotspot has the additional "jtreg" directory ifeq ($$($1_COMPONENT), jtreg) $1_COMPONENT := hotspot @@ -475,11 +494,12 @@ $$(eval $$(call SetJtregValue,$1,JTREG_BASIC_OPTIONS)) $$(eval $$(call SetJtregValue,$1,JTREG_PROBLEM_LIST)) + # Only the problem list for the current test root should be used. + $1_JTREG_PROBLEM_LIST := $$(filter $$($1_TEST_ROOT)%, $$($1_JTREG_PROBLEM_LIST)) + ifneq ($(TEST_JOBS), 0) - # User has specified TEST_JOBS, use that as fallback default $$(eval $$(call SetJtregValue,$1,JTREG_JOBS,$$(TEST_JOBS))) else - # Use JOBS as default (except for hotspot) $$(eval $$(call SetJtregValue,$1,JTREG_JOBS,$$(JOBS))) endif @@ -487,7 +507,7 @@ # we may end up with a lot of JVM's $1_JTREG_MAX_RAM_PERCENTAGE := $$(shell $$(EXPR) 25 / $$($1_JTREG_JOBS)) - JTREG_TIMEOUT ?= 4 + JTREG_TIMEOUT_FACTOR ?= 4 JTREG_VERBOSE ?= fail,error,summary JTREG_RETAIN ?= fail,error @@ -498,10 +518,10 @@ $1_JTREG_BASIC_OPTIONS += -$$($1_JTREG_TEST_MODE) \ -verbose:$$(JTREG_VERBOSE) -retain:$$(JTREG_RETAIN) \ - -concurrency:$$($1_JTREG_JOBS) -timeoutFactor:$$(JTREG_TIMEOUT) \ + -concurrency:$$($1_JTREG_JOBS) -timeoutFactor:$$(JTREG_TIMEOUT_FACTOR) \ -vmoption:-XX:MaxRAMPercentage=$$($1_JTREG_MAX_RAM_PERCENTAGE) - $1_JTREG_BASIC_OPTIONS += -automatic -keywords:\!ignore -ignore:quiet + $1_JTREG_BASIC_OPTIONS += -automatic -ignore:quiet # Make it possible to specify the JIB_DATA_DIR for tests using the # JIB Artifact resolver @@ -531,6 +551,14 @@ $1_JTREG_BASIC_OPTIONS += $$(addprefix -exclude:, $$($1_JTREG_PROBLEM_LIST)) endif + ifneq ($$(JTREG_EXTRA_PROBLEM_LISTS), ) + # Accept both absolute paths as well as relative to the current test root. + $1_JTREG_BASIC_OPTIONS += $$(addprefix -exclude:, $$(wildcard \ + $$(JTREG_EXTRA_PROBLEM_LISTS) \ + $$(addprefix $$($1_TEST_ROOT)/, $$(JTREG_EXTRA_PROBLEM_LISTS)) \ + )) + endif + ifneq ($$(JIB_HOME), ) $1_JTREG_BASIC_OPTIONS += -e:JIB_HOME=$$(JIB_HOME) endif @@ -541,10 +569,21 @@ $1_JTREG_LAUNCHER_OPTIONS += -Djava.library.path="$(JTREG_FAILURE_HANDLER_DIR)" endif + ifneq ($$(JTREG_KEYWORDS), ) + # The keywords string may contain problematic characters and may be quoted + # already when it arrives here. Remove any existing quotes and replace them + # with one set of single quotes. + $1_JTREG_KEYWORDS := \ + $$(strip $$(subst $$(SQUOTE),,$$(subst $$(DQUOTE),,$$(JTREG_KEYWORDS)))) + ifneq ($$($1_JTREG_KEYWORDS), ) + $1_JTREG_BASIC_OPTIONS += -k:'$$($1_JTREG_KEYWORDS)' + endif + endif + clean-workdir-$1: $$(RM) -r $$($1_TEST_SUPPORT_DIR) - run-test-$1: clean-workdir-$1 + run-test-$1: clean-workdir-$1 $(TEST_PREREQS) $$(call LogWarn) $$(call LogWarn, Running test '$$($1_TEST)') $$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR)) @@ -631,7 +670,7 @@ $$(error Invalid special test specification: $$($1_TEST_NAME)) endif - run-test-$1: + run-test-$1: $(TEST_PREREQS) $$(call LogWarn) $$(call LogWarn, Running test '$$($1_TEST)') $$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR))
--- a/make/RunTestsPrebuilt.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/RunTestsPrebuilt.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -49,10 +49,11 @@ # given. # Note: No spaces are allowed around the arguments. # -# $1: The name of the argument +# $1: The name of the variable # $2: The default value, if any, or OPTIONAL (do not provide a default but # do not exit if it is missing) # $3: If NO_CHECK, disable checking for target file/directory existence +# If MKDIR, create the default directory define SetupVariable ifeq ($$($1), ) ifeq ($2, ) @@ -75,10 +76,17 @@ endif # If $1 has a value (is not optional), and $3 is not set (to NO_CHECK), # and if wildcard is empty, then complain that the file is missing. - ifeq ($$(strip $$(if $$($1), , OPTIONAL) $$(wildcard $$($1)) $3), ) - $$(info Error: Prebuilt variable $1 points to missing file/directory:) - $$(info '$$($1)') - $$(error Cannot continue.) + ifeq ($3, MKDIR) + ifneq ($$(findstring $$(LOG), info debug trace), ) + $$(info Creating directory for $1) + endif + $$(shell mkdir -p $$($1)) + else ifneq ($3, NO_CHECK) + ifeq ($$(strip $$(if $$($1), , OPTIONAL) $$(wildcard $$($1))), ) + $$(info Error: Prebuilt variable $1 points to missing file/directory:) + $$(info '$$($1)') + $$(error Cannot continue.) + endif endif endef @@ -106,14 +114,14 @@ # Verify that user has given correct additional input. # These variables are absolutely necessary -$(eval $(call SetupVariable,OUTPUTDIR)) +$(eval $(call SetupVariable,OUTPUTDIR,$(TOPDIR)/build/run-test-prebuilt,MKDIR)) $(eval $(call SetupVariable,BOOT_JDK)) $(eval $(call SetupVariable,JT_HOME)) # These can have default values based on the ones above $(eval $(call SetupVariable,JDK_IMAGE_DIR,$(OUTPUTDIR)/images/jdk)) $(eval $(call SetupVariable,TEST_IMAGE_DIR,$(OUTPUTDIR)/images/test)) -$(eval $(call SetupVariable,SYMBOLS_IMAGE_DIR,$(OUTPUTDIR)/images/symbols)) +$(eval $(call SetupVariable,SYMBOLS_IMAGE_DIR,$(OUTPUTDIR)/images/symbols,NO_CHECK)) # Provide default values for tools that we need $(eval $(call SetupVariable,MAKE,make,NO_CHECK)) @@ -202,8 +210,8 @@ ifeq ($(OPENJDK_TARGET_OS), windows) ifeq ($(wildcard $(TEST_IMAGE_DIR)/bin/fixpath.exe), ) - $$(info Error: fixpath is missing from test image '$(TEST_IMAGE_DIR)') - $$(error Cannot continue.) + $(info Error: fixpath is missing from test image '$(TEST_IMAGE_DIR)') + $(error Cannot continue.) endif FIXPATH := $(TEST_IMAGE_DIR)/bin/fixpath.exe -c PATH_SEP:=; @@ -214,15 +222,17 @@ # Check number of cores ifeq ($(OPENJDK_TARGET_OS), linux) - NUM_CORES := $(shell $(CAT) /proc/cpuinfo | $(GREP) -c processor) + NUM_CORES := $(shell $(CAT) /proc/cpuinfo | $(GREP) -c processor) else ifeq ($(OPENJDK_TARGET_OS), macosx) - NUM_CORES := $(shell /usr/sbin/sysctl -n hw.ncpu) + NUM_CORES := $(shell /usr/sbin/sysctl -n hw.ncpu) else ifeq ($(OPENJDK_TARGET_OS), solaris) - NUM_CORES := $(shell LC_MESSAGES=C /usr/sbin/psrinfo -v | $(GREP) -c on-line) + NUM_CORES := $(shell LC_MESSAGES=C /usr/sbin/psrinfo -v | $(GREP) -c on-line) else ifeq ($(OPENJDK_TARGET_OS), windows) - NUM_CORES := $(NUMBER_OF_PROCESSORS) -else - NUM_CORES := 1 + NUM_CORES := $(NUMBER_OF_PROCESSORS) +endif +ifeq ($(NUM_CORES), ) + $(warn Could not find number of CPUs, assuming 1) + NUM_CORES := 1 endif ################################################################################ @@ -276,9 +286,6 @@ @$(RM) -f $(MAKESUPPORT_OUTPUTDIR)/exit-with-error @cd $(TOPDIR) && $(MAKE) $(MAKE_ARGS) -f make/RunTests.gmk run-test \ TEST="$(TEST)" - @if test -f $(MAKESUPPORT_OUTPUTDIR)/exit-with-error ; then \ - exit 1 ; \ - fi all: run-test-prebuilt
--- a/make/RunTestsPrebuiltSpec.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/RunTestsPrebuiltSpec.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -124,7 +124,7 @@ JMOD := $(FIXPATH) $(JMOD_CMD) JARSIGNER := $(FIXPATH) $(JARSIGNER_CMD) -BUILD_JAVA := $(JAVA) +BUILD_JAVA := $(JDK_IMAGE_DIR)/bin/JAVA ################################################################################ # Some common tools. Assume most common name and no path. AWK := awk @@ -172,3 +172,13 @@ EXPR := expr FILE := file HG := hg + +# On Solaris gnu versions of some tools are required. +ifeq ($(OPENJDK_BUILD_OS), solaris) + AWK := gawk + GREP := ggrep + EGREP := ggrep -E + FGREP := grep -F + SED := gsed + TAR := gtar +endif
--- a/make/autoconf/basics.m4 Mon Oct 15 10:29:06 2018 +0530 +++ b/make/autoconf/basics.m4 Tue Oct 16 14:26:22 2018 +0530 @@ -569,7 +569,8 @@ BASIC_REQUIRE_PROGS(GZIP, pigz gzip) BASIC_REQUIRE_PROGS(LN, ln) BASIC_REQUIRE_PROGS(LS, ls) - BASIC_REQUIRE_PROGS(MKDIR, mkdir) + # 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])
--- a/make/autoconf/configure.ac Mon Oct 15 10:29:06 2018 +0530 +++ b/make/autoconf/configure.ac Tue Oct 16 14:26:22 2018 +0530 @@ -233,6 +233,7 @@ JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST JDKOPT_EXCLUDE_TRANSLATIONS JDKOPT_ENABLE_DISABLE_MANPAGES +JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE ############################################################################### #
--- a/make/autoconf/hotspot.m4 Mon Oct 15 10:29:06 2018 +0530 +++ b/make/autoconf/hotspot.m4 Tue Oct 16 14:26:22 2018 +0530 @@ -252,14 +252,6 @@ AC_MSG_ERROR([Invalid value for --enable-cds: $enable_cds]) fi - # 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 - AC_SUBST(ENABLE_CDS) ]) @@ -489,6 +481,34 @@ # All variants but minimal (and custom) get these features NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES cmsgc g1gc parallelgc serialgc epsilongc jni-check jvmti management nmt services vm-structs" + # 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. + DISABLE_CDS=`$ECHO $DISABLED_JVM_FEATURES | $GREP cds` + if test "x$DISABLE_CDS" = "xcds"; 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 + + # Disable CDS for zero, minimal, core.. + if HOTSPOT_CHECK_JVM_VARIANT(zero) || HOTSPOT_CHECK_JVM_VARIANT(minimal) || HOTSPOT_CHECK_JVM_VARIANT(core); 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
--- a/make/autoconf/jdk-options.m4 Mon Oct 15 10:29:06 2018 +0530 +++ b/make/autoconf/jdk-options.m4 Tue Oct 16 14:26:22 2018 +0530 @@ -527,7 +527,7 @@ # 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)); then + 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" @@ -605,3 +605,37 @@ AC_SUBST(BUILD_MANPAGES) ]) + +################################################################################ +# +# Disable the default CDS archive generation +# cross compilation - disabled +# +AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE], +[ + AC_ARG_ENABLE([cds-archive], [AS_HELP_STRING([--disable-cds-archive], + [Set to disable generation of a default CDS archive in the product image @<:@enabled@:>@])]) + + AC_MSG_CHECKING([if a default CDS archive should be generated]) + if test "x$ENABLE_CDS" = "xfalse"; then + AC_MSG_RESULT([no, because CDS is disabled]) + BUILD_CDS_ARCHIVE="false" + elif test "x$COMPILE_TYPE" = "xcross"; then + AC_MSG_RESULT([no, not possible with cross compilation]) + BUILD_CDS_ARCHIVE="false" + elif test "x$enable_cds_archive" = "xyes"; then + AC_MSG_RESULT([yes, forced]) + BUILD_CDS_ARCHIVE="true" + elif test "x$enable_cds_archive" = "x"; then + AC_MSG_RESULT([yes]) + BUILD_CDS_ARCHIVE="true" + elif test "x$enable_cds_archive" = "xno"; then + AC_MSG_RESULT([no, forced]) + BUILD_CDS_ARCHIVE="false" + else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([--enable-cds_archive can only be yes/no or empty]) + fi + + AC_SUBST(BUILD_CDS_ARCHIVE) +])
--- a/make/autoconf/spec.gmk.in Mon Oct 15 10:29:06 2018 +0530 +++ b/make/autoconf/spec.gmk.in Tue Oct 16 14:26:22 2018 +0530 @@ -309,6 +309,8 @@ BUILD_MANPAGES := @BUILD_MANPAGES@ +BUILD_CDS_ARCHIVE := @BUILD_CDS_ARCHIVE@ + # The boot jdk to use. This is overridden in bootcycle-spec.gmk. Make sure to keep # it in sync. BOOT_JDK:=@BOOT_JDK@
--- a/make/common/JarArchive.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/common/JarArchive.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -235,7 +235,7 @@ # Here is the rule that creates/updates the jar file. $$($1_JAR) : $$($1_DEPENDENCIES) $$($1_MANIFEST) $$($1_VARDEPS_FILE) - $(MKDIR) -p $$($1_BIN) + $$(call MakeTargetDir) $$($1_GREP_INCLUDE_OUTPUT) $$($1_GREP_EXCLUDE_OUTPUT) # If the vardeps file is part of the newer prereq list, it means that
--- a/make/common/JavaCompilation.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/common/JavaCompilation.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -76,8 +76,8 @@ $1_COPY_$$($2_TARGET) := 1 # Now we can setup the dependency that will trigger the copying. $$($1_BIN)$$($1_MODULE_SUBDIR)$$($2_TARGET) : $2 - $(MKDIR) -p $$(@D) - $(CP) $$< $$@ + $$(call LogInfo, Copying $$(patsubst $(OUTPUTDIR)/%,%, $$@)) + $$(install-file) $(CHMOD) -f ug+w $$@ # And do not forget this target @@ -120,7 +120,8 @@ ifneq ($$($1_CLEAN_$$($2_TARGET)), 1) $1_CLEAN_$$($2_TARGET) := 1 $$($1_BIN)$$($1_MODULE_SUBDIR)$$($2_TARGET) : $2 - $(MKDIR) -p $$(@D) + $$(call LogInfo, Cleaning $$(patsubst $(OUTPUTDIR)/%,%, $$@)) + $$(call MakeTargetDir) export LC_ALL=C ; ( $(CAT) $$< && $(ECHO) "" ) \ | $(SED) -e 's/\([^\\]\):/\1\\:/g' -e 's/\([^\\]\)=/\1\\=/g' \ -e 's/\([^\\]\)!/\1\\!/g' -e 's/^[ ]*#.*/#/g' \ @@ -422,7 +423,7 @@ $1_HEADERS_ARG := -h $$($1_HEADERS).$1.tmp $$($1_HEADERS)/_the.$1_headers: $$($1_COMPILE_TARGET) - $(MKDIR) -p $$(@D) + $$(call MakeTargetDir) if [ -d "$$($1_HEADERS).$1.tmp" ]; then \ for f in `$(CD) $$($1_HEADERS).$1.tmp && $(FIND) . -type f`; do \ if [ ! -f "$$($1_HEADERS)/$$$$f" ] \
--- a/make/common/JdkNativeCompilation.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/common/JdkNativeCompilation.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -47,6 +47,29 @@ $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS_TYPE)/native/$(strip $2) \ $(TOPDIR)/src/$(strip $1)/share/native/$(strip $2))) +# Find a library +# Param 1 - module name +# Param 2 - library name +# Param 3 - optional subdir for library +FindLib = \ + $(call FindLibDirForModule, \ + $(strip $1))$(strip $3)/$(LIBRARY_PREFIX)$(strip $2)$(SHARED_LIBRARY_SUFFIX) + +# Find a static library +# Param 1 - module name +# Param 2 - library name +# Param 3 - optional subdir for library +FindStaticLib = \ + $(addprefix $(SUPPORT_OUTPUTDIR)/native/, \ + $(strip $1)$(strip $3)/$(LIBRARY_PREFIX)$(strip $2)$(STATIC_LIBRARY_SUFFIX)) + +# If only generating compile_commands.json, make these return empty to avoid +# declaring dependencies. +ifeq ($(GENERATE_COMPILE_COMMANDS_ONLY), true) + FindLib = + FindStaticLib = +endif + GetJavaHeaderDir = \ $(wildcard $(SUPPORT_OUTPUTDIR)/headers/$(strip $1))
--- a/make/common/MakeBase.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/common/MakeBase.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -842,7 +842,7 @@ # Parameter 1 is the name of the rule, and is also the name of the variable. # # Remaining parameters are named arguments. These include: -# KEYWORDS A list of valid keywords +# SINGLE_KEYWORDS A list of valid keywords with single string values # STRING_KEYWORDS A list of valid keywords, processed as string. This means # that '%20' will be replaced by ' ' to allow for multi-word strings. # @@ -856,7 +856,7 @@ $$(eval mangled_part_eval := $$(call DoubleDollar, $$(mangled_part))) \ $$(eval part := $$$$(subst ||||,$$$$(SPACE),$$$$(mangled_part_eval))) \ $$(eval $1_NO_MATCH := true) \ - $$(foreach keyword, $$($1_KEYWORDS), \ + $$(foreach keyword, $$($1_SINGLE_KEYWORDS), \ $$(eval keyword_eval := $$(call DoubleDollar, $$(keyword))) \ $$(if $$(filter $$(keyword)=%, $$(part)), \ $$(eval $(strip $1)_$$$$(keyword_eval) := $$$$(strip $$$$(patsubst $$$$(keyword_eval)=%, %, $$$$(part)))) \ @@ -871,11 +871,11 @@ ) \ ) \ $$(if $$($1_NO_MATCH), \ - $$(if $$(filter $$(part), $$($1_KEYWORDS) $$($1_STRING_KEYWORDS)), \ + $$(if $$(filter $$(part), $$($1_SINGLE_KEYWORDS) $$($1_STRING_KEYWORDS)), \ $$(info Keyword $$(part) for $1 needs to be assigned a value.) \ , \ $$(info $$(part) is not a valid keyword for $1.) \ - $$(info Valid keywords: $$($1_KEYWORDS) $$($1_STRING_KEYWORDS).) \ + $$(info Valid keywords: $$($1_SINGLE_KEYWORDS) $$($1_STRING_KEYWORDS).) \ ) \ $$(error Cannot continue) \ ) \
--- a/make/common/Modules.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/common/Modules.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -321,7 +321,7 @@ $(MODULE_DEPS_MAKEFILE): $(MODULE_INFOS) \ $(call DependOnVariable, MODULE_INFOS, $(MAKESUPPORT_OUTPUTDIR)/MODULE_INFOS.vardeps) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(RM) $@ $(foreach m, $(MODULE_INFOS), \ ( $(PRINTF) "DEPS_$(call GetModuleNameFromModuleInfo, $m) :=" && \
--- a/make/common/NativeCompilation.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/common/NativeCompilation.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -60,6 +60,29 @@ endef ################################################################################ +# Creates a recipe that creates a compile_commands.json fragment. Remove any +# occurences of FIXPATH programs from the command to show the actual invocation. +# +# Param 1: Name of file to create +# Param 2: Working directory +# Param 3: Source file +# Param 4: Compile command +# Param 5: Object name +################################################################################ +define WriteCompileCommandsFragment + $(call LogInfo, Creating compile commands fragment for $(notdir $3)) + $(call MakeDir, $(dir $1)) + $(call WriteFile,{ \ + "directory": "$(strip $2)"$(COMMA) \ + "file": "$(strip $3)"$(COMMA) \ + "command": "$(strip $(subst $(DQUOTE),\$(DQUOTE),$(subst \,\\,\ + $(subst $(FIXPATH),,$4))))"$(COMMA) \ + "output": "$(strip $5)" \ + }$(COMMA), \ + $1) +endef + +################################################################################ # Define a native toolchain configuration that can be used by # SetupNativeCompilation calls # @@ -203,6 +226,11 @@ $1_OBJ := $$($$($1_BASE)_OBJECT_DIR)/$$(call replace_with_obj_extension, \ $$($1_FILENAME)) + # Generate the corresponding compile_commands.json fragment. + $1_OBJ_JSON = $$(MAKESUPPORT_OUTPUTDIR)/compile-commands/$$(subst /,_,$$(subst \ + $$(OUTPUTDIR)/,,$$($1_OBJ))).json + $$($1_BASE)_ALL_OBJS_JSON += $$($1_OBJ_JSON) + # Only continue if this object file hasn't been processed already. This lets # the first found source file override any other with the same name. ifeq ($$(findstring $$($1_OBJ), $$($$($1_BASE)_OBJS_SO_FAR)), ) @@ -297,8 +325,15 @@ $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_OBJ).vardeps) endif - $$($1_OBJ): $$($1_SRC_FILE) $$($$($1_BASE)_COMPILE_VARDEPS_FILE) \ - $$($$($1_BASE)_EXTRA_DEPS) $$($1_VARDEPS_FILE) | $$($$($1_BASE)_BUILD_INFO) + $1_OBJ_DEPS := $$($1_SRC_FILE) $$($$($1_BASE)_COMPILE_VARDEPS_FILE) \ + $$($$($1_BASE)_EXTRA_DEPS) $$($1_VARDEPS_FILE) + $1_COMPILE_OPTIONS := $$($1_FLAGS) $(CC_OUT_OPTION)$$($1_OBJ) $$($1_SRC_FILE) + + $$($1_OBJ_JSON): $$($1_OBJ_DEPS) + $$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$($1_SRC_FILE), \ + $$($1_COMPILER) $$($1_COMPILE_OPTIONS), $$($1_OBJ)) + + $$($1_OBJ): $$($1_OBJ_DEPS) | $$($$($1_BASE)_BUILD_INFO) $$(call LogInfo, Compiling $$($1_FILENAME) (for $$($$($1_BASE)_BASENAME))) $$(call MakeDir, $$(@D)) ifneq ($(TOOLCHAIN_TYPE), microsoft) @@ -307,13 +342,11 @@ # object file in the generated deps files. Fixing it with sed. If # compiling assembly, don't try this. $$(call ExecuteWithLog, $$@, \ - $$($1_COMPILER) $$($1_FLAGS) $$($1_DEP_FLAG) $$($1_DEP).tmp \ - $(CC_OUT_OPTION)$$($1_OBJ) $$($1_SRC_FILE)) + $$($1_COMPILER) $$($1_DEP_FLAG) $$($1_DEP).tmp $$($1_COMPILE_OPTIONS)) $(SED) 's|^$$(@F):|$$@:|' $$($1_DEP).tmp > $$($1_DEP) else $$(call ExecuteWithLog, $$@, \ - $$($1_COMPILER) $$($1_FLAGS) $$($1_DEP_FLAG) $$($1_DEP) \ - $(CC_OUT_OPTION)$$($1_OBJ) $$($1_SRC_FILE)) + $$($1_COMPILER) $$($1_DEP_FLAG) $$($1_DEP) $$($1_COMPILE_OPTIONS)) endif # Create a dependency target file from the dependency file. # Solution suggested by http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ @@ -329,8 +362,7 @@ # on Windows. No need to save exit code from compilation since # pipefail is always active on Windows. $$(call ExecuteWithLog, $$@, \ - $$($1_COMPILER) $$($1_FLAGS) -showIncludes \ - $(CC_OUT_OPTION)$$($1_OBJ) $$($1_SRC_FILE)) \ + $$($1_COMPILER) -showIncludes $$($1_COMPILE_OPTIONS)) \ | $(TR) -d '\r' | $(GREP) -v -e "^Note: including file:" \ -e "^$$($1_FILENAME)$$$$" || test "$$$$?" = "1" ; \ $(ECHO) $$@: \\ > $$($1_DEP) ; \ @@ -694,17 +726,25 @@ -include $$($1_PCH_DEP) -include $$($1_PCH_DEP_TARGETS) + $1_PCH_COMMAND := $$($1_CC) $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \ + $$($1_OPT_CFLAGS) -x c++-header -c $(C_FLAG_DEPS) $$($1_PCH_DEP) + $$($1_PCH_FILE): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE) $$(call LogInfo, Generating precompiled header) $$(call MakeDir, $$(@D)) - $$(call ExecuteWithLog, $$@, \ - $$($1_CC) $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \ - $$($1_OPT_CFLAGS) \ - -x c++-header -c $(C_FLAG_DEPS) $$($1_PCH_DEP) $$< -o $$@) + $$(call ExecuteWithLog, $$@, $$($1_PCH_COMMAND) $$< -o $$@) $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_PCH_DEP) > $$($1_PCH_DEP_TARGETS) $$($1_ALL_OBJS): $$($1_PCH_FILE) + # Generate the corresponding compile_commands.json fragment. + $1_PCH_FILE_JSON := $$(MAKESUPPORT_OUTPUTDIR)/compile-commands/$$(subst /,_,$$(subst \ + $$(OUTPUTDIR)/,,$$($1_PCH_FILE))).json + $1_ALL_OBJS_JSON += $$($1_PCH_FILE_JSON) + + $$($1_PCH_FILE_JSON): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE) + $$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$<, \ + $$($1_PCH_COMMAND) $$< -o $$($1_PCH_FILE), $$($1_PCH_FILE)) endif endif endif @@ -1025,6 +1065,10 @@ endif endif endif + + ifeq ($(GENERATE_COMPILE_COMMANDS_ONLY), true) + $1 := $$($1_ALL_OBJS_JSON) + endif endef endif # _NATIVE_COMPILATION_GMK
--- a/make/common/ZipArchive.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/common/ZipArchive.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -124,8 +124,8 @@ # If zip has nothing to do, it returns 12 and would fail the build. Check for 12 # and only fail if it's not. $$($1_ZIP) : $$($1_ALL_SRCS) $$($1_EXTRA_DEPS) - $(MKDIR) -p $$(@D) - $(ECHO) Updating $$($1_NAME) + $$(call LogWarn, Updating $$($1_NAME)) + $$(call MakeTargetDir) $$(foreach s,$$($1_SRC),(cd $$s && $(ZIPEXE) -qru $$($1_ZIP_OPTIONS) $$@ . \ $$($1_ZIP_INCLUDES) $$($1_ZIP_EXCLUDES) -x \*_the.\* \ $$($1_ZIP_EXCLUDES_$$s) \
--- a/make/conf/jib-profiles.js Mon Oct 15 10:29:06 2018 +0530 +++ b/make/conf/jib-profiles.js Tue Oct 16 14:26:22 2018 +0530 @@ -522,7 +522,7 @@ .forEach(function (name) { var maketestName = name + "-testmake"; profiles[maketestName] = concatObjects(profiles[name], testmakeBase); - profiles[maketestName].default_make_targets = [ "test-make" ]; + profiles[maketestName].default_make_targets = [ "test-make", "test-compile-commands" ]; }); // Profiles for building the zero jvm variant. These are used for verification. @@ -755,16 +755,15 @@ "run-test-prebuilt": { target_os: input.build_os, target_cpu: input.build_cpu, + dependencies: [ "jtreg", "gnumake", "boot_jdk", "jib", testedProfile + ".jdk", + testedProfile + ".test" + ], src: "src.conf", - dependencies: [ "jtreg", "gnumake", "boot_jdk", "jib", testedProfile + ".jdk", - testedProfile + ".test", "src.full" - ], - work_dir: input.get("src.full", "install_path") + "/test", + make_args: [ "run-test-prebuilt", "LOG_CMDLINES=true" ], environment: { - "JT_JAVA": common.boot_jdk_home, - "PRODUCT_HOME": input.get(testedProfile + ".jdk", "home_path"), - "TEST_IMAGE_DIR": input.get(testedProfile + ".test", "home_path"), - "TEST_OUTPUT_DIR": input.src_top_dir + "BOOT_JDK": common.boot_jdk_home, + "JDK_IMAGE_DIR": input.get(testedProfile + ".jdk", "home_path"), + "TEST_IMAGE_DIR": input.get(testedProfile + ".test", "home_path") }, labels: "test" } @@ -802,13 +801,34 @@ windowsRunTestPrebuiltExtra = { dependencies: [ testedProfile + ".jdk_symbols" ], environment: { - "PRODUCT_SYMBOLS_HOME": input.get(testedProfile + ".jdk_symbols", "home_path"), + "SYMBOLS_IMAGE_DIR": input.get(testedProfile + ".jdk_symbols", "home_path"), } }; profiles["run-test-prebuilt"] = concatObjects(profiles["run-test-prebuilt"], windowsRunTestPrebuiltExtra); } + // The profile run-test-prebuilt defines src.conf as the src bundle. When + // running in Mach 5, this reduces the time it takes to populate the + // considerably. But with just src.conf, we cannot actually run any tests, + // so if running from a workspace with just src.conf in it, we need to also + // get src.full as a dependency, and define the work_dir (where make gets + // run) to be in the src.full install path. By running in the install path, + // the same cached installation of the full src can be reused for multiple + // test tasks. Care must however be taken not to polute that work dir by + // setting the appropriate make variables to control output directories. + // + // Use the existance of the top level README as indication of if this is + // the full source or just src.conf. + if (!new java.io.File(__DIR__, "../../README").exists()) { + var runTestPrebuiltSrcFullExtra = { + dependencies: "src.full", + work_dir: input.get("src.full", "install_path"), + } + profiles["run-test-prebuilt"] = concatObjects(profiles["run-test-prebuilt"], + runTestPrebuiltSrcFullExtra); + } + // Generate the missing platform attributes profiles = generatePlatformAttributes(profiles); profiles = generateDefaultMakeTargetsConfigureArg(common, profiles); @@ -835,7 +855,7 @@ : "gcc7.3.0-Fedora27+1.0"), linux_arm: (input.profile != null && input.profile.indexOf("hflt") >= 0 ? "gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux+1.0" - : (input.profile.indexOf("arm32") >= 0 + : (input.profile != null && input.profile.indexOf("arm32") >= 0 ? "gcc7.3.0-Fedora27+1.0" : "arm-linaro-4.7+1.0" )
--- a/make/copy/Copy-java.base.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/copy/Copy-java.base.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -128,7 +128,7 @@ POLICY_SRC_LIST := $(POLICY_SRC) $(POLICY_DST): $(POLICY_SRC_LIST) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(RM) $@ $@.tmp $(foreach f,$(POLICY_SRC_LIST),$(CAT) $(f) >> $@.tmp;) $(MV) $@.tmp $@ @@ -153,7 +153,7 @@ endif $(DEF_POLICY_DST): $(DEF_POLICY_SRC_LIST) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(RM) $@ $@.tmp $(foreach f,$(DEF_POLICY_SRC_LIST),$(CAT) $(f) >> $@.tmp;) $(MV) $@.tmp $@
--- a/make/data/jdwp/jdwp.spec Mon Oct 15 10:29:06 2018 +0530 +++ b/make/data/jdwp/jdwp.spec Tue Oct 16 14:26:22 2018 +0530 @@ -2185,7 +2185,7 @@ "in this thread group. Threads and thread groups in child " "thread groups are not included. " "A thread is alive if it has been started and has not yet been stopped. " - "See <a href=../../../api/java/lang/ThreadGroup.html>java.lang.ThreadGroup </a> + "See <a href=../../api/java.base/java/lang/ThreadGroup.html>java.lang.ThreadGroup </a> "for information about active ThreadGroups. (Out (threadGroupObject group "The thread group object ID. ")
--- a/make/data/unicodedata/UnicodeData.txt Mon Oct 15 10:29:06 2018 +0530 +++ b/make/data/unicodedata/UnicodeData.txt Tue Oct 16 14:26:22 2018 +0530 @@ -11729,6 +11729,7 @@ 32FC;CIRCLED KATAKANA WI;So;0;L;<circle> 30F0;;;;N;;;;; 32FD;CIRCLED KATAKANA WE;So;0;L;<circle> 30F1;;;;N;;;;; 32FE;CIRCLED KATAKANA WO;So;0;L;<circle> 30F2;;;;N;;;;; +32FF;SQUARE ERA NAME NEWERA;So;0;L;<square> 5143 53F7;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME NEWERA;;;; 3300;SQUARE APAATO;So;0;L;<square> 30A2 30D1 30FC 30C8;;;;N;SQUARED APAATO;;;; 3301;SQUARE ARUHUA;So;0;L;<square> 30A2 30EB 30D5 30A1;;;;N;SQUARED ARUHUA;;;; 3302;SQUARE ANPEA;So;0;L;<square> 30A2 30F3 30DA 30A2;;;;N;SQUARED ANPEA;;;;
--- a/make/gendata/GendataFontConfig.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/gendata/GendataFontConfig.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -38,7 +38,7 @@ $(GENDATA_FONT_CONFIG_DST)/%.bfc: \ $(GENDATA_FONT_CONFIG_DATA_DIR)/$(OPENJDK_TARGET_OS).%.properties \ $(BUILD_TOOLS_JDK) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(RM) $@ $(TOOL_COMPILEFONTCONFIG) $< $@ $(CHMOD) 444 $@
--- a/make/gendata/GendataHtml32dtd.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/gendata/GendataHtml32dtd.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -28,7 +28,7 @@ HTML32DTD = $(JDK_OUTPUTDIR)/modules/java.desktop/javax/swing/text/html/parser/html32.bdtd $(HTML32DTD): $(BUILD_TOOLS_JDK) $(call LogInfo, Generating HTML DTD file) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(RM) $@ ($(TOOL_DTDBUILDER) html32 > $@) || exit 1
--- a/make/gendata/GendataTZDB.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/gendata/GendataTZDB.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -35,8 +35,8 @@ GENDATA_TZDB_DAT := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE)/tzdb.dat $(GENDATA_TZDB_DAT): $(TZDATA_TZFILES) + $(call MakeTargetDir) $(RM) $(GENDATA_TZDB_DAT) - $(MKDIR) -p $(@D) $(TOOL_TZDB) -srcdir $(TZDATA_DIR) -dstfile $(GENDATA_TZDB_DAT) $(TZDATA_TZFILE) TARGETS += $(GENDATA_TZDB_DAT)
--- a/make/gensrc/GensrcCLDR.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/gensrc/GensrcCLDR.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -50,7 +50,7 @@ $(wildcard $(CLDRSRCDIR)/supplemental/*.xml) \ $(ZONENAME_TEMPLATE) \ $(BUILD_TOOLS_JDK) - $(MKDIR) -p $(GENSRC_BASEDIR) + $(call MakeDir, $(GENSRC_BASEDIR)) $(TOOL_CLDRCONVERTER) -base $(CLDRSRCDIR) \ -baselocales $(CLDR_BASE_LOCALES) \ -o $(GENSRC_BASEDIR) \ @@ -62,7 +62,7 @@ $(wildcard $(CLDRSRCDIR)/main/*.xml) \ $(wildcard $(CLDRSRCDIR)/supplemental/*.xml) \ $(BUILD_TOOLS_JDK) - $(MKDIR) -p $(GENSRC_DIR) + $(call MakeDir, $(GENSRC_DIR)) $(TOOL_CLDRCONVERTER) -base $(CLDRSRCDIR) \ -baselocales $(CLDR_BASE_LOCALES) \ -o $(GENSRC_DIR)
--- a/make/gensrc/GensrcCharsetCoder.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/gensrc/GensrcCharsetCoder.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -34,8 +34,8 @@ ################################################################################ $(GENSRC_CHARSETCODER_DST)/CharsetDecoder.java: $(GENSRC_CHARSETCODER_TEMPLATE) - $(MKDIR) -p $(@D) - -$(RM) $@.tmp + $(call MakeTargetDir) + $(RM) $@.tmp $(TOOL_SPP) < $< >$@.tmp \ -Kdecoder \ -DA='A' \ @@ -69,8 +69,8 @@ ################################################################################ $(GENSRC_CHARSETCODER_DST)/CharsetEncoder.java: $(GENSRC_CHARSETCODER_TEMPLATE) - $(MKDIR) -p $(@D) - -$(RM) $@.tmp + $(call MakeTargetDir) + $(RM) $@.tmp $(TOOL_SPP) < $< >$@.tmp \ -Kencoder \ -DA='An' \
--- a/make/gensrc/GensrcCommonLangtools.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/gensrc/GensrcCommonLangtools.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -49,7 +49,7 @@ # root. define SetupVersionProperties $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/$$(strip $2): - $(MKDIR) -p $$(@D) + $$(call MakeTargetDir) $(PRINTF) "jdk=$(VERSION_NUMBER)\nfull=$(VERSION_STRING)\nrelease=$(VERSION_SHORT)\n" \ > $$@ @@ -92,7 +92,7 @@ # Now setup the rule for the generation of the resource bundles. $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the_props: $$(PROPSOURCES) - $(MKDIR) -p $$(@D) $$(PROPDIRS) + $$(call MakeDir, $$(@D) $$(PROPDIRS)) $(FIND) $$(@D) -name "*.java" -a ! -name "*Properties.java" $(FIND_DELETE) $(ECHO) Compiling $$(words $$(PROPSOURCES)) properties into resource bundles for $(MODULE) $(TOOL_COMPILEPROPS_CMD) $$(PROPCMDLINE) @@ -122,7 +122,7 @@ # Now setup the rule for the generation of the resource bundles. $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the_parsed_props: $$(PARSEPROPSOURCES) - $(MKDIR) -p $$(@D) $$(PARSEPROPDIRS) + $$(call MakeDir, $$(@D) $$(PARSEPROPDIRS)) $(FIND) $$(@D) -name "*Properties.java" $(FIND_DELETE) $(ECHO) Parsing $$(words $$(PARSEPROPSOURCES)) properties into enum-like class for $(MODULE) $(TOOL_PARSEPROPS_CMD) $$(PARSEPROPCMDLINE)
--- a/make/gensrc/GensrcLocaleData.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/gensrc/GensrcLocaleData.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -131,7 +131,7 @@ $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/BaseLocaleDataMetaInfo.java: \ $(TOPDIR)/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template $(call LogInfo, Creating sun/util/locale/provider/BaseLocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" \ > $(SUPPORT_OUTPUTDIR)/gensrc/java.base/_the.locale_resources $(SED) $(SED_BASEARGS) $< > $@ @@ -139,7 +139,7 @@ $(SUPPORT_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonBaseLocaleDataMetaInfo.java: \ $(TOPDIR)/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template $(call LogInfo, Creating sun/util/resources/provider/NonBaseLocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" \ > $(SUPPORT_OUTPUTDIR)/gensrc/jdk.localedata/_the.locale_resources $(SED) $(SED_NONBASEARGS) $< > $@
--- a/make/gensrc/GensrcModuleLoaderMap.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/gensrc/GensrcModuleLoaderMap.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -46,7 +46,7 @@ $(SUPPORT_OUTPUTDIR)/gensrc/java.base/jdk/internal/module/ModuleLoaderMap.java: \ $(TOPDIR)/src/java.base/share/classes/jdk/internal/module/ModuleLoaderMap.java \ $(VARDEPS_FILE) $(BUILD_TOOLS_JDK) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(RM) $@ $@.tmp $(TOOL_GENCLASSLOADERMAP) -boot $(BOOT_MODULES_LIST) \ -platform $(PLATFORM_MODULES_LIST) -o $@.tmp $<
--- a/make/gensrc/GensrcProperties.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/gensrc/GensrcProperties.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -34,7 +34,7 @@ $$(subst _zh_TW,_zh_HK, $2)) $$($1_$2_TARGET): $2 - $(MKDIR) -p $$(@D) + $$(call MakeTargetDir) $(CAT) $$< | $(SED) -e '/class/s/_zh_TW/_zh_HK/' > $$@ $1 += $$($1_$2_TARGET) @@ -105,8 +105,8 @@ # Now setup the rule for the generation of the resource bundles. $$($1_TARGET): $$($1_SRC_FILES) $$($1_JAVAS) $(BUILD_TOOLS_JDK) - $(MKDIR) -p $$(@D) $$($1_DIRS) - $(ECHO) Compiling $$(words $$($1_SRC_FILES)) properties into resource bundles for $(MODULE) + $$(call LogWarn, Compiling $$(words $$($1_SRC_FILES)) properties into resource bundles for $(MODULE)) + $$(call MakeDir, $$(@D) $$($1_DIRS)) $$(eval $$(call ListPathsSafely, $1_CMDLINE, $$($1_CMDLINE_FILE))) $(TOOL_COMPILEPROPERTIES) -quiet @$$($1_CMDLINE_FILE) $(TOUCH) $$@
--- a/make/gensrc/GensrcSwing.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/gensrc/GensrcSwing.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -32,7 +32,7 @@ $(SUPPORT_OUTPUTDIR)/gensrc/java.desktop/_the.generated_nimbus: $(NIMBUS_SKIN_FILE) $(BUILD_TOOLS_JDK) $(call LogInfo, Generating Nimbus source files) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(TOOL_GENERATENIMBUS) $(LOG_DEBUG) \ -skinFile $(NIMBUS_SKIN_FILE) -buildDir $(SUPPORT_OUTPUTDIR)/gensrc/java.desktop \ -packagePrefix $(NIMBUS_PACKAGE).nimbus -lafName Nimbus
--- a/make/hotspot/lib/CompileJvm.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/hotspot/lib/CompileJvm.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -92,7 +92,7 @@ DISABLED_WARNINGS_gcc += return-type switch endif -DISABLED_WARNINGS_clang := tautological-compare deprecated-declarations \ +DISABLED_WARNINGS_clang := tautological-compare \ undefined-var-template sometimes-uninitialized unknown-pragmas \ delete-non-virtual-dtor missing-braces char-subscripts \ ignored-qualifiers missing-field-initializers mismatched-tags @@ -214,15 +214,17 @@ $(VM_VERSION_OBJ): $(filter-out $(VM_VERSION_OBJ) $(JVM_MAPFILE), \ $(BUILD_LIBJVM_TARGET_DEPS)) -ifeq ($(OPENJDK_TARGET_OS), windows) - # It doesn't matter which jvm.lib file gets exported, but we need - # to pick just one. - ifeq ($(JVM_VARIANT), $(JVM_VARIANT_MAIN)) - $(eval $(call SetupCopyFiles, COPY_JVM_LIB, \ - DEST := $(LIB_OUTPUTDIR), \ - FILES :=$(BUILD_LIBJVM_IMPORT_LIBRARY), \ - )) - TARGETS += $(COPY_JVM_LIB) +ifneq ($(GENERATE_COMPILE_COMMANDS_ONLY), true) + ifeq ($(OPENJDK_TARGET_OS), windows) + # It doesn't matter which jvm.lib file gets exported, but we need + # to pick just one. + ifeq ($(JVM_VARIANT), $(JVM_VARIANT_MAIN)) + $(eval $(call SetupCopyFiles, COPY_JVM_LIB, \ + DEST := $(LIB_OUTPUTDIR), \ + FILES :=$(BUILD_LIBJVM_IMPORT_LIBRARY), \ + )) + TARGETS += $(COPY_JVM_LIB) + endif endif endif @@ -261,44 +263,46 @@ # Search the output for the operator(s) of interest, to see where they are # referenced. -ifneq ($(filter $(TOOLCHAIN_TYPE), gcc clang solstudio), ) +ifneq ($(GENERATE_COMPILE_COMMANDS_ONLY), true) + ifneq ($(filter $(TOOLCHAIN_TYPE), gcc clang solstudio), ) - DEMANGLED_REGEXP := [^:]operator (new|delete) + DEMANGLED_REGEXP := [^:]operator (new|delete) - # Running c++filt to find offending symbols in all files is too expensive, - # especially on Solaris, so use mangled names when looking for symbols. - # Save the demangling for when something is actually found. - ifeq ($(TOOLCHAIN_TYPE), solstudio) - MANGLED_SYMS := \ - __1c2n6FL_pv_ \ - __1c2N6FL_pv_ \ - __1c2k6Fpv_v_ \ - __1c2K6Fpv_v_ \ - # - UNDEF_PATTERN := UNDEF - else - MANGLED_SYMS := \ - _ZdaPv \ - _ZdlPv \ - _Znam \ - _Znwm \ - # - UNDEF_PATTERN := ' U ' + # Running c++filt to find offending symbols in all files is too expensive, + # especially on Solaris, so use mangled names when looking for symbols. + # Save the demangling for when something is actually found. + ifeq ($(TOOLCHAIN_TYPE), solstudio) + MANGLED_SYMS := \ + __1c2n6FL_pv_ \ + __1c2N6FL_pv_ \ + __1c2k6Fpv_v_ \ + __1c2K6Fpv_v_ \ + # + UNDEF_PATTERN := UNDEF + else + MANGLED_SYMS := \ + _ZdaPv \ + _ZdlPv \ + _Znam \ + _Znwm \ + # + UNDEF_PATTERN := ' U ' + endif + + define SetupOperatorNewDeleteCheck + $1.op_check: $1 + if [ -n "`$(NM) $$< | $(GREP) $(addprefix -e , $(MANGLED_SYMS)) \ + | $(GREP) $(UNDEF_PATTERN)`" ]; then \ + $(ECHO) "$$<: Error: Use of global operators new and delete is not allowed in Hotspot:"; \ + $(NM) $$< | $(CXXFILT) | $(EGREP) '$(DEMANGLED_REGEXP)' | $(GREP) $(UNDEF_PATTERN); \ + $(ECHO) "See: $(TOPDIR)/make/hotspot/lib/CompileJvm.gmk"; \ + exit 1; \ + fi + $(TOUCH) $$@ + + TARGETS += $1.op_check + endef + + $(foreach o, $(BUILD_LIBJVM_ALL_OBJS), $(eval $(call SetupOperatorNewDeleteCheck,$o))) endif - - define SetupOperatorNewDeleteCheck - $1.op_check: $1 - if [ -n "`$(NM) $$< | $(GREP) $(addprefix -e , $(MANGLED_SYMS)) \ - | $(GREP) $(UNDEF_PATTERN)`" ]; then \ - $(ECHO) "$$<: Error: Use of global operators new and delete is not allowed in Hotspot:"; \ - $(NM) $$< | $(CXXFILT) | $(EGREP) '$(DEMANGLED_REGEXP)' | $(GREP) $(UNDEF_PATTERN); \ - $(ECHO) "See: $(TOPDIR)/make/hotspot/lib/CompileJvm.gmk"; \ - exit 1; \ - fi - $(TOUCH) $$@ - - TARGETS += $1.op_check - endef - - $(foreach o, $(BUILD_LIBJVM_ALL_OBJS), $(eval $(call SetupOperatorNewDeleteCheck,$o))) endif
--- a/make/launcher/Launcher-java.base.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/launcher/Launcher-java.base.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -45,7 +45,7 @@ )) $(SUPPORT_OUTPUTDIR)/modules_cmds/java.base/java$(EXE_SUFFIX): $(BUILD_LAUNCHER_java) - $(MKDIR) -p $(@D) + $(call MakeTargetDir) $(RM) $@ $(CP) $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/java_objs/java$(EXE_SUFFIX) $@
--- a/make/launcher/Launcher-jdk.pack.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/launcher/Launcher-jdk.pack.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -91,21 +91,15 @@ CFLAGS_solaris := -KPIC, \ CFLAGS_macosx := -fPIC, \ DISABLED_WARNINGS_clang := format-nonliteral, \ - LDFLAGS := $(UNPACKEXE_ZIPOBJS) \ - $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \ + LDFLAGS := $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := $(UNPACKEXE_LIBS) $(LIBCXX), \ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpackexe, \ MANIFEST := $(TOPDIR)/src/jdk.pack/windows/native/unpack200/unpack200_proto.exe.manifest, \ MANIFEST_VERSION := $(VERSION_NUMBER_FOUR_POSITIONS), \ + EXTRA_OBJECT_FILES := $(UNPACKEXE_ZIPOBJS) \ )) -ifneq ($(USE_EXTERNAL_LIBZ), true) - - $(BUILD_UNPACKEXE): $(UNPACKEXE_ZIPOBJS) - -endif - TARGETS += $(BUILD_UNPACKEXE) ################################################################################
--- a/make/launcher/LauncherCommon.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/launcher/LauncherCommon.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -135,7 +135,7 @@ $1_LIBS += -lz endif - $1_WINDOWS_JLI_LIB := $(SUPPORT_OUTPUTDIR)/native/java.base/libjli/jli.lib + $1_WINDOWS_JLI_LIB := $(call FindStaticLib, java.base, jli, /libjli) $$(eval $$(call SetupJdkExecutable, BUILD_LAUNCHER_$1, \ NAME := $1, \ @@ -181,11 +181,11 @@ TARGETS += $$($1) ifeq ($(OPENJDK_TARGET_OS), aix) - $$(BUILD_LAUNCHER_$1): $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a + $$(BUILD_LAUNCHER_$1): $(call FindStaticLib, java.base, jli_static) endif ifeq ($(OPENJDK_TARGET_OS), windows) - $$(BUILD_LAUNCHER_$1): $(SUPPORT_OUTPUTDIR)/native/java.base/libjava/java.lib \ + $$(BUILD_LAUNCHER_$1): $(call FindStaticLib, java.base, java, /libjava) \ $$($1_WINDOWS_JLI_LIB) endif endef
--- a/make/lib/Awt2dLibraries.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/lib/Awt2dLibraries.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -739,11 +739,11 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) $(BUILD_LIBJAWT): $(BUILD_LIBAWT_XAWT) else - $(BUILD_LIBJAWT): $(INSTALL_LIBRARIES_HERE)/$(LIBRARY_PREFIX)awt_headless$(SHARED_LIBRARY_SUFFIX) + $(BUILD_LIBJAWT): $(call FindLib, $(MODULE), awt_headless) endif ifeq ($(OPENJDK_TARGET_OS), macosx) - $(BUILD_LIBJAWT): $(INSTALL_LIBRARIES_HERE)/$(LIBRARY_PREFIX)awt_lwawt$(SHARED_LIBRARY_SUFFIX) + $(BUILD_LIBJAWT): $(call FindLib, $(MODULE), awt_lwawt) endif endif # OPENJDK_TARGET_OS
--- a/make/lib/Lib-jdk.accessibility.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/lib/Lib-jdk.accessibility.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -55,7 +55,7 @@ VERSIONINFO_RESOURCE := $(ROOT_SRCDIR)/common/AccessBridgeStatusWindow.rc, \ ) - $$(BUILD_JAVAACCESSBRIDGE$1): $(SUPPORT_OUTPUTDIR)/native/java.desktop/libjawt/jawt.lib + $$(BUILD_JAVAACCESSBRIDGE$1): $(call FindStaticLib, java.desktop, jawt, /libjawt) TARGETS += $$(BUILD_JAVAACCESSBRIDGE$1) endef
--- a/make/lib/Lib-jdk.hotspot.agent.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/lib/Lib-jdk.hotspot.agent.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -44,7 +44,12 @@ ifeq ($(OPENJDK_TARGET_CPU), x86_64) SA_CXXFLAGS := -DWIN64 else - SA_CXXFLAGS := -RTC1 + # Only add /RTC1 flag for debug builds as it's + # incompatible with release type builds. See + # https://msdn.microsoft.com/en-us/library/8wtf2dfz.aspx + ifeq ($(DEBUG_LEVEL),slowdebug) + SA_CXXFLAGS := -RTC1 + endif endif endif
--- a/make/lib/LibCommon.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/lib/LibCommon.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -61,24 +61,6 @@ endif endif -################################################################################ -# Find a library -# Param 1 - module name -# Param 2 - library name -# Param 3 - optional subdir for library -FindLib = \ - $(call FindLibDirForModule, \ - $(strip $1))$(strip $3)/$(LIBRARY_PREFIX)$(strip $2)$(SHARED_LIBRARY_SUFFIX) - -################################################################################ -# Find a static library -# Param 1 - module name -# Param 2 - library name -# Param 3 - optional subdir for library -FindStaticLib = \ - $(addprefix $(SUPPORT_OUTPUTDIR)/native/, \ - $(strip $1)$(strip $3)/$(LIBRARY_PREFIX)$(strip $2)$(STATIC_LIBRARY_SUFFIX)) - # Put the libraries here. INSTALL_LIBRARIES_HERE := $(call FindLibDirForModule, $(MODULE))
--- a/make/rmic/Rmic-java.management.rmi.gmk Mon Oct 15 10:29:06 2018 +0530 +++ b/make/rmic/Rmic-java.management.rmi.gmk Tue Oct 16 14:26:22 2018 +0530 @@ -51,7 +51,7 @@ $(foreach src, $(classfiles), \ $(eval target := $(patsubst $(RMIC_GENSRC_DIR)/%, \ $(STUB_CLASSES_DIR)/%, $(src))) \ - $(MKDIR) -p $(dir $(target)) ; \ + $(call MakeDir, $(dir $(target))) \ $(MV) $(src) $(target) $(NEWLINE)) $(TOUCH) $@
--- a/make/scripts/compare.sh Mon Oct 15 10:29:06 2018 +0530 +++ b/make/scripts/compare.sh Tue Oct 16 14:26:22 2018 +0530 @@ -385,6 +385,7 @@ ! -name "JavaUpdater" ! -name "JavaWSApplicationStub" \ ! -name "jspawnhelper" ! -name "JavawsLauncher" ! -name "*.a" \ ! -name "finish_installation" ! -name "Sparkle" ! -name "*.tar.gz" \ + ! -name "classes.jsa" \ | $GREP -v "./bin/" | $SORT | $FILTER) echo Other files with binary differences...
--- a/src/hotspot/cpu/ppc/c2_globals_ppc.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/cpu/ppc/c2_globals_ppc.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -62,7 +62,7 @@ define_pd_global(bool, UseCISCSpill, false); define_pd_global(bool, OptoBundling, false); define_pd_global(bool, OptoRegScheduling, false); -define_pd_global(bool, SuperWordLoopUnrollAnalysis, false); +define_pd_global(bool, SuperWordLoopUnrollAnalysis, true); // GL: // Detected a problem with unscaled compressed oops and // narrow_oop_use_complex_address() == false.
--- a/src/hotspot/cpu/s390/frame_s390.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/cpu/s390/frame_s390.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -53,14 +53,135 @@ bool frame::safe_for_sender(JavaThread *thread) { bool safe = false; - address cursp = (address)sp(); - address curfp = (address)fp(); - if ((cursp != NULL && curfp != NULL && - (cursp <= thread->stack_base() && cursp >= thread->stack_base() - thread->stack_size())) && - (curfp <= thread->stack_base() && curfp >= thread->stack_base() - thread->stack_size())) { - safe = true; + address sp = (address)_sp; + 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; + + // 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) { + return false; } - return safe; + + // Unextended sp must be within the stack + bool unextended_sp_safe = (unextended_sp < thread->stack_base()); + + if (!unextended_sp_safe) { + return false; + } + + // An fp must be within the stack and above (but not equal) sp. + bool fp_safe = (fp <= thread->stack_base()) && (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); + + // 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 + // toward eliminating issues when we get in frame construction code + + if (_cb != NULL ) { + // Entry frame checks + if (is_entry_frame()) { + // An entry frame must have a valid fp. + return fp_safe && is_entry_frame_valid(thread); + } + + // Now check if the frame is complete and the test is + // reliable. Unfortunately we can only check frame completeness for + // runtime stubs. Other generic buffer blobs are more + // problematic so we just assume they are OK. Adapter blobs never have a + // complete frame and are never OK. nmethods should be OK on s390. + if (!_cb->is_frame_complete_at(_pc)) { + if (_cb->is_adapter_blob() || _cb->is_runtime_stub()) { + return false; + } + } + + // Could just be some random pointer within the codeBlob. + if (!_cb->code_contains(_pc)) { + return false; + } + + if (is_interpreted_frame() && !fp_interp_safe) { + return false; + } + + z_abi_160* sender_abi = (z_abi_160*) fp; + intptr_t* sender_sp = (intptr_t*) sender_abi->callers_sp; + address sender_pc = (address) sender_abi->return_pc; + + // We must always be able to find a recognizable pc. + CodeBlob* sender_blob = CodeCache::find_blob_unsafe(sender_pc); + if (sender_blob == NULL) { + return false; + } + + // Could be a zombie method + if (sender_blob->is_zombie() || sender_blob->is_unloaded()) { + return false; + } + + // It should be safe to construct the sender though it might not be valid. + + frame sender(sender_sp, sender_pc); + + // Do we have a valid fp? + address sender_fp = (address) sender.fp(); + + // 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) { + return false; + } + + // If the potential sender is the interpreter then we can do some more checking. + if (Interpreter::contains(sender_pc)) { + return sender.is_interpreted_frame_valid(thread); + } + + // Could just be some random pointer within the codeBlob. + if (!sender.cb()->code_contains(sender_pc)) { + return false; + } + + // We should never be able to see an adapter if the current frame is something from code cache. + if (sender_blob->is_adapter_blob()) { + return false; + } + + if (sender.is_entry_frame()) { + return sender.is_entry_frame_valid(thread); + } + + // Frame size is always greater than zero. If the sender frame size is zero or less, + // something is really weird and we better give up. + if (sender_blob->frame_size() <= 0) { + return false; + } + + return true; + } + + // Must be native-compiled frame. Since sender will try and use fp to find + // linkages it must be safe + + if (!fp_safe) { + return false; + } + + return true; } bool frame::is_interpreted_frame() const {
--- a/src/hotspot/cpu/s390/frame_s390.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/cpu/s390/frame_s390.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -491,9 +491,12 @@ static int interpreter_frame_interpreterstate_size_in_bytes(); static int interpreter_frame_monitor_size_in_bytes(); + + // template interpreter state + inline z_ijava_state* ijava_state_unchecked() const; + private: - // template interpreter state inline z_ijava_state* ijava_state() const; // Where z_ijava_state.monitors is saved.
--- a/src/hotspot/cpu/s390/frame_s390.inline.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/cpu/s390/frame_s390.inline.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -77,8 +77,13 @@ #endif // template interpreter state +inline frame::z_ijava_state* frame::ijava_state_unchecked() const { + z_ijava_state* state = (z_ijava_state*) ((uintptr_t)fp() - z_ijava_state_size); + return state; +} + inline frame::z_ijava_state* frame::ijava_state() const { - z_ijava_state* state = (z_ijava_state*) ((uintptr_t)fp() - z_ijava_state_size); + z_ijava_state* state = ijava_state_unchecked(); assert(state->magic == (intptr_t) frame::z_istate_magic_number, "wrong z_ijava_state in interpreter frame (no magic found)"); return state;
--- a/src/hotspot/cpu/sparc/nativeInst_sparc.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/cpu/sparc/nativeInst_sparc.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -205,9 +205,9 @@ uint idx; int offsets[] = { 0x0, - 0xfffffff0, - 0x7ffffff0, - 0x80000000, + (int)0xfffffff0, + (int)0x7ffffff0, + (int)0x80000000, 0x20, 0x4000, }; @@ -361,9 +361,9 @@ uint idx; int offsets[] = { 0x0, - 0x7fffffff, - 0x80000000, - 0xffffffff, + (int)0x7fffffff, + (int)0x80000000, + (int)0xffffffff, 0x20, 4096, 4097, @@ -534,9 +534,9 @@ uint idx; int offsets[] = { 0x0, - 0x7fffffff, - 0x80000000, - 0xffffffff, + (int)0x7fffffff, + (int)0x80000000, + (int)0xffffffff, 0x20, 4096, 4097, @@ -630,9 +630,9 @@ uint idx1; int offsets[] = { 0x0, - 0xffffffff, - 0x7fffffff, - 0x80000000, + (int)0xffffffff, + (int)0x7fffffff, + (int)0x80000000, 4096, 4097, 0x20, @@ -751,9 +751,9 @@ uint idx; int offsets[] = { 0x0, - 0xffffffff, - 0x7fffffff, - 0x80000000, + (int)0xffffffff, + (int)0x7fffffff, + (int)0x80000000, 4096, 4097, 0x20,
--- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -688,7 +688,7 @@ } LIR_Opr result = new_register(T_INT); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), - result, type); + result, T_INT); return result; }
--- a/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -35,9 +35,6 @@ #define BUFFER_SIZE 30*wordSize -// Instead of issuing lfence for LoadLoad barrier, we create data dependency -// between loads, which is more efficient than lfence. - // Common register usage: // rax/xmm0: result // c_rarg0: jni env @@ -77,12 +74,6 @@ __ mov (robj, c_rarg1); __ testb (rcounter, 1); __ jcc (Assembler::notZero, slow); - - __ xorptr(robj, rcounter); - __ xorptr(robj, rcounter); // obj, since - // robj ^ rcounter ^ rcounter == robj - // robj is data dependent on rcounter. - __ mov (roffset, c_rarg2); __ shrptr(roffset, 2); // offset @@ -103,12 +94,7 @@ default: ShouldNotReachHere(); } - // create data dependency on rax - __ lea(rcounter_addr, counter); - __ xorptr(rcounter_addr, rax); - __ xorptr(rcounter_addr, rax); - __ cmpl (rcounter, Address(rcounter_addr, 0)); - + __ cmp32 (rcounter, counter); __ jcc (Assembler::notEqual, slow); __ ret (0); @@ -178,11 +164,6 @@ __ testb (rcounter, 1); __ jcc (Assembler::notZero, slow); - __ xorptr(robj, rcounter); - __ xorptr(robj, rcounter); // obj, since - // robj ^ rcounter ^ rcounter == robj - // robj is data dependent on rcounter. - // Both robj and rtmp are clobbered by try_resolve_jobject_in_native. BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); bs->try_resolve_jobject_in_native(masm, /* jni_env */ c_rarg0, robj, rtmp, slow); @@ -198,13 +179,7 @@ case T_DOUBLE: __ movdbl (xmm0, Address(robj, roffset, Address::times_1)); break; default: ShouldNotReachHere(); } - - __ lea(rcounter_addr, counter); - __ movdq (rax, xmm0); - // counter address is data dependent on xmm0. - __ xorptr(rcounter_addr, rax); - __ xorptr(rcounter_addr, rax); - __ cmpl (rcounter, Address(rcounter_addr, 0)); + __ cmp32 (rcounter, counter); __ jcc (Assembler::notEqual, slow); __ ret (0);
--- a/src/hotspot/cpu/x86/stubRoutines_x86.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/cpu/x86/stubRoutines_x86.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -33,7 +33,7 @@ enum platform_dependent_constants { code_size1 = 20000 LP64_ONLY(+10000), // simply increase if too small (assembler will crash if too small) - code_size2 = 33800 LP64_ONLY(+10000) // simply increase if too small (assembler will crash if too small) + code_size2 = 35300 LP64_ONLY(+10000) // simply increase if too small (assembler will crash if too small) }; class x86 {
--- a/src/hotspot/os/aix/os_aix.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/os/aix/os_aix.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -4259,7 +4259,7 @@ // or -1 on failure (e.g. can't fork a new process). // Unlike system(), this function can be called from signal handler. It // doesn't block SIGINT et al. -int os::fork_and_exec(char* cmd) { +int os::fork_and_exec(char* cmd, bool use_vfork_if_available) { char * argv[4] = {"sh", "-c", cmd, NULL}; pid_t pid = fork();
--- a/src/hotspot/os/bsd/os_bsd.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/os/bsd/os_bsd.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -3238,16 +3238,6 @@ Bsd::clock_init(); initial_time_count = javaTimeNanos(); -#ifdef __APPLE__ - // XXXDARWIN - // Work around the unaligned VM callbacks in hotspot's - // sharedRuntime. The callbacks don't use SSE2 instructions, and work on - // Linux, Solaris, and FreeBSD. On Mac OS X, dyld (rightly so) enforces - // alignment when doing symbol lookup. To work around this, we force early - // binding of all symbols now, thus binding when alignment is known-good. - _dyld_bind_fully_image_containing_address((const void *) &os::init); -#endif - os::Posix::init(); } @@ -3795,7 +3785,7 @@ // or -1 on failure (e.g. can't fork a new process). // Unlike system(), this function can be called from signal handler. It // doesn't block SIGINT et al. -int os::fork_and_exec(char* cmd) { +int os::fork_and_exec(char* cmd, bool use_vfork_if_available) { const char * argv[4] = {"sh", "-c", cmd, NULL}; // fork() in BsdThreads/NPTL is not async-safe. It needs to run
--- a/src/hotspot/os/linux/os_linux.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/os/linux/os_linux.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -5676,10 +5676,16 @@ // or -1 on failure (e.g. can't fork a new process). // Unlike system(), this function can be called from signal handler. It // doesn't block SIGINT et al. -int os::fork_and_exec(char* cmd) { +int os::fork_and_exec(char* cmd, bool use_vfork_if_available) { const char * argv[4] = {"sh", "-c", cmd, NULL}; - pid_t pid = fork(); + pid_t pid ; + + if (use_vfork_if_available) { + pid = vfork(); + } else { + pid = fork(); + } if (pid < 0) { // fork failed
--- a/src/hotspot/os/solaris/os_solaris.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/os/solaris/os_solaris.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -1567,11 +1567,11 @@ } typedef struct { - Elf32_Half code; // Actual value as defined in elf.h - Elf32_Half compat_class; // Compatibility of archs at VM's sense - char elf_class; // 32 or 64 bit - char endianess; // MSB or LSB - char* name; // String representation + Elf32_Half code; // Actual value as defined in elf.h + Elf32_Half compat_class; // Compatibility of archs at VM's sense + unsigned char elf_class; // 32 or 64 bit + unsigned char endianess; // MSB or LSB + char* name; // String representation } arch_t; static const arch_t arch_array[]={ @@ -5252,7 +5252,7 @@ // or -1 on failure (e.g. can't fork a new process). // Unlike system(), this function can be called from signal handler. It // doesn't block SIGINT et al. -int os::fork_and_exec(char* cmd) { +int os::fork_and_exec(char* cmd, bool use_vfork_if_available) { char * argv[4]; argv[0] = (char *)"sh"; argv[1] = (char *)"-c";
--- a/src/hotspot/os/windows/os_windows.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/os/windows/os_windows.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -5254,7 +5254,7 @@ // Run the specified command in a separate process. Return its exit value, // or -1 on failure (e.g. can't create a new process). -int os::fork_and_exec(char* cmd) { +int os::fork_and_exec(char* cmd, bool use_vfork_if_available) { STARTUPINFO si; PROCESS_INFORMATION pi; DWORD exit_code;
--- a/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -42,10 +42,51 @@ } bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava) { - ucontext_t* uc = (ucontext_t*) ucontext; - *fr_addr = frame((intptr_t*)uc->uc_mcontext.gregs[15/*REG_SP*/], + assert(this->is_Java_thread(), "must be JavaThread"); + + // If we have a last_Java_frame, then we should use it even if + // isInJava == true. It should be more reliable than ucontext info. + if (has_last_Java_frame() && frame_anchor()->walkable()) { + *fr_addr = pd_last_frame(); + return true; + } + + if (isInJava) { + ucontext_t* uc = (ucontext_t*) ucontext; + frame ret_frame((intptr_t*)uc->uc_mcontext.gregs[15/*Z_SP*/], (address)uc->uc_mcontext.psw.addr); - return true; + + if (ret_frame.pc() == NULL) { + // ucontext wasn't useful + return false; + } + + if (ret_frame.is_interpreted_frame()) { + frame::z_ijava_state* istate = ret_frame.ijava_state_unchecked(); + if (!((Method*)(istate->method))->is_metaspace_object()) { + return false; + } + uint64_t reg_bcp = uc->uc_mcontext.gregs[13/*Z_BCP*/]; + uint64_t istate_bcp = istate->bcp; + uint64_t code_start = (uint64_t)(((Method*)(istate->method))->code_base()); + uint64_t code_end = (uint64_t)(((Method*)istate->method)->code_base() + ((Method*)istate->method)->code_size()); + if (istate_bcp >= code_start && istate_bcp < code_end) { + // we have a valid bcp, don't touch it, do nothing + } else if (reg_bcp >= code_start && reg_bcp < code_end) { + istate->bcp = reg_bcp; + } else { + return false; + } + } + if (!ret_frame.safe_for_sender(this)) { + // nothing else to try if the frame isn't good + return false; + } + *fr_addr = ret_frame; + return true; + } + // nothing else to try + return false; } // Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Linux/S390x.
--- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -54,6 +54,16 @@ "std %0, %1\n" : "=&f"(tmp), "=Q"(*(volatile double*)dst) : "Q"(*(volatile double*)src)); +#elif defined(__ARM_ARCH_7A__) + // Note that a ldrexd + clrex combination is only needed for + // correctness on the OS level (context-switches). In this + // case, clrex *may* be beneficial for performance. For now + // don't bother with clrex as this is Zero. + jlong tmp; + asm volatile ("ldrexd %0, [%1]\n" + : "=r"(tmp) + : "r"(src), "m"(src)); + *(jlong *) dst = tmp; #else *(jlong *) dst = *(const jlong *) src; #endif
--- a/src/hotspot/share/aot/aotCodeHeap.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/aot/aotCodeHeap.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -436,14 +436,19 @@ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_new_instance", address, JVMCIRuntime::new_instance); SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_new_array", address, JVMCIRuntime::new_array); SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_new_multi_array", address, JVMCIRuntime::new_multi_array); + SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_dynamic_new_instance", address, JVMCIRuntime::dynamic_new_instance); SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_dynamic_new_array", address, JVMCIRuntime::dynamic_new_array); + SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_new_instance_or_null", address, JVMCIRuntime::new_instance_or_null); + SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_new_array_or_null", address, JVMCIRuntime::new_array_or_null); + SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_new_multi_array_or_null", address, JVMCIRuntime::new_multi_array_or_null); + SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_dynamic_new_instance_or_null", address, JVMCIRuntime::dynamic_new_instance_or_null); + SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_dynamic_new_array_or_null", address, JVMCIRuntime::dynamic_new_array_or_null); SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_validate_object", address, JVMCIRuntime::validate_object); #if INCLUDE_G1GC SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_write_barrier_pre", address, JVMCIRuntime::write_barrier_pre); SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_write_barrier_post", address, JVMCIRuntime::write_barrier_post); #endif SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_identity_hash_code", address, JVMCIRuntime::identity_hash_code); - SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_dynamic_new_instance", address, JVMCIRuntime::dynamic_new_instance); SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_thread_is_interrupted", address, JVMCIRuntime::thread_is_interrupted); SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_exception_handler_for_pc", address, JVMCIRuntime::exception_handler_for_pc); SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_test_deoptimize_call_int", address, JVMCIRuntime::test_deoptimize_call_int); @@ -735,6 +740,14 @@ NOT_PRODUCT( klasses_seen++; ) + // AOT does not support custom class loaders. + ClassLoaderData* cld = ik->class_loader_data(); + if (!cld->is_builtin_class_loader_data()) { + log_trace(aot, class, load)("skip class %s for custom classloader %s (%p) tid=" INTPTR_FORMAT, + ik->internal_name(), cld->loader_name(), cld, p2i(thread)); + return false; + } + AOTKlassData* klass_data = find_klass(ik); if (klass_data == NULL) { return false; @@ -759,9 +772,10 @@ assert(klass_data->_class_id < _class_count, "invalid class id"); AOTClass* aot_class = &_classes[klass_data->_class_id]; - if (aot_class->_classloader != NULL && aot_class->_classloader != ik->class_loader_data()) { - log_trace(aot, class, load)("class %s in %s already loaded for classloader %p vs %p tid=" INTPTR_FORMAT, - ik->internal_name(), _lib->name(), aot_class->_classloader, ik->class_loader_data(), p2i(thread)); + ClassLoaderData* aot_cld = aot_class->_classloader; + if (aot_cld != NULL && aot_cld != cld) { + log_trace(aot, class, load)("class %s in %s already loaded for classloader %s (%p) vs %s (%p) tid=" INTPTR_FORMAT, + ik->internal_name(), _lib->name(), aot_cld->loader_name(), aot_cld, cld->loader_name(), cld, p2i(thread)); NOT_PRODUCT( aot_klasses_cl_miss++; ) return false; } @@ -774,9 +788,9 @@ NOT_PRODUCT( aot_klasses_found++; ) - log_trace(aot, class, load)("found %s in %s for classloader %p tid=" INTPTR_FORMAT, ik->internal_name(), _lib->name(), ik->class_loader_data(), p2i(thread)); + log_trace(aot, class, load)("found %s in %s for classloader %s (%p) tid=" INTPTR_FORMAT, ik->internal_name(), _lib->name(), cld->loader_name(), cld, p2i(thread)); - aot_class->_classloader = ik->class_loader_data(); + aot_class->_classloader = cld; // Set klass's Resolve (second) got cell. _klasses_got[klass_data->_got_index] = ik; if (ik->is_initialized()) {
--- a/src/hotspot/share/classfile/classLoader.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/classfile/classLoader.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -135,7 +135,6 @@ PerfCounter* ClassLoader::_sync_JVMDefineClassLockFreeCounter = NULL; PerfCounter* ClassLoader::_sync_JNIDefineClassLockFreeCounter = NULL; PerfCounter* ClassLoader::_unsafe_defineClassCallCounter = NULL; -PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL; GrowableArray<ModuleClassPathList*>* ClassLoader::_patch_mod_entries = NULL; GrowableArray<ModuleClassPathList*>* ClassLoader::_exploded_entries = NULL; @@ -1604,9 +1603,6 @@ NEWPERFEVENTCOUNTER(_unsafe_defineClassCallCounter, SUN_CLS, "unsafeDefineClassCalls"); - - NEWPERFEVENTCOUNTER(_load_instance_class_failCounter, SUN_CLS, - "loadInstanceClassFailRate"); } // lookup zip library entry points
--- a/src/hotspot/share/classfile/classLoader.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/classfile/classLoader.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -192,7 +192,6 @@ static PerfCounter* _sync_JNIDefineClassLockFreeCounter; static PerfCounter* _unsafe_defineClassCallCounter; - static PerfCounter* _load_instance_class_failCounter; // The boot class path consists of 3 ordered pieces: // 1. the module/path pairs specified to --patch-module @@ -340,12 +339,6 @@ return _unsafe_defineClassCallCounter; } - // Record how many times SystemDictionary::load_instance_class call - // fails with linkageError when Unsyncloadclass flag is set. - static PerfCounter* load_instance_class_failCounter() { - return _load_instance_class_failCounter; - } - // Modular java runtime image is present vs. a build with exploded modules static bool has_jrt_entry() { return (_jrt_entry != NULL); } static ClassPathEntry* get_jrt_entry() { return _jrt_entry; }
--- a/src/hotspot/share/classfile/classLoaderDataGraph.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/classfile/classLoaderDataGraph.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -487,6 +487,21 @@ } #endif // PRODUCT +bool ClassLoaderDataGraph::is_valid(ClassLoaderData* loader_data) { + DEBUG_ONLY( if (!VMError::is_error_reported()) { assert_locked_or_safepoint(ClassLoaderDataGraph_lock); } ) + if (loader_data != NULL) { + if (loader_data == ClassLoaderData::the_null_class_loader_data()) { + return true; + } + for (ClassLoaderData* data = _head; data != NULL; data = data->next()) { + if (loader_data == data) { + return true; + } + } + } + return false; +} + // Move class loader data from main list to the unloaded list for unloading // and deallocation later. bool ClassLoaderDataGraph::do_unloading(bool do_cleaning) {
--- a/src/hotspot/share/classfile/classLoaderDataGraph.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/classfile/classLoaderDataGraph.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -146,6 +146,10 @@ #ifndef PRODUCT static bool contains_loader_data(ClassLoaderData* loader_data); #endif + + // Check if ClassLoaderData is part of the ClassLoaderDataGraph (not unloaded) + // Usage without lock only allowed during error reporting. + static bool is_valid(ClassLoaderData* loader_data); }; class LockedClassesDo : public KlassClosure {
--- a/src/hotspot/share/classfile/compactHashtable.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/classfile/compactHashtable.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -174,7 +174,7 @@ // The CompactHashtable implementation // -void SimpleCompactHashtable::serialize(SerializeClosure* soc) { +void SimpleCompactHashtable::serialize_header(SerializeClosure* soc) { soc->do_ptr((void**)&_base_address); soc->do_u4(&_entry_count); soc->do_u4(&_bucket_count);
--- a/src/hotspot/share/classfile/compactHashtable.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/classfile/compactHashtable.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -123,6 +123,15 @@ public: void dump(SimpleCompactHashtable *cht, const char* table_name); + + static int default_num_buckets(size_t num_entries) { + return default_num_buckets((int)num_entries); + } + static int default_num_buckets(int num_entries) { + int num_buckets = num_entries / SharedSymbolTableBucketSize; + // calculation of num_buckets can result in zero buckets, we need at least one + return (num_buckets < 1) ? 1 : num_buckets; + } }; #endif // INCLUDE_CDS @@ -213,8 +222,8 @@ _entries = entries; } - // For reading from/writing to the CDS archive - void serialize(SerializeClosure* soc) NOT_CDS_RETURN; + // Read/Write the table's header from/to the CDS archive + void serialize_header(SerializeClosure* soc) NOT_CDS_RETURN; inline bool empty() { return (_entry_count == 0);
--- a/src/hotspot/share/classfile/javaClasses.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/classfile/javaClasses.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -36,8 +36,9 @@ #include "interpreter/linkResolver.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" +#include "memory/heapShared.inline.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" -#include "memory/metaspaceShared.inline.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/fieldStreams.hpp" @@ -750,7 +751,7 @@ { assert(fd->signature() == vmSymbols::string_signature(), "just checking"); - if (DumpSharedSpaces && MetaspaceShared::is_archive_object(mirror())) { + if (DumpSharedSpaces && HeapShared::is_archived_object(mirror())) { // Archive the String field and update the pointer. oop s = mirror()->obj_field(fd->offset()); oop archived_s = StringTable::create_archived_string(s, CHECK); @@ -788,7 +789,7 @@ } if (k->is_shared() && k->has_raw_archived_mirror()) { - if (MetaspaceShared::open_archive_heap_region_mapped()) { + if (HeapShared::open_archive_heap_region_mapped()) { bool present = restore_archived_mirror(k, Handle(), Handle(), Handle(), CHECK); assert(present, "Missing archived mirror for %s", k->external_name()); return; @@ -1011,14 +1012,14 @@ }; void java_lang_Class::archive_basic_type_mirrors(TRAPS) { - assert(MetaspaceShared::is_heap_object_archiving_allowed(), - "MetaspaceShared::is_heap_object_archiving_allowed() must be true"); + assert(HeapShared::is_heap_object_archiving_allowed(), + "HeapShared::is_heap_object_archiving_allowed() must be true"); for (int t = 0; t <= T_VOID; t++) { oop m = Universe::_mirrors[t]; if (m != NULL) { // Update the field at _array_klass_offset to point to the relocated array klass. - oop archived_m = MetaspaceShared::archive_heap_object(m, THREAD); + oop archived_m = HeapShared::archive_heap_object(m, THREAD); assert(archived_m != NULL, "sanity"); Klass *ak = (Klass*)(archived_m->metadata_field(_array_klass_offset)); assert(ak != NULL || t == T_VOID, "should not be NULL"); @@ -1071,8 +1072,8 @@ // be used at runtime, new mirror object is created for the shared // class. The _has_archived_raw_mirror is cleared also during the process. oop java_lang_Class::archive_mirror(Klass* k, TRAPS) { - assert(MetaspaceShared::is_heap_object_archiving_allowed(), - "MetaspaceShared::is_heap_object_archiving_allowed() must be true"); + assert(HeapShared::is_heap_object_archiving_allowed(), + "HeapShared::is_heap_object_archiving_allowed() must be true"); // Mirror is already archived if (k->has_raw_archived_mirror()) { @@ -1101,7 +1102,7 @@ } // Now start archiving the mirror object - oop archived_mirror = MetaspaceShared::archive_heap_object(mirror, THREAD); + oop archived_mirror = HeapShared::archive_heap_object(mirror, THREAD); if (archived_mirror == NULL) { return NULL; } @@ -1139,7 +1140,7 @@ if (k->is_typeArray_klass()) { // The primitive type mirrors are already archived. Get the archived mirror. oop comp_mirror = java_lang_Class::component_mirror(mirror); - archived_comp_mirror = MetaspaceShared::find_archived_heap_object(comp_mirror); + archived_comp_mirror = HeapShared::find_archived_heap_object(comp_mirror); assert(archived_comp_mirror != NULL, "Must be"); } else { assert(k->is_objArray_klass(), "Must be"); @@ -1202,7 +1203,7 @@ return true; } - oop m = MetaspaceShared::materialize_archived_object(k->archived_java_mirror_raw_narrow()); + oop m = HeapShared::materialize_archived_object(k->archived_java_mirror_raw_narrow()); if (m == NULL) { return false; @@ -1211,7 +1212,7 @@ log_debug(cds, mirror)("Archived mirror is: " PTR_FORMAT, p2i(m)); // mirror is archived, restore - assert(MetaspaceShared::is_archive_object(m), "must be archived mirror object"); + assert(HeapShared::is_archived_object(m), "must be archived mirror object"); Handle mirror(THREAD, m); if (!k->is_array_klass()) {
--- a/src/hotspot/share/classfile/stringTable.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/classfile/stringTable.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -36,7 +36,6 @@ #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "memory/heapShared.inline.hpp" -#include "memory/metaspaceShared.inline.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/access.inline.hpp" @@ -798,18 +797,17 @@ oop StringTable::create_archived_string(oop s, Thread* THREAD) { assert(DumpSharedSpaces, "this function is only used with -Xshare:dump"); - if (MetaspaceShared::is_archive_object(s)) { + if (HeapShared::is_archived_object(s)) { return s; } oop new_s = NULL; typeArrayOop v = java_lang_String::value_no_keepalive(s); - typeArrayOop new_v = - (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD); + typeArrayOop new_v = (typeArrayOop)HeapShared::archive_heap_object(v, THREAD); if (new_v == NULL) { return NULL; } - new_s = MetaspaceShared::archive_heap_object(s, THREAD); + new_s = HeapShared::archive_heap_object(s, THREAD); if (new_s == NULL) { return NULL; } @@ -819,18 +817,9 @@ return new_s; } -class CompactStringTableWriter: public CompactHashtableWriter { -public: - CompactStringTableWriter(int num_entries, CompactHashtableStats* stats) : - CompactHashtableWriter(num_entries, stats) {} - void add(unsigned int hash, oop string) { - CompactHashtableWriter::add(hash, CompressedOops::encode(string)); - } -}; - struct CopyToArchive : StackObj { - CompactStringTableWriter* _writer; - CopyToArchive(CompactStringTableWriter* writer) : _writer(writer) {} + CompactHashtableWriter* _writer; + CopyToArchive(CompactHashtableWriter* writer) : _writer(writer) {} bool operator()(WeakHandle<vm_string_table_data>* val) { oop s = val->peek(); if (s == NULL) { @@ -838,6 +827,7 @@ } unsigned int hash = java_lang_String::hash_code(s); if (hash == 0) { + // We do not archive Strings with a 0 hashcode because ...... return true; } @@ -849,34 +839,34 @@ val->replace(new_s); // add to the compact table - _writer->add(hash, new_s); + _writer->add(hash, CompressedOops::encode(new_s)); return true; } }; -void StringTable::copy_shared_string_table(CompactStringTableWriter* writer) { - assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be"); +void StringTable::copy_shared_string_table(CompactHashtableWriter* writer) { + assert(HeapShared::is_heap_object_archiving_allowed(), "must be"); CopyToArchive copy(writer); StringTable::the_table()->_local_table->do_scan(Thread::current(), copy); } void StringTable::write_to_archive() { - assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be"); + assert(HeapShared::is_heap_object_archiving_allowed(), "must be"); _shared_table.reset(); - int num_buckets = the_table()->_items_count / SharedSymbolTableBucketSize; - // calculation of num_buckets can result in zero buckets, we need at least one - CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1, - &MetaspaceShared::stats()->string); + int num_buckets = CompactHashtableWriter::default_num_buckets( + StringTable::the_table()->_items_count); + CompactHashtableWriter writer(num_buckets, + &MetaspaceShared::stats()->string); // Copy the interned strings into the "string space" within the java heap copy_shared_string_table(&writer); writer.dump(&_shared_table, "string"); } -void StringTable::serialize(SerializeClosure* soc) { - _shared_table.serialize(soc); +void StringTable::serialize_shared_table_header(SerializeClosure* soc) { + _shared_table.serialize_header(soc); if (soc->writing()) { // Sanity. Make sure we don't use the shared table at dump time
--- a/src/hotspot/share/classfile/stringTable.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/classfile/stringTable.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -33,7 +33,7 @@ #include "oops/weakHandle.hpp" #include "utilities/concurrentHashTable.hpp" -class CompactStringTableWriter; +class CompactHashtableWriter; class SerializeClosure; class StringTable; @@ -163,14 +163,14 @@ // Sharing private: oop lookup_shared(const jchar* name, int len, unsigned int hash) NOT_CDS_JAVA_HEAP_RETURN_(NULL); - static void copy_shared_string_table(CompactStringTableWriter* ch_table) NOT_CDS_JAVA_HEAP_RETURN; + static void copy_shared_string_table(CompactHashtableWriter* ch_table) NOT_CDS_JAVA_HEAP_RETURN; public: static oop create_archived_string(oop s, Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN_(NULL); static void set_shared_string_mapped() { _shared_string_mapped = true; } static bool shared_string_mapped() { return _shared_string_mapped; } static void shared_oops_do(OopClosure* f) NOT_CDS_JAVA_HEAP_RETURN; static void write_to_archive() NOT_CDS_JAVA_HEAP_RETURN; - static void serialize(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN; + static void serialize_shared_table_header(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN; // Jcmd static void dump(outputStream* st, bool verbose=false);
--- a/src/hotspot/share/classfile/symbolTable.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/classfile/symbolTable.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -627,43 +627,31 @@ } #if INCLUDE_CDS -class CompactSymbolTableWriter: public CompactHashtableWriter { -public: - CompactSymbolTableWriter(int num_buckets, CompactHashtableStats* stats) : - CompactHashtableWriter(num_buckets, stats) {} - void add(unsigned int hash, Symbol *symbol) { - uintx deltax = MetaspaceShared::object_delta(symbol); +struct CopyToArchive : StackObj { + CompactHashtableWriter* _writer; + CopyToArchive(CompactHashtableWriter* writer) : _writer(writer) {} + bool operator()(Symbol** value) { + assert(value != NULL, "expected valid value"); + assert(*value != NULL, "value should point to a symbol"); + Symbol* sym = *value; + unsigned int fixed_hash = hash_shared_symbol((const char*)sym->bytes(), sym->utf8_length()); + assert(fixed_hash == hash_symbol((const char*)sym->bytes(), sym->utf8_length(), false), + "must not rehash during dumping"); + + uintx deltax = MetaspaceShared::object_delta(sym); // When the symbols are stored into the archive, we already check that // they won't be more than MAX_SHARED_DELTA from the base address, or // else the dumping would have been aborted. assert(deltax <= MAX_SHARED_DELTA, "must not be"); u4 delta = u4(deltax); - CompactHashtableWriter::add(hash, delta); - } -}; - -struct CopyToArchive : StackObj { - CompactSymbolTableWriter* _writer; - CopyToArchive(CompactSymbolTableWriter* writer) : _writer(writer) {} - bool operator()(Symbol** value) { - assert(value != NULL, "expected valid value"); - assert(*value != NULL, "value should point to a symbol"); - Symbol* sym = *value; - unsigned int fixed_hash = hash_shared_symbol((const char*)sym->bytes(), sym->utf8_length()); - if (fixed_hash == 0) { - return true; - } - assert(fixed_hash == hash_symbol((const char*)sym->bytes(), sym->utf8_length(), false), - "must not rehash during dumping"); - // add to the compact table - _writer->add(fixed_hash, sym); + _writer->add(fixed_hash, delta); return true; } }; -void SymbolTable::copy_shared_symbol_table(CompactSymbolTableWriter* writer) { +void SymbolTable::copy_shared_symbol_table(CompactHashtableWriter* writer) { CopyToArchive copy(writer); SymbolTable::the_table()->_local_table->do_scan(Thread::current(), copy); } @@ -671,10 +659,10 @@ void SymbolTable::write_to_archive() { _shared_table.reset(); - int num_buckets = (int)(SymbolTable::the_table()->_items_count / SharedSymbolTableBucketSize); - // calculation of num_buckets can result in zero buckets, we need at least one - CompactSymbolTableWriter writer(num_buckets > 1 ? num_buckets : 1, - &MetaspaceShared::stats()->symbol); + int num_buckets = CompactHashtableWriter::default_num_buckets( + SymbolTable::the_table()->_items_count); + CompactHashtableWriter writer(num_buckets, + &MetaspaceShared::stats()->symbol); copy_shared_symbol_table(&writer); writer.dump(&_shared_table, "symbol"); @@ -686,8 +674,8 @@ assert(sym == _shared_table.lookup(name, hash, len), "sanity"); } -void SymbolTable::serialize(SerializeClosure* soc) { - _shared_table.serialize(soc); +void SymbolTable::serialize_shared_table_header(SerializeClosure* soc) { + _shared_table.serialize_header(soc); if (soc->writing()) { // Sanity. Make sure we don't use the shared table at dump time
--- a/src/hotspot/share/classfile/symbolTable.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/classfile/symbolTable.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -84,7 +84,7 @@ operator Symbol*() { return _temp; } }; -class CompactSymbolTableWriter; +class CompactHashtableWriter; class SerializeClosure; class SymbolTableConfig; @@ -240,10 +240,10 @@ // Sharing private: - static void copy_shared_symbol_table(CompactSymbolTableWriter* ch_table); + static void copy_shared_symbol_table(CompactHashtableWriter* ch_table); public: static void write_to_archive() NOT_CDS_RETURN; - static void serialize(SerializeClosure* soc) NOT_CDS_RETURN; + static void serialize_shared_table_header(SerializeClosure* soc) NOT_CDS_RETURN; static void metaspace_pointers_do(MetaspaceClosure* it); // Jcmd
--- a/src/hotspot/share/classfile/systemDictionary.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/classfile/systemDictionary.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -52,6 +52,7 @@ #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/filemap.hpp" +#include "memory/heapShared.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" @@ -2037,13 +2038,13 @@ // ConstantPool::restore_unshareable_info (restores the archived // resolved_references array object). // - // MetaspaceShared::fixup_mapped_heap_regions() fills the empty + // HeapShared::fixup_mapped_heap_regions() fills the empty // spaces in the archived heap regions and may use // SystemDictionary::Object_klass(), so we can do this only after // Object_klass is resolved. See the above resolve_wk_klasses_through() // call. No mirror objects are accessed/restored in the above call. // Mirrors are restored after java.lang.Class is loaded. - MetaspaceShared::fixup_mapped_heap_regions(); + HeapShared::fixup_mapped_heap_regions(); // Initialize the constant pool for the Object_class Object_klass()->constants()->restore_unshareable_info(CHECK);
--- a/src/hotspot/share/classfile/verificationType.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/classfile/verificationType.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -111,7 +111,7 @@ VerificationType comp_from = from.get_component(context, CHECK_false); if (!comp_this.is_bogus() && !comp_from.is_bogus()) { return comp_this.is_component_assignable_from(comp_from, context, - from_field_is_protected, CHECK_false); + from_field_is_protected, THREAD); } } return false;
--- a/src/hotspot/share/classfile/verificationType.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/classfile/verificationType.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -312,7 +312,7 @@ case Short: return false; default: - return is_assignable_from(from, context, from_field_is_protected, CHECK_false); + return is_assignable_from(from, context, from_field_is_protected, THREAD); } } }
--- a/src/hotspot/share/code/codeBlob.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/code/codeBlob.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -26,7 +26,9 @@ #include "jvm.h" #include "code/codeBlob.hpp" #include "code/codeCache.hpp" +#include "code/icBuffer.hpp" #include "code/relocInfo.hpp" +#include "code/vtableStubs.hpp" #include "compiler/disassembler.hpp" #include "interpreter/bytecode.hpp" #include "memory/allocation.inline.hpp" @@ -559,6 +561,67 @@ st->print_cr("[CodeBlob]"); } +void CodeBlob::dump_for_addr(address addr, outputStream* st, bool verbose) const { + if (is_buffer_blob()) { + // the interpreter is generated into a buffer blob + InterpreterCodelet* i = Interpreter::codelet_containing(addr); + if (i != NULL) { + st->print_cr(INTPTR_FORMAT " is at code_begin+%d in an Interpreter codelet", p2i(addr), (int)(addr - i->code_begin())); + i->print_on(st); + return; + } + if (Interpreter::contains(addr)) { + st->print_cr(INTPTR_FORMAT " is pointing into interpreter code" + " (not bytecode specific)", p2i(addr)); + return; + } + // + if (AdapterHandlerLibrary::contains(this)) { + st->print_cr(INTPTR_FORMAT " is at code_begin+%d in an AdapterHandler", p2i(addr), (int)(addr - code_begin())); + AdapterHandlerLibrary::print_handler_on(st, this); + } + // the stubroutines are generated into a buffer blob + StubCodeDesc* d = StubCodeDesc::desc_for(addr); + if (d != NULL) { + st->print_cr(INTPTR_FORMAT " is at begin+%d in a stub", p2i(addr), (int)(addr - d->begin())); + d->print_on(st); + st->cr(); + return; + } + if (StubRoutines::contains(addr)) { + st->print_cr(INTPTR_FORMAT " is pointing to an (unnamed) stub routine", p2i(addr)); + return; + } + // the InlineCacheBuffer is using stubs generated into a buffer blob + if (InlineCacheBuffer::contains(addr)) { + st->print_cr(INTPTR_FORMAT " is pointing into InlineCacheBuffer", p2i(addr)); + return; + } + VtableStub* v = VtableStubs::stub_containing(addr); + if (v != NULL) { + st->print_cr(INTPTR_FORMAT " is at entry_point+%d in a vtable stub", p2i(addr), (int)(addr - v->entry_point())); + v->print_on(st); + st->cr(); + return; + } + } + if (is_nmethod()) { + nmethod* nm = (nmethod*)this; + ResourceMark rm; + st->print(INTPTR_FORMAT " is at entry_point+%d in (nmethod*)" INTPTR_FORMAT, + p2i(addr), (int)(addr - nm->entry_point()), p2i(nm)); + if (verbose) { + st->print(" for "); + nm->method()->print_value_on(st); + } + st->cr(); + nm->print_nmethod(verbose); + return; + } + st->print_cr(INTPTR_FORMAT " is at code_begin+%d in ", p2i(addr), (int)(addr - code_begin())); + print_on(st); +} + void RuntimeBlob::verify() { ShouldNotReachHere(); }
--- a/src/hotspot/share/code/codeBlob.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/code/codeBlob.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -221,6 +221,7 @@ virtual void print() const { print_on(tty); }; virtual void print_on(outputStream* st) const; virtual void print_value_on(outputStream* st) const; + void dump_for_addr(address addr, outputStream* st, bool verbose) const; void print_code(); // Print the comment associated with offset on stream, if there is one
--- a/src/hotspot/share/code/nmethod.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/code/nmethod.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -2340,7 +2340,7 @@ for (int i = 0; i < oops_count(); i++) { oop o = oop_at(i); tty->print("#%3d: " INTPTR_FORMAT " ", i, p2i(o)); - if (o == (oop)Universe::non_oop_word()) { + if (o == Universe::non_oop_word()) { tty->print("non-oop word"); } else { if (o != NULL) {
--- a/src/hotspot/share/code/relocInfo.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/code/relocInfo.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -574,7 +574,7 @@ oop oop_Relocation::oop_value() { oop v = *oop_addr(); // clean inline caches store a special pseudo-null - if (v == (oop)Universe::non_oop_word()) v = NULL; + if (v == Universe::non_oop_word()) v = NULL; return v; }
--- a/src/hotspot/share/compiler/compileBroker.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/compiler/compileBroker.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -1781,30 +1781,31 @@ return; // Stop this thread. } } - continue; - } + } else { + // Assign the task to the current thread. Mark this compilation + // thread as active for the profiler. + // CompileTaskWrapper also keeps the Method* from being deallocated if redefinition + // occurs after fetching the compile task off the queue. + CompileTaskWrapper ctw(task); + nmethodLocker result_handle; // (handle for the nmethod produced by this task) + task->set_code_handle(&result_handle); + methodHandle method(thread, task->method()); - if (UseDynamicNumberOfCompilerThreads) { - possibly_add_compiler_threads(); - } + // Never compile a method if breakpoints are present in it + if (method()->number_of_breakpoints() == 0) { + // Compile the method. + if ((UseCompiler || AlwaysCompileLoopMethods) && CompileBroker::should_compile_new_jobs()) { + invoke_compiler_on_method(task); + thread->start_idle_timer(); + } else { + // After compilation is disabled, remove remaining methods from queue + method->clear_queued_for_compilation(); + task->set_failure_reason("compilation is disabled"); + } + } - // Assign the task to the current thread. Mark this compilation - // thread as active for the profiler. - CompileTaskWrapper ctw(task); - nmethodLocker result_handle; // (handle for the nmethod produced by this task) - task->set_code_handle(&result_handle); - methodHandle method(thread, task->method()); - - // Never compile a method if breakpoints are present in it - if (method()->number_of_breakpoints() == 0) { - // Compile the method. - if ((UseCompiler || AlwaysCompileLoopMethods) && CompileBroker::should_compile_new_jobs()) { - invoke_compiler_on_method(task); - thread->start_idle_timer(); - } else { - // After compilation is disabled, remove remaining methods from queue - method->clear_queued_for_compilation(); - task->set_failure_reason("compilation is disabled"); + if (UseDynamicNumberOfCompilerThreads) { + possibly_add_compiler_threads(); } } }
--- a/src/hotspot/share/compiler/oopMap.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/compiler/oopMap.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -350,7 +350,7 @@ // implicit null check is used in compiled code. // The narrow_oop_base could be NULL or be the address // of the page below heap depending on compressed oops mode. - if (base_loc != NULL && *base_loc != (oop)NULL && !Universe::is_narrow_oop_base(*base_loc)) { + if (base_loc != NULL && *base_loc != NULL && !Universe::is_narrow_oop_base(*base_loc)) { derived_oop_fn(base_loc, derived_loc); } oms.next(); @@ -371,7 +371,7 @@ guarantee(loc != NULL, "missing saved register"); if ( omv.type() == OopMapValue::oop_value ) { oop val = *loc; - if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) { + if (val == NULL || Universe::is_narrow_oop_base(val)) { // Ignore NULL oops and decoded NULL narrow oops which // equal to Universe::narrow_oop_base when a narrow oop // implicit null check is used in compiled code. @@ -769,7 +769,7 @@ assert(Universe::heap()->is_in_or_null(*base_loc), "not an oop"); assert(derived_loc != base_loc, "Base and derived in same location"); if (_active) { - assert(*derived_loc != (oop)base_loc, "location already added"); + assert(*derived_loc != (void*)base_loc, "location already added"); assert(_list != NULL, "list must exist"); intptr_t offset = value_of_loc(derived_loc) - value_of_loc(base_loc); // This assert is invalid because derived pointers can be
--- a/src/hotspot/share/gc/epsilon/epsilonHeap.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/epsilon/epsilonHeap.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -118,6 +118,8 @@ } HeapWord* EpsilonHeap::allocate_work(size_t size) { + assert(is_object_aligned(size), "Allocation size should be aligned: " SIZE_FORMAT, size); + HeapWord* res = _space->par_allocate(size); while (res == NULL) { @@ -168,6 +170,7 @@ } } + assert(is_object_aligned(res), "Object should be aligned: " PTR_FORMAT, p2i(res)); return res; } @@ -211,6 +214,9 @@ // Always honor boundaries size = MAX2(min_size, MIN2(_max_tlab_size, size)); + // Always honor alignment + size = align_up(size, MinObjAlignment); + if (log_is_enabled(Trace, gc)) { ResourceMark rm; log_trace(gc)("TLAB size for \"%s\" (Requested: " SIZE_FORMAT "K, Min: " SIZE_FORMAT
--- a/src/hotspot/share/gc/g1/g1Allocator.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/g1/g1Allocator.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -270,7 +270,7 @@ // Check if the object is in open archive static inline bool is_open_archive_object(oop object); // Check if the object is either in closed archive or open archive - static inline bool is_archive_object(oop object); + static inline bool is_archived_object(oop object); private: static bool _archive_check_enabled;
--- a/src/hotspot/share/gc/g1/g1Allocator.inline.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/g1/g1Allocator.inline.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -141,7 +141,7 @@ return (archive_check_enabled() && in_open_archive_range(object)); } -inline bool G1ArchiveAllocator::is_archive_object(oop object) { +inline bool G1ArchiveAllocator::is_archived_object(oop object) { return (archive_check_enabled() && (in_closed_archive_range(object) || in_open_archive_range(object))); }
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -80,7 +80,6 @@ #include "logging/log.hpp" #include "memory/allocation.hpp" #include "memory/iterator.hpp" -#include "memory/metaspaceShared.inline.hpp" #include "memory/resourceArea.hpp" #include "oops/access.inline.hpp" #include "oops/compressedOops.inline.hpp" @@ -827,7 +826,7 @@ oop G1CollectedHeap::materialize_archived_object(oop obj) { assert(obj != NULL, "archived obj is NULL"); - assert(MetaspaceShared::is_archive_object(obj), "must be archived object"); + assert(G1ArchiveAllocator::is_archived_object(obj), "must be archived object"); // Loading an archived object makes it strongly reachable. If it is // loaded during concurrent marking, it must be enqueued to the SATB
--- a/src/hotspot/share/gc/g1/g1FullGCOopClosures.inline.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/g1/g1FullGCOopClosures.inline.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -68,7 +68,7 @@ oop obj = CompressedOops::decode_not_null(heap_oop); assert(Universe::heap()->is_in(obj), "should be in heap"); - if (G1ArchiveAllocator::is_archive_object(obj)) { + if (G1ArchiveAllocator::is_archived_object(obj)) { // We never forward archive objects. return; }
--- a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -248,7 +248,7 @@ oop obj = RawAccess<>::oop_load(p); if (_hr->is_open_archive()) { - guarantee(obj == NULL || G1ArchiveAllocator::is_archive_object(obj), + guarantee(obj == NULL || G1ArchiveAllocator::is_archived_object(obj), "Archive object at " PTR_FORMAT " references a non-archive object at " PTR_FORMAT, p2i(p), p2i(obj)); } else {
--- a/src/hotspot/share/gc/parallel/pcTasks.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/parallel/pcTasks.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -35,6 +35,7 @@ #include "gc/shared/gcTimer.hpp" #include "gc/shared/gcTraceTime.inline.hpp" #include "logging/log.hpp" +#include "memory/iterator.inline.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/objArrayKlass.inline.hpp" @@ -58,7 +59,7 @@ ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); - ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm); + PCMarkAndPushClosure mark_and_push_closure(cm); MarkingCodeBlobClosure mark_and_push_in_blobs(&mark_and_push_closure, !CodeBlobToOopClosure::FixRelocations); _thread->oops_do(&mark_and_push_closure, &mark_and_push_in_blobs); @@ -73,7 +74,7 @@ ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); - ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm); + PCMarkAndPushClosure mark_and_push_closure(cm); switch (_root_type) { case universe: @@ -139,7 +140,7 @@ ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); - ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm); + PCMarkAndPushClosure mark_and_push_closure(cm); ParCompactionManager::FollowStackClosure follow_stack_closure(cm); _rp_task.work(_work_id, *PSParallelCompact::is_alive_closure(), mark_and_push_closure, follow_stack_closure); @@ -182,13 +183,12 @@ ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); - ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm); oop obj = NULL; ObjArrayTask task; do { while (ParCompactionManager::steal_objarray(which, task)) { - cm->follow_contents((objArrayOop)task.obj(), task.index()); + cm->follow_array((objArrayOop)task.obj(), task.index()); cm->follow_marking_stacks(); } while (ParCompactionManager::steal(which, obj)) {
--- a/src/hotspot/share/gc/parallel/psCardTable.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/parallel/psCardTable.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -28,7 +28,7 @@ #include "gc/parallel/parallelScavengeHeap.inline.hpp" #include "gc/parallel/psCardTable.hpp" #include "gc/parallel/psPromotionManager.inline.hpp" -#include "gc/parallel/psScavenge.hpp" +#include "gc/parallel/psScavenge.inline.hpp" #include "gc/parallel/psTasks.hpp" #include "gc/parallel/psYoungGen.hpp" #include "memory/iterator.inline.hpp"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/gc/parallel/psClosure.inline.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_PARALLEL_PSCLOSURE_INLINE_HPP +#define SHARE_VM_GC_PARALLEL_PSCLOSURE_INLINE_HPP + +#include "gc/parallel/psPromotionManager.inline.hpp" +#include "gc/parallel/psScavenge.inline.hpp" +#include "memory/iterator.hpp" +#include "oops/access.inline.hpp" +#include "oops/oop.inline.hpp" +#include "utilities/globalDefinitions.hpp" + +template <bool promote_immediately> +class PSRootsClosure: public OopClosure { +private: + PSPromotionManager* _promotion_manager; + + template <class T> void do_oop_work(T *p) { + if (PSScavenge::should_scavenge(p)) { + // We never card mark roots, maybe call a func without test? + _promotion_manager->copy_and_push_safe_barrier<T, promote_immediately>(p); + } + } +public: + PSRootsClosure(PSPromotionManager* pm) : _promotion_manager(pm) { } + void do_oop(oop* p) { PSRootsClosure::do_oop_work(p); } + void do_oop(narrowOop* p) { PSRootsClosure::do_oop_work(p); } +}; + +typedef PSRootsClosure</*promote_immediately=*/false> PSScavengeRootsClosure; +typedef PSRootsClosure</*promote_immediately=*/true> PSPromoteRootsClosure; + +// Scavenges a single oop in a ClassLoaderData. +class PSScavengeFromCLDClosure: public OopClosure { +private: + PSPromotionManager* _pm; + // Used to redirty a scanned cld if it has oops + // pointing to the young generation after being scanned. + ClassLoaderData* _scanned_cld; +public: + PSScavengeFromCLDClosure(PSPromotionManager* pm) : _pm(pm), _scanned_cld(NULL) { } + void do_oop(narrowOop* p) { ShouldNotReachHere(); } + void do_oop(oop* p) { + ParallelScavengeHeap* psh = ParallelScavengeHeap::heap(); + assert(!psh->is_in_reserved(p), "GC barrier needed"); + if (PSScavenge::should_scavenge(p)) { + assert(PSScavenge::should_scavenge(p, true), "revisiting object?"); + + oop o = *p; + oop new_obj; + if (o->is_forwarded()) { + new_obj = o->forwardee(); + } else { + new_obj = _pm->copy_to_survivor_space</*promote_immediately=*/false>(o); + } + RawAccess<IS_NOT_NULL>::oop_store(p, new_obj); + + if (PSScavenge::is_obj_in_young(new_obj)) { + do_cld_barrier(); + } + } + } + + void set_scanned_cld(ClassLoaderData* cld) { + assert(_scanned_cld == NULL || cld == NULL, "Should always only handling one cld at a time"); + _scanned_cld = cld; + } + +private: + void do_cld_barrier() { + assert(_scanned_cld != NULL, "Should not be called without having a scanned cld"); + _scanned_cld->record_modified_oops(); + } +}; + +// Scavenges the oop in a ClassLoaderData. +class PSScavengeCLDClosure: public CLDClosure { +private: + PSScavengeFromCLDClosure _oop_closure; +public: + PSScavengeCLDClosure(PSPromotionManager* pm) : _oop_closure(pm) { } + void do_cld(ClassLoaderData* cld) { + // If the cld has not been dirtied we know that there's + // no references into the young gen and we can skip it. + + if (cld->has_modified_oops()) { + // Setup the promotion manager to redirty this cld + // if references are left in the young gen. + _oop_closure.set_scanned_cld(cld); + + // Clean the cld since we're going to scavenge all the metadata. + cld->oops_do(&_oop_closure, false, /*clear_modified_oops*/true); + + _oop_closure.set_scanned_cld(NULL); + } + } +}; + +#endif
--- a/src/hotspot/share/gc/parallel/psCompactionManager.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/parallel/psCompactionManager.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -132,113 +132,6 @@ return _manager_array[index]; } -void InstanceKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) { - assert(obj != NULL, "can't follow the content of NULL object"); - - cm->follow_klass(this); - // Only mark the header and let the scan of the meta-data mark - // everything else. - - ParCompactionManager::MarkAndPushClosure cl(cm); - if (UseCompressedOops) { - InstanceKlass::oop_oop_iterate_oop_maps<narrowOop>(obj, &cl); - } else { - InstanceKlass::oop_oop_iterate_oop_maps<oop>(obj, &cl); - } -} - -void InstanceMirrorKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) { - InstanceKlass::oop_pc_follow_contents(obj, cm); - - // Follow the klass field in the mirror. - Klass* klass = java_lang_Class::as_Klass(obj); - if (klass != NULL) { - // An unsafe anonymous class doesn't have its own class loader, - // so the call to follow_klass will mark and push its java mirror instead of the - // class loader. When handling the java mirror for an unsafe anonymous - // class we need to make sure its class loader data is claimed, this is done - // by calling follow_class_loader explicitly. For non-anonymous classes the - // call to follow_class_loader is made when the class loader itself is handled. - if (klass->is_instance_klass() && - InstanceKlass::cast(klass)->is_unsafe_anonymous()) { - cm->follow_class_loader(klass->class_loader_data()); - } else { - cm->follow_klass(klass); - } - } else { - // If klass is NULL then this a mirror for a primitive type. - // We don't have to follow them, since they are handled as strong - // roots in Universe::oops_do. - assert(java_lang_Class::is_primitive(obj), "Sanity check"); - } - - ParCompactionManager::MarkAndPushClosure cl(cm); - if (UseCompressedOops) { - oop_oop_iterate_statics<narrowOop>(obj, &cl); - } else { - oop_oop_iterate_statics<oop>(obj, &cl); - } -} - -void InstanceClassLoaderKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) { - InstanceKlass::oop_pc_follow_contents(obj, cm); - - ClassLoaderData * const loader_data = java_lang_ClassLoader::loader_data_acquire(obj); - if (loader_data != NULL) { - cm->follow_class_loader(loader_data); - } -} - -template <class T> -static void oop_pc_follow_contents_specialized(InstanceRefKlass* klass, oop obj, ParCompactionManager* cm) { - T* referent_addr = (T*)java_lang_ref_Reference::referent_addr_raw(obj); - T heap_oop = RawAccess<>::oop_load(referent_addr); - log_develop_trace(gc, ref)("InstanceRefKlass::oop_pc_follow_contents " PTR_FORMAT, p2i(obj)); - if (!CompressedOops::is_null(heap_oop)) { - oop referent = CompressedOops::decode_not_null(heap_oop); - if (PSParallelCompact::mark_bitmap()->is_unmarked(referent) && - PSParallelCompact::ref_processor()->discover_reference(obj, klass->reference_type())) { - // reference already enqueued, referent will be traversed later - klass->InstanceKlass::oop_pc_follow_contents(obj, cm); - log_develop_trace(gc, ref)(" Non NULL enqueued " PTR_FORMAT, p2i(obj)); - return; - } else { - // treat referent as normal oop - log_develop_trace(gc, ref)(" Non NULL normal " PTR_FORMAT, p2i(obj)); - cm->mark_and_push(referent_addr); - } - } - // Treat discovered as normal oop. - T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr_raw(obj); - cm->mark_and_push(discovered_addr); - klass->InstanceKlass::oop_pc_follow_contents(obj, cm); -} - - -void InstanceRefKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) { - if (UseCompressedOops) { - oop_pc_follow_contents_specialized<narrowOop>(this, obj, cm); - } else { - oop_pc_follow_contents_specialized<oop>(this, obj, cm); - } -} - -void ObjArrayKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) { - cm->follow_klass(this); - - if (UseCompressedOops) { - oop_pc_follow_contents_specialized<narrowOop>(objArrayOop(obj), 0, cm); - } else { - oop_pc_follow_contents_specialized<oop>(objArrayOop(obj), 0, cm); - } -} - -void TypeArrayKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) { - assert(obj->is_typeArray(),"must be a type array"); - // Performance tweak: We skip iterating over the klass pointer since we - // know that Universe::TypeArrayKlass never moves. -} - void ParCompactionManager::follow_marking_stacks() { do { // Drain the overflow stack first, to allow stealing from the marking stack. @@ -253,7 +146,7 @@ // Process ObjArrays one at a time to avoid marking stack bloat. ObjArrayTask task; if (_objarray_stack.pop_overflow(task) || _objarray_stack.pop_local(task)) { - follow_contents((objArrayOop)task.obj(), task.index()); + follow_array((objArrayOop)task.obj(), task.index()); } } while (!marking_stacks_empty());
--- a/src/hotspot/share/gc/parallel/psCompactionManager.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/parallel/psCompactionManager.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -171,24 +171,10 @@ void drain_region_stacks(); void follow_contents(oop obj); - void follow_contents(objArrayOop array, int index); + void follow_array(objArrayOop array, int index); void update_contents(oop obj); - class MarkAndPushClosure: public BasicOopIterateClosure { - private: - ParCompactionManager* _compaction_manager; - public: - MarkAndPushClosure(ParCompactionManager* cm) : _compaction_manager(cm) { } - - template <typename T> void do_oop_work(T* p); - virtual void do_oop(oop* p); - virtual void do_oop(narrowOop* p); - - // This closure provides its own oop verification code. - debug_only(virtual bool should_verify_oops() { return false; }) - }; - class FollowStackClosure: public VoidClosure { private: ParCompactionManager* _compaction_manager;
--- a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_GC_PARALLEL_PSCOMPACTIONMANAGER_INLINE_HPP #define SHARE_VM_GC_PARALLEL_PSCOMPACTIONMANAGER_INLINE_HPP +#include "classfile/javaClasses.inline.hpp" #include "gc/parallel/parMarkBitMap.hpp" #include "gc/parallel/psCompactionManager.hpp" #include "gc/parallel/psParallelCompact.inline.hpp" @@ -37,6 +38,37 @@ #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" +class PCMarkAndPushClosure: public OopClosure { +private: + ParCompactionManager* _compaction_manager; +public: + PCMarkAndPushClosure(ParCompactionManager* cm) : _compaction_manager(cm) { } + + template <typename T> void do_oop_nv(T* p) { _compaction_manager->mark_and_push(p); } + virtual void do_oop(oop* p) { do_oop_nv(p); } + virtual void do_oop(narrowOop* p) { do_oop_nv(p); } + + // This closure provides its own oop verification code. + debug_only(virtual bool should_verify_oops() { return false; }) +}; + +class PCIterateMarkAndPushClosure: public MetadataVisitingOopIterateClosure { +private: + ParCompactionManager* _compaction_manager; +public: + PCIterateMarkAndPushClosure(ParCompactionManager* cm, ReferenceProcessor* rp) : MetadataVisitingOopIterateClosure(rp), _compaction_manager(cm) { } + + template <typename T> void do_oop_nv(T* p) { _compaction_manager->mark_and_push(p); } + virtual void do_oop(oop* p) { do_oop_nv(p); } + virtual void do_oop(narrowOop* p) { do_oop_nv(p); } + + void do_klass_nv(Klass* k) { _compaction_manager->follow_klass(k); } + void do_cld_nv(ClassLoaderData* cld) { _compaction_manager->follow_class_loader(cld); } + + // This closure provides its own oop verification code. + debug_only(virtual bool should_verify_oops() { return false; }) +}; + inline bool ParCompactionManager::steal(int queue_num, oop& t) { return stack_array()->steal(queue_num, t); } @@ -84,14 +116,6 @@ } } -template <typename T> -inline void ParCompactionManager::MarkAndPushClosure::do_oop_work(T* p) { - _compaction_manager->mark_and_push(p); -} - -inline void ParCompactionManager::MarkAndPushClosure::do_oop(oop* p) { do_oop_work(p); } -inline void ParCompactionManager::MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_work(p); } - inline void ParCompactionManager::follow_klass(Klass* klass) { oop holder = klass->klass_holder(); mark_and_push(&holder); @@ -101,19 +125,8 @@ _compaction_manager->follow_marking_stacks(); } -inline void ParCompactionManager::follow_class_loader(ClassLoaderData* cld) { - MarkAndPushClosure mark_and_push_closure(this); - - cld->oops_do(&mark_and_push_closure, true); -} - -inline void ParCompactionManager::follow_contents(oop obj) { - assert(PSParallelCompact::mark_bitmap()->is_marked(obj), "should be marked"); - obj->pc_follow_contents(this); -} - -template <class T> -inline void oop_pc_follow_contents_specialized(objArrayOop obj, int index, ParCompactionManager* cm) { +template <typename T> +inline void follow_array_specialized(objArrayOop obj, int index, ParCompactionManager* cm) { const size_t len = size_t(obj->length()); const size_t beg_index = size_t(index); assert(beg_index < len || len == 0, "index too large"); @@ -134,16 +147,34 @@ } } -inline void ParCompactionManager::follow_contents(objArrayOop obj, int index) { +inline void ParCompactionManager::follow_array(objArrayOop obj, int index) { if (UseCompressedOops) { - oop_pc_follow_contents_specialized<narrowOop>(obj, index, this); + follow_array_specialized<narrowOop>(obj, index, this); } else { - oop_pc_follow_contents_specialized<oop>(obj, index, this); + follow_array_specialized<oop>(obj, index, this); } } inline void ParCompactionManager::update_contents(oop obj) { - obj->pc_update_contents(this); + if (!obj->klass()->is_typeArray_klass()) { + PCAdjustPointerClosure apc(this); + obj->oop_iterate(&apc); + } +} + +inline void ParCompactionManager::follow_class_loader(ClassLoaderData* cld) { + PCMarkAndPushClosure mark_and_push_closure(this); + cld->oops_do(&mark_and_push_closure, true); +} + +inline void ParCompactionManager::follow_contents(oop obj) { + assert(PSParallelCompact::mark_bitmap()->is_marked(obj), "should be marked"); + if (obj->is_objArray()) { + follow_array(objArrayOop(obj), 0); + } else { + PCIterateMarkAndPushClosure cl(this, PSParallelCompact::ref_processor()); + obj->oop_iterate(&cl); + } } #endif // SHARE_VM_GC_PARALLEL_PSCOMPACTIONMANAGER_INLINE_HPP
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -846,18 +846,43 @@ bool PSParallelCompact::IsAliveClosure::do_object_b(oop p) { return mark_bitmap()->is_marked(p); } +class PCReferenceProcessor: public ReferenceProcessor { +public: + PCReferenceProcessor( + BoolObjectClosure* is_subject_to_discovery, + BoolObjectClosure* is_alive_non_header) : + ReferenceProcessor(is_subject_to_discovery, + ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing + ParallelGCThreads, // mt processing degree + true, // mt discovery + ParallelGCThreads, // mt discovery degree + true, // atomic_discovery + is_alive_non_header) { + } + + template<typename T> bool discover(oop obj, ReferenceType type) { + T* referent_addr = (T*) java_lang_ref_Reference::referent_addr_raw(obj); + T heap_oop = RawAccess<>::oop_load(referent_addr); + oop referent = CompressedOops::decode_not_null(heap_oop); + return PSParallelCompact::mark_bitmap()->is_unmarked(referent) + && ReferenceProcessor::discover_reference(obj, type); + } + virtual bool discover_reference(oop obj, ReferenceType type) { + if (UseCompressedOops) { + return discover<narrowOop>(obj, type); + } else { + return discover<oop>(obj, type); + } + } +}; + void PSParallelCompact::post_initialize() { ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); _span_based_discoverer.set_span(heap->reserved_region()); _ref_processor = - new ReferenceProcessor(&_span_based_discoverer, - ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing - ParallelGCThreads, // mt processing degree - true, // mt discovery - ParallelGCThreads, // mt discovery degree - true, // atomic_discovery - &_is_alive_closure, // non-header is alive closure - false); // disable adjusting number of processing threads + new PCReferenceProcessor(&_span_based_discoverer, + &_is_alive_closure); // non-header is alive closure + _counters = new CollectorCounters("PSParallelCompact", 1); // Initialize static fields in ParCompactionManager. @@ -2077,7 +2102,7 @@ TaskQueueSetSuper* qset = ParCompactionManager::stack_array(); ParallelTaskTerminator terminator(active_gc_threads, qset); - ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm); + PCMarkAndPushClosure mark_and_push_closure(cm); ParCompactionManager::FollowStackClosure follow_stack_closure(cm); // Need new claim bits before marking starts. @@ -2178,7 +2203,7 @@ // Need new claim bits when tracing through and adjusting pointers. ClassLoaderDataGraph::clear_claimed_marks(); - PSParallelCompact::AdjustPointerClosure oop_closure(cm); + PCAdjustPointerClosure oop_closure(cm); // General strong roots. Universe::oops_do(&oop_closure); @@ -3071,76 +3096,6 @@ update_state(words); } -void InstanceKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) { - PSParallelCompact::AdjustPointerClosure closure(cm); - if (UseCompressedOops) { - oop_oop_iterate_oop_maps<narrowOop>(obj, &closure); - } else { - oop_oop_iterate_oop_maps<oop>(obj, &closure); - } -} - -void InstanceMirrorKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) { - InstanceKlass::oop_pc_update_pointers(obj, cm); - - PSParallelCompact::AdjustPointerClosure closure(cm); - if (UseCompressedOops) { - oop_oop_iterate_statics<narrowOop>(obj, &closure); - } else { - oop_oop_iterate_statics<oop>(obj, &closure); - } -} - -void InstanceClassLoaderKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) { - InstanceKlass::oop_pc_update_pointers(obj, cm); -} - -#ifdef ASSERT -template <class T> static void trace_reference_gc(const char *s, oop obj, - T* referent_addr, - T* discovered_addr) { - log_develop_trace(gc, ref)("%s obj " PTR_FORMAT, s, p2i(obj)); - log_develop_trace(gc, ref)(" referent_addr/* " PTR_FORMAT " / " PTR_FORMAT, - p2i(referent_addr), referent_addr ? p2i((oop)RawAccess<>::oop_load(referent_addr)) : NULL); - log_develop_trace(gc, ref)(" discovered_addr/* " PTR_FORMAT " / " PTR_FORMAT, - p2i(discovered_addr), discovered_addr ? p2i((oop)RawAccess<>::oop_load(discovered_addr)) : NULL); -} -#endif - -template <class T> -static void oop_pc_update_pointers_specialized(oop obj, ParCompactionManager* cm) { - T* referent_addr = (T*)java_lang_ref_Reference::referent_addr_raw(obj); - PSParallelCompact::adjust_pointer(referent_addr, cm); - T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr_raw(obj); - PSParallelCompact::adjust_pointer(discovered_addr, cm); - debug_only(trace_reference_gc("InstanceRefKlass::oop_update_ptrs", obj, - referent_addr, discovered_addr);) -} - -void InstanceRefKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) { - InstanceKlass::oop_pc_update_pointers(obj, cm); - - if (UseCompressedOops) { - oop_pc_update_pointers_specialized<narrowOop>(obj, cm); - } else { - oop_pc_update_pointers_specialized<oop>(obj, cm); - } -} - -void ObjArrayKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) { - assert(obj->is_objArray(), "obj must be obj array"); - PSParallelCompact::AdjustPointerClosure closure(cm); - if (UseCompressedOops) { - oop_oop_iterate_elements<narrowOop>(objArrayOop(obj), &closure); - } else { - oop_oop_iterate_elements<oop>(objArrayOop(obj), &closure); - } -} - -void TypeArrayKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) { - assert(obj->is_typeArray(),"must be a type array"); -} - ParMarkBitMapClosure::IterationStatus MoveAndUpdateClosure::do_addr(HeapWord* addr, size_t words) { assert(destination() != NULL, "sanity");
--- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -934,23 +934,6 @@ virtual bool do_object_b(oop p); }; - class AdjustPointerClosure: public BasicOopIterateClosure { - public: - AdjustPointerClosure(ParCompactionManager* cm) { - assert(cm != NULL, "associate ParCompactionManage should not be NULL"); - _cm = cm; - } - template <typename T> void do_oop_work(T* p); - virtual void do_oop(oop* p); - virtual void do_oop(narrowOop* p); - - // This closure provides its own oop verification code. - debug_only(virtual bool should_verify_oops() { return false; }) - private: - ParCompactionManager* _cm; - }; - - friend class AdjustPointerClosure; friend class RefProcTaskProxy; friend class PSParallelCompactTest;
--- a/src/hotspot/share/gc/parallel/psParallelCompact.inline.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/parallel/psParallelCompact.inline.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -124,12 +124,21 @@ } } -template <typename T> -void PSParallelCompact::AdjustPointerClosure::do_oop_work(T* p) { - adjust_pointer(p, _cm); -} +class PCAdjustPointerClosure: public BasicOopIterateClosure { +public: + PCAdjustPointerClosure(ParCompactionManager* cm) { + assert(cm != NULL, "associate ParCompactionManage should not be NULL"); + _cm = cm; + } + template <typename T> void do_oop_nv(T* p) { PSParallelCompact::adjust_pointer(p, _cm); } + virtual void do_oop(oop* p) { do_oop_nv(p); } + virtual void do_oop(narrowOop* p) { do_oop_nv(p); } -inline void PSParallelCompact::AdjustPointerClosure::do_oop(oop* p) { do_oop_work(p); } -inline void PSParallelCompact::AdjustPointerClosure::do_oop(narrowOop* p) { do_oop_work(p); } + // This closure provides its own oop verification code. + debug_only(virtual bool should_verify_oops() { return false; }) + virtual ReferenceIterationMode reference_iteration_mode() { return DO_FIELDS; } +private: + ParCompactionManager* _cm; +}; #endif // SHARE_VM_GC_PARALLEL_PSPARALLELCOMPACT_INLINE_HPP
--- a/src/hotspot/share/gc/parallel/psPromotionManager.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/parallel/psPromotionManager.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -41,14 +41,7 @@ #include "memory/padded.inline.hpp" #include "memory/resourceArea.hpp" #include "oops/access.inline.hpp" -#include "oops/arrayOop.inline.hpp" #include "oops/compressedOops.inline.hpp" -#include "oops/instanceClassLoaderKlass.inline.hpp" -#include "oops/instanceKlass.inline.hpp" -#include "oops/instanceMirrorKlass.inline.hpp" -#include "oops/objArrayKlass.inline.hpp" -#include "oops/objArrayOop.inline.hpp" -#include "oops/oop.inline.hpp" PaddedEnd<PSPromotionManager>* PSPromotionManager::_manager_array = NULL; OopStarTaskQueueSet* PSPromotionManager::_stack_array_depth = NULL; @@ -397,101 +390,6 @@ } } -class PushContentsClosure : public BasicOopIterateClosure { - PSPromotionManager* _pm; - public: - PushContentsClosure(PSPromotionManager* pm) : _pm(pm) {} - - template <typename T> void do_oop_work(T* p) { - if (PSScavenge::should_scavenge(p)) { - _pm->claim_or_forward_depth(p); - } - } - - virtual void do_oop(oop* p) { do_oop_work(p); } - virtual void do_oop(narrowOop* p) { do_oop_work(p); } - - // Don't use the oop verification code in the oop_oop_iterate framework. - debug_only(virtual bool should_verify_oops() { return false; }) -}; - -void InstanceKlass::oop_ps_push_contents(oop obj, PSPromotionManager* pm) { - PushContentsClosure cl(pm); - if (UseCompressedOops) { - oop_oop_iterate_oop_maps_reverse<narrowOop>(obj, &cl); - } else { - oop_oop_iterate_oop_maps_reverse<oop>(obj, &cl); - } -} - -void InstanceMirrorKlass::oop_ps_push_contents(oop obj, PSPromotionManager* pm) { - // Note that we don't have to follow the mirror -> klass pointer, since all - // klasses that are dirty will be scavenged when we iterate over the - // ClassLoaderData objects. - - InstanceKlass::oop_ps_push_contents(obj, pm); - - PushContentsClosure cl(pm); - if (UseCompressedOops) { - oop_oop_iterate_statics<narrowOop>(obj, &cl); - } else { - oop_oop_iterate_statics<oop>(obj, &cl); - } -} - -void InstanceClassLoaderKlass::oop_ps_push_contents(oop obj, PSPromotionManager* pm) { - InstanceKlass::oop_ps_push_contents(obj, pm); - - // This is called by the young collector. It will already have taken care of - // all class loader data. So, we don't have to follow the class loader -> - // class loader data link. -} - -template <class T> -static void oop_ps_push_contents_specialized(oop obj, InstanceRefKlass *klass, PSPromotionManager* pm) { - T* referent_addr = (T*)java_lang_ref_Reference::referent_addr_raw(obj); - if (PSScavenge::should_scavenge(referent_addr)) { - ReferenceProcessor* rp = PSScavenge::reference_processor(); - if (rp->discover_reference(obj, klass->reference_type())) { - // reference discovered, referent will be traversed later. - klass->InstanceKlass::oop_ps_push_contents(obj, pm); - return; - } else { - // treat referent as normal oop - pm->claim_or_forward_depth(referent_addr); - } - } - // Treat discovered as normal oop - T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr_raw(obj); - if (PSScavenge::should_scavenge(discovered_addr)) { - pm->claim_or_forward_depth(discovered_addr); - } - klass->InstanceKlass::oop_ps_push_contents(obj, pm); -} - -void InstanceRefKlass::oop_ps_push_contents(oop obj, PSPromotionManager* pm) { - if (UseCompressedOops) { - oop_ps_push_contents_specialized<narrowOop>(obj, this, pm); - } else { - oop_ps_push_contents_specialized<oop>(obj, this, pm); - } -} - -void ObjArrayKlass::oop_ps_push_contents(oop obj, PSPromotionManager* pm) { - assert(obj->is_objArray(), "obj must be obj array"); - PushContentsClosure cl(pm); - if (UseCompressedOops) { - oop_oop_iterate_elements<narrowOop>(objArrayOop(obj), &cl); - } else { - oop_oop_iterate_elements<oop>(objArrayOop(obj), &cl); - } -} - -void TypeArrayKlass::oop_ps_push_contents(oop obj, PSPromotionManager* pm) { - assert(obj->is_typeArray(),"must be a type array"); - ShouldNotReachHere(); -} - oop PSPromotionManager::oop_promotion_failed(oop obj, markOop obj_mark) { assert(_old_gen_is_full || PromotionFailureALot, "Sanity");
--- a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -30,9 +30,10 @@ #include "gc/parallel/psOldGen.hpp" #include "gc/parallel/psPromotionLAB.inline.hpp" #include "gc/parallel/psPromotionManager.hpp" -#include "gc/parallel/psScavenge.hpp" +#include "gc/parallel/psScavenge.inline.hpp" #include "gc/shared/taskqueue.inline.hpp" #include "logging/log.hpp" +#include "memory/iterator.inline.hpp" #include "oops/access.inline.hpp" #include "oops/oop.inline.hpp" @@ -99,8 +100,48 @@ } } +class PSPushContentsClosure: public BasicOopIterateClosure { + PSPromotionManager* _pm; + public: + PSPushContentsClosure(PSPromotionManager* pm) : BasicOopIterateClosure(PSScavenge::reference_processor()), _pm(pm) {} + + template <typename T> void do_oop_nv(T* p) { + if (PSScavenge::should_scavenge(p)) { + _pm->claim_or_forward_depth(p); + } + } + + virtual void do_oop(oop* p) { do_oop_nv(p); } + virtual void do_oop(narrowOop* p) { do_oop_nv(p); } + + // Don't use the oop verification code in the oop_oop_iterate framework. + debug_only(virtual bool should_verify_oops() { return false; }) +}; + +// +// This closure specialization will override the one that is defined in +// instanceRefKlass.inline.cpp. It swaps the order of oop_oop_iterate and +// oop_oop_iterate_ref_processing. Unfortunately G1 and Parallel behaves +// significantly better (especially in the Derby benchmark) using opposite +// order of these function calls. +// +template <> +inline void InstanceRefKlass::oop_oop_iterate_reverse<oop, PSPushContentsClosure>(oop obj, PSPushContentsClosure* closure) { + oop_oop_iterate_ref_processing<oop>(obj, closure); + InstanceKlass::oop_oop_iterate_reverse<oop>(obj, closure); +} + +template <> +inline void InstanceRefKlass::oop_oop_iterate_reverse<narrowOop, PSPushContentsClosure>(oop obj, PSPushContentsClosure* closure) { + oop_oop_iterate_ref_processing<narrowOop>(obj, closure); + InstanceKlass::oop_oop_iterate_reverse<narrowOop>(obj, closure); +} + inline void PSPromotionManager::push_contents(oop obj) { - obj->ps_push_contents(this); + if (!obj->klass()->is_typeArray_klass()) { + PSPushContentsClosure pcc(this); + obj->oop_iterate_backwards(&pcc); + } } // // This method is pretty bulky. It would be nice to split it up
--- a/src/hotspot/share/gc/parallel/psScavenge.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -28,8 +28,10 @@ #include "gc/parallel/gcTaskManager.hpp" #include "gc/parallel/parallelScavengeHeap.hpp" #include "gc/parallel/psAdaptiveSizePolicy.hpp" +#include "gc/parallel/psClosure.inline.hpp" #include "gc/parallel/psMarkSweepProxy.hpp" #include "gc/parallel/psParallelCompact.inline.hpp" +#include "gc/parallel/psPromotionManager.inline.hpp" #include "gc/parallel/psScavenge.inline.hpp" #include "gc/parallel/psTasks.hpp" #include "gc/shared/collectorPolicy.hpp"
--- a/src/hotspot/share/gc/parallel/psScavenge.inline.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/parallel/psScavenge.inline.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -26,7 +26,6 @@ #define SHARE_VM_GC_PARALLEL_PSSCAVENGE_INLINE_HPP #include "gc/parallel/parallelScavengeHeap.hpp" -#include "gc/parallel/psPromotionManager.inline.hpp" #include "gc/parallel/psScavenge.hpp" #include "logging/log.hpp" #include "memory/iterator.hpp" @@ -65,93 +64,4 @@ return should_scavenge(p); } -template<bool promote_immediately> -class PSRootsClosure: public OopClosure { - private: - PSPromotionManager* _promotion_manager; - - protected: - template <class T> void do_oop_work(T *p) { - if (PSScavenge::should_scavenge(p)) { - // We never card mark roots, maybe call a func without test? - _promotion_manager->copy_and_push_safe_barrier<T, promote_immediately>(p); - } - } - public: - PSRootsClosure(PSPromotionManager* pm) : _promotion_manager(pm) { } - void do_oop(oop* p) { PSRootsClosure::do_oop_work(p); } - void do_oop(narrowOop* p) { PSRootsClosure::do_oop_work(p); } -}; - -typedef PSRootsClosure</*promote_immediately=*/false> PSScavengeRootsClosure; -typedef PSRootsClosure</*promote_immediately=*/true> PSPromoteRootsClosure; - -// Scavenges a single oop in a ClassLoaderData. -class PSScavengeFromCLDClosure: public OopClosure { - private: - PSPromotionManager* _pm; - // Used to redirty a scanned cld if it has oops - // pointing to the young generation after being scanned. - ClassLoaderData* _scanned_cld; - public: - PSScavengeFromCLDClosure(PSPromotionManager* pm) : _pm(pm), _scanned_cld(NULL) { } - void do_oop(narrowOop* p) { ShouldNotReachHere(); } - void do_oop(oop* p) { - ParallelScavengeHeap* psh = ParallelScavengeHeap::heap(); - assert(!psh->is_in_reserved(p), "GC barrier needed"); - if (PSScavenge::should_scavenge(p)) { - assert(PSScavenge::should_scavenge(p, true), "revisiting object?"); - - oop o = *p; - oop new_obj; - if (o->is_forwarded()) { - new_obj = o->forwardee(); - } else { - new_obj = _pm->copy_to_survivor_space</*promote_immediately=*/false>(o); - } - RawAccess<IS_NOT_NULL>::oop_store(p, new_obj); - - if (PSScavenge::is_obj_in_young(new_obj)) { - do_cld_barrier(); - } - } - } - - void set_scanned_cld(ClassLoaderData* cld) { - assert(_scanned_cld == NULL || cld == NULL, "Should always only handling one cld at a time"); - _scanned_cld = cld; - } - - private: - void do_cld_barrier() { - assert(_scanned_cld != NULL, "Should not be called without having a scanned cld"); - _scanned_cld->record_modified_oops(); - } -}; - -// Scavenges the oop in a ClassLoaderData. -class PSScavengeCLDClosure: public CLDClosure { - private: - PSScavengeFromCLDClosure _oop_closure; - protected: - public: - PSScavengeCLDClosure(PSPromotionManager* pm) : _oop_closure(pm) { } - void do_cld(ClassLoaderData* cld) { - // If the cld has not been dirtied we know that there's - // no references into the young gen and we can skip it. - - if (cld->has_modified_oops()) { - // Setup the promotion manager to redirty this cld - // if references are left in the young gen. - _oop_closure.set_scanned_cld(cld); - - // Clean the cld since we're going to scavenge all the metadata. - cld->oops_do(&_oop_closure, false, /*clear_modified_oops*/true); - - _oop_closure.set_scanned_cld(NULL); - } - } -}; - - #endif // SHARE_VM_GC_PARALLEL_PSSCAVENGE_INLINE_HPP
--- a/src/hotspot/share/gc/parallel/psTasks.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/parallel/psTasks.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -29,6 +29,7 @@ #include "code/codeCache.hpp" #include "gc/parallel/gcTaskManager.hpp" #include "gc/parallel/psCardTable.hpp" +#include "gc/parallel/psClosure.inline.hpp" #include "gc/parallel/psPromotionManager.hpp" #include "gc/parallel/psPromotionManager.inline.hpp" #include "gc/parallel/psScavenge.inline.hpp"
--- a/src/hotspot/share/gc/shared/barrierSet.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/barrierSet.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -130,6 +130,10 @@ virtual void on_thread_detach(JavaThread* thread) {} virtual void make_parsable(JavaThread* thread) {} +#ifdef CHECK_UNHANDLED_OOPS + virtual bool oop_equals_operator_allowed() { return true; } +#endif + public: // Print a description of the memory for the barrier set virtual void print_on(outputStream* st) const = 0;
--- a/src/hotspot/share/gc/shared/collectedHeap.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -445,6 +445,15 @@ CollectedHeap::fill_with_object(start, end, zap); } +size_t CollectedHeap::min_dummy_object_size() const { + return oopDesc::header_size(); +} + +size_t CollectedHeap::tlab_alloc_reserve() const { + size_t min_size = min_dummy_object_size(); + return min_size > (size_t)MinObjAlignment ? align_object_size(min_size) : 0; +} + HeapWord* CollectedHeap::allocate_new_tlab(size_t min_size, size_t requested_size, size_t* actual_size) { @@ -586,3 +595,7 @@ void CollectedHeap::deduplicate_string(oop str) { // Do nothing, unless overridden in subclass. } + +size_t CollectedHeap::obj_size(oop obj) const { + return obj->size(); +}
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -309,6 +309,8 @@ } virtual void fill_with_dummy_object(HeapWord* start, HeapWord* end, bool zap); + virtual size_t min_dummy_object_size() const; + size_t tlab_alloc_reserve() const; // Return the address "addr" aligned by "alignment_in_bytes" if such // an address is below "end". Return NULL otherwise. @@ -576,6 +578,8 @@ virtual bool is_oop(oop object) const; + virtual size_t obj_size(oop obj) const; + // Non product verification and debugging. #ifndef PRODUCT // Support for PromotionFailureALot. Return true if it's time to cause a
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -649,9 +649,6 @@ // a whole heap collection. complete = complete || collected_old; - print_heap_change(young_prev_used, old_prev_used); - MetaspaceUtils::print_metaspace_change(metadata_prev_used); - // Adjust generation sizes. if (collected_old) { _old_gen->compute_new_size(); @@ -667,6 +664,9 @@ update_full_collections_completed(); } + print_heap_change(young_prev_used, old_prev_used); + MetaspaceUtils::print_metaspace_change(metadata_prev_used); + // Track memory usage and detect low memory after GC finishes MemoryService::track_memory_usage();
--- a/src/hotspot/share/gc/shared/memAllocator.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/memAllocator.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -120,27 +120,22 @@ return false; } - if (!_overhead_limit_exceeded) { + const char* message = _overhead_limit_exceeded ? "GC overhead limit exceeded" : "Java heap space"; + if (!THREAD->in_retryable_allocation()) { // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support - report_java_out_of_memory("Java heap space"); + report_java_out_of_memory(message); if (JvmtiExport::should_post_resource_exhausted()) { JvmtiExport::post_resource_exhausted( JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP, - "Java heap space"); + message); } - THROW_OOP_(Universe::out_of_memory_error_java_heap(), true); + oop exception = _overhead_limit_exceeded ? + Universe::out_of_memory_error_gc_overhead_limit() : + Universe::out_of_memory_error_java_heap(); + THROW_OOP_(exception, true); } else { - // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support - report_java_out_of_memory("GC overhead limit exceeded"); - - if (JvmtiExport::should_post_resource_exhausted()) { - JvmtiExport::post_resource_exhausted( - JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP, - "GC overhead limit exceeded"); - } - - THROW_OOP_(Universe::out_of_memory_error_gc_overhead_limit(), true); + THROW_OOP_(Universe::out_of_memory_error_retry(), true); } } @@ -192,7 +187,7 @@ // support for JVMTI VMObjectAlloc event (no-op if not enabled) JvmtiExport::vm_object_alloc_event_collector(obj()); - if (!ThreadHeapSampler::enabled()) { + if (!JvmtiExport::should_post_sampled_object_alloc()) { // Sampling disabled return; } @@ -203,15 +198,6 @@ return; } - assert(JavaThread::current()->heap_sampler().add_sampling_collector(), - "Should never return false."); - - // Only check if the sampler could actually sample something in this path. - assert(!JvmtiExport::should_post_sampled_object_alloc() || - !JvmtiSampledObjectAllocEventCollector::object_alloc_is_safe_to_sample() || - _thread->heap_sampler().sampling_collector_present(), - "Sampling collector not present."); - if (JvmtiExport::should_post_sampled_object_alloc()) { // If we want to be sampling, protect the allocated object with a Handle // before doing the callback. The callback is done in the destructor of @@ -224,8 +210,6 @@ _thread->heap_sampler().check_for_sampling(obj_h(), size_in_bytes, bytes_since_last); } - assert(JavaThread::current()->heap_sampler().remove_sampling_collector(), "Should never return false."); - if (_tlab_end_reset_for_sample || _allocated_tlab_size != 0) { _thread->tlab().set_sample_end(); } @@ -298,7 +282,7 @@ HeapWord* mem = NULL; ThreadLocalAllocBuffer& tlab = _thread->tlab(); - if (ThreadHeapSampler::enabled()) { + if (JvmtiExport::should_post_sampled_object_alloc()) { // Try to allocate the sampled object from TLAB, it is possible a sample // point was put and the TLAB still has space. tlab.set_back_allocation_end();
--- a/src/hotspot/share/gc/shared/oopStorage.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/oopStorage.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -727,7 +727,7 @@ _allocation_mutex(allocation_mutex), _active_mutex(active_mutex), _allocation_count(0), - _concurrent_iteration_active(false) + _concurrent_iteration_count(0) { _active_array->increment_refcount(); assert(_active_mutex->rank() < _allocation_mutex->rank(), @@ -769,7 +769,7 @@ // blocks available for deletion. while (reduce_deferred_updates()) {} // Don't interfere with a concurrent iteration. - if (_concurrent_iteration_active) return; + if (_concurrent_iteration_count > 0) return; // Delete empty (and otherwise deletable) blocks from end of _allocation_list. for (Block* block = _allocation_list.tail(); (block != NULL) && block->is_deletable(); @@ -804,7 +804,7 @@ { MutexLockerEx aml(_active_mutex, Mutex::_no_safepoint_check_flag); // Don't interfere with a concurrent iteration. - if (_concurrent_iteration_active) return; + if (_concurrent_iteration_count > 0) return; _active_array->remove(block); } // Remove block from _allocation_list and delete it. @@ -875,7 +875,7 @@ _concurrent(concurrent) { assert(estimated_thread_count > 0, "estimated thread count must be positive"); - update_iteration_state(true); + update_concurrent_iteration_count(1); // Get the block count *after* iteration state updated, so concurrent // empty block deletion is suppressed and can't reduce the count. But // ensure the count we use was written after the block with that count @@ -885,14 +885,14 @@ OopStorage::BasicParState::~BasicParState() { _storage->relinquish_block_array(_active_array); - update_iteration_state(false); + update_concurrent_iteration_count(-1); } -void OopStorage::BasicParState::update_iteration_state(bool value) { +void OopStorage::BasicParState::update_concurrent_iteration_count(int value) { if (_concurrent) { MutexLockerEx ml(_storage->_active_mutex, Mutex::_no_safepoint_check_flag); - assert(_storage->_concurrent_iteration_active != value, "precondition"); - _storage->_concurrent_iteration_active = value; + _storage->_concurrent_iteration_count += value; + assert(_storage->_concurrent_iteration_count >= 0, "invariant"); } } @@ -954,7 +954,7 @@ st->print("%s: " SIZE_FORMAT " entries in " SIZE_FORMAT " blocks (%.F%%), " SIZE_FORMAT " bytes", name(), allocations, blocks, alloc_percentage, total_memory_usage()); - if (_concurrent_iteration_active) { + if (_concurrent_iteration_count > 0) { st->print(", concurrent iteration active"); } }
--- a/src/hotspot/share/gc/shared/oopStorage.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/oopStorage.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -220,7 +220,7 @@ mutable SingleWriterSynchronizer _protect_active; // mutable because this gets set even for const iteration. - mutable bool _concurrent_iteration_active; + mutable int _concurrent_iteration_count; Block* find_block_or_null(const oop* ptr) const; void delete_empty_block(const Block& block);
--- a/src/hotspot/share/gc/shared/oopStorageParState.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/oopStorageParState.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -31,22 +31,16 @@ ////////////////////////////////////////////////////////////////////////////// // Support for parallel and optionally concurrent state iteration. // -// Parallel iteration is for the exclusive use of the GC. Other iteration -// clients must use serial iteration. -// // Concurrent Iteration // // Iteration involves the _active_array (an ActiveArray), which contains all // of the blocks owned by a storage object. // -// At most one concurrent ParState can exist at a time for a given storage -// object. -// -// A concurrent ParState sets the associated storage's -// _concurrent_iteration_active flag true when the state is constructed, and -// sets it false when the state is destroyed. These assignments are made with +// A concurrent ParState increments the associated storage's +// _concurrent_iteration_count when the state is constructed, and +// decrements it when the state is destroyed. These assignments are made with // _active_mutex locked. Meanwhile, empty block deletion is not done while -// _concurrent_iteration_active is true. The flag check and the dependent +// _concurrent_iteration_count is non-zero. The counter check and the dependent // removal of a block from the _active_array is performed with _active_mutex // locked. This prevents concurrent iteration and empty block deletion from // interfering with with each other. @@ -83,8 +77,8 @@ // scheduling both operations to run at the same time. // // ParState<concurrent, is_const> -// concurrent must be true if iteration is concurrent with the -// mutator, false if iteration is at a safepoint. +// concurrent must be true if iteration may be concurrent with the +// mutators. // // is_const must be true if the iteration is over a constant storage // object, false if the iteration may modify the storage object. @@ -92,8 +86,7 @@ // ParState([const] OopStorage* storage) // Construct an object for managing an iteration over storage. For a // concurrent ParState, empty block deletion for the associated storage -// is inhibited for the life of the ParState. There can be no more -// than one live concurrent ParState at a time for a given storage object. +// is inhibited for the life of the ParState. // // template<typename F> void iterate(F f) // Repeatedly claims a block from the associated storage that has @@ -152,7 +145,7 @@ struct IterationData; - void update_iteration_state(bool value); + void update_concurrent_iteration_count(int value); bool claim_next_segment(IterationData* data); bool finish_iteration(const IterationData* data) const;
--- a/src/hotspot/share/gc/shared/plab.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/plab.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -27,7 +27,6 @@ #include "gc/shared/plab.inline.hpp" #include "gc/shared/threadLocalAllocBuffer.hpp" #include "logging/log.hpp" -#include "oops/arrayOop.hpp" #include "oops/oop.inline.hpp" size_t PLAB::min_size() { @@ -43,8 +42,7 @@ _word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL), _end(NULL), _hard_end(NULL), _allocated(0), _wasted(0), _undo_wasted(0) { - // ArrayOopDesc::header_size depends on command line initialization. - AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? align_object_size(arrayOopDesc::header_size(T_INT)) : 0; + AlignmentReserve = Universe::heap()->tlab_alloc_reserve(); assert(min_size() > AlignmentReserve, "Minimum PLAB size " SIZE_FORMAT " must be larger than alignment reserve " SIZE_FORMAT " " "to be able to contain objects", min_size(), AlignmentReserve);
--- a/src/hotspot/share/gc/shared/referenceProcessor.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/referenceProcessor.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -284,7 +284,7 @@ // First _prev_next ref actually points into DiscoveredList (gross). oop new_next; - if (_next_discovered == _current_discovered) { + if (oopDesc::equals_raw(_next_discovered, _current_discovered)) { // At the end of the list, we should make _prev point to itself. // If _ref is the first ref, then _prev_next will be in the DiscoveredList, // and _prev will be NULL. @@ -474,7 +474,7 @@ ReferenceProcessor::clear_discovered_references(DiscoveredList& refs_list) { oop obj = NULL; oop next = refs_list.head(); - while (next != obj) { + while (!oopDesc::equals_raw(next, obj)) { obj = next; next = java_lang_ref_Reference::discovered(obj); java_lang_ref_Reference::set_discovered_raw(obj, NULL); @@ -746,7 +746,7 @@ ref_lists[to_idx].inc_length(refs_to_move); // Remove the chain from the from list. - if (move_tail == new_head) { + if (oopDesc::equals_raw(move_tail, new_head)) { // We found the end of the from list. ref_lists[from_idx].set_head(NULL); } else {
--- a/src/hotspot/share/gc/shared/referenceProcessor.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/referenceProcessor.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -143,13 +143,13 @@ inline size_t removed() const { return _removed; } inline void move_to_next() { - if (_current_discovered == _next_discovered) { + if (oopDesc::equals_raw(_current_discovered, _next_discovered)) { // End of the list. _current_discovered = NULL; } else { _current_discovered = _next_discovered; } - assert(_current_discovered != _first_seen, "cyclic ref_list found"); + assert(!oopDesc::equals_raw(_current_discovered, _first_seen), "cyclic ref_list found"); _processed++; } };
--- a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -375,7 +375,7 @@ } typeArrayOop existing_value = lookup_or_add(value, latin1, hash); - if (existing_value == value) { + if (oopDesc::equals_raw(existing_value, value)) { // Same value, already known stat->inc_known(); return;
--- a/src/hotspot/share/gc/shared/taskqueue.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/taskqueue.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -370,6 +370,8 @@ public: // Returns "true" if some TaskQueue in the set contains a task. virtual bool peek() = 0; + // Tasks in queue + virtual uint tasks() const = 0; }; template <MEMFLAGS F> class TaskQueueSetSuperImpl: public CHeapObj<F>, public TaskQueueSetSuper { @@ -399,6 +401,7 @@ bool steal(uint queue_num, E& t); bool peek(); + uint tasks() const; uint size() const { return _n; } }; @@ -424,6 +427,15 @@ return false; } +template<class T, MEMFLAGS F> +uint GenericTaskQueueSet<T, F>::tasks() const { + uint n = 0; + for (uint j = 0; j < _n; j++) { + n += _queues[j]->size(); + } + return n; +} + // When to terminate from the termination protocol. class TerminatorTerminator: public CHeapObj<mtInternal> { public:
--- a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/threadLocalAllocBuffer.inline.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" @@ -461,3 +462,8 @@ _perf_max_slow_allocations ->set_value(_max_slow_allocations); } } + +size_t ThreadLocalAllocBuffer::end_reserve() { + size_t reserve_size = Universe::heap()->tlab_alloc_reserve(); + return MAX2(reserve_size, (size_t)_reserve_for_allocation_prefetch); +}
--- a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -26,7 +26,6 @@ #define SHARE_VM_GC_SHARED_THREADLOCALALLOCBUFFER_HPP #include "gc/shared/gcUtil.hpp" -#include "oops/typeArrayOop.hpp" #include "runtime/perfData.hpp" #include "runtime/vm_version.hpp" @@ -138,10 +137,7 @@ inline HeapWord* allocate(size_t size); // Reserve space at the end of TLAB - static size_t end_reserve() { - int reserve_size = typeArrayOopDesc::header_size(T_INT); - return MAX2(reserve_size, _reserve_for_allocation_prefetch); - } + static size_t end_reserve(); static size_t alignment_reserve() { return align_object_size(end_reserve()); } static size_t alignment_reserve_in_bytes() { return alignment_reserve() * HeapWordSize; }
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -1427,6 +1427,10 @@ return c; } +bool ZBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const { + return type == T_OBJECT || type == T_ARRAY; +} + // == Verification == #ifdef ASSERT
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -194,7 +194,7 @@ virtual void enqueue_useful_gc_barrier(Unique_Node_List &worklist, Node* node) const; virtual void register_potential_barrier_node(Node* node) const; virtual void unregister_potential_barrier_node(Node* node) const; - virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const { return true; } + virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const; virtual Node* step_over_gc_barrier(Node* c) const; // If the BarrierSetC2 state has kept macro nodes in its compilation unit state to be // expanded later, then now is the time to do so.
--- a/src/hotspot/share/interpreter/linkResolver.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/interpreter/linkResolver.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -793,24 +793,6 @@ check_method_loader_constraints(link_info, resolved_method, "method", CHECK_NULL); } - // For private method invocation we should only find the method in the resolved class. - // If that is not the case then we have a found a supertype method that we have nestmate - // access to. - if (resolved_method->is_private() && resolved_method->method_holder() != resolved_klass) { - ResourceMark rm(THREAD); - DEBUG_ONLY(bool is_nestmate = InstanceKlass::cast(link_info.current_klass())->has_nestmate_access_to(InstanceKlass::cast(resolved_klass), THREAD);) - assert(is_nestmate, "was only expecting nestmates to get here!"); - Exceptions::fthrow( - THREAD_AND_LOCATION, - vmSymbols::java_lang_NoSuchMethodError(), - "%s: method %s%s not found", - resolved_klass->external_name(), - resolved_method->name()->as_C_string(), - resolved_method->signature()->as_C_string() - ); - return NULL; - } - return resolved_method; }
--- a/src/hotspot/share/interpreter/templateTable.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/interpreter/templateTable.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -36,6 +36,7 @@ // and the snippet generator, a template is assigned to each bytecode which can be // used to generate the bytecode's implementation if needed. +class BarrierSet; class InterpreterMacroAssembler; // A Template describes the properties of a code template for a given bytecode
--- a/src/hotspot/share/jvmci/jvmciEnv.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -148,7 +148,7 @@ require_local); if (elem_klass != NULL) { // Now make an array for it - return elem_klass->array_klass(CHECK_NULL); + return elem_klass->array_klass(THREAD); } }
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -109,22 +109,72 @@ } } -JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_instance(JavaThread* thread, Klass* klass)) +// Manages a scope for a JVMCI runtime call that attempts a heap allocation. +// If there is a pending exception upon closing the scope and the runtime +// call is of the variety where allocation failure returns NULL without an +// exception, the following action is taken: +// 1. The pending exception is cleared +// 2. NULL is written to JavaThread::_vm_result +// 3. Checks that an OutOfMemoryError is Universe::out_of_memory_error_retry(). +class RetryableAllocationMark: public StackObj { + private: + JavaThread* _thread; + public: + RetryableAllocationMark(JavaThread* thread, bool activate) { + if (activate) { + assert(!thread->in_retryable_allocation(), "retryable allocation scope is non-reentrant"); + _thread = thread; + _thread->set_in_retryable_allocation(true); + } else { + _thread = NULL; + } + } + ~RetryableAllocationMark() { + if (_thread != NULL) { + _thread->set_in_retryable_allocation(false); + JavaThread* THREAD = _thread; + if (HAS_PENDING_EXCEPTION) { + oop ex = PENDING_EXCEPTION; + CLEAR_PENDING_EXCEPTION; + oop retry_oome = Universe::out_of_memory_error_retry(); + if (ex->is_a(retry_oome->klass()) && retry_oome != ex) { + ResourceMark rm; + fatal("Unexpected exception in scope of retryable allocation: " INTPTR_FORMAT " of type %s", p2i(ex), ex->klass()->external_name()); + } + _thread->set_vm_result(NULL); + } + } + } +}; + +JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_instance_common(JavaThread* thread, Klass* klass, bool null_on_fail)) JRT_BLOCK; assert(klass->is_klass(), "not a class"); Handle holder(THREAD, klass->klass_holder()); // keep the klass alive InstanceKlass* ik = InstanceKlass::cast(klass); - ik->check_valid_for_instantiation(true, CHECK); - // make sure klass is initialized - ik->initialize(CHECK); - // allocate instance and return via TLS - oop obj = ik->allocate_instance(CHECK); - thread->set_vm_result(obj); + { + RetryableAllocationMark ram(thread, null_on_fail); + ik->check_valid_for_instantiation(true, CHECK); + oop obj; + if (null_on_fail) { + if (!ik->is_initialized()) { + // Cannot re-execute class initialization without side effects + // so return without attempting the initialization + return; + } + } else { + // make sure klass is initialized + ik->initialize(CHECK); + } + // allocate instance and return via TLS + obj = ik->allocate_instance(CHECK); + thread->set_vm_result(obj); + } JRT_BLOCK_END; SharedRuntime::on_slowpath_allocation_exit(thread); JRT_END -JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array(JavaThread* thread, Klass* array_klass, jint length)) +JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array_common(JavaThread* thread, Klass* array_klass, jint length, bool null_on_fail)) JRT_BLOCK; // Note: no handle for klass needed since they are not used // anymore after new_objArray() and no GC can happen before. @@ -133,10 +183,12 @@ oop obj; if (array_klass->is_typeArray_klass()) { BasicType elt_type = TypeArrayKlass::cast(array_klass)->element_type(); + RetryableAllocationMark ram(thread, null_on_fail); obj = oopFactory::new_typeArray(elt_type, length, CHECK); } else { Handle holder(THREAD, array_klass->klass_holder()); // keep the klass alive Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass(); + RetryableAllocationMark ram(thread, null_on_fail); obj = oopFactory::new_objArray(elem_klass, length, CHECK); } thread->set_vm_result(obj); @@ -146,8 +198,12 @@ static int deopts = 0; // Alternate between deoptimizing and raising an error (which will also cause a deopt) if (deopts++ % 2 == 0) { - ResourceMark rm(THREAD); - THROW(vmSymbols::java_lang_OutOfMemoryError()); + if (null_on_fail) { + return; + } else { + ResourceMark rm(THREAD); + THROW(vmSymbols::java_lang_OutOfMemoryError()); + } } else { deopt_caller(); } @@ -156,32 +212,43 @@ SharedRuntime::on_slowpath_allocation_exit(thread); JRT_END -JRT_ENTRY(void, JVMCIRuntime::new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims)) +JRT_ENTRY(void, JVMCIRuntime::new_multi_array_common(JavaThread* thread, Klass* klass, int rank, jint* dims, bool null_on_fail)) assert(klass->is_klass(), "not a class"); assert(rank >= 1, "rank must be nonzero"); Handle holder(THREAD, klass->klass_holder()); // keep the klass alive + RetryableAllocationMark ram(thread, null_on_fail); oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK); thread->set_vm_result(obj); JRT_END -JRT_ENTRY(void, JVMCIRuntime::dynamic_new_array(JavaThread* thread, oopDesc* element_mirror, jint length)) +JRT_ENTRY(void, JVMCIRuntime::dynamic_new_array_common(JavaThread* thread, oopDesc* element_mirror, jint length, bool null_on_fail)) + RetryableAllocationMark ram(thread, null_on_fail); oop obj = Reflection::reflect_new_array(element_mirror, length, CHECK); thread->set_vm_result(obj); JRT_END -JRT_ENTRY(void, JVMCIRuntime::dynamic_new_instance(JavaThread* thread, oopDesc* type_mirror)) +JRT_ENTRY(void, JVMCIRuntime::dynamic_new_instance_common(JavaThread* thread, oopDesc* type_mirror, bool null_on_fail)) InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(type_mirror)); if (klass == NULL) { ResourceMark rm(THREAD); THROW(vmSymbols::java_lang_InstantiationException()); } + RetryableAllocationMark ram(thread, null_on_fail); // Create new instance (the receiver) klass->check_valid_for_instantiation(false, CHECK); - // Make sure klass gets initialized - klass->initialize(CHECK); + if (null_on_fail) { + if (!klass->is_initialized()) { + // Cannot re-execute class initialization without side effects + // so return without attempting the initialization + return; + } + } else { + // Make sure klass gets initialized + klass->initialize(CHECK); + } oop obj = klass->allocate_instance(CHECK); thread->set_vm_result(obj);
--- a/src/hotspot/share/jvmci/jvmciRuntime.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -121,13 +121,35 @@ static BasicType kindToBasicType(Handle kind, TRAPS); - // The following routines are all called from compiled JVMCI code + static void new_instance_common(JavaThread* thread, Klass* klass, bool null_on_fail); + static void new_array_common(JavaThread* thread, Klass* klass, jint length, bool null_on_fail); + static void new_multi_array_common(JavaThread* thread, Klass* klass, int rank, jint* dims, bool null_on_fail); + static void dynamic_new_array_common(JavaThread* thread, oopDesc* element_mirror, jint length, bool null_on_fail); + static void dynamic_new_instance_common(JavaThread* thread, oopDesc* type_mirror, bool null_on_fail); - static void new_instance(JavaThread* thread, Klass* klass); - static void new_array(JavaThread* thread, Klass* klass, jint length); - static void new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims); - static void dynamic_new_array(JavaThread* thread, oopDesc* element_mirror, jint length); - static void dynamic_new_instance(JavaThread* thread, oopDesc* type_mirror); + // The following routines are called from compiled JVMCI code + + // When allocation fails, these stubs: + // 1. Exercise -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError handling and also + // post a JVMTI_EVENT_RESOURCE_EXHAUSTED event if the failure is an OutOfMemroyError + // 2. Return NULL with a pending exception. + // Compiled code must ensure these stubs are not called twice for the same allocation + // site due to the non-repeatable side effects in the case of OOME. + static void new_instance(JavaThread* thread, Klass* klass) { new_instance_common(thread, klass, false); } + static void new_array(JavaThread* thread, Klass* klass, jint length) { new_array_common(thread, klass, length, false); } + static void new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims) { new_multi_array_common(thread, klass, rank, dims, false); } + static void dynamic_new_array(JavaThread* thread, oopDesc* element_mirror, jint length) { dynamic_new_array_common(thread, element_mirror, length, false); } + static void dynamic_new_instance(JavaThread* thread, oopDesc* type_mirror) { dynamic_new_instance_common(thread, type_mirror, false); } + + // When allocation fails, these stubs return NULL and have no pending exception. Compiled code + // can use these stubs if a failed allocation will be retried (e.g., by deoptimizing and + // re-executing in the interpreter). + static void new_instance_or_null(JavaThread* thread, Klass* klass) { new_instance_common(thread, klass, true); } + static void new_array_or_null(JavaThread* thread, Klass* klass, jint length) { new_array_common(thread, klass, length, true); } + static void new_multi_array_or_null(JavaThread* thread, Klass* klass, int rank, jint* dims) { new_multi_array_common(thread, klass, rank, dims, true); } + static void dynamic_new_array_or_null(JavaThread* thread, oopDesc* element_mirror, jint length) { dynamic_new_array_common(thread, element_mirror, length, true); } + static void dynamic_new_instance_or_null(JavaThread* thread, oopDesc* type_mirror) { dynamic_new_instance_common(thread, type_mirror, true); } + static jboolean thread_is_interrupted(JavaThread* thread, oopDesc* obj, jboolean clear_interrupted); static void vm_message(jboolean vmError, jlong format, jlong v1, jlong v2, jlong v3); static jint identity_hash_code(JavaThread* thread, oopDesc* obj);
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -622,6 +622,12 @@ declare_function(JVMCIRuntime::dynamic_new_array) \ declare_function(JVMCIRuntime::dynamic_new_instance) \ \ + declare_function(JVMCIRuntime::new_instance_or_null) \ + declare_function(JVMCIRuntime::new_array_or_null) \ + declare_function(JVMCIRuntime::new_multi_array_or_null) \ + declare_function(JVMCIRuntime::dynamic_new_array_or_null) \ + declare_function(JVMCIRuntime::dynamic_new_instance_or_null) \ + \ declare_function(JVMCIRuntime::thread_is_interrupted) \ declare_function(JVMCIRuntime::vm_message) \ declare_function(JVMCIRuntime::identity_hash_code) \
--- a/src/hotspot/share/memory/filemap.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/memory/filemap.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -191,7 +191,7 @@ _shared_path_table_size = mapinfo->_shared_path_table_size; _shared_path_table = mapinfo->_shared_path_table; _shared_path_entry_size = mapinfo->_shared_path_entry_size; - if (MetaspaceShared::is_heap_object_archiving_allowed()) { + if (HeapShared::is_heap_object_archiving_allowed()) { _heap_reserved = Universe::heap()->reserved_region(); } @@ -908,7 +908,7 @@ // regions may be added. GC may mark and update references in the mapped // open archive objects. void FileMapInfo::map_heap_regions_impl() { - if (!MetaspaceShared::is_heap_object_archiving_allowed()) { + if (!HeapShared::is_heap_object_archiving_allowed()) { log_info(cds)("CDS heap data is being ignored. UseG1GC, " "UseCompressedOops and UseCompressedClassPointers are required."); return; @@ -1000,7 +1000,7 @@ MetaspaceShared::max_open_archive_heap_region, &num_open_archive_heap_ranges, true /* open */)) { - MetaspaceShared::set_open_archive_heap_region_mapped(); + HeapShared::set_open_archive_heap_region_mapped(); } } } @@ -1014,7 +1014,7 @@ assert(string_ranges == NULL && num_string_ranges == 0, "sanity"); } - if (!MetaspaceShared::open_archive_heap_region_mapped()) { + if (!HeapShared::open_archive_heap_region_mapped()) { assert(open_archive_heap_ranges == NULL && num_open_archive_heap_ranges == 0, "sanity"); } } @@ -1088,8 +1088,8 @@ } bool FileMapInfo::verify_mapped_heap_regions(int first, int num) { - for (int i = first; - i <= first + num; i++) { + assert(num > 0, "sanity"); + for (int i = first; i < first + num; i++) { if (!verify_region_checksum(i)) { return false; } @@ -1160,7 +1160,7 @@ if ((MetaspaceShared::is_string_region(i) && !StringTable::shared_string_mapped()) || (MetaspaceShared::is_open_archive_heap_region(i) && - !MetaspaceShared::open_archive_heap_region_mapped())) { + !HeapShared::open_archive_heap_region_mapped())) { return true; // archived heap data is not mapped } const char* buf = region_addr(i);
--- a/src/hotspot/share/memory/heapShared.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/memory/heapShared.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -24,66 +24,218 @@ #include "precompiled.hpp" #include "classfile/javaClasses.inline.hpp" +#include "classfile/stringTable.hpp" #include "classfile/symbolTable.hpp" #include "classfile/vmSymbols.hpp" #include "logging/log.hpp" #include "logging/logMessage.hpp" #include "logging/logStream.hpp" +#include "memory/filemap.hpp" #include "memory/heapShared.inline.hpp" #include "memory/iterator.inline.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" -#include "memory/metaspaceShared.inline.hpp" #include "memory/resourceArea.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/fieldDescriptor.inline.hpp" +#include "runtime/safepointVerifiers.hpp" #include "utilities/bitMap.inline.hpp" +#if INCLUDE_G1GC +#include "gc/g1/g1CollectedHeap.hpp" +#endif #if INCLUDE_CDS_JAVA_HEAP -KlassSubGraphInfo* HeapShared::_subgraph_info_list = NULL; -int HeapShared::_num_archived_subgraph_info_records = 0; -Array<ArchivedKlassSubGraphInfoRecord>* HeapShared::_archived_subgraph_info_records = NULL; -KlassSubGraphInfo* HeapShared::find_subgraph_info(Klass* k) { - KlassSubGraphInfo* info = _subgraph_info_list; - while (info != NULL) { - if (info->klass() == k) { - return info; - } - info = info->next(); +bool HeapShared::_open_archive_heap_region_mapped = false; +bool HeapShared::_archive_heap_region_fixed = false; + +address HeapShared::_narrow_oop_base; +int HeapShared::_narrow_oop_shift; + +//////////////////////////////////////////////////////////////// +// +// Java heap object archiving support +// +//////////////////////////////////////////////////////////////// +void HeapShared::fixup_mapped_heap_regions() { + FileMapInfo *mapinfo = FileMapInfo::current_info(); + mapinfo->fixup_mapped_heap_regions(); + set_archive_heap_region_fixed(); +} + +unsigned HeapShared::oop_hash(oop const& p) { + assert(!p->mark()->has_bias_pattern(), + "this object should never have been locked"); // so identity_hash won't safepoin + unsigned hash = (unsigned)p->identity_hash(); + return hash; +} + +HeapShared::ArchivedObjectCache* HeapShared::_archived_object_cache = NULL; +oop HeapShared::find_archived_heap_object(oop obj) { + assert(DumpSharedSpaces, "dump-time only"); + ArchivedObjectCache* cache = archived_object_cache(); + oop* p = cache->get(obj); + if (p != NULL) { + return *p; + } else { + return NULL; + } +} + +oop HeapShared::archive_heap_object(oop obj, Thread* THREAD) { + assert(DumpSharedSpaces, "dump-time only"); + + oop ao = find_archived_heap_object(obj); + if (ao != NULL) { + // already archived + return ao; + } + + int len = obj->size(); + if (G1CollectedHeap::heap()->is_archive_alloc_too_large(len)) { + log_debug(cds, heap)("Cannot archive, object (" PTR_FORMAT ") is too large: " SIZE_FORMAT, + p2i(obj), (size_t)obj->size()); + return NULL; + } + + // Pre-compute object identity hash at CDS dump time. + obj->identity_hash(); + + oop archived_oop = (oop)G1CollectedHeap::heap()->archive_mem_allocate(len); + if (archived_oop != NULL) { + Copy::aligned_disjoint_words((HeapWord*)obj, (HeapWord*)archived_oop, len); + MetaspaceShared::relocate_klass_ptr(archived_oop); + ArchivedObjectCache* cache = archived_object_cache(); + cache->put(obj, archived_oop); + log_debug(cds, heap)("Archived heap object " PTR_FORMAT " ==> " PTR_FORMAT, + p2i(obj), p2i(archived_oop)); + } else { + log_error(cds, heap)( + "Cannot allocate space for object " PTR_FORMAT " in archived heap region", + p2i(obj)); + vm_exit(1); + } + return archived_oop; +} + +oop HeapShared::materialize_archived_object(narrowOop v) { + assert(archive_heap_region_fixed(), + "must be called after archive heap regions are fixed"); + if (!CompressedOops::is_null(v)) { + oop obj = HeapShared::decode_from_archive(v); + return G1CollectedHeap::heap()->materialize_archived_object(obj); } return NULL; } +void HeapShared::archive_klass_objects(Thread* THREAD) { + GrowableArray<Klass*>* klasses = MetaspaceShared::collected_klasses(); + assert(klasses != NULL, "sanity"); + for (int i = 0; i < klasses->length(); i++) { + Klass* k = klasses->at(i); + + // archive mirror object + java_lang_Class::archive_mirror(k, CHECK); + + // archive the resolved_referenes array + if (k->is_instance_klass()) { + InstanceKlass* ik = InstanceKlass::cast(k); + ik->constants()->archive_resolved_references(THREAD); + } + } +} + +void HeapShared::archive_java_heap_objects(GrowableArray<MemRegion> *closed, + GrowableArray<MemRegion> *open) { + if (!is_heap_object_archiving_allowed()) { + if (log_is_enabled(Info, cds)) { + log_info(cds)( + "Archived java heap is not supported as UseG1GC, " + "UseCompressedOops and UseCompressedClassPointers are required." + "Current settings: UseG1GC=%s, UseCompressedOops=%s, UseCompressedClassPointers=%s.", + BOOL_TO_STR(UseG1GC), BOOL_TO_STR(UseCompressedOops), + BOOL_TO_STR(UseCompressedClassPointers)); + } + return; + } + + { + NoSafepointVerifier nsv; + + // Cache for recording where the archived objects are copied to + create_archived_object_cache(); + + tty->print_cr("Dumping objects to closed archive heap region ..."); + NOT_PRODUCT(StringTable::verify()); + copy_closed_archive_heap_objects(closed); + + tty->print_cr("Dumping objects to open archive heap region ..."); + copy_open_archive_heap_objects(open); + + destroy_archived_object_cache(); + } + + G1HeapVerifier::verify_archive_regions(); +} + +void HeapShared::copy_closed_archive_heap_objects( + GrowableArray<MemRegion> * closed_archive) { + assert(is_heap_object_archiving_allowed(), "Cannot archive java heap objects"); + + Thread* THREAD = Thread::current(); + G1CollectedHeap::heap()->begin_archive_alloc_range(); + + // Archive interned string objects + StringTable::write_to_archive(); + + G1CollectedHeap::heap()->end_archive_alloc_range(closed_archive, + os::vm_allocation_granularity()); +} + +void HeapShared::copy_open_archive_heap_objects( + GrowableArray<MemRegion> * open_archive) { + assert(is_heap_object_archiving_allowed(), "Cannot archive java heap objects"); + + Thread* THREAD = Thread::current(); + G1CollectedHeap::heap()->begin_archive_alloc_range(true /* open */); + + java_lang_Class::archive_basic_type_mirrors(THREAD); + + archive_klass_objects(THREAD); + + archive_object_subgraphs(THREAD); + + G1CollectedHeap::heap()->end_archive_alloc_range(open_archive, + os::vm_allocation_granularity()); +} + +void HeapShared::init_narrow_oop_decoding(address base, int shift) { + _narrow_oop_base = base; + _narrow_oop_shift = shift; +} + +// +// Subgraph archiving support +// +HeapShared::DumpTimeKlassSubGraphInfoTable* HeapShared::_dump_time_subgraph_info_table = NULL; +HeapShared::RunTimeKlassSubGraphInfoTable HeapShared::_run_time_subgraph_info_table; + // Get the subgraph_info for Klass k. A new subgraph_info is created if // there is no existing one for k. The subgraph_info records the relocated // Klass* of the original k. KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) { + assert(DumpSharedSpaces, "dump time only"); Klass* relocated_k = MetaspaceShared::get_relocated_klass(k); - KlassSubGraphInfo* info = find_subgraph_info(relocated_k); - if (info != NULL) { - return info; + KlassSubGraphInfo* info = _dump_time_subgraph_info_table->get(relocated_k); + if (info == NULL) { + _dump_time_subgraph_info_table->put(relocated_k, KlassSubGraphInfo(relocated_k)); + info = _dump_time_subgraph_info_table->get(relocated_k); + ++ _dump_time_subgraph_info_table->_count; } - - info = new KlassSubGraphInfo(relocated_k, _subgraph_info_list); - _subgraph_info_list = info; return info; } -address HeapShared::_narrow_oop_base; -int HeapShared::_narrow_oop_shift; - -int HeapShared::num_of_subgraph_infos() { - int num = 0; - KlassSubGraphInfo* info = _subgraph_info_list; - while (info != NULL) { - num ++; - info = info->next(); - } - return num; -} - // Add an entry field to the current KlassSubGraphInfo. void KlassSubGraphInfo::add_subgraph_entry_field(int static_field_offset, oop v) { assert(DumpSharedSpaces, "dump time only"); @@ -156,7 +308,6 @@ // Initialize an archived subgraph_info_record from the given KlassSubGraphInfo. void ArchivedKlassSubGraphInfoRecord::init(KlassSubGraphInfo* info) { _k = info->klass(); - _next = NULL; _entry_field_records = NULL; _subgraph_object_klasses = NULL; @@ -191,6 +342,26 @@ } } +struct CopyKlassSubGraphInfoToArchive : StackObj { + CompactHashtableWriter* _writer; + CopyKlassSubGraphInfoToArchive(CompactHashtableWriter* writer) : _writer(writer) {} + + bool do_entry(Klass* klass, KlassSubGraphInfo& info) { + if (info.subgraph_object_klasses() != NULL || info.subgraph_entry_fields() != NULL) { + ArchivedKlassSubGraphInfoRecord* record = + (ArchivedKlassSubGraphInfoRecord*)MetaspaceShared::read_only_space_alloc(sizeof(ArchivedKlassSubGraphInfoRecord)); + record->init(&info); + + unsigned int hash = primitive_hash<Klass*>(klass); + uintx deltax = MetaspaceShared::object_delta(record); + guarantee(deltax <= MAX_SHARED_DELTA, "must not be"); + u4 delta = u4(deltax); + _writer->add(hash, delta); + } + return true; // keep on iterating + } +}; + // Build the records of archived subgraph infos, which include: // - Entry points to all subgraphs from the containing class mirror. The entry // points are static fields in the mirror. For each entry point, the field @@ -198,144 +369,95 @@ // back to the corresponding field at runtime. // - A list of klasses that need to be loaded/initialized before archived // java object sub-graph can be accessed at runtime. -// -// The records are saved in the archive file and reloaded at runtime. -// -// Layout of the archived subgraph info records: -// -// records_size | num_records | records* -// ArchivedKlassSubGraphInfoRecord | entry_fields | subgraph_object_klasses -size_t HeapShared::build_archived_subgraph_info_records(int num_records) { - // remember the start address - char* start_p = MetaspaceShared::read_only_space_top(); +void HeapShared::write_subgraph_info_table() { + // Allocate the contents of the hashtable(s) inside the RO region of the CDS archive. + DumpTimeKlassSubGraphInfoTable* d_table = _dump_time_subgraph_info_table; + CompactHashtableStats stats; - // now populate the archived subgraph infos, which will be saved in the - // archive file - _archived_subgraph_info_records = - MetaspaceShared::new_ro_array<ArchivedKlassSubGraphInfoRecord>(num_records); - KlassSubGraphInfo* info = _subgraph_info_list; - int i = 0; - while (info != NULL) { - assert(i < _archived_subgraph_info_records->length(), "sanity"); - ArchivedKlassSubGraphInfoRecord* record = - _archived_subgraph_info_records->adr_at(i); - record->init(info); - info = info->next(); - i ++; - } + _run_time_subgraph_info_table.reset(); - // _subgraph_info_list is no longer needed - delete _subgraph_info_list; - _subgraph_info_list = NULL; + int num_buckets = CompactHashtableWriter::default_num_buckets(d_table->_count); + CompactHashtableWriter writer(num_buckets, &stats); + CopyKlassSubGraphInfoToArchive copy(&writer); + _dump_time_subgraph_info_table->iterate(©); - char* end_p = MetaspaceShared::read_only_space_top(); - size_t records_size = end_p - start_p; - return records_size; + writer.dump(&_run_time_subgraph_info_table, "subgraphs"); } -// Write the subgraph info records in the shared _ro region -void HeapShared::write_archived_subgraph_infos() { - assert(DumpSharedSpaces, "dump time only"); - - Array<intptr_t>* records_header = MetaspaceShared::new_ro_array<intptr_t>(3); - - _num_archived_subgraph_info_records = num_of_subgraph_infos(); - size_t records_size = build_archived_subgraph_info_records( - _num_archived_subgraph_info_records); - - // Now write the header information: - // records_size, num_records, _archived_subgraph_info_records - assert(records_header != NULL, "sanity"); - intptr_t* p = (intptr_t*)(records_header->data()); - *p = (intptr_t)records_size; - p ++; - *p = (intptr_t)_num_archived_subgraph_info_records; - p ++; - *p = (intptr_t)_archived_subgraph_info_records; -} - -char* HeapShared::read_archived_subgraph_infos(char* buffer) { - Array<intptr_t>* records_header = (Array<intptr_t>*)buffer; - intptr_t* p = (intptr_t*)(records_header->data()); - size_t records_size = (size_t)(*p); - p ++; - _num_archived_subgraph_info_records = *p; - p ++; - _archived_subgraph_info_records = - (Array<ArchivedKlassSubGraphInfoRecord>*)(*p); - - buffer = (char*)_archived_subgraph_info_records + records_size; - return buffer; +void HeapShared::serialize_subgraph_info_table_header(SerializeClosure* soc) { + _run_time_subgraph_info_table.serialize_header(soc); } void HeapShared::initialize_from_archived_subgraph(Klass* k) { - if (!MetaspaceShared::open_archive_heap_region_mapped()) { + if (!open_archive_heap_region_mapped()) { return; // nothing to do } + assert(!DumpSharedSpaces, "Should not be called with DumpSharedSpaces"); - if (_num_archived_subgraph_info_records == 0) { - return; // no subgraph info records - } + unsigned int hash = primitive_hash<Klass*>(k); + ArchivedKlassSubGraphInfoRecord* record = _run_time_subgraph_info_table.lookup(k, hash, 0); // Initialize from archived data. Currently this is done only // during VM initialization time. No lock is needed. - Thread* THREAD = Thread::current(); - for (int i = 0; i < _archived_subgraph_info_records->length(); i++) { - ArchivedKlassSubGraphInfoRecord* record = _archived_subgraph_info_records->adr_at(i); - if (record->klass() == k) { - int i; - // Found the archived subgraph info record for the requesting klass. - // Load/link/initialize the klasses of the objects in the subgraph. - // NULL class loader is used. - Array<Klass*>* klasses = record->subgraph_object_klasses(); - if (klasses != NULL) { - for (i = 0; i < klasses->length(); i++) { - Klass* obj_k = klasses->at(i); - Klass* resolved_k = SystemDictionary::resolve_or_null( - (obj_k)->name(), THREAD); - if (resolved_k != obj_k) { - return; - } - if ((obj_k)->is_instance_klass()) { - InstanceKlass* ik = InstanceKlass::cast(obj_k); - ik->initialize(THREAD); - } else if ((obj_k)->is_objArray_klass()) { - ObjArrayKlass* oak = ObjArrayKlass::cast(obj_k); - oak->initialize(THREAD); - } + if (record != NULL) { + Thread* THREAD = Thread::current(); + if (log_is_enabled(Info, cds, heap)) { + ResourceMark rm; + log_info(cds, heap)("initialize_from_archived_subgraph " PTR_FORMAT " %s", p2i(k), + k->external_name()); + } + + int i; + // Load/link/initialize the klasses of the objects in the subgraph. + // NULL class loader is used. + Array<Klass*>* klasses = record->subgraph_object_klasses(); + if (klasses != NULL) { + for (i = 0; i < klasses->length(); i++) { + Klass* obj_k = klasses->at(i); + Klass* resolved_k = SystemDictionary::resolve_or_null( + (obj_k)->name(), THREAD); + if (resolved_k != obj_k) { + return; + } + if ((obj_k)->is_instance_klass()) { + InstanceKlass* ik = InstanceKlass::cast(obj_k); + ik->initialize(THREAD); + } else if ((obj_k)->is_objArray_klass()) { + ObjArrayKlass* oak = ObjArrayKlass::cast(obj_k); + oak->initialize(THREAD); } } + } - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - // None of the field value will be set if there was an exception. - // The java code will not see any of the archived objects in the - // subgraphs referenced from k in this case. - return; + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + // None of the field value will be set if there was an exception. + // The java code will not see any of the archived objects in the + // subgraphs referenced from k in this case. + return; + } + + // Load the subgraph entry fields from the record and store them back to + // the corresponding fields within the mirror. + oop m = k->java_mirror(); + Array<juint>* entry_field_records = record->entry_field_records(); + if (entry_field_records != NULL) { + int efr_len = entry_field_records->length(); + assert(efr_len % 2 == 0, "sanity"); + for (i = 0; i < efr_len;) { + int field_offset = entry_field_records->at(i); + // The object refereced by the field becomes 'known' by GC from this + // point. All objects in the subgraph reachable from the object are + // also 'known' by GC. + oop v = materialize_archived_object(entry_field_records->at(i+1)); + m->obj_field_put(field_offset, v); + i += 2; + + log_debug(cds, heap)(" " PTR_FORMAT " init field @ %2d = " PTR_FORMAT, p2i(k), field_offset, p2i(v)); } - // Load the subgraph entry fields from the record and store them back to - // the corresponding fields within the mirror. - oop m = k->java_mirror(); - Array<juint>* entry_field_records = record->entry_field_records(); - if (entry_field_records != NULL) { - int efr_len = entry_field_records->length(); - assert(efr_len % 2 == 0, "sanity"); - for (i = 0; i < efr_len;) { - int field_offset = entry_field_records->at(i); - // The object refereced by the field becomes 'known' by GC from this - // point. All objects in the subgraph reachable from the object are - // also 'known' by GC. - oop v = MetaspaceShared::materialize_archived_object( - entry_field_records->at(i+1)); - m->obj_field_put(field_offset, v); - i += 2; - } - } - - // Done. Java code can see the archived sub-graphs referenced from k's - // mirror after this point. - return; + // Done. Java code can see the archived sub-graphs referenced from k's + // mirror after this point. } } } @@ -362,7 +484,7 @@ template <class T> void do_oop_work(T *p) { oop obj = RawAccess<>::oop_load(p); if (!CompressedOops::is_null(obj)) { - assert(!MetaspaceShared::is_archive_object(obj), + assert(!HeapShared::is_archived_object(obj), "original objects must not point to archived objects"); size_t field_delta = pointer_delta(p, _orig_referencing_obj, sizeof(char)); @@ -381,7 +503,7 @@ oop archived = HeapShared::archive_reachable_objects_from(_level + 1, _subgraph_info, obj, THREAD); assert(archived != NULL, "VM should have exited with unarchivable objects for _level > 1"); - assert(MetaspaceShared::is_archive_object(archived), "must be"); + assert(HeapShared::is_archived_object(archived), "must be"); if (!_record_klasses_only) { // Update the reference in the archived copy of the referencing object. @@ -399,7 +521,7 @@ // (3) Record the klasses of all orig_obj and all reachable objects. oop HeapShared::archive_reachable_objects_from(int level, KlassSubGraphInfo* subgraph_info, oop orig_obj, TRAPS) { assert(orig_obj != NULL, "must be"); - assert(!MetaspaceShared::is_archive_object(orig_obj), "sanity"); + assert(!is_archived_object(orig_obj), "sanity"); // java.lang.Class instances cannot be included in an archived // object sub-graph. @@ -408,7 +530,7 @@ vm_exit(1); } - oop archived_obj = MetaspaceShared::find_archived_heap_object(orig_obj); + oop archived_obj = find_archived_heap_object(orig_obj); if (java_lang_String::is_instance(orig_obj) && archived_obj != NULL) { // To save time, don't walk strings that are already archived. They just contain // pointers to a type array, whose klass doesn't need to be recorded. @@ -425,7 +547,7 @@ bool record_klasses_only = (archived_obj != NULL); if (archived_obj == NULL) { ++_num_new_archived_objs; - archived_obj = MetaspaceShared::archive_heap_object(orig_obj, THREAD); + archived_obj = archive_heap_object(orig_obj, THREAD); if (archived_obj == NULL) { // Skip archiving the sub-graph referenced from the current entry field. ResourceMark rm; @@ -499,7 +621,7 @@ assert(k->is_shared_boot_class(), "must be boot class"); oop m = k->java_mirror(); - oop archived_m = MetaspaceShared::find_archived_heap_object(m); + oop archived_m = find_archived_heap_object(m); if (CompressedOops::is_null(archived_m)) { return; } @@ -560,7 +682,7 @@ assert(k->is_shared_boot_class(), "must be boot class"); oop m = k->java_mirror(); - oop archived_m = MetaspaceShared::find_archived_heap_object(m); + oop archived_m = find_archived_heap_object(m); if (CompressedOops::is_null(archived_m)) { return; } @@ -571,7 +693,7 @@ } void HeapShared::verify_subgraph_from(oop orig_obj) { - oop archived_obj = MetaspaceShared::find_archived_heap_object(orig_obj); + oop archived_obj = find_archived_heap_object(orig_obj); if (archived_obj == NULL) { // It's OK for the root of a subgraph to be not archived. See comments in // archive_reachable_objects_from(). @@ -598,11 +720,11 @@ set_has_been_seen_during_subgraph_recording(obj); if (is_archived) { - assert(MetaspaceShared::is_archive_object(obj), "must be"); - assert(MetaspaceShared::find_archived_heap_object(obj) == NULL, "must be"); + assert(is_archived_object(obj), "must be"); + assert(find_archived_heap_object(obj) == NULL, "must be"); } else { - assert(!MetaspaceShared::is_archive_object(obj), "must be"); - assert(MetaspaceShared::find_archived_heap_object(obj) != NULL, "must be"); + assert(!is_archived_object(obj), "must be"); + assert(find_archived_heap_object(obj) != NULL, "must be"); } VerifySharedOopClosure walker(is_archived); @@ -702,6 +824,8 @@ }; void HeapShared::init_archivable_static_fields(Thread* THREAD) { + _dump_time_subgraph_info_table = new (ResourceObj::C_HEAP, mtClass)DumpTimeKlassSubGraphInfoTable(); + for (int i = 0; i < num_archivable_static_fields; i++) { ArchivableStaticFieldInfo* info = &archivable_static_fields[i]; TempNewSymbol klass_name = SymbolTable::new_symbol(info->klass_name, THREAD); @@ -720,7 +844,7 @@ } } -void HeapShared::archive_static_fields(Thread* THREAD) { +void HeapShared::archive_object_subgraphs(Thread* THREAD) { // For each class X that has one or more archived fields: // [1] Dump the subgraph of each archived field // [2] Create a list of all the class of the objects that can be reached @@ -817,11 +941,6 @@ return oopmap; } -void HeapShared::init_narrow_oop_decoding(address base, int shift) { - _narrow_oop_base = base; - _narrow_oop_shift = shift; -} - // Patch all the embedded oop pointers inside an archived heap region, // to be consistent with the runtime oop encoding. class PatchEmbeddedPointers: public BitMapClosure {
--- a/src/hotspot/share/memory/heapShared.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/memory/heapShared.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_MEMORY_HEAPSHARED_HPP #define SHARE_VM_MEMORY_HEAPSHARED_HPP +#include "classfile/compactHashtable.hpp" #include "classfile/systemDictionary.hpp" #include "memory/allocation.hpp" #include "memory/universe.hpp" @@ -42,7 +43,6 @@ // within the sub-graphs. class KlassSubGraphInfo: public CHeapObj<mtClass> { private: - KlassSubGraphInfo* _next; // The class that contains the static field(s) as the entry point(s) // of archived object sub-graph(s). Klass* _k; @@ -54,8 +54,8 @@ GrowableArray<juint>* _subgraph_entry_fields; public: - KlassSubGraphInfo(Klass* k, KlassSubGraphInfo* next) : - _next(next), _k(k), _subgraph_object_klasses(NULL), + KlassSubGraphInfo(Klass* k) : + _k(k), _subgraph_object_klasses(NULL), _subgraph_entry_fields(NULL) {} ~KlassSubGraphInfo() { if (_subgraph_object_klasses != NULL) { @@ -66,7 +66,6 @@ } }; - KlassSubGraphInfo* next() { return _next; } Klass* klass() { return _k; } GrowableArray<Klass*>* subgraph_object_klasses() { return _subgraph_object_klasses; @@ -87,7 +86,6 @@ // at runtime. class ArchivedKlassSubGraphInfoRecord { private: - ArchivedKlassSubGraphInfoRecord* _next; Klass* _k; // contains pairs of field offset and value for each subgraph entry field @@ -98,11 +96,9 @@ Array<Klass*>* _subgraph_object_klasses; public: ArchivedKlassSubGraphInfoRecord() : - _next(NULL), _k(NULL), _entry_field_records(NULL), _subgraph_object_klasses(NULL) {} + _k(NULL), _entry_field_records(NULL), _subgraph_object_klasses(NULL) {} void init(KlassSubGraphInfo* info); Klass* klass() { return _k; } - ArchivedKlassSubGraphInfoRecord* next() { return _next; } - void set_next(ArchivedKlassSubGraphInfoRecord* next) { _next = next; } Array<juint>* entry_field_records() { return _entry_field_records; } Array<Klass*>* subgraph_object_klasses() { return _subgraph_object_klasses; } }; @@ -111,15 +107,58 @@ class HeapShared: AllStatic { friend class VerifySharedOopClosure; private: + #if INCLUDE_CDS_JAVA_HEAP - // This is a list of subgraph infos built at dump time while - // archiving object subgraphs. - static KlassSubGraphInfo* _subgraph_info_list; + static bool _open_archive_heap_region_mapped; + static bool _archive_heap_region_fixed; - // Contains a list of ArchivedKlassSubGraphInfoRecords that is stored - // in the archive file and reloaded at runtime. - static int _num_archived_subgraph_info_records; - static Array<ArchivedKlassSubGraphInfoRecord>* _archived_subgraph_info_records; + static bool oop_equals(oop const& p1, oop const& p2) { + return oopDesc::equals(p1, p2); + } + static unsigned oop_hash(oop const& p); + + typedef ResourceHashtable<oop, oop, + HeapShared::oop_hash, + HeapShared::oop_equals, + 15889, // prime number + ResourceObj::C_HEAP> ArchivedObjectCache; + static ArchivedObjectCache* _archived_object_cache; + + static bool klass_equals(Klass* const& p1, Klass* const& p2) { + return primitive_equals<Klass*>(p1, p2); + } + + static unsigned klass_hash(Klass* const& klass) { + return primitive_hash<address>((address)klass); + } + + class DumpTimeKlassSubGraphInfoTable + : public ResourceHashtable<Klass*, KlassSubGraphInfo, + HeapShared::klass_hash, + HeapShared::klass_equals, + 137, // prime number + ResourceObj::C_HEAP> { + public: + int _count; + }; + + inline static ArchivedKlassSubGraphInfoRecord* read_record_from_compact_hashtable(address base_address, u4 offset) { + return (ArchivedKlassSubGraphInfoRecord*)(base_address + offset); + } + + inline static bool record_equals_compact_hashtable_entry(ArchivedKlassSubGraphInfoRecord* value, const Klass* key, int len_unused) { + return (value->klass() == key); + } + + typedef CompactHashtable< + const Klass*, + ArchivedKlassSubGraphInfoRecord*, + read_record_from_compact_hashtable, + record_equals_compact_hashtable_entry + > RunTimeKlassSubGraphInfoTable; + + static DumpTimeKlassSubGraphInfoTable* _dump_time_subgraph_info_table; + static RunTimeKlassSubGraphInfoTable _run_time_subgraph_info_table; // Archive object sub-graph starting from the given static field // in Klass k's mirror. @@ -131,24 +170,15 @@ static void verify_reachable_objects_from(oop obj, bool is_archived) PRODUCT_RETURN; - static KlassSubGraphInfo* find_subgraph_info(Klass *k); static KlassSubGraphInfo* get_subgraph_info(Klass *k); static int num_of_subgraph_infos(); - static size_t build_archived_subgraph_info_records(int num_records); + static void build_archived_subgraph_info_records(int num_records); // Used by decode_from_archive static address _narrow_oop_base; static int _narrow_oop_shift; - static bool oop_equals(oop const& p1, oop const& p2) { - return primitive_equals<oop>(p1, p2); - } - - static unsigned oop_hash(oop const& p) { - return primitive_hash<address>((address)p); - } - typedef ResourceHashtable<oop, bool, HeapShared::oop_hash, HeapShared::oop_equals, @@ -184,8 +214,60 @@ static bool has_been_seen_during_subgraph_recording(oop obj); static void set_has_been_seen_during_subgraph_recording(oop obj); + + public: + static void create_archived_object_cache() { + _archived_object_cache = + new (ResourceObj::C_HEAP, mtClass)ArchivedObjectCache(); + } + static void destroy_archived_object_cache() { + delete _archived_object_cache; + _archived_object_cache = NULL; + } + static ArchivedObjectCache* archived_object_cache() { + return _archived_object_cache; + } + + static oop find_archived_heap_object(oop obj); + static oop archive_heap_object(oop obj, Thread* THREAD); + static oop materialize_archived_object(narrowOop v); + + static void archive_klass_objects(Thread* THREAD); + + static void set_archive_heap_region_fixed() { + _archive_heap_region_fixed = true; + } + static bool archive_heap_region_fixed() { + return _archive_heap_region_fixed; + } + + static void archive_java_heap_objects(GrowableArray<MemRegion> *closed, + GrowableArray<MemRegion> *open); + static void copy_closed_archive_heap_objects(GrowableArray<MemRegion> * closed_archive); + static void copy_open_archive_heap_objects(GrowableArray<MemRegion> * open_archive); #endif // INCLUDE_CDS_JAVA_HEAP + public: + static bool is_heap_object_archiving_allowed() { + CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedOops && UseCompressedClassPointers);) + NOT_CDS_JAVA_HEAP(return false;) + } + + static void set_open_archive_heap_region_mapped() { + CDS_JAVA_HEAP_ONLY(_open_archive_heap_region_mapped = true); + NOT_CDS_JAVA_HEAP_RETURN; + } + static bool open_archive_heap_region_mapped() { + CDS_JAVA_HEAP_ONLY(return _open_archive_heap_region_mapped); + NOT_CDS_JAVA_HEAP_RETURN_(false); + } + + static void fixup_mapped_heap_regions() NOT_CDS_JAVA_HEAP_RETURN; + + inline static bool is_archived_object(oop p) NOT_CDS_JAVA_HEAP_RETURN_(false); + + static void archive_java_heap_objects() NOT_CDS_JAVA_HEAP_RETURN; + static char* read_archived_subgraph_infos(char* buffer) NOT_CDS_JAVA_HEAP_RETURN_(buffer); static void write_archived_subgraph_infos() NOT_CDS_JAVA_HEAP_RETURN; static void initialize_from_archived_subgraph(Klass* k) NOT_CDS_JAVA_HEAP_RETURN; @@ -202,7 +284,9 @@ size_t oopmap_in_bits) NOT_CDS_JAVA_HEAP_RETURN; static void init_archivable_static_fields(Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN; - static void archive_static_fields(Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN; + static void archive_object_subgraphs(Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN; + static void write_subgraph_info_table() NOT_CDS_JAVA_HEAP_RETURN; + static void serialize_subgraph_info_table_header(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN; #if INCLUDE_CDS_JAVA_HEAP static ResourceBitMap calculate_oopmap(MemRegion region);
--- a/src/hotspot/share/memory/heapShared.inline.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/memory/heapShared.inline.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -27,9 +27,16 @@ #include "oops/compressedOops.inline.hpp" #include "memory/heapShared.hpp" +#if INCLUDE_G1GC +#include "gc/g1/g1Allocator.inline.hpp" +#endif #if INCLUDE_CDS_JAVA_HEAP +bool HeapShared::is_archived_object(oop p) { + return (p == NULL) ? false : G1ArchiveAllocator::is_archived_object(p); +} + inline oop HeapShared::decode_from_archive(narrowOop v) { assert(!CompressedOops::is_null(v), "narrow oop value can never be zero"); oop result = (oop)(void*)((uintptr_t)_narrow_oop_base + ((uintptr_t)v << _narrow_oop_shift));
--- a/src/hotspot/share/memory/metaspace.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/memory/metaspace.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -863,6 +863,42 @@ #endif } +// Utils to check if a pointer or range is part of a committed metaspace region. +metaspace::VirtualSpaceNode* MetaspaceUtils::find_enclosing_virtual_space(const void* p) { + VirtualSpaceNode* vsn = Metaspace::space_list()->find_enclosing_space(p); + if (Metaspace::using_class_space() && vsn == NULL) { + vsn = Metaspace::class_space_list()->find_enclosing_space(p); + } + return vsn; +} + +bool MetaspaceUtils::is_in_committed(const void* p) { +#if INCLUDE_CDS + if (UseSharedSpaces) { + for (int idx = MetaspaceShared::ro; idx <= MetaspaceShared::mc; idx++) { + if (FileMapInfo::current_info()->is_in_shared_region(p, idx)) { + return true; + } + } + } +#endif + return find_enclosing_virtual_space(p) != NULL; +} + +bool MetaspaceUtils::is_range_in_committed(const void* from, const void* to) { +#if INCLUDE_CDS + if (UseSharedSpaces) { + for (int idx = MetaspaceShared::ro; idx <= MetaspaceShared::mc; idx++) { + if (FileMapInfo::current_info()->is_in_shared_region(from, idx)) { + return FileMapInfo::current_info()->is_in_shared_region(to, idx); + } + } + } +#endif + VirtualSpaceNode* vsn = find_enclosing_virtual_space(from); + return (vsn != NULL) && vsn->contains(to); +} + // Metaspace methods
--- a/src/hotspot/share/memory/metaspace.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/memory/metaspace.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -71,6 +71,7 @@ class PrintCLDMetaspaceInfoClosure; class SpaceManager; class VirtualSpaceList; + class VirtualSpaceNode; } // Metaspaces each have a SpaceManager and allocations @@ -297,6 +298,10 @@ // Spacemanager updates running counters. friend class metaspace::SpaceManager; + // Special access for error reporting (checks without locks). + friend class oopDesc; + friend class Klass; + // Running counters for statistics concerning in-use chunks. // Note: capacity = used + free + waste + overhead. Note that we do not // count free and waste. Their sum can be deduces from the three other values. @@ -324,6 +329,12 @@ // Helper for print_xx_report. static void print_vs(outputStream* out, size_t scale); + // Utils to check if a pointer or range is part of a committed metaspace region + // without acquiring any locks. + static metaspace::VirtualSpaceNode* find_enclosing_virtual_space(const void* p); + static bool is_in_committed(const void* p); + static bool is_range_in_committed(const void* from, const void* to); + public: // Collect used metaspace statistics. This involves walking the CLDG. The resulting
--- a/src/hotspot/share/memory/metaspace/virtualSpaceList.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/memory/metaspace/virtualSpaceList.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -141,17 +141,17 @@ // This function looks at the mmap regions in the metaspace without locking. // The chunks are added with store ordering and not deleted except for at // unloading time during a safepoint. -bool VirtualSpaceList::contains(const void* ptr) { +VirtualSpaceNode* VirtualSpaceList::find_enclosing_space(const void* ptr) { // List should be stable enough to use an iterator here because removing virtual // space nodes is only allowed at a safepoint. VirtualSpaceListIterator iter(virtual_space_list()); while (iter.repeat()) { VirtualSpaceNode* vsn = iter.get_next(); if (vsn->contains(ptr)) { - return true; + return vsn; } } - return false; + return NULL; } void VirtualSpaceList::retire_current_virtual_space() {
--- a/src/hotspot/share/memory/metaspace/virtualSpaceList.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/memory/metaspace/virtualSpaceList.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -116,7 +116,8 @@ void inc_virtual_space_count(); void dec_virtual_space_count(); - bool contains(const void* ptr); + VirtualSpaceNode* find_enclosing_space(const void* ptr); + bool contains(const void* ptr) { return find_enclosing_space(ptr) != NULL; } // Unlink empty VirtualSpaceNodes and free it. void purge(ChunkManager* chunk_manager);
--- a/src/hotspot/share/memory/metaspaceShared.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/memory/metaspaceShared.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -75,8 +75,6 @@ bool MetaspaceShared::_has_error_classes; bool MetaspaceShared::_archive_loading_failed = false; bool MetaspaceShared::_remapped_readwrite = false; -bool MetaspaceShared::_open_archive_heap_region_mapped = false; -bool MetaspaceShared::_archive_heap_region_fixed = false; address MetaspaceShared::_cds_i2i_entry_code_buffers = NULL; size_t MetaspaceShared::_cds_i2i_entry_code_buffers_size = 0; size_t MetaspaceShared::_core_spaces_size = 0; @@ -108,7 +106,7 @@ // [5] C++ vtables are copied into the md region. // [6] Original class files are copied into the od region. // -// The s0/s1 and oa0/oa1 regions are populated inside MetaspaceShared::dump_java_heap_objects. +// The s0/s1 and oa0/oa1 regions are populated inside HeapShared::archive_java_heap_objects. // Their layout is independent of the other 5 regions. class DumpRegion { @@ -420,10 +418,10 @@ vmSymbols::serialize(soc); soc->do_tag(--tag); - // Dump/restore the symbol and string tables - SymbolTable::serialize(soc); - StringTable::serialize(soc); - soc->do_tag(--tag); + // Dump/restore the symbol/string/subgraph_info tables + SymbolTable::serialize_shared_table_header(soc); + StringTable::serialize_shared_table_header(soc); + HeapShared::serialize_subgraph_info_table_header(soc); JavaClasses::serialize_offsets(soc); InstanceMirrorKlass::serialize_offsets(soc); @@ -454,6 +452,10 @@ // is run at a safepoint just before exit, this is the entire set of classes. static GrowableArray<Klass*>* _global_klass_objects; +GrowableArray<Klass*>* MetaspaceShared::collected_klasses() { + return _global_klass_objects; +} + static void collect_array_classes(Klass* k) { _global_klass_objects->append_if_missing(k); if (k->is_array_klass()) { @@ -512,7 +514,7 @@ } static void clear_basic_type_mirrors() { - assert(!MetaspaceShared::is_heap_object_archiving_allowed(), "Sanity"); + assert(!HeapShared::is_heap_object_archiving_allowed(), "Sanity"); Universe::set_int_mirror(NULL); Universe::set_float_mirror(NULL); Universe::set_double_mirror(NULL); @@ -850,7 +852,7 @@ if (*o == NULL) { _dump_region->append_intptr_t(0); } else { - assert(MetaspaceShared::is_heap_object_archiving_allowed(), + assert(HeapShared::is_heap_object_archiving_allowed(), "Archiving heap object is not allowed"); _dump_region->append_intptr_t( (intptr_t)CompressedOops::encode_not_null(*o)); @@ -1098,6 +1100,21 @@ return _alloc_stats; } + // Use this when you allocate space with MetaspaceShare::read_only_space_alloc() + // outside of ArchiveCompactor::allocate(). These are usually for misc tables + // that are allocated in the RO space. + class OtherROAllocMark { + char* _oldtop; + public: + OtherROAllocMark() { + _oldtop = _ro_region.top(); + } + ~OtherROAllocMark() { + char* newtop = _ro_region.top(); + ArchiveCompactor::alloc_stats()->record_other_type(int(newtop - _oldtop), true); + } + }; + static void allocate(MetaspaceClosure::Ref* ref, bool read_only) { address obj = ref->obj(); int bytes = ref->size() * BytesPerWord; @@ -1308,13 +1325,13 @@ } char* VM_PopulateDumpSharedSpace::dump_read_only_tables() { - char* oldtop = _ro_region.top(); + ArchiveCompactor::OtherROAllocMark mark; // Reorder the system dictionary. Moving the symbols affects // how the hash table indices are calculated. SystemDictionary::reorder_dictionary_for_sharing(); tty->print("Removing java_mirror ... "); - if (!MetaspaceShared::is_heap_object_archiving_allowed()) { + if (!HeapShared::is_heap_object_archiving_allowed()) { clear_basic_type_mirrors(); } remove_java_mirror_in_classes(); @@ -1329,11 +1346,6 @@ char* table_top = _ro_region.allocate(table_bytes, sizeof(intptr_t)); SystemDictionary::copy_table(table_top, _ro_region.top()); - // Write the archived object sub-graph infos. For each klass with sub-graphs, - // the info includes the static fields (sub-graph entry points) and Klasses - // of objects included in the sub-graph. - HeapShared::write_archived_subgraph_infos(); - // Write the other data to the output array. WriteClosure wc(&_ro_region); MetaspaceShared::serialize(&wc); @@ -1341,8 +1353,6 @@ // Write the bitmaps for patching the archive heap regions dump_archive_heap_oopmaps(); - char* newtop = _ro_region.top(); - ArchiveCompactor::alloc_stats()->record_other_type(int(newtop - oldtop), true); return buckets_top; } @@ -1790,42 +1800,18 @@ #if INCLUDE_CDS_JAVA_HEAP void VM_PopulateDumpSharedSpace::dump_java_heap_objects() { - if (!MetaspaceShared::is_heap_object_archiving_allowed()) { - if (log_is_enabled(Info, cds)) { - log_info(cds)( - "Archived java heap is not supported as UseG1GC, " - "UseCompressedOops and UseCompressedClassPointers are required." - "Current settings: UseG1GC=%s, UseCompressedOops=%s, UseCompressedClassPointers=%s.", - BOOL_TO_STR(UseG1GC), BOOL_TO_STR(UseCompressedOops), - BOOL_TO_STR(UseCompressedClassPointers)); - } - return; - } - - { - NoSafepointVerifier nsv; - - // Cache for recording where the archived objects are copied to - MetaspaceShared::create_archive_object_cache(); - - tty->print_cr("Dumping objects to closed archive heap region ..."); - NOT_PRODUCT(StringTable::verify()); - // The closed space has maximum two regions. See FileMapInfo::write_archive_heap_regions() for details. - _closed_archive_heap_regions = new GrowableArray<MemRegion>(2); - MetaspaceShared::dump_closed_archive_heap_objects(_closed_archive_heap_regions); - - tty->print_cr("Dumping objects to open archive heap region ..."); - _open_archive_heap_regions = new GrowableArray<MemRegion>(2); - MetaspaceShared::dump_open_archive_heap_objects(_open_archive_heap_regions); - - MetaspaceShared::destroy_archive_object_cache(); - } - - G1HeapVerifier::verify_archive_regions(); + // The closed and open archive heap space has maximum two regions. + // See FileMapInfo::write_archive_heap_regions() for details. + _closed_archive_heap_regions = new GrowableArray<MemRegion>(2); + _open_archive_heap_regions = new GrowableArray<MemRegion>(2); + HeapShared::archive_java_heap_objects(_closed_archive_heap_regions, + _open_archive_heap_regions); + ArchiveCompactor::OtherROAllocMark mark; + HeapShared::write_subgraph_info_table(); } void VM_PopulateDumpSharedSpace::dump_archive_heap_oopmaps() { - if (MetaspaceShared::is_heap_object_archiving_allowed()) { + if (HeapShared::is_heap_object_archiving_allowed()) { _closed_archive_heap_oopmaps = new GrowableArray<ArchiveHeapOopmapInfo>(2); dump_archive_heap_oopmaps(_closed_archive_heap_regions, _closed_archive_heap_oopmaps); @@ -1853,124 +1839,6 @@ oopmaps->append(info); } } - -void MetaspaceShared::dump_closed_archive_heap_objects( - GrowableArray<MemRegion> * closed_archive) { - assert(is_heap_object_archiving_allowed(), "Cannot dump java heap objects"); - - Thread* THREAD = Thread::current(); - G1CollectedHeap::heap()->begin_archive_alloc_range(); - - // Archive interned string objects - StringTable::write_to_archive(); - - G1CollectedHeap::heap()->end_archive_alloc_range(closed_archive, - os::vm_allocation_granularity()); -} - -void MetaspaceShared::dump_open_archive_heap_objects( - GrowableArray<MemRegion> * open_archive) { - assert(UseG1GC, "Only support G1 GC"); - assert(UseCompressedOops && UseCompressedClassPointers, - "Only support UseCompressedOops and UseCompressedClassPointers enabled"); - - Thread* THREAD = Thread::current(); - G1CollectedHeap::heap()->begin_archive_alloc_range(true /* open */); - - java_lang_Class::archive_basic_type_mirrors(THREAD); - - MetaspaceShared::archive_klass_objects(THREAD); - - HeapShared::archive_static_fields(THREAD); - - G1CollectedHeap::heap()->end_archive_alloc_range(open_archive, - os::vm_allocation_granularity()); -} - -unsigned MetaspaceShared::obj_hash(oop const& p) { - assert(!p->mark()->has_bias_pattern(), - "this object should never have been locked"); // so identity_hash won't safepoin - unsigned hash = (unsigned)p->identity_hash(); - return hash; -} - -MetaspaceShared::ArchivedObjectCache* MetaspaceShared::_archive_object_cache = NULL; -oop MetaspaceShared::find_archived_heap_object(oop obj) { - assert(DumpSharedSpaces, "dump-time only"); - ArchivedObjectCache* cache = MetaspaceShared::archive_object_cache(); - oop* p = cache->get(obj); - if (p != NULL) { - return *p; - } else { - return NULL; - } -} - -oop MetaspaceShared::archive_heap_object(oop obj, Thread* THREAD) { - assert(DumpSharedSpaces, "dump-time only"); - - oop ao = find_archived_heap_object(obj); - if (ao != NULL) { - // already archived - return ao; - } - - int len = obj->size(); - if (G1CollectedHeap::heap()->is_archive_alloc_too_large(len)) { - log_debug(cds, heap)("Cannot archive, object (" PTR_FORMAT ") is too large: " SIZE_FORMAT, - p2i(obj), (size_t)obj->size()); - return NULL; - } - - int hash = obj->identity_hash(); - oop archived_oop = (oop)G1CollectedHeap::heap()->archive_mem_allocate(len); - if (archived_oop != NULL) { - Copy::aligned_disjoint_words((HeapWord*)obj, (HeapWord*)archived_oop, len); - relocate_klass_ptr(archived_oop); - ArchivedObjectCache* cache = MetaspaceShared::archive_object_cache(); - cache->put(obj, archived_oop); - log_debug(cds, heap)("Archived heap object " PTR_FORMAT " ==> " PTR_FORMAT, - p2i(obj), p2i(archived_oop)); - } else { - log_error(cds, heap)( - "Cannot allocate space for object " PTR_FORMAT " in archived heap region", - p2i(obj)); - vm_exit(1); - } - return archived_oop; -} - -oop MetaspaceShared::materialize_archived_object(narrowOop v) { - assert(archive_heap_region_fixed(), - "must be called after archive heap regions are fixed"); - if (!CompressedOops::is_null(v)) { - oop obj = HeapShared::decode_from_archive(v); - return G1CollectedHeap::heap()->materialize_archived_object(obj); - } - return NULL; -} - -void MetaspaceShared::archive_klass_objects(Thread* THREAD) { - int i; - for (i = 0; i < _global_klass_objects->length(); i++) { - Klass* k = _global_klass_objects->at(i); - - // archive mirror object - java_lang_Class::archive_mirror(k, CHECK); - - // archive the resolved_referenes array - if (k->is_instance_klass()) { - InstanceKlass* ik = InstanceKlass::cast(k); - ik->constants()->archive_resolved_references(THREAD); - } - } -} - -void MetaspaceShared::fixup_mapped_heap_regions() { - FileMapInfo *mapinfo = FileMapInfo::current_info(); - mapinfo->fixup_mapped_heap_regions(); - set_archive_heap_region_fixed(); -} #endif // INCLUDE_CDS_JAVA_HEAP // Closure for serializing initialization data in from a data area @@ -2010,12 +1878,12 @@ void do_oop(oop *p) { narrowOop o = (narrowOop)nextPtr(); - if (o == 0 || !MetaspaceShared::open_archive_heap_region_mapped()) { + if (o == 0 || !HeapShared::open_archive_heap_region_mapped()) { p = NULL; } else { - assert(MetaspaceShared::is_heap_object_archiving_allowed(), + assert(HeapShared::is_heap_object_archiving_allowed(), "Archived heap object is not allowed"); - assert(MetaspaceShared::open_archive_heap_region_mapped(), + assert(HeapShared::open_archive_heap_region_mapped(), "Open archive heap region is not mapped"); *p = HeapShared::decode_from_archive(o); } @@ -2145,9 +2013,6 @@ buffer += sizeof(intptr_t); buffer += len; - // The table of archived java heap object sub-graph infos - buffer = HeapShared::read_archived_subgraph_infos(buffer); - // Verify various attributes of the archive, plus initialize the // shared string/symbol tables intptr_t* array = (intptr_t*)buffer;
--- a/src/hotspot/share/memory/metaspaceShared.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/memory/metaspaceShared.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -58,8 +58,6 @@ static bool _has_error_classes; static bool _archive_loading_failed; static bool _remapped_readwrite; - static bool _open_archive_heap_region_mapped; - static bool _archive_heap_region_fixed; static address _cds_i2i_entry_code_buffers; static size_t _cds_i2i_entry_code_buffers_size; static size_t _core_spaces_size; @@ -93,63 +91,7 @@ static int preload_classes(const char * class_list_path, TRAPS) NOT_CDS_RETURN_(0); -#if INCLUDE_CDS_JAVA_HEAP - private: - static bool obj_equals(oop const& p1, oop const& p2) { - return p1 == p2; - } - static unsigned obj_hash(oop const& p); - - typedef ResourceHashtable<oop, oop, - MetaspaceShared::obj_hash, - MetaspaceShared::obj_equals, - 15889, // prime number - ResourceObj::C_HEAP> ArchivedObjectCache; - static ArchivedObjectCache* _archive_object_cache; - - public: - static ArchivedObjectCache* archive_object_cache() { - return _archive_object_cache; - } - static oop find_archived_heap_object(oop obj); - static oop archive_heap_object(oop obj, Thread* THREAD); - static oop materialize_archived_object(narrowOop v); - static void archive_klass_objects(Thread* THREAD); - - static void set_archive_heap_region_fixed() { - _archive_heap_region_fixed = true; - } - - static bool archive_heap_region_fixed() { - return _archive_heap_region_fixed; - } -#endif - - inline static bool is_archive_object(oop p) NOT_CDS_JAVA_HEAP_RETURN_(false); - - static bool is_heap_object_archiving_allowed() { - CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedOops && UseCompressedClassPointers);) - NOT_CDS_JAVA_HEAP(return false;) - } - static void create_archive_object_cache() { - CDS_JAVA_HEAP_ONLY(_archive_object_cache = new (ResourceObj::C_HEAP, mtClass)ArchivedObjectCache();); - } - static void destroy_archive_object_cache() { - CDS_JAVA_HEAP_ONLY(delete _archive_object_cache; _archive_object_cache = NULL;); - } - static void fixup_mapped_heap_regions() NOT_CDS_JAVA_HEAP_RETURN; - - static void dump_closed_archive_heap_objects(GrowableArray<MemRegion> * closed_archive) NOT_CDS_JAVA_HEAP_RETURN; - - static void dump_open_archive_heap_objects(GrowableArray<MemRegion> * open_archive) NOT_CDS_JAVA_HEAP_RETURN; - static void set_open_archive_heap_region_mapped() { - CDS_JAVA_HEAP_ONLY(_open_archive_heap_region_mapped = true); - NOT_CDS_JAVA_HEAP_RETURN; - } - static bool open_archive_heap_region_mapped() { - CDS_JAVA_HEAP_ONLY(return _open_archive_heap_region_mapped); - NOT_CDS_JAVA_HEAP_RETURN_(false); - } + static GrowableArray<Klass*>* collected_klasses(); static ReservedSpace* shared_rs() { CDS_ONLY(return &_shared_rs);
--- a/src/hotspot/share/memory/universe.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/memory/universe.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -39,6 +39,7 @@ #include "interpreter/interpreter.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" +#include "memory/heapShared.hpp" #include "memory/filemap.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" @@ -113,6 +114,7 @@ oop Universe::_out_of_memory_error_array_size = NULL; oop Universe::_out_of_memory_error_gc_overhead_limit = NULL; oop Universe::_out_of_memory_error_realloc_objects = NULL; +oop Universe::_out_of_memory_error_retry = NULL; oop Universe::_delayed_stack_overflow_error_message = NULL; objArrayOop Universe::_preallocated_out_of_memory_error_array = NULL; volatile jint Universe::_preallocated_out_of_memory_error_avail_count = 0; @@ -195,6 +197,7 @@ f->do_oop((oop*)&_out_of_memory_error_array_size); f->do_oop((oop*)&_out_of_memory_error_gc_overhead_limit); f->do_oop((oop*)&_out_of_memory_error_realloc_objects); + f->do_oop((oop*)&_out_of_memory_error_retry); f->do_oop((oop*)&_delayed_stack_overflow_error_message); f->do_oop((oop*)&_preallocated_out_of_memory_error_array); f->do_oop((oop*)&_null_ptr_exception_instance); @@ -240,8 +243,15 @@ f->do_ptr((void**)&_objectArrayKlassObj); #if INCLUDE_CDS_JAVA_HEAP - // The mirrors are NULL if MetaspaceShared::is_heap_object_archiving_allowed - // is false. +#ifdef ASSERT + if (DumpSharedSpaces && !HeapShared::is_heap_object_archiving_allowed()) { + assert(_int_mirror == NULL && _float_mirror == NULL && + _double_mirror == NULL && _byte_mirror == NULL && + _bool_mirror == NULL && _char_mirror == NULL && + _long_mirror == NULL && _short_mirror == NULL && + _void_mirror == NULL, "mirrors should be NULL"); + } +#endif f->do_oop(&_int_mirror); f->do_oop(&_float_mirror); f->do_oop(&_double_mirror); @@ -420,9 +430,9 @@ void Universe::initialize_basic_type_mirrors(TRAPS) { #if INCLUDE_CDS_JAVA_HEAP if (UseSharedSpaces && - MetaspaceShared::open_archive_heap_region_mapped() && + HeapShared::open_archive_heap_region_mapped() && _int_mirror != NULL) { - assert(MetaspaceShared::is_heap_object_archiving_allowed(), "Sanity"); + assert(HeapShared::is_heap_object_archiving_allowed(), "Sanity"); assert(_float_mirror != NULL && _double_mirror != NULL && _byte_mirror != NULL && _byte_mirror != NULL && _bool_mirror != NULL && _char_mirror != NULL && @@ -565,7 +575,8 @@ (!oopDesc::equals(throwable(), Universe::_out_of_memory_error_class_metaspace)) && (!oopDesc::equals(throwable(), Universe::_out_of_memory_error_array_size)) && (!oopDesc::equals(throwable(), Universe::_out_of_memory_error_gc_overhead_limit)) && - (!oopDesc::equals(throwable(), Universe::_out_of_memory_error_realloc_objects))); + (!oopDesc::equals(throwable(), Universe::_out_of_memory_error_realloc_objects)) && + (!oopDesc::equals(throwable(), Universe::_out_of_memory_error_retry))); } @@ -974,6 +985,7 @@ Universe::_out_of_memory_error_gc_overhead_limit = ik->allocate_instance(CHECK_false); Universe::_out_of_memory_error_realloc_objects = ik->allocate_instance(CHECK_false); + Universe::_out_of_memory_error_retry = ik->allocate_instance(CHECK_false); // Setup preallocated cause message for delayed StackOverflowError if (StackReservedPages > 0) { @@ -1019,6 +1031,9 @@ msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK_false); java_lang_Throwable::set_message(Universe::_out_of_memory_error_realloc_objects, msg()); + msg = java_lang_String::create_from_str("Java heap space: failed retryable allocation", CHECK_false); + java_lang_Throwable::set_message(Universe::_out_of_memory_error_retry, msg()); + msg = java_lang_String::create_from_str("/ by zero", CHECK_false); java_lang_Throwable::set_message(Universe::_arithmetic_exception_instance, msg());
--- a/src/hotspot/share/memory/universe.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/memory/universe.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -148,6 +148,7 @@ static oop _out_of_memory_error_array_size; static oop _out_of_memory_error_gc_overhead_limit; static oop _out_of_memory_error_realloc_objects; + static oop _out_of_memory_error_retry; // preallocated cause message for delayed StackOverflowError static oop _delayed_stack_overflow_error_message; @@ -363,6 +364,8 @@ static oop out_of_memory_error_array_size() { return gen_out_of_memory_error(_out_of_memory_error_array_size); } static oop out_of_memory_error_gc_overhead_limit() { return gen_out_of_memory_error(_out_of_memory_error_gc_overhead_limit); } static oop out_of_memory_error_realloc_objects() { return gen_out_of_memory_error(_out_of_memory_error_realloc_objects); } + // Throw default _out_of_memory_error_retry object as it will never propagate out of the VM + static oop out_of_memory_error_retry() { return _out_of_memory_error_retry; } static oop delayed_stack_overflow_error_message() { return _delayed_stack_overflow_error_message; } // The particular choice of collected heap.
--- a/src/hotspot/share/oops/access.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/access.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -277,7 +277,7 @@ } static bool equals(oop o1, oop o2) { - verify_decorators<INTERNAL_EMPTY>(); + verify_decorators<AS_RAW>(); return AccessInternal::equals<decorators>(o1, o2); } };
--- a/src/hotspot/share/oops/accessBackend.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/accessBackend.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -410,7 +410,7 @@ static oop resolve(oop obj) { return obj; } - static bool equals(oop o1, oop o2) { return o1 == o2; } + static bool equals(oop o1, oop o2) { return (void*)o1 == (void*)o2; } }; // Below is the implementation of the first 4 steps of the template pipeline: @@ -998,7 +998,7 @@ template <DecoratorSet decorators> inline static typename EnableIf< - HasDecorator<decorators, INTERNAL_BT_TO_SPACE_INVARIANT>::value, bool>::type + HasDecorator<decorators, AS_RAW>::value || HasDecorator<decorators, INTERNAL_BT_TO_SPACE_INVARIANT>::value, bool>::type equals(oop o1, oop o2) { typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw; return Raw::equals(o1, o2); @@ -1006,7 +1006,7 @@ template <DecoratorSet decorators> inline static typename EnableIf< - !HasDecorator<decorators, INTERNAL_BT_TO_SPACE_INVARIANT>::value, bool>::type + !HasDecorator<decorators, AS_RAW>::value && !HasDecorator<decorators, INTERNAL_BT_TO_SPACE_INVARIANT>::value, bool>::type equals(oop o1, oop o2) { return RuntimeDispatch<decorators, oop, BARRIER_EQUALS>::equals(o1, o2); }
--- a/src/hotspot/share/oops/arrayKlass.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/arrayKlass.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -130,14 +130,7 @@ } objArrayOop ArrayKlass::allocate_arrayArray(int n, int length, TRAPS) { - if (length < 0) { - THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length)); - } - if (length > arrayOopDesc::max_array_length(T_ARRAY)) { - report_java_out_of_memory("Requested array size exceeds VM limit"); - JvmtiExport::post_array_size_exhausted(); - THROW_OOP_0(Universe::out_of_memory_error_array_size()); - } + check_array_allocation_length(length, arrayOopDesc::max_array_length(T_ARRAY), CHECK_0); int size = objArrayOopDesc::object_size(length); Klass* k = array_klass(n+dimension(), CHECK_0); ArrayKlass* ak = ArrayKlass::cast(k);
--- a/src/hotspot/share/oops/compressedOops.inline.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/compressedOops.inline.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -66,7 +66,7 @@ assert(OopEncodingHeapMax > pd, "change encoding max if new encoding"); uint64_t result = pd >> shift; assert((result & CONST64(0xffffffff00000000)) == 0, "narrow oop overflow"); - assert(decode(result) == v, "reversibility"); + assert(oopDesc::equals_raw(decode(result), v), "reversibility"); return (narrowOop)result; }
--- a/src/hotspot/share/oops/constantPool.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/constantPool.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -33,6 +33,7 @@ #include "interpreter/linkResolver.hpp" #include "memory/allocation.inline.hpp" #include "memory/heapInspection.hpp" +#include "memory/heapShared.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/metaspaceShared.hpp" @@ -295,7 +296,7 @@ } } - oop archived = MetaspaceShared::archive_heap_object(rr, THREAD); + oop archived = HeapShared::archive_heap_object(rr, THREAD); // If the resolved references array is not archived (too large), // the 'archived' object is NULL. No need to explicitly check // the return value of archive_heap_object here. At runtime, the @@ -340,7 +341,7 @@ if (SystemDictionary::Object_klass_loaded()) { ClassLoaderData* loader_data = pool_holder()->class_loader_data(); #if INCLUDE_CDS_JAVA_HEAP - if (MetaspaceShared::open_archive_heap_region_mapped() && + if (HeapShared::open_archive_heap_region_mapped() && _cache->archived_references() != NULL) { oop archived = _cache->archived_references(); // Create handle for the archived resolved reference array object @@ -373,7 +374,7 @@ // If archiving heap objects is not allowed, clear the resolved references. // Otherwise, it is cleared after the resolved references array is cached // (see archive_resolved_references()). - if (!MetaspaceShared::is_heap_object_archiving_allowed()) { + if (!HeapShared::is_heap_object_archiving_allowed()) { set_resolved_references(NULL); } @@ -471,7 +472,7 @@ // or any internal exception fields such as cause or stacktrace. But since the // detail message is often a class name or other literal string, we will repeat it // if we can find it in the symbol table. - throw_resolution_error(this_cp, which, CHECK_0); + throw_resolution_error(this_cp, which, CHECK_NULL); ShouldNotReachHere(); }
--- a/src/hotspot/share/oops/cpCache.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/cpCache.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -30,6 +30,7 @@ #include "interpreter/linkResolver.hpp" #include "interpreter/rewriter.hpp" #include "logging/log.hpp" +#include "memory/heapShared.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/metaspaceShared.hpp" @@ -777,7 +778,7 @@ if (CompressedOops::is_null(_archived_references)) { return NULL; } - return MetaspaceShared::materialize_archived_object(_archived_references); + return HeapShared::materialize_archived_object(_archived_references); } void ConstantPoolCache::set_archived_references(oop o) {
--- a/src/hotspot/share/oops/instanceClassLoaderKlass.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/instanceClassLoaderKlass.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ // An InstanceClassLoaderKlass is a specialization of the InstanceKlass. It does // not add any field. It is added to walk the dependencies for the class loader // key that this class loader points to. This is how the loader_data graph is -// walked and dependant class loaders are kept alive. I thought we walked +// walked and dependent class loaders are kept alive. I thought we walked // the list later? class InstanceClassLoaderKlass: public InstanceKlass { @@ -48,21 +48,10 @@ public: InstanceClassLoaderKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); } - // GC specific object visitors - // -#if INCLUDE_PARALLELGC - // Parallel Scavenge - void oop_ps_push_contents( oop obj, PSPromotionManager* pm); - // Parallel Compact - void oop_pc_follow_contents(oop obj, ParCompactionManager* cm); - void oop_pc_update_pointers(oop obj, ParCompactionManager* cm); -#endif - // Oop fields (and metadata) iterators // // The InstanceClassLoaderKlass iterators also visit the CLD pointer (or mirror of anonymous klasses.) - public: // Forward iteration // Iterate over the oop fields and metadata. template <typename T, class OopClosureType>
--- a/src/hotspot/share/oops/instanceKlass.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/instanceKlass.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -1201,14 +1201,7 @@ } objArrayOop InstanceKlass::allocate_objArray(int n, int length, TRAPS) { - if (length < 0) { - THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length)); - } - if (length > arrayOopDesc::max_array_length(T_OBJECT)) { - report_java_out_of_memory("Requested array size exceeds VM limit"); - JvmtiExport::post_array_size_exhausted(); - THROW_OOP_0(Universe::out_of_memory_error_array_size()); - } + check_array_allocation_length(length, arrayOopDesc::max_array_length(T_OBJECT), CHECK_NULL); int size = objArrayOopDesc::object_size(length); Klass* ak = array_klass(n, CHECK_NULL); objArrayOop o = (objArrayOop)Universe::heap()->array_allocate(ak, size, length, @@ -2745,48 +2738,6 @@ return; } -// tell if two classes have the same enclosing class (at package level) -bool InstanceKlass::is_same_package_member(const Klass* class2, TRAPS) const { - if (class2 == this) return true; - if (!class2->is_instance_klass()) return false; - - // must be in same package before we try anything else - if (!is_same_class_package(class2)) - return false; - - // As long as there is an outer_this.getEnclosingClass, - // shift the search outward. - const InstanceKlass* outer_this = this; - for (;;) { - // As we walk along, look for equalities between outer_this and class2. - // Eventually, the walks will terminate as outer_this stops - // at the top-level class around the original class. - bool ignore_inner_is_member; - const Klass* next = outer_this->compute_enclosing_class(&ignore_inner_is_member, - CHECK_false); - if (next == NULL) break; - if (next == class2) return true; - outer_this = InstanceKlass::cast(next); - } - - // Now do the same for class2. - const InstanceKlass* outer2 = InstanceKlass::cast(class2); - for (;;) { - bool ignore_inner_is_member; - Klass* next = outer2->compute_enclosing_class(&ignore_inner_is_member, - CHECK_false); - if (next == NULL) break; - // Might as well check the new outer against all available values. - if (next == this) return true; - if (next == outer_this) return true; - outer2 = InstanceKlass::cast(next); - } - - // If by this point we have not found an equality between the - // two classes, we know they are in separate package members. - return false; -} - bool InstanceKlass::find_inner_classes_attr(int* ooff, int* noff, TRAPS) const { constantPoolHandle i_cp(THREAD, constants()); for (InnerClassesIterator iter(this); !iter.done(); iter.next()) {
--- a/src/hotspot/share/oops/instanceKlass.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/instanceKlass.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -507,9 +507,6 @@ ClassLoaderData* loader_data, TRAPS); public: - // tell if two classes have the same enclosing class (at package level) - bool is_same_package_member(const Klass* class2, TRAPS) const; - // initialization state bool is_loaded() const { return _init_state >= loaded; } bool is_linked() const { return _init_state >= linked; } @@ -1186,16 +1183,6 @@ const char* signature_name() const; static Symbol* package_from_name(const Symbol* name, TRAPS); - // GC specific object visitors - // -#if INCLUDE_PARALLELGC - // Parallel Scavenge - void oop_ps_push_contents( oop obj, PSPromotionManager* pm); - // Parallel Compact - void oop_pc_follow_contents(oop obj, ParCompactionManager* cm); - void oop_pc_update_pointers(oop obj, ParCompactionManager* cm); -#endif - // Oop fields (and metadata) iterators // // The InstanceKlass iterators also visits the Object's klass.
--- a/src/hotspot/share/oops/instanceMirrorKlass.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/instanceMirrorKlass.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -52,7 +52,7 @@ // Since mirrors can be variable sized because of the static fields, store // the size in the mirror itself. - return (instanceOop)Universe::heap()->class_allocate(this, size, CHECK_NULL); + return (instanceOop)Universe::heap()->class_allocate(this, size, THREAD); } int InstanceMirrorKlass::oop_size(oop obj) const {
--- a/src/hotspot/share/oops/instanceMirrorKlass.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/instanceMirrorKlass.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -89,16 +89,6 @@ // allocation instanceOop allocate_instance(Klass* k, TRAPS); - // GC specific object visitors - // -#if INCLUDE_PARALLELGC - // Parallel Scavenge - void oop_ps_push_contents( oop obj, PSPromotionManager* pm); - // Parallel Compact - void oop_pc_follow_contents(oop obj, ParCompactionManager* cm); - void oop_pc_update_pointers(oop obj, ParCompactionManager* cm); -#endif - static void serialize_offsets(class SerializeClosure* f) NOT_CDS_RETURN; // Oop fields (and metadata) iterators
--- a/src/hotspot/share/oops/instanceRefKlass.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/instanceRefKlass.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,16 +58,6 @@ public: InstanceRefKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); } - // GC specific object visitors - // -#if INCLUDE_PARALLELGC - // Parallel Scavenge - void oop_ps_push_contents( oop obj, PSPromotionManager* pm); - // Parallel Compact - void oop_pc_follow_contents(oop obj, ParCompactionManager* cm); - void oop_pc_update_pointers(oop obj, ParCompactionManager* cm); -#endif - // Oop fields (and metadata) iterators // // The InstanceRefKlass iterators also support reference processing.
--- a/src/hotspot/share/oops/klass.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/klass.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/classLoaderData.inline.hpp" +#include "classfile/classLoaderDataGraph.inline.hpp" #include "classfile/dictionary.hpp" #include "classfile/javaClasses.hpp" #include "classfile/systemDictionary.hpp" @@ -31,6 +32,7 @@ #include "gc/shared/collectedHeap.inline.hpp" #include "logging/log.hpp" #include "memory/heapInspection.hpp" +#include "memory/heapShared.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/metaspaceShared.hpp" @@ -541,7 +543,7 @@ if (this->has_raw_archived_mirror()) { ResourceMark rm; log_debug(cds, mirror)("%s has raw archived mirror", external_name()); - if (MetaspaceShared::open_archive_heap_region_mapped()) { + if (HeapShared::open_archive_heap_region_mapped()) { bool present = java_lang_Class::restore_archived_mirror(this, loader, module_handle, protection_domain, CHECK); @@ -610,6 +612,20 @@ return NULL; } +void Klass::check_array_allocation_length(int length, int max_length, TRAPS) { + if (length > max_length) { + if (!THREAD->in_retryable_allocation()) { + report_java_out_of_memory("Requested array size exceeds VM limit"); + JvmtiExport::post_array_size_exhausted(); + THROW_OOP(Universe::out_of_memory_error_array_size()); + } else { + THROW_OOP(Universe::out_of_memory_error_retry()); + } + } else if (length < 0) { + THROW_MSG(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length)); + } +} + oop Klass::class_loader() const { return class_loader_data()->class_loader(); } // In product mode, this function doesn't have virtual function calls so @@ -740,6 +756,22 @@ guarantee(obj->klass()->is_klass(), "klass field is not a klass"); } +Klass* Klass::decode_klass_raw(narrowKlass narrow_klass) { + return (Klass*)(void*)( (uintptr_t)Universe::narrow_klass_base() + + ((uintptr_t)narrow_klass << Universe::narrow_klass_shift())); +} + +bool Klass::is_valid(Klass* k) { + if (!is_aligned(k, sizeof(MetaWord))) return false; + if ((size_t)k < os::min_page_size()) return false; + + if (!os::is_readable_range(k, k + 1)) return false; + if (!MetaspaceUtils::is_range_in_committed(k, k + 1)) return false; + + if (!Symbol::is_valid(k->name())) return false; + return ClassLoaderDataGraph::is_valid(k->class_loader_data()); +} + klassVtable Klass::vtable() const { return klassVtable(const_cast<Klass*>(this), start_of_vtable(), vtable_length() / vtableEntry::size()); }
--- a/src/hotspot/share/oops/klass.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/klass.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -514,6 +514,9 @@ virtual Klass* array_klass_impl(bool or_null, int rank, TRAPS); virtual Klass* array_klass_impl(bool or_null, TRAPS); + // Error handling when length > max_length or length < 0 + static void check_array_allocation_length(int length, int max_length, TRAPS); + void set_vtable_length(int len) { _vtable_len= len; } vtableEntry* start_of_vtable() const; @@ -670,16 +673,6 @@ clean_weak_klass_links(/*unloading_occurred*/ true , /* clean_alive_klasses */ false); } - // GC specific object visitors - // -#if INCLUDE_PARALLELGC - // Parallel Scavenge - virtual void oop_ps_push_contents( oop obj, PSPromotionManager* pm) = 0; - // Parallel Compact - virtual void oop_pc_follow_contents(oop obj, ParCompactionManager* cm) = 0; - virtual void oop_pc_update_pointers(oop obj, ParCompactionManager* cm) = 0; -#endif - virtual void array_klasses_do(void f(Klass* k)) {} // Return self, except for abstract classes with exactly 1 @@ -715,6 +708,10 @@ virtual void oop_verify_on(oop obj, outputStream* st); + // for error reporting + static Klass* decode_klass_raw(narrowKlass narrow_klass); + static bool is_valid(Klass* k); + static bool is_null(narrowKlass obj); static bool is_null(Klass* obj);
--- a/src/hotspot/share/oops/objArrayKlass.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/objArrayKlass.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -170,19 +170,10 @@ } objArrayOop ObjArrayKlass::allocate(int length, TRAPS) { - if (length >= 0) { - if (length <= arrayOopDesc::max_array_length(T_OBJECT)) { - int size = objArrayOopDesc::object_size(length); - return (objArrayOop)Universe::heap()->array_allocate(this, size, length, - /* do_zero */ true, THREAD); - } else { - report_java_out_of_memory("Requested array size exceeds VM limit"); - JvmtiExport::post_array_size_exhausted(); - THROW_OOP_0(Universe::out_of_memory_error_array_size()); - } - } else { - THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length)); - } + check_array_allocation_length(length, arrayOopDesc::max_array_length(T_OBJECT), CHECK_0); + int size = objArrayOopDesc::object_size(length); + return (objArrayOop)Universe::heap()->array_allocate(this, size, length, + /* do_zero */ true, THREAD); } static int multi_alloc_counter = 0;
--- a/src/hotspot/share/oops/objArrayKlass.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/objArrayKlass.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -120,16 +120,6 @@ // Initialization (virtual from Klass) void initialize(TRAPS); - // GC specific object visitors - // -#if INCLUDE_PARALLELGC - // Parallel Scavenge - void oop_ps_push_contents( oop obj, PSPromotionManager* pm); - // Parallel Compact - void oop_pc_follow_contents(oop obj, ParCompactionManager* cm); - void oop_pc_update_pointers(oop obj, ParCompactionManager* cm); -#endif - // Oop fields (and metadata) iterators // // The ObjArrayKlass iterators also visits the Object's klass.
--- a/src/hotspot/share/oops/oop.cpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/oop.cpp Tue Oct 16 14:26:22 2018 +0530 @@ -25,7 +25,7 @@ #include "precompiled.hpp" #include "classfile/altHashing.hpp" #include "classfile/javaClasses.inline.hpp" -#include "memory/metaspaceShared.inline.hpp" +#include "memory/heapShared.inline.hpp" #include "memory/resourceArea.hpp" #include "oops/access.inline.hpp" #include "oops/oop.inline.hpp" @@ -144,8 +144,8 @@ } #if INCLUDE_CDS_JAVA_HEAP -bool oopDesc::is_archive_object(oop p) { - return MetaspaceShared::is_archive_object(p); +bool oopDesc::is_archived_object(oop p) { + return HeapShared::is_archived_object(p); } #endif #endif // PRODUCT @@ -171,6 +171,63 @@ return UseCompressedClassPointers; } +oop oopDesc::decode_oop_raw(narrowOop narrow_oop) { + return (oop)(void*)( (uintptr_t)Universe::narrow_oop_base() + + ((uintptr_t)narrow_oop << Universe::narrow_oop_shift())); +} + +void* oopDesc::load_klass_raw(oop obj) { + if (UseCompressedClassPointers) { + narrowKlass narrow_klass = *(obj->compressed_klass_addr()); + if (narrow_klass == 0) return NULL; + return (void*)Klass::decode_klass_raw(narrow_klass); + } else { + return *(void**)(obj->klass_addr()); + } +} + +void* oopDesc::load_oop_raw(oop obj, int offset) { + uintptr_t addr = (uintptr_t)(void*)obj + (uint)offset; + if (UseCompressedOops) { + narrowOop narrow_oop = *(narrowOop*)addr; + if (narrow_oop == 0) return NULL; + return (void*)decode_oop_raw(narrow_oop); + } else { + return *(void**)addr; + } +} + +bool oopDesc::is_valid(oop obj) { + if (!is_object_aligned(obj)) return false; + if ((size_t)(oopDesc*)obj < os::min_page_size()) return false; + + // We need at least the mark and the klass word in the committed region. + if (!os::is_readable_range(obj, (oopDesc*)obj + 1)) return false; + if (!Universe::heap()->is_in(obj)) return false; + + Klass* k = (Klass*)load_klass_raw(obj); + + if (!os::is_readable_range(k, k + 1)) return false; + return MetaspaceUtils::is_range_in_committed(k, k + 1); +} + +oop oopDesc::oop_or_null(address addr) { + if (is_valid(oop(addr))) { + // We were just given an oop directly. + return oop(addr); + } + + // Try to find addr using block_start. + HeapWord* p = Universe::heap()->block_start(addr); + if (p != NULL && Universe::heap()->block_is_obj(p)) { + if (!is_valid(oop(p))) return NULL; + return oop(p); + } + + // If we can't find it it just may mean that heap wasn't parsable. + return NULL; +} + oop oopDesc::obj_field_acquire(int offset) const { return HeapAccess<MO_ACQUIRE>::oop_load_at(as_oop(), offset); } void oopDesc::obj_field_put_raw(int offset, oop value) { RawAccess<>::oop_store_at(as_oop(), offset, value); }
--- a/src/hotspot/share/oops/oop.hpp Mon Oct 15 10:29:06 2018 +0530 +++ b/src/hotspot/share/oops/oop.hpp Tue Oct 16 14:26:22 2018 +0530 @@ -46,7 +46,6 @@ class ScanClosure; class FastScanClosure; class FilteringClosure; -class BarrierSet; class CMSIsAliveClosure; class PSPromotionManager; @@ -154,6 +153,8 @@ inline static bool equals(oop o1, oop o2) { return Access<>::equals(o1, o2); } + inline static bool equals_raw(oop o1, oop o2) { return RawAccess<>::equals(o1, o2); } + // Access to fields in a instanceOop through these methods. template <DecoratorSet decorator> oop obj_field_access(int offset) const; @@ -256,7 +257,7 @@ static bool is_oop_or_null(oop obj, bool ignore_mark_word = false); #ifndef PRODUCT inline bool is_unlocked_oop() const; - static bool is_archive_object(oop p) NOT_CDS_JAVA_HEAP_RETURN_(false); + static bool is_archived_object(oop p) NOT_CDS_JAVA_HEAP_RETURN_(false); #endif // garbage collection @@ -284,16 +285,6 @@ // mark-sweep support void follow_body(int begin, int end); - // Garbage Collection support - -#if INCLUDE_PARALLELGC - // Parallel