diff --git a/.hgtags b/.hgtags index f2cb64f8785..dd49fb5ce19 100644 --- a/.hgtags +++ b/.hgtags @@ -488,3 +488,4 @@ e1e60f75cd39312a7f59d2a4f91d624e5aecc95e jdk-11+11 3595bd343b65f8c37818ebe6a4c343ddeb1a5f88 jdk-11+14 a11c1cb542bbd1671d25b85efe7d09b983c48525 jdk-11+15 02934b0d661b82b7fe1052a04998d2091352e08d jdk-11+16 +64e4b1686141e57a681936a8283983341484676e jdk-11+17 diff --git a/make/common/JdkNativeCompilation.gmk b/make/common/JdkNativeCompilation.gmk index 49b0f3e795c..c1bd70350dd 100644 --- a/make/common/JdkNativeCompilation.gmk +++ b/make/common/JdkNativeCompilation.gmk @@ -32,6 +32,36 @@ endif include NativeCompilation.gmk +# Hook to include the corresponding custom file, if present. +$(eval $(call IncludeCustomExtension, common/JdkNativeCompilation.gmk)) + +FindSrcDirsForLib += \ + $(call uniq, $(wildcard \ + $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS)/native/lib$(strip $2) \ + $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS_TYPE)/native/lib$(strip $2) \ + $(TOPDIR)/src/$(strip $1)/share/native/lib$(strip $2))) + +FindSrcDirsForComponent += \ + $(call uniq, $(wildcard \ + $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS)/native/$(strip $2) \ + $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS_TYPE)/native/$(strip $2) \ + $(TOPDIR)/src/$(strip $1)/share/native/$(strip $2))) + +GetJavaHeaderDir = \ + $(wildcard $(SUPPORT_OUTPUTDIR)/headers/$(strip $1)) + +# Process a dir description such as "java.base:headers" into a set of proper absolute paths. +ProcessDir = \ + $(if $(findstring :, $1), \ + $(call FindSrcDirsForComponent, $(firstword $(subst :, , $1)), $(lastword $(subst :, , $1))) \ + , \ + $(if $(filter /%, $1), \ + $1 \ + , \ + $(call FindSrcDirsForComponent, $(MODULE), $1) \ + ) \ + ) + # Setup make rules for creating a native shared library with suitable defaults # for the OpenJDK project. # @@ -39,8 +69,16 @@ include NativeCompilation.gmk # and the targets generated are listed in a variable by that name. # # Remaining parameters are named arguments. These are all passed on to -# SetupNativeCompilation, except for +# SetupNativeCompilation, except for # EXTRA_RC_FLAGS -- additional RC_FLAGS to append. +# EXTRA_HEADER_DIRS -- additional directories to look for headers in +# EXTRA_SRC -- additional directories to look for source in +# EXCLUDE_SRC_PATTERNS -- exclude source dirs matching these patterns from +# appearing in SRC. +# HEADERS_FROM_SRC -- if false, does not add source dirs automatically as +# header include dirs. (Defaults to true.) +# SRC -- this is passed on, but preprocessed to accept source dir designations +# such as "java.base:headers". SetupJdkLibrary = $(NamedParamsMacroTemplate) define SetupJdkLibraryBody ifeq ($$($1_OUTPUT_DIR), ) @@ -51,6 +89,20 @@ define SetupJdkLibraryBody $1_OBJECT_DIR := $$(SUPPORT_OUTPUTDIR)/native/$$(MODULE)/lib$$($1_NAME) endif + ifeq ($$($1_SRC), ) + $1_SRC := $$(call FindSrcDirsForLib, $$(MODULE), $$($1_NAME)) + else + $1_SRC := $$(foreach dir, $$($1_SRC), $$(call ProcessDir, $$(dir))) + endif + ifneq ($$($1_EXTRA_SRC), ) + $1_SRC += $$(foreach dir, $$($1_EXTRA_SRC), $$(call ProcessDir, $$(dir))) + endif + + ifneq ($$($1_EXCLUDE_SRC_PATTERNS), ) + $1_EXCLUDE_SRC := $$(call containing, $$($1_EXCLUDE_SRC_PATTERNS), $$($1_SRC)) + $1_SRC := $$(filter-out $$($1_EXCLUDE_SRC), $$($1_SRC)) + endif + ifeq ($$($1_VERSIONINFO_RESOURCE), ) $1_VERSIONINFO_RESOURCE := $$(GLOBAL_VERSION_INFO_RESOURCE) else ifeq ($$($1_VERSIONINFO_RESOURCE), DISABLE) @@ -66,6 +118,25 @@ define SetupJdkLibraryBody $1_RC_FLAGS := endif + ifneq ($$($1_HEADERS_FROM_SRC), false) + $1_SRC_HEADER_FLAGS := $$(foreach dir, $$(wildcard $$($1_SRC) \ + $$(call GetJavaHeaderDir, $$(MODULE))), -I$$(dir)) + endif + ifneq ($$($1_EXTRA_HEADER_DIRS), ) + $1_PROCESSED_EXTRA_HEADER_DIRS := $$(foreach dir, $$($1_EXTRA_HEADER_DIRS), \ + $$(call ProcessDir, $$(dir))) + $1_EXTRA_HEADER_FLAGS := $$(addprefix -I, $$($1_PROCESSED_EXTRA_HEADER_DIRS)) + endif + + ifneq ($$($1_CFLAGS), ) + $1_CFLAGS += $$($1_SRC_HEADER_FLAGS) $$($1_EXTRA_HEADER_FLAGS) + endif + ifneq ($$($1_CXXFLAGS), ) + $1_CXXFLAGS += $$($1_SRC_HEADER_FLAGS) $$($1_EXTRA_HEADER_FLAGS) + endif + ifeq ($$($1_CFLAGS)$$($1_CXXFLAGS), ) + $1_CFLAGS += $$($1_SRC_HEADER_FLAGS) $$($1_EXTRA_HEADER_FLAGS) + endif $1_RC_FLAGS += $$($1_EXTRA_RC_FLAGS) # Since we reuse the rule name ($1), all our arguments will pass through. @@ -80,7 +151,7 @@ endef # and the targets generated are listed in a variable by that name. # # Remaining parameters are named arguments. These are all passed on to -# SetupNativeCompilation, except for +# SetupNativeCompilation, except for # EXTRA_RC_FLAGS -- additional RC_FLAGS to append. SetupJdkExecutable = $(NamedParamsMacroTemplate) define SetupJdkExecutableBody diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index 960e9985206..b3a59e14aa1 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -634,7 +634,7 @@ endef ################################################################################ # Filter out duplicate sub strings while preserving order. Keeps the first occurance. uniq = \ - $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) + $(strip $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))) # Returns all whitespace-separated words in $2 where at least one of the # whitespace-separated words in $1 is a substring. diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 9618f156aa7..be1fefee0d8 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -233,7 +233,7 @@ var getJibProfilesCommon = function (input, data) { common.main_profile_names = [ "linux-x64", "linux-x86", "macosx-x64", "solaris-x64", "solaris-sparcv9", "windows-x64", "windows-x86", - "linux-aarch64", "linux-arm64", "linux-arm-vfp-hflt", + "linux-aarch64", "linux-arm32", "linux-arm64", "linux-arm-vfp-hflt", "linux-arm-vfp-hflt-dyn" ]; @@ -452,6 +452,17 @@ var getJibProfilesProfiles = function (input, common, data) { ], }, + "linux-arm32": { + target_os: "linux", + target_cpu: "arm", + build_cpu: "x64", + dependencies: ["devkit", "autoconf", "build_devkit", "cups"], + configure_args: [ + "--openjdk-target=arm-linux-gnueabihf", "--with-freetype=bundled", + "--with-abi-profile=arm-vfp-hflt", "--disable-warnings-as-errors" + ], + }, + "linux-arm-vfp-hflt": { target_os: "linux", target_cpu: "arm", @@ -586,6 +597,9 @@ var getJibProfilesProfiles = function (input, common, data) { "linux-aarch64": { platform: "linux-aarch64", }, + "linux-arm32": { + platform: "linux-arm32", + }, "linux-arm64": { platform: "linux-arm64-vfp-hflt", }, @@ -790,7 +804,11 @@ var getJibProfilesDependencies = function (input, common) { : "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" - : "arm-linaro-4.7+1.0") + : (input.profile.indexOf("arm32") >= 0 + ? "gcc7.3.0-Fedora27+1.0" + : "arm-linaro-4.7+1.0" + ) + ) }; var devkit_platform = (input.target_cpu == "x86" diff --git a/make/devkit/Makefile b/make/devkit/Makefile index 1bd37951fd3..d0464fbecd9 100644 --- a/make/devkit/Makefile +++ b/make/devkit/Makefile @@ -42,6 +42,8 @@ # line looking like this: # # make cross_compile_target="aarch64-linux-gnu" BASE_OS=Fedora27 +# or +# make cross_compile_target="arm-linux-gnueabihf" BASE_OS=Fedora27 # # This is the makefile which iterates over all host and target platforms. # diff --git a/make/devkit/Tools.gmk b/make/devkit/Tools.gmk index 5bc63448111..5e87a848e68 100644 --- a/make/devkit/Tools.gmk +++ b/make/devkit/Tools.gmk @@ -44,13 +44,23 @@ $(info HOST=$(HOST)) $(info BUILD=$(BUILD)) ARCH := $(word 1,$(subst -, ,$(TARGET))) + +ifeq ($(TARGET), arm-linux-gnueabihf) + ARCH=armhfp +endif + $(info ARCH=$(ARCH)) ifeq ($(BASE_OS), OEL6) OEL_URL := http://yum.oracle.com/repo/OracleLinux/OL6/4/base/$(ARCH)/ LINUX_VERSION := OEL6.4 else ifeq ($(BASE_OS), Fedora27) - OEL_URL := https://dl.fedoraproject.org/pub/fedora-secondary/releases/27/Everything/$(ARCH)/os/Packages/ + ifeq ($(ARCH), aarch64) + FEDORA_TYPE=fedora-secondary + else + FEDORA_TYPE=fedora/linux + endif + OEL_URL := https://dl.fedoraproject.org/pub/$(FEDORA_TYPE)/releases/27/Everything/$(ARCH)/os/Packages/ LINUX_VERSION := Fedora 27 else $(error Unknown base OS $(BASE_OS)) @@ -189,6 +199,8 @@ ifeq ($(ARCH),x86_64) endif else ifeq ($(ARCH),i686) RPM_ARCHS := i386 i686 noarch +else ifeq ($(ARCH), armhfp) + RPM_ARCHS := $(ARCH) armv7hl noarch else RPM_ARCHS := $(ARCH) noarch endif @@ -410,6 +422,10 @@ ifneq (,$(findstring linux,$(TARGET))) $(BUILDDIR)/$(gcc_ver)/Makefile : CONFIG += --enable-__cxa_atexit endif +ifeq ($(ARCH), armhfp) + $(BUILDDIR)/$(gcc_ver)/Makefile : CONFIG += --with-float=hard +endif + # Want: # c,c++ # shared libs diff --git a/make/gensrc/Gensrc-jdk.compiler.gmk b/make/gensrc/Gensrc-jdk.compiler.gmk index 24be68e89c1..e5a299f7970 100644 --- a/make/gensrc/Gensrc-jdk.compiler.gmk +++ b/make/gensrc/Gensrc-jdk.compiler.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 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 @@ -32,6 +32,7 @@ $(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ $(JAVAC_VERSION))) $(eval $(call SetupParseProperties,PARSE_PROPERTIES, \ - com/sun/tools/javac/resources/compiler.properties)) + com/sun/tools/javac/resources/compiler.properties \ + com/sun/tools/javac/resources/launcher.properties)) all: $(COMPILE_PROPERTIES) $(PARSE_PROPERTIES) diff --git a/make/langtools/build.properties b/make/langtools/build.properties index 53260739538..30ca441558c 100644 --- a/make/langtools/build.properties +++ b/make/langtools/build.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 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 @@ -38,7 +38,8 @@ module.names = java.compiler \ jdk.jshell langtools.resource.includes = \ - com/sun/tools/javac/resources/compiler.properties + com/sun/tools/javac/resources/compiler.properties \ + com/sun/tools/javac/resources/launcher.properties # Version info -- override as needed jdk.version = 9 diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk index 67b89581c91..8a138b2e788 100644 --- a/make/lib/Awt2dLibraries.gmk +++ b/make/lib/Awt2dLibraries.gmk @@ -27,37 +27,38 @@ $(eval $(call IncludeCustomExtension, lib/Awt2dLibraries-pre.gmk)) WIN_AWT_LIB := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libawt/awt.lib +LIBAWT_DEFAULT_HEADER_DIRS := \ + libawt/awt/image \ + libawt/awt/image/cvutils \ + libawt/java2d \ + libawt/java2d/loops \ + libawt/java2d/pipe \ + # + ################################################################################ -BUILD_LIBMLIB_SRC := $(TOPDIR)/src/java.desktop/share/native/libmlib_image \ - $(TOPDIR)/src/java.desktop/share/native/common/awt/medialib -BUILD_LIBMLIB_CFLAGS := -D__USE_J2D_NAMES -D__MEDIALIB_OLD_NAMES \ - $(addprefix -I, $(BUILD_LIBMLIB_SRC)) \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libmlib_image +# We must not include java.desktop/unix/native/libmlib_image, which is only +# for usage by solaris-sparc in libmlib_image_v. +BUILD_LIBMLIB_EXCLUDE_SRC_PATTERNS := unix -BUILD_LIBMLIB_LDLIBS := - -BUILD_LIBMLIB_CFLAGS += -DMLIB_NO_LIBSUNMATH +BUILD_LIBMLIB_CFLAGS := -D__USE_J2D_NAMES -D__MEDIALIB_OLD_NAMES -DMLIB_NO_LIBSUNMATH ifeq ($(OPENJDK_TARGET_CPU_BITS), 64) BUILD_LIBMLIB_CFLAGS += -DMLIB_OS64BIT endif -ifneq ($(OPENJDK_TARGET_OS), windows) - BUILD_LIBMLIB_LDLIBS += $(LIBM) $(LIBDL) -endif - $(eval $(call SetupJdkLibrary, BUILD_LIBMLIB_IMAGE, \ NAME := mlib_image, \ - SRC := $(BUILD_LIBMLIB_SRC), \ + EXTRA_SRC := common/awt/medialib, \ EXCLUDE_FILES := mlib_c_ImageBlendTable.c, \ + EXCLUDE_SRC_PATTERNS := $(BUILD_LIBMLIB_EXCLUDE_SRC_PATTERNS), \ OPTIMIZATION := HIGHEST, \ CFLAGS := $(CFLAGS_JDKLIB) \ $(BUILD_LIBMLIB_CFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ - LIBS := $(BUILD_LIBMLIB_LDLIBS) \ - $(JDKLIB_LIBS), \ + LIBS := $(JDKLIB_LIBS), \ + LIBS_unix := $(LIBM) $(LIBDL), \ )) $(BUILD_LIBMLIB_IMAGE): $(call FindLib, java.base, java) @@ -68,14 +69,19 @@ TARGETS += $(BUILD_LIBMLIB_IMAGE) ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc) - LIBMLIB_IMAGE_V_SRC := $(TOPDIR)/src/java.desktop/share/native/libmlib_image \ - $(TOPDIR)/src/java.desktop/unix/native/libmlib_image \ - $(TOPDIR)/src/java.desktop/share/native/common/awt/medialib \ - $(TOPDIR)/src/java.desktop/unix/native/common/awt/medialib \ - # - LIBMLIB_IMAGE_V_CFLAGS := $(TOPDIR)/src/java.desktop/unix/native/libmlib_image/vis_$(OPENJDK_TARGET_CPU_BITS).il \ - $(addprefix -I, $(LIBMLIB_IMAGE_V_SRC)) \ - # + # libmlib_image_v is basically built from mlib_image sources, with some additions + # and some exclusions. + LIBMLIB_IMAGE_V_SRC := \ + libmlib_image \ + common/awt/medialib \ + # + + LIBMLIB_IMAGE_V_CFLAGS := -xarch=sparcvis -D__USE_J2D_NAMES -D__MEDIALIB_OLD_NAMES \ + $(TOPDIR)/src/$(MODULE)/unix/native/libmlib_image/vis_$(OPENJDK_TARGET_CPU_BITS).il + + ifeq ($(OPENJDK_TARGET_CPU_BITS), 64) + LIBMLIB_IMAGE_V_CFLAGS += -DMLIB_OS64BIT + endif BUILD_LIBMLIB_IMAGE_V_EXFILES := \ awt_ImagingLib.c \ @@ -95,19 +101,16 @@ ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc) mlib_c_ImageLookUp_f.c \ # - LIBMLIB_IMAGE_V_CFLAGS += $(filter-out -DMLIB_NO_LIBSUNMATH, $(BUILD_LIBMLIB_CFLAGS)) - $(eval $(call SetupJdkLibrary, BUILD_LIBMLIB_IMAGE_V, \ NAME := mlib_image_v, \ SRC := $(LIBMLIB_IMAGE_V_SRC), \ EXCLUDE_FILES := $(BUILD_LIBMLIB_IMAGE_V_EXFILES), \ OPTIMIZATION := HIGHEST, \ - CFLAGS := -xarch=sparcvis \ - $(LIBMLIB_IMAGE_V_CFLAGS) \ - $(CFLAGS_JDKLIB), \ + CFLAGS := $(CFLAGS_JDKLIB) \ + $(LIBMLIB_IMAGE_V_CFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ - LIBS := -ljava -ljvm $(BUILD_LIBMLIB_LDLIBS), \ + LIBS := -ljava -ljvm $(LIBM) $(LIBDL), \ )) $(BUILD_LIBMLIB_IMAGE_V): $(call FindLib, java.base, java) @@ -118,18 +121,22 @@ endif ################################################################################ -LIBAWT_DIRS := $(TOPDIR)/src/java.desktop/share/native/libawt \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt \ - $(TOPDIR)/src/java.desktop/share/native/common/awt/debug \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \ +LIBAWT_EXTRA_SRC := \ + common/awt/debug \ + $(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \ # -ifeq ($(OPENJDK_TARGET_OS), aix) - LIBAWT_DIRS += $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/libawt +ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc) + LIBAWT_EXTRA_SRC += $(TOPDIR)/src/$(MODULE)/share/native/common/awt/medialib endif ifeq ($(OPENJDK_TARGET_OS), windows) - LIBAWT_DIRS += $(TOPDIR)/src/java.desktop/share/native/common/awt/utility + LIBAWT_EXTRA_SRC += \ + $(TOPDIR)/src/$(MODULE)/share/native/common/awt/utility \ + $(TOPDIR)/src/$(MODULE)/share/native/common/font \ + $(TOPDIR)/src/$(MODULE)/share/native/common/java2d/opengl \ + $(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt/systemscale \ + # endif ifneq ($(filter $(OPENJDK_TARGET_OS), solaris linux macosx aix), ) @@ -140,33 +147,45 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) LIBAWT_EXFILES += initIDs.c awt/image/cvutils/img_colors.c endif -LIBAWT_CFLAGS += -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - $(addprefix -I, $(shell find $(LIBAWT_DIRS) -type d)) \ - $(LIBJAVA_HEADER_FLAGS) \ - $(addprefix -I, $(BUILD_LIBMLIB_IMAGE_SRC)) \ +ifeq ($(OPENJDK_TARGET_OS), windows) + LIBAWT_EXFILES += \ + java2d/d3d/D3DShaderGen.c \ + awt/image/cvutils/img_colors.c \ + # +endif + +ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), solaris-sparcv9) + LIBAWT_EXFILES += java2d/loops/MapAccelFunc.c +else + LIBAWT_EXCLUDES += \ + $(TOPDIR)/src/$(MODULE)/unix/native/libawt/awt/medialib \ + $(TOPDIR)/src/$(MODULE)/unix/native/libawt/java2d/loops \ + $(TOPDIR)/src/$(MODULE)/unix/native/common/awt/medialib \ + # +endif + +LIBAWT_EXTRA_HEADER_DIRS := \ + $(LIBAWT_DEFAULT_HEADER_DIRS) \ + $(call GetJavaHeaderDir, java.base) \ + libawt/awt/medialib \ + libawt/java2d/d3d \ + libawt/java2d/opengl \ + libawt/java2d/windows \ + libawt/windows \ + common/awt/medialib \ + libmlib_image \ + include \ + java.base:libjava \ + java.base:include \ # LIBAWT_CFLAGS += -D__MEDIALIB_OLD_NAMES -D__USE_J2D_NAMES $(X_CFLAGS) -ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc) - LIBAWT_CFLAGS += -DMLIB_ADD_SUFF - LIBAWT_CFLAGS += -xarch=sparcvis +ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), solaris-sparcv9) + LIBAWT_CFLAGS += -xarch=sparcvis -DMLIB_ADD_SUFF \ + $(TOPDIR)/src/$(MODULE)/unix/native/libmlib_image/vis_$(OPENJDK_TARGET_CPU_BITS).il - LIBAWT_CFLAGS += $(TOPDIR)/src/java.desktop/unix/native/libmlib_image/vis_$(OPENJDK_TARGET_CPU_BITS).il - LIBAWT_DIRS += $(TOPDIR)/src/java.desktop/share/native/common/awt/medialib - LIBAWT_EXFILES += java2d/loops/MapAccelFunc.c - - ifeq ($(OPENJDK_TARGET_CPU), sparcv9) - LIBAWT_ASFLAGS = -P -xarch=v9a - else - LIBAWT_ASFLAGS = -P -xarch=v8plusa - endif -else - LIBAWT_EXCLUDES += \ - $(TOPDIR)/src/java.desktop/unix/native/libawt/awt/medialib \ - $(TOPDIR)/src/java.desktop/unix/native/libawt/java2d/loops \ - $(TOPDIR)/src/java.desktop/unix/native/common/awt/medialib \ - # + LIBAWT_ASFLAGS = -P -xarch=v9a endif ifneq ($(OPENJDK_TARGET_OS), solaris) @@ -174,29 +193,13 @@ ifneq ($(OPENJDK_TARGET_OS), solaris) endif ifeq ($(OPENJDK_TARGET_OS), windows) - LIBAWT_DIRS += $(TOPDIR)/src/java.desktop/share/native/common/font \ - $(TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt/systemscale \ - # Why does libawt need java.base headers? - LIBAWT_CFLAGS += -I$(TOPDIR)/src/java.desktop/share/native/common/font \ - -I$(TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d/opengl \ - -I$(TOPDIR)/src/java.desktop/windows/native/include \ - -I$(TOPDIR)/src/java.desktop/share/native/include \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - # - LIBAWT_EXFILES += \ - java2d/d3d/D3DShaderGen.c \ - awt/image/cvutils/img_colors.c \ - # - LIBAWT_CFLAGS += -EHsc -DUNICODE -D_UNICODE ifeq ($(OPENJDK_TARGET_CPU_BITS), 64) LIBAWT_CFLAGS += -DMLIB_OS64BIT endif LIBAWT_RC_FLAGS ?= -I $(TOPDIR)/src/java.base/windows/native/launcher/icons - LIBAWT_VERSIONINFO_RESOURCE := $(TOPDIR)/src/java.desktop/windows/native/libawt/windows/awt.rc + LIBAWT_VERSIONINFO_RESOURCE := $(TOPDIR)/src/$(MODULE)/windows/native/libawt/windows/awt.rc endif ifeq ($(OPENJDK_TARGET_OS), linux) @@ -215,11 +218,12 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \ NAME := awt, \ - SRC := $(LIBAWT_DIRS), \ + EXTRA_SRC := $(LIBAWT_EXTRA_SRC), \ EXCLUDES := $(LIBAWT_EXCLUDES), \ EXCLUDE_FILES := $(LIBAWT_EXFILES), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) $(LIBAWT_CFLAGS), \ + EXTRA_HEADER_DIRS := $(LIBAWT_EXTRA_HEADER_DIRS), \ DISABLED_WARNINGS_gcc := sign-compare unused-result maybe-uninitialized \ format-nonliteral parentheses, \ DISABLED_WARNINGS_clang := logical-op-parentheses extern-initializer, \ @@ -265,39 +269,26 @@ TARGETS += $(BUILD_LIBAWT) ################################################################################ -ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),) +ifeq ($(findstring $(OPENJDK_TARGET_OS), windows macosx), ) ifeq ($(ENABLE_HEADLESS_ONLY), false) - LIBAWT_XAWT_DIRS := \ - $(wildcard $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/libawt_xawt) \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt_xawt \ - $(TOPDIR)/src/java.desktop/share/native/common/awt/debug \ - $(TOPDIR)/src/java.desktop/share/native/common/awt/utility \ - $(TOPDIR)/src/java.desktop/share/native/common/font \ - $(TOPDIR)/src/java.desktop/share/native/common/java2d \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \ + LIBAWT_XAWT_EXTRA_SRC := \ + common/awt \ + common/java2d \ + common/font \ # - ifneq ($(filter $(OPENJDK_TARGET_OS),linux solaris aix), ) - LIBAWT_XAWT_DIRS += $(TOPDIR)/src/java.desktop/unix/native/common/awt/systemscale - endif - LIBAWT_XAWT_EXCLUDES := medialib - LIBAWT_XAWT_CFLAGS := $(addprefix -I, $(shell $(FIND) $(LIBAWT_XAWT_DIRS) -type d)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - -I$(TOPDIR)/src/java.desktop/share/native/include \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/include \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/include \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d/loops \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d/pipe \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/awt/image/cvutils \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/awt/image \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/font \ - $(LIBJAVA_HEADER_FLAGS) + LIBAWT_XAWT_EXTRA_HEADER_DIRS := \ + $(LIBAWT_DEFAULT_HEADER_DIRS) \ + libawt_xawt/awt \ + include \ + common/awt/debug \ + common/awt/systemscale \ + common/font \ + common/java2d/opengl \ + common/java2d/x11 \ # LIBAWT_XAWT_CFLAGS += -DXAWT -DXAWT_HACK \ @@ -334,7 +325,8 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),) $(eval $(call SetupJdkLibrary, BUILD_LIBAWT_XAWT, \ NAME := awt_xawt, \ - SRC := $(LIBAWT_XAWT_DIRS), \ + EXTRA_SRC := $(LIBAWT_XAWT_EXTRA_SRC), \ + EXTRA_HEADER_DIRS := $(LIBAWT_XAWT_EXTRA_HEADER_DIRS), \ EXCLUDES := $(LIBAWT_XAWT_EXCLUDES), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) $(LIBAWT_XAWT_CFLAGS) \ @@ -350,10 +342,6 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),) $(call SET_SHARED_LIBRARY_ORIGIN) \ -L$(INSTALL_LIBRARIES_HERE), \ LIBS := $(X_LIBS) $(LIBAWT_XAWT_LIBS), \ - RC_FLAGS := $(RC_FLAGS) \ - -D "JDK_FNAME=xawt.dll" \ - -D "JDK_INTERNAL_NAME=xawt" \ - -D "JDK_FTYPE=0x2L", \ )) $(BUILD_LIBAWT_XAWT): $(call FindLib, java.base, java) @@ -367,36 +355,34 @@ endif ################################################################################ -LIBLCMS_SRC := $(TOPDIR)/src/java.desktop/share/native/liblcms -LIBLCMS_CPPFLAGS += -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/share/native/common/awt/debug \ - $(LIBJAVA_HEADER_FLAGS) \ - # # The fast floor code loses precision. LCMS_CFLAGS=-DCMS_DONT_USE_FAST_FLOOR +LCMS_CFLAGS_JDKLIB := $(filter-out -xc99=%none, $(CFLAGS_JDKLIB)) + ifeq ($(USE_EXTERNAL_LCMS), true) # If we're using an external library, we'll just need the wrapper part. # By including it explicitly, all other files will be excluded. BUILD_LIBLCMS_INCLUDE_FILES := LCMS.c + # If we're using an external library, we can't include our own SRC path + # as includes, instead the system headers should be used. + LIBLCMS_HEADERS_FROM_SRC := false else BUILD_LIBLCMS_INCLUDE_FILES := - # If we're using the bundled library, we'll need to include it in the - # include path explicitly. Otherwise the system headers will be used. - LIBLCMS_CPPFLAGS += $(addprefix -I, $(LIBLCMS_SRC)) endif $(eval $(call SetupJdkLibrary, BUILD_LIBLCMS, \ NAME := lcms, \ - SRC := $(LIBLCMS_SRC), \ INCLUDE_FILES := $(BUILD_LIBLCMS_INCLUDE_FILES), \ OPTIMIZATION := HIGHEST, \ - CFLAGS := $(filter-out -xc99=%none, $(CFLAGS_JDKLIB)) \ - $(LIBLCMS_CPPFLAGS) \ + CFLAGS := $(LCMS_CFLAGS_JDKLIB) \ $(LCMS_CFLAGS), \ CFLAGS_solaris := -xc99=no_lib, \ CFLAGS_windows := -DCMS_IS_WINDOWS_, \ + EXTRA_HEADER_DIRS := \ + common/awt/debug \ + libawt/java2d, \ + HEADERS_FROM_SRC := $(LIBLCMS_HEADERS_FROM_SRC), \ DISABLED_WARNINGS_gcc := format-nonliteral type-limits misleading-indentation, \ DISABLED_WARNINGS_clang := tautological-compare, \ DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \ @@ -414,8 +400,6 @@ $(BUILD_LIBLCMS): $(BUILD_LIBAWT) ################################################################################ -LIBJAVAJPEG_SRC += $(TOPDIR)/src/java.desktop/share/native/libjavajpeg - # "DISABLED_WARNINGS_gcc := clobbered" rationale: # Suppress gcc warnings like "variable might be clobbered by 'longjmp' # or 'vfork'": this warning indicates that some variable is placed to @@ -429,21 +413,20 @@ ifeq ($(USE_EXTERNAL_LIBJPEG), true) BUILD_LIBJAVAJPEG_INCLUDE_FILES := \ imageioJPEG.c \ jpegdecoder.c - BUILD_LIBJAVAJPEG_HEADERS := + # If we're using an external library, we can't include our own SRC path + # as includes, instead the system headers should be used. + LIBJPEG_HEADERS_FROM_SRC := false else LIBJPEG_LIBS := BUILD_LIBJAVAJPEG_INCLUDE_FILES := - BUILD_LIBJAVAJPEG_HEADERS := $(addprefix -I, $(LIBJAVAJPEG_SRC)) endif $(eval $(call SetupJdkLibrary, BUILD_LIBJAVAJPEG, \ NAME := javajpeg, \ - SRC := $(LIBJAVAJPEG_SRC), \ INCLUDE_FILES := $(BUILD_LIBJAVAJPEG_INCLUDE_FILES), \ OPTIMIZATION := HIGHEST, \ - CFLAGS := $(CFLAGS_JDKLIB) $(BUILD_LIBJAVAJPEG_HEADERS) \ - $(LIBJAVA_HEADER_FLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop, \ + CFLAGS := $(CFLAGS_JDKLIB), \ + HEADERS_FROM_SRC := $(LIBJPEG_HEADERS_FROM_SRC), \ DISABLED_WARNINGS_gcc := clobbered implicit-fallthrough shift-negative-value, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ @@ -460,42 +443,32 @@ TARGETS += $(BUILD_LIBJAVAJPEG) # Mac and Windows only use the native AWT lib, do not build libawt_headless ifeq ($(findstring $(OPENJDK_TARGET_OS), windows macosx),) - LIBAWT_HEADLESS_DIRS := $(TOPDIR)/src/java.desktop/unix/native/libawt_headless/awt \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d \ - $(TOPDIR)/src/java.desktop/share/native/common/java2d \ - $(TOPDIR)/src/java.desktop/share/native/common/font \ + LIBAWT_HEADLESS_EXTRA_SRC := \ + common/font \ + common/java2d \ + $(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \ # LIBAWT_HEADLESS_EXCLUDES := medialib - LIBAWT_HEADLESS_CFLAGS := -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - $(addprefix -I, $(LIBAWT_HEADLESS_DIRS)) \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/awt/image \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/awt/image/cvutils \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d/loops \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d/pipe \ - -I$(TOPDIR)/src/java.desktop/share/native/common/awt/debug \ - -I$(TOPDIR)/src/java.desktop/share/native/common/font \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/font \ - -I$(TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d/opengl \ - $(LIBJAVA_HEADER_FLAGS) \ + + LIBAWT_HEADLESS_EXTRA_HEADER_DIRS := \ + $(LIBAWT_DEFAULT_HEADER_DIRS) \ + common/awt/debug \ + common/font \ + common/java2d/opengl \ # + LIBAWT_HEADLESS_CFLAGS := $(CUPS_CFLAGS) $(FONTCONFIG_CFLAGS) $(X_CFLAGS) \ + -DHEADLESS=true -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" + $(eval $(call SetupJdkLibrary, BUILD_LIBAWT_HEADLESS, \ NAME := awt_headless, \ - SRC := $(LIBAWT_HEADLESS_DIRS), \ + EXTRA_SRC := $(LIBAWT_HEADLESS_EXTRA_SRC), \ EXCLUDES := $(LIBAWT_HEADLESS_EXCLUDES), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) \ - -DHEADLESS=true \ - -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \ - $(CUPS_CFLAGS) \ - $(FONTCONFIG_CFLAGS) \ - $(X_CFLAGS) \ $(LIBAWT_HEADLESS_CFLAGS), \ + EXTRA_HEADER_DIRS := $(LIBAWT_HEADLESS_EXTRA_HEADER_DIRS), \ DISABLED_WARNINGS_xlc := 1506-356, \ DISABLED_WARNINGS_solstudio := E_EMPTY_TRANSLATION_UNIT, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ @@ -519,12 +492,15 @@ endif ################################################################################ ifeq ($(FREETYPE_TO_USE), system) + # For use by libfontmanager: LIBFREETYPE_CFLAGS := $(FREETYPE_CFLAGS) LIBFREETYPE_LIBS := $(FREETYPE_LIBS) else - LIBFREETYPE_SRC := $(TOPDIR)/src/java.desktop/share/native/libfreetype - BUILD_LIBFREETYPE_HEADERS := $(addprefix -I, $(LIBFREETYPE_SRC)/include) - LIBFREETYPE_CFLAGS := $(BUILD_LIBFREETYPE_HEADERS) + BUILD_LIBFREETYPE_HEADER_DIRS := $(TOPDIR)/src/$(MODULE)/share/native/libfreetype/include + BUILD_LIBFREETYPE_CFLAGS := -DFT2_BUILD_LIBRARY $(EXPORT_ALL_SYMBOLS) + + # For use by libfontmanager: + LIBFREETYPE_CFLAGS := -I$(BUILD_LIBFREETYPE_HEADER_DIRS) ifeq ($(OPENJDK_TARGET_OS), windows) LIBFREETYPE_LIBS := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libfreetype/freetype.lib else @@ -533,10 +509,10 @@ else $(eval $(call SetupJdkLibrary, BUILD_LIBFREETYPE, \ NAME := freetype, \ - SRC := $(LIBFREETYPE_SRC)/src, \ OPTIMIZATION := HIGHEST, \ - CFLAGS := $(CFLAGS_JDKLIB) $(BUILD_LIBFREETYPE_HEADERS) \ - -DFT2_BUILD_LIBRARY $(EXPORT_ALL_SYMBOLS), \ + CFLAGS := $(CFLAGS_JDKLIB) \ + $(BUILD_LIBFREETYPE_CFLAGS), \ + EXTRA_HEADER_DIRS := $(BUILD_LIBFREETYPE_HEADER_DIRS), \ DISABLED_WARNINGS_solstudio := \ E_STATEMENT_NOT_REACHED \ E_END_OF_LOOP_CODE_NOT_REACHED, \ @@ -551,19 +527,6 @@ endif ########################################################################### -LIBFONTMANAGER_SRC := $(TOPDIR)/src/java.desktop/share/native/libfontmanager \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libfontmanager -LIBFONTMANAGER_CFLAGS := \ - $(addprefix -I, $(shell $(FIND) \ - $(LIBFONTMANAGER_SRC) \ - $(TOPDIR)/src/java.desktop/share/native/libawt \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt \ - $(TOPDIR)/src/java.desktop/share/native/common \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common -type d)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - $(LIBJAVA_HEADER_FLAGS) \ - # - #### Begin harfbuzz configuration HARFBUZZ_CFLAGS := -DHAVE_OT -DHAVE_FALLBACK -DHAVE_UCDN @@ -591,6 +554,16 @@ LIBFONTMANAGER_CFLAGS += $(HARFBUZZ_CFLAGS) #### End harfbuzz configuration +LIBFONTMANAGER_EXTRA_HEADER_DIRS := \ + libfontmanager/harfbuzz \ + libfontmanager/harfbuzz/hb-ucdn \ + common/awt \ + common/font \ + libawt/java2d \ + libawt/java2d/pipe \ + libawt/java2d/loops \ + # + LIBFONTMANAGER_CFLAGS += $(LIBFREETYPE_CFLAGS) BUILD_LIBFONTMANAGER_FONTLIB += $(LIBFREETYPE_LIBS) @@ -600,7 +573,6 @@ ifeq ($(OPENJDK_TARGET_OS), windows) LIBFONTMANAGER_EXCLUDE_FILES += X11FontScaler.c \ X11TextRenderer.c LIBFONTMANAGER_OPTIMIZATION := HIGHEST - LIBFONTMANAGER_CFLAGS += -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt/windows else ifeq ($(OPENJDK_TARGET_OS), macosx) LIBFONTMANAGER_EXCLUDE_FILES += X11FontScaler.c \ X11TextRenderer.c \ @@ -611,7 +583,7 @@ else lcdglyph.c endif -LIBFONTMANAGER_CFLAGS += $(FONT_HEADERS) $(X_CFLAGS) -DLE_STANDALONE -DHEADLESS +LIBFONTMANAGER_CFLAGS += $(X_CFLAGS) -DLE_STANDALONE -DHEADLESS ifeq ($(TOOLCHAIN_TYPE), gcc) # Turn off all warnings for sunFont.c. This is needed because the specific warning @@ -627,7 +599,6 @@ endif # libawt_xawt). See JDK-8196516 for details. $(eval $(call SetupJdkLibrary, BUILD_LIBFONTMANAGER, \ NAME := fontmanager, \ - SRC := $(LIBFONTMANAGER_SRC), \ EXCLUDE_FILES := $(LIBFONTMANAGER_EXCLUDE_FILES) \ AccelGlyphCache.c, \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ @@ -635,6 +606,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBFONTMANAGER, \ CXXFLAGS := $(CXXFLAGS_JDKLIB) $(LIBFONTMANAGER_CFLAGS), \ OPTIMIZATION := $(LIBFONTMANAGER_OPTIMIZATION), \ CFLAGS_windows = -DCC_NOEX, \ + EXTRA_HEADER_DIRS := $(LIBFONTMANAGER_EXTRA_HEADER_DIRS), \ WARNINGS_AS_ERRORS_xlc := false, \ DISABLED_WARNINGS_gcc := sign-compare int-to-pointer-cast \ type-limits missing-field-initializers implicit-fallthrough, \ @@ -666,7 +638,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBFONTMANAGER, \ $(BUILD_LIBFONTMANAGER): $(BUILD_LIBAWT) ifeq ($(OPENJDK_TARGET_OS), macosx) - $(BUILD_LIBFONTMANAGER): $(call FindLib, java.desktop, awt_lwawt) + $(BUILD_LIBFONTMANAGER): $(call FindLib, $(MODULE), awt_lwawt) endif ifeq ($(FREETYPE_TO_USE), bundled) @@ -678,29 +650,30 @@ TARGETS += $(BUILD_LIBFONTMANAGER) ################################################################################ ifeq ($(OPENJDK_TARGET_OS), windows) - LIBJAWT_SRC := $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libjawt - LIBJAWT_CFLAGS := -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt/windows \ - -I$(TOPDIR)/src/java.desktop/share/native/common/awt/debug \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/awt/image/cvutils \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt/java2d/windows \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - -I$(TOPDIR)/src/java.desktop/windows/native/include \ - -I$(TOPDIR)/src/java.desktop/share/native/include \ - $(LIBJAVA_HEADER_FLAGS) \ + + LIBJAWT_CFLAGS := -EHsc -DUNICODE -D_UNICODE + + LIBJAWT_EXTRA_HEADER_DIRS := \ + include \ + common/awt/debug \ + libawt/awt/image/cvutils \ + libawt/java2d \ + libawt/java2d/windows \ + libawt/windows \ + java.base:include \ + java.base:libjava \ # ifeq ($(OPENJDK_TARGET_CPU), x86) KERNEL32_LIB := kernel32.lib endif + $(eval $(call SetupJdkLibrary, BUILD_LIBJAWT, \ NAME := jawt, \ - SRC := $(LIBJAWT_SRC), \ - INCLUDE_FILES := $(LIBJAWT_INCLUDE_FILES), \ OPTIMIZATION := LOW, \ CFLAGS := $(CXXFLAGS_JDKLIB) \ - -EHsc -DUNICODE -D_UNICODE \ $(LIBJAWT_CFLAGS), \ + EXTRA_HEADER_DIRS := $(LIBJAWT_EXTRA_HEADER_DIRS), \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK), \ LIBS := $(JDKLIB_LIBS) $(KERNEL32_LIB) advapi32.lib $(WIN_AWT_LIB), \ )) @@ -719,17 +692,9 @@ ifeq ($(OPENJDK_TARGET_OS), windows) else # OPENJDK_TARGET_OS not windows ifeq ($(OPENJDK_TARGET_OS), macosx) - LIBJAWT_SRC := $(TOPDIR)/src/java.desktop/macosx/native/libjawt - else - LIBJAWT_SRC := $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libjawt + # libjawt on macosx do not use the unix code + LIBJAWT_EXCLUDE_SRC_PATTERNS := unix endif - LIBJAWT_CFLAGS := \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/include \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/include \ - -I$(TOPDIR)/src/java.desktop/share/native/include \ - $(LIBJAVA_HEADER_FLAGS) \ - # ifeq ($(OPENJDK_TARGET_OS), macosx) JAWT_LIBS := -lawt_lwawt @@ -742,19 +707,22 @@ else # OPENJDK_TARGET_OS not windows JAWT_LIBS += -lawt_xawt else JAWT_LIBS += -lawt_headless - HEADLESS_CFLAG += -DHEADLESS + ifeq ($(OPENJDK_TARGET_OS), linux) + JAWT_CFLAGS += -DHEADLESS + endif endif endif $(eval $(call SetupJdkLibrary, BUILD_LIBJAWT, \ NAME := jawt, \ - SRC := $(LIBJAWT_SRC), \ + EXCLUDE_SRC_PATTERNS := $(LIBJAWT_EXCLUDE_SRC_PATTERNS), \ INCLUDE_FILES := $(JAWT_FILES), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) \ - $(LIBJAWT_CFLAGS), \ - CFLAGS_linux := $(HEADLESS_CFLAG), \ - CFLAGS_macosx := $(LIBJAWT_CFLAGS_macosx), \ + $(JAWT_CFLAGS), \ + EXTRA_HEADER_DIRS := \ + include \ + common/awt, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \ @@ -782,52 +750,56 @@ TARGETS += $(BUILD_LIBJAWT) ifeq ($(ENABLE_HEADLESS_ONLY), false) - LIBSPLASHSCREEN_DIRS := \ - $(TOPDIR)/src/java.desktop/share/native/libjavajpeg \ - $(TOPDIR)/src/java.desktop/share/native/libsplashscreen \ + LIBSPLASHSCREEN_EXTRA_SRC := \ + common/awt/systemscale \ # - ifeq ($(USE_EXTERNAL_LIBGIF), true) - GIFLIB_LIBS := -lgif - LIBSPLASHSCREEN_EXCLUDES := giflib + ifeq ($(USE_EXTERNAL_LIBGIF), false) + LIBSPLASHSCREEN_HEADER_DIRS += libsplashscreen/giflib else - LIBSPLASHSCREEN_CFLAGS += -I$(TOPDIR)/src/java.desktop/share/native/libsplashscreen/giflib + LIBSPLASHSCREEN_EXCLUDES := giflib + GIFLIB_LIBS := -lgif endif - ifeq ($(USE_EXTERNAL_LIBJPEG), true) - LIBJPEG_LIBS := -ljpeg + ifeq ($(USE_EXTERNAL_LIBJPEG), false) + # While the following ought to work, it will currently pull in the closed + # additions to this library, and this was not done previously in the build. + # LIBSPLASHSCREEN_EXTRA_SRC += libjavajpeg + LIBSPLASHSCREEN_EXTRA_SRC += $(TOPDIR)/src/java.desktop/share/native/libjavajpeg else - LIBSPLASHSCREEN_DIRS += $(TOPDIR)/src/java.desktop/share/native/libjavajpeg - LIBJPEG_CFLAGS := -I$(TOPDIR)/src/java.desktop/share/native/libjavajpeg + LIBJPEG_LIBS := -ljpeg endif ifeq ($(USE_EXTERNAL_LIBPNG), false) - LIBSPLASHSCREEN_DIRS += $(TOPDIR)/src/java.desktop/share/native/libsplashscreen/libpng + LIBSPLASHSCREEN_HEADER_DIRS += libsplashscreen/libpng + + ifeq ($(OPENJDK_TARGET_OS), macosx) + ifeq ($(USE_EXTERNAL_LIBZ), true) + # When building our own libpng and using an external libz, we need to + # inject our own libz.h to tweak the exported ZLIB_VERNUM macro. See + # $(TOPDIR)/src/java.desktop/macosx/native/libsplashscreen/libpng/zlibwrapper/zlib.h + # for details. This must be specified with -iquote, not -I to avoid a + # circular include. + LIBSPLASHSCREEN_CFLAGS += -iquote $(TOPDIR)/src/$(MODULE)/macosx/native/libsplashscreen/libpng/zlibwrapper + endif + endif else LIBSPLASHSCREEN_EXCLUDES += libpng endif - ifneq ($(OPENJDK_TARGET_OS), macosx) - LIBSPLASHSCREEN_DIRS += $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libsplashscreen - else - LIBSPLASHSCREEN_DIRS += $(TOPDIR)/src/java.desktop/macosx/native/libsplashscreen + ifeq ($(USE_EXTERNAL_LIBZ), false) + LIBSPLASHSCREEN_EXTRA_SRC += java.base:libzip/zlib endif - ifneq ($(filter $(OPENJDK_TARGET_OS),linux solaris aix), ) - LIBSPLASHSCREEN_DIRS += $(TOPDIR)/src/java.desktop/unix/native/common/awt/systemscale + ifeq ($(OPENJDK_TARGET_OS), macosx) + # libsplashscreen on macosx do not use the unix code + LIBSPLASHSCREEN_EXCLUDE_SRC_PATTERNS := unix endif - ifeq ($(OPENJDK_TARGET_OS), windows) - LIBSPLASHSCREEN_DIRS += $(TOPDIR)/src/java.desktop/windows/native/common/awt/systemscale - endif - LIBSPLASHSCREEN_CFLAGS += -DSPLASHSCREEN -DPNG_NO_MMX_CODE -DPNG_ARM_NEON_OPT=0 \ - $(addprefix -I, $(LIBSPLASHSCREEN_DIRS)) \ - $(LIBJAVA_HEADER_FLAGS) \ - # + LIBSPLASHSCREEN_CFLAGS += -DSPLASHSCREEN -DPNG_NO_MMX_CODE -DPNG_ARM_NEON_OPT=0 ifeq ($(OPENJDK_TARGET_OS), macosx) LIBSPLASHSCREEN_CFLAGS += -DWITH_MACOSX - LIBSPLASHSCREEN_CFLAGS += -I$(TOPDIR)/src/java.desktop/macosx/native/libosxapp BUILD_LIBSPLASHSCREEN_java_awt_SplashScreen.c_CFLAGS := -x objective-c -O0 BUILD_LIBSPLASHSCREEN_splashscreen_gfx_impl.c_CFLAGS := -x objective-c -O0 @@ -845,20 +817,6 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) LIBSPLASHSCREEN_LIBS := - ifeq ($(USE_EXTERNAL_LIBZ), false) - LIBSPLASHSCREEN_DIRS += $(TOPDIR)/src/java.base/share/native/libzip/zlib - else - ifeq ($(OPENJDK_TARGET_OS), macosx) - ifeq ($(USE_EXTERNAL_LIBPNG), false) - # When building our own libpng and using an external libz, we need to - # inject our own libz.h to tweak the exported ZLIB_VERNUM macro. See - # $(TOPDIR)/src/java.desktop/macosx/native/libsplashscreen/libpng/zlib.h - # for details. - LIBSPLASHSCREEN_CFLAGS += -iquote $(TOPDIR)/src/java.desktop/macosx/native/libsplashscreen/libpng - endif - endif - endif - ifeq ($(OPENJDK_TARGET_OS), macosx) LIBSPLASHSCREEN_LIBS += \ $(LIBM) -lpthread -liconv -losxapp \ @@ -872,14 +830,22 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) LIBSPLASHSCREEN_LIBS += $(X_LIBS) -lX11 -lXext $(LIBM) -lpthread -ldl endif + LIBSPLASHSCREEN_HEADER_DIRS += \ + libosxapp \ + java.base:include \ + java.base:libjava \ + # + $(eval $(call SetupJdkLibrary, BUILD_LIBSPLASHSCREEN, \ NAME := splashscreen, \ - SRC := $(LIBSPLASHSCREEN_DIRS), \ + EXTRA_SRC := $(LIBSPLASHSCREEN_EXTRA_SRC), \ + EXCLUDE_SRC_PATTERNS := $(LIBSPLASHSCREEN_EXCLUDE_SRC_PATTERNS), \ EXCLUDE_FILES := imageioJPEG.c jpegdecoder.c pngtest.c, \ EXCLUDES := $(LIBSPLASHSCREEN_EXCLUDES), \ OPTIMIZATION := LOW, \ - CFLAGS := $(LIBSPLASHSCREEN_CFLAGS) $(CFLAGS_JDKLIB) \ + CFLAGS := $(CFLAGS_JDKLIB) $(LIBSPLASHSCREEN_CFLAGS) \ $(GIFLIB_CFLAGS) $(LIBJPEG_CFLAGS) $(PNG_CFLAGS) $(LIBZ_CFLAGS), \ + EXTRA_HEADER_DIRS := $(LIBSPLASHSCREEN_HEADER_DIRS), \ DISABLED_WARNINGS_gcc := sign-compare type-limits unused-result \ maybe-uninitialized shift-negative-value implicit-fallthrough, \ DISABLED_WARNINGS_clang := incompatible-pointer-types, \ @@ -898,7 +864,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) TARGETS += $(BUILD_LIBSPLASHSCREEN) ifeq ($(OPENJDK_TARGET_OS), macosx) - $(BUILD_LIBSPLASHSCREEN): $(call FindLib, java.desktop, osxapp) + $(BUILD_LIBSPLASHSCREEN): $(call FindLib, $(MODULE), osxapp) endif endif @@ -907,49 +873,38 @@ endif ifeq ($(OPENJDK_TARGET_OS), macosx) - LIBAWT_LWAWT_DIRS := \ - $(TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt \ - $(TOPDIR)/src/java.desktop/unix/native/common/awt \ - $(TOPDIR)/src/java.desktop/share/native/common/font \ - $(TOPDIR)/src/java.desktop/share/native/common/java2d \ + LIBAWT_LWAWT_EXTRA_SRC := \ + $(TOPDIR)/src/$(MODULE)/unix/native/common/awt \ + $(TOPDIR)/src/$(MODULE)/share/native/common/font \ + $(TOPDIR)/src/$(MODULE)/share/native/common/java2d \ # - LIBAWT_LWAWT_CFLAGS := \ - $(addprefix -I, $(LIBAWT_LWAWT_DIRS)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/awt \ - -I$(TOPDIR)/src/java.desktop/unix/native/libawt_xawt/awt \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/font \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl \ - -I$(TOPDIR)/src/java.desktop/share/native/common/awt/debug \ - -I$(TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \ - -I$(TOPDIR)/src/java.desktop/macosx/native/include \ - -I$(TOPDIR)/src/java.desktop/share/native/include \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/awt/image \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/awt/image/cvutils \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/unix/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d/loops \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d/pipe \ - -I$(TOPDIR)/src/java.desktop/share/native/libmlib_image/ \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libosxapp \ - $(LIBJAVA_HEADER_FLAGS) \ + LIBAWT_LWAWT_EXTRA_HEADER_DIRS := \ + $(LIBAWT_DEFAULT_HEADER_DIRS) \ + libawt_lwawt/awt \ + libawt_lwawt/font \ + libawt_lwawt/java2d/opengl \ + include \ + common/awt/debug \ + common/java2d/opengl \ + libosxapp \ # + LIBAWT_LWAWT_CFLAGS := $(X_CFLAGS) $(X_LIBS) + LIBAWT_LWAWT_EXFILES := fontpath.c awt_Font.c X11Color.c - LIBAWT_LWAWT_EXCLUDES := $(TOPDIR)/src/java.desktop/unix/native/common/awt/medialib + LIBAWT_LWAWT_EXCLUDES := $(TOPDIR)/src/$(MODULE)/unix/native/common/awt/medialib $(eval $(call SetupJdkLibrary, BUILD_LIBAWT_LWAWT, \ NAME := awt_lwawt, \ - SRC := $(LIBAWT_LWAWT_DIRS), \ + EXTRA_SRC := $(LIBAWT_LWAWT_EXTRA_SRC), \ INCLUDE_FILES := $(LIBAWT_LWAWT_FILES), \ EXCLUDE_FILES := $(LIBAWT_LWAWT_EXFILES), \ EXCLUDES := $(LIBAWT_LWAWT_EXCLUDES), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) \ - $(X_CFLAGS) \ - $(X_LIBS) \ $(LIBAWT_LWAWT_CFLAGS), \ + EXTRA_HEADER_DIRS := $(LIBAWT_LWAWT_EXTRA_HEADER_DIRS), \ DISABLED_WARNINGS_clang := incomplete-implementation enum-conversion \ deprecated-declarations objc-method-access bitwise-op-parentheses \ incompatible-pointer-types parentheses-equality extra-tokens, \ @@ -976,7 +931,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) $(BUILD_LIBAWT_LWAWT): $(BUILD_LIBMLIB_IMAGE) - $(BUILD_LIBAWT_LWAWT): $(call FindLib, java.desktop, osxapp) + $(BUILD_LIBAWT_LWAWT): $(call FindLib, $(MODULE), osxapp) $(BUILD_LIBAWT_LWAWT): $(call FindLib, java.base, java) @@ -988,15 +943,11 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) $(eval $(call SetupJdkLibrary, BUILD_LIBOSXUI, \ NAME := osxui, \ - SRC := $(TOPDIR)/src/java.desktop/macosx/native/libosxui, \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libosxui \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/awt \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libosxapp \ - -I$(TOPDIR)/src/java.base/share/native/libjava \ - -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop, \ + CFLAGS := $(CFLAGS_JDKLIB), \ + EXTRA_HEADER_DIRS := \ + libawt_lwawt/awt \ + libosxapp, \ DISABLED_WARNINGS_clang := deprecated-declarations, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN) \ @@ -1015,7 +966,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) $(BUILD_LIBOSXUI): $(BUILD_LIBAWT) - $(BUILD_LIBOSXUI): $(call FindLib, java.desktop, osxapp) + $(BUILD_LIBOSXUI): $(call FindLib, $(MODULE), osxapp) $(BUILD_LIBOSXUI): $(BUILD_LIBAWT_LWAWT) diff --git a/make/lib/CoreLibraries.gmk b/make/lib/CoreLibraries.gmk index 4a7dae1b7e6..46edc878893 100644 --- a/make/lib/CoreLibraries.gmk +++ b/make/lib/CoreLibraries.gmk @@ -104,7 +104,6 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBVERIFY, \ NAME := verify, \ - SRC := $(TOPDIR)/src/java.base/share/native/libverify, \ OPTIMIZATION := $(LIBVERIFY_OPTIMIZATION), \ CFLAGS := $(CFLAGS_JDKLIB), \ DISABLED_WARNINGS_gcc := implicit-fallthrough, \ @@ -119,13 +118,7 @@ TARGETS += $(BUILD_LIBVERIFY) ########################################################################################## -# Allow a custom makefile to add extra src dirs -LIBJAVA_SRC_DIRS += $(call FindSrcDirsForLib, java.base, java) - -LIBJAVA_CFLAGS := $(addprefix -I, $(LIBJAVA_SRC_DIRS)) \ - -I$(TOPDIR)/src/java.base/share/native/libfdlibm \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - -DARCHPROPNAME='"$(OPENJDK_TARGET_CPU_OSARCH)"' +LIBJAVA_CFLAGS := -DARCHPROPNAME='"$(OPENJDK_TARGET_CPU_OSARCH)"' ifeq ($(OPENJDK_TARGET_OS), macosx) BUILD_LIBJAVA_java_props_md.c_CFLAGS := -x objective-c @@ -134,12 +127,12 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBJAVA, \ NAME := java, \ - SRC := $(LIBJAVA_SRC_DIRS), \ OPTIMIZATION := HIGH, \ CFLAGS := $(CFLAGS_JDKLIB) \ $(LIBJAVA_CFLAGS), \ System.c_CFLAGS := $(VERSION_CFLAGS), \ jdk_util.c_CFLAGS := $(VERSION_CFLAGS), \ + EXTRA_HEADER_DIRS := libfdlibm, \ WARNINGS_AS_ERRORS_xlc := false, \ DISABLED_WARNINGS_gcc := unused-result, \ DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \ @@ -180,13 +173,9 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBZIP, \ NAME := zip, \ OPTIMIZATION := LOW, \ - SRC := $(TOPDIR)/src/java.base/share/native/libzip, \ EXCLUDES := $(LIBZIP_EXCLUDES), \ CFLAGS := $(CFLAGS_JDKLIB) \ - $(LIBZ_CFLAGS) \ - -I$(TOPDIR)/src/java.base/share/native/libjava \ - -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base, \ + $(LIBZ_CFLAGS), \ CFLAGS_unix := $(BUILD_LIBZIP_MMAP) -UDEBUG, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ @@ -200,22 +189,12 @@ TARGETS += $(BUILD_LIBZIP) ########################################################################################## -JIMAGELIB_CPPFLAGS := \ - -I$(TOPDIR)/src/java.base/share/native/libjava \ - -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava \ - -I$(TOPDIR)/src/java.base/share/native/libjimage \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - # - $(eval $(call SetupJdkLibrary, BUILD_LIBJIMAGE, \ NAME := jimage, \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ OPTIMIZATION := LOW, \ - SRC := $(TOPDIR)/src/java.base/share/native/libjimage \ - $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjimage, \ - EXCLUDES := $(LIBJIMAGE_EXCLUDES), \ - CFLAGS := $(CFLAGS_JDKLIB) $(JIMAGELIB_CPPFLAGS), \ - CXXFLAGS := $(CXXFLAGS_JDKLIB) $(JIMAGELIB_CPPFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ + CXXFLAGS := $(CXXFLAGS_JDKLIB), \ DISABLED_WARNINGS_gcc := implicit-fallthrough, \ CFLAGS_unix := -UDEBUG, \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ @@ -231,10 +210,6 @@ TARGETS += $(BUILD_LIBJIMAGE) ########################################################################################## -LIBJLI_SRC_DIRS := $(call FindSrcDirsForLib, java.base, jli) - -LIBJLI_CFLAGS := $(CFLAGS_JDKLIB) - ifeq ($(call check-jvm-variant, zero), true) ERGO_FAMILY := zero else @@ -263,7 +238,7 @@ endif ifeq ($(OPENJDK_TARGET_OS), windows) # Staticically link with c runtime on windows. - LIBJLI_CFLAGS := $(filter-out -MD, $(LIBJLI_CFLAGS)) + LIBJLI_CFLAGS_JDKLIB := $(filter-out -MD, $(CFLAGS_JDKLIB)) LIBJLI_OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE) # Supply the name of the C runtime lib. LIBJLI_CFLAGS += -DMSVCR_DLL_NAME='"$(notdir $(MSVCR_DLL))"' @@ -271,11 +246,10 @@ ifeq ($(OPENJDK_TARGET_OS), windows) LIBJLI_CFLAGS += -DMSVCP_DLL_NAME='"$(notdir $(MSVCP_DLL))"' endif else + LIBJLI_CFLAGS_JDKLIB := $(CFLAGS_JDKLIB) LIBJLI_OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE)/jli endif -LIBJLI_CFLAGS += $(addprefix -I, $(LIBJLI_SRC_DIRS)) - LIBJLI_CFLAGS += $(LIBZ_CFLAGS) ifneq ($(USE_EXTERNAL_LIBZ), true) @@ -293,12 +267,10 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBJLI, \ NAME := jli, \ OUTPUT_DIR := $(LIBJLI_OUTPUT_DIR), \ - SRC := $(LIBJLI_SRC_DIRS), \ EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \ OPTIMIZATION := HIGH, \ - CFLAGS := $(LIBJLI_CFLAGS), \ - DISABLED_WARNINGS_gcc := maybe-uninitialized, \ + CFLAGS := $(LIBJLI_CFLAGS_JDKLIB) $(LIBJLI_CFLAGS), \ DISABLED_WARNINGS_solstudio := \ E_ASM_DISABLES_OPTIMIZATION \ E_STATEMENT_NOT_REACHED, \ @@ -316,6 +288,8 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJLI, \ TARGETS += $(BUILD_LIBJLI) +LIBJLI_SRC_DIRS := $(call FindSrcDirsForComponent, java.base, libjli) + # On windows, the static library has the same suffix as the import library created by # with the shared library, so the static library is given a different name. No harm # in doing it for all platform to reduce complexity. @@ -328,7 +302,8 @@ ifeq ($(OPENJDK_TARGET_OS), windows) EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \ OPTIMIZATION := HIGH, \ - CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS), \ + CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS_JDKLIB) $(LIBJLI_CFLAGS) \ + $(addprefix -I, $(LIBJLI_SRC_DIRS)), \ ARFLAGS := $(ARFLAGS), \ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static, \ )) @@ -347,7 +322,8 @@ else ifeq ($(OPENJDK_TARGET_OS), macosx) EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \ OPTIMIZATION := HIGH, \ - CFLAGS := $(CFLAGS_JDKLIB) $(LIBJLI_CFLAGS), \ + CFLAGS := $(LIBJLI_CFLAGS_JDKLIB) $(LIBJLI_CFLAGS) \ + $(addprefix -I, $(LIBJLI_SRC_DIRS)), \ LDFLAGS := -nostdlib $(ARFLAGS), \ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static, \ )) @@ -371,7 +347,7 @@ else ifeq ($(OPENJDK_TARGET_OS), aix) EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \ OPTIMIZATION := HIGH, \ - CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS), \ + CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS_JDKLIB) $(LIBJLI_CFLAGS), \ ARFLAGS := $(ARFLAGS), \ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static)) diff --git a/make/lib/Lib-java.base.gmk b/make/lib/Lib-java.base.gmk index 1d29fb9e820..66327271dd1 100644 --- a/make/lib/Lib-java.base.gmk +++ b/make/lib/Lib-java.base.gmk @@ -29,9 +29,7 @@ include LibCommon.gmk $(eval $(call IncludeCustomExtension, lib/Lib-java.base.gmk)) # Prepare the find cache. -LIB_java.base_SRC_DIRS += $(TOPDIR)/src/java.base/*/native - -$(eval $(call FillCacheFind, $(wildcard $(LIB_java.base_SRC_DIRS)))) +$(eval $(call FillCacheFind, $(wildcard $(TOPDIR)/src/java.base/*/native))) ################################################################################ # Create all the core libraries @@ -41,14 +39,10 @@ include CoreLibraries.gmk ################################################################################ # Create the network library -LIBNET_SRC_DIRS := $(call FindSrcDirsForLib, java.base, net) - $(eval $(call SetupJdkLibrary, BUILD_LIBNET, \ NAME := net, \ - SRC := $(LIBNET_SRC_DIRS), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - $(LIBJAVA_HEADER_FLAGS) $(addprefix -I, $(LIBNET_SRC_DIRS)), \ + CFLAGS := $(CFLAGS_JDKLIB), \ DISABLED_WARNINGS_gcc := format-nonliteral, \ DISABLED_WARNINGS_clang := parentheses-equality constant-logical-operand, \ DISABLED_WARNINGS_microsoft := 4244 4047 4133 4996, \ @@ -72,31 +66,15 @@ TARGETS += $(BUILD_LIBNET) ################################################################################ # Create the nio library -BUILD_LIBNIO_SRC := \ - $(TOPDIR)/src/java.base/share/native/libnio \ - $(TOPDIR)/src/java.base/share/native/libnio/ch \ - $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libnio \ - $(sort $(wildcard \ - $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libnio/ch \ - $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libnio/fs \ - $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libnio/ch \ - $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libnio/fs)) \ - # - -BUILD_LIBNIO_CFLAGS := \ - $(addprefix -I, $(BUILD_LIBNIO_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - $(LIBJAVA_HEADER_FLAGS) \ - $(addprefix -I, $(BUILD_LIBNET_SRC)) - $(eval $(call SetupJdkLibrary, BUILD_LIBNIO, \ NAME := nio, \ - SRC := $(BUILD_LIBNIO_SRC), \ - EXCLUDE_FILES := $(BUILD_LIBNIO_EXFILES), \ OPTIMIZATION := HIGH, \ WARNINGS_AS_ERRORS_xlc := false, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(BUILD_LIBNIO_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ + EXTRA_HEADER_DIRS := \ + libnio/ch \ + libnio/fs \ + libnet, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_unix := -ljava -lnet, \ @@ -122,17 +100,10 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) # JavaNativeFoundation framework not supported in static builds ifneq ($(STATIC_BUILD), true) - LIBOSXSECURITY_DIRS := $(TOPDIR)/src/java.base/macosx/native/libosxsecurity - LIBOSXSECURITY_CFLAGS := -I$(LIBOSXSECURITY_DIRS) \ - $(LIBJAVA_HEADER_FLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - $(eval $(call SetupJdkLibrary, BUILD_LIBOSXSECURITY, \ NAME := osxsecurity, \ - SRC := $(LIBOSXSECURITY_DIRS), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(LIBOSXSECURITY_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ DISABLED_WARNINGS_clang := deprecated-declarations, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base \ @@ -158,7 +129,6 @@ endif ifeq ($(OPENJDK_TARGET_OS_TYPE), unix) ifeq ($(STATIC_BUILD), false) - LIBJSIG_SRC_DIR := $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjsig LIBJSIG_MAPFILE := $(wildcard $(TOPDIR)/make/mapfiles/libjsig/mapfile-vers-$(OPENJDK_TARGET_OS)) ifeq ($(OPENJDK_TARGET_OS), linux) @@ -168,7 +138,6 @@ ifeq ($(OPENJDK_TARGET_OS_TYPE), unix) $(eval $(call SetupJdkLibrary, BUILD_LIBJSIG, \ NAME := jsig, \ - SRC := $(LIBJSIG_SRC_DIR), \ CFLAGS := $(CFLAGS_JDKLIB) $(LIBJSIG_CFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/make/lib/Lib-java.desktop.gmk b/make/lib/Lib-java.desktop.gmk index 5a2f77f878b..81f85fe28f0 100644 --- a/make/lib/Lib-java.desktop.gmk +++ b/make/lib/Lib-java.desktop.gmk @@ -29,9 +29,7 @@ include LibCommon.gmk $(eval $(call IncludeCustomExtension, lib/Lib-java.desktop.gmk)) # Prepare the find cache. -LIB_java.desktop_SRC_DIRS += $(TOPDIR)/src/java.desktop/*/native - -$(eval $(call FillCacheFind, $(wildcard $(LIB_java.desktop_SRC_DIRS)))) +$(eval $(call FillCacheFind, $(wildcard $(TOPDIR)/src/java.desktop/*/native))) ################################################################################ # Create the AWT/2D libraries @@ -43,16 +41,8 @@ include Awt2dLibraries.gmk ifneq ($(OPENJDK_TARGET_OS), aix) - LIBJSOUND_SRC_DIRS := $(wildcard \ - $(TOPDIR)/src/java.desktop/share/native/libjsound \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/libjsound \ - ) - LIBJSOUND_CFLAGS := \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ $(ALSA_CFLAGS) \ - $(LIBJAVA_HEADER_FLAGS) \ - $(foreach dir, $(LIBJSOUND_SRC_DIRS), -I$(dir)) \ -DX_PLATFORM=X_$(OPENJDK_TARGET_OS_UPPERCASE) \ -DUSE_PORTS=TRUE \ -DUSE_DAUDIO=TRUE \ @@ -71,7 +61,6 @@ ifneq ($(OPENJDK_TARGET_OS), aix) $(eval $(call SetupJdkLibrary, BUILD_LIBJSOUND, \ NAME := jsound, \ - SRC := $(LIBJSOUND_SRC_DIRS), \ TOOLCHAIN := $(LIBJSOUND_TOOLCHAIN), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) \ @@ -97,15 +86,11 @@ endif # Create the macosx specific osxapp and osx libraries ifeq ($(OPENJDK_TARGET_OS), macosx) - LIBOSXAPP_SRC := $(TOPDIR)/src/java.desktop/macosx/native/libosxapp $(eval $(call SetupJdkLibrary, BUILD_LIBOSXAPP, \ NAME := osxapp, \ - SRC := $(LIBOSXAPP_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(addprefix -I, $(LIBOSXAPP_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop, \ + CFLAGS := $(CFLAGS_JDKLIB), \ DISABLED_WARNINGS_clang := objc-method-access objc-root-class \ deprecated-declarations, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ @@ -129,19 +114,11 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) ############################################################################## - LIBOSX_DIRS := $(TOPDIR)/src/java.desktop/macosx/native/libosx - LIBOSX_CFLAGS := -I$(LIBOSX_DIRS) \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libosxapp \ - $(LIBJAVA_HEADER_FLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - # - $(eval $(call SetupJdkLibrary, BUILD_LIBOSX, \ NAME := osx, \ - SRC := $(LIBOSX_DIRS), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(LIBOSX_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ + EXTRA_HEADER_DIRS := libosxapp, \ DISABLED_WARNINGS_clang := deprecated-declarations, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.desktop \ diff --git a/make/lib/Lib-java.instrument.gmk b/make/lib/Lib-java.instrument.gmk index 3ec153ef462..7e625e3a036 100644 --- a/make/lib/Lib-java.instrument.gmk +++ b/make/lib/Lib-java.instrument.gmk @@ -30,32 +30,24 @@ $(eval $(call IncludeCustomExtension, lib/Lib-java.instrument.gmk)) ################################################################################ -LIBINSTRUMENT_SRC := $(TOPDIR)/src/java.instrument/share/native/libinstrument \ - $(TOPDIR)/src/java.instrument/$(OPENJDK_TARGET_OS_TYPE)/native/libinstrument \ - # -LIBINSTRUMENT_CFLAGS := $(CFLAGS_JDKLIB) \ - $(addprefix -I, $(LIBINSTRUMENT_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.instrument \ - -I$(TOPDIR)/src/java.base/share/native/libjli \ - -I$(TOPDIR)/src/java.base/share/native/libjava \ - # - ifeq ($(OPENJDK_TARGET_OS), windows) # Statically link the C runtime so that there are not dependencies on modules # not on the search patch when invoked from the Windows system directory # (or elsewhere). - LIBINSTRUMENT_CFLAGS := $(filter-out -MD, $(LIBINSTRUMENT_CFLAGS)) + LIBINSTRUMENT_CFLAGS_JDKLIB := $(filter-out -MD, $(CFLAGS_JDKLIB)) # equivalent of strcasecmp is stricmp on Windows - LIBINSTRUMENT_CFLAGS += -Dstrcasecmp=stricmp + LIBINSTRUMENT_CFLAGS := -Dstrcasecmp=stricmp +else + LIBINSTRUMENT_CFLAGS_JDKLIB := $(CFLAGS_JDKLIB) endif $(eval $(call SetupJdkLibrary, BUILD_LIBINSTRUMENT, \ NAME := instrument, \ - SRC := $(LIBINSTRUMENT_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(LIBINSTRUMENT_CFLAGS), \ + CFLAGS := $(LIBINSTRUMENT_CFLAGS_JDKLIB) $(LIBINSTRUMENT_CFLAGS), \ CFLAGS_debug := -DJPLIS_LOGGING, \ CFLAGS_release := -DNO_JPLIS_LOGGING, \ + EXTRA_HEADER_DIRS := java.base:libjli, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN) \ $(LIBINSTRUMENT_LDFLAGS), \ diff --git a/make/lib/Lib-java.management.gmk b/make/lib/Lib-java.management.gmk index 6444feaa2f5..a70a3ccf45a 100644 --- a/make/lib/Lib-java.management.gmk +++ b/make/lib/Lib-java.management.gmk @@ -30,13 +30,6 @@ $(eval $(call IncludeCustomExtension, lib/Lib-java.management.gmk)) ################################################################################ -LIBMANAGEMENT_SRC += $(TOPDIR)/src/java.management/share/native/libmanagement -LIBMANAGEMENT_CFLAGS := -I$(TOPDIR)/src/hotspot/share/include \ - $(addprefix -I,$(LIBMANAGEMENT_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.management \ - $(LIBJAVA_HEADER_FLAGS) \ - # - LIBMANAGEMENT_OPTIMIZATION := HIGH ifneq ($(findstring $(OPENJDK_TARGET_OS), solaris linux), ) ifeq ($(COMPILE_WITH_DEBUG_SYMBOLS), true) @@ -46,9 +39,8 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBMANAGEMENT, \ NAME := management, \ - SRC := $(LIBMANAGEMENT_SRC), \ OPTIMIZATION := $(LIBMANAGEMENT_OPTIMIZATION), \ - CFLAGS := $(CFLAGS_JDKLIB) $(LIBMANAGEMENT_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := $(JDKLIB_LIBS), \ diff --git a/make/lib/Lib-java.prefs.gmk b/make/lib/Lib-java.prefs.gmk index 6d72189d563..cac3b17e26a 100644 --- a/make/lib/Lib-java.prefs.gmk +++ b/make/lib/Lib-java.prefs.gmk @@ -27,18 +27,16 @@ include LibCommon.gmk ################################################################################ +# libprefs on macosx do not use the unix code ifeq ($(OPENJDK_TARGET_OS), macosx) - LIBPREF_SRC_DIRS := $(TOPDIR)/src/java.prefs/macosx/native/libprefs -else - LIBPREF_SRC_DIRS := $(TOPDIR)/src/java.prefs/$(OPENJDK_TARGET_OS_TYPE)/native/libprefs + LIBPREFS_EXCLUDE_SRC_PATTERNS := unix endif $(eval $(call SetupJdkLibrary, BUILD_LIBPREFS, \ NAME := prefs, \ - SRC := $(LIBPREF_SRC_DIRS), \ + EXCLUDE_SRC_PATTERNS := $(LIBPREFS_EXCLUDE_SRC_PATTERNS), \ OPTIMIZATION := HIGH, \ - CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBPREF_SRC_DIRS)) \ - $(LIBJAVA_HEADER_FLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_unix := -ljvm, \ diff --git a/make/lib/Lib-java.rmi.gmk b/make/lib/Lib-java.rmi.gmk index f2c09c01829..56b60905603 100644 --- a/make/lib/Lib-java.rmi.gmk +++ b/make/lib/Lib-java.rmi.gmk @@ -29,9 +29,8 @@ include LibCommon.gmk $(eval $(call SetupJdkLibrary, BUILD_LIBRMI, \ NAME := rmi, \ - SRC := $(TOPDIR)/src/java.rmi/share/native/librmi, \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/java.rmi, \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_unix := -ljvm, \ diff --git a/make/lib/Lib-java.security.jgss.gmk b/make/lib/Lib-java.security.jgss.gmk index 89752deef9f..b130671efd6 100644 --- a/make/lib/Lib-java.security.jgss.gmk +++ b/make/lib/Lib-java.security.jgss.gmk @@ -27,16 +27,10 @@ include LibCommon.gmk ################################################################################ -LIBJ2GSS_SRC := $(TOPDIR)/src/java.security.jgss/share/native/libj2gss \ - # - $(eval $(call SetupJdkLibrary, BUILD_LIBJ2GSS, \ NAME := j2gss, \ - SRC := $(LIBJ2GSS_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBJ2GSS_SRC)) \ - $(LIBJAVA_HEADER_FLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.security.jgss, \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := $(LIBDL), \ @@ -49,15 +43,10 @@ TARGETS += $(BUILD_LIBJ2GSS) ifneq ($(BUILD_CRYPTO), false) ifeq ($(OPENJDK_TARGET_OS), windows) - BUILD_LIBW2K_LSA_AUTH_SRC := $(call FindSrcDirsForLib, $(MODULE), w2k_lsa_auth) - $(eval $(call SetupJdkLibrary, BUILD_LIBW2K_LSA_AUTH, \ NAME := w2k_lsa_auth, \ - SRC := $(BUILD_LIBW2K_LSA_AUTH_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(addprefix -I, $(BUILD_LIBW2K_LSA_AUTH_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.security.jgss, \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := advapi32.lib Secur32.lib netapi32.lib kernel32.lib user32.lib \ @@ -69,17 +58,12 @@ ifneq ($(BUILD_CRYPTO), false) endif ifeq ($(OPENJDK_TARGET_OS), macosx) - BUILD_LIBOSXKRB5_SRC := $(call FindSrcDirsForLib, $(MODULE), osxkrb5) - # libosxkrb5 needs to call deprecated krb5 APIs so that java # can use the native credentials cache. $(eval $(call SetupJdkLibrary, BUILD_LIBOSXKRB5, \ NAME := osxkrb5, \ - SRC := $(BUILD_LIBOSXKRB5_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(addprefix -I, $(BUILD_LIBOSXKRB5_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.security.jgss, \ + CFLAGS := $(CFLAGS_JDKLIB), \ DISABLED_WARNINGS_clang := deprecated-declarations, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/make/lib/Lib-java.smartcardio.gmk b/make/lib/Lib-java.smartcardio.gmk index 337daa48e1e..a8c65061521 100644 --- a/make/lib/Lib-java.smartcardio.gmk +++ b/make/lib/Lib-java.smartcardio.gmk @@ -27,18 +27,12 @@ include LibCommon.gmk ################################################################################ -LIBJ2PCSC_SRC := $(TOPDIR)/src/java.smartcardio/share/native/libj2pcsc \ - $(TOPDIR)/src/java.smartcardio/$(OPENJDK_TARGET_OS_TYPE)/native/libj2pcsc -LIBJ2PCSC_CPPFLAGS := $(addprefix -I,$(LIBJ2PCSC_SRC)) \ - -I$(TOPDIR)/src/java.smartcardio/$(OPENJDK_TARGET_OS_TYPE)/native/libj2pcsc/MUSCLE \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.smartcardio - $(eval $(call SetupJdkLibrary, BUILD_LIBJ2PCSC, \ NAME := j2pcsc, \ - SRC := $(LIBJ2PCSC_SRC), \ + CFLAGS := $(CFLAGS_JDKLIB), \ CFLAGS_unix := -D__sun_jdk, \ + EXTRA_HEADER_DIRS := libj2pcsc/MUSCLE, \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(LIBJ2PCSC_CPPFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_unix := $(LIBDL), \ diff --git a/make/lib/Lib-jdk.accessibility.gmk b/make/lib/Lib-jdk.accessibility.gmk index ea35ab39293..b7f820b8ba3 100644 --- a/make/lib/Lib-jdk.accessibility.gmk +++ b/make/lib/Lib-jdk.accessibility.gmk @@ -30,12 +30,6 @@ include LibCommon.gmk ifeq ($(OPENJDK_TARGET_OS), windows) ROOT_SRCDIR := $(TOPDIR)/src/jdk.accessibility/windows/native - JAVA_AB_SRCDIR := $(ROOT_SRCDIR)/libjavaaccessbridge $(ROOT_SRCDIR)/common - WIN_AB_SRCDIR := $(ROOT_SRCDIR)/libwindowsaccessbridge $(ROOT_SRCDIR)/common - SYSINFO_SRCDIR := $(ROOT_SRCDIR)/libjabsysinfo - ACCESSBRIDGE_CFLAGS := -I$(SUPPORT_OUTPUTDIR)/headers/jdk.accessibility \ - -I$(TOPDIR)/src/java.desktop/windows/native/include \ - -I$(TOPDIR)/src/java.desktop/share/native/include define SetupJavaDLL # Parameter 1 Suffix @@ -43,13 +37,16 @@ ifeq ($(OPENJDK_TARGET_OS), windows) $(call SetupJdkLibrary, BUILD_JAVAACCESSBRIDGE$1, \ NAME := javaaccessbridge$1, \ - SRC := $(JAVA_AB_SRCDIR), \ + SRC := libjavaaccessbridge, \ + EXTRA_SRC := common, \ OPTIMIZATION := LOW, \ DISABLED_WARNINGS_microsoft := 4311 4302 4312, \ - CFLAGS := $(CFLAGS_JDKLIB) $(ACCESSBRIDGE_CFLAGS) \ - $(addprefix -I,$(JAVA_AB_SRCDIR)) \ - -I$(ROOT_SRCDIR)/include/bridge \ + CFLAGS := $(CFLAGS_JDKLIB) \ -DACCESSBRIDGE_ARCH_$2, \ + EXTRA_HEADER_DIRS := \ + include/bridge \ + java.base:include \ + java.desktop:include, \ LDFLAGS := $(LDFLAGS_JDKLIB), \ LIBS := kernel32.lib user32.lib gdi32.lib \ winspool.lib comdlg32.lib advapi32.lib shell32.lib \ @@ -68,13 +65,15 @@ ifeq ($(OPENJDK_TARGET_OS), windows) # Parameter 2 ACCESSBRIDGE_ARCH_ suffix $(call SetupJdkLibrary, BUILD_WINDOWSACCESSBRIDGE$1, \ NAME := windowsaccessbridge$1, \ - SRC := $(WIN_AB_SRCDIR), \ + SRC := libwindowsaccessbridge, \ + EXTRA_SRC := common, \ OPTIMIZATION := LOW, \ DISABLED_WARNINGS_microsoft := 4311 4302 4312, \ - CFLAGS := $(filter-out -MD, $(CFLAGS_JDKLIB)) -MT $(ACCESSBRIDGE_CFLAGS) \ - $(addprefix -I,$(WIN_AB_SRCDIR)) \ - -I$(ROOT_SRCDIR)/include/bridge \ + CFLAGS := $(filter-out -MD, $(CFLAGS_JDKLIB)) -MT \ -DACCESSBRIDGE_ARCH_$2, \ + EXTRA_HEADER_DIRS := \ + include/bridge \ + java.base:include, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ -def:$(ROOT_SRCDIR)/libwindowsaccessbridge/WinAccessBridge.DEF, \ LIBS := kernel32.lib user32.lib gdi32.lib \ @@ -91,9 +90,8 @@ ifeq ($(OPENJDK_TARGET_OS), windows) $(call SetupJdkLibrary, BUILD_ACCESSBRIDGESYSINFO, \ NAME := jabsysinfo, \ - SRC := $(SYSINFO_SRCDIR), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(ACCESSBRIDGE_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB), \ VERSIONINFO_RESOURCE := $(ROOT_SRCDIR)/common/AccessBridgeStatusWindow.rc, \ ) diff --git a/make/lib/Lib-jdk.attach.gmk b/make/lib/Lib-jdk.attach.gmk index 827f1bf723e..1c24e554037 100644 --- a/make/lib/Lib-jdk.attach.gmk +++ b/make/lib/Lib-jdk.attach.gmk @@ -36,11 +36,8 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBATTACH, \ NAME := attach, \ - SRC := $(call FindSrcDirsForLib, jdk.attach, attach), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.attach \ - $(LIBJAVA_HEADER_FLAGS) $(LIBATTACH_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB) $(LIBATTACH_CFLAGS), \ CFLAGS_windows := /Gy, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/make/lib/Lib-jdk.crypto.cryptoki.gmk b/make/lib/Lib-jdk.crypto.cryptoki.gmk index 847d5b356be..3f25d7c04fd 100644 --- a/make/lib/Lib-jdk.crypto.cryptoki.gmk +++ b/make/lib/Lib-jdk.crypto.cryptoki.gmk @@ -27,16 +27,10 @@ include LibCommon.gmk ################################################################################ -LIBJ2PKCS11_SRC := $(TOPDIR)/src/jdk.crypto.cryptoki/share/native/libj2pkcs11 \ - $(TOPDIR)/src/jdk.crypto.cryptoki/$(OPENJDK_TARGET_OS_TYPE)/native/libj2pkcs11 - $(eval $(call SetupJdkLibrary, BUILD_LIBJ2PKCS11, \ NAME := j2pkcs11, \ - SRC := $(LIBJ2PKCS11_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBJ2PKCS11_SRC)) \ - $(LIBJAVA_HEADER_FLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.crypto.cryptoki, \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_unix := $(LIBDL), \ diff --git a/make/lib/Lib-jdk.crypto.ec.gmk b/make/lib/Lib-jdk.crypto.ec.gmk index e30b57d4341..dfecc1d3cbd 100644 --- a/make/lib/Lib-jdk.crypto.ec.gmk +++ b/make/lib/Lib-jdk.crypto.ec.gmk @@ -28,31 +28,23 @@ include LibCommon.gmk ################################################################################ ifeq ($(ENABLE_INTREE_EC), true) - - LIBSUNEC_SRC := $(TOPDIR)/src/jdk.crypto.ec/share/native/libsunec - BUILD_LIBSUNEC_FLAGS := $(addprefix -I, $(SUNEC_SRC)) - - # # On sol-sparc...all libraries are compiled with -xregs=no%appl - # (set in CFLAGS_REQUIRED_sparc) - # - # except!!! libsunec.so - # - ECC_JNI_SOLSPARC_FILTER := + # (set in CFLAGS_REQUIRED_sparc) except libsunec.so ifeq ($(OPENJDK_TARGET_CPU_ARCH), sparc) - ECC_JNI_SOLSPARC_FILTER := -xregs=no%appl + BUILD_LIBSUNEC_CFLAGS_JDKLIB := $(filter-out -xregs=no%appl, $(CFLAGS_JDKLIB)) + BUILD_LIBSUNEC_CXXFLAGS_JDKLIB := $(filter-out -xregs=no%appl, $(CXXFLAGS_JDKLIB)) + else + BUILD_LIBSUNEC_CFLAGS_JDKLIB := $(CFLAGS_JDKLIB) + BUILD_LIBSUNEC_CXXFLAGS_JDKLIB := $(CXXFLAGS_JDKLIB) endif $(eval $(call SetupJdkLibrary, BUILD_LIBSUNEC, \ NAME := sunec, \ - SRC := $(LIBSUNEC_SRC), \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ OPTIMIZATION := LOW, \ - CFLAGS := $(filter-out $(ECC_JNI_SOLSPARC_FILTER), $(CFLAGS_JDKLIB)) \ - $(BUILD_LIBSUNEC_FLAGS) \ + CFLAGS := $(BUILD_LIBSUNEC_CFLAGS_JDKLIB) \ -DMP_API_COMPATIBLE -DNSS_ECC_MORE_THAN_SUITE_B, \ - CXXFLAGS := $(filter-out $(ECC_JNI_SOLSPARC_FILTER), $(CXXFLAGS_JDKLIB)) \ - $(BUILD_LIBSUNEC_FLAGS), \ + CXXFLAGS := $(BUILD_LIBSUNEC_CXXFLAGS_JDKLIB), \ DISABLED_WARNINGS_gcc := sign-compare implicit-fallthrough, \ DISABLED_WARNINGS_microsoft := 4101 4244 4146 4018, \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK), \ diff --git a/make/lib/Lib-jdk.crypto.mscapi.gmk b/make/lib/Lib-jdk.crypto.mscapi.gmk index 3bd4eb9e357..e28e428f49e 100644 --- a/make/lib/Lib-jdk.crypto.mscapi.gmk +++ b/make/lib/Lib-jdk.crypto.mscapi.gmk @@ -29,14 +29,10 @@ include LibCommon.gmk ifeq ($(OPENJDK_TARGET_OS), windows) - LIBSUNMSCAPI_SRC := $(TOPDIR)/src/jdk.crypto.mscapi/$(OPENJDK_TARGET_OS_TYPE)/native/libsunmscapi - $(eval $(call SetupJdkLibrary, BUILD_LIBSUNMSCAPI, \ NAME := sunmscapi, \ - SRC := $(LIBSUNMSCAPI_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - -I$(LIBSUNMSCAPI_SRC), \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := crypt32.lib advapi32.lib, \ diff --git a/make/lib/Lib-jdk.crypto.ucrypto.gmk b/make/lib/Lib-jdk.crypto.ucrypto.gmk index 758491007d3..c00e543737b 100644 --- a/make/lib/Lib-jdk.crypto.ucrypto.gmk +++ b/make/lib/Lib-jdk.crypto.ucrypto.gmk @@ -29,14 +29,10 @@ include LibCommon.gmk ifeq ($(OPENJDK_TARGET_OS), solaris) - LIBJ2UCRYPTO_SRC := $(TOPDIR)/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto - $(eval $(call SetupJdkLibrary, BUILD_LIBJ2UCRYPTO, \ NAME := j2ucrypto, \ - SRC := $(LIBJ2UCRYPTO_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(addprefix -I, $(LIBJ2UCRYPTO_SRC)), \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB), \ LIBS := $(LIBDL), \ )) diff --git a/make/lib/Lib-jdk.hotspot.agent.gmk b/make/lib/Lib-jdk.hotspot.agent.gmk index 3f023dbd772..2f805c438e8 100644 --- a/make/lib/Lib-jdk.hotspot.agent.gmk +++ b/make/lib/Lib-jdk.hotspot.agent.gmk @@ -29,19 +29,6 @@ $(eval $(call IncludeCustomExtension, hotspot/lib/Lib-jdk.hotspot.agent.gmk)) ################################################################################ -SA_TOPDIR := $(TOPDIR)/src/jdk.hotspot.agent - -SA_SRC += \ - $(SA_TOPDIR)/share/native/libsaproc \ - $(SA_TOPDIR)/$(OPENJDK_TARGET_OS)/native/libsaproc \ - # - -SA_INCLUDES := \ - $(addprefix -I, $(SA_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.hotspot.agent \ - -I$(TOPDIR)/src/hotspot/os/$(OPENJDK_TARGET_OS) \ - # - ifeq ($(OPENJDK_TARGET_OS), linux) SA_CFLAGS := -D_FILE_OFFSET_BITS=64 @@ -68,9 +55,8 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBSA, \ DISABLED_WARNINGS_microsoft := 4267, \ DISABLED_WARNINGS_gcc := sign-compare, \ DISABLED_WARNINGS_CXX_solstudio := truncwarn unknownpragma, \ - SRC := $(SA_SRC), \ - CFLAGS := $(CFLAGS_JDKLIB) $(SA_INCLUDES) $(SA_CFLAGS) $(SA_CUSTOM_CFLAGS), \ - CXXFLAGS := $(CXXFLAGS_JDKLIB) $(SA_INCLUDES) $(SA_CFLAGS) $(SA_CXXFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB) $(SA_CFLAGS), \ + CXXFLAGS := $(CXXFLAGS_JDKLIB) $(SA_CFLAGS) $(SA_CXXFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB) $(SA_LDFLAGS), \ LIBS_linux := -lthread_db $(LIBDL), \ LIBS_solaris := -ldl -ldemangle -lthread -lproc, \ diff --git a/make/lib/Lib-jdk.internal.le.gmk b/make/lib/Lib-jdk.internal.le.gmk index 62f69bcadd3..0aa7bb273f5 100644 --- a/make/lib/Lib-jdk.internal.le.gmk +++ b/make/lib/Lib-jdk.internal.le.gmk @@ -29,19 +29,10 @@ include LibCommon.gmk ifeq ($(OPENJDK_TARGET_OS), windows) - LIBLE_SRC := $(TOPDIR)/src/jdk.internal.le/$(OPENJDK_TARGET_OS_TYPE)/native/lible \ - # - LIBLE_CPPFLAGS := \ - $(addprefix -I, $(LIBLE_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.internal.le \ - # - $(eval $(call SetupJdkLibrary, BUILD_LIBLE, \ NAME := le, \ - SRC := $(LIBLE_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(LIBJAVA_HEADER_FLAGS)\ - $(LIBLE_CPPFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB), \ LIBS := $(JDKLIB_LIBS) user32.lib, \ )) diff --git a/make/lib/Lib-jdk.jdi.gmk b/make/lib/Lib-jdk.jdi.gmk index ff0cd954b75..197b95c2e20 100644 --- a/make/lib/Lib-jdk.jdi.gmk +++ b/make/lib/Lib-jdk.jdi.gmk @@ -29,22 +29,13 @@ include LibCommon.gmk ifeq ($(OPENJDK_TARGET_OS), windows) - LIBDT_SHMEM_SRC := $(TOPDIR)/src/jdk.jdi/share/native/libdt_shmem \ - $(TOPDIR)/src/jdk.jdi/$(OPENJDK_TARGET_OS_TYPE)/native/libdt_shmem \ - # - LIBDT_SHMEM_CPPFLAGS := -I$(INCLUDEDIR) -I$(JDK_OUTPUTDIR)/include/$(OPENJDK_TARGET_OS) \ - $(addprefix -I, $(LIBDT_SHMEM_SRC)) \ - -I$(TOPDIR)/src/jdk.jdwp.agent/share/native/libjdwp/export \ - -I$(TOPDIR)/src/jdk.jdwp.agent/share/native/include \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.jdi \ - # - $(eval $(call SetupJdkLibrary, BUILD_LIBDT_SHMEM, \ NAME := dt_shmem, \ - SRC := $(LIBDT_SHMEM_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP \ - $(LIBDT_SHMEM_CPPFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP, \ + EXTRA_HEADER_DIRS := \ + jdk.jdwp.agent:include \ + jdk.jdwp.agent:libjdwp/export, \ LDFLAGS := $(LDFLAGS_JDKLIB), \ LIBS := $(JDKLIB_LIBS), \ )) diff --git a/make/lib/Lib-jdk.jdwp.agent.gmk b/make/lib/Lib-jdk.jdwp.agent.gmk index f0dc9f3d01c..0bc93e0d352 100644 --- a/make/lib/Lib-jdk.jdwp.agent.gmk +++ b/make/lib/Lib-jdk.jdwp.agent.gmk @@ -27,21 +27,14 @@ include LibCommon.gmk ################################################################################ -LIBDT_SOCKET_SRC := $(TOPDIR)/src/jdk.jdwp.agent/share/native/libdt_socket \ - $(TOPDIR)/src/jdk.jdwp.agent/$(OPENJDK_TARGET_OS_TYPE)/native/libdt_socket -LIBDT_SOCKET_CPPFLAGS := \ - $(addprefix -I, $(LIBDT_SOCKET_SRC)) \ - -I$(TOPDIR)/src/jdk.jdwp.agent/share/native/libjdwp/export \ - -I$(TOPDIR)/src/jdk.jdwp.agent/share/native/libjdwp \ - -I$(TOPDIR)/src/jdk.jdwp.agent/share/native/include \ - # - $(eval $(call SetupJdkLibrary, BUILD_LIBDT_SOCKET, \ NAME := dt_socket, \ - SRC := $(LIBDT_SOCKET_SRC), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP \ $(LIBDT_SOCKET_CPPFLAGS), \ + EXTRA_HEADER_DIRS := \ + include \ + libjdwp/export, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_linux := -lpthread, \ @@ -56,21 +49,14 @@ TARGETS += $(BUILD_LIBDT_SOCKET) ################################################################################ -LIBJDWP_SRC := $(TOPDIR)/src/jdk.jdwp.agent/share/native/libjdwp \ - $(TOPDIR)/src/jdk.jdwp.agent/$(OPENJDK_TARGET_OS_TYPE)/native/libjdwp -LIBJDWP_CPPFLAGS := \ - -I$(TOPDIR)/src/jdk.jdwp.agent/share/native/libjdwp/export \ - -I$(TOPDIR)/src/jdk.jdwp.agent/share/native/include \ - $(addprefix -I, $(LIBJDWP_SRC)) - # JDWP_LOGGING causes log messages to be compiled into the library. $(eval $(call SetupJdkLibrary, BUILD_LIBJDWP, \ NAME := jdwp, \ - SRC := $(LIBJDWP_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) -DJDWP_LOGGING \ - $(LIBJDWP_CPPFLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.jdwp.agent, \ + CFLAGS := $(CFLAGS_JDKLIB) -DJDWP_LOGGING, \ + EXTRA_HEADER_DIRS := \ + include \ + libjdwp/export, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := $(JDKLIB_LIBS), \ diff --git a/make/lib/Lib-jdk.management.agent.gmk b/make/lib/Lib-jdk.management.agent.gmk index 426e84d30d3..35bf7ea21c8 100644 --- a/make/lib/Lib-jdk.management.agent.gmk +++ b/make/lib/Lib-jdk.management.agent.gmk @@ -27,17 +27,10 @@ include LibCommon.gmk ################################################################################ -LIBMANAGEMENT_AGENT_SRC += $(TOPDIR)/src/jdk.management.agent/$(OPENJDK_TARGET_OS_TYPE)/native/libmanagement_agent -LIBMANAGEMENT_AGENT_CFLAGS := $(addprefix -I,$(LIBMANAGEMENT_AGENT_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.management.agent \ - $(LIBJAVA_HEADER_FLAGS) \ - # - $(eval $(call SetupJdkLibrary, BUILD_LIBMANAGEMENT_AGENT, \ NAME := management_agent, \ - SRC := $(LIBMANAGEMENT_AGENT_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(LIBMANAGEMENT_AGENT_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := $(JDKLIB_LIBS), \ diff --git a/make/lib/Lib-jdk.management.gmk b/make/lib/Lib-jdk.management.gmk index 22a167e23b5..29bfc7a5aa2 100644 --- a/make/lib/Lib-jdk.management.gmk +++ b/make/lib/Lib-jdk.management.gmk @@ -30,15 +30,6 @@ $(eval $(call IncludeCustomExtension, lib/Lib-jdk.management.gmk)) ################################################################################ -LIBMANAGEMENT_EXT_SRC += $(TOPDIR)/src/jdk.management/share/native/libmanagement_ext \ - $(TOPDIR)/src/jdk.management/$(OPENJDK_TARGET_OS_TYPE)/native/libmanagement_ext \ - $(TOPDIR)/src/jdk.management/$(OPENJDK_TARGET_OS)/native/libmanagement_ext -LIBMANAGEMENT_EXT_CFLAGS := -I$(TOPDIR)/src/java.management/share/native/include \ - $(addprefix -I,$(LIBMANAGEMENT_EXT_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.management \ - $(LIBJAVA_HEADER_FLAGS) \ - # - ifeq ($(OPENJDK_TARGET_OS), windows) # In (at least) VS2013 and later, -DPSAPI_VERSION=1 is needed to generate # a binary that is compatible with windows versions older than 7/2008R2. @@ -55,8 +46,6 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBMANAGEMENT_EXT, \ NAME := management_ext, \ - SRC := $(LIBMANAGEMENT_EXT_SRC), \ - LANG := C, \ OPTIMIZATION := $(LIBMANAGEMENT_EXT_OPTIMIZATION), \ CFLAGS := $(CFLAGS_JDKLIB) $(LIBMANAGEMENT_EXT_CFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ diff --git a/make/lib/Lib-jdk.net.gmk b/make/lib/Lib-jdk.net.gmk index 642d29809e0..b202c6373f7 100644 --- a/make/lib/Lib-jdk.net.gmk +++ b/make/lib/Lib-jdk.net.gmk @@ -31,9 +31,8 @@ ifneq ($(filter $(OPENJDK_TARGET_OS), solaris linux macosx), ) $(eval $(call SetupJdkLibrary, BUILD_LIBEXTNET, \ NAME := extnet, \ - SRC := $(TOPDIR)/src/jdk.net/$(OPENJDK_TARGET_OS)/native/libextnet, \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.net, \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := -ljava, \ diff --git a/make/lib/Lib-jdk.pack.gmk b/make/lib/Lib-jdk.pack.gmk index 9884818852c..f401e03e7c0 100644 --- a/make/lib/Lib-jdk.pack.gmk +++ b/make/lib/Lib-jdk.pack.gmk @@ -29,16 +29,13 @@ include LibCommon.gmk $(eval $(call SetupJdkLibrary, BUILD_LIBUNPACK, \ NAME := unpack, \ - SRC := $(TOPDIR)/src/jdk.pack/share/native/libunpack \ - $(TOPDIR)/src/jdk.pack/share/native/common-unpack, \ + EXTRA_SRC := common-unpack, \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ OPTIMIZATION := LOW, \ CFLAGS := $(CXXFLAGS_JDKLIB) \ - -DNO_ZLIB -DUNPACK_JNI -DFULL \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - -I$(TOPDIR)/src/jdk.pack/share/native/common-unpack \ - $(LIBJAVA_HEADER_FLAGS), \ + -DNO_ZLIB -DUNPACK_JNI -DFULL, \ CFLAGS_release := -DPRODUCT, \ + EXTRA_HEADER_DIRS := $(call GetJavaHeaderDir, java.base), \ DISABLED_WARNINGS_gcc := implicit-fallthrough, \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/make/lib/Lib-jdk.sctp.gmk b/make/lib/Lib-jdk.sctp.gmk index c1d2e468e86..2676102021e 100644 --- a/make/lib/Lib-jdk.sctp.gmk +++ b/make/lib/Lib-jdk.sctp.gmk @@ -29,18 +29,15 @@ include LibCommon.gmk ifeq ($(OPENJDK_TARGET_OS_TYPE), unix) - ifeq (, $(filter $(OPENJDK_TARGET_OS), macosx aix)) + ifeq ($(filter $(OPENJDK_TARGET_OS), macosx aix), ) $(eval $(call SetupJdkLibrary, BUILD_LIBSCTP, \ NAME := sctp, \ - SRC := $(TOPDIR)/src/jdk.sctp/$(OPENJDK_TARGET_OS_TYPE)/native/libsctp, \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - -I $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libnio/ch \ - -I $(TOPDIR)/src/java.base/share/native/libnio/ch \ - $(addprefix -I, $(call FindSrcDirsForLib, java.base, net)) \ - $(LIBJAVA_HEADER_FLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.sctp \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base, \ + CFLAGS := $(CFLAGS_JDKLIB), \ + EXTRA_HEADER_DIRS := \ + $(call GetJavaHeaderDir, java.base) \ + java.base:libnet \ + java.base:libnio/ch, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_unix := -lnio -lnet -ljava -ljvm, \ diff --git a/make/lib/Lib-jdk.security.auth.gmk b/make/lib/Lib-jdk.security.auth.gmk index de3332f1522..12c26ca3758 100644 --- a/make/lib/Lib-jdk.security.auth.gmk +++ b/make/lib/Lib-jdk.security.auth.gmk @@ -29,9 +29,8 @@ include LibCommon.gmk $(eval $(call SetupJdkLibrary, BUILD_LIBJAAS, \ NAME := jaas, \ - SRC := $(call FindSrcDirsForLib, jdk.security.auth, jaas), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.security.auth, \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_windows := netapi32.lib user32.lib mpr.lib advapi32.lib $(JDKLIB_LIBS), \ diff --git a/make/lib/LibCommon.gmk b/make/lib/LibCommon.gmk index 57993303829..7e25925c7d1 100644 --- a/make/lib/LibCommon.gmk +++ b/make/lib/LibCommon.gmk @@ -25,9 +25,6 @@ include JdkNativeCompilation.gmk -# Hook to include the corresponding custom file, if present. -$(eval $(call IncludeCustomExtension, lib/LibCommon.gmk)) - ################################################################################ GLOBAL_VERSION_INFO_RESOURCE := $(TOPDIR)/src/java.base/windows/native/common/version.rc @@ -66,16 +63,6 @@ else ifeq ($(TOOLCHAIN_TYPE), xlc) endif endif -################################################################################ -# Find the default set of src dirs for a native library. -# Param 1 - module name -# Param 2 - library name -FindSrcDirsForLib += \ - $(call uniq, $(wildcard \ - $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS)/native/lib$(strip $2) \ - $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS_TYPE)/native/lib$(strip $2) \ - $(TOPDIR)/src/$(strip $1)/share/native/lib$(strip $2))) - ################################################################################ # Find a library # Param 1 - module name @@ -94,10 +81,6 @@ FindStaticLib = \ $(addprefix $(SUPPORT_OUTPUTDIR)/native/, \ $(strip $1)$(strip $3)/$(LIBRARY_PREFIX)$(strip $2)$(STATIC_LIBRARY_SUFFIX)) -################################################################################ -# Define the header include flags needed to compile against it. -LIBJAVA_HEADER_FLAGS := $(addprefix -I, $(call FindSrcDirsForLib, java.base, java)) - # Put the libraries here. INSTALL_LIBRARIES_HERE := $(call FindLibDirForModule, $(MODULE)) diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 96ef3f9763f..08ebdf4ac87 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -37,6 +37,7 @@ #include "compiler/disassembler.hpp" #include "memory/resourceArea.hpp" #include "nativeInst_aarch64.hpp" +#include "oops/accessDecorators.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/klass.inline.hpp" #include "oops/oop.hpp" @@ -2127,7 +2128,7 @@ void MacroAssembler::resolve_jobject(Register value, Register thread, Register t bind(not_weak); // Resolve (untagged) jobject. - bs->load_at(this, IN_ROOT | IN_CONCURRENT_ROOT, T_OBJECT, + bs->load_at(this, IN_CONCURRENT_ROOT, T_OBJECT, value, Address(value, 0), tmp, thread); verify_oop(value); bind(done); @@ -3664,7 +3665,7 @@ void MacroAssembler::load_klass(Register dst, Register src) { void MacroAssembler::resolve_oop_handle(Register result, Register tmp) { // OopHandle::resolve is an indirection. BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); - bs->load_at(this, IN_ROOT | IN_CONCURRENT_ROOT, T_OBJECT, + bs->load_at(this, IN_CONCURRENT_ROOT, T_OBJECT, result, Address(result, 0), tmp, rthread); } @@ -3983,6 +3984,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src, Register tmp1, Register thread_tmp) { BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, thread_tmp); @@ -3995,6 +3997,7 @@ void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register src, Register tmp1, Register thread_tmp) { BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, dst, src, tmp1, thread_tmp); diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp index 1e6e9d32e61..39fa305f5d2 100644 --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp @@ -813,7 +813,7 @@ void TemplateTable::aaload() do_oop_load(_masm, Address(r1, arrayOopDesc::base_offset_in_bytes(T_OBJECT)), r0, - IN_HEAP | IN_HEAP_ARRAY); + IN_HEAP_ARRAY); } void TemplateTable::baload() @@ -1141,7 +1141,7 @@ void TemplateTable::aastore() { // Get the value we will store __ ldr(r0, at_tos()); // Now store using the appropriate barrier - do_oop_store(_masm, element_address, r0, IN_HEAP | IN_HEAP_ARRAY); + do_oop_store(_masm, element_address, r0, IN_HEAP_ARRAY); __ b(done); // Have a NULL in r0, r3=array, r2=index. Store NULL at ary[idx] @@ -1149,7 +1149,7 @@ void TemplateTable::aastore() { __ profile_null_seen(r2); // Store a NULL - do_oop_store(_masm, element_address, noreg, IN_HEAP | IN_HEAP_ARRAY); + do_oop_store(_masm, element_address, noreg, IN_HEAP_ARRAY); // Pop stack arguments __ bind(done); diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.cpp b/src/hotspot/cpu/arm/macroAssembler_arm.cpp index 1bca5dc5134..96e84000d0b 100644 --- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp @@ -36,6 +36,7 @@ #include "gc/shared/collectedHeap.inline.hpp" #include "interpreter/interpreter.hpp" #include "memory/resourceArea.hpp" +#include "oops/accessDecorators.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" #include "runtime/biasedLocking.hpp" @@ -2133,7 +2134,7 @@ void MacroAssembler::resolve_jobject(Register value, b(done); bind(not_weak); // Resolve (untagged) jobject. - access_load_at(T_OBJECT, IN_ROOT | IN_CONCURRENT_ROOT, + access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, Address(value, 0), value, tmp1, tmp2, noreg); verify_oop(value); bind(done); @@ -2700,6 +2701,7 @@ void MacroAssembler::store_heap_oop_null(Address obj, Register new_val, Register void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Address src, Register dst, Register tmp1, Register tmp2, Register tmp3) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, tmp2, tmp3); @@ -2711,6 +2713,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address obj, Register new_val, Register tmp1, Register tmp2, Register tmp3, bool is_null) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, obj, new_val, tmp1, tmp2, tmp3, is_null); diff --git a/src/hotspot/cpu/ppc/assembler_ppc.cpp b/src/hotspot/cpu/ppc/assembler_ppc.cpp index 17cc095b08b..b646371b6d6 100644 --- a/src/hotspot/cpu/ppc/assembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/assembler_ppc.cpp @@ -486,7 +486,7 @@ int Assembler::add_const_optimized(Register d, Register s, long x, Register tmp, // Case 2: Can use addis. if (xd == 0) { short xc = rem & 0xFFFF; // 2nd 16-bit chunk. - rem = (rem >> 16) + ((unsigned short)xd >> 15); + rem = (rem >> 16) + ((unsigned short)xc >> 15); if (rem == 0) { addis(d, s, xc); return 0; diff --git a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp index fba326a74f4..e6b163e46be 100644 --- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp @@ -214,11 +214,9 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Decorato assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code"); // Does store cross heap regions? - if (G1RSBarrierRegionFilter) { - __ xorr(tmp1, store_addr, new_val); - __ srdi_(tmp1, tmp1, HeapRegion::LogOfHRGrainBytes); - __ beq(CCR0, filtered); - } + __ xorr(tmp1, store_addr, new_val); + __ srdi_(tmp1, tmp1, HeapRegion::LogOfHRGrainBytes); + __ beq(CCR0, filtered); // Crosses regions, storing NULL? if (not_null) { diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp index 10a006cabc4..8466ebb958b 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp @@ -32,6 +32,7 @@ #include "code/codeCache.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" +#include "oops/accessDecorators.hpp" #include "runtime/safepointMechanism.hpp" inline bool MacroAssembler::is_ld_largeoffset(address a) { @@ -332,6 +333,7 @@ inline void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorat ON_UNKNOWN_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); bool as_raw = (decorators & AS_RAW) != 0; + decorators = AccessInternal::decorator_fixup(decorators); if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, base, ind_or_offs, val, @@ -349,6 +351,7 @@ inline void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorato assert((decorators & ~(AS_RAW | IN_HEAP | IN_HEAP_ARRAY | IN_ROOT | OOP_NOT_NULL | ON_PHANTOM_OOP_REF | ON_WEAK_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, diff --git a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp index d22b0d50f94..4b15fb04e0c 100644 --- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp @@ -688,7 +688,7 @@ void TemplateTable::aaload() { Rtemp2 = R31; __ index_check(Rarray, R17_tos /* index */, UseCompressedOops ? 2 : LogBytesPerWord, Rtemp, Rload_addr); do_oop_load(_masm, Rload_addr, arrayOopDesc::base_offset_in_bytes(T_OBJECT), R17_tos, Rtemp, Rtemp2, - IN_HEAP | IN_HEAP_ARRAY); + IN_HEAP_ARRAY); __ verify_oop(R17_tos); //__ dcbt(R17_tos); // prefetch } @@ -1015,14 +1015,14 @@ void TemplateTable::aastore() { __ bind(Lis_null); do_oop_store(_masm, Rstore_addr, arrayOopDesc::base_offset_in_bytes(T_OBJECT), noreg /* 0 */, - Rscratch, Rscratch2, Rscratch3, IN_HEAP | IN_HEAP_ARRAY); + Rscratch, Rscratch2, Rscratch3, IN_HEAP_ARRAY); __ profile_null_seen(Rscratch, Rscratch2); __ b(Ldone); // Store is OK. __ bind(Lstore_ok); do_oop_store(_masm, Rstore_addr, arrayOopDesc::base_offset_in_bytes(T_OBJECT), R17_tos /* value */, - Rscratch, Rscratch2, Rscratch3, IN_HEAP | IN_HEAP_ARRAY | OOP_NOT_NULL); + Rscratch, Rscratch2, Rscratch3, IN_HEAP_ARRAY | OOP_NOT_NULL); __ bind(Ldone); // Adjust sp (pops array, index and value). diff --git a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp index fe7dd910225..c039838953b 100644 --- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp @@ -273,16 +273,14 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Decorato // Does store cross heap regions? // It does if the two addresses specify different grain addresses. - if (G1RSBarrierRegionFilter) { - if (VM_Version::has_DistinctOpnds()) { - __ z_xgrk(Rtmp1, Rstore_addr, Rnew_val); - } else { - __ z_lgr(Rtmp1, Rstore_addr); - __ z_xgr(Rtmp1, Rnew_val); - } - __ z_srag(Rtmp1, Rtmp1, HeapRegion::LogOfHRGrainBytes); - __ z_bre(filtered); + if (VM_Version::has_DistinctOpnds()) { + __ z_xgrk(Rtmp1, Rstore_addr, Rnew_val); + } else { + __ z_lgr(Rtmp1, Rstore_addr); + __ z_xgr(Rtmp1, Rnew_val); } + __ z_srag(Rtmp1, Rtmp1, HeapRegion::LogOfHRGrainBytes); + __ z_bre(filtered); // Crosses regions, storing NULL? if (not_null) { diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index 6186428d533..f76720156ae 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -34,6 +34,7 @@ #include "gc/shared/cardTableBarrierSet.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" +#include "oops/accessDecorators.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/klass.inline.hpp" #include "opto/compile.hpp" @@ -4053,6 +4054,7 @@ void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, assert((decorators & ~(AS_RAW | IN_HEAP | IN_HEAP_ARRAY | IN_ROOT | OOP_NOT_NULL | ON_UNKNOWN_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, @@ -4071,6 +4073,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, assert((decorators & ~(AS_RAW | IN_HEAP | IN_HEAP_ARRAY | IN_ROOT | OOP_NOT_NULL | ON_PHANTOM_OOP_REF | ON_WEAK_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, diff --git a/src/hotspot/cpu/s390/templateTable_s390.cpp b/src/hotspot/cpu/s390/templateTable_s390.cpp index ac8a06c73b5..994e2e36e1f 100644 --- a/src/hotspot/cpu/s390/templateTable_s390.cpp +++ b/src/hotspot/cpu/s390/templateTable_s390.cpp @@ -853,7 +853,7 @@ void TemplateTable::aaload() { index_check(Z_tmp_1, index, shift); // Now load array element. do_oop_load(_masm, Address(Z_tmp_1, index, arrayOopDesc::base_offset_in_bytes(T_OBJECT)), Z_tos, - Z_tmp_2, Z_tmp_3, IN_HEAP | IN_HEAP_ARRAY); + Z_tmp_2, Z_tmp_3, IN_HEAP_ARRAY); __ verify_oop(Z_tos); } @@ -1197,7 +1197,7 @@ void TemplateTable::aastore() { // Store a NULL. do_oop_store(_masm, Address(Rstore_addr, (intptr_t)0), noreg, - tmp3, tmp2, tmp1, IN_HEAP | IN_HEAP_ARRAY); + tmp3, tmp2, tmp1, IN_HEAP_ARRAY); __ z_bru(done); // Come here on success. @@ -1205,7 +1205,7 @@ void TemplateTable::aastore() { // Now store using the appropriate barrier. do_oop_store(_masm, Address(Rstore_addr, (intptr_t)0), Rvalue, - tmp3, tmp2, tmp1, IN_HEAP | IN_HEAP_ARRAY | OOP_NOT_NULL); + tmp3, tmp2, tmp1, IN_HEAP_ARRAY | OOP_NOT_NULL); // Pop stack arguments. __ bind(done); diff --git a/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp index 82d30d69cb4..90bc2b6d801 100644 --- a/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp +++ b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp @@ -369,12 +369,10 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Register G1BarrierSet* bs = barrier_set_cast(BarrierSet::barrier_set()); - if (G1RSBarrierRegionFilter) { - __ xor3(store_addr, new_val, tmp); - __ srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp); + __ xor3(store_addr, new_val, tmp); + __ srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp); - __ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); - } + __ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); // If the "store_addr" register is an "in" or "local" register, move it to // a scratch reg so we can pass it as an argument. diff --git a/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp b/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp index cddb000724a..17a28f36259 100644 --- a/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp +++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp @@ -32,6 +32,7 @@ #include "interpreter/interpreter.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" +#include "oops/accessDecorators.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" #include "runtime/biasedLocking.hpp" @@ -181,7 +182,7 @@ void MacroAssembler::resolve_jobject(Register value, Register tmp) { br (Assembler::always, true, Assembler::pt, done); delayed()->nop(); bind(not_weak); - access_load_at(T_OBJECT, IN_ROOT | IN_CONCURRENT_ROOT, + access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, Address(value, 0), value, tmp); verify_oop(value); bind(done); @@ -3401,7 +3402,7 @@ void MacroAssembler::reserved_stack_check() { // ((OopHandle)result).resolve(); void MacroAssembler::resolve_oop_handle(Register result, Register tmp) { // OopHandle::resolve is an indirection. - access_load_at(T_OBJECT, IN_ROOT | IN_CONCURRENT_ROOT, + access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, Address(result, 0), result, tmp); } @@ -3446,6 +3447,7 @@ void MacroAssembler::store_klass_gap(Register s, Register d) { void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Register src, Address dst, Register tmp) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, src, dst, tmp); @@ -3457,6 +3459,7 @@ void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Address src, Register dst, Register tmp) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, src, dst, tmp); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 7830873de17..df90ffbfbe8 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -33,7 +33,7 @@ #include "interpreter/interpreter.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" -#include "oops/access.hpp" +#include "oops/accessDecorators.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" #include "runtime/biasedLocking.hpp" @@ -5259,7 +5259,7 @@ void MacroAssembler::resolve_jobject(Register value, jmp(done); bind(not_weak); // Resolve (untagged) jobject. - access_load_at(T_OBJECT, IN_ROOT | IN_CONCURRENT_ROOT, + access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, value, Address(value, 0), tmp, thread); verify_oop(value); bind(done); @@ -6281,7 +6281,7 @@ void MacroAssembler::resolve_oop_handle(Register result, Register tmp) { // Only 64 bit platforms support GCs that require a tmp register // Only IN_HEAP loads require a thread_tmp register // OopHandle::resolve is an indirection like jobject. - access_load_at(T_OBJECT, IN_ROOT | IN_CONCURRENT_ROOT, + access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, result, Address(result, 0), tmp, /*tmp_thread*/noreg); } @@ -6323,6 +6323,7 @@ void MacroAssembler::store_klass(Register dst, Register src) { void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src, Register tmp1, Register thread_tmp) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, thread_tmp); @@ -6334,6 +6335,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Reg void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register src, Register tmp1, Register tmp2) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, dst, src, tmp1, tmp2); diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index ea0f16ac18c..e576342b613 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -11607,16 +11607,6 @@ instruct testUL_reg(rFlagsRegU cr, rRegL src, immL0 zero) ins_pipe(ialu_cr_reg_imm); %} -instruct compUB_mem_imm(rFlagsReg cr, memory mem, immU8 imm) -%{ - match(Set cr (CmpI (LoadUB mem) imm)); - - ins_cost(125); - format %{ "cmpb $mem, $imm" %} - ins_encode %{ __ cmpb($mem$$Address, $imm$$constant); %} - ins_pipe(ialu_cr_reg_mem); -%} - instruct compB_mem_imm(rFlagsReg cr, memory mem, immI8 imm) %{ match(Set cr (CmpI (LoadB mem) imm)); @@ -11627,16 +11617,6 @@ instruct compB_mem_imm(rFlagsReg cr, memory mem, immI8 imm) ins_pipe(ialu_cr_reg_mem); %} -instruct testUB_mem_imm(rFlagsReg cr, memory mem, immU8 imm, immI0 zero) -%{ - match(Set cr (CmpI (AndI (LoadUB mem) imm) zero)); - - ins_cost(125); - format %{ "testb $mem, $imm" %} - ins_encode %{ __ testb($mem$$Address, $imm$$constant); %} - ins_pipe(ialu_cr_reg_mem); -%} - instruct testB_mem_imm(rFlagsReg cr, memory mem, immI8 imm, immI0 zero) %{ match(Set cr (CmpI (AndI (LoadB mem) imm) zero)); diff --git a/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp b/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp new file mode 100644 index 00000000000..4a5fc402d1a --- /dev/null +++ b/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018 SAP SE. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" + +#include "classfile/classLoaderData.inline.hpp" +#include "classfile/classLoaderHierarchyDCmd.hpp" +#include "memory/allocation.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/safepoint.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" + + +ClassLoaderHierarchyDCmd::ClassLoaderHierarchyDCmd(outputStream* output, bool heap) + : DCmdWithParser(output, heap) + , _show_classes("show-classes", "Print loaded classes.", "BOOLEAN", false, "false") + , _verbose("verbose", "Print detailed information.", "BOOLEAN", false, "false") { + _dcmdparser.add_dcmd_option(&_show_classes); + _dcmdparser.add_dcmd_option(&_verbose); +} + + +int ClassLoaderHierarchyDCmd::num_arguments() { + ResourceMark rm; + ClassLoaderHierarchyDCmd* dcmd = new ClassLoaderHierarchyDCmd(NULL, false); + if (dcmd != NULL) { + DCmdMark mark(dcmd); + return dcmd->_dcmdparser.num_arguments(); + } else { + return 0; + } +} + +// Helper class for drawing the branches to the left of a node. +class BranchTracker : public StackObj { + // "" + // " |---" + // " | | + // " | " + // " | |--- + // " | |--- + // ^^^^^^^ ^^^ + // A B + + // Some terms for the graphics: + // - branch: vertical connection between a node's ancestor to a later sibling. + // - branchwork: (A) the string to print as a prefix at the start of each line, contains all branches. + // - twig (B): Length of the dashed line connecting a node to its branch. + // - branch spacing: how many spaces between branches are printed. + +public: + + enum { max_depth = 64, twig_len = 2, branch_spacing = 5 }; + +private: + + char _branches[max_depth]; + int _pos; + +public: + BranchTracker() + : _pos(0) {} + + void push(bool has_branch) { + if (_pos < max_depth) { + _branches[_pos] = has_branch ? '|' : ' '; + } + _pos ++; // beyond max depth, omit branch drawing but do count on. + } + + void pop() { + assert(_pos > 0, "must be"); + _pos --; + } + + void print(outputStream* st) { + for (int i = 0; i < _pos; i ++) { + st->print("%c%.*s", _branches[i], branch_spacing, " "); + } + } + + class Mark { + BranchTracker& _tr; + public: + Mark(BranchTracker& tr, bool has_branch_here) + : _tr(tr) { _tr.push(has_branch_here); } + ~Mark() { _tr.pop(); } + }; + +}; // end: BranchTracker + +struct LoadedClassInfo : public ResourceObj { +public: + LoadedClassInfo* _next; + Klass* const _klass; + const ClassLoaderData* const _cld; + + LoadedClassInfo(Klass* klass, const ClassLoaderData* cld) + : _klass(klass), _cld(cld) {} + +}; + +class LoaderTreeNode : public ResourceObj { + + // We walk the CLDG and, for each CLD which is non-anonymous, add + // a tree node. To add a node we need its parent node; if it itself + // does not exist yet, we add a preliminary node for it. This preliminary + // node just contains its loader oop; later, when encountering its CLD in + // our CLDG walk, we complete the missing information in this node. + + const oop _loader_oop; + const ClassLoaderData* _cld; + + LoaderTreeNode* _child; + LoaderTreeNode* _next; + + LoadedClassInfo* _classes; + int _num_classes; + + LoadedClassInfo* _anon_classes; + int _num_anon_classes; + + void print_with_childs(outputStream* st, BranchTracker& branchtracker, + bool print_classes, bool verbose) const { + + ResourceMark rm; + + if (_cld == NULL) { + // Not sure how this could happen: we added a preliminary node for a parent but then never encountered + // its CLD? + return; + } + + // Retrieve information. + const Klass* const loader_klass = _cld->class_loader_klass(); + const Symbol* const loader_name = _cld->class_loader_name(); + + branchtracker.print(st); + + // e.g. "+--- jdk.internal.reflect.DelegatingClassLoader" + st->print("+%.*s", BranchTracker::twig_len, "----------"); + if (_cld->is_the_null_class_loader_data()) { + st->print(" "); + } else { + if (loader_name != NULL) { + st->print(" \"%s\",", loader_name->as_C_string()); + } + st->print(" %s", loader_klass != NULL ? loader_klass->external_name() : "??"); + st->print(" {" PTR_FORMAT "}", p2i(_loader_oop)); + } + st->cr(); + + // Output following this node (node details and child nodes) - up to the next sibling node + // needs to be prefixed with "|" if there is a follow up sibling. + const bool have_sibling = _next != NULL; + BranchTracker::Mark trm(branchtracker, have_sibling); + + { + // optional node details following this node needs to be prefixed with "|" + // if there are follow up child nodes. + const bool have_child = _child != NULL; + BranchTracker::Mark trm(branchtracker, have_child); + + // Empty line + branchtracker.print(st); + st->cr(); + + const int indentation = 18; + + if (verbose) { + branchtracker.print(st); + st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Data:", p2i(_cld)); + branchtracker.print(st); + st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Klass:", p2i(loader_klass)); + + // Empty line + branchtracker.print(st); + st->cr(); + } + + if (print_classes) { + + if (_classes != NULL) { + for (LoadedClassInfo* lci = _classes; lci; lci = lci->_next) { + branchtracker.print(st); + if (lci == _classes) { // first iteration + st->print("%*s ", indentation, "Classes:"); + } else { + st->print("%*s ", indentation, ""); + } + st->print("%s", lci->_klass->external_name()); + st->cr(); + // Non-anonymous classes should live in the primary CLD of its loader + assert(lci->_cld == _cld, "must be"); + } + branchtracker.print(st); + st->print("%*s ", indentation, ""); + st->print_cr("(%u class%s)", _num_classes, (_num_classes == 1) ? "" : "es"); + + // Empty line + branchtracker.print(st); + st->cr(); + } + + if (_anon_classes != NULL) { + for (LoadedClassInfo* lci = _anon_classes; lci; lci = lci->_next) { + branchtracker.print(st); + if (lci == _anon_classes) { // first iteration + st->print("%*s ", indentation, "Anonymous Classes:"); + } else { + st->print("%*s ", indentation, ""); + } + st->print("%s", lci->_klass->external_name()); + // For anonymous classes, also print CLD if verbose. Should be a different one than the primary CLD. + assert(lci->_cld != _cld, "must be"); + if (verbose) { + st->print(" (CLD: " PTR_FORMAT ")", p2i(lci->_cld)); + } + st->cr(); + } + branchtracker.print(st); + st->print("%*s ", indentation, ""); + st->print_cr("(%u anonymous class%s)", _num_anon_classes, (_num_anon_classes == 1) ? "" : "es"); + + // Empty line + branchtracker.print(st); + st->cr(); + } + + } // end: print_classes + + } // Pop branchtracker mark + + // Print children, recursively + LoaderTreeNode* c = _child; + while (c != NULL) { + c->print_with_childs(st, branchtracker, print_classes, verbose); + c = c->_next; + } + + } + +public: + + LoaderTreeNode(const oop loader_oop) + : _loader_oop(loader_oop), _cld(NULL) + , _child(NULL), _next(NULL) + , _classes(NULL), _anon_classes(NULL) + , _num_classes(0), _num_anon_classes(0) {} + + void set_cld(const ClassLoaderData* cld) { + _cld = cld; + } + + void add_child(LoaderTreeNode* info) { + info->_next = _child; + _child = info; + } + + void add_sibling(LoaderTreeNode* info) { + assert(info->_next == NULL, "must be"); + info->_next = _next; + _next = info; + } + + void add_classes(LoadedClassInfo* first_class, int num_classes, bool anonymous) { + LoadedClassInfo** p_list_to_add_to = anonymous ? &_anon_classes : &_classes; + // Search tail. + while ((*p_list_to_add_to) != NULL) { + p_list_to_add_to = &(*p_list_to_add_to)->_next; + } + *p_list_to_add_to = first_class; + if (anonymous) { + _num_anon_classes += num_classes; + } else { + _num_classes += num_classes; + } + } + + const ClassLoaderData* cld() const { + return _cld; + } + + const oop loader_oop() const { + return _loader_oop; + } + + LoaderTreeNode* find(const oop loader_oop) { + LoaderTreeNode* result = NULL; + if (_loader_oop == loader_oop) { + result = this; + } else { + LoaderTreeNode* c = _child; + while (c != NULL && result == NULL) { + result = c->find(loader_oop); + c = c->_next; + } + } + return result; + } + + void print_with_childs(outputStream* st, bool print_classes, bool print_add_info) const { + BranchTracker bwt; + print_with_childs(st, bwt, print_classes, print_add_info); + } + +}; + +class LoadedClassCollectClosure : public KlassClosure { +public: + LoadedClassInfo* _list; + const ClassLoaderData* _cld; + int _num_classes; + LoadedClassCollectClosure(const ClassLoaderData* cld) + : _list(NULL), _cld(cld), _num_classes(0) {} + void do_klass(Klass* k) { + LoadedClassInfo* lki = new LoadedClassInfo(k, _cld); + lki->_next = _list; + _list = lki; + _num_classes ++; + } +}; + +class LoaderInfoScanClosure : public CLDClosure { + + const bool _print_classes; + const bool _verbose; + LoaderTreeNode* _root; + + static void fill_in_classes(LoaderTreeNode* info, const ClassLoaderData* cld) { + assert(info != NULL && cld != NULL, "must be"); + LoadedClassCollectClosure lccc(cld); + const_cast(cld)->classes_do(&lccc); + if (lccc._num_classes > 0) { + info->add_classes(lccc._list, lccc._num_classes, cld->is_anonymous()); + } + } + + LoaderTreeNode* find_node_or_add_empty_node(oop loader_oop) { + + assert(_root != NULL, "root node must exist"); + + if (loader_oop == NULL) { + return _root; + } + + // Check if a node for this oop already exists. + LoaderTreeNode* info = _root->find(loader_oop); + + if (info == NULL) { + // It does not. Create a node. + info = new LoaderTreeNode(loader_oop); + + // Add it to tree. + LoaderTreeNode* parent_info = NULL; + + // Recursively add parent nodes if needed. + const oop parent_oop = java_lang_ClassLoader::parent(loader_oop); + if (parent_oop == NULL) { + parent_info = _root; + } else { + parent_info = find_node_or_add_empty_node(parent_oop); + } + assert(parent_info != NULL, "must be"); + + parent_info->add_child(info); + } + return info; + } + + +public: + LoaderInfoScanClosure(bool print_classes, bool verbose) + : _print_classes(print_classes), _verbose(verbose), _root(NULL) { + _root = new LoaderTreeNode(NULL); + } + + void print_results(outputStream* st) const { + _root->print_with_childs(st, _print_classes, _verbose); + } + + void do_cld (ClassLoaderData* cld) { + + // We do not display unloading loaders, for now. + if (cld->is_unloading()) { + return; + } + + const oop loader_oop = cld->class_loader(); + + LoaderTreeNode* info = find_node_or_add_empty_node(loader_oop); + assert(info != NULL, "must be"); + + // Update CLD in node, but only if this is the primary CLD for this loader. + if (cld->is_anonymous() == false) { + assert(info->cld() == NULL, "there should be only one primary CLD per loader"); + info->set_cld(cld); + } + + // Add classes. + fill_in_classes(info, cld); + } + +}; + + +class ClassLoaderHierarchyVMOperation : public VM_Operation { + outputStream* const _out; + const bool _show_classes; + const bool _verbose; +public: + ClassLoaderHierarchyVMOperation(outputStream* out, bool show_classes, bool verbose) : + _out(out), _show_classes(show_classes), _verbose(verbose) + {} + + VMOp_Type type() const { + return VMOp_ClassLoaderHierarchyOperation; + } + + void doit() { + assert(SafepointSynchronize::is_at_safepoint(), "must be a safepoint"); + ResourceMark rm; + LoaderInfoScanClosure cl (_show_classes, _verbose); + ClassLoaderDataGraph::cld_do(&cl); + cl.print_results(_out); + } +}; + +// This command needs to be executed at a safepoint. +void ClassLoaderHierarchyDCmd::execute(DCmdSource source, TRAPS) { + ClassLoaderHierarchyVMOperation op(output(), _show_classes.value(), _verbose.value()); + VMThread::execute(&op); +} diff --git a/src/hotspot/share/classfile/classLoaderHierarchyDCmd.hpp b/src/hotspot/share/classfile/classLoaderHierarchyDCmd.hpp new file mode 100644 index 00000000000..0db0eccf4dc --- /dev/null +++ b/src/hotspot/share/classfile/classLoaderHierarchyDCmd.hpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018 SAP SE. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 HOTSPOT_SHARE_CLASSFILE_CLASSLOADERHIERARCHYDCMD_HPP_ +#define HOTSPOT_SHARE_CLASSFILE_CLASSLOADERHIERARCHYDCMD_HPP_ + +#include "services/diagnosticCommand.hpp" + +class ClassLoaderHierarchyDCmd: public DCmdWithParser { + DCmdArgument _show_classes; + DCmdArgument _verbose; +public: + + ClassLoaderHierarchyDCmd(outputStream* output, bool heap); + + static const char* name() { + return "VM.classloaders"; + } + + static const char* description() { + return "Prints classloader hierarchy."; + } + static const char* impact() { + return "Medium: Depends on number of class loaders and classes loaded."; + } + static const JavaPermission permission() { + JavaPermission p = {"java.lang.management.ManagementPermission", + "monitor", NULL}; + return p; + } + static int num_arguments(); + virtual void execute(DCmdSource source, TRAPS); + +}; + +#endif /* HOTSPOT_SHARE_CLASSFILE_CLASSLOADERHIERARCHYDCMD_HPP_ */ diff --git a/src/hotspot/share/classfile/stringTable.cpp b/src/hotspot/share/classfile/stringTable.cpp index 96e3f858563..fc696792e7d 100644 --- a/src/hotspot/share/classfile/stringTable.cpp +++ b/src/hotspot/share/classfile/stringTable.cpp @@ -29,7 +29,10 @@ #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" #include "gc/shared/collectedHeap.hpp" +#include "gc/shared/oopStorage.inline.hpp" +#include "gc/shared/oopStorageParState.inline.hpp" #include "logging/log.hpp" +#include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "memory/metaspaceShared.hpp" @@ -38,171 +41,196 @@ #include "oops/access.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayOop.inline.hpp" +#include "oops/weakHandle.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/handles.inline.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/safepointVerifiers.hpp" +#include "runtime/timerTrace.hpp" +#include "runtime/interfaceSupport.inline.hpp" #include "services/diagnosticCommand.hpp" -#include "utilities/hashtable.inline.hpp" +#include "utilities/concurrentHashTable.inline.hpp" +#include "utilities/concurrentHashTableTasks.inline.hpp" #include "utilities/macros.hpp" -// the number of buckets a thread claims -const int ClaimChunkSize = 32; - -#ifdef ASSERT -class StableMemoryChecker : public StackObj { - enum { _bufsize = wordSize*4 }; - - address _region; - jint _size; - u1 _save_buf[_bufsize]; - - int sample(u1* save_buf) { - if (_size <= _bufsize) { - memcpy(save_buf, _region, _size); - return _size; - } else { - // copy head and tail - memcpy(&save_buf[0], _region, _bufsize/2); - memcpy(&save_buf[_bufsize/2], _region + _size - _bufsize/2, _bufsize/2); - return (_bufsize/2)*2; - } - } - - public: - StableMemoryChecker(const void* region, jint size) { - _region = (address) region; - _size = size; - sample(_save_buf); - } - - bool verify() { - u1 check_buf[sizeof(_save_buf)]; - int check_size = sample(check_buf); - return (0 == memcmp(_save_buf, check_buf, check_size)); - } - - void set_region(const void* region) { _region = (address) region; } -}; -#endif - +// We prefer short chains of avg 2 +#define PREF_AVG_LIST_LEN 2 +// 2^24 is max size +#define END_SIZE 24 +// If a chain gets to 32 something might be wrong +#define REHASH_LEN 32 +// If we have as many dead items as 50% of the number of bucket +#define CLEAN_DEAD_HIGH_WATER_MARK 0.5 // -------------------------------------------------------------------------- StringTable* StringTable::_the_table = NULL; bool StringTable::_shared_string_mapped = false; -bool StringTable::_needs_rehashing = false; - -volatile int StringTable::_parallel_claimed_idx = 0; - CompactHashtable StringTable::_shared_table; +bool StringTable::_alt_hash = false; -// Pick hashing algorithm -unsigned int StringTable::hash_string(const jchar* s, int len) { - return use_alternate_hashcode() ? alt_hash_string(s, len) : - java_lang_String::hash_code(s, len); +static juint murmur_seed = 0; + +uintx hash_string(const jchar* s, int len, bool useAlt) { + return useAlt ? + AltHashing::murmur3_32(murmur_seed, s, len) : + java_lang_String::hash_code(s, len); } -unsigned int StringTable::alt_hash_string(const jchar* s, int len) { - return AltHashing::murmur3_32(seed(), s, len); -} - -unsigned int StringTable::hash_string(oop string) { - EXCEPTION_MARK; - if (string == NULL) { - return hash_string((jchar*)NULL, 0); - } - ResourceMark rm(THREAD); - // All String oops are hashed as unicode - int length; - jchar* chars = java_lang_String::as_unicode_string(string, length, THREAD); - if (chars != NULL) { - return hash_string(chars, length); - } else { - vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "unable to create Unicode string for verification"); +class StringTableConfig : public StringTableHash::BaseConfig { + private: + public: + static uintx get_hash(WeakHandle const& value, + bool* is_dead) { + EXCEPTION_MARK; + oop val_oop = value.peek(); + if (val_oop == NULL) { + *is_dead = true; + return 0; + } + *is_dead = false; + ResourceMark rm(THREAD); + // All String oops are hashed as unicode + int length; + jchar* chars = java_lang_String::as_unicode_string(val_oop, length, THREAD); + if (chars != NULL) { + return hash_string(chars, length, StringTable::_alt_hash); + } + vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "get hash from oop"); return 0; } -} + // We use default allocation/deallocation but counted + static void* allocate_node(size_t size, + WeakHandle const& value) { + StringTable::item_added(); + return StringTableHash::BaseConfig::allocate_node(size, value); + } + static void free_node(void* memory, + WeakHandle const& value) { + value.release(); + StringTableHash::BaseConfig::free_node(memory, value); + StringTable::item_removed(); + } +}; -oop StringTable::string_object(HashtableEntry* entry) { - return RootAccess::oop_load(entry->literal_addr()); -} +class StringTableLookupJchar : StackObj { + private: + Thread* _thread; + uintx _hash; + int _len; + const jchar* _str; + Handle _found; -oop StringTable::string_object_no_keepalive(HashtableEntry* entry) { - // The AS_NO_KEEPALIVE peeks at the oop without keeping it alive. - // This is *very dangerous* in general but is okay in this specific - // case. The subsequent oop_load keeps the oop alive if it it matched - // the jchar* string. - return RootAccess::oop_load(entry->literal_addr()); -} - -void StringTable::set_string_object(HashtableEntry* entry, oop string) { - RootAccess::oop_store(entry->literal_addr(), string); -} - -oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) { - assert(hash == java_lang_String::hash_code(name, len), - "hash must be computed using java_lang_String::hash_code"); - return _shared_table.lookup((const char*)name, hash, len); -} - -oop StringTable::lookup_in_main_table(int index, jchar* name, - int len, unsigned int hash) { - int count = 0; - for (HashtableEntry* l = bucket(index); l != NULL; l = l->next()) { - count++; - if (l->hash() == hash) { - if (java_lang_String::equals(string_object_no_keepalive(l), name, len)) { - // We must perform a new load with string_object() that keeps the string - // alive as we must expose the oop as strongly reachable when exiting - // this context, in case the oop gets published. - return string_object(l); - } + public: + StringTableLookupJchar(Thread* thread, uintx hash, const jchar* key, int len) + : _thread(thread), _hash(hash), _str(key), _len(len) { + } + uintx get_hash() const { + return _hash; + } + bool equals(WeakHandle* value, bool* is_dead) { + oop val_oop = value->peek(); + if (val_oop == NULL) { + // dead oop, mark this hash dead for cleaning + *is_dead = true; + return false; } + bool equals = java_lang_String::equals(val_oop, (jchar*)_str, _len); + if (!equals) { + return false; + } + // Need to resolve weak handle and Handleize through possible safepoint. + _found = Handle(_thread, value->resolve()); + return true; } - // If the bucket size is too deep check if this hash code is insufficient. - if (count >= rehash_count && !needs_rehashing()) { - _needs_rehashing = check_rehash_table(count); +}; + +class StringTableLookupOop : public StackObj { + private: + Thread* _thread; + uintx _hash; + Handle _find; + Handle _found; // Might be a different oop with the same value that's already + // in the table, which is the point. + public: + StringTableLookupOop(Thread* thread, uintx hash, Handle handle) + : _thread(thread), _hash(hash), _find(handle) { } + + uintx get_hash() const { + return _hash; } - return NULL; + + bool equals(WeakHandle* value, bool* is_dead) { + oop val_oop = value->peek(); + if (val_oop == NULL) { + // dead oop, mark this hash dead for cleaning + *is_dead = true; + return false; + } + bool equals = java_lang_String::equals(_find(), val_oop); + if (!equals) { + return false; + } + // Need to resolve weak handle and Handleize through possible safepoint. + _found = Handle(_thread, value->resolve()); + return true; + } +}; + +static size_t ceil_pow_2(uintx val) { + size_t ret; + for (ret = 1; ((size_t)1 << ret) < val; ++ret); + return ret; } - -oop StringTable::basic_add(int index_arg, Handle string, jchar* name, - int len, unsigned int hashValue_arg, TRAPS) { - - assert(java_lang_String::equals(string(), name, len), - "string must be properly initialized"); - // Cannot hit a safepoint in this function because the "this" pointer can move. - NoSafepointVerifier nsv; - - // Check if the symbol table has been rehashed, if so, need to recalculate - // the hash value and index before second lookup. - unsigned int hashValue; - int index; - if (use_alternate_hashcode()) { - hashValue = alt_hash_string(name, len); - index = hash_to_index(hashValue); - } else { - hashValue = hashValue_arg; - index = index_arg; - } - - // Since look-up was done lock-free, we need to check if another - // thread beat us in the race to insert the symbol. - - // No need to lookup the shared table from here since the caller (intern()) already did - oop test = lookup_in_main_table(index, name, len, hashValue); // calls lookup(u1*, int) - if (test != NULL) { - // Entry already added - return test; - } - - HashtableEntry* entry = new_entry(hashValue, string()); - add_entry(index, entry); - return string(); +StringTable::StringTable() : _local_table(NULL), _current_size(0), _has_work(0), + _needs_rehashing(false), _weak_handles(NULL), _items(0), _uncleaned_items(0) { + _weak_handles = new OopStorage("StringTable weak", + StringTableWeakAlloc_lock, + StringTableWeakActive_lock); + size_t start_size_log_2 = ceil_pow_2(StringTableSize); + _current_size = ((size_t)1) << start_size_log_2; + log_trace(stringtable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")", + _current_size, start_size_log_2); + _local_table = new StringTableHash(start_size_log_2, END_SIZE, REHASH_LEN); } +size_t StringTable::item_added() { + return Atomic::add((size_t)1, &(the_table()->_items)); +} +size_t StringTable::items_to_clean(size_t ncl) { + size_t total = Atomic::add((size_t)ncl, &(the_table()->_uncleaned_items)); + log_trace(stringtable)( + "Uncleaned items:" SIZE_FORMAT " added: " SIZE_FORMAT " total:" SIZE_FORMAT, + the_table()->_uncleaned_items, ncl, total); + return total; +} + +void StringTable::item_removed() { + Atomic::add((size_t)-1, &(the_table()->_items)); + Atomic::add((size_t)-1, &(the_table()->_uncleaned_items)); +} + +double StringTable::get_load_factor() { + return (_items*1.0)/_current_size; +} + +double StringTable::get_dead_factor() { + return (_uncleaned_items*1.0)/_current_size; +} + +size_t StringTable::table_size(Thread* thread) { + return ((size_t)(1)) << _local_table->get_size_log2(thread != NULL ? thread + : Thread::current()); +} + +void StringTable::trigger_concurrent_work() { + MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); + the_table()->_has_work = true; + Service_lock->notify_all(); +} + +// Probing oop StringTable::lookup(Symbol* symbol) { ResourceMark rm; int length; @@ -211,71 +239,45 @@ oop StringTable::lookup(Symbol* symbol) { } oop StringTable::lookup(jchar* name, int len) { - // shared table always uses java_lang_String::hash_code unsigned int hash = java_lang_String::hash_code(name, len); - oop string = lookup_shared(name, len, hash); + oop string = StringTable::the_table()->lookup_shared(name, len, hash); if (string != NULL) { return string; } - if (use_alternate_hashcode()) { - hash = alt_hash_string(name, len); + if (StringTable::_alt_hash) { + hash = hash_string(name, len, true); } - int index = the_table()->hash_to_index(hash); - string = the_table()->lookup_in_main_table(index, name, len, hash); - - return string; + return StringTable::the_table()->do_lookup(name, len, hash); } -oop StringTable::intern(Handle string_or_null, jchar* name, - int len, TRAPS) { - // shared table always uses java_lang_String::hash_code - unsigned int hashValue = java_lang_String::hash_code(name, len); - oop found_string = lookup_shared(name, len, hashValue); - if (found_string != NULL) { - return found_string; +class StringTableGet : public StackObj { + Thread* _thread; + Handle _return; + public: + StringTableGet(Thread* thread) : _thread(thread) {} + void operator()(WeakHandle* val) { + oop result = val->resolve(); + assert(result != NULL, "Result should be reachable"); + _return = Handle(_thread, result); } - if (use_alternate_hashcode()) { - hashValue = alt_hash_string(name, len); + oop get_res_oop() { + return _return(); } - int index = the_table()->hash_to_index(hashValue); - found_string = the_table()->lookup_in_main_table(index, name, len, hashValue); +}; - // Found - if (found_string != NULL) { - return found_string; +oop StringTable::do_lookup(jchar* name, int len, uintx hash) { + Thread* thread = Thread::current(); + StringTableLookupJchar lookup(thread, hash, name, len); + StringTableGet stg(thread); + bool rehash_warning; + _local_table->get(thread, lookup, stg, &rehash_warning); + if (rehash_warning) { + _needs_rehashing = true; } - - debug_only(StableMemoryChecker smc(name, len * sizeof(name[0]))); - assert(!Universe::heap()->is_in_reserved(name), - "proposed name of symbol must be stable"); - - HandleMark hm(THREAD); // cleanup strings created - Handle string; - // try to reuse the string if possible - if (!string_or_null.is_null()) { - string = string_or_null; - } else { - string = java_lang_String::create_from_unicode(name, len, CHECK_NULL); - } - - // Deduplicate the string before it is interned. Note that we should never - // deduplicate a string after it has been interned. Doing so will counteract - // compiler optimizations done on e.g. interned string literals. - Universe::heap()->deduplicate_string(string()); - - // Grab the StringTable_lock before getting the_table() because it could - // change at safepoint. - oop added_or_found; - { - MutexLocker ml(StringTable_lock, THREAD); - // Otherwise, add to symbol to table - added_or_found = the_table()->basic_add(index, string, name, len, - hashValue, CHECK_NULL); - } - - return added_or_found; + return stg.get_res_oop(); } +// Interning oop StringTable::intern(Symbol* symbol, TRAPS) { if (symbol == NULL) return NULL; ResourceMark rm(THREAD); @@ -286,19 +288,17 @@ oop StringTable::intern(Symbol* symbol, TRAPS) { return result; } - -oop StringTable::intern(oop string, TRAPS) -{ +oop StringTable::intern(oop string, TRAPS) { if (string == NULL) return NULL; ResourceMark rm(THREAD); int length; Handle h_string (THREAD, string); - jchar* chars = java_lang_String::as_unicode_string(string, length, CHECK_NULL); + jchar* chars = java_lang_String::as_unicode_string(string, length, + CHECK_NULL); oop result = intern(h_string, chars, length, CHECK_NULL); return result; } - oop StringTable::intern(const char* utf8_string, TRAPS) { if (utf8_string == NULL) return NULL; ResourceMark rm(THREAD); @@ -310,342 +310,451 @@ oop StringTable::intern(const char* utf8_string, TRAPS) { return result; } -void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int* processed, int* removed) { - BucketUnlinkContext context; - buckets_unlink_or_oops_do(is_alive, f, 0, the_table()->table_size(), &context); - _the_table->bulk_free_entries(&context); - *processed = context._num_processed; - *removed = context._num_removed; -} - -void StringTable::possibly_parallel_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int* processed, int* removed) { - // Readers of the table are unlocked, so we should only be removing - // entries at a safepoint. - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); - const int limit = the_table()->table_size(); - - BucketUnlinkContext context; - for (;;) { - // Grab next set of buckets to scan - int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize; - if (start_idx >= limit) { - // End of table - break; - } - - int end_idx = MIN2(limit, start_idx + ClaimChunkSize); - buckets_unlink_or_oops_do(is_alive, f, start_idx, end_idx, &context); +oop StringTable::intern(Handle string_or_null_h, jchar* name, int len, TRAPS) { + // shared table always uses java_lang_String::hash_code + unsigned int hash = java_lang_String::hash_code(name, len); + oop found_string = StringTable::the_table()->lookup_shared(name, len, hash); + if (found_string != NULL) { + return found_string; } - _the_table->bulk_free_entries(&context); - *processed = context._num_processed; - *removed = context._num_removed; -} - -void StringTable::buckets_oops_do(OopClosure* f, int start_idx, int end_idx) { - const int limit = the_table()->table_size(); - - assert(0 <= start_idx && start_idx <= limit, - "start_idx (%d) is out of bounds", start_idx); - assert(0 <= end_idx && end_idx <= limit, - "end_idx (%d) is out of bounds", end_idx); - assert(start_idx <= end_idx, - "Index ordering: start_idx=%d, end_idx=%d", - start_idx, end_idx); - - for (int i = start_idx; i < end_idx; i += 1) { - HashtableEntry* entry = the_table()->bucket(i); - while (entry != NULL) { - assert(!entry->is_shared(), "CDS not used for the StringTable"); - - f->do_oop((oop*)entry->literal_addr()); - - entry = entry->next(); - } + if (StringTable::_alt_hash) { + hash = hash_string(name, len, true); } + return StringTable::the_table()->do_intern(string_or_null_h, name, len, + hash, CHECK_NULL); } -void StringTable::buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, BucketUnlinkContext* context) { - const int limit = the_table()->table_size(); +class StringTableCreateEntry : public StackObj { + private: + Thread* _thread; + Handle _return; + Handle _store; + public: + StringTableCreateEntry(Thread* thread, Handle store) + : _thread(thread), _store(store) {} - assert(0 <= start_idx && start_idx <= limit, - "start_idx (%d) is out of bounds", start_idx); - assert(0 <= end_idx && end_idx <= limit, - "end_idx (%d) is out of bounds", end_idx); - assert(start_idx <= end_idx, - "Index ordering: start_idx=%d, end_idx=%d", - start_idx, end_idx); + WeakHandle operator()() { // No dups found + WeakHandle wh = + WeakHandle::create(_store); + return wh; + } + void operator()(bool inserted, WeakHandle* val) { + oop result = val->resolve(); + assert(result != NULL, "Result should be reachable"); + _return = Handle(_thread, result); + } + oop get_return() const { + return _return(); + } +}; - for (int i = start_idx; i < end_idx; ++i) { - HashtableEntry** p = the_table()->bucket_addr(i); - HashtableEntry* entry = the_table()->bucket(i); - while (entry != NULL) { - assert(!entry->is_shared(), "CDS not used for the StringTable"); +oop StringTable::do_intern(Handle string_or_null_h, jchar* name, + int len, uintx hash, TRAPS) { + HandleMark hm(THREAD); // cleanup strings created + Handle string_h; - if (is_alive->do_object_b(string_object_no_keepalive(entry))) { - if (f != NULL) { - f->do_oop(entry->literal_addr()); - } - p = entry->next_addr(); - } else { - *p = entry->next(); - context->free_entry(entry); - } - context->_num_processed++; - entry = *p; + if (!string_or_null_h.is_null()) { + string_h = string_or_null_h; + } else { + string_h = java_lang_String::create_from_unicode(name, len, CHECK_NULL); + } + + // Deduplicate the string before it is interned. Note that we should never + // deduplicate a string after it has been interned. Doing so will counteract + // compiler optimizations done on e.g. interned string literals. + Universe::heap()->deduplicate_string(string_h()); + + assert(java_lang_String::equals(string_h(), name, len), + "string must be properly initialized"); + assert(len == java_lang_String::length(string_h()), "Must be same length"); + StringTableLookupOop lookup(THREAD, hash, string_h); + StringTableCreateEntry stc(THREAD, string_h); + + bool rehash_warning; + _local_table->get_insert_lazy(THREAD, lookup, stc, stc, &rehash_warning); + if (rehash_warning) { + _needs_rehashing = true; + } + return stc.get_return(); +} + +// GC support +class StringTableIsAliveCounter : public BoolObjectClosure { + BoolObjectClosure* _real_boc; + public: + size_t _count; + size_t _count_total; + StringTableIsAliveCounter(BoolObjectClosure* boc) : _real_boc(boc), _count(0), + _count_total(0) {} + bool do_object_b(oop obj) { + bool ret = _real_boc->do_object_b(obj); + if (!ret) { + ++_count; } + ++_count_total; + return ret; + } +}; + +void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, + int* processed, int* removed) { + DoNothingClosure dnc; + assert(is_alive != NULL, "No closure"); + StringTableIsAliveCounter stiac(is_alive); + OopClosure* tmp = f != NULL ? f : &dnc; + + StringTable::the_table()->_weak_handles->weak_oops_do(&stiac, tmp); + + StringTable::the_table()->items_to_clean(stiac._count); + StringTable::the_table()->check_concurrent_work(); + if (processed != NULL) { + *processed = (int) stiac._count_total; + } + if (removed != NULL) { + *removed = (int) stiac._count; } } void StringTable::oops_do(OopClosure* f) { - buckets_oops_do(f, 0, the_table()->table_size()); + assert(f != NULL, "No closure"); + StringTable::the_table()->_weak_handles->oops_do(f); } -void StringTable::possibly_parallel_oops_do(OopClosure* f) { - const int limit = the_table()->table_size(); +void StringTable::possibly_parallel_unlink( + OopStorage::ParState* _par_state_string, BoolObjectClosure* cl, + int* processed, int* removed) +{ + DoNothingClosure dnc; + assert(cl != NULL, "No closure"); + StringTableIsAliveCounter stiac(cl); - for (;;) { - // Grab next set of buckets to scan - int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize; - if (start_idx >= limit) { - // End of table - break; + _par_state_string->weak_oops_do(&stiac, &dnc); + + StringTable::the_table()->items_to_clean(stiac._count); + StringTable::the_table()->check_concurrent_work(); + *processed = (int) stiac._count_total; + *removed = (int) stiac._count; +} + +void StringTable::possibly_parallel_oops_do( + OopStorage::ParState* + _par_state_string, OopClosure* f) +{ + assert(f != NULL, "No closure"); + _par_state_string->oops_do(f); +} + +// Concurrent work +void StringTable::grow(JavaThread* jt) { + StringTableHash::GrowTask gt(_local_table); + if (!gt.prepare(jt)) { + return; + } + log_trace(stringtable)("Started to grow"); + { + TraceTime timer("Grow", TRACETIME_LOG(Debug, stringtable, perf)); + while (gt.doTask(jt)) { + gt.pause(jt); + { + ThreadBlockInVM tbivm(jt); + } + gt.cont(jt); } + } + gt.done(jt); + _current_size = table_size(jt); + log_debug(stringtable)("Grown to size:" SIZE_FORMAT, _current_size); +} - int end_idx = MIN2(limit, start_idx + ClaimChunkSize); - buckets_oops_do(f, start_idx, end_idx); +struct StringTableDoDelete : StackObj { + long _count; + StringTableDoDelete() : _count(0) {} + void operator()(WeakHandle* val) { + ++_count; + } +}; + +struct StringTableDeleteCheck : StackObj { + long _count; + long _item; + StringTableDeleteCheck() : _count(0), _item(0) {} + bool operator()(WeakHandle* val) { + ++_item; + oop tmp = val->peek(); + if (tmp == NULL) { + ++_count; + return true; + } else { + return false; + } + } +}; + +void StringTable::clean_dead_entries(JavaThread* jt) { + StringTableHash::BulkDeleteTask bdt(_local_table); + if (!bdt.prepare(jt)) { + return; + } + + StringTableDeleteCheck stdc; + StringTableDoDelete stdd; + bool interrupted = false; + { + TraceTime timer("Clean", TRACETIME_LOG(Debug, stringtable, perf)); + while(bdt.doTask(jt, stdc, stdd)) { + bdt.pause(jt); + { + ThreadBlockInVM tbivm(jt); + } + if (!bdt.cont(jt)) { + interrupted = true; + break; + } + } + } + if (interrupted) { + _has_work = true; + } else { + bdt.done(jt); + } + log_debug(stringtable)("Cleaned %ld of %ld", stdc._count, stdc._item); +} + +void StringTable::check_concurrent_work() { + if (_has_work) { + return; + } + double load_factor = StringTable::get_load_factor(); + double dead_factor = StringTable::get_dead_factor(); + // We should clean/resize if we have more dead than alive, + // more items than preferred load factor or + // more dead items than water mark. + if ((dead_factor > load_factor) || + (load_factor > PREF_AVG_LIST_LEN) || + (dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) { + log_debug(stringtable)("Concurrent work triggered, live factor:%g dead factor:%g", + load_factor, dead_factor); + trigger_concurrent_work(); } } +void StringTable::concurrent_work(JavaThread* jt) { + _has_work = false; + double load_factor = get_load_factor(); + log_debug(stringtable, perf)("Concurrent work, live factor: %g", load_factor); + // We prefer growing, since that also removes dead items + if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) { + grow(jt); + } else { + clean_dead_entries(jt); + } +} + +void StringTable::do_concurrent_work(JavaThread* jt) { + StringTable::the_table()->concurrent_work(jt); +} + +// Rehash +bool StringTable::do_rehash() { + if (!_local_table->is_safepoint_safe()) { + return false; + } + + // We use max size + StringTableHash* new_table = new StringTableHash(END_SIZE, END_SIZE, REHASH_LEN); + // Use alt hash from now on + _alt_hash = true; + if (!_local_table->try_move_nodes_to(Thread::current(), new_table)) { + _alt_hash = false; + delete new_table; + return false; + } + + // free old table + delete _local_table; + _local_table = new_table; + + return true; +} + +void StringTable::try_rehash_table() { + static bool rehashed = false; + log_debug(stringtable)("Table imbalanced, rehashing called."); + + // Grow instead of rehash. + if (get_load_factor() > PREF_AVG_LIST_LEN && + !_local_table->is_max_size_reached()) { + log_debug(stringtable)("Choosing growing over rehashing."); + trigger_concurrent_work(); + _needs_rehashing = false; + return; + } + // Already rehashed. + if (rehashed) { + log_warning(stringtable)("Rehashing already done, still long lists."); + trigger_concurrent_work(); + _needs_rehashing = false; + return; + } + + murmur_seed = AltHashing::compute_seed(); + { + if (do_rehash()) { + rehashed = true; + } else { + log_info(stringtable)("Resizes in progress rehashing skipped."); + } + } + _needs_rehashing = false; +} + +void StringTable::rehash_table() { + StringTable::the_table()->try_rehash_table(); +} + +// Statistics +static int literal_size(oop obj) { + // NOTE: this would over-count if (pre-JDK8) + // java_lang_Class::has_offset_field() is true and the String.value array is + // shared by several Strings. However, starting from JDK8, the String.value + // array is not shared anymore. + if (obj == NULL) { + return 0; + } else if (obj->klass() == SystemDictionary::String_klass()) { + return (obj->size() + java_lang_String::value(obj)->size()) * HeapWordSize; + } else { + return obj->size(); + } +} + +struct SizeFunc : StackObj { + size_t operator()(WeakHandle* val) { + oop s = val->peek(); + if (s == NULL) { + // Dead + return 0; + } + return literal_size(s); + }; +}; + +void StringTable::print_table_statistics(outputStream* st, + const char* table_name) { + SizeFunc sz; + _local_table->statistics_to(Thread::current(), sz, st, table_name); +} + +// Verification +class VerifyStrings : StackObj { + public: + bool operator()(WeakHandle* val) { + oop s = val->peek(); + if (s != NULL) { + assert(java_lang_String::length(s) >= 0, "Length on string must work."); + } + return true; + }; +}; + // This verification is part of Universe::verify() and needs to be quick. -// See StringTable::verify_and_compare() below for exhaustive verification. void StringTable::verify() { - for (int i = 0; i < the_table()->table_size(); ++i) { - HashtableEntry* p = the_table()->bucket(i); - for ( ; p != NULL; p = p->next()) { - oop s = string_object_no_keepalive(p); - guarantee(s != NULL, "interned string is NULL"); - unsigned int h = hash_string(s); - guarantee(p->hash() == h, "broken hash in string table entry"); - guarantee(the_table()->hash_to_index(h) == i, - "wrong index in string table"); - } + Thread* thr = Thread::current(); + VerifyStrings vs; + if (!the_table()->_local_table->try_scan(thr, vs)) { + log_info(stringtable)("verify unavailable at this moment"); } } +// Verification and comp +class VerifyCompStrings : StackObj { + GrowableArray* _oops; + public: + size_t _errors; + VerifyCompStrings(GrowableArray* oops) : _oops(oops), _errors(0) {} + bool operator()(WeakHandle* val) { + oop s = val->resolve(); + if (s == NULL) { + return true; + } + int len = _oops->length(); + for (int i = 0; i < len; i++) { + bool eq = java_lang_String::equals(s, _oops->at(i)); + assert(!eq, "Duplicate strings"); + if (eq) { + _errors++; + } + } + _oops->push(s); + return true; + }; +}; + +size_t StringTable::verify_and_compare_entries() { + Thread* thr = Thread::current(); + GrowableArray* oops = + new (ResourceObj::C_HEAP, mtInternal) + GrowableArray((int)the_table()->_current_size, true); + + VerifyCompStrings vcs(oops); + if (!the_table()->_local_table->try_scan(thr, vcs)) { + log_info(stringtable)("verify unavailable at this moment"); + } + delete oops; + return vcs._errors; +} + +// Dumping +class PrintString : StackObj { + Thread* _thr; + outputStream* _st; + public: + PrintString(Thread* thr, outputStream* st) : _thr(thr), _st(st) {} + bool operator()(WeakHandle* val) { + oop s = val->peek(); + if (s == NULL) { + return true; + } + typeArrayOop value = java_lang_String::value_no_keepalive(s); + int length = java_lang_String::length(s); + bool is_latin1 = java_lang_String::is_latin1(s); + + if (length <= 0) { + _st->print("%d: ", length); + } else { + ResourceMark rm(_thr); + int utf8_length = length; + char* utf8_string; + + if (!is_latin1) { + jchar* chars = value->char_at_addr(0); + utf8_string = UNICODE::as_utf8(chars, utf8_length); + } else { + jbyte* bytes = value->byte_at_addr(0); + utf8_string = UNICODE::as_utf8(bytes, utf8_length); + } + + _st->print("%d: ", utf8_length); + HashtableTextDump::put_utf8(_st, utf8_string, utf8_length); + } + _st->cr(); + return true; + }; +}; + void StringTable::dump(outputStream* st, bool verbose) { if (!verbose) { - the_table()->print_table_statistics(st, "StringTable", string_object_no_keepalive); + the_table()->print_table_statistics(st, "StringTable"); } else { - Thread* THREAD = Thread::current(); + Thread* thr = Thread::current(); + ResourceMark rm(thr); st->print_cr("VERSION: 1.1"); - for (int i = 0; i < the_table()->table_size(); ++i) { - HashtableEntry* p = the_table()->bucket(i); - for ( ; p != NULL; p = p->next()) { - oop s = string_object_no_keepalive(p); - typeArrayOop value = java_lang_String::value_no_keepalive(s); - int length = java_lang_String::length(s); - bool is_latin1 = java_lang_String::is_latin1(s); - - if (length <= 0) { - st->print("%d: ", length); - } else { - ResourceMark rm(THREAD); - int utf8_length = length; - char* utf8_string; - - if (!is_latin1) { - jchar* chars = value->char_at_addr(0); - utf8_string = UNICODE::as_utf8(chars, utf8_length); - } else { - jbyte* bytes = value->byte_at_addr(0); - utf8_string = UNICODE::as_utf8(bytes, utf8_length); - } - - st->print("%d: ", utf8_length); - HashtableTextDump::put_utf8(st, utf8_string, utf8_length); - } - st->cr(); - } + PrintString ps(thr, st); + if (!the_table()->_local_table->try_scan(thr, ps)) { + st->print_cr("dump unavailable at this moment"); } } } -StringTable::VerifyRetTypes StringTable::compare_entries( - int bkt1, int e_cnt1, - HashtableEntry* e_ptr1, - int bkt2, int e_cnt2, - HashtableEntry* e_ptr2) { - // These entries are sanity checked by verify_and_compare_entries() - // before this function is called. - oop str1 = string_object_no_keepalive(e_ptr1); - oop str2 = string_object_no_keepalive(e_ptr2); - - if (str1 == str2) { - tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") " - "in entry @ bucket[%d][%d] and entry @ bucket[%d][%d]", - p2i(str1), bkt1, e_cnt1, bkt2, e_cnt2); - return _verify_fail_continue; - } - - if (java_lang_String::equals(str1, str2)) { - tty->print_cr("ERROR: identical String values in entry @ " - "bucket[%d][%d] and entry @ bucket[%d][%d]", - bkt1, e_cnt1, bkt2, e_cnt2); - return _verify_fail_continue; - } - - return _verify_pass; -} - -StringTable::VerifyRetTypes StringTable::verify_entry(int bkt, int e_cnt, - HashtableEntry* e_ptr, - StringTable::VerifyMesgModes mesg_mode) { - - VerifyRetTypes ret = _verify_pass; // be optimistic - - oop str = string_object_no_keepalive(e_ptr); - if (str == NULL) { - if (mesg_mode == _verify_with_mesgs) { - tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt, - e_cnt); - } - // NULL oop means no more verifications are possible - return _verify_fail_done; - } - - if (str->klass() != SystemDictionary::String_klass()) { - if (mesg_mode == _verify_with_mesgs) { - tty->print_cr("ERROR: oop is not a String in entry @ bucket[%d][%d]", - bkt, e_cnt); - } - // not a String means no more verifications are possible - return _verify_fail_done; - } - - unsigned int h = hash_string(str); - if (e_ptr->hash() != h) { - if (mesg_mode == _verify_with_mesgs) { - tty->print_cr("ERROR: broken hash value in entry @ bucket[%d][%d], " - "bkt_hash=%d, str_hash=%d", bkt, e_cnt, e_ptr->hash(), h); - } - ret = _verify_fail_continue; - } - - if (the_table()->hash_to_index(h) != bkt) { - if (mesg_mode == _verify_with_mesgs) { - tty->print_cr("ERROR: wrong index value for entry @ bucket[%d][%d], " - "str_hash=%d, hash_to_index=%d", bkt, e_cnt, h, - the_table()->hash_to_index(h)); - } - ret = _verify_fail_continue; - } - - return ret; -} - -// See StringTable::verify() above for the quick verification that is -// part of Universe::verify(). This verification is exhaustive and -// reports on every issue that is found. StringTable::verify() only -// reports on the first issue that is found. -// -// StringTable::verify_entry() checks: -// - oop value != NULL (same as verify()) -// - oop value is a String -// - hash(String) == hash in entry (same as verify()) -// - index for hash == index of entry (same as verify()) -// -// StringTable::compare_entries() checks: -// - oops are unique across all entries -// - String values are unique across all entries -// -int StringTable::verify_and_compare_entries() { - assert(StringTable_lock->is_locked(), "sanity check"); - - int fail_cnt = 0; - - // first, verify all the entries individually: - for (int bkt = 0; bkt < the_table()->table_size(); bkt++) { - HashtableEntry* e_ptr = the_table()->bucket(bkt); - for (int e_cnt = 0; e_ptr != NULL; e_ptr = e_ptr->next(), e_cnt++) { - VerifyRetTypes ret = verify_entry(bkt, e_cnt, e_ptr, _verify_with_mesgs); - if (ret != _verify_pass) { - fail_cnt++; - } - } - } - - // Optimization: if the above check did not find any failures, then - // the comparison loop below does not need to call verify_entry() - // before calling compare_entries(). If there were failures, then we - // have to call verify_entry() to see if the entry can be passed to - // compare_entries() safely. When we call verify_entry() in the loop - // below, we do so quietly to void duplicate messages and we don't - // increment fail_cnt because the failures have already been counted. - bool need_entry_verify = (fail_cnt != 0); - - // second, verify all entries relative to each other: - for (int bkt1 = 0; bkt1 < the_table()->table_size(); bkt1++) { - HashtableEntry* e_ptr1 = the_table()->bucket(bkt1); - for (int e_cnt1 = 0; e_ptr1 != NULL; e_ptr1 = e_ptr1->next(), e_cnt1++) { - if (need_entry_verify) { - VerifyRetTypes ret = verify_entry(bkt1, e_cnt1, e_ptr1, - _verify_quietly); - if (ret == _verify_fail_done) { - // cannot use the current entry to compare against other entries - continue; - } - } - - for (int bkt2 = bkt1; bkt2 < the_table()->table_size(); bkt2++) { - HashtableEntry* e_ptr2 = the_table()->bucket(bkt2); - int e_cnt2; - for (e_cnt2 = 0; e_ptr2 != NULL; e_ptr2 = e_ptr2->next(), e_cnt2++) { - if (bkt1 == bkt2 && e_cnt2 <= e_cnt1) { - // skip the entries up to and including the one that - // we're comparing against - continue; - } - - if (need_entry_verify) { - VerifyRetTypes ret = verify_entry(bkt2, e_cnt2, e_ptr2, - _verify_quietly); - if (ret == _verify_fail_done) { - // cannot compare against this entry - continue; - } - } - - // compare two entries, report and count any failures: - if (compare_entries(bkt1, e_cnt1, e_ptr1, bkt2, e_cnt2, e_ptr2) - != _verify_pass) { - fail_cnt++; - } - } - } - } - } - return fail_cnt; -} - -// Create a new table and using alternate hash code, populate the new table -// with the existing strings. Set flag to use the alternate hash code afterwards. -void StringTable::rehash_table() { - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); - // This should never happen with -Xshare:dump but it might in testing mode. - if (DumpSharedSpaces) return; - StringTable* new_table = new StringTable(); - - // Rehash the table - the_table()->move_to(new_table); - - // Delete the table and buckets (entries are reused in new table). - delete _the_table; - // Don't check if we need rehashing until the table gets unbalanced again. - // Then rehash with a new global seed. - _needs_rehashing = false; - _the_table = new_table; -} - // Utility for dumping strings StringtableDCmd::StringtableDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), @@ -671,14 +780,21 @@ int StringtableDCmd::num_arguments() { } } -#if INCLUDE_CDS_JAVA_HEAP // Sharing +#if INCLUDE_CDS_JAVA_HEAP +oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) { + assert(hash == java_lang_String::hash_code(name, len), + "hash must be computed using java_lang_String::hash_code"); + return _shared_table.lookup((const char*)name, hash, len); +} + oop StringTable::create_archived_string(oop s, Thread* THREAD) { assert(DumpSharedSpaces, "this function is only used with -Xshare:dump"); 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)MetaspaceShared::archive_heap_object(v, THREAD); if (new_v == NULL) { return NULL; } @@ -692,51 +808,51 @@ oop StringTable::create_archived_string(oop s, Thread* THREAD) { return new_s; } -bool StringTable::copy_shared_string(GrowableArray *string_space, - CompactStringTableWriter* writer) { +struct CopyToArchive : StackObj { + CompactStringTableWriter* _writer; + CopyToArchive(CompactStringTableWriter* writer) : _writer(writer) {} + bool operator()(WeakHandle* val) { + oop s = val->peek(); + if (s == NULL) { + return true; + } + unsigned int hash = java_lang_String::hash_code(s); + if (hash == 0) { + return true; + } + + java_lang_String::set_hash(s, hash); + oop new_s = StringTable::create_archived_string(s, Thread::current()); + if (new_s == NULL) { + return true; + } + + val->replace(new_s); + // add to the compact table + _writer->add(hash, new_s); + return true; + } +}; + +void StringTable::copy_shared_string_table(CompactStringTableWriter* writer) { assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be"); - Thread* THREAD = Thread::current(); - for (int i = 0; i < the_table()->table_size(); ++i) { - HashtableEntry* bucket = the_table()->bucket(i); - for ( ; bucket != NULL; bucket = bucket->next()) { - oop s = string_object_no_keepalive(bucket); - unsigned int hash = java_lang_String::hash_code(s); - if (hash == 0) { - continue; - } - - java_lang_String::set_hash(s, hash); - oop new_s = create_archived_string(s, THREAD); - if (new_s == NULL) { - continue; - } - - // set the archived string in bucket - set_string_object(bucket, new_s); - - // add to the compact table - writer->add(hash, new_s); - } - } - - return true; + CopyToArchive copy(writer); + StringTable::the_table()->_local_table->do_scan(Thread::current(), copy); } -void StringTable::write_to_archive(GrowableArray *string_space) { +void StringTable::write_to_archive() { assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be"); _shared_table.reset(); - int num_buckets = the_table()->number_of_entries() / - SharedSymbolTableBucketSize; + int num_buckets = the_table()->_items / 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); // Copy the interned strings into the "string space" within the java heap - if (copy_shared_string(string_space, &writer)) { - writer.dump(&_shared_table); - } + copy_shared_string_table(&writer); + writer.dump(&_shared_table); } void StringTable::serialize(SerializeClosure* soc) { @@ -744,7 +860,8 @@ void StringTable::serialize(SerializeClosure* soc) { _shared_table.serialize(soc); if (soc->writing()) { - _shared_table.reset(); // Sanity. Make sure we don't use the shared table at dump time + // Sanity. Make sure we don't use the shared table at dump time + _shared_table.reset(); } else if (!_shared_string_mapped) { _shared_table.reset(); } diff --git a/src/hotspot/share/classfile/stringTable.hpp b/src/hotspot/share/classfile/stringTable.hpp index fa99e4f32cd..ca056949930 100644 --- a/src/hotspot/share/classfile/stringTable.hpp +++ b/src/hotspot/share/classfile/stringTable.hpp @@ -25,109 +25,111 @@ #ifndef SHARE_VM_CLASSFILE_STRINGTABLE_HPP #define SHARE_VM_CLASSFILE_STRINGTABLE_HPP -#include "utilities/hashtable.hpp" +#include "gc/shared/oopStorage.hpp" +#include "gc/shared/oopStorageParState.hpp" +#include "memory/allocation.hpp" +#include "memory/padded.hpp" +#include "oops/oop.hpp" +#include "oops/weakHandle.hpp" +#include "utilities/concurrentHashTable.hpp" template class CompactHashtable; class CompactStringTableWriter; -class FileMapInfo; class SerializeClosure; -class StringTable : public RehashableHashtable { +class StringTable; +class StringTableConfig; +typedef ConcurrentHashTable, + StringTableConfig, mtSymbol> StringTableHash; + +class StringTableCreateEntry; + +class StringTable : public CHeapObj{ friend class VMStructs; friend class Symbol; + friend class StringTableConfig; + friend class StringTableCreateEntry; private: + void grow(JavaThread* jt); + void clean_dead_entries(JavaThread* jt); + // The string table static StringTable* _the_table; - // Shared string table static CompactHashtable _shared_table; static bool _shared_string_mapped; + static bool _alt_hash; +private: - // Set if one bucket is out of balance due to hash algorithm deficiency - static bool _needs_rehashing; + // Set if one bucket is out of balance due to hash algorithm deficiency + StringTableHash* _local_table; + size_t _current_size; + volatile bool _has_work; + volatile bool _needs_rehashing; - // Claimed high water mark for parallel chunked scanning - static volatile int _parallel_claimed_idx; + OopStorage* _weak_handles; - static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS); - oop basic_add(int index, Handle string_or_null, jchar* name, int len, - unsigned int hashValue, TRAPS); + volatile size_t _items; + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile size_t)); + volatile size_t _uncleaned_items; + DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile size_t)); - oop lookup_in_main_table(int index, jchar* chars, int length, unsigned int hashValue); - static oop lookup_shared(jchar* name, int len, unsigned int hash); + double get_load_factor(); + double get_dead_factor(); - // Apply the give oop closure to the entries to the buckets - // in the range [start_idx, end_idx). - static void buckets_oops_do(OopClosure* f, int start_idx, int end_idx); + void check_concurrent_work(); + void trigger_concurrent_work(); - typedef StringTable::BucketUnlinkContext BucketUnlinkContext; - // Unlink or apply the give oop closure to the entries to the buckets - // in the range [start_idx, end_idx). Unlinked bucket entries are collected in the given - // context to be freed later. - // This allows multiple threads to work on the table at once. - static void buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, BucketUnlinkContext* context); + static uintx item_added(); + static void item_removed(); + static size_t items_to_clean(size_t ncl); - // Hashing algorithm, used as the hash value used by the - // StringTable for bucket selection and comparison (stored in the - // HashtableEntry structures). This is used in the String.intern() method. - static unsigned int hash_string(const jchar* s, int len); - static unsigned int hash_string(oop string); - static unsigned int alt_hash_string(const jchar* s, int len); + StringTable(); - // Accessors for the string roots in the hashtable entries. - // Use string_object_no_keepalive() only when the value is not returned - // outside of a scope where a thread transition is possible. - static oop string_object(HashtableEntry* entry); - static oop string_object_no_keepalive(HashtableEntry* entry); - static void set_string_object(HashtableEntry* entry, oop string); + static oop intern(Handle string_or_null_h, jchar* name, int len, TRAPS); + oop do_intern(Handle string_or_null, jchar* name, int len, uintx hash, TRAPS); + oop do_lookup(jchar* name, int len, uintx hash); - StringTable() : RehashableHashtable((int)StringTableSize, - sizeof (HashtableEntry)) {} + void concurrent_work(JavaThread* jt); + void print_table_statistics(outputStream* st, const char* table_name); - StringTable(HashtableBucket* t, int number_of_entries) - : RehashableHashtable((int)StringTableSize, sizeof (HashtableEntry), t, - number_of_entries) {} -public: + void try_rehash_table(); + bool do_rehash(); + + public: // The string table static StringTable* the_table() { return _the_table; } + size_t table_size(Thread* thread = NULL); - // Size of one bucket in the string table. Used when checking for rollover. - static uint bucket_size() { return sizeof(HashtableBucket); } + static OopStorage* weak_storage() { return the_table()->_weak_handles; } static void create_table() { assert(_the_table == NULL, "One string table allowed."); _the_table = new StringTable(); } + static void do_concurrent_work(JavaThread* jt); + static bool has_work() { return the_table()->_has_work; } + // GC support // Delete pointers to otherwise-unreachable objects. - static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f) { - int processed = 0; - int removed = 0; - unlink_or_oops_do(cl, f, &processed, &removed); - } static void unlink(BoolObjectClosure* cl) { - int processed = 0; - int removed = 0; - unlink_or_oops_do(cl, NULL, &processed, &removed); - } - static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed); - static void unlink(BoolObjectClosure* cl, int* processed, int* removed) { - unlink_or_oops_do(cl, NULL, processed, removed); + unlink_or_oops_do(cl); } + static void unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f = NULL, + int* processed = NULL, int* removed = NULL); + // Serially invoke "f->do_oop" on the locations of all oops in the table. static void oops_do(OopClosure* f); // Possibly parallel versions of the above - static void possibly_parallel_unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed); - static void possibly_parallel_unlink(BoolObjectClosure* cl, int* processed, int* removed) { - possibly_parallel_unlink_or_oops_do(cl, NULL, processed, removed); - } - static void possibly_parallel_oops_do(OopClosure* f); - - // Internal test. - static void test_alt_hash() PRODUCT_RETURN; + static void possibly_parallel_unlink( + OopStorage::ParState* par_state_string, + BoolObjectClosure* cl, int* processed, int* removed); + static void possibly_parallel_oops_do( + OopStorage::ParState* par_state_string, + OopClosure* f); // Probing static oop lookup(Symbol* symbol); @@ -138,46 +140,28 @@ public: static oop intern(oop string, TRAPS); static oop intern(const char *utf8_string, TRAPS); - // Debugging - static void verify(); - static void dump(outputStream* st, bool verbose=false); - - enum VerifyMesgModes { - _verify_quietly = 0, - _verify_with_mesgs = 1 - }; - - enum VerifyRetTypes { - _verify_pass = 0, - _verify_fail_continue = 1, - _verify_fail_done = 2 - }; - - static VerifyRetTypes compare_entries(int bkt1, int e_cnt1, - HashtableEntry* e_ptr1, - int bkt2, int e_cnt2, - HashtableEntry* e_ptr2); - static VerifyRetTypes verify_entry(int bkt, int e_cnt, - HashtableEntry* e_ptr, - VerifyMesgModes mesg_mode); - static int verify_and_compare_entries(); + // Rehash the string table if it gets out of balance + static void rehash_table(); + static bool needs_rehashing() + { return StringTable::the_table()->_needs_rehashing; } // Sharing + private: + oop lookup_shared(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; + public: + static oop create_archived_string(oop s, Thread* THREAD); 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 bool copy_shared_string(GrowableArray *string_space, - CompactStringTableWriter* ch_table) NOT_CDS_JAVA_HEAP_RETURN_(false); - static oop create_archived_string(oop s, Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN_(NULL); - static void write_to_archive(GrowableArray *string_space) 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; - // Rehash the symbol table if it gets out of balance - static void rehash_table(); - static bool needs_rehashing() { return _needs_rehashing; } - - // Parallel chunked scanning - static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; } - static int parallel_claimed_index() { return _parallel_claimed_idx; } + // Jcmd + static void dump(outputStream* st, bool verbose=false); + // Debugging + static size_t verify_and_compare_entries(); + static void verify(); }; + #endif // SHARE_VM_CLASSFILE_STRINGTABLE_HPP diff --git a/src/hotspot/share/gc/cms/cmsHeap.cpp b/src/hotspot/share/gc/cms/cmsHeap.cpp index 838a58cc449..b2c426967cf 100644 --- a/src/hotspot/share/gc/cms/cmsHeap.cpp +++ b/src/hotspot/share/gc/cms/cmsHeap.cpp @@ -220,13 +220,14 @@ void CMSHeap::cms_process_roots(StrongRootsScope* scope, ScanningOption so, bool only_strong_roots, OopsInGenClosure* root_closure, - CLDClosure* cld_closure) { + CLDClosure* cld_closure, + OopStorage::ParState* par_state_string) { MarkingCodeBlobClosure mark_code_closure(root_closure, !CodeBlobToOopClosure::FixRelocations); CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure; process_roots(scope, so, root_closure, cld_closure, weak_cld_closure, &mark_code_closure); if (!only_strong_roots) { - process_string_table_roots(scope, root_closure); + process_string_table_roots(scope, root_closure, par_state_string); } if (young_gen_as_roots && diff --git a/src/hotspot/share/gc/cms/cmsHeap.hpp b/src/hotspot/share/gc/cms/cmsHeap.hpp index ee800fff7f8..93f177aadec 100644 --- a/src/hotspot/share/gc/cms/cmsHeap.hpp +++ b/src/hotspot/share/gc/cms/cmsHeap.hpp @@ -30,6 +30,7 @@ #include "gc/shared/collectedHeap.hpp" #include "gc/shared/gcCause.hpp" #include "gc/shared/genCollectedHeap.hpp" +#include "gc/shared/oopStorageParState.hpp" #include "utilities/growableArray.hpp" class CLDClosure; @@ -90,7 +91,8 @@ public: ScanningOption so, bool only_strong_roots, OopsInGenClosure* root_closure, - CLDClosure* cld_closure); + CLDClosure* cld_closure, + OopStorage::ParState* par_state_string = NULL); GCMemoryManager* old_manager() const { return _old_manager; } diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp index 779bc201e10..422ba66bcae 100644 --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp @@ -54,6 +54,7 @@ #include "gc/shared/genCollectedHeap.hpp" #include "gc/shared/genOopClosures.inline.hpp" #include "gc/shared/isGCActiveMark.hpp" +#include "gc/shared/oopStorageParState.hpp" #include "gc/shared/referencePolicy.hpp" #include "gc/shared/space.inline.hpp" #include "gc/shared/strongRootsScope.hpp" @@ -2769,10 +2770,12 @@ class CMSParMarkTask : public AbstractGangTask { protected: CMSCollector* _collector; uint _n_workers; + OopStorage::ParState _par_state_string; CMSParMarkTask(const char* name, CMSCollector* collector, uint n_workers) : AbstractGangTask(name), _collector(collector), - _n_workers(n_workers) {} + _n_workers(n_workers), + _par_state_string(StringTable::weak_storage()) {} // Work method in support of parallel rescan ... of young gen spaces void do_young_space_rescan(OopsInGenClosure* cl, ContiguousSpace* space, @@ -4274,7 +4277,9 @@ void CMSParInitialMarkTask::work(uint worker_id) { GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()), _collector->should_unload_classes(), &par_mri_cl, - &cld_closure); + &cld_closure, + &_par_state_string); + assert(_collector->should_unload_classes() || (_collector->CMSCollector::roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache), "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops"); @@ -4403,7 +4408,8 @@ void CMSParRemarkTask::work(uint worker_id) { GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()), _collector->should_unload_classes(), &par_mrias_cl, - NULL); // The dirty klasses will be handled below + NULL, // The dirty klasses will be handled below + &_par_state_string); assert(_collector->should_unload_classes() || (_collector->CMSCollector::roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache), diff --git a/src/hotspot/share/gc/cms/parNewGeneration.cpp b/src/hotspot/share/gc/cms/parNewGeneration.cpp index 836bd392986..4e625ed1ec3 100644 --- a/src/hotspot/share/gc/cms/parNewGeneration.cpp +++ b/src/hotspot/share/gc/cms/parNewGeneration.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/stringTable.hpp" #include "gc/cms/cmsHeap.inline.hpp" #include "gc/cms/compactibleFreeListSpace.hpp" #include "gc/cms/concurrentMarkSweepGeneration.hpp" @@ -589,7 +590,8 @@ ParNewGenTask::ParNewGenTask(ParNewGeneration* young_gen, _young_gen(young_gen), _old_gen(old_gen), _young_old_boundary(young_old_boundary), _state_set(state_set), - _strong_roots_scope(strong_roots_scope) + _strong_roots_scope(strong_roots_scope), + _par_state_string(StringTable::weak_storage()) {} void ParNewGenTask::work(uint worker_id) { @@ -611,7 +613,8 @@ void ParNewGenTask::work(uint worker_id) { heap->young_process_roots(_strong_roots_scope, &par_scan_state.to_space_root_closure(), &par_scan_state.older_gen_closure(), - &cld_scan_closure); + &cld_scan_closure, + &_par_state_string); par_scan_state.end_strong_roots(); diff --git a/src/hotspot/share/gc/cms/parNewGeneration.hpp b/src/hotspot/share/gc/cms/parNewGeneration.hpp index 92b74004876..3ccd16224d6 100644 --- a/src/hotspot/share/gc/cms/parNewGeneration.hpp +++ b/src/hotspot/share/gc/cms/parNewGeneration.hpp @@ -29,6 +29,7 @@ #include "gc/serial/defNewGeneration.hpp" #include "gc/shared/copyFailedInfo.hpp" #include "gc/shared/gcTrace.hpp" +#include "gc/shared/oopStorageParState.hpp" #include "gc/shared/plab.hpp" #include "gc/shared/preservedMarks.hpp" #include "gc/shared/taskqueue.hpp" @@ -236,6 +237,7 @@ class ParNewGenTask: public AbstractGangTask { HeapWord* _young_old_boundary; class ParScanThreadStateSet* _state_set; StrongRootsScope* _strong_roots_scope; + OopStorage::ParState _par_state_string; public: ParNewGenTask(ParNewGeneration* young_gen, diff --git a/src/hotspot/share/gc/g1/collectionSetChooser.cpp b/src/hotspot/share/gc/g1/collectionSetChooser.cpp index f9aa2423e02..9d2c90b546c 100644 --- a/src/hotspot/share/gc/g1/collectionSetChooser.cpp +++ b/src/hotspot/share/gc/g1/collectionSetChooser.cpp @@ -147,7 +147,7 @@ void CollectionSetChooser::sort_regions() { void CollectionSetChooser::add_region(HeapRegion* hr) { assert(!hr->is_pinned(), "Pinned region shouldn't be added to the collection set (index %u)", hr->hrm_index()); - assert(!hr->is_young(), "should not be young!"); + assert(hr->is_old(), "should be old but is %s", hr->get_type_str()); assert(hr->rem_set()->is_complete(), "Trying to add region %u to the collection set with incomplete remembered set", hr->hrm_index()); _regions.append(hr); @@ -185,7 +185,7 @@ uint CollectionSetChooser::claim_array_chunk(uint chunk_size) { void CollectionSetChooser::set_region(uint index, HeapRegion* hr) { assert(regions_at(index) == NULL, "precondition"); - assert(!hr->is_young(), "should not be young!"); + assert(hr->is_old(), "should be old but is %s", hr->get_type_str()); regions_at_put(index, hr); hr->calc_gc_efficiency(); } @@ -233,18 +233,19 @@ public: _cset_updater(hrSorted, true /* parallel */, chunk_size) { } bool do_heap_region(HeapRegion* r) { - // Do we have any marking information for this region? - if (r->is_marked()) { - // We will skip any region that's currently used as an old GC - // alloc region (we should not consider those for collection - // before we fill them up). - if (_cset_updater.should_add(r) && !_g1h->is_old_gc_alloc_region(r)) { - _cset_updater.add_region(r); - } else if (r->is_old()) { - // Can clean out the remembered sets of all regions that we did not choose but - // we created the remembered set for. - r->rem_set()->clear(true); - } + // We will skip any region that's currently used as an old GC + // alloc region (we should not consider those for collection + // before we fill them up). + if (_cset_updater.should_add(r) && !_g1h->is_old_gc_alloc_region(r)) { + _cset_updater.add_region(r); + } else if (r->is_old()) { + // Keep remembered sets for humongous regions, otherwise clean out remembered + // sets for old regions. + r->rem_set()->clear(true /* only_cardset */); + } else { + assert(!r->is_old() || !r->rem_set()->is_tracked(), + "Missed to clear unused remembered set of region %u (%s) that is %s", + r->hrm_index(), r->get_type_str(), r->rem_set()->get_state_str()); } return false; } @@ -280,11 +281,10 @@ bool CollectionSetChooser::region_occupancy_low_enough_for_evac(size_t live_byte } bool CollectionSetChooser::should_add(HeapRegion* hr) const { - assert(hr->is_marked(), "pre-condition"); - assert(!hr->is_young(), "should never consider young regions"); - return !hr->is_pinned() && - region_occupancy_low_enough_for_evac(hr->live_bytes()) && - hr->rem_set()->is_complete(); + return !hr->is_young() && + !hr->is_pinned() && + region_occupancy_low_enough_for_evac(hr->live_bytes()) && + hr->rem_set()->is_complete(); } void CollectionSetChooser::rebuild(WorkGang* workers, uint n_regions) { diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 00954e6e940..48cbd9802e2 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -69,6 +69,7 @@ #include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/generationSpec.hpp" #include "gc/shared/isGCActiveMark.hpp" +#include "gc/shared/oopStorageParState.hpp" #include "gc/shared/preservedMarks.inline.hpp" #include "gc/shared/suspendibleThreadSet.hpp" #include "gc/shared/referenceProcessor.inline.hpp" @@ -3218,6 +3219,7 @@ class G1StringAndSymbolCleaningTask : public AbstractGangTask { private: BoolObjectClosure* _is_alive; G1StringDedupUnlinkOrOopsDoClosure _dedup_closure; + OopStorage::ParState _par_state_string; int _initial_string_table_size; int _initial_symbol_table_size; @@ -3237,24 +3239,19 @@ public: AbstractGangTask("String/Symbol Unlinking"), _is_alive(is_alive), _dedup_closure(is_alive, NULL, false), + _par_state_string(StringTable::weak_storage()), _process_strings(process_strings), _strings_processed(0), _strings_removed(0), _process_symbols(process_symbols), _symbols_processed(0), _symbols_removed(0), _process_string_dedup(process_string_dedup) { - _initial_string_table_size = StringTable::the_table()->table_size(); + _initial_string_table_size = (int) StringTable::the_table()->table_size(); _initial_symbol_table_size = SymbolTable::the_table()->table_size(); - if (process_strings) { - StringTable::clear_parallel_claimed_index(); - } if (process_symbols) { SymbolTable::clear_parallel_claimed_index(); } } ~G1StringAndSymbolCleaningTask() { - guarantee(!_process_strings || StringTable::parallel_claimed_index() >= _initial_string_table_size, - "claim value %d after unlink less than initial string table size %d", - StringTable::parallel_claimed_index(), _initial_string_table_size); guarantee(!_process_symbols || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size, "claim value %d after unlink less than initial symbol table size %d", SymbolTable::parallel_claimed_index(), _initial_symbol_table_size); @@ -3273,7 +3270,7 @@ public: int symbols_processed = 0; int symbols_removed = 0; if (_process_strings) { - StringTable::possibly_parallel_unlink(_is_alive, &strings_processed, &strings_removed); + StringTable::possibly_parallel_unlink(&_par_state_string, _is_alive, &strings_processed, &strings_removed); Atomic::add(strings_processed, &_strings_processed); Atomic::add(strings_removed, &_strings_removed); } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 272d91ec869..37ed91d9c73 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -1651,7 +1651,11 @@ void G1ConcurrentMark::weak_refs_work(bool clear_all_soft_refs) { } if (has_overflown()) { - // We can not trust g1_is_alive if the marking stack overflowed + // We can not trust g1_is_alive and the contents of the heap if the marking stack + // overflowed while processing references. Exit the VM. + fatal("Overflow during reference processing, can not continue. Please " + "increase MarkStackSizeMax (current value: " SIZE_FORMAT ") and " + "restart.", MarkStackSizeMax); return; } diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index 5aeb4baa453..8d70c0fe108 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -468,15 +468,24 @@ G1EvacPhaseWithTrimTimeTracker::G1EvacPhaseWithTrimTimeTracker(G1ParScanThreadSt _pss(pss), _start(Ticks::now()), _total_time(total_time), - _trim_time(trim_time) { + _trim_time(trim_time), + _stopped(false) { assert(_pss->trim_ticks().value() == 0, "Possibly remaining trim ticks left over from previous use"); } G1EvacPhaseWithTrimTimeTracker::~G1EvacPhaseWithTrimTimeTracker() { + if (!_stopped) { + stop(); + } +} + +void G1EvacPhaseWithTrimTimeTracker::stop() { + assert(!_stopped, "Should only be called once"); _total_time += (Ticks::now() - _start) - _pss->trim_ticks(); _trim_time += _pss->trim_ticks(); _pss->reset_trim_ticks(); + _stopped = true; } G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id) : @@ -504,6 +513,8 @@ G1EvacPhaseTimesTracker::G1EvacPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1EvacPhaseTimesTracker::~G1EvacPhaseTimesTracker() { if (_phase_times != NULL) { + // Explicitly stop the trim tracker since it's not yet destructed. + _trim_tracker.stop(); // Exclude trim time by increasing the start time. _start_time += _trim_time; _phase_times->record_or_add_objcopy_time_secs(_worker_id, _trim_time.seconds()); diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp index d5ec33400c0..3b20cfe4d2d 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp @@ -373,9 +373,13 @@ class G1EvacPhaseWithTrimTimeTracker : public StackObj { Tickspan& _total_time; Tickspan& _trim_time; + + bool _stopped; public: G1EvacPhaseWithTrimTimeTracker(G1ParScanThreadState* pss, Tickspan& total_time, Tickspan& trim_time); ~G1EvacPhaseWithTrimTimeTracker(); + + void stop(); }; class G1GCParPhaseTimesTracker : public CHeapObj { diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index 4f882a1fb20..d94a1173208 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -825,10 +825,10 @@ double G1Policy::predict_base_elapsed_time_ms(size_t pending_cards) const { size_t G1Policy::predict_bytes_to_copy(HeapRegion* hr) const { size_t bytes_to_copy; - if (hr->is_marked()) + if (!hr->is_young()) { bytes_to_copy = hr->max_live_bytes(); - else { - assert(hr->is_young() && hr->age_in_surv_rate_group() != -1, "invariant"); + } else { + assert(hr->age_in_surv_rate_group() != -1, "invariant"); int age = hr->age_in_surv_rate_group(); double yg_surv_rate = predict_yg_surv_rate(age, hr->surv_rate_group()); bytes_to_copy = (size_t) (hr->used() * yg_surv_rate); diff --git a/src/hotspot/share/gc/g1/g1RootProcessor.cpp b/src/hotspot/share/gc/g1/g1RootProcessor.cpp index 73b3c91ab94..e47c9f7baea 100644 --- a/src/hotspot/share/gc/g1/g1RootProcessor.cpp +++ b/src/hotspot/share/gc/g1/g1RootProcessor.cpp @@ -38,6 +38,7 @@ #include "gc/g1/g1RootClosures.hpp" #include "gc/g1/g1RootProcessor.hpp" #include "gc/g1/heapRegion.inline.hpp" +#include "gc/shared/oopStorageParState.hpp" #include "gc/shared/referenceProcessor.hpp" #include "gc/shared/weakProcessor.hpp" #include "memory/allocation.inline.hpp" @@ -72,6 +73,7 @@ G1RootProcessor::G1RootProcessor(G1CollectedHeap* g1h, uint n_workers) : _process_strong_tasks(G1RP_PS_NumElements), _srs(n_workers), _lock(Mutex::leaf, "G1 Root Scanning barrier lock", false, Monitor::_safepoint_check_never), + _par_state_string(StringTable::weak_storage()), _n_workers_discovered_strong_classes(0) {} void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_i) { @@ -301,7 +303,7 @@ void G1RootProcessor::process_string_table_roots(G1RootClosures* closures, G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::StringTableRoots, worker_i); // All threads execute the following. A specific chunk of buckets // from the StringTable are the individual tasks. - StringTable::possibly_parallel_oops_do(closures->weak_oops()); + StringTable::possibly_parallel_oops_do(&_par_state_string, closures->weak_oops()); } void G1RootProcessor::process_code_cache_roots(CodeBlobClosure* code_closure, diff --git a/src/hotspot/share/gc/g1/g1RootProcessor.hpp b/src/hotspot/share/gc/g1/g1RootProcessor.hpp index c4b5f03016e..3c2e811cb80 100644 --- a/src/hotspot/share/gc/g1/g1RootProcessor.hpp +++ b/src/hotspot/share/gc/g1/g1RootProcessor.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_VM_GC_G1_G1ROOTPROCESSOR_HPP #define SHARE_VM_GC_G1_G1ROOTPROCESSOR_HPP +#include "gc/shared/oopStorageParState.hpp" #include "gc/shared/strongRootsScope.hpp" #include "memory/allocation.hpp" #include "runtime/mutex.hpp" @@ -49,6 +50,7 @@ class G1RootProcessor : public StackObj { G1CollectedHeap* _g1h; SubTasksDone _process_strong_tasks; StrongRootsScope _srs; + OopStorage::ParState _par_state_string; // Used to implement the Thread work barrier. Monitor _lock; diff --git a/src/hotspot/share/gc/g1/g1_globals.hpp b/src/hotspot/share/gc/g1/g1_globals.hpp index 6c2263586e6..8c7aec8472e 100644 --- a/src/hotspot/share/gc/g1/g1_globals.hpp +++ b/src/hotspot/share/gc/g1/g1_globals.hpp @@ -108,9 +108,6 @@ "When expanding, % of uncommitted space to claim.") \ range(0, 100) \ \ - develop(bool, G1RSBarrierRegionFilter, true, \ - "If true, generate region filtering code in RS barrier") \ - \ product(size_t, G1UpdateBufferSize, 256, \ "Size of an update buffer") \ range(1, NOT_LP64(32*M) LP64_ONLY(1*G)) \ diff --git a/src/hotspot/share/gc/g1/heapRegion.hpp b/src/hotspot/share/gc/g1/heapRegion.hpp index 3bb6049332d..01d3c4d8758 100644 --- a/src/hotspot/share/gc/g1/heapRegion.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.hpp @@ -541,10 +541,6 @@ class HeapRegion: public G1ContiguousSpace { // objects during evac failure handling. void note_self_forwarding_removal_end(size_t marked_bytes); - // Returns "false" iff no object in the region was allocated when the - // last mark phase ended. - bool is_marked() { return _prev_top_at_mark_start != bottom(); } - void reset_during_compaction() { assert(is_humongous(), "should only be called for humongous regions"); diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index 18a5d69d41f..75af999fc0b 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -373,7 +373,8 @@ HeapWord* CollectedHeap::obj_allocate_raw(Klass* klass, size_t size, return result; } } - return Universe::heap()->mem_allocate(size, gc_overhead_limit_was_exceeded); + + return allocate_outside_tlab(klass, size, gc_overhead_limit_was_exceeded, THREAD); } HeapWord* CollectedHeap::allocate_from_tlab_slow(Klass* klass, size_t size, TRAPS) { diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index 3d5c71e46d2..a2ab0d6a253 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -144,6 +144,9 @@ class CollectedHeap : public CHeapObj { inline static HeapWord* allocate_from_tlab(Klass* klass, size_t size, TRAPS); static HeapWord* allocate_from_tlab_slow(Klass* klass, size_t size, TRAPS); + inline static HeapWord* allocate_outside_tlab(Klass* klass, size_t size, + bool* gc_overhead_limit_was_exceeded, TRAPS); + // Raw memory allocation facilities // The obj and array allocate methods are covers for these methods. // mem_allocate() should never be diff --git a/src/hotspot/share/gc/shared/collectedHeap.inline.hpp b/src/hotspot/share/gc/shared/collectedHeap.inline.hpp index 6c2893d9f54..08c8131333f 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.inline.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.inline.hpp @@ -142,14 +142,6 @@ HeapWord* CollectedHeap::common_mem_allocate_noinit(Klass* klass, size_t size, T HeapWord* result = heap->obj_allocate_raw(klass, size, &gc_overhead_limit_was_exceeded, THREAD); if (result != NULL) { - NOT_PRODUCT(Universe::heap()-> - check_for_non_bad_heap_word_value(result, size)); - assert(!HAS_PENDING_EXCEPTION, - "Unexpected exception, will result in uninitialized storage"); - THREAD->incr_allocated_bytes(size * HeapWordSize); - - AllocTracer::send_allocation_outside_tlab(klass, result, size * HeapWordSize, THREAD); - return result; } @@ -198,6 +190,22 @@ HeapWord* CollectedHeap::allocate_from_tlab(Klass* klass, size_t size, TRAPS) { return obj; } +HeapWord* CollectedHeap::allocate_outside_tlab(Klass* klass, size_t size, + bool* gc_overhead_limit_was_exceeded, TRAPS) { + HeapWord* result = Universe::heap()->mem_allocate(size, gc_overhead_limit_was_exceeded); + if (result == NULL) { + return result; + } + + NOT_PRODUCT(Universe::heap()->check_for_non_bad_heap_word_value(result, size)); + assert(!HAS_PENDING_EXCEPTION, + "Unexpected exception, will result in uninitialized storage"); + THREAD->incr_allocated_bytes(size * HeapWordSize); + + AllocTracer::send_allocation_outside_tlab(klass, result, size * HeapWordSize, THREAD); + return result; +} + void CollectedHeap::init_obj(HeapWord* obj, size_t size) { assert(obj != NULL, "cannot initialize NULL object"); const size_t hs = oopDesc::header_size(); diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp index efd714ef7b0..5a5804f053e 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp @@ -44,6 +44,7 @@ #include "gc/shared/genCollectedHeap.hpp" #include "gc/shared/genOopClosures.inline.hpp" #include "gc/shared/generationSpec.hpp" +#include "gc/shared/oopStorageParState.inline.hpp" #include "gc/shared/space.hpp" #include "gc/shared/strongRootsScope.hpp" #include "gc/shared/vmGCOperations.hpp" @@ -851,12 +852,17 @@ void GenCollectedHeap::process_roots(StrongRootsScope* scope, } void GenCollectedHeap::process_string_table_roots(StrongRootsScope* scope, - OopClosure* root_closure) { + OopClosure* root_closure, + OopStorage::ParState* par_state_string) { assert(root_closure != NULL, "Must be set"); // All threads execute the following. A specific chunk of buckets // from the StringTable are the individual tasks. + + // Either we should be single threaded or have a ParState + assert((scope->n_threads() <= 1) || par_state_string != NULL, "Parallel but no ParState"); + if (scope->n_threads() > 1) { - StringTable::possibly_parallel_oops_do(root_closure); + StringTable::possibly_parallel_oops_do(par_state_string, root_closure); } else { StringTable::oops_do(root_closure); } @@ -865,12 +871,13 @@ void GenCollectedHeap::process_string_table_roots(StrongRootsScope* scope, void GenCollectedHeap::young_process_roots(StrongRootsScope* scope, OopsInGenClosure* root_closure, OopsInGenClosure* old_gen_closure, - CLDClosure* cld_closure) { + CLDClosure* cld_closure, + OopStorage::ParState* par_state_string) { MarkingCodeBlobClosure mark_code_closure(root_closure, CodeBlobToOopClosure::FixRelocations); process_roots(scope, SO_ScavengeCodeCache, root_closure, cld_closure, cld_closure, &mark_code_closure); - process_string_table_roots(scope, root_closure); + process_string_table_roots(scope, root_closure, par_state_string); if (!_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) { root_closure->reset_generation(); @@ -890,7 +897,8 @@ void GenCollectedHeap::full_process_roots(StrongRootsScope* scope, ScanningOption so, bool only_strong_roots, OopsInGenClosure* root_closure, - CLDClosure* cld_closure) { + CLDClosure* cld_closure, + OopStorage::ParState* par_state_string) { MarkingCodeBlobClosure mark_code_closure(root_closure, is_adjust_phase); CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure; @@ -899,7 +907,7 @@ void GenCollectedHeap::full_process_roots(StrongRootsScope* scope, // We never treat the string table as roots during marking // for the full gc, so we only need to process it during // the adjust phase. - process_string_table_roots(scope, root_closure); + process_string_table_roots(scope, root_closure, par_state_string); } _process_strong_tasks->all_tasks_completed(scope->n_threads()); diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.hpp b/src/hotspot/share/gc/shared/genCollectedHeap.hpp index a56eff2190e..a250fcd8a14 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp @@ -28,6 +28,7 @@ #include "gc/shared/collectedHeap.hpp" #include "gc/shared/collectorPolicy.hpp" #include "gc/shared/generation.hpp" +#include "gc/shared/oopStorageParState.hpp" #include "gc/shared/softRefGenPolicy.hpp" class AdaptiveSizePolicy; @@ -401,7 +402,8 @@ public: CodeBlobToOopClosure* code_roots); void process_string_table_roots(StrongRootsScope* scope, - OopClosure* root_closure); + OopClosure* root_closure, + OopStorage::ParState* par_state_string); // Accessor for memory state verification support NOT_PRODUCT( @@ -415,14 +417,16 @@ public: void young_process_roots(StrongRootsScope* scope, OopsInGenClosure* root_closure, OopsInGenClosure* old_gen_closure, - CLDClosure* cld_closure); + CLDClosure* cld_closure, + OopStorage::ParState* par_state_string = NULL); void full_process_roots(StrongRootsScope* scope, bool is_adjust_phase, ScanningOption so, bool only_strong_roots, OopsInGenClosure* root_closure, - CLDClosure* cld_closure); + CLDClosure* cld_closure, + OopStorage::ParState* par_state_string = NULL); // Apply "root_closure" to all the weak roots of the system. // These include JNI weak roots, string table, diff --git a/src/hotspot/share/gc/shared/strongRootsScope.cpp b/src/hotspot/share/gc/shared/strongRootsScope.cpp index 43a697f8cda..a167ba48958 100644 --- a/src/hotspot/share/gc/shared/strongRootsScope.cpp +++ b/src/hotspot/share/gc/shared/strongRootsScope.cpp @@ -38,8 +38,6 @@ MarkScope::~MarkScope() { StrongRootsScope::StrongRootsScope(uint n_threads) : _n_threads(n_threads) { Threads::change_thread_claim_parity(); - // Zero the claimed high water mark in the StringTable - StringTable::clear_parallel_claimed_index(); } StrongRootsScope::~StrongRootsScope() { diff --git a/src/hotspot/share/memory/metaspaceShared.cpp b/src/hotspot/share/memory/metaspaceShared.cpp index 72bd6e99205..a89cfd0d25f 100644 --- a/src/hotspot/share/memory/metaspaceShared.cpp +++ b/src/hotspot/share/memory/metaspaceShared.cpp @@ -1841,7 +1841,7 @@ void MetaspaceShared::dump_closed_archive_heap_objects( G1CollectedHeap::heap()->begin_archive_alloc_range(); // Archive interned string objects - StringTable::write_to_archive(closed_archive); + StringTable::write_to_archive(); G1CollectedHeap::heap()->end_archive_alloc_range(closed_archive, os::vm_allocation_granularity()); diff --git a/src/hotspot/share/oops/accessBackend.inline.hpp b/src/hotspot/share/oops/accessBackend.inline.hpp index 51ad1b544be..8305b896cde 100644 --- a/src/hotspot/share/oops/accessBackend.inline.hpp +++ b/src/hotspot/share/oops/accessBackend.inline.hpp @@ -247,14 +247,14 @@ RawAccessBarrier::atomic_cmpxchg_maybe_locked(T new_value, void* addr, T com } class RawAccessBarrierArrayCopy: public AllStatic { + template struct IsHeapWordSized: public IntegralConstant { }; public: template static inline typename EnableIf< - HasDecorator::value>::type + HasDecorator::value>::type arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, size_t length) { - src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); @@ -270,48 +270,68 @@ public: template static inline typename EnableIf< - !HasDecorator::value>::type - arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const T* src_raw, arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, size_t length) { - + !HasDecorator::value && + HasDecorator::value>::type + arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, + arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, + size_t length) { src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); - if (HasDecorator::value) { - AccessInternal::arraycopy_arrayof_conjoint(const_cast(src_raw), dst_raw, length); - } else if (HasDecorator::value && sizeof(T) == HeapWordSize) { - // There is only a disjoint optimization for word granularity copying - if (HasDecorator::value) { - AccessInternal::arraycopy_disjoint_words_atomic(const_cast(src_raw), dst_raw, length); - } else { - AccessInternal::arraycopy_disjoint_words(const_cast(src_raw), dst_raw, length); - } + AccessInternal::arraycopy_arrayof_conjoint(src_raw, dst_raw, length); + } + + template + static inline typename EnableIf< + !HasDecorator::value && + HasDecorator::value && IsHeapWordSized::value>::type + arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, + arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, + size_t length) { + src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); + dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); + + // There is only a disjoint optimization for word granularity copying + if (HasDecorator::value) { + AccessInternal::arraycopy_disjoint_words_atomic(src_raw, dst_raw, length); } else { - if (HasDecorator::value) { - AccessInternal::arraycopy_conjoint_atomic(const_cast(src_raw), dst_raw, length); - } else { - AccessInternal::arraycopy_conjoint(const_cast(src_raw), dst_raw, length); - } + AccessInternal::arraycopy_disjoint_words(src_raw, dst_raw, length); } } - template + template static inline typename EnableIf< - !HasDecorator::value>::type - arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const void* src_raw, - arrayOop dst_obj, size_t dst_offset_in_bytes, void* dst_raw, + !HasDecorator::value && + !(HasDecorator::value && IsHeapWordSized::value) && + !HasDecorator::value && + !HasDecorator::value>::type + arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, + arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, size_t length) { - src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); - if (HasDecorator::value) { - AccessInternal::arraycopy_conjoint_atomic(const_cast(src_raw), dst_raw, length); - } else { - AccessInternal::arraycopy_conjoint(const_cast(src_raw), dst_raw, length); - } + AccessInternal::arraycopy_conjoint(src_raw, dst_raw, length); + } + + template + static inline typename EnableIf< + !HasDecorator::value && + !(HasDecorator::value && IsHeapWordSized::value) && + !HasDecorator::value && + HasDecorator::value>::type + arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, + arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, + size_t length) { + src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); + dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); + + AccessInternal::arraycopy_conjoint_atomic(src_raw, dst_raw, length); } }; +template<> struct RawAccessBarrierArrayCopy::IsHeapWordSized: public IntegralConstant { }; + template template inline bool RawAccessBarrier::arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, diff --git a/src/hotspot/share/oops/instanceRefKlass.inline.hpp b/src/hotspot/share/oops/instanceRefKlass.inline.hpp index fe6fce234ef..fbbf648c982 100644 --- a/src/hotspot/share/oops/instanceRefKlass.inline.hpp +++ b/src/hotspot/share/oops/instanceRefKlass.inline.hpp @@ -53,13 +53,20 @@ void InstanceRefKlass::do_discovered(oop obj, OopClosureType* closure, Contains& } } +static inline oop load_referent(oop obj, ReferenceType type) { + if (type == REF_PHANTOM) { + return HeapAccess::oop_load(java_lang_ref_Reference::referent_addr_raw(obj)); + } else { + return HeapAccess::oop_load(java_lang_ref_Reference::referent_addr_raw(obj)); + } +} + template bool InstanceRefKlass::try_discover(oop obj, ReferenceType type, OopClosureType* closure) { ReferenceDiscoverer* rd = closure->ref_discoverer(); if (rd != NULL) { - T referent_oop = RawAccess<>::oop_load((T*)java_lang_ref_Reference::referent_addr_raw(obj)); - if (!CompressedOops::is_null(referent_oop)) { - oop referent = CompressedOops::decode_not_null(referent_oop); + oop referent = load_referent(obj, type); + if (referent != NULL) { if (!referent->is_gc_marked()) { // Only try to discover if not yet marked. return rd->discover_reference(obj, type); @@ -179,9 +186,9 @@ void InstanceRefKlass::trace_reference_gc(const char *s, oop obj) { log_develop_trace(gc, ref)("InstanceRefKlass %s for obj " PTR_FORMAT, s, p2i(obj)); log_develop_trace(gc, ref)(" referent_addr/* " PTR_FORMAT " / " PTR_FORMAT, - p2i(referent_addr), p2i(referent_addr ? RawAccess<>::oop_load(referent_addr) : (oop)NULL)); + p2i(referent_addr), p2i((oop)HeapAccess::oop_load_at(obj, java_lang_ref_Reference::referent_offset))); log_develop_trace(gc, ref)(" discovered_addr/* " PTR_FORMAT " / " PTR_FORMAT, - p2i(discovered_addr), p2i(discovered_addr ? RawAccess<>::oop_load(discovered_addr) : (oop)NULL)); + p2i(discovered_addr), p2i((oop)HeapAccess::oop_load(discovered_addr))); } #endif diff --git a/src/hotspot/share/oops/weakHandle.cpp b/src/hotspot/share/oops/weakHandle.cpp index 82072718334..7de613d1391 100644 --- a/src/hotspot/share/oops/weakHandle.cpp +++ b/src/hotspot/share/oops/weakHandle.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" +#include "classfile/stringTable.hpp" #include "gc/shared/oopStorage.hpp" #include "oops/access.inline.hpp" #include "oops/oop.hpp" @@ -35,6 +36,10 @@ template <> OopStorage* WeakHandle::get_storage() { return SystemDictionary::vm_weak_oop_storage(); } +template <> OopStorage* WeakHandle::get_storage() { + return StringTable::weak_storage(); +} + template WeakHandle WeakHandle::create(Handle obj) { assert(obj() != NULL, "no need to create weak null oop"); @@ -68,4 +73,5 @@ void WeakHandle::print_on(outputStream* st) const { // Provide instantiation. template class WeakHandle; +template class WeakHandle; diff --git a/src/hotspot/share/oops/weakHandle.hpp b/src/hotspot/share/oops/weakHandle.hpp index d1054efbd9c..57587c4f224 100644 --- a/src/hotspot/share/oops/weakHandle.hpp +++ b/src/hotspot/share/oops/weakHandle.hpp @@ -39,12 +39,11 @@ class OopStorage; // This is the vm version of jweak but has different GC lifetimes and policies, // depending on the type. -enum WeakHandleType { vm_class_loader_data, vm_string }; +enum WeakHandleType { vm_class_loader_data, vm_string, vm_string_table_data }; template class WeakHandle { public: - private: oop* _obj; @@ -59,6 +58,8 @@ class WeakHandle { void release() const; bool is_null() const { return _obj == NULL; } + void replace(oop with_obj); + void print() const; void print_on(outputStream* st) const; }; diff --git a/src/hotspot/share/oops/weakHandle.inline.hpp b/src/hotspot/share/oops/weakHandle.inline.hpp index 6b8b5ffc2b4..7037fcea796 100644 --- a/src/hotspot/share/oops/weakHandle.inline.hpp +++ b/src/hotspot/share/oops/weakHandle.inline.hpp @@ -40,4 +40,10 @@ oop WeakHandle::peek() const { return RootAccess::oop_load(_obj); } +template +void WeakHandle::replace(oop with_obj) { + RootAccess::oop_store(_obj, with_obj); +} + #endif // SHARE_VM_OOPS_WEAKHANDLE_INLINE_HPP + diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index 1d0e16532b3..ac2e7619951 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -53,6 +53,9 @@ diagnostic(bool, StressGCM, false, \ "Randomize instruction scheduling in GCM") \ \ + develop(bool, StressMethodHandleLinkerInlining, false, \ + "Stress inlining through method handle linkers") \ + \ develop(intx, OptoPrologueNops, 0, \ "Insert this many extra nop instructions " \ "in the prologue of every nmethod") \ diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index 3a0dd830ac1..b778b5ebfe9 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -932,7 +932,7 @@ CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* speculative_receiver_type = (receiver_type != NULL) ? receiver_type->speculative_type() : NULL; } CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, - true /* allow_inline */, + !StressMethodHandleLinkerInlining /* allow_inline */, PROB_ALWAYS, speculative_receiver_type); return cg; diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 7fbf0736f36..9ee22c2e1a0 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -2641,6 +2641,9 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts) int old_progress = C->major_progress(); uint orig_worklist_size = _igvn._worklist.size(); + // Reset major-progress flag for the driver's heuristics + C->clear_major_progress(); + #ifndef PRODUCT // Capture for later assert uint unique = C->unique(); @@ -2711,16 +2714,11 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts) if( !_verify_me && !_verify_only && _ltree_root->_child ) { C->print_method(PHASE_BEFORE_BEAUTIFY_LOOPS, 3); if( _ltree_root->_child->beautify_loops( this ) ) { - // IdealLoopTree::split_outer_loop may produce phi-nodes with a single in edge. - // Transform them away. - _igvn.optimize(); - // Re-build loop tree! _ltree_root->_child = NULL; _nodes.clear(); reallocate_preorders(); build_loop_tree(); - // Check for bailout, and return if (C->failing()) { return; @@ -2732,9 +2730,6 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts) } } - // Reset major-progress flag for the driver's heuristics - C->clear_major_progress(); - // Build Dominators for elision of NULL checks & loop finding. // Since nodes do not have a slot for immediate dominator, make // a persistent side array for that info indexed on node->_idx. diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 9c5f49cf173..1b3c2612a01 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -1115,7 +1115,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassSigners(JNIEnv *env, jclass cls)) return NULL; } - objArrayOop signers = java_lang_Class::signers(JNIHandles::resolve_non_null(cls)); + objArrayHandle signers(THREAD, java_lang_Class::signers(JNIHandles::resolve_non_null(cls))); // If there are no signers set in the class, or if the class // is an array, return NULL. diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index c223f6e02fe..a01e05e66fa 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -4447,6 +4447,18 @@ void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, c PropertyList_add(plist, k, v, writeable == WriteableProperty, internal == InternalProperty); } +// Update existing property with new value. +void Arguments::PropertyList_update_value(SystemProperty* plist, const char* k, const char* v) { + SystemProperty* prop; + for (prop = plist; prop != NULL; prop = prop->next()) { + if (strcmp(k, prop->key()) == 0) { + prop->set_value(v); + return; + } + } + assert(false, "invalid property"); +} + // Copies src into buf, replacing "%%" with "%" and "%p" with pid // Returns true if all of the source pointed by src has been copied over to // the destination buffer pointed by buf. Otherwise, returns false. diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp index edf88193673..42b9933130e 100644 --- a/src/hotspot/share/runtime/arguments.hpp +++ b/src/hotspot/share/runtime/arguments.hpp @@ -651,6 +651,7 @@ class Arguments : AllStatic { static void PropertyList_unique_add(SystemProperty** plist, const char* k, const char* v, PropertyAppendable append, PropertyWriteable writeable, PropertyInternal internal); + static void PropertyList_update_value(SystemProperty* plist, const char* k, const char* v); static const char* PropertyList_get_value(SystemProperty* plist, const char* key); static const char* PropertyList_get_readable_value(SystemProperty* plist, const char* key); static int PropertyList_count(SystemProperty* pl); diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 3729eb2992c..412c440a790 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -2542,8 +2542,9 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G); "Relax the access control checks in the verifier") \ \ product(uintx, StringTableSize, defaultStringTableSize, \ - "Number of buckets in the interned String table") \ - range(minimumStringTableSize, 111*defaultStringTableSize) \ + "Number of buckets in the interned String table " \ + "(will be rounded to nearest higher power of 2)") \ + range(minimumStringTableSize, 16777216ul) \ \ experimental(uintx, SymbolTableSize, defaultSymbolTableSize, \ "Number of buckets in the JVM internal Symbol table") \ diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index f557239aea6..f5dab8d4447 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -524,14 +524,9 @@ void before_exit(JavaThread* thread) { } if (VerifyStringTableAtExit) { - int fail_cnt = 0; - { - MutexLocker ml(StringTable_lock); - fail_cnt = StringTable::verify_and_compare_entries(); - } - + size_t fail_cnt = StringTable::verify_and_compare_entries(); if (fail_cnt != 0) { - tty->print_cr("ERROR: fail_cnt=%d", fail_cnt); + tty->print_cr("ERROR: fail_cnt=" SIZE_FORMAT, fail_cnt); guarantee(fail_cnt == 0, "unexpected StringTable verification failures"); } } diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index 485cd6d7c0a..7eb058385bf 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -48,6 +48,8 @@ Mutex* JNIGlobalAlloc_lock = NULL; Mutex* JNIGlobalActive_lock = NULL; Mutex* JNIWeakAlloc_lock = NULL; Mutex* JNIWeakActive_lock = NULL; +Mutex* StringTableWeakAlloc_lock = NULL; +Mutex* StringTableWeakActive_lock = NULL; Mutex* JNIHandleBlockFreeList_lock = NULL; Mutex* VMWeakAlloc_lock = NULL; Mutex* VMWeakActive_lock = NULL; @@ -186,6 +188,9 @@ void mutex_init() { def(VMWeakAlloc_lock , PaddedMutex , vmweak, true, Monitor::_safepoint_check_never); def(VMWeakActive_lock , PaddedMutex , vmweak-1, true, Monitor::_safepoint_check_never); + def(StringTableWeakAlloc_lock , PaddedMutex , vmweak, true, Monitor::_safepoint_check_never); + def(StringTableWeakActive_lock , PaddedMutex , vmweak-1, true, Monitor::_safepoint_check_never); + if (UseConcMarkSweepGC || UseG1GC) { def(FullGCCount_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never); // in support of ExplicitGCInvokesConcurrent } diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp index 673d7ed56c6..a477899929c 100644 --- a/src/hotspot/share/runtime/mutexLocker.hpp +++ b/src/hotspot/share/runtime/mutexLocker.hpp @@ -42,6 +42,8 @@ extern Mutex* JNIGlobalAlloc_lock; // JNI global storage allocate extern Mutex* JNIGlobalActive_lock; // JNI global storage active list lock extern Mutex* JNIWeakAlloc_lock; // JNI weak storage allocate list lock extern Mutex* JNIWeakActive_lock; // JNI weak storage active list lock +extern Mutex* StringTableWeakAlloc_lock; // StringTable weak storage allocate list lock +extern Mutex* StringTableWeakActive_lock; // STringTable weak storage active list lock extern Mutex* JNIHandleBlockFreeList_lock; // a lock on the JNI handle block free list extern Mutex* VMWeakAlloc_lock; // VM Weak Handles storage allocate list lock extern Mutex* VMWeakActive_lock; // VM Weak Handles storage active list lock diff --git a/src/hotspot/share/runtime/serviceThread.cpp b/src/hotspot/share/runtime/serviceThread.cpp index 5174a32ebfa..364a62ff1b1 100644 --- a/src/hotspot/share/runtime/serviceThread.cpp +++ b/src/hotspot/share/runtime/serviceThread.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/stringTable.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/serviceThread.hpp" @@ -82,6 +83,7 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) { bool has_gc_notification_event = false; bool has_dcmd_notification_event = false; bool acs_notify = false; + bool stringtable_work = false; JvmtiDeferredEvent jvmti_event; { // Need state transition ThreadBlockInVM so that this thread @@ -98,7 +100,8 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) { while (!(sensors_changed = LowMemoryDetector::has_pending_requests()) && !(has_jvmti_events = JvmtiDeferredEventQueue::has_events()) && !(has_gc_notification_event = GCNotifier::has_event()) && - !(has_dcmd_notification_event = DCmdFactory::has_pending_jmx_notification())) { + !(has_dcmd_notification_event = DCmdFactory::has_pending_jmx_notification()) && + !(stringtable_work = StringTable::has_work())) { // wait until one of the sensors has pending requests, or there is a // pending JVMTI event or JMX GC notification to post Service_lock->wait(Mutex::_no_safepoint_check_flag); @@ -109,6 +112,10 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) { } } + if (stringtable_work) { + StringTable::do_concurrent_work(jt); + } + if (has_jvmti_events) { jvmti_event.post(); } diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 624f4ace08b..fac653f3dc4 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -1082,6 +1082,7 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread, Bytecode_invoke bytecode(caller, bci); int bytecode_index = bytecode.index(); + bc = bytecode.invoke_code(); methodHandle attached_method = extract_attached_method(vfst); if (attached_method.not_null()) { @@ -1095,6 +1096,11 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread, // Adjust invocation mode according to the attached method. switch (bc) { + case Bytecodes::_invokevirtual: + if (attached_method->method_holder()->is_interface()) { + bc = Bytecodes::_invokeinterface; + } + break; case Bytecodes::_invokeinterface: if (!attached_method->method_holder()->is_interface()) { bc = Bytecodes::_invokevirtual; @@ -1110,10 +1116,10 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread, break; } } - } else { - bc = bytecode.invoke_code(); } + assert(bc != Bytecodes::_illegal, "not initialized"); + bool has_receiver = bc != Bytecodes::_invokestatic && bc != Bytecodes::_invokedynamic && bc != Bytecodes::_invokehandle; diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index 9c25a047e59..7cfdaad2c01 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -1132,6 +1132,9 @@ static void reset_vm_info_property(TRAPS) { ResourceMark rm(THREAD); const char *vm_info = VM_Version::vm_info_string(); + // update the native system property first + Arguments::PropertyList_update_value(Arguments::system_properties(), "java.vm.info", vm_info); + // java.lang.System class Klass* klass = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK); @@ -3779,9 +3782,10 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { initialize_java_lang_classes(main_thread, CHECK_JNI_ERR); - // We need this for ClassDataSharing - the initial vm.info property is set - // with the default value of CDS "sharing" which may be reset through - // command line options. + // We need this to update the java.vm.info property in case any flags used + // to initially define it have been changed. This is needed for both CDS and + // AOT, since UseSharedSpaces and UseAOT may be changed after java.vm.info + // is initially computed. See Abstract_VM_Version::vm_info_string(). reset_vm_info_property(CHECK_JNI_ERR); quicken_jni_functions(); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 48a51aba18e..68739477371 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -164,7 +164,6 @@ typedef HashtableEntry IntptrHashtableEntry; typedef Hashtable IntptrHashtable; typedef Hashtable SymbolHashtable; typedef HashtableEntry SymbolHashtableEntry; -typedef Hashtable StringHashtable; typedef Hashtable KlassHashtable; typedef HashtableEntry KlassHashtableEntry; typedef CompactHashtable SymbolCompactHashTable; @@ -476,12 +475,6 @@ typedef PaddedEnd PaddedObjectMonitor; static_field(SymbolTable, _shared_table, SymbolCompactHashTable) \ static_field(RehashableSymbolHashtable, _seed, juint) \ \ - /***************/ \ - /* StringTable */ \ - /***************/ \ - \ - static_field(StringTable, _the_table, StringTable*) \ - \ /********************/ \ /* CompactHashTable */ \ /********************/ \ @@ -1365,7 +1358,6 @@ typedef PaddedEnd PaddedObjectMonitor; declare_toplevel_type(BasicHashtable) \ declare_type(RehashableSymbolHashtable, BasicHashtable) \ declare_type(SymbolTable, SymbolHashtable) \ - declare_type(StringTable, StringHashtable) \ declare_type(Dictionary, KlassHashtable) \ declare_toplevel_type(BasicHashtableEntry) \ declare_type(IntptrHashtableEntry, BasicHashtableEntry) \ diff --git a/src/hotspot/share/runtime/vm_operations.hpp b/src/hotspot/share/runtime/vm_operations.hpp index 25bc9e72652..56cb4fae9b9 100644 --- a/src/hotspot/share/runtime/vm_operations.hpp +++ b/src/hotspot/share/runtime/vm_operations.hpp @@ -103,6 +103,7 @@ template(RotateGCLog) \ template(WhiteBoxOperation) \ template(ClassLoaderStatsOperation) \ + template(ClassLoaderHierarchyOperation) \ template(DumpHashtable) \ template(DumpTouchedMethods) \ template(MarkActiveNMethods) \ diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index 490aa3d40d5..ab19c5fa1cf 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "jvm.h" +#include "classfile/classLoaderHierarchyDCmd.hpp" #include "classfile/classLoaderStats.hpp" #include "classfile/compactHashtable.hpp" #include "compiler/compileBroker.hpp" @@ -101,6 +102,7 @@ void DCmdRegistrant::register_dcmds(){ #endif // INCLUDE_JVMTI DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); diff --git a/src/hotspot/share/utilities/concurrentHashTable.hpp b/src/hotspot/share/utilities/concurrentHashTable.hpp index 545f8e73dfe..6d5ab1c42fd 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.hpp @@ -484,6 +484,9 @@ class ConcurrentHashTable : public CHeapObj { void statistics_to(Thread* thread, VALUE_SIZE_FUNC& vs_f, outputStream* st, const char* table_name); + // Moves all nodes from this table to to_cht + bool try_move_nodes_to(Thread* thread, ConcurrentHashTable* to_cht); + // This is a Curiously Recurring Template Pattern (CRPT) interface for the // specialization. struct BaseConfig { diff --git a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp index 089cd79c5e7..71487d8234e 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp @@ -293,7 +293,7 @@ template inline void ConcurrentHashTable:: write_synchonize_on_visible_epoch(Thread* thread) { - assert(_resize_lock->owned_by_self(), "Re-size lock not held"); + assert(_resize_lock_owner == thread, "Re-size lock not held"); OrderAccess::fence(); // Prevent below load from floating up. // If no reader saw this version we can skip write_synchronize. if (OrderAccess::load_acquire(&_invisible_epoch) == thread) { @@ -488,7 +488,7 @@ inline void ConcurrentHashTable:: { // Here we have resize lock so table is SMR safe, and there is no new // table. Can do this in parallel if we want. - assert(_resize_lock->owned_by_self(), "Re-size lock not held"); + assert(_resize_lock_owner == thread, "Re-size lock not held"); Node* ndel[BULK_DELETE_LIMIT]; InternalTable* table = get_table(); assert(start_idx < stop_idx, "Must be"); @@ -500,9 +500,9 @@ inline void ConcurrentHashTable:: // own read-side. GlobalCounter::critical_section_begin(thread); for (size_t bucket_it = start_idx; bucket_it < stop_idx; bucket_it++) { - Bucket* bucket = _table->get_bucket(bucket_it); + Bucket* bucket = table->get_bucket(bucket_it); Bucket* prefetch_bucket = (bucket_it+1) < stop_idx ? - _table->get_bucket(bucket_it+1) : NULL; + table->get_bucket(bucket_it+1) : NULL; if (!HaveDeletables::value, EVALUATE_FUNC>:: have_deletable(bucket, eval_f, prefetch_bucket)) { @@ -695,17 +695,13 @@ inline bool ConcurrentHashTable:: if (!try_resize_lock(thread)) { return false; } - - assert(_resize_lock->owned_by_self(), "Re-size lock not held"); - + assert(_resize_lock_owner == thread, "Re-size lock not held"); if (_table->_log2_size == _log2_start_size || _table->_log2_size <= log2_size) { unlock_resize_lock(thread); return false; } - _new_table = new InternalTable(_table->_log2_size - 1); - return true; } @@ -713,8 +709,7 @@ template inline void ConcurrentHashTable:: internal_shrink_epilog(Thread* thread) { - assert(_resize_lock->owned_by_self(), "Re-size lock not held"); - assert(_resize_lock_owner, "Should be locked"); + assert(_resize_lock_owner == thread, "Re-size lock not held"); InternalTable* old_table = set_table_from_new(); _size_limit_reached = false; @@ -771,14 +766,13 @@ inline bool ConcurrentHashTable:: internal_shrink(Thread* thread, size_t log2_size) { if (!internal_shrink_prolog(thread, log2_size)) { - assert(!_resize_lock->owned_by_self(), "Re-size lock held"); + assert(_resize_lock_owner != thread, "Re-size lock held"); return false; } - assert(_resize_lock->owned_by_self(), "Re-size lock not held"); assert(_resize_lock_owner == thread, "Should be locked by me"); internal_shrink_range(thread, 0, _new_table->_size); internal_shrink_epilog(thread); - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); + assert(_resize_lock_owner != thread, "Re-size lock held"); return true; } @@ -815,8 +809,7 @@ template inline void ConcurrentHashTable:: internal_grow_epilog(Thread* thread) { - assert(_resize_lock->owned_by_self(), "Re-size lock not held"); - assert(_resize_lock_owner, "Should be locked"); + assert(_resize_lock_owner == thread, "Should be locked"); InternalTable* old_table = set_table_from_new(); unlock_resize_lock(thread); @@ -835,14 +828,13 @@ inline bool ConcurrentHashTable:: internal_grow(Thread* thread, size_t log2_size) { if (!internal_grow_prolog(thread, log2_size)) { - assert(!_resize_lock->owned_by_self(), "Re-size lock held"); + assert(_resize_lock_owner != thread, "Re-size lock held"); return false; } - assert(_resize_lock->owned_by_self(), "Re-size lock not held"); assert(_resize_lock_owner == thread, "Should be locked by me"); internal_grow_range(thread, 0, _table->_size); internal_grow_epilog(thread); - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); + assert(_resize_lock_owner != thread, "Re-size lock held"); return true; } @@ -955,15 +947,13 @@ template inline void ConcurrentHashTable:: do_scan_locked(Thread* thread, FUNC& scan_f) { - assert(_resize_lock->owned_by_self() || - (thread->is_VM_thread() && SafepointSynchronize::is_at_safepoint()), - "Re-size lock not held or not VMThread at safepoint"); + assert(_resize_lock_owner == thread, "Re-size lock not held"); // We can do a critical section over the entire loop but that would block // updates for a long time. Instead we choose to block resizes. InternalTable* table = get_table(); - for (size_t bucket_it = 0; bucket_it < _table->_size; bucket_it++) { + for (size_t bucket_it = 0; bucket_it < table->_size; bucket_it++) { ScopedCS cs(thread, this); - if (!visit_nodes(_table->get_bucket(bucket_it), scan_f)) { + if (!visit_nodes(table->get_bucket(bucket_it), scan_f)) { break; /* ends critical section */ } } /* ends critical section */ @@ -1094,17 +1084,11 @@ template inline bool ConcurrentHashTable:: try_scan(Thread* thread, SCAN_FUNC& scan_f) { - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); - bool vm_and_safepoint = thread->is_VM_thread() && - SafepointSynchronize::is_at_safepoint(); - if (!vm_and_safepoint && !try_resize_lock(thread)) { + if (!try_resize_lock(thread)) { return false; } do_scan_locked(thread, scan_f); - if (!vm_and_safepoint) { - unlock_resize_lock(thread); - } - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); + unlock_resize_lock(thread); return true; } @@ -1113,11 +1097,11 @@ template inline void ConcurrentHashTable:: do_scan(Thread* thread, SCAN_FUNC& scan_f) { - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); + assert(_resize_lock_owner != thread, "Re-size lock held"); lock_resize_lock(thread); do_scan_locked(thread, scan_f); unlock_resize_lock(thread); - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); + assert(_resize_lock_owner != thread, "Re-size lock held"); } template @@ -1126,12 +1110,11 @@ inline bool ConcurrentHashTable:: try_bulk_delete(Thread* thread, EVALUATE_FUNC& eval_f, DELETE_FUNC& del_f) { if (!try_resize_lock(thread)) { - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); return false; } do_bulk_delete_locked(thread, eval_f, del_f); unlock_resize_lock(thread); - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); + assert(_resize_lock_owner != thread, "Re-size lock held"); return true; } @@ -1140,11 +1123,9 @@ template inline void ConcurrentHashTable:: bulk_delete(Thread* thread, EVALUATE_FUNC& eval_f, DELETE_FUNC& del_f) { - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); lock_resize_lock(thread); do_bulk_delete_locked(thread, eval_f, del_f); unlock_resize_lock(thread); - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); } template @@ -1155,17 +1136,16 @@ inline void ConcurrentHashTable:: { NumberSeq summary; size_t literal_bytes = 0; - if ((thread->is_VM_thread() && !SafepointSynchronize::is_at_safepoint()) || - (!thread->is_VM_thread() && !try_resize_lock(thread))) { + if (!try_resize_lock(thread)) { st->print_cr("statistics unavailable at this moment"); return; } InternalTable* table = get_table(); - for (size_t bucket_it = 0; bucket_it < _table->_size; bucket_it++) { + for (size_t bucket_it = 0; bucket_it < table->_size; bucket_it++) { ScopedCS cs(thread, this); size_t count = 0; - Bucket* bucket = _table->get_bucket(bucket_it); + Bucket* bucket = table->get_bucket(bucket_it); if (bucket->have_redirect() || bucket->is_locked()) { continue; } @@ -1208,9 +1188,37 @@ inline void ConcurrentHashTable:: st->print_cr("Std. dev. of bucket size: %9.3f", summary.sd()); st->print_cr("Maximum bucket size : %9" PRIuPTR, (size_t)summary.maximum()); - if (!thread->is_VM_thread()) { - unlock_resize_lock(thread); + unlock_resize_lock(thread); +} + +template +inline bool ConcurrentHashTable:: + try_move_nodes_to(Thread* thread, ConcurrentHashTable* to_cht) +{ + if (!try_resize_lock(thread)) { + return false; } + assert(_new_table == NULL, "Must be NULL"); + for (size_t bucket_it = 0; bucket_it < _table->_size; bucket_it++) { + Bucket* bucket = _table->get_bucket(bucket_it); + assert(!bucket->have_redirect() && !bucket->is_locked(), "Table must be uncontended"); + while (bucket->first() != NULL) { + Node* move_node = bucket->first(); + bool ok = bucket->cas_first(move_node->next(), move_node); + assert(ok, "Uncontended cas must work"); + bool dead_hash = false; + size_t insert_hash = CONFIG::get_hash(*move_node->value(), &dead_hash); + if (!dead_hash) { + Bucket* insert_bucket = to_cht->get_bucket(insert_hash); + assert(!bucket->have_redirect() && !bucket->is_locked(), "Not bit should be present"); + move_node->set_next(insert_bucket->first()); + ok = insert_bucket->cas_first(move_node, insert_bucket->first()); + assert(ok, "Uncontended cas must work"); + } + } + } + unlock_resize_lock(thread); + return true; } #endif // include guard diff --git a/src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp b/src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp index 8a1bc40d37b..cfee9fb7e22 100644 --- a/src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp +++ b/src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_UTILITIES_CONCURRENT_HASH_TABLE_TASKS_INLINE_HPP #define SHARE_UTILITIES_CONCURRENT_HASH_TABLE_TASKS_INLINE_HPP +#include "utilities/globalDefinitions.hpp" #include "utilities/concurrentHashTable.inline.hpp" // This inline file contains BulkDeleteTask and GrowTasks which are both bucket @@ -63,6 +64,7 @@ class ConcurrentHashTable::BucketsOperation { // Calculate starting values. void setup() { _size_log2 = _cht->_table->_log2_size; + _task_size_log2 = MIN2(_task_size_log2, _size_log2); size_t tmp = _size_log2 > _task_size_log2 ? _size_log2 - _task_size_log2 : 0; _stop_task = (((size_t)1) << tmp); diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index 088316591ea..2dccbc1fe54 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -424,8 +424,8 @@ const int max_method_code_size = 64*K - 1; // JVM spec, 2nd ed. section 4.8.1 ( //---------------------------------------------------------------------------------------------------- // Default and minimum StringTableSize values -const int defaultStringTableSize = NOT_LP64(1009) LP64_ONLY(60013); -const int minimumStringTableSize = 1009; +const int defaultStringTableSize = NOT_LP64(1024) LP64_ONLY(65536); +const int minimumStringTableSize = 128; const int defaultSymbolTableSize = 20011; const int minimumSymbolTableSize = 1009; diff --git a/src/java.base/aix/native/libjsig/jsig.c b/src/java.base/aix/native/libjsig/jsig.c deleted file mode 100644 index 8914e2881a9..00000000000 --- a/src/java.base/aix/native/libjsig/jsig.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - * - */ - -/* CopyrightVersion 1.2 */ - -/* This is a special library that should be loaded before libc & - * libthread to interpose the signal handler installation functions: - * sigaction(), signal(), sigset(). - * Used for signal-chaining. See RFE 4381843. - */ - -#include -#include -#include -#include -#include -#include -#include "jni.h" - -#define bool int -#define true 1 -#define false 0 - -static struct sigaction sact[NSIG]; /* saved signal handlers */ -static sigset_t jvmsigs; /* Signals used by jvm. */ - -/* Used to synchronize the installation of signal handlers. */ -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; -static pthread_t tid = 0; - -typedef void (*sa_handler_t)(int); -typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); -// signal_t is already defined on AIX. -typedef sa_handler_t (*signal_like_function_t)(int, sa_handler_t); -typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *); - -static signal_like_function_t os_signal = 0; /* os's version of signal()/sigset() */ -static sigaction_t os_sigaction = 0; /* os's version of sigaction() */ - -static bool jvm_signal_installing = false; -static bool jvm_signal_installed = false; - -static void signal_lock() { - pthread_mutex_lock(&mutex); - /* When the jvm is installing its set of signal handlers, threads - * other than the jvm thread should wait. */ - if (jvm_signal_installing) { - if (tid != pthread_self()) { - pthread_cond_wait(&cond, &mutex); - } - } -} - -static void signal_unlock() { - pthread_mutex_unlock(&mutex); -} - -static sa_handler_t call_os_signal(int sig, sa_handler_t disp, - bool is_sigset) { - if (os_signal == NULL) { - if (!is_sigset) { - // Aix: call functions directly instead of dlsym'ing them. - os_signal = signal; - } else { - // Aix: call functions directly instead of dlsym'ing them. - os_signal = sigset; - } - if (os_signal == NULL) { - printf("%s\n", dlerror()); - exit(0); - } - } - return (*os_signal)(sig, disp); -} - -static void save_signal_handler(int sig, sa_handler_t disp) { - sigset_t set; - sact[sig].sa_handler = disp; - sigemptyset(&set); - sact[sig].sa_mask = set; - sact[sig].sa_flags = 0; -} - -static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) { - sa_handler_t oldhandler; - bool sigused; - - signal_lock(); - - sigused = sigismember(&jvmsigs, sig); - if (jvm_signal_installed && sigused) { - /* jvm has installed its signal handler for this signal. */ - /* Save the handler. Don't really install it. */ - oldhandler = sact[sig].sa_handler; - save_signal_handler(sig, disp); - - signal_unlock(); - return oldhandler; - } else if (jvm_signal_installing) { - /* jvm is installing its signal handlers. Install the new - * handlers and save the old ones. jvm uses sigaction(). - * Leave the piece here just in case. */ - oldhandler = call_os_signal(sig, disp, is_sigset); - save_signal_handler(sig, oldhandler); - - /* Record the signals used by jvm */ - sigaddset(&jvmsigs, sig); - - signal_unlock(); - return oldhandler; - } else { - /* jvm has no relation with this signal (yet). Install the - * the handler. */ - oldhandler = call_os_signal(sig, disp, is_sigset); - - signal_unlock(); - return oldhandler; - } -} - -JNIEXPORT sa_handler_t JNICALL -signal(int sig, sa_handler_t disp) { - return set_signal(sig, disp, false); -} - -JNIEXPORT sa_handler_t JNICALL -sigset(int sig, sa_handler_t disp) { - return set_signal(sig, disp, true); -} - -static int call_os_sigaction(int sig, const struct sigaction *act, - struct sigaction *oact) { - if (os_sigaction == NULL) { - // Aix: call functions directly instead of dlsym'ing them. - os_sigaction = sigaction; - if (os_sigaction == NULL) { - printf("%s\n", dlerror()); - exit(0); - } - } - return (*os_sigaction)(sig, act, oact); -} - -JNIEXPORT int JNICALL -sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { - int res; - bool sigused; - struct sigaction oldAct; - - signal_lock(); - - sigused = sigismember(&jvmsigs, sig); - if (jvm_signal_installed && sigused) { - /* jvm has installed its signal handler for this signal. */ - /* Save the handler. Don't really install it. */ - if (oact != NULL) { - *oact = sact[sig]; - } - if (act != NULL) { - sact[sig] = *act; - } - - signal_unlock(); - return 0; - } else if (jvm_signal_installing) { - /* jvm is installing its signal handlers. Install the new - * handlers and save the old ones. */ - res = call_os_sigaction(sig, act, &oldAct); - sact[sig] = oldAct; - if (oact != NULL) { - *oact = oldAct; - } - - /* Record the signals used by jvm. */ - sigaddset(&jvmsigs, sig); - - signal_unlock(); - return res; - } else { - /* jvm has no relation with this signal (yet). Install the - * the handler. */ - res = call_os_sigaction(sig, act, oact); - - signal_unlock(); - return res; - } -} - -/* The three functions for the jvm to call into. */ -JNIEXPORT void JNICALL -JVM_begin_signal_setting() { - signal_lock(); - sigemptyset(&jvmsigs); - jvm_signal_installing = true; - tid = pthread_self(); - signal_unlock(); -} - -JNIEXPORT void JNICALL -JVM_end_signal_setting() { - signal_lock(); - jvm_signal_installed = true; - jvm_signal_installing = false; - pthread_cond_broadcast(&cond); - signal_unlock(); -} - -JNIEXPORT struct sigaction * JNICALL -JVM_get_signal_action(int sig) { - /* Does race condition make sense here? */ - if (sigismember(&jvmsigs, sig)) { - return &sact[sig]; - } - return NULL; -} diff --git a/src/java.base/share/classes/java/lang/Object.java b/src/java.base/share/classes/java/lang/Object.java index 2e031553d5b..0ccdc6b738c 100644 --- a/src/java.base/share/classes/java/lang/Object.java +++ b/src/java.base/share/classes/java/lang/Object.java @@ -333,12 +333,12 @@ public class Object { * by being notified or interrupted, or until a * certain amount of real time has elapsed. *

- * In all respects, this method behaves as if {@code wait(timeout, 0)} + * In all respects, this method behaves as if {@code wait(timeoutMillis, 0)} * had been called. See the specification of the {@link #wait(long, int)} method * for details. * - * @param timeout the maximum time to wait, in milliseconds - * @throws IllegalArgumentException if the value of {@code timeout} is negative + * @param timeoutMillis the maximum time to wait, in milliseconds + * @throws IllegalArgumentException if {@code timeoutMillis} is negative * @throws IllegalMonitorStateException if the current thread is not * the owner of the object's monitor * @throws InterruptedException if any thread interrupted the current thread before or @@ -349,7 +349,7 @@ public class Object { * @see #wait() * @see #wait(long, int) */ - public final native void wait(long timeout) throws InterruptedException; + public final native void wait(long timeoutMillis) throws InterruptedException; /** * Causes the current thread to wait until it is awakened, typically @@ -378,7 +378,7 @@ public class Object { * thread T. *

  • The specified amount of real time has elapsed, more or less. * The amount of real time, in nanoseconds, is given by the expression - * {@code 1000000 * timeout + nanos}. If {@code timeout} and {@code nanos} + * {@code 1000000 * timeoutMillis + nanos}. If {@code timeoutMillis} and {@code nanos} * are both zero, then real time is not taken into consideration and the * thread waits until awakened by one of the other causes. *
  • Thread T is awakened spuriously. (See below.) @@ -423,17 +423,17 @@ public class Object { *
    {@code
          *     synchronized (obj) {
          *         while ( and ) {
    -     *             long timeout = ... ; // recompute timeout values
    +     *             long timeoutMillis = ... ; // recompute timeout values
          *             int nanos = ... ;
    -     *             obj.wait(timeout, nanos);
    +     *             obj.wait(timeoutMillis, nanos);
          *         }
          *         ... // Perform action appropriate to condition or timeout
          *     }
          * }
    * - * @param timeout the maximum time to wait, in milliseconds + * @param timeoutMillis the maximum time to wait, in milliseconds * @param nanos additional time, in nanoseconds, in the range range 0-999999 inclusive - * @throws IllegalArgumentException if the value of {@code timeout} is negative, + * @throws IllegalArgumentException if {@code timeoutMillis} is negative, * or if the value of {@code nanos} is out of range * @throws IllegalMonitorStateException if the current thread is not * the owner of the object's monitor @@ -445,9 +445,9 @@ public class Object { * @see #wait() * @see #wait(long) */ - public final void wait(long timeout, int nanos) throws InterruptedException { - if (timeout < 0) { - throw new IllegalArgumentException("timeout value is negative"); + public final void wait(long timeoutMillis, int nanos) throws InterruptedException { + if (timeoutMillis < 0) { + throw new IllegalArgumentException("timeoutMillis value is negative"); } if (nanos < 0 || nanos > 999999) { @@ -456,10 +456,10 @@ public class Object { } if (nanos > 0) { - timeout++; + timeoutMillis++; } - wait(timeout); + wait(timeoutMillis); } /** diff --git a/src/java.base/share/classes/java/nio/channels/SelectionKey.java b/src/java.base/share/classes/java/nio/channels/SelectionKey.java index ad08fe43822..ceb7f575c4d 100644 --- a/src/java.base/share/classes/java/nio/channels/SelectionKey.java +++ b/src/java.base/share/classes/java/nio/channels/SelectionKey.java @@ -189,6 +189,83 @@ public abstract class SelectionKey { */ public abstract SelectionKey interestOps(int ops); + /** + * Atomically sets this key's interest set to the bitwise union ("or") of + * the existing interest set and the given value. This method is guaranteed + * to be atomic with respect to other concurrent calls to this method or to + * {@link #interestOpsAnd(int)}. + * + *

    This method may be invoked at any time. If this method is invoked + * while a selection operation is in progress then it has no effect upon + * that operation; the change to the key's interest set will be seen by the + * next selection operation. + * + * @implSpec The default implementation synchronizes on this key and invokes + * {@code interestOps()} and {@code interestOps(int)} to retrieve and set + * this key's interest set. + * + * @param ops The interest set to apply + * + * @return The previous interest set + * + * @throws IllegalArgumentException + * If a bit in the set does not correspond to an operation that + * is supported by this key's channel, that is, if + * {@code (ops & ~channel().validOps()) != 0} + * + * @throws CancelledKeyException + * If this key has been cancelled + * + * @since 11 + */ + public int interestOpsOr(int ops) { + synchronized (this) { + int oldVal = interestOps(); + interestOps(oldVal | ops); + return oldVal; + } + } + + /** + * Atomically sets this key's interest set to the bitwise intersection ("and") + * of the existing interest set and the given value. This method is guaranteed + * to be atomic with respect to other concurrent calls to this method or to + * {@link #interestOpsOr(int)}. + * + *

    This method may be invoked at any time. If this method is invoked + * while a selection operation is in progress then it has no effect upon + * that operation; the change to the key's interest set will be seen by the + * next selection operation. + * + * @apiNote Unlike the {@code interestOps(int)} and {@code interestOpsOr(int)} + * methods, this method does not throw {@code IllegalArgumentException} when + * invoked with bits in the interest set that do not correspond to an + * operation that is supported by this key's channel. This is to allow + * operation bits in the interest set to be cleared using bitwise complement + * values, e.g., {@code interestOpsAnd(~SelectionKey.OP_READ)} will remove + * the {@code OP_READ} from the interest set without affecting other bits. + * + * @implSpec The default implementation synchronizes on this key and invokes + * {@code interestOps()} and {@code interestOps(int)} to retrieve and set + * this key's interest set. + * + * @param ops The interest set to apply + * + * @return The previous interest set + * + * @throws CancelledKeyException + * If this key has been cancelled + * + * @since 11 + */ + public int interestOpsAnd(int ops) { + synchronized (this) { + int oldVal = interestOps(); + interestOps(oldVal & ops); + return oldVal; + } + } + /** * Retrieves this key's ready-operation set. * diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index 41ac57fa3cf..65fb4a5f2bf 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -1391,8 +1391,9 @@ public final class Files { * specific exception) * @throws DirectoryNotEmptyException * the {@code REPLACE_EXISTING} option is specified but the file - * cannot be replaced because it is a non-empty directory - * (optional specific exception) + * cannot be replaced because it is a non-empty directory, or the + * source is a non-empty directory containing entries that would + * be required to be moved (optional specific exceptions) * @throws AtomicMoveNotSupportedException * if the options array contains the {@code ATOMIC_MOVE} option but * the file cannot be moved as an atomic file system operation. diff --git a/src/java.base/share/classes/java/time/Clock.java b/src/java.base/share/classes/java/time/Clock.java index a372251f983..37e723ec7bf 100644 --- a/src/java.base/share/classes/java/time/Clock.java +++ b/src/java.base/share/classes/java/time/Clock.java @@ -586,7 +586,7 @@ public abstract class Clock { * This is typically used for testing. */ static final class FixedClock extends Clock implements Serializable { - private static final long serialVersionUID = 7430389292664866958L; + private static final long serialVersionUID = 7430389292664866958L; private final Instant instant; private final ZoneId zone; @@ -636,7 +636,7 @@ public abstract class Clock { * Implementation of a clock that adds an offset to an underlying clock. */ static final class OffsetClock extends Clock implements Serializable { - private static final long serialVersionUID = 2007484719125426256L; + private static final long serialVersionUID = 2007484719125426256L; private final Clock baseClock; private final Duration offset; diff --git a/src/java.base/share/classes/java/time/Duration.java b/src/java.base/share/classes/java/time/Duration.java index cf44f93978d..c446bf338ac 100644 --- a/src/java.base/share/classes/java/time/Duration.java +++ b/src/java.base/share/classes/java/time/Duration.java @@ -231,7 +231,7 @@ public final class Duration * This method allows an arbitrary number of nanoseconds to be passed in. * The factory will alter the values of the second and nanosecond in order * to ensure that the stored nanosecond is in the range 0 to 999,999,999. - * For example, the following will result in the exactly the same duration: + * For example, the following will result in exactly the same duration: *

          *  Duration.ofSeconds(3, 1);
          *  Duration.ofSeconds(4, -999_999_999);
    @@ -1357,12 +1357,14 @@ public final class Duration
          * Truncating the duration returns a copy of the original with conceptual fields
          * smaller than the specified unit set to zero.
          * For example, truncating with the {@link ChronoUnit#MINUTES MINUTES} unit will
    -     * round down to the nearest minute, setting the seconds and nanoseconds to zero.
    +     * round down towards zero to the nearest minute, setting the seconds and
    +     * nanoseconds to zero.
          * 

    * The unit must have a {@linkplain TemporalUnit#getDuration() duration} * that divides into the length of a standard day without remainder. - * This includes all supplied time units on {@link ChronoUnit} and - * {@link ChronoUnit#DAYS DAYS}. Other ChronoUnits throw an exception. + * This includes all + * {@linkplain ChronoUnit#isTimeBased() time-based units on {@code ChronoUnit}} + * and {@link ChronoUnit#DAYS DAYS}. Other ChronoUnits throw an exception. *

    * This instance is immutable and unaffected by this method call. * @@ -1388,7 +1390,7 @@ public final class Duration throw new UnsupportedTemporalTypeException("Unit must divide into a standard day without remainder"); } long nod = (seconds % LocalTime.SECONDS_PER_DAY) * LocalTime.NANOS_PER_SECOND + nanos; - long result = (nod / dur) * dur ; + long result = (nod / dur) * dur; return plusNanos(result - nod); } diff --git a/src/java.base/share/classes/java/time/Instant.java b/src/java.base/share/classes/java/time/Instant.java index 1aefddfffce..0aafa49fd40 100644 --- a/src/java.base/share/classes/java/time/Instant.java +++ b/src/java.base/share/classes/java/time/Instant.java @@ -311,7 +311,7 @@ public final class Instant * This method allows an arbitrary number of nanoseconds to be passed in. * The factory will alter the values of the second and nanosecond in order * to ensure that the stored nanosecond is in the range 0 to 999,999,999. - * For example, the following will result in the exactly the same instant: + * For example, the following will result in exactly the same instant: *

          *  Instant.ofEpochSecond(3, 1);
          *  Instant.ofEpochSecond(4, -999_999_999);
    @@ -757,7 +757,7 @@ public final class Instant
                 throw new UnsupportedTemporalTypeException("Unit must divide into a standard day without remainder");
             }
             long nod = (seconds % LocalTime.SECONDS_PER_DAY) * LocalTime.NANOS_PER_SECOND + nanos;
    -        long result = Math.floorDiv(nod, dur) * dur ;
    +        long result = Math.floorDiv(nod, dur) * dur;
             return plusNanos(result - nod);
         }
     
    diff --git a/src/java.base/share/classes/java/time/LocalTime.java b/src/java.base/share/classes/java/time/LocalTime.java
    index 76b5fed0367..80241339c35 100644
    --- a/src/java.base/share/classes/java/time/LocalTime.java
    +++ b/src/java.base/share/classes/java/time/LocalTime.java
    @@ -356,14 +356,14 @@ public final class LocalTime
          * @return the local time, not null
          * @since 9
          */
    -     public static LocalTime ofInstant(Instant instant, ZoneId zone) {
    -         Objects.requireNonNull(instant, "instant");
    -         Objects.requireNonNull(zone, "zone");
    -         ZoneOffset offset = zone.getRules().getOffset(instant);
    -         long localSecond = instant.getEpochSecond() + offset.getTotalSeconds();
    -         int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY);
    -         return ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + instant.getNano());
    -     }
    +    public static LocalTime ofInstant(Instant instant, ZoneId zone) {
    +        Objects.requireNonNull(instant, "instant");
    +        Objects.requireNonNull(zone, "zone");
    +        ZoneOffset offset = zone.getRules().getOffset(instant);
    +        long localSecond = instant.getEpochSecond() + offset.getTotalSeconds();
    +        int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY);
    +        return ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + instant.getNano());
    +    }
     
         //-----------------------------------------------------------------------
         /**
    diff --git a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java
    index 26513379b43..3d236ff4ccd 100644
    --- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java
    +++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java
    @@ -110,7 +110,7 @@ import java.util.Objects;
      *        int year = date.get(ChronoField.YEAR);
      *        System.out.printf("  Today is %s %s %d-%s-%d%n", date.getChronology().getID(),
      *                dow, day, month, year);
    -
    + *
      *        // Print today's date and the last day of the year
      *        ChronoLocalDate now1 = Chronology.of("Hijrah").dateNow();
      *        ChronoLocalDate first = now1.with(ChronoField.DAY_OF_MONTH, 1)
    diff --git a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java
    index d8411961697..51637c2b5d8 100644
    --- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java
    +++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java
    @@ -201,7 +201,7 @@ public interface ChronoLocalDateTime
          *
          * @return the date part of this date-time, not null
          */
    -    D toLocalDate() ;
    +    D toLocalDate();
     
         /**
          * Gets the local time part of this date-time.
    diff --git a/src/java.base/share/classes/java/time/chrono/Chronology.java b/src/java.base/share/classes/java/time/chrono/Chronology.java
    index d1c3919cb63..f35f9b95c3e 100644
    --- a/src/java.base/share/classes/java/time/chrono/Chronology.java
    +++ b/src/java.base/share/classes/java/time/chrono/Chronology.java
    @@ -736,8 +736,8 @@ public interface Chronology extends Comparable {
          * @throws DateTimeException if any of the values are out of range
          * @since 9
          */
    -     public default long epochSecond(int prolepticYear, int month, int dayOfMonth,
    -                                     int hour, int minute, int second, ZoneOffset zoneOffset) {
    +    public default long epochSecond(int prolepticYear, int month, int dayOfMonth,
    +                                    int hour, int minute, int second, ZoneOffset zoneOffset) {
             Objects.requireNonNull(zoneOffset, "zoneOffset");
             HOUR_OF_DAY.checkValidValue(hour);
             MINUTE_OF_HOUR.checkValidValue(minute);
    @@ -765,8 +765,8 @@ public interface Chronology extends Comparable {
          * @throws DateTimeException if any of the values are out of range
          * @since 9
          */
    -     public default long epochSecond(Era era, int yearOfEra, int month, int dayOfMonth,
    -                                     int hour, int minute, int second, ZoneOffset zoneOffset) {
    +    public default long epochSecond(Era era, int yearOfEra, int month, int dayOfMonth,
    +                                    int hour, int minute, int second, ZoneOffset zoneOffset) {
             Objects.requireNonNull(era, "era");
             return epochSecond(prolepticYear(era, yearOfEra), month, dayOfMonth, hour, minute, second, zoneOffset);
         }
    diff --git a/src/java.base/share/classes/java/time/chrono/IsoChronology.java b/src/java.base/share/classes/java/time/chrono/IsoChronology.java
    index 4919b3d7d3a..18d73689569 100644
    --- a/src/java.base/share/classes/java/time/chrono/IsoChronology.java
    +++ b/src/java.base/share/classes/java/time/chrono/IsoChronology.java
    @@ -287,9 +287,9 @@ public final class IsoChronology extends AbstractChronology implements Serializa
          *         or if the day-of-month is invalid for the month-of-year
          * @since 9
          */
    -     @Override
    -     public long epochSecond(int prolepticYear, int month, int dayOfMonth,
    -                             int hour, int minute, int second, ZoneOffset zoneOffset) {
    +    @Override
    +    public long epochSecond(int prolepticYear, int month, int dayOfMonth,
    +                            int hour, int minute, int second, ZoneOffset zoneOffset) {
             YEAR.checkValidValue(prolepticYear);
             MONTH_OF_YEAR.checkValidValue(month);
             DAY_OF_MONTH.checkValidValue(dayOfMonth);
    diff --git a/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java b/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java
    index 4478c4c7de1..8cd67a05908 100644
    --- a/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java
    +++ b/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java
    @@ -459,38 +459,38 @@ public final class JapaneseChronology extends AbstractChronology implements Seri
             return era.getPrivateEra().getSinceDate().getYear() + yearOfEra - 1;
         }
     
    -     private ChronoLocalDate resolveYMD(JapaneseEra era, int yoe, Map fieldValues, ResolverStyle resolverStyle) {
    -         fieldValues.remove(ERA);
    -         fieldValues.remove(YEAR_OF_ERA);
    -         if (resolverStyle == ResolverStyle.LENIENT) {
    -             int y = prolepticYearLenient(era, yoe);
    -             long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
    -             long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1);
    -             return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS);
    -         }
    -         int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
    -         int dom = range(DAY_OF_MONTH).checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH);
    -         if (resolverStyle == ResolverStyle.SMART) {  // previous valid
    -             if (yoe < 1) {
    -                 throw new DateTimeException("Invalid YearOfEra: " + yoe);
    -             }
    -             int y = prolepticYearLenient(era, yoe);
    -             JapaneseDate result;
    -             try {
    -                 result = date(y, moy, dom);
    -             } catch (DateTimeException ex) {
    -                 result = date(y, moy, 1).with(TemporalAdjusters.lastDayOfMonth());
    -             }
    -             // handle the era being changed
    -             // only allow if the new date is in the same Jan-Dec as the era change
    -             // determine by ensuring either original yoe or result yoe is 1
    -             if (result.getEra() != era && result.get(YEAR_OF_ERA) > 1 && yoe > 1) {
    -                 throw new DateTimeException("Invalid YearOfEra for Era: " + era + " " + yoe);
    -             }
    -             return result;
    -         }
    -         return date(era, yoe, moy, dom);
    -     }
    +    private ChronoLocalDate resolveYMD(JapaneseEra era, int yoe, Map fieldValues, ResolverStyle resolverStyle) {
    +        fieldValues.remove(ERA);
    +        fieldValues.remove(YEAR_OF_ERA);
    +        if (resolverStyle == ResolverStyle.LENIENT) {
    +            int y = prolepticYearLenient(era, yoe);
    +            long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
    +            long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1);
    +            return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS);
    +        }
    +        int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
    +        int dom = range(DAY_OF_MONTH).checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH);
    +        if (resolverStyle == ResolverStyle.SMART) {  // previous valid
    +            if (yoe < 1) {
    +                throw new DateTimeException("Invalid YearOfEra: " + yoe);
    +            }
    +            int y = prolepticYearLenient(era, yoe);
    +            JapaneseDate result;
    +            try {
    +                result = date(y, moy, dom);
    +            } catch (DateTimeException ex) {
    +                result = date(y, moy, 1).with(TemporalAdjusters.lastDayOfMonth());
    +            }
    +            // handle the era being changed
    +            // only allow if the new date is in the same Jan-Dec as the era change
    +            // determine by ensuring either original yoe or result yoe is 1
    +            if (result.getEra() != era && result.get(YEAR_OF_ERA) > 1 && yoe > 1) {
    +                throw new DateTimeException("Invalid YearOfEra for Era: " + era + " " + yoe);
    +            }
    +            return result;
    +        }
    +        return date(era, yoe, moy, dom);
    +    }
     
         private ChronoLocalDate resolveYD(JapaneseEra era, int yoe, Map  fieldValues, ResolverStyle resolverStyle) {
             fieldValues.remove(ERA);
    diff --git a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
    index 8e9437f2184..589792c18e2 100644
    --- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
    +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
    @@ -3049,7 +3049,7 @@ public final class DateTimeFormatterBuilder {
          * Prints and parses a numeric date-time field with optional padding.
          */
         static final class FractionPrinterParser extends NumberPrinterParser {
    -       private final boolean decimalPoint;
    +        private final boolean decimalPoint;
     
             /**
              * Constructor.
    diff --git a/src/java.base/share/classes/java/time/format/DecimalStyle.java b/src/java.base/share/classes/java/time/format/DecimalStyle.java
    index 73f3cb23160..989c1c19e48 100644
    --- a/src/java.base/share/classes/java/time/format/DecimalStyle.java
    +++ b/src/java.base/share/classes/java/time/format/DecimalStyle.java
    @@ -216,7 +216,6 @@ public final class DecimalStyle {
          *
          * @param zeroDigit  the character for zero
          * @return  a copy with a new character that represents zero, not null
    -
          */
         public DecimalStyle withZeroDigit(char zeroDigit) {
             if (zeroDigit == this.zeroDigit) {
    diff --git a/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java b/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java
    index 4014c23c083..03e618731fc 100644
    --- a/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java
    +++ b/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java
    @@ -119,7 +119,7 @@ import java.util.Collections;
      * Providers must ensure that once a rule has been seen by the application, the
      * rule must continue to be available.
      * 

    -* Providers are encouraged to implement a meaningful {@code toString} method. + * Providers are encouraged to implement a meaningful {@code toString} method. *

    * Many systems would like to update time-zone rules dynamically without stopping the JVM. * When examined in detail, this is a complex problem. diff --git a/src/java.base/share/classes/java/util/Formatter.java b/src/java.base/share/classes/java/util/Formatter.java index d61f2774df1..0fd1176b970 100644 --- a/src/java.base/share/classes/java/util/Formatter.java +++ b/src/java.base/share/classes/java/util/Formatter.java @@ -2914,7 +2914,7 @@ public final class Formatter implements Closeable, Flushable { a.append(System.lineSeparator()); break; case Conversion.PERCENT_SIGN: - a.append('%'); + print("%", l); break; default: assert false; diff --git a/src/java.base/share/classes/java/util/concurrent/TimeUnit.java b/src/java.base/share/classes/java/util/concurrent/TimeUnit.java index cbddf59c337..7942fb55816 100644 --- a/src/java.base/share/classes/java/util/concurrent/TimeUnit.java +++ b/src/java.base/share/classes/java/util/concurrent/TimeUnit.java @@ -35,6 +35,7 @@ package java.util.concurrent; +import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.Objects; @@ -191,6 +192,50 @@ public enum TimeUnit { } } + /** + * Converts the given time duration to this unit. + * + *

    For any TimeUnit {@code unit}, + * {@code unit.convert(Duration.ofNanos(n))} + * is equivalent to + * {@code unit.convert(n, NANOSECONDS)}, and + * {@code unit.convert(Duration.of(n, unit.toChronoUnit()))} + * is equivalent to {@code n} (in the absence of overflow). + * + * @param duration the time duration + * @return the converted duration in this unit, + * or {@code Long.MIN_VALUE} if conversion would negatively overflow, + * or {@code Long.MAX_VALUE} if it would positively overflow. + * @throws NullPointerException if {@code duration} is null + * @see Duration#of(long,TemporalUnit) + * @since 11 + */ + public long convert(Duration duration) { + long secs = duration.getSeconds(); + int nano = duration.getNano(); + if (secs < 0 && nano > 0) { + // use representation compatible with integer division + secs++; + nano -= SECOND_SCALE; + } + final long s, nanoVal; + // Optimize for the common case - NANOSECONDS without overflow + if (this == NANOSECONDS) + nanoVal = nano; + else if ((s = scale) < SECOND_SCALE) + nanoVal = nano / s; + else if (this == SECONDS) + return secs; + else + return secs / secRatio; + long val = secs * secRatio + nanoVal; + return ((secs < maxSecs && secs > -maxSecs) || + (secs == maxSecs && val > 0) || + (secs == -maxSecs && val < 0)) + ? val + : (secs > 0) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + /** * Equivalent to * {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}. @@ -221,10 +266,8 @@ public enum TimeUnit { */ public long toMicros(long duration) { long s, m; - if ((s = scale) == MICRO_SCALE) - return duration; - else if (s < MICRO_SCALE) - return duration / microRatio; + if ((s = scale) <= MICRO_SCALE) + return (s == MICRO_SCALE) ? duration : duration / microRatio; else if (duration > (m = maxMicros)) return Long.MAX_VALUE; else if (duration < -m) @@ -243,10 +286,8 @@ public enum TimeUnit { */ public long toMillis(long duration) { long s, m; - if ((s = scale) == MILLI_SCALE) - return duration; - else if (s < MILLI_SCALE) - return duration / milliRatio; + if ((s = scale) <= MILLI_SCALE) + return (s == MILLI_SCALE) ? duration : duration / milliRatio; else if (duration > (m = maxMillis)) return Long.MAX_VALUE; else if (duration < -m) @@ -265,10 +306,8 @@ public enum TimeUnit { */ public long toSeconds(long duration) { long s, m; - if ((s = scale) == SECOND_SCALE) - return duration; - else if (s < SECOND_SCALE) - return duration / secRatio; + if ((s = scale) <= SECOND_SCALE) + return (s == SECOND_SCALE) ? duration : duration / secRatio; else if (duration > (m = maxSecs)) return Long.MAX_VALUE; else if (duration < -m) diff --git a/src/java.base/share/classes/java/util/jar/JarFile.java b/src/java.base/share/classes/java/util/jar/JarFile.java index ec7fdf0f06a..5562611cfe4 100644 --- a/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/src/java.base/share/classes/java/util/jar/JarFile.java @@ -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 @@ -93,10 +93,14 @@ import java.util.zip.ZipFile; * argument. This assures that classes compatible with the major * version of the running JVM are loaded from multi-release jar files. * - *

    If the verify flag is on when opening a signed jar file, the content of - * the file is verified against its signature embedded inside the file. Please - * note that the verification process does not include validating the signer's - * certificate. A caller should inspect the return value of + *

    If the {@code verify} flag is on when opening a signed jar file, the content + * of the jar entry is verified against the signature embedded inside the manifest + * that is associated with its {@link JarEntry#getRealName() path name}. For a + * multi-release jar file, the content of a versioned entry is verfieid against + * its own signature and {@link JarEntry#getCodeSigners()} returns its own signers. + * + * Please note that the verification process does not include validating the + * signer's certificate. A caller should inspect the return value of * {@link JarEntry#getCodeSigners()} to further determine if the signature * can be trusted. * diff --git a/src/java.base/share/classes/java/util/jar/Manifest.java b/src/java.base/share/classes/java/util/jar/Manifest.java index 9ee93aa079f..ea73a1f65ac 100644 --- a/src/java.base/share/classes/java/util/jar/Manifest.java +++ b/src/java.base/share/classes/java/util/jar/Manifest.java @@ -393,7 +393,27 @@ public class Manifest implements Cloneable { off += n; total += n; pos = tpos; - if (c == '\n' || c == '\r') { + c = tbuf[tpos-1]; + if (c == '\n') { + break; + } + if (c == '\r') { + if (count == pos) { + // try to see if there is a trailing LF + fill(); + if (pos < count && tbuf[pos] == '\n') { + if (total < len) { + b[off++] = '\n'; + total++; + } else { + // we should always have big enough lbuf but + // just in case we don't, replace the last CR + // with LF. + b[off - 1] = '\n'; + } + pos++; + } + } break; } } diff --git a/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/src/java.base/share/classes/sun/launcher/LauncherHelper.java index 38f9e3a6784..4b10ca85b72 100644 --- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java +++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -502,12 +502,13 @@ public final class LauncherHelper { } // From src/share/bin/java.c: - // enum LaunchMode { LM_UNKNOWN = 0, LM_CLASS, LM_JAR, LM_MODULE } + // enum LaunchMode { LM_UNKNOWN = 0, LM_CLASS, LM_JAR, LM_MODULE, LM_SOURCE } private static final int LM_UNKNOWN = 0; private static final int LM_CLASS = 1; private static final int LM_JAR = 2; private static final int LM_MODULE = 3; + private static final int LM_SOURCE = 4; static void abort(Throwable t, String msgKey, Object... args) { if (msgKey != null) { @@ -538,13 +539,21 @@ public final class LauncherHelper { * * @return the application's main class */ + @SuppressWarnings("fallthrough") public static Class checkAndLoadMain(boolean printToStderr, int mode, String what) { initOutput(printToStderr); - Class mainClass = (mode == LM_MODULE) ? loadModuleMainClass(what) - : loadMainClass(mode, what); + Class mainClass = null; + switch (mode) { + case LM_MODULE: case LM_SOURCE: + mainClass = loadModuleMainClass(what); + break; + default: + mainClass = loadMainClass(mode, what); + break; + } // record the real main class for UI purposes // neither method above can return null, they will abort() diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher.properties b/src/java.base/share/classes/sun/launcher/resources/launcher.properties index 6cdde5aadb7..63e21860a09 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 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 @@ -25,13 +25,17 @@ # Translators please note do not translate the options themselves java.launcher.opt.header = Usage: {0} [options] [args...]\n\ -\ (to execute a class)\n or {0} [options] -jar [args...]\n\ +\ (to execute a class)\n\ +\ or {0} [options] -jar [args...]\n\ \ (to execute a jar file)\n\ \ or {0} [options] -m [/] [args...]\n\ \ {0} [options] --module [/] [args...]\n\ -\ (to execute the main class in a module)\n\n\ -\ Arguments following the main class, -jar , -m or --module\n\ -\ / are passed as the arguments to main class.\n\n\ +\ (to execute the main class in a module)\n\ +\ or {0} [options] [args]\n\ +\ (to execute a single source-file program)\n\n\ +\ Arguments following the main class, source file, -jar ,\n\ +\ -m or --module / are passed as the arguments to\n\ +\ main class.\n\n\ \ where options include:\n\n java.launcher.opt.vmselect =\ {0}\t to select the "{1}" VM\n @@ -114,7 +118,7 @@ java.launcher.opt.footer = \ \ -disable-@files\n\ \ prevent further argument file expansion\n\ \ --enable-preview\n\ -\ allow classes to depend on preview features of this release +\ allow classes to depend on preview features of this release\n\ \To specify an argument for a long option, you can use --= or\n\ \-- .\n @@ -176,7 +180,9 @@ java.launcher.X.usage=\n\ \ --patch-module =({0})*\n\ \ override or augment a module with classes and resources\n\ \ in JAR files or directories.\n\ -\ --disable-@files disable further argument file expansion\n\n\ +\ --disable-@files disable further argument file expansion\n\ +\ --source \n\ +\ set the version of the source in source-file mode.\n\n\ These extra options are subject to change without notice.\n # Translators please note do not translate the options themselves diff --git a/src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java b/src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java index 2f917c8d2e3..256c5194e04 100644 --- a/src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java @@ -25,6 +25,9 @@ package sun.nio.ch; +import java.lang.invoke.ConstantBootstraps; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; import java.nio.channels.CancelledKeyException; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; @@ -39,6 +42,13 @@ import java.nio.channels.spi.AbstractSelectionKey; public final class SelectionKeyImpl extends AbstractSelectionKey { + private static final VarHandle INTERESTOPS = + ConstantBootstraps.fieldVarHandle( + MethodHandles.lookup(), + "interestOps", + VarHandle.class, + SelectionKeyImpl.class, int.class); + private final SelChImpl channel; private final SelectorImpl selector; @@ -84,7 +94,35 @@ public final class SelectionKeyImpl @Override public SelectionKey interestOps(int ops) { ensureValid(); - return nioInterestOps(ops); + if ((ops & ~channel().validOps()) != 0) + throw new IllegalArgumentException(); + int oldOps = (int) INTERESTOPS.getAndSet(this, ops); + if (ops != oldOps) { + selector.setEventOps(this); + } + return this; + } + + @Override + public int interestOpsOr(int ops) { + ensureValid(); + if ((ops & ~channel().validOps()) != 0) + throw new IllegalArgumentException(); + int oldVal = (int) INTERESTOPS.getAndBitwiseOr(this, ops); + if (oldVal != (oldVal | ops)) { + selector.setEventOps(this); + } + return oldVal; + } + + @Override + public int interestOpsAnd(int ops) { + ensureValid(); + int oldVal = (int) INTERESTOPS.getAndBitwiseAnd(this, ops); + if (oldVal != (oldVal & ops)) { + selector.setEventOps(this); + } + return oldVal; } @Override diff --git a/src/java.base/share/native/launcher/main.c b/src/java.base/share/native/launcher/main.c index a477c80784b..b734fe2ba78 100644 --- a/src/java.base/share/native/launcher/main.c +++ b/src/java.base/share/native/launcher/main.c @@ -183,7 +183,7 @@ main(int argc, char **argv) } // Iterate the rest of command line for (i = 1; i < argc; i++) { - JLI_List argsInFile = JLI_PreprocessArg(argv[i]); + JLI_List argsInFile = JLI_PreprocessArg(argv[i], JNI_TRUE); if (NULL == argsInFile) { JLI_List_add(args, JLI_StringDup(argv[i])); } else { diff --git a/src/java.base/share/native/libjli/args.c b/src/java.base/share/native/libjli/args.c index 4de8f07b633..45954ef78bb 100644 --- a/src/java.base/share/native/libjli/args.c +++ b/src/java.base/share/native/libjli/args.c @@ -79,6 +79,11 @@ static size_t argsCount = 1; static jboolean stopExpansion = JNI_FALSE; static jboolean relaunch = JNI_FALSE; +/* + * Prototypes for internal functions. + */ +static jboolean expand(JLI_List args, const char *str, const char *var_name); + JNIEXPORT void JNICALL JLI_InitArgProcessing(jboolean hasJavaArgs, jboolean disableArgFile) { // No expansion for relaunch @@ -300,6 +305,8 @@ static JLI_List readArgFile(FILE *file) { ctx.state = FIND_NEXT; ctx.parts = JLI_List_new(4); + // initialize to avoid -Werror=maybe-uninitialized issues from gcc 7.3 onwards. + ctx.quote_char = '"'; /* arbitrarily pick 8, seems to be a reasonable number of arguments */ rv = JLI_List_new(8); @@ -376,9 +383,22 @@ static JLI_List expandArgFile(const char *arg) { return rv; } +/* + * expand a string into a list of words separated by whitespace. + */ +static JLI_List expandArg(const char *arg) { + JLI_List rv; + + /* arbitrarily pick 8, seems to be a reasonable number of arguments */ + rv = JLI_List_new(8); + + expand(rv, arg, NULL); + + return rv; +} + JNIEXPORT JLI_List JNICALL -JLI_PreprocessArg(const char *arg) -{ +JLI_PreprocessArg(const char *arg, jboolean expandSourceOpt) { JLI_List rv; if (firstAppArgIndex > 0) { @@ -392,6 +412,12 @@ JLI_PreprocessArg(const char *arg) return NULL; } + if (expandSourceOpt + && JLI_StrCCmp(arg, "--source") == 0 + && JLI_StrChr(arg, ' ') != NULL) { + return expandArg(arg); + } + if (arg[0] != '@') { checkArg(arg); return NULL; @@ -435,9 +461,6 @@ int isTerminalOpt(char *arg) { JNIEXPORT jboolean JNICALL JLI_AddArgsFromEnvVar(JLI_List args, const char *var_name) { char *env = getenv(var_name); - char *p, *arg; - char quote; - JLI_List argsInFile; if (firstAppArgIndex == 0) { // Not 'java', return @@ -453,44 +476,64 @@ JLI_AddArgsFromEnvVar(JLI_List args, const char *var_name) { } JLI_ReportMessage(ARG_INFO_ENVVAR, var_name, env); + return expand(args, env, var_name); +} + +/* + * Expand a string into a list of args. + * If the string is the result of looking up an environment variable, + * var_name should be set to the name of that environment variable, + * for use if needed in error messages. + */ + +static jboolean expand(JLI_List args, const char *str, const char *var_name) { + jboolean inEnvVar = (var_name != NULL); + + char *p, *arg; + char quote; + JLI_List argsInFile; // This is retained until the process terminates as it is saved as the args - p = JLI_MemAlloc(JLI_StrLen(env) + 1); - while (*env != '\0') { - while (*env != '\0' && isspace(*env)) { - env++; + p = JLI_MemAlloc(JLI_StrLen(str) + 1); + while (*str != '\0') { + while (*str != '\0' && isspace(*str)) { + str++; } // Trailing space - if (*env == '\0') { + if (*str == '\0') { break; } arg = p; - while (*env != '\0' && !isspace(*env)) { - if (*env == '"' || *env == '\'') { - quote = *env++; - while (*env != quote && *env != '\0') { - *p++ = *env++; + while (*str != '\0' && !isspace(*str)) { + if (inEnvVar && (*str == '"' || *str == '\'')) { + quote = *str++; + while (*str != quote && *str != '\0') { + *p++ = *str++; } - if (*env == '\0') { + if (*str == '\0') { JLI_ReportMessage(ARG_ERROR8, var_name); exit(1); } - env++; + str++; } else { - *p++ = *env++; + *p++ = *str++; } } *p++ = '\0'; - argsInFile = JLI_PreprocessArg(arg); + argsInFile = JLI_PreprocessArg(arg, JNI_FALSE); if (NULL == argsInFile) { if (isTerminalOpt(arg)) { - JLI_ReportMessage(ARG_ERROR9, arg, var_name); + if (inEnvVar) { + JLI_ReportMessage(ARG_ERROR9, arg, var_name); + } else { + JLI_ReportMessage(ARG_ERROR15, arg); + } exit(1); } JLI_List_add(args, arg); @@ -501,7 +544,11 @@ JLI_AddArgsFromEnvVar(JLI_List args, const char *var_name) { for (idx = 0; idx < cnt; idx++) { arg = argsInFile->elements[idx]; if (isTerminalOpt(arg)) { - JLI_ReportMessage(ARG_ERROR10, arg, argFile, var_name); + if (inEnvVar) { + JLI_ReportMessage(ARG_ERROR10, arg, argFile, var_name); + } else { + JLI_ReportMessage(ARG_ERROR16, arg, argFile); + } exit(1); } JLI_List_add(args, arg); @@ -517,11 +564,15 @@ JLI_AddArgsFromEnvVar(JLI_List args, const char *var_name) { * caught now. */ if (firstAppArgIndex != NOT_FOUND) { - JLI_ReportMessage(ARG_ERROR11, var_name); + if (inEnvVar) { + JLI_ReportMessage(ARG_ERROR11, var_name); + } else { + JLI_ReportMessage(ARG_ERROR17); + } exit(1); } - assert (*env == '\0' || isspace(*env)); + assert (*str == '\0' || isspace(*str)); } return JNI_TRUE; @@ -642,7 +693,7 @@ int main(int argc, char** argv) { if (argc > 1) { for (i = 0; i < argc; i++) { - JLI_List tokens = JLI_PreprocessArg(argv[i]); + JLI_List tokens = JLI_PreprocessArg(argv[i], JNI_FALSE); if (NULL != tokens) { for (j = 0; j < tokens->size; j++) { printf("Token[%lu]: <%s>\n", (unsigned long) j, tokens->elements[j]); diff --git a/src/java.base/share/native/libjli/emessages.h b/src/java.base/share/native/libjli/emessages.h index 2f94a60bce8..3506a886e25 100644 --- a/src/java.base/share/native/libjli/emessages.h +++ b/src/java.base/share/native/libjli/emessages.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, 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 @@ -51,6 +51,11 @@ #define ARG_ERROR10 "Error: Option %s in %s is not allowed in environment variable %s" #define ARG_ERROR11 "Error: Cannot specify main class in environment variable %s" #define ARG_ERROR12 "Error: %s requires module name" +#define ARG_ERROR13 "Error: %s requires source version" +#define ARG_ERROR14 "Error: Option %s is not allowed with --source" +#define ARG_ERROR15 "Error: Option %s is not allowed in this context" +#define ARG_ERROR16 "Error: Option %s in %s is not allowed in this context" +#define ARG_ERROR17 "Error: Cannot specify main class in this context" #define JVM_ERROR1 "Error: Could not create the Java Virtual Machine.\n" GEN_ERROR #define JVM_ERROR2 "Error: Could not detach main thread.\n" JNI_ERROR diff --git a/src/java.base/share/native/libjli/java.c b/src/java.base/share/native/libjli/java.c index f274a25da7a..9c6f170ac8c 100644 --- a/src/java.base/share/native/libjli/java.c +++ b/src/java.base/share/native/libjli/java.c @@ -172,6 +172,9 @@ static int KnownVMIndex(const char* name); static void FreeKnownVMs(); static jboolean IsWildCardEnabled(); + +#define SOURCE_LAUNCHER_MAIN_ENTRY "jdk.compiler/com.sun.tools.javac.launcher.Main" + /* * This reports error. VM will not be created and no usage is printed. */ @@ -214,7 +217,7 @@ static jlong initialHeapSize = 0; /* inital heap size */ * Entry point. */ JNIEXPORT int JNICALL -JLI_Launch(int argc, char ** argv, /* main argc, argc */ +JLI_Launch(int argc, char ** argv, /* main argc, argv */ int jargc, const char** jargv, /* java args */ int appclassc, const char** appclassv, /* app classpath */ const char* fullversion, /* full version defined */ @@ -317,8 +320,7 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ /* Parse command line options; if the return value of * ParseArguments is false, the program should exit. */ - if (!ParseArguments(&argc, &argv, &mode, &what, &ret, jrepath)) - { + if (!ParseArguments(&argc, &argv, &mode, &what, &ret, jrepath)) { return(ret); } @@ -585,7 +587,8 @@ IsLauncherOption(const char* name) { return IsClassPathOption(name) || IsLauncherMainOption(name) || JLI_StrCmp(name, "--describe-module") == 0 || - JLI_StrCmp(name, "-d") == 0; + JLI_StrCmp(name, "-d") == 0 || + JLI_StrCmp(name, "--source") == 0; } /* @@ -626,6 +629,29 @@ IsWhiteSpaceOption(const char* name) { IsLauncherOption(name); } +/* + * Check if it is OK to set the mode. + * If the mode was previously set, and should not be changed, + * a fatal error is reported. + */ +static int +checkMode(int mode, int newMode, const char *arg) { + if (mode == LM_SOURCE) { + JLI_ReportErrorMessage(ARG_ERROR14, arg); + exit(1); + } + return newMode; +} + +/* + * Test if an arg identifies a source file. + */ +jboolean +IsSourceFile(const char *arg) { + struct stat st; + return (JLI_HasSuffix(arg, ".java") && stat(arg, &st) == 0); +} + /* * Checks the command line options to find which JVM type was * specified. If no command line option was given for the JVM type, @@ -1230,7 +1256,8 @@ GetOpt(int *pargc, char ***pargv, char **poption, char **pvalue) { value = equals+1; if (JLI_StrCCmp(arg, "--describe-module=") == 0 || JLI_StrCCmp(arg, "--module=") == 0 || - JLI_StrCCmp(arg, "--class-path=") == 0) { + JLI_StrCCmp(arg, "--class-path=") == 0|| + JLI_StrCCmp(arg, "--source=") == 0) { kind = LAUNCHER_OPTION_WITH_ARGUMENT; } else { kind = VM_LONG_OPTION; @@ -1274,17 +1301,28 @@ ParseArguments(int *pargc, char ***pargv, */ if (JLI_StrCmp(arg, "-jar") == 0) { ARG_CHECK(argc, ARG_ERROR2, arg); - mode = LM_JAR; + mode = checkMode(mode, LM_JAR, arg); } else if (JLI_StrCmp(arg, "--module") == 0 || JLI_StrCCmp(arg, "--module=") == 0 || JLI_StrCmp(arg, "-m") == 0) { REPORT_ERROR (has_arg, ARG_ERROR5, arg); SetMainModule(value); - mode = LM_MODULE; + mode = checkMode(mode, LM_MODULE, arg); if (has_arg) { *pwhat = value; break; } + } else if (JLI_StrCmp(arg, "--source") == 0 || + JLI_StrCCmp(arg, "--source=") == 0) { + REPORT_ERROR (has_arg, ARG_ERROR13, arg); + mode = LM_SOURCE; + if (has_arg) { + const char *prop = "-Djdk.internal.javac.source="; + size_t size = JLI_StrLen(prop) + JLI_StrLen(value) + 1; + char *propValue = (char *)JLI_MemAlloc(size); + JLI_Snprintf(propValue, size, "%s%s", prop, value); + AddOption(propValue, NULL); + } } else if (JLI_StrCmp(arg, "--class-path") == 0 || JLI_StrCCmp(arg, "--class-path=") == 0 || JLI_StrCmp(arg, "-classpath") == 0 || @@ -1435,12 +1473,25 @@ ParseArguments(int *pargc, char ***pargv, if (!_have_classpath) { SetClassPath("."); } - mode = LM_CLASS; + mode = IsSourceFile(arg) ? LM_SOURCE : LM_CLASS; + } else if (mode == LM_CLASS && IsSourceFile(arg)) { + /* override LM_CLASS mode if given a source file */ + mode = LM_SOURCE; } - if (argc >= 0) { - *pargc = argc; - *pargv = argv; + if (mode == LM_SOURCE) { + AddOption("--add-modules=ALL-DEFAULT", NULL); + *pwhat = SOURCE_LAUNCHER_MAIN_ENTRY; + // adjust (argc, argv) so that the name of the source file + // is included in the args passed to the source launcher + // main entry class + *pargc = argc + 1; + *pargv = argv - 1; + } else { + if (argc >= 0) { + *pargc = argc; + *pargv = argv; + } } *pmode = mode; diff --git a/src/java.base/share/native/libjli/java.h b/src/java.base/share/native/libjli/java.h index 3bea2e11eec..0e77e3c4004 100644 --- a/src/java.base/share/native/libjli/java.h +++ b/src/java.base/share/native/libjli/java.h @@ -230,11 +230,12 @@ enum LaunchMode { // cf. sun.launcher.LauncherHelper LM_UNKNOWN = 0, LM_CLASS, LM_JAR, - LM_MODULE + LM_MODULE, + LM_SOURCE }; static const char *launchModeNames[] - = { "Unknown", "Main class", "JAR file", "Module" }; + = { "Unknown", "Main class", "JAR file", "Module", "Source" }; typedef struct { int argc; diff --git a/src/java.base/share/native/libjli/jli_util.c b/src/java.base/share/native/libjli/jli_util.c index 014e810ece7..3b24a784491 100644 --- a/src/java.base/share/native/libjli/jli_util.c +++ b/src/java.base/share/native/libjli/jli_util.c @@ -84,6 +84,16 @@ JLI_MemFree(void *ptr) free(ptr); } +jboolean +JLI_HasSuffix(const char *s1, const char *s2) +{ + char *p = JLI_StrRChr(s1, '.'); + if (p == NULL || *p == '\0') { + return JNI_FALSE; + } + return (JLI_StrCaseCmp(p, s2) == 0); +} + /* * debug helpers we use */ diff --git a/src/java.base/share/native/libjli/jli_util.h b/src/java.base/share/native/libjli/jli_util.h index 2968f1ee7e7..b8987010f31 100644 --- a/src/java.base/share/native/libjli/jli_util.h +++ b/src/java.base/share/native/libjli/jli_util.h @@ -51,7 +51,8 @@ JLI_StringDup(const char *s1); JNIEXPORT void JNICALL JLI_MemFree(void *ptr); -int JLI_StrCCmp(const char *s1, const char* s2); +int JLI_StrCCmp(const char *s1, const char *s2); +jboolean JLI_HasSuffix(const char *s1, const char *s2); typedef struct { char *arg; @@ -158,7 +159,7 @@ JNIEXPORT void JNICALL JLI_InitArgProcessing(jboolean hasJavaArgs, jboolean disableArgFile); JNIEXPORT JLI_List JNICALL -JLI_PreprocessArg(const char *arg); +JLI_PreprocessArg(const char *arg, jboolean expandSourceOpt); JNIEXPORT jboolean JNICALL JLI_AddArgsFromEnvVar(JLI_List args, const char *var_name); diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java b/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java index 34fe5d24526..5d5cca7626d 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -373,6 +373,22 @@ class UnixCopyFile { } } + // throw a DirectoryNotEmpty exception if appropriate + static void ensureEmptyDir(UnixPath dir) throws IOException { + try { + long ptr = opendir(dir); + try (UnixDirectoryStream stream = + new UnixDirectoryStream(dir, ptr, e -> true)) { + if (stream.iterator().hasNext()) { + throw new DirectoryNotEmptyException( + dir.getPathForExceptionMessage()); + } + } + } catch (UnixException e) { + e.rethrowAsIOException(dir); + } + } + // move file from source to target static void move(UnixPath source, UnixPath target, CopyOption... options) throws IOException @@ -465,6 +481,7 @@ class UnixCopyFile { // copy source to target if (sourceAttrs.isDirectory()) { + ensureEmptyDir(source); copyDirectory(source, sourceAttrs, target, flags); } else { if (sourceAttrs.isSymbolicLink()) { diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java b/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java index c96a699370f..2fe40b78204 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -249,6 +249,17 @@ class WindowsFileCopy { } } + // throw a DirectoryNotEmpty exception if not empty + static void ensureEmptyDir(WindowsPath dir) throws IOException { + try (WindowsDirectoryStream dirStream = + new WindowsDirectoryStream(dir, (e) -> true)) { + if (dirStream.iterator().hasNext()) { + throw new DirectoryNotEmptyException( + dir.getPathForExceptionMessage()); + } + } + } + /** * Move file from source to target */ @@ -407,6 +418,7 @@ class WindowsFileCopy { // create new directory or directory junction try { if (sourceAttrs.isDirectory()) { + ensureEmptyDir(source); CreateDirectory(targetPath, 0L); } else { String linkTarget = WindowsLinkSupport.readLink(source); diff --git a/src/java.base/windows/native/libjava/TimeZone_md.c b/src/java.base/windows/native/libjava/TimeZone_md.c index ab89a7d54ed..d46b3c3b57d 100644 --- a/src/java.base/windows/native/libjava/TimeZone_md.c +++ b/src/java.base/windows/native/libjava/TimeZone_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -437,6 +437,8 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName char *mapFileName; char lineBuffer[MAX_ZONE_CHAR * 4]; int noMapID = *mapID == '\0'; /* no mapID on Vista and later */ + int offset = 0; + const char* errorMessage = "unknown error"; mapFileName = malloc(strlen(java_home_dir) + strlen(MAPPINGS_FILE) + 1); if (mapFileName == NULL) { @@ -472,10 +474,14 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName items[itemIndex] = start; while (*idx && *idx != ':') { if (++idx >= endp) { + errorMessage = "premature end of line"; + offset = (int)(idx - lineBuffer); goto illegal_format; } } if (*idx == '\0') { + errorMessage = "illegal null character found"; + offset = (int)(idx - lineBuffer); goto illegal_format; } *idx++ = '\0'; @@ -483,6 +489,8 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName } if (*idx != '\n') { + errorMessage = "illegal non-newline character found"; + offset = (int)(idx - lineBuffer); goto illegal_format; } @@ -516,7 +524,8 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName illegal_format: (void) fclose(fp); - jio_fprintf(stderr, "tzmappings: Illegal format at line %d.\n", line); + jio_fprintf(stderr, "Illegal format in tzmappings file: %s at line %d, offset %d.\n", + errorMessage, line, offset); return NULL; } diff --git a/src/java.base/windows/native/libjli/cmdtoargs.c b/src/java.base/windows/native/libjli/cmdtoargs.c index 9de0e43c536..9bbbdaf9865 100644 --- a/src/java.base/windows/native/libjli/cmdtoargs.c +++ b/src/java.base/windows/native/libjli/cmdtoargs.c @@ -246,7 +246,7 @@ JLI_CmdToArgs(char* cmdline) { // iterate through rest of command line while (src != NULL) { src = next_arg(src, arg, &wildcard); - argsInFile = JLI_PreprocessArg(arg); + argsInFile = JLI_PreprocessArg(arg, JNI_TRUE); if (argsInFile != NULL) { // resize to accommodate another Arg cnt = argsInFile->size; diff --git a/src/java.desktop/macosx/native/libsplashscreen/libpng/zlib.h b/src/java.desktop/macosx/native/libsplashscreen/libpng/zlibwrapper/zlib.h similarity index 100% rename from src/java.desktop/macosx/native/libsplashscreen/libpng/zlib.h rename to src/java.desktop/macosx/native/libsplashscreen/libpng/zlibwrapper/zlib.h diff --git a/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c b/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c index 02c4a164fc1..d71e261decd 100644 --- a/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c +++ b/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -28,6 +28,7 @@ #include #include #include +#include "java_awt_SplashScreen.h" JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM * vm, void *reserved) diff --git a/src/java.prefs/macosx/native/libprefs/MacOSXPreferencesFile.m b/src/java.prefs/macosx/native/libprefs/MacOSXPreferencesFile.m index 269981aecd5..8a17427af8d 100644 --- a/src/java.prefs/macosx/native/libprefs/MacOSXPreferencesFile.m +++ b/src/java.prefs/macosx/native/libprefs/MacOSXPreferencesFile.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, 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 @@ -63,6 +63,7 @@ #include "jni_util.h" #include "jlong.h" #include "jvm.h" +#include "java_util_prefs_MacOSXPreferencesFile.h" /* * Declare library specific JNI_Onload entry if static build diff --git a/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c b/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c index 05dc673ae6d..c591f04d30a 100644 --- a/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c +++ b/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -34,6 +34,7 @@ #include #include #include "jni_util.h" +#include "java_util_prefs_FileSystemPreferences.h" /* * Declare library specific JNI_Onload entry if static build diff --git a/src/java.prefs/windows/native/libprefs/WindowsPreferences.c b/src/java.prefs/windows/native/libprefs/WindowsPreferences.c index 0512b69b45c..0d512a36527 100644 --- a/src/java.prefs/windows/native/libprefs/WindowsPreferences.c +++ b/src/java.prefs/windows/native/libprefs/WindowsPreferences.c @@ -28,6 +28,8 @@ #include "jni.h" #include "jni_util.h" #include "jvm.h" +#include "java_util_prefs_WindowsPreferences.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c b/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c index d5424cf4f5f..a973eea330e 100644 --- a/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c +++ b/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -44,6 +44,7 @@ #include #include "jni_util.h" #include +#include "sun_security_krb5_Credentials.h" #undef LSA_SUCCESS #define LSA_SUCCESS(Status) ((Status) >= 0) diff --git a/src/java.security.jgss/windows/native/libw2k_lsa_auth/WindowsDirectory.c b/src/java.security.jgss/windows/native/libw2k_lsa_auth/WindowsDirectory.c index 7466022f752..0edf6ec8bad 100644 --- a/src/java.security.jgss/windows/native/libw2k_lsa_auth/WindowsDirectory.c +++ b/src/java.security.jgss/windows/native/libw2k_lsa_auth/WindowsDirectory.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2009, 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 @@ -27,6 +27,7 @@ #include #include #include +#include "sun_security_krb5_Config.h" /* * Class: sun_security_krb5_Config diff --git a/src/java.sql.rowset/share/classes/javax/sql/rowset/package-info.java b/src/java.sql.rowset/share/classes/javax/sql/rowset/package-info.java new file mode 100644 index 00000000000..1057b7e37ff --- /dev/null +++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/package-info.java @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2017, 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. + */ + +/** + * Standard interfaces and base classes for JDBC RowSet + * implementations. This package contains interfaces and classes + * that a standard RowSet implementation either implements or extends. + * + *

    Table of Contents

    + * + * + *

    1.0 Package Specification

    + * This package specifies five standard JDBC RowSet interfaces. + * All five extend the + * RowSet interface described in the JDBC 3.0 + * specification. It is anticipated that additional definitions + * of more specialized JDBC RowSet types will emerge as this technology + * matures. Future definitions should be specified as subinterfaces using + * inheritance similar to the way it is used in this specification. + *

    + * Note: The interface definitions provided in this package form the basis for + * all compliant JDBC RowSet implementations. Vendors and more advanced + * developers who intend to provide their own compliant RowSet implementations + * should pay particular attention to the assertions detailed in specification + * interfaces. + * + *

    2.0 Standard RowSet Definitions

    + *
      + *
    • JdbcRowSet - A wrapper around + * a ResultSet object that makes it possible to use the result set as a + * JavaBeans™ component. Thus, + * a JdbcRowSet object can be a Bean that any tool + * makes available for assembling an application as part of a component based + * architecture. A JdbcRowSet object is a connected RowSet + * object, that is, it + * must continually maintain its connection to its data source using a JDBC + * technology-enabled driver ("JDBC driver"). In addition, a JdbcRowSet + * object provides a fully updatable and scrollable tabular + * data structure as defined in the JDBC 3.0 specification. + * + *
    • + * CachedRowSet + * - A CachedRowSet object is a JavaBeans™ + * component that is scrollable, updatable, serializable, and generally disconnected from + * the source of its data. A CachedRowSet object + * typically contains rows from a result set, but it can also contain rows from any + * file with a tabular format, such as a spreadsheet. CachedRowSet implementations + * must use the SyncFactory to manage and obtain pluggable + * SyncProvider objects to provide synchronization between the + * disconnected RowSet object and the originating data source. + * Typically a SyncProvider implementation relies upon a JDBC + * driver to obtain connectivity to a particular data source. + * Further details on this mechanism are discussed in the javax.sql.rowset.spi package + * specification. + * + *
    • WebRowSet - A + * WebRowSet object is an extension of CachedRowSet + * that can read and write a RowSet object in a well formed XML format. + * This class calls an XmlReader object + * (an extension of the RowSetReader + * interface) to read a rowset in XML format. It calls an + * XmlWriter object (an extension of the + * RowSetWriter interface) + * to write a rowset in XML format. The reader and writer required by + * WebRowSet objects are provided by the + * SyncFactory in the form of SyncProvider + * implementations. In order to ensure well formed XML usage, a standard generic XML + * Schema is defined and published at + * + * http://java.sun.com/xml/ns/jdbc/webrowset.xsd. + * + *
    • FilteredRowSet - A + * FilteredRowSet object provides filtering functionality in a programmatic + * and extensible way. There are many instances when a RowSet object + * has a need to provide filtering in its contents without sacrificing the disconnected + * environment, thus saving the expense of having to create a connection to the data source. + * Solutions to this need vary from providing heavyweight full scale + * SQL query abilities, to portable components, to more lightweight + * approaches. A FilteredRowSet object consumes + * an implementation of the Predicate + * interface, which may define a filter at run time. In turn, a + * FilteredRowSet object is tasked with enforcing the set filter for both + * inbound and outbound read and write operations. That is, all filters can be + * considered as bi-directional. No standard filters are defined; + * however, sufficient mechanics are specified to permit any required filter to be + * implemented. + * + *
    • JoinRowSet - The JoinRowSet + * interface describes a mechanism by which relationships can be established between + * two or more standard RowSet implementations. Any number of RowSet + * objects can be added to a JoinRowSet object provided the RowSetobjects + * can be related in a SQL JOIN like fashion. By definition, the SQL JOIN + * statement is used to combine the data contained in two (or more) relational + * database tables based upon a common attribute. By establishing and then enforcing + * column matches, a JoinRowSet object establishes relationships between + * RowSet instances without the need to touch the originating data source. + *
    + * + *

    3.0 Implementer's Guide

    + * Compliant implementations of JDBC RowSet Implementations + * must follow the assertions described in this specification. In accordance + * with the terms of the Java Community Process, a + * Test Compatibility Kit (TCK) can be licensed to ensure compatibility with the + * specification. The following paragraphs outline a number of starting points for + * implementers of the standard JDBC RowSet definitions. Implementers + * should also consult the Implementer's Guide in the javax.sql.rowset.spi package for guidelines + * on SyncProvider implementations. + * + *
      + *
    • 3.1 Constructor + *

      + * All RowSet implementations must provide a + * no-argument constructor. + *

    • + *
    • 3.2 Role of the BaseRowSet Class + *

      + * A compliant JDBC RowSet implementation must implement one or more + * standard interfaces specified in this package and may extend the + * BaseRowSet abstract class. For example, a + * CachedRowSet implementation must implement the CachedRowSet + * interface and extend the BaseRowSet abstract class. The + * BaseRowSet class provides the standard architecture on which all + * RowSet implementations should be built, regardless of whether the + * RowSet objects exist in a connected or disconnected environment. + * The BaseRowSet abstract class provides any RowSet implementation + * with its base functionality, including property manipulation and event notification + * that is fully compliant with JavaBeans + * component requirements. As an example, all implementations provided in the + * reference implementations (contained in the com.sun.rowset package) use + * the BaseRowSet class as a basis for their implementations. + *

      + * The following table illustrates the features that the BaseRowSet + * abstract class provides. + *

      + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
      Features in BaseRowSet
      FeatureDetails
      PropertiesProvides standard JavaBeans property manipulation + * mechanisms to allow applications to get and set RowSet command and + * property values. Refer to the documentation of the javax.sql.RowSet + * interface (available in the JDBC 3.0 specification) for more details on + * the standard RowSet properties.
      Event notificationProvides standard JavaBeans event notifications + * to registered event listeners. Refer to the documentation of javax.sql.RowSetEvent + * interface (available in the JDBC 3.0 specification) for + * more details on how to register and handle standard RowSet events generated + * by compliant implementations.
      Setters for a RowSet object's commandProvides a complete set of setter methods + * for setting RowSet command parameters.
      StreamsProvides fields for storing of stream instances + * in addition to providing a set of constants for stream type designation.
      + *
      + * + *
    • 3.3 Connected RowSet Requirements + *

      + * The JdbcRowSet describes a RowSet object that must always + * be connected to the originating data source. Implementations of the JdbcRowSet + * should ensure that this connection is provided solely by a JDBC driver. + * Furthermore, RowSet objects that are implementations of the + * JdbcRowSet interface and are therefore operating in a connected environment + * do not use the SyncFactory to obtain a RowSetReader object + * or a RowSetWriter object. They can safely rely on the JDBC driver to + * supply their needs by virtue of the presence of an underlying updatable and scrollable + * ResultSet implementation. + * + *

    • + * 3.4 Disconnected RowSet Requirements + *

      + * A disconnected RowSet object, such as a CachedRowSet object, + * should delegate + * connection management to a SyncProvider object provided by the + * SyncFactory. To ensure fully disconnected semantics, all + * disconnected RowSet objects must ensure + * that the original connection made to the data source to populate the RowSet + * object is closed to permit the garbage collector to recover and release resources. The + * SyncProvider object ensures that the critical JDBC properties are + * maintained in order to re-establish a connection to the data source when a + * synchronization is required. A disconnected RowSet object should + * therefore ensure that no + * extraneous references remain on the Connection object. + * + *

    • 3.5 Role of RowSetMetaDataImpl + *

      + * The RowsetMetaDataImpl class is a utility class that provides an implementation of the + * RowSetMetaData interface, supplying standard setter + * method implementations for metadata for both connected and disconnected + * RowSet objects. All implementations are free to use this standard + * implementation but are not required to do so. + * + *

    • 3.6 RowSetWarning Class + *

      + * The RowSetWarning class provides warnings that can be set + * on RowSet implementations. + * Similar to SQLWarning objects, + * RowSetWarning objects are silently chained to the object whose method + * caused the warning to be thrown. All RowSet implementations should + * ensure that this chaining occurs if a warning is generated and also ensure that the + * warnings are available via the getRowSetWarnings method defined in either + * the JdbcRowSet interface or the CachedRowSet interface. + * After a warning has been retrieved with one of the + * getRowSetWarnings methods, the RowSetWarning method + * getNextWarning can be called on it to retrieve any warnings that might + * be chained on it. If a warning is returned, getNextWarning can be called + * on it, and so on until there are no more warnings. + * + *

    • 3.7 The Joinable Interface + *

      + * The Joinable interface provides both connected and disconnected + * RowSet objects with the capability to be added to a + * JoinRowSet object in an SQL JOIN operation. + * A RowSet object that has implemented the Joinable + * interface can set a match column, retrieve a match column, or unset a match column. + * A JoinRowSet object can then use the RowSet object's + * match column as a basis for adding the RowSet object. + *

    • + * + *
    • 3.8 The RowSetFactory Interface + *

      + * A RowSetFactory implementation must + * be provided. + *

    • + *
    + * + *

    4.0 Related Specifications

    + * + * + *

    5.0 Related Documentation

    + * + */ +package javax.sql.rowset; diff --git a/src/java.sql.rowset/share/classes/javax/sql/rowset/package.html b/src/java.sql.rowset/share/classes/javax/sql/rowset/package.html deleted file mode 100644 index 12ee65c9b8e..00000000000 --- a/src/java.sql.rowset/share/classes/javax/sql/rowset/package.html +++ /dev/null @@ -1,297 +0,0 @@ - - - - - - - javax.sql.rowset Package - - - - -Standard interfaces and base classes for JDBC RowSet -implementations. This package contains interfaces and classes -that a standard RowSet implementation either implements or extends. - - -

    Table of Contents

    - - -

    1.0 Package Specification

    -This package specifies five standard JDBC RowSet interfaces. - All five extend the -RowSet interface described in the JDBC 3.0 -specification. It is anticipated that additional definitions -of more specialized JDBC RowSet types will emerge as this technology -matures. Future definitions should be specified as subinterfaces using -inheritance similar to the way it is used in this specification. -

    -Note: The interface definitions provided in this package form the basis for -all compliant JDBC RowSet implementations. Vendors and more advanced -developers who intend to provide their own compliant RowSet implementations -should pay particular attention to the assertions detailed in specification -interfaces. - -

    2.0 Standard RowSet Definitions

    -
      -
    • JdbcRowSet - A wrapper around -a ResultSet object that makes it possible to use the result set as a -JavaBeans™ component. Thus, -a JdbcRowSet object can be a Bean that any tool -makes available for assembling an application as part of a component based -architecture. A JdbcRowSet object is a connected RowSet -object, that is, it -must continually maintain its connection to its data source using a JDBC -technology-enabled driver ("JDBC driver"). In addition, a JdbcRowSet -object provides a fully updatable and scrollable tabular -data structure as defined in the JDBC 3.0 specification. - -
    • -CachedRowSet - - A CachedRowSet object is a JavaBeans™ - component that is scrollable, updatable, serializable, and generally disconnected from - the source of its data. A CachedRowSet object -typically contains rows from a result set, but it can also contain rows from any -file with a tabular format, such as a spreadsheet. CachedRowSet implementations -must use the SyncFactory to manage and obtain pluggable -SyncProvider objects to provide synchronization between the -disconnected RowSet object and the originating data source. -Typically a SyncProvider implementation relies upon a JDBC -driver to obtain connectivity to a particular data source. -Further details on this mechanism are discussed in the javax.sql.rowset.spi package -specification. - -
    • WebRowSet - A -WebRowSet object is an extension of CachedRowSet -that can read and write a RowSet object in a well formed XML format. -This class calls an XmlReader object -(an extension of the RowSetReader -interface) to read a rowset in XML format. It calls an -XmlWriter object (an extension of the -RowSetWriter interface) -to write a rowset in XML format. The reader and writer required by -WebRowSet objects are provided by the -SyncFactory in the form of SyncProvider -implementations. In order to ensure well formed XML usage, a standard generic XML -Schema is defined and published at - -http://java.sun.com/xml/ns/jdbc/webrowset.xsd. - -
    • FilteredRowSet - A -FilteredRowSet object provides filtering functionality in a programmatic -and extensible way. There are many instances when a RowSet object -has a need to provide filtering in its contents without sacrificing the disconnected -environment, thus saving the expense of having to create a connection to the data source. -Solutions to this need vary from providing heavyweight full scale -SQL query abilities, to portable components, to more lightweight -approaches. A FilteredRowSet object consumes -an implementation of the Predicate -interface, which may define a filter at run time. In turn, a -FilteredRowSet object is tasked with enforcing the set filter for both -inbound and outbound read and write operations. That is, all filters can be -considered as bi-directional. No standard filters are defined; -however, sufficient mechanics are specified to permit any required filter to be -implemented. - -
    • JoinRowSet - The JoinRowSet -interface describes a mechanism by which relationships can be established between -two or more standard RowSet implementations. Any number of RowSet - objects can be added to a JoinRowSet object provided the RowSetobjects -can be related in a SQL JOIN like fashion. By definition, the SQL JOIN -statement is used to combine the data contained in two (or more) relational -database tables based upon a common attribute. By establishing and then enforcing -column matches, a JoinRowSet object establishes relationships between -RowSet instances without the need to touch the originating data source. -
    - -

    3.0 Implementer's Guide

    -Compliant implementations of JDBC RowSet Implementations -must follow the assertions described in this specification. In accordance -with the terms of the Java Community Process, a -Test Compatibility Kit (TCK) can be licensed to ensure compatibility with the -specification. The following paragraphs outline a number of starting points for -implementers of the standard JDBC RowSet definitions. Implementers -should also consult the Implementer's Guide in the javax.sql.rowset.spi package for guidelines -on SyncProvider implementations. - -
      -
    • 3.1 Constructor -

      - All RowSet implementations must provide a -no-argument constructor. -

    • -
    • 3.2 Role of the BaseRowSet Class -

      -A compliant JDBC RowSet implementation must implement one or more -standard interfaces specified in this package and may extend the -BaseRowSet abstract class. For example, a -CachedRowSet implementation must implement the CachedRowSet -interface and extend the BaseRowSet abstract class. The -BaseRowSet class provides the standard architecture on which all -RowSet implementations should be built, regardless of whether the -RowSet objects exist in a connected or disconnected environment. -The BaseRowSet abstract class provides any RowSet implementation -with its base functionality, including property manipulation and event notification -that is fully compliant with JavaBeans -component requirements. As an example, all implementations provided in the -reference implementations (contained in the com.sun.rowset package) use -the BaseRowSet class as a basis for their implementations. -

      -The following table illustrates the features that the BaseRowSet -abstract class provides. -

      - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Features in BaseRowSet
      FeatureDetails
      PropertiesProvides standard JavaBeans property manipulation -mechanisms to allow applications to get and set RowSet command and -property values. Refer to the documentation of the javax.sql.RowSet -interface (available in the JDBC 3.0 specification) for more details on -the standard RowSet properties.
      Event notificationProvides standard JavaBeans event notifications -to registered event listeners. Refer to the documentation of javax.sql.RowSetEvent -interface (available in the JDBC 3.0 specification) for -more details on how to register and handle standard RowSet events generated -by compliant implementations.
      Setters for a RowSet object's commandProvides a complete set of setter methods - for setting RowSet command parameters.
      StreamsProvides fields for storing of stream instances - in addition to providing a set of constants for stream type designation.
      -
      - -
    • 3.3 Connected RowSet Requirements -

      -The JdbcRowSet describes a RowSet object that must always -be connected to the originating data source. Implementations of the JdbcRowSet -should ensure that this connection is provided solely by a JDBC driver. -Furthermore, RowSet objects that are implementations of the -JdbcRowSet interface and are therefore operating in a connected environment -do not use the SyncFactory to obtain a RowSetReader object -or a RowSetWriter object. They can safely rely on the JDBC driver to -supply their needs by virtue of the presence of an underlying updatable and scrollable -ResultSet implementation. - -

    • -3.4 Disconnected RowSet Requirements -

      -A disconnected RowSet object, such as a CachedRowSet object, -should delegate -connection management to a SyncProvider object provided by the -SyncFactory. To ensure fully disconnected semantics, all -disconnected RowSet objects must ensure -that the original connection made to the data source to populate the RowSet -object is closed to permit the garbage collector to recover and release resources. The -SyncProvider object ensures that the critical JDBC properties are -maintained in order to re-establish a connection to the data source when a -synchronization is required. A disconnected RowSet object should -therefore ensure that no -extraneous references remain on the Connection object. - -

    • 3.5 Role of RowSetMetaDataImpl -

      -The RowsetMetaDataImpl class is a utility class that provides an implementation of the -RowSetMetaData interface, supplying standard setter -method implementations for metadata for both connected and disconnected -RowSet objects. All implementations are free to use this standard -implementation but are not required to do so. - -

    • 3.6 RowSetWarning Class -

      -The RowSetWarning class provides warnings that can be set -on RowSet implementations. -Similar to SQLWarning objects, -RowSetWarning objects are silently chained to the object whose method -caused the warning to be thrown. All RowSet implementations should -ensure that this chaining occurs if a warning is generated and also ensure that the -warnings are available via the getRowSetWarnings method defined in either -the JdbcRowSet interface or the CachedRowSet interface. -After a warning has been retrieved with one of the -getRowSetWarnings methods, the RowSetWarning method -getNextWarning can be called on it to retrieve any warnings that might -be chained on it. If a warning is returned, getNextWarning can be called -on it, and so on until there are no more warnings. - -

    • 3.7 The Joinable Interface -

      -The Joinable interface provides both connected and disconnected -RowSet objects with the capability to be added to a -JoinRowSet object in an SQL JOIN operation. -A RowSet object that has implemented the Joinable -interface can set a match column, retrieve a match column, or unset a match column. -A JoinRowSet object can then use the RowSet object's -match column as a basis for adding the RowSet object. -

    • - -
    • 3.8 The RowSetFactory Interface -

      - A RowSetFactory implementation must - be provided. -

    • -
    - -

    4.0 Related Specifications

    - - -

    5.0 Related Documentation

    - - - diff --git a/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package-info.java b/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package-info.java new file mode 100644 index 00000000000..713b4a1a9a7 --- /dev/null +++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package-info.java @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2003, 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. + */ + +/** + * The standard classes and interfaces that a third party vendor has to + * use in its implementation of a synchronization provider. These classes and + * interfaces are referred to as the Service Provider Interface (SPI). To make it possible + * for a RowSet object to use an implementation, the vendor must register + * it with the SyncFactory singleton. (See the class comment for + * SyncProvider for a full explanation of the registration process and + * the naming convention to be used.) + * + *

    Table of Contents

    + * + * + *

    1.0 Package Specification

    + *

    + * The following classes and interfaces make up the javax.sql.rowset.spi + * package: + *

      + *
    • SyncFactory + *
    • SyncProvider + *
    • SyncFactoryException + *
    • SyncProviderException + *
    • SyncResolver + *
    • XmlReader + *
    • XmlWriter + *
    • TransactionalWriter + *
    + * The following interfaces, in the javax.sql package, are also part of the SPI: + *
      + *
    • RowSetReader + *
    • RowSetWriter + *
    + *

    + * A SyncProvider implementation provides a disconnected RowSet + * object with the mechanisms for reading data into it and for writing data that has been + * modified in it + * back to the underlying data source. A reader, a RowSetReader or + * XMLReader object, reads data into a RowSet object when the + * CachedRowSet methods execute or populate + * are called. A writer, a RowSetWriter or XMLWriter + * object, writes changes back to the underlying data source when the + * CachedRowSet method acceptChanges is called. + *

    + * The process of writing changes in a RowSet object to its data source + * is known as synchronization. The SyncProvider implementation that a + * RowSet object is using determines the level of synchronization that the + * RowSet object's writer uses. The various levels of synchronization are + * referred to as grades. + *

    + * The lower grades of synchronization are + * known as optimistic concurrency levels because they optimistically + * assume that there will be no conflicts or very few conflicts. A conflict exists when + * the same data modified in the RowSet object has also been modified + * in the data source. Using the optimistic concurrency model means that if there + * is a conflict, modifications to either the data source or the RowSet + * object will be lost. + *

    + * Higher grades of synchronization are called pessimistic because they assume + * that others will be accessing the data source and making modifications. These + * grades set varying levels of locks to increase the chances that no conflicts + * occur. + *

    + * The lowest level of synchronization is simply writing any changes made to the + * RowSet object to its underlying data source. The writer does + * nothing to check for conflicts. + * If there is a conflict and the data + * source values are overwritten, the changes other parties have made by to the data + * source are lost. + *

    + * The RIXMLProvider implementation uses the lowest level + * of synchronization and just writes RowSet changes to the data source. + * + *

    + * For the next level up, the + * writer checks to see if there are any conflicts, and if there are, + * it does not write anything to the data source. The problem with this concurrency + * level is that if another party has modified the corresponding data in the data source + * since the RowSet object got its data, + * the changes made to the RowSet object are lost. The + * RIOptimisticProvider implementation uses this level of synchronization. + *

    + * At higher levels of synchronization, referred to as pessimistic concurrency, + * the writer take steps to avoid conflicts by setting locks. Setting locks + * can vary from setting a lock on a single row to setting a lock on a table + * or the entire data source. The level of synchronization is therefore a tradeoff + * between the ability of users to access the data source concurrently and the ability + * of the writer to keep the data in the RowSet object and its data source + * synchronized. + *

    + * It is a requirement that all disconnected RowSet objects + * (CachedRowSet, FilteredRowSet, JoinRowSet, + * and WebRowSet objects) obtain their SyncProvider objects + * from the SyncFactory mechanism. + *

    + * The reference implementation (RI) provides two synchronization providers. + *

      + *
    • RIOptimisticProvider
      + * The default provider that the SyncFactory instance will + * supply to a disconnected RowSet object when no provider + * implementation is specified.
      + * This synchronization provider uses an optimistic concurrency model, + * assuming that there will be few conflicts among users + * who are accessing the same data in a database. It avoids + * using locks; rather, it checks to see if there is a conflict + * before trying to synchronize the RowSet object and the + * data source. If there is a conflict, it does nothing, meaning that + * changes to the RowSet object are not persisted to the data + * source. + *
    • RIXMLProvider
      + * A synchronization provider that can be used with a + * WebRowSet object, which is a rowset that can be written + * in XML format or read from XML format. The + * RIXMLProvider implementation does no checking at all for + * conflicts and simply writes any updated data in the + * WebRowSet object to the underlying data source. + * WebRowSet objects use this provider when they are + * dealing with XML data. + *
    + * + * These SyncProvider implementations + * are bundled with the reference implementation, which makes them always available to + * RowSet implementations. + * SyncProvider implementations make themselves available by being + * registered with the SyncFactory singleton. When a RowSet + * object requests a provider, by specifying it in the constructor or as an argument to the + * CachedRowSet method setSyncProvider, + * the SyncFactory singleton + * checks to see if the requested provider has been registered with it. + * If it has, the SyncFactory creates an instance of it and passes it to the + * requesting RowSet object. + * If the SyncProvider implementation that is specified has not been registered, + * the SyncFactory singleton causes a SyncFactoryException object + * to be thrown. If no provider is specified, + * the SyncFactory singleton will create an instance of the default + * provider implementation, RIOptimisticProvider, + * and pass it to the requesting RowSet object. + * + *

    + * If a WebRowSet object does not specify a provider in its constructor, the + * SyncFactory will give it an instance of RIOptimisticProvider. + * However, the constructor for WebRowSet is implemented to set the provider + * to the RIXMLProvider, which reads and writes a RowSet object + * in XML format. + *

    + * See the SyncProvider class + * specification for further details. + *

    + * Vendors may develop a SyncProvider implementation with any one of the possible + * levels of synchronization, thus giving RowSet objects a choice of + * synchronization mechanisms. + * + *

    2.0 Service Provider Interface Architecture

    + * 2.1 Overview + *

    + * The Service Provider Interface provides a pluggable mechanism by which + * SyncProvider implementations can be registered and then generated when + * required. The lazy reference mechanism employed by the SyncFactory limits + * unnecessary resource consumption by not creating an instance until it is + * required by a disconnected + * RowSet object. The SyncFactory class also provides + * a standard API to configure logging options and streams that may be provided + * by a particular SyncProvider implementation. + *

    + * 2.2 Registering with the SyncFactory + *

    + * A third party SyncProvider implementation must be registered with the + * SyncFactory in order for a disconnected RowSet object + * to obtain it and thereby use its javax.sql.RowSetReader and + * javax.sql.RowSetWriter + * implementations. The following registration mechanisms are available to all + * SyncProvider implementations: + *

      + *
    • System properties - Properties set at the command line. These + * properties are set at run time and apply system-wide per invocation of the Java + * application. See the section "Related Documentation" + * further related information. + * + *
    • Property Files - Properties specified in a standard property file. + * This can be specified using a System Property or by modifying a standard + * property file located in the platform run-time. The + * reference implementation of this technology includes a standard property + * file than can be edited to add additional SyncProvider objects. + * + *
    • JNDI Context - Available providers can be registered on a JNDI + * context. The SyncFactory will attempt to load SyncProvider + * objects bound to the context and register them with the factory. This + * context must be supplied to the SyncFactory for the mechanism to + * function correctly. + *
    + *

    + * Details on how to specify the system properties or properties in a property file + * and how to configure the JNDI Context are explained in detail in the + * SyncFactory class description. + *

    + * 2.3 SyncFactory Provider Instance Generation Policies + *

    + * The SyncFactory generates a requested SyncProvider + * object if the provider has been correctly registered. The + * following policies are adhered to when either a disconnected RowSet object + * is instantiated with a specified SyncProvider implementation or is + * reconfigured at runtime with an alternative SyncProvider object. + *

      + *
    • If a SyncProvider object is specified and the SyncFactory + * contains no reference to the provider, a SyncFactoryException is + * thrown. + * + *
    • If a SyncProvider object is specified and the SyncFactory + * contains a reference to the provider, the requested provider is supplied. + * + *
    • If no SyncProvider object is specified, the reference + * implementation provider RIOptimisticProvider is supplied. + *
    + *

    + * These policies are explored in more detail in the + * SyncFactory class. + * + *

    3.0 SyncProvider Implementer's Guide

    + * + * 3.1 Requirements + *

    + * A compliant SyncProvider implementation that is fully pluggable + * into the SyncFactory must extend and implement all + * abstract methods in the SyncProvider + * class. In addition, an implementation must determine the + * grade, locking and updatable view capabilities defined in the + * SyncProvider class definition. One or more of the + * SyncProvider description criteria must be supported. It + * is expected that vendor implementations will offer a range of grade, locking, and + * updatable view capabilities. + *

    + * Furthermore, the SyncProvider naming convention must be followed as + * detailed in the SyncProvider class + * description. + *

    + * 3.2 Grades + *

    + * JSR 114 defines a set of grades to describe the quality of synchronization + * a SyncProvider object can offer a disconnected RowSet + * object. These grades are listed from the lowest quality of service to the highest. + *

      + *
    • GRADE_NONE - No synchronization with the originating data source is + * provided. A SyncProvider implementation returning this grade will simply + * attempt to write any data that has changed in the RowSet object to the + *underlying data source, overwriting whatever is there. No attempt is made to compare + * original values with current values to see if there is a conflict. The + * RIXMLProvider is implemented with this grade. + * + *
    • GRADE_CHECK_MODIFIED_AT_COMMIT - A low grade of optimistic synchronization. + * A SyncProvider implementation returning this grade + * will check for conflicts in rows that have changed between the last synchronization + * and the current synchronization under way. Any changes in the originating data source + * that have been modified will not be reflected in the disconnected RowSet + * object. If there are no conflicts, changes in the RowSet object will be + * written to the data source. If there are conflicts, no changes are written. + * The RIOptimisticProvider implementation uses this grade. + * + *
    • GRADE_CHECK_ALL_AT_COMMIT - A high grade of optimistic synchronization. + * A SyncProvider implementation returning this grade + * will check all rows, including rows that have not changed in the disconnected + * RowSet object. In this way, any changes to rows in the underlying + * data source will be reflected in the disconnected RowSet object + * when the synchronization finishes successfully. + * + *
    • GRADE_LOCK_WHEN_MODIFIED - A pessimistic grade of synchronization. + * SyncProvider implementations returning this grade will lock + * the row in the originating data source that corresponds to the row being changed + * in the RowSet object to reduce the possibility of other + * processes modifying the same data in the data source. + * + *
    • GRADE_LOCK_WHEN_LOADED - A higher pessimistic synchronization grade. + * A SyncProvider implementation returning this grade will lock + * the entire view and/or table affected by the original query used to + * populate a RowSet object. + *
    + *

    + * 3.3 Locks + *

    + * JSR 114 defines a set of constants that specify whether any locks have been + * placed on a RowSet object's underlying data source and, if so, + * on which constructs the locks are placed. These locks will remain on the data + * source while the RowSet object is disconnected from the data source. + *

    + * These constants should be considered complementary to the + * grade constants. The default setting for the majority of grade settings requires + * that no data source locks remain when a RowSet object is disconnected + * from its data source. + * The grades GRADE_LOCK_WHEN_MODIFIED and + * GRADE_LOCK_WHEN_LOADED allow a disconnected RowSet object + * to have a fine-grained control over the degree of locking. + *

      + *
    • DATASOURCE_NO_LOCK - No locks remain on the originating data source. + * This is the default lock setting for all SyncProvider implementations + * unless otherwise directed by a RowSet object. + * + *
    • DATASOURCE_ROW_LOCK - A lock is placed on the rows that are touched by + * the original SQL query used to populate the RowSet object. + * + *
    • DATASOURCE_TABLE_LOCK - A lock is placed on all tables that are touched + * by the query that was used to populate the RowSet object. + * + *
    • DATASOURCE_DB_LOCK + * A lock is placed on the entire data source that is used by the RowSet + * object. + *
    + *

    + * 3.4 Updatable Views + *

    + * A RowSet object may be populated with data from an SQL VIEW. + * The following constants indicate whether a SyncProvider object can + * update data in the table or tables from which the VIEW was derived. + *

      + *
    • UPDATABLE_VIEW_SYNC + * Indicates that a SyncProvider implementation supports synchronization + * to the table or tables from which the SQL VIEW used to populate + * a RowSet object is derived. + * + *
    • NONUPDATABLE_VIEW_SYNC + * Indicates that a SyncProvider implementation does not support + * synchronization to the table or tables from which the SQL VIEW + * used to populate a RowSet object is derived. + *
    + *

    + * 3.5 Usage of SyncProvider Grading and Locking + *

    + * In the example below, the reference CachedRowSetImpl implementation + * reconfigures its current SyncProvider object by calling the + * setSyncProvider method.
    + * + *

    + *   CachedRowSetImpl crs = new CachedRowSetImpl();
    + *   crs.setSyncProvider("com.foo.bar.HASyncProvider");
    + * 
    + * An application can retrieve the SyncProvider object currently in use + * by a disconnected RowSet object. It can also retrieve the + * grade of synchronization with which the provider was implemented and the degree of + * locking currently in use. In addition, an application has the flexibility to set + * the degree of locking to be used, which can increase the possibilities for successful + * synchronization. These operation are shown in the following code fragment. + *
    + *   SyncProvider sync = crs.getSyncProvider();
    + *
    + *   switch (sync.getProviderGrade()) {
    + *   case: SyncProvider.GRADE_CHECK_ALL_AT_COMMIT
    + *         //A high grade of optimistic synchronization
    + *    break;
    + *    case: SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT
    + *         //A low grade of optimistic synchronization
    + *    break;
    + *    case: SyncProvider.GRADE_LOCK_WHEN_LOADED
    + *         // A pessimistic synchronization grade
    + *    break;
    + *    case: SyncProvider.GRADE_LOCK_WHEN_MODIFIED
    + *         // A pessimistic synchronization grade
    + *    break;
    + *    case: SyncProvider.GRADE_NONE
    + *      // No synchronization with the originating data source provided
    + *    break;
    + *    }
    + *
    + *    switch (sync.getDataSourcLock() {
    + *      case: SyncProvider.DATASOURCE_DB_LOCK
    + *       // A lock is placed on the entire datasource that is used by the
    + *       // RowSet object
    + *       break;
    + *
    + *      case: SyncProvider.DATASOURCE_NO_LOCK
    + *       // No locks remain on the  originating data source.
    + *      break;
    + *
    + *      case: SyncProvider.DATASOURCE_ROW_LOCK
    + *       // A lock is placed on the rows that are  touched by the original
    + *       // SQL statement used to populate
    + *       // the RowSet object that is using the SyncProvider
    + *       break;
    + *
    + *      case: DATASOURCE_TABLE_LOCK
    + *       // A lock is placed on  all tables that are touched by the original
    + *       // SQL statement used to populated
    + *       // the RowSet object that is using the SyncProvider
    + *      break;
    + *
    + * 
    + * It is also possible using the static utility method in the + * SyncFactory class to determine the list of SyncProvider + * implementations currently registered with the SyncFactory. + * + *
    + *       Enumeration e = SyncFactory.getRegisteredProviders();
    + * 
    + * + * + *

    4.0 Resolving Synchronization Conflicts

    + * + * The interface SyncResolver provides a way for an application to + * decide manually what to do when a conflict occurs. When the CachedRowSet + * method acceptChanges finishes and has detected one or more conflicts, + * it throws a SyncProviderException object. An application can + * catch the exception and + * have it retrieve a SyncResolver object by calling the method + * SyncProviderException.getSyncResolver(). + *

    + * A SyncResolver object, which is a special kind of + * CachedRowSet object or + * a JdbcRowSet object that has implemented the SyncResolver + * interface, examines the conflicts row by row. It is a duplicate of the + * RowSet object being synchronized except that it contains only the data + * from the data source this is causing a conflict. All of the other column values are + * set to null. To navigate from one conflict value to another, a + * SyncResolver object provides the methods nextConflict and + * previousConflict. + *

    + * The SyncResolver interface also + * provides methods for doing the following: + *

      + *
    • finding out whether the conflict involved an update, a delete, or an insert + *
    • getting the value in the data source that caused the conflict + *
    • setting the value that should be in the data source if it needs to be changed + * or setting the value that should be in the RowSet object if it needs + * to be changed + *
    + *

    + * When the CachedRowSet method acceptChanges is called, it + * delegates to the RowSet object's SyncProvider object. + * How the writer provided by that SyncProvider object is implemented + * determines what level (grade) of checking for conflicts will be done. After all + * checking for conflicts is completed and one or more conflicts has been found, the method + * acceptChanges throws a SyncProviderException object. The + * application can catch the exception and use it to obtain a SyncResolver object. + *

    + * The application can then use SyncResolver methods to get information + * about each conflict and decide what to do. If the application logic or the user + * decides that a value in the RowSet object should be the one to + * persist, the application or user can overwrite the data source value with it. + *

    + * The comment for the SyncResolver interface has more detail. + * + *

    5.0 Related Specifications

    + * + *

    6.0 Related Documentation

    + * + */ +package javax.sql.rowset.spi; diff --git a/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package.html b/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package.html deleted file mode 100644 index 786b906fec9..00000000000 --- a/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package.html +++ /dev/null @@ -1,493 +0,0 @@ - - - - - - - - - javax.sql.rowset.spi - - - - -The standard classes and interfaces that a third party vendor has to -use in its implementation of a synchronization provider. These classes and -interfaces are referred to as the Service Provider Interface (SPI). To make it possible -for a RowSet object to use an implementation, the vendor must register -it with the SyncFactory singleton. (See the class comment for -SyncProvider for a full explanation of the registration process and -the naming convention to be used.) - -

    Table of Contents

    - - -

    1.0 Package Specification

    -

    -The following classes and interfaces make up the javax.sql.rowset.spi -package: -

      -
    • SyncFactory -
    • SyncProvider -
    • SyncFactoryException -
    • SyncProviderException -
    • SyncResolver -
    • XmlReader -
    • XmlWriter -
    • TransactionalWriter -
    -The following interfaces, in the javax.sql package, are also part of the SPI: -
      -
    • RowSetReader -
    • RowSetWriter -
    -

    -A SyncProvider implementation provides a disconnected RowSet -object with the mechanisms for reading data into it and for writing data that has been -modified in it -back to the underlying data source. A reader, a RowSetReader or -XMLReader object, reads data into a RowSet object when the -CachedRowSet methods execute or populate -are called. A writer, a RowSetWriter or XMLWriter -object, writes changes back to the underlying data source when the -CachedRowSet method acceptChanges is called. -

    -The process of writing changes in a RowSet object to its data source -is known as synchronization. The SyncProvider implementation that a -RowSet object is using determines the level of synchronization that the -RowSet object's writer uses. The various levels of synchronization are -referred to as grades. -

    -The lower grades of synchronization are -known as optimistic concurrency levels because they optimistically -assume that there will be no conflicts or very few conflicts. A conflict exists when -the same data modified in the RowSet object has also been modified -in the data source. Using the optimistic concurrency model means that if there -is a conflict, modifications to either the data source or the RowSet -object will be lost. -

    -Higher grades of synchronization are called pessimistic because they assume -that others will be accessing the data source and making modifications. These -grades set varying levels of locks to increase the chances that no conflicts -occur. -

    -The lowest level of synchronization is simply writing any changes made to the -RowSet object to its underlying data source. The writer does -nothing to check for conflicts. -If there is a conflict and the data -source values are overwritten, the changes other parties have made by to the data -source are lost. -

    -The RIXMLProvider implementation uses the lowest level -of synchronization and just writes RowSet changes to the data source. - -

    -For the next level up, the -writer checks to see if there are any conflicts, and if there are, -it does not write anything to the data source. The problem with this concurrency -level is that if another party has modified the corresponding data in the data source -since the RowSet object got its data, -the changes made to the RowSet object are lost. The -RIOptimisticProvider implementation uses this level of synchronization. -

    -At higher levels of synchronization, referred to as pessimistic concurrency, -the writer take steps to avoid conflicts by setting locks. Setting locks -can vary from setting a lock on a single row to setting a lock on a table -or the entire data source. The level of synchronization is therefore a tradeoff -between the ability of users to access the data source concurrently and the ability -of the writer to keep the data in the RowSet object and its data source -synchronized. -

    -It is a requirement that all disconnected RowSet objects -(CachedRowSet, FilteredRowSet, JoinRowSet, -and WebRowSet objects) obtain their SyncProvider objects -from the SyncFactory mechanism. -

    -The reference implementation (RI) provides two synchronization providers. -

      -
    • RIOptimisticProvider
      - The default provider that the SyncFactory instance will - supply to a disconnected RowSet object when no provider - implementation is specified.
      - This synchronization provider uses an optimistic concurrency model, - assuming that there will be few conflicts among users - who are accessing the same data in a database. It avoids - using locks; rather, it checks to see if there is a conflict - before trying to synchronize the RowSet object and the - data source. If there is a conflict, it does nothing, meaning that - changes to the RowSet object are not persisted to the data - source. -
    • RIXMLProvider
      - A synchronization provider that can be used with a - WebRowSet object, which is a rowset that can be written - in XML format or read from XML format. The - RIXMLProvider implementation does no checking at all for - conflicts and simply writes any updated data in the - WebRowSet object to the underlying data source. - WebRowSet objects use this provider when they are - dealing with XML data. -
    - -These SyncProvider implementations -are bundled with the reference implementation, which makes them always available to -RowSet implementations. -SyncProvider implementations make themselves available by being -registered with the SyncFactory singleton. When a RowSet -object requests a provider, by specifying it in the constructor or as an argument to the -CachedRowSet method setSyncProvider, -the SyncFactory singleton -checks to see if the requested provider has been registered with it. -If it has, the SyncFactory creates an instance of it and passes it to the -requesting RowSet object. -If the SyncProvider implementation that is specified has not been registered, -the SyncFactory singleton causes a SyncFactoryException object -to be thrown. If no provider is specified, -the SyncFactory singleton will create an instance of the default -provider implementation, RIOptimisticProvider, -and pass it to the requesting RowSet object. - -

    -If a WebRowSet object does not specify a provider in its constructor, the -SyncFactory will give it an instance of RIOptimisticProvider. -However, the constructor for WebRowSet is implemented to set the provider -to the RIXMLProvider, which reads and writes a RowSet object -in XML format. -

    -See the SyncProvider class -specification for further details. -

    -Vendors may develop a SyncProvider implementation with any one of the possible -levels of synchronization, thus giving RowSet objects a choice of -synchronization mechanisms. - -

    2.0 Service Provider Interface Architecture

    -2.1 Overview -

    -The Service Provider Interface provides a pluggable mechanism by which -SyncProvider implementations can be registered and then generated when -required. The lazy reference mechanism employed by the SyncFactory limits -unnecessary resource consumption by not creating an instance until it is -required by a disconnected -RowSet object. The SyncFactory class also provides -a standard API to configure logging options and streams that may be provided -by a particular SyncProvider implementation. -

    -2.2 Registering with the SyncFactory -

    -A third party SyncProvider implementation must be registered with the -SyncFactory in order for a disconnected RowSet object -to obtain it and thereby use its javax.sql.RowSetReader and -javax.sql.RowSetWriter -implementations. The following registration mechanisms are available to all -SyncProvider implementations: -

      -
    • System properties - Properties set at the command line. These -properties are set at run time and apply system-wide per invocation of the Java -application. See the section "Related Documentation" -further related information. - -
    • Property Files - Properties specified in a standard property file. -This can be specified using a System Property or by modifying a standard -property file located in the platform run-time. The -reference implementation of this technology includes a standard property -file than can be edited to add additional SyncProvider objects. - -
    • JNDI Context - Available providers can be registered on a JNDI -context. The SyncFactory will attempt to load SyncProvider -objects bound to the context and register them with the factory. This -context must be supplied to the SyncFactory for the mechanism to -function correctly. -
    -

    -Details on how to specify the system properties or properties in a property file -and how to configure the JNDI Context are explained in detail in the -SyncFactory class description. -

    -2.3 SyncFactory Provider Instance Generation Policies -

    -The SyncFactory generates a requested SyncProvider -object if the provider has been correctly registered. The -following policies are adhered to when either a disconnected RowSet object -is instantiated with a specified SyncProvider implementation or is -reconfigured at runtime with an alternative SyncProvider object. -

      -
    • If a SyncProvider object is specified and the SyncFactory -contains no reference to the provider, a SyncFactoryException is -thrown. - -
    • If a SyncProvider object is specified and the SyncFactory -contains a reference to the provider, the requested provider is supplied. - -
    • If no SyncProvider object is specified, the reference -implementation provider RIOptimisticProvider is supplied. -
    -

    -These policies are explored in more detail in the -SyncFactory class. - -

    3.0 SyncProvider Implementer's Guide

    - -3.1 Requirements -

    -A compliant SyncProvider implementation that is fully pluggable -into the SyncFactory must extend and implement all -abstract methods in the SyncProvider -class. In addition, an implementation must determine the -grade, locking and updatable view capabilities defined in the -SyncProvider class definition. One or more of the -SyncProvider description criteria must be supported. It -is expected that vendor implementations will offer a range of grade, locking, and -updatable view capabilities. -

    -Furthermore, the SyncProvider naming convention must be followed as -detailed in the SyncProvider class -description. -

    -3.2 Grades -

    -JSR 114 defines a set of grades to describe the quality of synchronization -a SyncProvider object can offer a disconnected RowSet -object. These grades are listed from the lowest quality of service to the highest. -

      -
    • GRADE_NONE - No synchronization with the originating data source is -provided. A SyncProvider implementation returning this grade will simply -attempt to write any data that has changed in the RowSet object to the -underlying data source, overwriting whatever is there. No attempt is made to compare -original values with current values to see if there is a conflict. The -RIXMLProvider is implemented with this grade. - -
    • GRADE_CHECK_MODIFIED_AT_COMMIT - A low grade of optimistic synchronization. -A SyncProvider implementation returning this grade -will check for conflicts in rows that have changed between the last synchronization -and the current synchronization under way. Any changes in the originating data source -that have been modified will not be reflected in the disconnected RowSet -object. If there are no conflicts, changes in the RowSet object will be -written to the data source. If there are conflicts, no changes are written. -The RIOptimisticProvider implementation uses this grade. - -
    • GRADE_CHECK_ALL_AT_COMMIT - A high grade of optimistic synchronization. -A SyncProvider implementation returning this grade -will check all rows, including rows that have not changed in the disconnected -RowSet object. In this way, any changes to rows in the underlying -data source will be reflected in the disconnected RowSet object -when the synchronization finishes successfully. - -
    • GRADE_LOCK_WHEN_MODIFIED - A pessimistic grade of synchronization. -SyncProvider implementations returning this grade will lock -the row in the originating data source that corresponds to the row being changed -in the RowSet object to reduce the possibility of other -processes modifying the same data in the data source. - -
    • GRADE_LOCK_WHEN_LOADED - A higher pessimistic synchronization grade. -A SyncProvider implementation returning this grade will lock -the entire view and/or table affected by the original query used to -populate a RowSet object. -
    -

    -3.3 Locks -

    -JSR 114 defines a set of constants that specify whether any locks have been -placed on a RowSet object's underlying data source and, if so, -on which constructs the locks are placed. These locks will remain on the data -source while the RowSet object is disconnected from the data source. -

    -These constants should be considered complementary to the -grade constants. The default setting for the majority of grade settings requires -that no data source locks remain when a RowSet object is disconnected -from its data source. -The grades GRADE_LOCK_WHEN_MODIFIED and -GRADE_LOCK_WHEN_LOADED allow a disconnected RowSet object -to have a fine-grained control over the degree of locking. -

      -
    • DATASOURCE_NO_LOCK - No locks remain on the originating data source. -This is the default lock setting for all SyncProvider implementations -unless otherwise directed by a RowSet object. - -
    • DATASOURCE_ROW_LOCK - A lock is placed on the rows that are touched by -the original SQL query used to populate the RowSet object. - -
    • DATASOURCE_TABLE_LOCK - A lock is placed on all tables that are touched -by the query that was used to populate the RowSet object. - -
    • DATASOURCE_DB_LOCK -A lock is placed on the entire data source that is used by the RowSet -object. -
    -

    -3.4 Updatable Views -

    -A RowSet object may be populated with data from an SQL VIEW. -The following constants indicate whether a SyncProvider object can -update data in the table or tables from which the VIEW was derived. -

      -
    • UPDATABLE_VIEW_SYNC -Indicates that a SyncProvider implementation supports synchronization -to the table or tables from which the SQL VIEW used to populate -a RowSet object is derived. - -
    • NONUPDATABLE_VIEW_SYNC -Indicates that a SyncProvider implementation does not support -synchronization to the table or tables from which the SQL VIEW -used to populate a RowSet object is derived. -
    -

    -3.5 Usage of SyncProvider Grading and Locking -

    -In the example below, the reference CachedRowSetImpl implementation -reconfigures its current SyncProvider object by calling the -setSyncProvider method.
    - -

    -    CachedRowSetImpl crs = new CachedRowSetImpl();
    -    crs.setSyncProvider("com.foo.bar.HASyncProvider");
    -
    - An application can retrieve the SyncProvider object currently in use -by a disconnected RowSet object. It can also retrieve the -grade of synchronization with which the provider was implemented and the degree of -locking currently in use. In addition, an application has the flexibility to set -the degree of locking to be used, which can increase the possibilities for successful -synchronization. These operation are shown in the following code fragment. -
    -    SyncProvider sync = crs.getSyncProvider();
    -
    -    switch (sync.getProviderGrade()) {
    -    case: SyncProvider.GRADE_CHECK_ALL_AT_COMMIT
    -         //A high grade of optimistic synchronization
    -    break;
    -    case: SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT
    -         //A low grade of optimistic synchronization
    -    break;
    -    case: SyncProvider.GRADE_LOCK_WHEN_LOADED
    -         // A pessimistic synchronization grade
    -    break;
    -    case: SyncProvider.GRADE_LOCK_WHEN_MODIFIED
    -         // A pessimistic synchronization grade
    -    break;
    -    case: SyncProvider.GRADE_NONE
    -      // No synchronization with the originating data source provided
    -    break;
    -    }
    -
    -    switch (sync.getDataSourcLock() {
    -      case: SyncProvider.DATASOURCE_DB_LOCK
    -       // A lock is placed on the entire datasource that is used by the
    -       // RowSet object
    -       break;
    -
    -      case: SyncProvider.DATASOURCE_NO_LOCK
    -       // No locks remain on the  originating data source.
    -      break;
    -
    -      case: SyncProvider.DATASOURCE_ROW_LOCK
    -       // A lock is placed on the rows that are  touched by the original
    -       // SQL statement used to populate
    -       // the RowSet object that is using the SyncProvider
    -       break;
    -
    -      case: DATASOURCE_TABLE_LOCK
    -       // A lock is placed on  all tables that are touched by the original
    -       // SQL statement used to populated
    -       // the RowSet object that is using the SyncProvider
    -       break;
    -
    -
    - It is also possible using the static utility method in the -SyncFactory class to determine the list of SyncProvider -implementations currently registered with the SyncFactory. - -
    -       Enumeration e = SyncFactory.getRegisteredProviders();
    -
    - - -

    4.0 Resolving Synchronization Conflicts

    - -The interface SyncResolver provides a way for an application to -decide manually what to do when a conflict occurs. When the CachedRowSet -method acceptChanges finishes and has detected one or more conflicts, -it throws a SyncProviderException object. An application can -catch the exception and -have it retrieve a SyncResolver object by calling the method -SyncProviderException.getSyncResolver(). -

    -A SyncResolver object, which is a special kind of -CachedRowSet object or -a JdbcRowSet object that has implemented the SyncResolver -interface, examines the conflicts row by row. It is a duplicate of the -RowSet object being synchronized except that it contains only the data -from the data source this is causing a conflict. All of the other column values are -set to null. To navigate from one conflict value to another, a -SyncResolver object provides the methods nextConflict and -previousConflict. -

    -The SyncResolver interface also -provides methods for doing the following: -

      -
    • finding out whether the conflict involved an update, a delete, or an insert -
    • getting the value in the data source that caused the conflict -
    • setting the value that should be in the data source if it needs to be changed - or setting the value that should be in the RowSet object if it needs - to be changed -
    -

    -When the CachedRowSet method acceptChanges is called, it -delegates to the RowSet object's SyncProvider object. -How the writer provided by that SyncProvider object is implemented -determines what level (grade) of checking for conflicts will be done. After all -checking for conflicts is completed and one or more conflicts has been found, the method -acceptChanges throws a SyncProviderException object. The -application can catch the exception and use it to obtain a SyncResolver object. -

    -The application can then use SyncResolver methods to get information -about each conflict and decide what to do. If the application logic or the user -decides that a value in the RowSet object should be the one to -persist, the application or user can overwrite the data source value with it. -

    -The comment for the SyncResolver interface has more detail. - -

    5.0 Related Specifications

    - -

    6.0 Related Documentation

    - - - - diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 1f223945b05..8b3bfa1ec5f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -291,7 +291,7 @@ public class Attr extends JCTree.Visitor { ((v.flags() & HASINIT) != 0 || !((base == null || - (base.hasTag(IDENT) && TreeInfo.name(base) == names._this)) && + TreeInfo.isThisQualifier(base)) && isAssignableAsBlankFinal(v, env)))) { if (v.isResourceVariable()) { //TWR resource log.error(pos, Errors.TryResourceMayNotBeAssigned(v)); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index 86849f4e41a..1fb91ebcd5f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -2391,31 +2391,18 @@ public class Flow { } public void visitAssign(JCAssign tree) { - JCTree lhs = TreeInfo.skipParens(tree.lhs); - if (!isIdentOrThisDotIdent(lhs)) - scanExpr(lhs); + if (!TreeInfo.isIdentOrThisDotIdent(tree.lhs)) + scanExpr(tree.lhs); scanExpr(tree.rhs); - letInit(lhs); - } - private boolean isIdentOrThisDotIdent(JCTree lhs) { - if (lhs.hasTag(IDENT)) - return true; - if (!lhs.hasTag(SELECT)) - return false; - - JCFieldAccess fa = (JCFieldAccess)lhs; - return fa.selected.hasTag(IDENT) && - ((JCIdent)fa.selected).name == names._this; + letInit(tree.lhs); } // check fields accessed through this. are definitely // assigned before reading their value public void visitSelect(JCFieldAccess tree) { super.visitSelect(tree); - JCTree sel = TreeInfo.skipParens(tree.selected); if (enforceThisDotInit && - sel.hasTag(IDENT) && - ((JCIdent)sel).name == names._this && + TreeInfo.isThisQualifier(tree.selected) && tree.sym.kind == VAR) { checkInit(tree.pos(), (VarSymbol)tree.sym); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java new file mode 100644 index 00000000000..c3afaea1945 --- /dev/null +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java @@ -0,0 +1,550 @@ +/* + * 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. + */ + +package com.sun.tools.javac.launcher; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URI; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import javax.lang.model.SourceVersion; +import javax.lang.model.element.NestingKind; +import javax.lang.model.element.TypeElement; +import javax.tools.FileObject; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileManager.Location; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.code.Source; +import com.sun.tools.javac.resources.LauncherProperties.Errors; +import com.sun.tools.javac.util.JCDiagnostic.Error; + +import jdk.internal.misc.VM; + +import static javax.tools.JavaFileObject.Kind.SOURCE; + +/** + * Compiles a source file, and executes the main method it contains. + * + *

    This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

    + */ +public class Main { + /** + * An exception used to report errors. + */ + public class Fault extends Exception { + private static final long serialVersionUID = 1L; + Fault(Error error) { + super(Main.this.getMessage(error)); + } + } + + /** + * Compiles a source file, and executes the main method it contains. + * + *

    This is normally invoked from the Java launcher, either when + * the {@code --source} option is used, or when the first argument + * that is not part of a runtime option ends in {@code .java}. + * + *

    The first entry in the {@code args} array is the source file + * to be compiled and run; all subsequent entries are passed as + * arguments to the main method of the first class found in the file. + * + *

    If any problem occurs before executing the main class, it will + * be reported to the standard error stream, and the the JVM will be + * terminated by calling {@code System.exit} with a non-zero return code. + * + * @param args the arguments + * @throws Throwable if the main method throws an exception + */ + public static void main(String... args) throws Throwable { + try { + new Main(System.err).run(VM.getRuntimeArguments(), args); + } catch (Fault f) { + System.err.println(f.getMessage()); + System.exit(1); + } catch (InvocationTargetException e) { + // leave VM to handle the stacktrace, in the standard manner + throw e.getTargetException(); + } + } + + /** Stream for reporting errors, such as compilation errors. */ + private PrintWriter out; + + /** + * Creates an instance of this class, providing a stream to which to report + * any errors. + * + * @param out the stream + */ + public Main(PrintStream out) { + this(new PrintWriter(new OutputStreamWriter(out), true)); + } + + /** + * Creates an instance of this class, providing a stream to which to report + * any errors. + * + * @param out the stream + */ + public Main(PrintWriter out) { + this.out = out; + } + + /** + * Compiles a source file, and executes the main method it contains. + * + *

    The first entry in the {@code args} array is the source file + * to be compiled and run; all subsequent entries are passed as + * arguments to the main method of the first class found in the file. + * + *

    Options for {@code javac} are obtained by filtering the runtime arguments. + * + *

    If the main method throws an exception, it will be propagated in an + * {@code InvocationTargetException}. In that case, the stack trace of the + * target exception will be truncated such that the main method will be the + * last entry on the stack. In other words, the stack frames leading up to the + * invocation of the main method will be removed. + * + * @param runtimeArgs the runtime arguments + * @param args the arguments + * @throws Fault if a problem is detected before the main method can be executed + * @throws InvocationTargetException if the main method throws an exception + */ + public void run(String[] runtimeArgs, String[] args) throws Fault, InvocationTargetException { + Path file = getFile(args); + + Context context = new Context(); + String mainClassName = compile(file, getJavacOpts(runtimeArgs), context); + + String[] appArgs = Arrays.copyOfRange(args, 1, args.length); + execute(mainClassName, appArgs, context); + } + + /** + * Returns the path for the filename found in the first of an array of arguments. + * + * @param args the array + * @return the path + * @throws Fault if there is a problem determining the path, or if the file does not exist + */ + private Path getFile(String[] args) throws Fault { + if (args.length == 0) { + // should not happen when invoked from launcher + throw new Fault(Errors.NoArgs); + } + Path file; + try { + file = Paths.get(args[0]); + } catch (InvalidPathException e) { + throw new Fault(Errors.InvalidFilename(args[0])); + } + if (!Files.exists(file)) { + // should not happen when invoked from launcher + throw new Fault(Errors.FileNotFound(file)); + } + return file; + } + + /** + * Reads a source file, ignoring the first line if it is not a Java source file and + * it begins with {@code #!}. + * + *

    If it is not a Java source file, and if the first two bytes are {@code #!}, + * indicating a "magic number" of an executable text file, the rest of the first line + * up to but not including the newline is ignored. All characters after the first two are + * read in the {@link Charset#defaultCharset default platform encoding}. + * + * @param file the file + * @return a file object containing the content of the file + * @throws Fault if an error occurs while reading the file + */ + private JavaFileObject readFile(Path file) throws Fault { + // use a BufferedInputStream to guarantee that we can use mark and reset. + try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(file))) { + boolean ignoreFirstLine; + if (file.getFileName().toString().endsWith(".java")) { + ignoreFirstLine = false; + } else { + in.mark(2); + ignoreFirstLine = (in.read() == '#') && (in.read() == '!'); + if (!ignoreFirstLine) { + in.reset(); + } + } + try (BufferedReader r = new BufferedReader(new InputStreamReader(in, Charset.defaultCharset()))) { + StringBuilder sb = new StringBuilder(); + if (ignoreFirstLine) { + r.readLine(); + sb.append("\n"); // preserve line numbers + } + char[] buf = new char[1024]; + int n; + while ((n = r.read(buf, 0, buf.length)) != -1) { + sb.append(buf, 0, n); + } + return new SimpleJavaFileObject(file.toUri(), SOURCE) { + @Override + public String getName() { + return file.toString(); + } + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return sb; + } + @Override + public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) { + // reject package-info and module-info; accept other names + return (kind == JavaFileObject.Kind.SOURCE) + && SourceVersion.isIdentifier(simpleName); + } + @Override + public String toString() { + return "JavacSourceLauncher[" + file + "]"; + } + }; + } + } catch (IOException e) { + throw new Fault(Errors.CantReadFile(file, e)); + } + } + + /** + * Returns the subset of the runtime arguments that are relevant to {@code javac}. + * Generally, the relevant options are those for setting paths and for configuring the + * module system. + * + * @param runtimeArgs the runtime arguments + * @return the subset of the runtime arguments + **/ + private List getJavacOpts(String... runtimeArgs) throws Fault { + List javacOpts = new ArrayList<>(); + + String sourceOpt = System.getProperty("jdk.internal.javac.source"); + if (sourceOpt != null) { + Source source = Source.lookup(sourceOpt); + if (source == null) { + throw new Fault(Errors.InvalidValueForSource(sourceOpt)); + } + javacOpts.addAll(List.of("--release", sourceOpt)); + } + + for (int i = 0; i < runtimeArgs.length; i++) { + String arg = runtimeArgs[i]; + String opt = arg, value = null; + if (arg.startsWith("--")) { + int eq = arg.indexOf('='); + if (eq > 0) { + opt = arg.substring(0, eq); + value = arg.substring(eq + 1); + } + } + switch (opt) { + // The following options all expect a value, either in the following + // position, or after '=', for options beginning "--". + case "--class-path": case "-classpath": case "-cp": + case "--module-path": case "-p": + case "--add-exports": + case "--add-modules": + case "--limit-modules": + case "--patch-module": + case "--upgrade-module-path": + if (value == null) { + if (i== runtimeArgs.length - 1) { + // should not happen when invoked from launcher + throw new Fault(Errors.NoValueForOption(opt)); + } + value = runtimeArgs[++i]; + } + if (opt.equals("--add-modules") && value.equals("ALL-DEFAULT")) { + // this option is only supported at run time; + // it is not required or supported at compile time + break; + } + javacOpts.add(opt); + javacOpts.add(value); + break; + case "--enable-preview": + javacOpts.add(opt); + if (sourceOpt == null) { + throw new Fault(Errors.EnablePreviewRequiresSource); + } + break; + default: + // ignore all other runtime args + } + } + + // add implicit options + javacOpts.add("-proc:none"); + + return javacOpts; + } + + /** + * Compiles a source file, placing the class files in a map in memory. + * Any messages generated during compilation will be written to the stream + * provided when this object was created. + * + * @param file the source file + * @param javacOpts compilation options for {@code javac} + * @param context the context for the compilation + * @return the name of the first class found in the source file + * @throws Fault if any compilation errors occur, or if no class was found + */ + private String compile(Path file, List javacOpts, Context context) throws Fault { + JavaFileObject fo = readFile(file); + + JavacTool javaCompiler = JavacTool.create(); + StandardJavaFileManager stdFileMgr = javaCompiler.getStandardFileManager(null, null, null); + try { + stdFileMgr.setLocation(StandardLocation.SOURCE_PATH, Collections.emptyList()); + } catch (IOException e) { + throw new java.lang.Error("unexpected exception from file manager", e); + } + JavaFileManager fm = context.getFileManager(stdFileMgr); + JavacTask t = javaCompiler.getTask(out, fm, null, javacOpts, null, List.of(fo)); + MainClassListener l = new MainClassListener(t); + Boolean ok = t.call(); + if (!ok) { + throw new Fault(Errors.CompilationFailed); + } + if (l.mainClass == null) { + throw new Fault(Errors.NoClass); + } + String mainClassName = l.mainClass.getQualifiedName().toString(); + return mainClassName; + } + + /** + * Invokes the {@code main} method of a specified class, using a class loader that + * will load recently compiled classes from memory. + * + * @param mainClassName the class to be executed + * @param appArgs the arguments for the {@code main} method + * @param context the context for the class to be executed + * @throws Fault if there is a problem finding or invoking the {@code main} method + * @throws InvocationTargetException if the {@code main} method throws an exception + */ + private void execute(String mainClassName, String[] appArgs, Context context) + throws Fault, InvocationTargetException { + ClassLoader cl = context.getClassLoader(ClassLoader.getSystemClassLoader()); + try { + Class appClass = Class.forName(mainClassName, true, cl); + if (appClass.getClassLoader() != cl) { + throw new Fault(Errors.UnexpectedClass(mainClassName)); + } + Method main = appClass.getDeclaredMethod("main", String[].class); + int PUBLIC_STATIC = Modifier.PUBLIC | Modifier.STATIC; + if ((main.getModifiers() & PUBLIC_STATIC) != PUBLIC_STATIC) { + throw new Fault(Errors.MainNotPublicStatic); + } + if (!main.getReturnType().equals(void.class)) { + throw new Fault(Errors.MainNotVoid); + } + main.setAccessible(true); + main.invoke(0, (Object) appArgs); + } catch (ClassNotFoundException e) { + throw new Fault(Errors.CantFindClass(mainClassName)); + } catch (NoSuchMethodException e) { + throw new Fault(Errors.CantFindMainMethod(mainClassName)); + } catch (IllegalAccessException e) { + throw new Fault(Errors.CantAccessMainMethod(mainClassName)); + } catch (InvocationTargetException e) { + // remove stack frames for source launcher + int invocationFrames = e.getStackTrace().length; + Throwable target = e.getTargetException(); + StackTraceElement[] targetTrace = target.getStackTrace(); + target.setStackTrace(Arrays.copyOfRange(targetTrace, 0, targetTrace.length - invocationFrames)); + throw e; + } + } + + private static final String bundleName = "com.sun.tools.javac.resources.launcher"; + private ResourceBundle resourceBundle = null; + private String errorPrefix; + + /** + * Returns a localized string from a resource bundle. + * + * @param error the error for which to get the localized text + * @return the localized string + */ + private String getMessage(Error error) { + String key = error.key(); + Object[] args = error.getArgs(); + try { + if (resourceBundle == null) { + resourceBundle = ResourceBundle.getBundle(bundleName); + errorPrefix = resourceBundle.getString("launcher.error"); + } + String resource = resourceBundle.getString(key); + String message = MessageFormat.format(resource, args); + return errorPrefix + message; + } catch (MissingResourceException e) { + return "Cannot access resource; " + key + Arrays.toString(args); + } + } + + /** + * A listener to detect the first class found in a compilation. + */ + static class MainClassListener implements TaskListener { + TypeElement mainClass; + + MainClassListener(JavacTask t) { + t.addTaskListener(this); + } + + @Override + public void started(TaskEvent ev) { + if (ev.getKind() == TaskEvent.Kind.ANALYZE && mainClass == null) { + TypeElement te = ev.getTypeElement(); + if (te.getNestingKind() == NestingKind.TOP_LEVEL) { + mainClass = te; + } + } + } + } + + /** + * An object to encapulate the set of in-memory classes, such that + * they can be written by a file manager and subsequently used by + * a class loader. + */ + private static class Context { + private Map inMemoryClasses = new HashMap<>(); + + JavaFileManager getFileManager(StandardJavaFileManager delegate) { + return new MemoryFileManager(inMemoryClasses, delegate); + } + + ClassLoader getClassLoader(ClassLoader parent) { + return new MemoryClassLoader(inMemoryClasses, parent); + } + } + + /** + * An in-memory file manager. + * + *

    Class files (of kind {@link JavaFileObject.Kind#CLASS CLASS} written to + * {@link StandardLocation#CLASS_OUTPUT} will be written to an in-memory cache. + * All other file manager operations will be delegated to a specified file manager. + */ + private static class MemoryFileManager extends ForwardingJavaFileManager { + private final Map map; + + MemoryFileManager(Map map, JavaFileManager delegate) { + super(delegate); + this.map = map; + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, + JavaFileObject.Kind kind, FileObject sibling) throws IOException { + if (location == StandardLocation.CLASS_OUTPUT && kind == JavaFileObject.Kind.CLASS) { + return createInMemoryClassFile(className); + } else { + return super.getJavaFileForOutput(location, className, kind, sibling); + } + } + + private JavaFileObject createInMemoryClassFile(String className) { + URI uri = URI.create("memory:///" + className.replace('.', '/') + ".class"); + return new SimpleJavaFileObject(uri, JavaFileObject.Kind.CLASS) { + @Override + public OutputStream openOutputStream() { + return new ByteArrayOutputStream() { + @Override + public void close() throws IOException { + super.close(); + map.put(className, toByteArray()); + } + }; + } + }; + } + } + + /** + * An in-memory classloader, that uses an in-memory cache written by {@link MemoryFileManager}. + * + *

    The classloader uses the standard parent-delegation model, just providing + * {@code findClass} to find classes in the in-memory cache. + */ + private static class MemoryClassLoader extends ClassLoader { + private final Map map; + + MemoryClassLoader(Map map, ClassLoader parent) { + super(parent); + this.map = map; + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + byte[] bytes = map.get(name); + if (bytes == null) { + throw new ClassNotFoundException(name); + } + return defineClass(name, bytes, 0, bytes.length); + } + } +} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher.properties new file mode 100644 index 00000000000..1721f9b5fc4 --- /dev/null +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher.properties @@ -0,0 +1,136 @@ +# +# 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. +# + +# Messages in this file which use "placeholders" for values (e.g. {0}, {1}) +# are preceded by a stylized comment describing the type of the corresponding +# values. +# The simple types currently in use are: +# +# annotation annotation compound +# boolean true or false +# diagnostic a sub-message; see compiler.misc.* +# fragment similar to 'message segment', but with more specific type +# modifier a Java modifier; e.g. public, private, protected +# file a file URL +# file object a file URL - similar to 'file' but typically used for source/class files, hence more specific +# flag a Flags.Flag instance +# name a name, typically a Java identifier +# number an integer +# option name the name of a command line option +# source version a source version number, such as 1.5, 1.6, 1.7 +# string a general string +# symbol the name of a declared type +# symbol kind the kind of a symbol (i.e. method, variable) +# kind name an informative description of the kind of a declaration; see compiler.misc.kindname.* +# token the name of a non-terminal in source code; see compiler.misc.token.* +# type a Java type; e.g. int, X, X +# object a Java object (unspecified) +# unused the value is not used in this message +# +# The following compound types are also used: +# +# collection of X a comma-separated collection of items; e.g. collection of type +# list of X a comma-separated list of items; e.g. list of type +# set of X a comma-separated set of items; e.g. set of modifier +# +# These may be composed: +# +# list of type or message segment +# +# The following type aliases are supported: +# +# message segment --> diagnostic or fragment +# file name --> file, path or file object +# +# Custom comments are supported in parenthesis i.e. +# +# number (classfile major version) +# +# These comments are used internally in order to generate an enum-like class declaration containing +# a method/field for each of the diagnostic keys listed here. Those methods/fields can then be used +# by javac code to build diagnostics in a type-safe fashion. +# +# In addition, these comments are verified by the jtreg test test/tools/javac/diags/MessageInfo, +# using info derived from the collected set of examples in test/tools/javac/diags/examples. +# MessageInfo can also be run as a standalone utility providing more facilities +# for manipulating this file. For more details, see MessageInfo.java. + +## All errors are preceded by this string. +launcher.error=\ + error:\u0020 + +launcher.err.no.args=\ + no filename + +# 0: string +launcher.err.invalid.filename=\ + invalid filename: {0} + +# 0: path +launcher.err.file.not.found=\ + file not found: {0} + +launcher.err.compilation.failed=\ + compilation failed + +launcher.err.no.class=\ + no class declared in file + +launcher.err.main.not.public.static=\ + ''main'' method is not declared ''public static'' + +launcher.err.main.not.void=\ + ''main'' method is not declared with a return type of ''void'' + +# 0: string +launcher.err.cant.find.class=\ + can''t find class: {0} + +# 0: string +launcher.err.unexpected.class=\ + class found on application class path: {0} + +# 0: string +launcher.err.cant.find.main.method=\ + can''t find main(String[]) method in class: {0} + +# 0: string +launcher.err.cant.access.main.method=\ + can''t access main method in class: {0} + +# 0: path, 1: object +launcher.err.cant.read.file=\ + error reading file {0}: {1} + +# 0: string +launcher.err.no.value.for.option=\ + no value given for option: {0} + +# 0: string +launcher.err.invalid.value.for.source=\ + invalid value for --source option: {0} + +launcher.err.enable.preview.requires.source=\ + --enable-preview must be used with --source diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java index 27553a36027..bcc14ac0762 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -148,6 +148,36 @@ public class TreeInfo { } } + /** Is this tree a 'this' identifier? + */ + public static boolean isThisQualifier(JCTree tree) { + switch (tree.getTag()) { + case PARENS: + return isThisQualifier(skipParens(tree)); + case IDENT: { + JCIdent id = (JCIdent)tree; + return id.name == id.name.table.names._this; + } + default: + return false; + } + } + + /** Is this tree an identifier, possibly qualified by 'this'? + */ + public static boolean isIdentOrThisDotIdent(JCTree tree) { + switch (tree.getTag()) { + case PARENS: + return isIdentOrThisDotIdent(skipParens(tree)); + case IDENT: + return true; + case SELECT: + return isThisQualifier(((JCFieldAccess)tree).selected); + default: + return false; + } + } + /** Is this a call to super? */ public static boolean isSuperCall(JCTree tree) { diff --git a/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp b/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp index c093b75a490..eeae66e7cde 100644 --- a/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp +++ b/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -26,6 +26,9 @@ #include #include "jni_util.h" #include "impl/ecc_impl.h" +#include "sun_security_ec_ECDHKeyAgreement.h" +#include "sun_security_ec_ECKeyPairGenerator.h" +#include "sun_security_ec_ECDSASignature.h" #define ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException" #define INVALID_ALGORITHM_PARAMETER_EXCEPTION \ diff --git a/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp b/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp index 223002661f2..8bf3f441532 100644 --- a/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp +++ b/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp @@ -37,7 +37,13 @@ #include #include #include - +#include "sun_security_mscapi_Key.h" +#include "sun_security_mscapi_KeyStore.h" +#include "sun_security_mscapi_PRNG.h" +#include "sun_security_mscapi_RSACipher.h" +#include "sun_security_mscapi_RSAKeyPairGenerator.h" +#include "sun_security_mscapi_RSAPublicKey.h" +#include "sun_security_mscapi_RSASignature.h" #define OID_EKU_ANY "2.5.29.37.0" @@ -1313,7 +1319,7 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_removeCertificate * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_destroyKeyContainer - (JNIEnv *env, jclass clazz, jstring keyContainerName) + (JNIEnv *env, jobject clazz, jstring keyContainerName) { HCRYPTPROV hCryptProv = NULL; const char* pszKeyContainerName = NULL; @@ -1435,7 +1441,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSACipher_encryptDecrypt * Signature: (J)[B */ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getPublicKeyBlob - (JNIEnv *env, jclass clazz, jlong hCryptKey) { + (JNIEnv *env, jobject clazz, jlong hCryptKey) { jbyteArray blob = NULL; DWORD dwBlobLen; @@ -1486,7 +1492,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getPublicKeyB * Signature: ([B)[B */ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getExponent - (JNIEnv *env, jclass clazz, jbyteArray jKeyBlob) { + (JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) { jbyteArray exponent = NULL; jbyte* exponentBytes = NULL; @@ -1542,7 +1548,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getExponent * Signature: ([B)[B */ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getModulus - (JNIEnv *env, jclass clazz, jbyteArray jKeyBlob) { + (JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) { jbyteArray modulus = NULL; jbyte* modulusBytes = NULL; @@ -1815,7 +1821,7 @@ jbyteArray generateKeyBlob( * Signature: (I[B[B[B[B[B[B[B[B)[B */ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_KeyStore_generatePrivateKeyBlob - (JNIEnv *env, jclass clazz, + (JNIEnv *env, jobject clazz, jint jKeyBitLength, jbyteArray jModulus, jbyteArray jPublicExponent, @@ -1852,7 +1858,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSASignature_generatePubli * Signature: ([BLjava/lang/String;I)Lsun/security/mscapi/RSAPrivateKey; */ JNIEXPORT jobject JNICALL Java_sun_security_mscapi_KeyStore_storePrivateKey - (JNIEnv *env, jclass clazz, jbyteArray keyBlob, jstring keyContainerName, + (JNIEnv *env, jobject clazz, jbyteArray keyBlob, jstring keyContainerName, jint keySize) { HCRYPTPROV hCryptProv = NULL; diff --git a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c index b23910b5469..064ad2f9933 100644 --- a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c +++ b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c @@ -30,6 +30,13 @@ #include "jni_util.h" #include "nativeCrypto.h" #include "nativeFunc.h" +#include "com_oracle_security_ucrypto_NativeCipher.h" +#include "com_oracle_security_ucrypto_NativeDigest.h" +#include "com_oracle_security_ucrypto_NativeKey.h" +#include "com_oracle_security_ucrypto_NativeKey.h" +#include "com_oracle_security_ucrypto_NativeRSACipher.h" +#include "com_oracle_security_ucrypto_NativeRSASignature.h" +#include "com_oracle_security_ucrypto_UcryptoProvider.h" /* * Dumps out byte array in hex with and name and length info diff --git a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCryptoMD.c b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCryptoMD.c index bac407d3f72..6bc951fa3ba 100644 --- a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCryptoMD.c +++ b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCryptoMD.c @@ -30,7 +30,7 @@ #include "jni_util.h" #include "nativeCrypto.h" #include "nativeFunc.h" - +#include "com_oracle_security_ucrypto_NativeDigestMD.h" extern void throwOutOfMemoryError(JNIEnv *env, const char *msg); extern jbyte* getBytes(JNIEnv *env, jbyteArray bytes, int offset, int len); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java index c227c4d82c4..c642da22f2b 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java @@ -49,6 +49,7 @@ import sun.jvm.hotspot.code.NMethod; import sun.jvm.hotspot.debugger.Address; import sun.jvm.hotspot.debugger.OopHandle; import sun.jvm.hotspot.classfile.ClassLoaderDataGraph; +import sun.jvm.hotspot.memory.FileMapInfo; import sun.jvm.hotspot.memory.SymbolTable; import sun.jvm.hotspot.memory.SystemDictionary; import sun.jvm.hotspot.memory.Universe; @@ -89,6 +90,7 @@ import sun.jvm.hotspot.ui.tree.OopTreeNodeAdapter; import sun.jvm.hotspot.ui.tree.SimpleTreeNode; import sun.jvm.hotspot.utilities.AddressOps; import sun.jvm.hotspot.utilities.Assert; +import sun.jvm.hotspot.utilities.CompactHashTable; import sun.jvm.hotspot.utilities.HeapProgressThunk; import sun.jvm.hotspot.utilities.LivenessPathElement; import sun.jvm.hotspot.utilities.MethodArray; @@ -637,12 +639,22 @@ public class CommandProcessor { }, new Command("symboldump", "symboldump", false) { public void doit(Tokens t) { - SymbolTable.getTheTable().symbolsDo(new SymbolTable.SymbolVisitor() { + SymbolTable theTable = SymbolTable.getTheTable(); + theTable.symbolsDo(new SymbolTable.SymbolVisitor() { public void visit(Symbol sym) { sym.printValueOn(out); out.println(); } }); + CompactHashTable sharedTable = theTable.getSharedTable(); + if (sharedTable != null) { + sharedTable.symbolsDo(new CompactHashTable.SymbolVisitor() { + public void visit(Symbol sym) { + sym.printValueOn(out); + out.println(); + } + }); + } } }, new Command("flags", "flags [ flag | -nd ]", false) { @@ -1048,6 +1060,15 @@ public class CommandProcessor { } if (node == null) { Type type = VM.getVM().getTypeDataBase().guessTypeForAddress(a); + if (type == null && VM.getVM().isSharingEnabled()) { + // Check if the value falls in the _md_region + Address loc1 = a.getAddressAt(0); + FileMapInfo cdsFileMapInfo = VM.getVM().getFileMapInfo(); + if (cdsFileMapInfo.inCopiedVtableSpace(loc1)) { + type = cdsFileMapInfo.getTypeForVptrAddress(loc1); + } + + } if (type != null) { out.println("Type is " + type.getName() + " (size of " + type.getSize() + ")"); node = new CTypeTreeNodeAdapter(a, type, null); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/StringTable.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/StringTable.java deleted file mode 100644 index 8bf42f0415e..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/StringTable.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.memory; - -import java.io.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.utilities.*; - -public class StringTable extends sun.jvm.hotspot.utilities.Hashtable { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("StringTable"); - theTableField = type.getAddressField("_the_table"); - } - - // Fields - private static AddressField theTableField; - - // Accessors - public static StringTable getTheTable() { - Address tmp = theTableField.getValue(); - return (StringTable) VMObjectFactory.newObject(StringTable.class, tmp); - } - - public StringTable(Address addr) { - super(addr); - } - - public interface StringVisitor { - public void visit(Instance string); - } - - public void stringsDo(StringVisitor visitor) { - ObjectHeap oh = VM.getVM().getObjectHeap(); - int numBuckets = tableSize(); - for (int i = 0; i < numBuckets; i++) { - for (HashtableEntry e = (HashtableEntry) bucket(i); e != null; - e = (HashtableEntry) e.next()) { - Instance s = (Instance)oh.newOop(e.literalValue().addOffsetToAsOopHandle(0)); - visitor.visit(s); - } - } - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SymbolTable.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SymbolTable.java index e2231b53ecb..f1082d5538f 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SymbolTable.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SymbolTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -65,6 +65,10 @@ public class SymbolTable extends sun.jvm.hotspot.utilities.Hashtable { return table; } + public CompactHashTable getSharedTable() { + return sharedTable; + } + public static long getSeed() { return (long) seedField.getValue(); } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java index bbfe6e65e99..05e695386d4 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -79,7 +79,6 @@ public class VM { private Universe universe; private ObjectHeap heap; private SymbolTable symbols; - private StringTable strings; private SystemDictionary dict; private ClassLoaderDataGraph cldGraph; private Threads threads; @@ -655,13 +654,6 @@ public class VM { return symbols; } - public StringTable getStringTable() { - if (strings == null) { - strings = StringTable.getTheTable(); - } - return strings; - } - public SystemDictionary getSystemDictionary() { if (dict == null) { dict = new SystemDictionary(); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java index 0d81604e7d5..7897191b390 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java @@ -129,7 +129,6 @@ public class HeapSummary extends Tool { } System.out.println(); - printInternStringStatistics(); } // Helper methods @@ -258,41 +257,4 @@ public class HeapSummary extends Tool { return -1; } } - - private void printInternStringStatistics() { - class StringStat implements StringTable.StringVisitor { - private int count; - private long size; - private OopField stringValueField; - - StringStat() { - VM vm = VM.getVM(); - SystemDictionary sysDict = vm.getSystemDictionary(); - InstanceKlass strKlass = sysDict.getStringKlass(); - // String has a field named 'value' of type 'byte[]'. - stringValueField = (OopField) strKlass.findField("value", "[B"); - } - - private long stringSize(Instance instance) { - // We include String content in size calculation. - return instance.getObjectSize() + - stringValueField.getValue(instance).getObjectSize(); - } - - public void visit(Instance str) { - count++; - size += stringSize(str); - } - - public void print() { - System.out.println(count + - " interned Strings occupying " + size + " bytes."); - } - } - - StringStat stat = new StringStat(); - StringTable strTable = VM.getVM().getStringTable(); - strTable.stringsDo(stat); - stat.print(); - } } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java index e03a85531fe..a136a3cf35f 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -119,4 +119,39 @@ public class CompactHashTable extends VMObject { } return null; } + + public interface SymbolVisitor { + public void visit(Symbol sym); + } + + public void symbolsDo(SymbolVisitor visitor) { + long symOffset; + Symbol sym; + Address baseAddress = baseAddressField.getValue(addr); + Address bucket = bucketsField.getValue(addr); + for (long index = 0; index < bucketCount(); index++) { + int bucketInfo = (int)bucket.getCIntegerAt(index * uintSize, uintSize, true); + int bucketOffset = bucketOffset(bucketInfo); + int nextBucketInfo = (int)bucket.getCIntegerAt((index+1) * uintSize, uintSize, true); + int nextBucketOffset = bucketOffset(nextBucketInfo); + + Address entry = entriesField.getValue(addr).addOffsetTo(bucketOffset * uintSize); + + if (isValueOnlyBucket(bucketInfo)) { + symOffset = entry.getCIntegerAt(0, uintSize, true); + sym = Symbol.create(baseAddress.addOffsetTo(symOffset)); + visitor.visit(sym); + } else { + Address entryMax = entriesField.getValue(addr).addOffsetTo(nextBucketOffset * uintSize); + while (entry.lessThan(entryMax)) { + symOffset = entry.getCIntegerAt(uintSize, uintSize, true); + Address symAddr = baseAddress.addOffsetTo(symOffset); + sym = Symbol.create(symAddr); + visitor.visit(sym); + entry = entry.addOffsetTo(2 * uintSize); + } + } + } + } } + diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java index 9ad9e5db556..600b0e0e257 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java @@ -172,8 +172,12 @@ public class HtmlDoclet extends AbstractDoclet { } } - if (!configuration.frames && !configuration.createoverview) { - IndexRedirectWriter.generate(configuration); + if (!configuration.frames) { + if (configuration.createoverview) { + IndexRedirectWriter.generate(configuration, DocPaths.OVERVIEW_SUMMARY, DocPaths.INDEX); + } else { + IndexRedirectWriter.generate(configuration); + } } if (configuration.helpfile.isEmpty() && !configuration.nohelp) { @@ -201,7 +205,7 @@ public class HtmlDoclet extends AbstractDoclet { } } - protected void copyJqueryFiles() throws DocletException { + private void copyJqueryFiles() throws DocletException { List files = Arrays.asList( "jquery-1.12.4.js", "jquery-ui.js", @@ -245,7 +249,6 @@ public class HtmlDoclet extends AbstractDoclet { protected void generateClassFiles(SortedSet arr, ClassTree classtree) throws DocletException { List list = new ArrayList<>(arr); - ListIterator iterator = list.listIterator(); for (TypeElement klass : list) { if (utils.hasHiddenTag(klass) || !(configuration.isGeneratedDoc(klass) && utils.isIncluded(klass))) { @@ -274,7 +277,6 @@ public class HtmlDoclet extends AbstractDoclet { ModuleIndexFrameWriter.generate(configuration); } List mdles = new ArrayList<>(configuration.modulePackages.keySet()); - int i = 0; for (ModuleElement mdle : mdles) { if (configuration.frames && configuration.modules.size() > 1) { ModulePackageIndexFrameWriter.generate(configuration, mdle); @@ -283,21 +285,10 @@ public class HtmlDoclet extends AbstractDoclet { AbstractBuilder moduleSummaryBuilder = configuration.getBuilderFactory().getModuleSummaryBuilder(mdle); moduleSummaryBuilder.build(); - i++; } } } - PackageElement getNamedPackage(List list, int idx) { - if (idx < list.size()) { - PackageElement pkg = list.get(idx); - if (pkg != null && !pkg.isUnnamed()) { - return pkg; - } - } - return null; - } - /** * {@inheritDoc} */ @@ -308,11 +299,10 @@ public class HtmlDoclet extends AbstractDoclet { PackageIndexFrameWriter.generate(configuration); } List pList = new ArrayList<>(packages); - for (int i = 0 ; i < pList.size() ; i++) { + for (PackageElement pkg : pList) { // if -nodeprecated option is set and the package is marked as // deprecated, do not generate the package-summary.html, package-frame.html // and package-tree.html pages for that package. - PackageElement pkg = pList.get(i); if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) { if (configuration.frames) { PackageFrameWriter.generate(configuration, pkg); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java index 2daa6182f75..6295dce952b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -41,8 +41,8 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocPath; import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; /** - * Writes an index.html file that tries to redirect to an alternate page. - * The redirect uses JavaSCript, if enabled, falling back on + * Writes a file that tries to redirect to an alternate page. + * The redirect uses JavaScript, if enabled, falling back on * {@code }. * If neither are supported/enabled in a browser, the page displays the * standard "JavaScipt not enabled" message, and a link to the alternate page. @@ -51,21 +51,27 @@ public class IndexRedirectWriter extends HtmlDocletWriter { public static void generate(HtmlConfiguration configuration) throws DocFileIOException { - IndexRedirectWriter indexRedirect; - DocPath filename = DocPaths.INDEX; - indexRedirect = new IndexRedirectWriter(configuration, filename); - indexRedirect.generateIndexFile(); + generate(configuration, DocPaths.INDEX, configuration.topFile); } - IndexRedirectWriter(HtmlConfiguration configuration, DocPath filename) { + public static void generate(HtmlConfiguration configuration, DocPath fileName, DocPath target) + throws DocFileIOException { + IndexRedirectWriter indexRedirect = new IndexRedirectWriter(configuration, fileName, target); + indexRedirect.generateIndexFile(); + } + + private DocPath target; + + private IndexRedirectWriter(HtmlConfiguration configuration, DocPath filename, DocPath target) { super(configuration, filename); + this.target = target; } /** * Generate an index file that redirects to an alternate file. * @throws DocFileIOException if there is a problem generating the file */ - void generateIndexFile() throws DocFileIOException { + private void generateIndexFile() throws DocFileIOException { DocType htmlDocType = DocType.forVersion(configuration.htmlVersion); Content htmlComment = contents.newPage; Head head = new Head(path, configuration.htmlVersion, configuration.docletVersion) @@ -77,15 +83,16 @@ public class IndexRedirectWriter extends HtmlDocletWriter { : resources.getText("doclet.Generated_Docs_Untitled"); head.setTitle(title) - .setCharset(configuration.charset); + .setCharset(configuration.charset) + .setCanonicalLink(target); - String topFilePath = configuration.topFile.getPath(); + String targetPath = target.getPath(); Script script = new Script("window.location.replace(") - .appendStringLiteral(topFilePath, '\'') + .appendStringLiteral(targetPath, '\'') .append(")"); HtmlTree metaRefresh = new HtmlTree(HtmlTag.META) .addAttr(HtmlAttr.HTTP_EQUIV, "Refresh") - .addAttr(HtmlAttr.CONTENT, "0;" + topFilePath); + .addAttr(HtmlAttr.CONTENT, "0;" + targetPath); head.addContent( script.asContent(), configuration.isOutputHtml5() ? HtmlTree.NOSCRIPT(metaRefresh) : metaRefresh); @@ -94,7 +101,7 @@ public class IndexRedirectWriter extends HtmlDocletWriter { bodyContent.addContent(HtmlTree.NOSCRIPT( HtmlTree.P(contents.getContent("doclet.No_Script_Message")))); - bodyContent.addContent(HtmlTree.P(HtmlTree.A(topFilePath, new StringContent(topFilePath)))); + bodyContent.addContent(HtmlTree.P(HtmlTree.A(targetPath, new StringContent(targetPath)))); Content body = new HtmlTree(HtmlTag.BODY); if (configuration.allowTag(HtmlTag.MAIN)) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java index 6e525d7cd0c..a9d76cda97d 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -67,7 +67,8 @@ public class Head { private Script mainBodyScript; private final List", + "", + "

    index.html

    "); + } } private void checkWarning() { diff --git a/test/langtools/tools/javac/DefiniteAssignment/T8204610.java b/test/langtools/tools/javac/DefiniteAssignment/T8204610.java new file mode 100644 index 00000000000..2827b37038d --- /dev/null +++ b/test/langtools/tools/javac/DefiniteAssignment/T8204610.java @@ -0,0 +1,95 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8204610 + * @summary Compiler confused by parenthesized "this" in final fields assignments + * @library /tools/javac/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + + * @run main T8204610 + */ + +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; + +public class T8204610 extends ComboInstance { + + enum ParenKind implements ComboParameter { + NONE(""), + ONE("#P"), + TWO("#P#P"), + THREE("#P#P#P"); + + String parensTemplate; + + ParenKind(String parensTemplate) { + this.parensTemplate = parensTemplate; + } + + @Override + public String expand(String optParameter) { + return parensTemplate.replaceAll("#P", optParameter.equals("OPEN") ? "(" : ")"); + } + } + + public static void main(String... args) { + new ComboTestHelper() + .withArrayDimension("PAREN", (x, pk, idx) -> x.parenKinds[idx] = pk, 3, ParenKind.values()) + .run(T8204610::new); + } + + ParenKind[] parenKinds = new ParenKind[3]; + + @Override + public void doWork() { + newCompilationTask() + .withSourceFromTemplate(bodyTemplate) + .analyze(this::check); + } + + String bodyTemplate = "class Test {\n" + + " final int x;\n" + + " Test() {\n" + + " #{PAREN[0].OPEN} #{PAREN[1].OPEN} this #{PAREN[1].CLOSE} . #{PAREN[2].OPEN} x #{PAREN[2].CLOSE} #{PAREN[0].CLOSE} = 1;\n" + + " } }"; + + void check(Result res) { + boolean expectedFail = parenKinds[2] != ParenKind.NONE; + if (expectedFail != res.hasErrors()) { + fail("unexpected compilation result for source:\n" + + res.compilationInfo()); + } + } +} diff --git a/test/langtools/tools/javac/diags/CheckResourceKeys.java b/test/langtools/tools/javac/diags/CheckResourceKeys.java index d7965c21b4b..8ce93dc8aa8 100644 --- a/test/langtools/tools/javac/diags/CheckResourceKeys.java +++ b/test/langtools/tools/javac/diags/CheckResourceKeys.java @@ -118,7 +118,8 @@ public class CheckResourceKeys { void findDeadKeys(Set codeStrings, Set resourceKeys) { String[] prefixes = { "compiler.err.", "compiler.warn.", "compiler.note.", "compiler.misc.", - "javac." + "javac.", + "launcher.err." }; for (String rk: resourceKeys) { // some keys are used directly, without a prefix. @@ -395,7 +396,7 @@ public class CheckResourceKeys { Set getResourceKeys() { Module jdk_compiler = ModuleLayer.boot().findModule("jdk.compiler").get(); Set results = new TreeSet(); - for (String name : new String[]{"javac", "compiler"}) { + for (String name : new String[]{"javac", "compiler", "launcher"}) { ResourceBundle b = ResourceBundle.getBundle("com.sun.tools.javac.resources." + name, jdk_compiler); results.addAll(b.keySet()); diff --git a/test/langtools/tools/javac/launcher/SourceLauncherTest.java b/test/langtools/tools/javac/launcher/SourceLauncherTest.java new file mode 100644 index 00000000000..79f5118b9a1 --- /dev/null +++ b/test/langtools/tools/javac/launcher/SourceLauncherTest.java @@ -0,0 +1,542 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8192920 + * @summary Test source launcher + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.launcher + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.JavaTask toolbox.JavacTask toolbox.TestRunner toolbox.ToolBox + * @run main SourceLauncherTest + */ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.InvocationTargetException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Properties; + +import com.sun.tools.javac.launcher.Main; + +import toolbox.JavaTask; +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.TestRunner; +import toolbox.TestRunner; +import toolbox.ToolBox; + +public class SourceLauncherTest extends TestRunner { + public static void main(String... args) throws Exception { + SourceLauncherTest t = new SourceLauncherTest(); + t.runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + SourceLauncherTest() { + super(System.err); + tb = new ToolBox(); + System.err.println("version: " + thisVersion); + } + + private final ToolBox tb; + private static final String thisVersion = System.getProperty("java.specification.version"); + + /* + * Positive tests. + */ + + @Test + public void testHelloWorld(Path base) throws IOException { + tb.writeJavaFiles(base, + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + testSuccess(base.resolve("HelloWorld.java"), "Hello World! [1, 2, 3]\n"); + } + + @Test + public void testHelloWorldInPackage(Path base) throws IOException { + tb.writeJavaFiles(base, + "package hello;\n" + + "import java.util.Arrays;\n" + + "class World {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + testSuccess(base.resolve("hello").resolve("World.java"), "Hello World! [1, 2, 3]\n"); + } + + @Test + public void testHelloWorldWithAux(Path base) throws IOException { + tb.writeJavaFiles(base, + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " Aux.write(args);\n" + + " }\n" + + "}\n" + + "class Aux {\n" + + " static void write(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + testSuccess(base.resolve("HelloWorld.java"), "Hello World! [1, 2, 3]\n"); + } + + @Test + public void testHelloWorldWithShebang(Path base) throws IOException { + tb.writeJavaFiles(base, + "#!/usr/bin/java --source 11\n" + + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + Files.copy(base.resolve("HelloWorld.java"), base.resolve("HelloWorld")); + testSuccess(base.resolve("HelloWorld"), "Hello World! [1, 2, 3]\n"); + } + + @Test + public void testNoAnnoProcessing(Path base) throws IOException { + Path annoSrc = base.resolve("annoSrc"); + tb.writeJavaFiles(annoSrc, + "import java.util.*;\n" + + "import javax.annotation.processing.*;\n" + + "import javax.lang.model.element.*;\n" + + "@SupportedAnnotationTypes(\"*\")\n" + + "public class AnnoProc extends AbstractProcessor {\n" + + " public boolean process(Set annos, RoundEnvironment rEnv) {\n" + + " throw new Error(\"Annotation processor should not be invoked\");\n" + + " }\n" + + "}\n"); + Path annoClasses = Files.createDirectories(base.resolve("classes")); + new JavacTask(tb) + .outdir(annoClasses) + .files(annoSrc.resolve("AnnoProc.java").toString()) + .run(); + Path serviceFile = annoClasses.resolve("META-INF").resolve("services") + .resolve("javax.annotation.processing.Processor"); + tb.writeFile(serviceFile, "AnnoProc"); + + Path mainSrc = base.resolve("mainSrc"); + tb.writeJavaFiles(mainSrc, + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + + List javacArgs = List.of("-classpath", annoClasses.toString()); + List classArgs = List.of("1", "2", "3"); + String expect = "Hello World! [1, 2, 3]\n"; + Result r = run(mainSrc.resolve("HelloWorld.java"), javacArgs, classArgs); + checkEqual("stdout", r.stdOut, expect); + checkEmpty("stderr", r.stdErr); + checkNull("exception", r.exception); + } + + @Test + public void testEnablePreview(Path base) throws IOException { + tb.writeJavaFiles(base, + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + + String log = new JavaTask(tb) + .vmOptions("--enable-preview", "--source", thisVersion) + .className(base.resolve("HelloWorld.java").toString()) + .classArgs("1", "2", "3") + .run(Task.Expect.SUCCESS) + .getOutput(Task.OutputKind.STDOUT); + checkEqual("stdout", log.trim(), "Hello World! [1, 2, 3]"); + } + + void testSuccess(Path file, String expect) throws IOException { + Result r = run(file, Collections.emptyList(), List.of("1", "2", "3")); + checkEqual("stdout", r.stdOut, expect); + checkEmpty("stderr", r.stdErr); + checkNull("exception", r.exception); + } + + /* + * Negative tests: such as cannot find or execute main method. + */ + + @Test + public void testHelloWorldWithShebangJava(Path base) throws IOException { + tb.writeJavaFiles(base, + "#!/usr/bin/java --source 11\n" + + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + Path file = base.resolve("HelloWorld.java"); + testError(file, + file + ":1: error: illegal character: '#'\n" + + "#!/usr/bin/java --source 11\n" + + "^\n" + + file + ":1: error: class, interface, or enum expected\n" + + "#!/usr/bin/java --source 11\n" + + " ^\n" + + "2 errors\n", + "error: compilation failed"); + } + + @Test + public void testNoClass(Path base) throws IOException { + Files.createDirectories(base); + Path file = base.resolve("NoClass.java"); + Files.write(file, List.of("package p;")); + testError(file, "", "error: no class declared in file"); + } + + @Test + public void testWrongClass(Path base) throws IOException { + Path src = base.resolve("src"); + Path file = src.resolve("WrongClass.java"); + tb.writeJavaFiles(src, "class WrongClass { }"); + Path classes = Files.createDirectories(base.resolve("classes")); + new JavacTask(tb) + .outdir(classes) + .files(file) + .run(); + String log = new JavaTask(tb) + .classpath(classes.toString()) + .className(file.toString()) + .run(Task.Expect.FAIL) + .getOutput(Task.OutputKind.STDERR); + checkEqual("stderr", log.trim(), + "error: class found on application class path: WrongClass"); + } + + @Test + public void testSyntaxErr(Path base) throws IOException { + tb.writeJavaFiles(base, "class SyntaxErr {"); + Path file = base.resolve("SyntaxErr.java"); + testError(file, + file + ":1: error: reached end of file while parsing\n" + + "class SyntaxErr {\n" + + " ^\n" + + "1 error\n", + "error: compilation failed"); + } + + @Test + public void testNoSourceOnClassPath(Path base) throws IOException { + Path auxSrc = base.resolve("auxSrc"); + tb.writeJavaFiles(auxSrc, + "public class Aux {\n" + + " static final String MESSAGE = \"Hello World\";\n" + + "}\n"); + + Path mainSrc = base.resolve("mainSrc"); + tb.writeJavaFiles(mainSrc, + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(Aux.MESSAGE + Arrays.toString(args));\n" + + " }\n" + + "}"); + + List javacArgs = List.of("-classpath", auxSrc.toString()); + List classArgs = List.of("1", "2", "3"); + String expectStdErr = + "testNoSourceOnClassPath/mainSrc/HelloWorld.java:4: error: cannot find symbol\n" + + " System.out.println(Aux.MESSAGE + Arrays.toString(args));\n" + + " ^\n" + + " symbol: variable Aux\n" + + " location: class HelloWorld\n" + + "1 error\n"; + Result r = run(mainSrc.resolve("HelloWorld.java"), javacArgs, classArgs); + checkEmpty("stdout", r.stdOut); + checkEqual("stderr", r.stdErr, expectStdErr); + checkFault("exception", r.exception, "error: compilation failed"); + + } + + // For any source file that is invoked through the OS shebang mechanism, invalid shebang + // lines will be caught and handled by the OS, before the launcher is even invoked. + // However, if such a file is passed directly to the launcher, perhaps using the --source + // option, a well-formed shebang line will be removed but a badly-formed one will be not be + // removed and will cause compilation errors. + @Test + public void testBadShebang(Path base) throws IOException { + tb.writeJavaFiles(base, + "#/usr/bin/java --source 11\n" + + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + Path file = base.resolve("HelloWorld.java"); + testError(file, + file + ":1: error: illegal character: '#'\n" + + "#/usr/bin/java --source 11\n" + + "^\n" + + file + ":1: error: class, interface, or enum expected\n" + + "#/usr/bin/java --source 11\n" + + " ^\n" + + "2 errors\n", + "error: compilation failed"); + } + + @Test + public void testBadSourceOpt(Path base) throws IOException { + Files.createDirectories(base); + Path file = base.resolve("DummyClass.java"); + Files.write(file, List.of("class DummyClass { }")); + Properties sysProps = System.getProperties(); + Properties p = new Properties(sysProps); + p.setProperty("jdk.internal.javac.source", ""); + System.setProperties(p); + try { + testError(file, "", "error: invalid value for --source option: "); + } finally { + System.setProperties(sysProps); + } + } + + @Test + public void testEnablePreviewNoSource(Path base) throws IOException { + tb.writeJavaFiles(base, + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + + String log = new JavaTask(tb) + .vmOptions("--enable-preview") + .className(base.resolve("HelloWorld.java").toString()) + .run(Task.Expect.FAIL) + .getOutput(Task.OutputKind.STDERR); + checkEqual("stderr", log.trim(), + "error: --enable-preview must be used with --source"); + } + + @Test + public void testNoMain(Path base) throws IOException { + tb.writeJavaFiles(base, "class NoMain { }"); + testError(base.resolve("NoMain.java"), "", + "error: can't find main(String[]) method in class: NoMain"); + } + + @Test + public void testMainBadParams(Path base) throws IOException { + tb.writeJavaFiles(base, + "class BadParams { public static void main() { } }"); + testError(base.resolve("BadParams.java"), "", + "error: can't find main(String[]) method in class: BadParams"); + } + + @Test + public void testMainNotPublic(Path base) throws IOException { + tb.writeJavaFiles(base, + "class NotPublic { static void main(String... args) { } }"); + testError(base.resolve("NotPublic.java"), "", + "error: 'main' method is not declared 'public static'"); + } + + @Test + public void testMainNotStatic(Path base) throws IOException { + tb.writeJavaFiles(base, + "class NotStatic { public void main(String... args) { } }"); + testError(base.resolve("NotStatic.java"), "", + "error: 'main' method is not declared 'public static'"); + } + + @Test + public void testMainNotVoid(Path base) throws IOException { + tb.writeJavaFiles(base, + "class NotVoid { public static int main(String... args) { return 0; } }"); + testError(base.resolve("NotVoid.java"), "", + "error: 'main' method is not declared with a return type of 'void'"); + } + + @Test + public void testClassInModule(Path base) throws IOException { + tb.writeJavaFiles(base, "package java.net; class InModule { }"); + Path file = base.resolve("java").resolve("net").resolve("InModule.java"); + testError(file, + file + ":1: error: package exists in another module: java.base\n" + + "package java.net; class InModule { }\n" + + "^\n" + + "1 error\n", + "error: compilation failed"); + } + + void testError(Path file, String expectStdErr, String expectFault) throws IOException { + Result r = run(file, Collections.emptyList(), List.of("1", "2", "3")); + checkEmpty("stdout", r.stdOut); + checkEqual("stderr", r.stdErr, expectStdErr); + checkFault("exception", r.exception, expectFault); + } + + /* + * Tests in which main throws an exception. + */ + @Test + public void testTargetException1(Path base) throws IOException { + tb.writeJavaFiles(base, + "import java.util.Arrays;\n" + + "class Thrower {\n" + + " public static void main(String... args) {\n" + + " throwWhenZero(Integer.parseInt(args[0]));\n" + + " }\n" + + " static void throwWhenZero(int arg) {\n" + + " if (arg == 0) throw new Error(\"zero!\");\n" + + " throwWhenZero(arg - 1);\n" + + " }\n" + + "}"); + Path file = base.resolve("Thrower.java"); + Result r = run(file, Collections.emptyList(), List.of("3")); + checkEmpty("stdout", r.stdOut); + checkEmpty("stderr", r.stdErr); + checkTrace("exception", r.exception, + "java.lang.Error: zero!", + "at Thrower.throwWhenZero(Thrower.java:7)", + "at Thrower.throwWhenZero(Thrower.java:8)", + "at Thrower.throwWhenZero(Thrower.java:8)", + "at Thrower.throwWhenZero(Thrower.java:8)", + "at Thrower.main(Thrower.java:4)"); + } + + Result run(Path file, List runtimeArgs, List appArgs) { + List args = new ArrayList<>(); + args.add(file.toString()); + args.addAll(appArgs); + + PrintStream prev = System.out; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (PrintStream out = new PrintStream(baos, true)) { + System.setOut(out); + StringWriter sw = new StringWriter(); + try (PrintWriter err = new PrintWriter(sw, true)) { + Main m = new Main(err); + m.run(toArray(runtimeArgs), toArray(args)); + return new Result(baos.toString(), sw.toString(), null); + } catch (Throwable t) { + return new Result(baos.toString(), sw.toString(), t); + } + } finally { + System.setOut(prev); + } + } + + void checkEqual(String name, String found, String expect) { + expect = expect.replace("\n", tb.lineSeparator); + out.println(name + ": " + found); + out.println(name + ": " + found); + if (!expect.equals(found)) { + error("Unexpected output; expected: " + expect); + } + } + + void checkEmpty(String name, String found) { + out.println(name + ": " + found); + if (!found.isEmpty()) { + error("Unexpected output; expected empty string"); + } + } + + void checkNull(String name, Throwable found) { + out.println(name + ": " + found); + if (found != null) { + error("Unexpected exception; expected null"); + } + } + + void checkFault(String name, Throwable found, String expect) { + expect = expect.replace("\n", tb.lineSeparator); + out.println(name + ": " + found); + if (found == null) { + error("No exception thrown; expected Main.Fault"); + } else { + if (!(found instanceof Main.Fault)) { + error("Unexpected exception; expected Main.Fault"); + } + if (!(found.getMessage().equals(expect))) { + error("Unexpected detail message; expected: " + expect); + } + } + } + + void checkTrace(String name, Throwable found, String... expect) { + if (!(found instanceof InvocationTargetException)) { + error("Unexpected exception; expected InvocationTargetException"); + out.println("Found:"); + found.printStackTrace(out); + } + StringWriter sw = new StringWriter(); + try (PrintWriter pw = new PrintWriter(sw)) { + ((InvocationTargetException) found).getTargetException().printStackTrace(pw); + } + String trace = sw.toString(); + out.println(name + ":\n" + trace); + String[] traceLines = trace.trim().split("[\r\n]+\\s+"); + try { + tb.checkEqual(List.of(traceLines), List.of(expect)); + } catch (Error e) { + error(e.getMessage()); + } + } + + String[] toArray(List list) { + return list.toArray(new String[list.size()]); + } + + class Result { + private final String stdOut; + private final String stdErr; + private final Throwable exception; + + Result(String stdOut, String stdErr, Throwable exception) { + this.stdOut = stdOut; + this.stdErr = stdErr; + this.exception = exception; + } + } +} diff --git a/test/lib/sun/hotspot/code/Compiler.java b/test/lib/sun/hotspot/code/Compiler.java new file mode 100644 index 00000000000..ae359531faf --- /dev/null +++ b/test/lib/sun/hotspot/code/Compiler.java @@ -0,0 +1,136 @@ +/* + * 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. + */ + +package sun.hotspot.code; + +import sun.hotspot.WhiteBox; + +/** + * API to obtain information about enabled JIT compilers + * retrieved from the VM with the WhiteBox API. + */ +public class Compiler { + + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + /** + * Check if Graal is used as JIT compiler. + * + * Graal is enabled if following conditions are true: + * - we are not in Interpreter mode + * - UseJVMCICompiler flag is true + * - jvmci.Compiler variable is equal to 'graal' + * - TieredCompilation is not used or TieredStopAtLevel is greater than 3 + * No need to check client mode because it set UseJVMCICompiler to false. + * + * @return true if Graal is used as JIT compiler. + */ + public static boolean isGraalEnabled() { + Boolean useCompiler = WB.getBooleanVMFlag("UseCompiler"); + if (useCompiler == null || !useCompiler) { + return false; + } + Boolean useJvmciComp = WB.getBooleanVMFlag("UseJVMCICompiler"); + if (useJvmciComp == null || !useJvmciComp) { + return false; + } + // This check might be redundant but let's keep it for now. + String jvmciCompiler = System.getProperty("jvmci.Compiler"); + if (jvmciCompiler == null || !jvmciCompiler.equals("graal")) { + return false; + } + + Boolean tieredCompilation = WB.getBooleanVMFlag("TieredCompilation"); + Long compLevel = WB.getIntxVMFlag("TieredStopAtLevel"); + // if TieredCompilation is enabled and compilation level is <= 3 then no Graal is used + if (tieredCompilation != null && tieredCompilation && + compLevel != null && compLevel <= 3) { + return false; + } + return true; + } + + /** + * Check if C2 is used as JIT compiler. + * + * C2 is enabled if following conditions are true: + * - we are not in Interpreter mode + * - we are in Server compilation mode + * - TieredCompilation is not used or TieredStopAtLevel is greater than 3 + * - Graal is not used + * + * @return true if C2 is used as JIT compiler. + */ + public static boolean isC2Enabled() { + Boolean useCompiler = WB.getBooleanVMFlag("UseCompiler"); + if (useCompiler == null || !useCompiler) { + return false; + } + Boolean serverMode = WB.getBooleanVMFlag("ProfileInterpreter"); + if (serverMode == null || !serverMode) { + return false; + } + + Boolean tieredCompilation = WB.getBooleanVMFlag("TieredCompilation"); + Long compLevel = WB.getIntxVMFlag("TieredStopAtLevel"); + // if TieredCompilation is enabled and compilation level is <= 3 then no Graal is used + if (tieredCompilation != null && tieredCompilation && + compLevel != null && compLevel <= 3) { + return false; + } + + if (isGraalEnabled()) { + return false; + } + + return true; + } + + /* + * Check if C1 is used as JIT compiler. + * + * C1 is enabled if following conditions are true: + * - we are not in Interpreter mode + * - we are not in Server compilation mode + * - TieredCompilation is used in Server mode + * + * @return true if C1 is used as JIT compiler. + */ + public static boolean isC1Enabled() { + Boolean useCompiler = WB.getBooleanVMFlag("UseCompiler"); + if (useCompiler == null || !useCompiler) { + return false; + } + Boolean serverMode = WB.getBooleanVMFlag("ProfileInterpreter"); + if (serverMode == null || !serverMode) { + return true; // Client mode + } + + Boolean tieredCompilation = WB.getBooleanVMFlag("TieredCompilation"); + // C1 is not used in server mode if TieredCompilation is off. + if (tieredCompilation != null && !tieredCompilation) { + return false; + } + return true; + } +} diff --git a/test/nashorn/script/basic/JDK-8204288.js b/test/nashorn/script/basic/JDK-8204288.js new file mode 100644 index 00000000000..2d325782bd3 --- /dev/null +++ b/test/nashorn/script/basic/JDK-8204288.js @@ -0,0 +1,35 @@ +/* + * 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. + */ + +/** + * JDK-8204288: Matching the end of a string followed by an empty greedy regex and a word boundary fails + * + * @test + * @run + */ + + +Assert.assertEquals(new RegExp("c.*\\b").exec("abc")[0], "c"); +Assert.assertEquals(new RegExp("abc.*\\b").exec("abc")[0], "abc"); +Assert.assertEquals(new RegExp("\\b.*abc.*\\b").exec("abc")[0], "abc"); + diff --git a/test/nashorn/script/basic/JDK-8204290.js b/test/nashorn/script/basic/JDK-8204290.js new file mode 100644 index 00000000000..57193b61cfb --- /dev/null +++ b/test/nashorn/script/basic/JDK-8204290.js @@ -0,0 +1,38 @@ +/* + * 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. + */ + +/** + * JDK-8204290: Add check to limit number of capture groups + * + * @test + * @run + */ + +try { + new RegExp("()".repeat(0x8001)); + fail("Expected exception"); +} catch (e) { + Assert.assertTrue(e instanceof SyntaxError); + Assert.assertEquals(e.message, "too many capture groups"); +} +