diff --git a/doc/ide.html b/doc/ide.html new file mode 100644 index 00000000000..1730eb0bef5 --- /dev/null +++ b/doc/ide.html @@ -0,0 +1,54 @@ + + +
+ + + +When you are familiar with building and testing the JDK, you may want to configure an IDE to work with the source code. The instructions differ a bit depending on whether you are interested in working with the native (C/C++) or the Java code.
+There are a few ways to generate IDE configuration for the native sources, depending on which IDE to use.
+The make system can generate a Visual Studio Code workspace that has C/C++ source indexing configured correctly, as well as launcher targets for tests and the Java launcher. After configuring, a workspace for the configuration can be generated using:
+make vscode-project
+This creates a file called jdk.code-workspace
in the build output folder. The full location will be printed after the workspace has been generated. To use it, choose File -> Open Workspace...
in Visual Studio Code.
The main vscode-project
target configures the default C++ support in Visual Studio Code. There are also other source indexers that can be installed, that may provide additional features. It's currently possible to generate configuration for two such indexers, clangd and rtags. These can be configured by appending the name of the indexer to the make target, such as:
make vscode-project-clangd
+Additional instructions for configuring the given indexer will be displayed after the workspace has been generated.
+This section is a work in progress.
+make ide-project
+The make system can generate generic native code indexing support in the form of a Compilation Database that can be used by many different IDEs and source code indexers.
+make compile-commands
+It's also possible to generate the Compilation Database for the HotSpot source code only, which is a bit faster as it includes less information.
+make compile-commands-hotspot
+This section is a work in progress.
+ + diff --git a/doc/ide.md b/doc/ide.md new file mode 100644 index 00000000000..4a692efd22f --- /dev/null +++ b/doc/ide.md @@ -0,0 +1,73 @@ +% IDE support in the JDK + +## Introduction + +When you are familiar with building and testing the JDK, you may want to +configure an IDE to work with the source code. The instructions differ a bit +depending on whether you are interested in working with the native (C/C++) or +the Java code. + +### IDE support for native code + +There are a few ways to generate IDE configuration for the native sources, +depending on which IDE to use. + +#### Visual Studio Code + +The make system can generate a [Visual Studio Code](https://code.visualstudio.com) +workspace that has C/C++ source indexing configured correctly, as well as +launcher targets for tests and the Java launcher. After configuring, a workspace +for the configuration can be generated using: + +```shell +make vscode-project +``` + +This creates a file called `jdk.code-workspace` in the build output folder. The +full location will be printed after the workspace has been generated. To use it, +choose `File -> Open Workspace...` in Visual Studio Code. + +##### Alternative indexers + +The main `vscode-project` target configures the default C++ support in Visual +Studio Code. There are also other source indexers that can be installed, that +may provide additional features. It's currently possible to generate +configuration for two such indexers, [clangd](https://clang.llvm.org/extra/clangd/) +and [rtags](https://github.com/Andersbakken/rtags). These can be configured by +appending the name of the indexer to the make target, such as: + +```shell +make vscode-project-clangd +``` + +Additional instructions for configuring the given indexer will be displayed +after the workspace has been generated. + +#### Visual Studio + +This section is a work in progress. + +```shell +make ide-project +``` + +#### Compilation Database + +The make system can generate generic native code indexing support in the form of +a [Compilation Database](https://clang.llvm.org/docs/JSONCompilationDatabase.html) +that can be used by many different IDEs and source code indexers. + +```shell +make compile-commands +``` + +It's also possible to generate the Compilation Database for the HotSpot source +code only, which is a bit faster as it includes less information. + +```shell +make compile-commands-hotspot +``` + +### IDE support for Java code + +This section is a work in progress. \ No newline at end of file diff --git a/make/Main.gmk b/make/Main.gmk index 791be753513..0bbcc5c65fc 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -287,6 +287,27 @@ compile-commands compile-commands-hotspot: ALL_TARGETS += $(COMPILE_COMMANDS_TARGETS_HOTSPOT) $(COMPILE_COMMANDS_TARGETS_JDK) ALL_TARGETS += compile-commands compile-commands-hotspot +################################################################################ +# VS Code projects +vscode-project: + +($(CD) $(TOPDIR)/make/vscode && $(MAKE) $(MAKE_ARGS) -f CreateVSCodeProject.gmk \ + VSCODE_INDEXER=cpptools) + +vscode-project-clangd: + +($(CD) $(TOPDIR)/make/vscode && $(MAKE) $(MAKE_ARGS) -f CreateVSCodeProject.gmk \ + VSCODE_INDEXER=clangd) + +vscode-project-rtags: + +($(CD) $(TOPDIR)/make/vscode && $(MAKE) $(MAKE_ARGS) -f CreateVSCodeProject.gmk \ + VSCODE_INDEXER=rtags) + +vscode-project-ccls: + +($(CD) $(TOPDIR)/make/vscode && $(MAKE) $(MAKE_ARGS) -f CreateVSCodeProject.gmk \ + VSCODE_INDEXER=ccls) + +ALL_TARGETS += vscode-project vscode-project-clangd vscode-project-rtags \ + vscode-project-ccls + ################################################################################ # Build demos targets @@ -774,6 +795,11 @@ else compile-commands-hotspot: $(COMPILE_COMMANDS_TARGETS_HOTSPOT) compile-commands: $(COMPILE_COMMANDS_TARGETS_HOTSPOT) $(COMPILE_COMMANDS_TARGETS_JDK) + vscode-project: compile-commands + vscode-project-clangd: compile-commands + vscode-project-rtags: compile-commands + vscode-project-ccls: compile-commands + # Jmods cannot be created until we have the jmod tool ready to run. During # a normal build we run it from the exploded image, but when cross compiling # it's run from the buildjdk, which is either created at build time or user diff --git a/make/UpdateBuildDocs.gmk b/make/UpdateBuildDocs.gmk index 011be4c620e..2f9aec75a29 100644 --- a/make/UpdateBuildDocs.gmk +++ b/make/UpdateBuildDocs.gmk @@ -61,6 +61,14 @@ $(eval $(call SetupProcessMarkdown, testing, \ )) TARGETS += $(testing) +$(eval $(call SetupProcessMarkdown, ide, \ + FILES := $(DOCS_DIR)/ide.md, \ + DEST := $(DOCS_DIR), \ + CSS := $(GLOBAL_SPECS_DEFAULT_CSS_FILE), \ + OPTIONS := --toc, \ +)) +TARGETS += $(ide) + ################################################################################ $(eval $(call IncludeCustomExtension, UpdateBuildDocs.gmk)) diff --git a/make/common/JdkNativeCompilation.gmk b/make/common/JdkNativeCompilation.gmk index c1c0a4323cd..67e4f927779 100644 --- a/make/common/JdkNativeCompilation.gmk +++ b/make/common/JdkNativeCompilation.gmk @@ -122,7 +122,9 @@ define SetupJdkLibraryBody endif ifneq ($$($1_EXCLUDE_SRC_PATTERNS), ) - $1_EXCLUDE_SRC := $$(call containing, $$($1_EXCLUDE_SRC_PATTERNS), $$($1_SRC)) + $1_SRC_WITHOUT_WORKSPACE_ROOT := $$(patsubst $$(WORKSPACE_ROOT)/%, %, $$($1_SRC)) + $1_EXCLUDE_SRC := $$(addprefix %, $$(call containing, $$($1_EXCLUDE_SRC_PATTERNS), \ + $$($1_SRC_WITHOUT_WORKSPACE_ROOT))) $1_SRC := $$(filter-out $$($1_EXCLUDE_SRC), $$($1_SRC)) endif diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index 44166ac3d3f..fad6778f96e 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -471,6 +471,22 @@ else $1 endif +################################################################################ +# FixPathList +# +# On Windows, converts a cygwin/unix style path list (colon-separated) into +# the native format (mixed mode, semicolon-separated). On other platforms, +# return the path list unchanged. +################################################################################ +ifeq ($(call isTargetOs, windows), true) + FixPathList = \ + $(subst @,$(SPACE),$(subst $(SPACE),;,$(foreach entry,$(subst :,$(SPACE),\ + $(subst $(SPACE),@,$(strip $1))),$(call FixPath, $(entry))))) +else + FixPathList = \ + $1 +endif + ################################################################################ # DependOnVariable # diff --git a/make/common/Utils.gmk b/make/common/Utils.gmk index e58e395ed7f..8bf8c15476a 100644 --- a/make/common/Utils.gmk +++ b/make/common/Utils.gmk @@ -122,7 +122,8 @@ DirToDotDot = \ # $2 - Directory to compute the relative path from RelativePath = \ $(eval $1_prefix := $(call FindCommonPathPrefix, $1, $2)) \ - $(eval $1_dotdots := $(call DirToDotDot, $(patsubst $($(strip $1)_prefix)/%, %, $2))) \ + $(eval $1_dotdots := $(call DirToDotDot, $(patsubst $($(strip $1)_prefix)%, %, $2))) \ + $(eval $1_dotdots := $(if $($(strip $1)_dotdots),$($(strip $1)_dotdots),.)) \ $(eval $1_suffix := $(patsubst $($(strip $1)_prefix)/%, %, $1)) \ $($(strip $1)_dotdots)/$($(strip $1)_suffix) diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk index f9aad66efc8..0f77eb33dd4 100644 --- a/make/lib/Awt2dLibraries.gmk +++ b/make/lib/Awt2dLibraries.gmk @@ -39,7 +39,7 @@ LIBAWT_DEFAULT_HEADER_DIRS := \ # 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_EXCLUDE_SRC_PATTERNS := /unix/ BUILD_LIBMLIB_CFLAGS := -D__USE_J2D_NAMES -D__MEDIALIB_OLD_NAMES -DMLIB_NO_LIBSUNMATH @@ -698,7 +698,7 @@ else # not windows ifeq ($(call isTargetOs, macosx), true) # libjawt on macosx do not use the unix code - LIBJAWT_EXCLUDE_SRC_PATTERNS := unix + LIBJAWT_EXCLUDE_SRC_PATTERNS := /unix/ endif ifeq ($(call isTargetOs, macosx), true) @@ -788,7 +788,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) ifeq ($(call isTargetOs, macosx), true) # libsplashscreen on macosx do not use the unix code - LIBSPLASHSCREEN_EXCLUDE_SRC_PATTERNS := unix + LIBSPLASHSCREEN_EXCLUDE_SRC_PATTERNS := /unix/ endif LIBSPLASHSCREEN_CFLAGS += -DSPLASHSCREEN -DPNG_NO_MMX_CODE -DPNG_ARM_NEON_OPT=0 diff --git a/make/vscode/CreateVSCodeProject.gmk b/make/vscode/CreateVSCodeProject.gmk new file mode 100644 index 00000000000..19f80426ddc --- /dev/null +++ b/make/vscode/CreateVSCodeProject.gmk @@ -0,0 +1,113 @@ +# +# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# This must be the first rule +default: all + +include $(SPEC) +include MakeBase.gmk + +################################################################################ +# Return the full path to an indexer-specific file fragment. +# +# Param 1: Fragment name +################################################################################ +GetIndexerFragment = \ + $(TOPDIR)/make/vscode/indexers/$(VSCODE_INDEXER)-$(1).txt + +################################################################################ +# Show indexer-specific notes if they exist, otherwise do nothing +################################################################################ +ifneq (,$(wildcard $(call GetIndexerFragment,notes))) + ShowIndexerNotes = $(CAT) $(call GetIndexerFragment,notes) +else + ShowIndexerNotes = +endif + +################################################################################ +# Return the platform-dependent preferred debug engine name. +################################################################################ +ifeq ($(call isTargetOs, windows), true) + DebugEngineName = cppvsdbg +else + DebugEngineName = cppdbg +endif + +################################################################################ +# Return an additional configuration fragment if the WORKSPACE_ROOT is different +# from TOPDIR. +################################################################################ +ifneq ($(WORKSPACE_ROOT),$(TOPDIR)) + GetExtraWorkspaceRoot = $(TOPDIR)/make/vscode/template-workspace-folder.txt +else + GetExtraWorkspaceRoot = /dev/null +endif + +################################################################################ +# Create a project configuration from a given template, replacing a known set +# of variables. +# +# Param 1: Template +# Param 2: Output +################################################################################ +define CreateFromTemplate + $(call LogInfo, Generating $2) + $(call MakeDir, $(dir $2)) + $(SED) -e '/{{INDEXER_EXTENSIONS}}/r $(call GetIndexerFragment,extensions)' \ + -e '/{{INDEXER_SETTINGS}}/r $(call GetIndexerFragment,settings)' \ + -e '/{{EXTRA_WORKSPACE_ROOT}}/r $(call GetExtraWorkspaceRoot)' $1 | \ + $(SED) -e 's!{{TOPDIR}}!$(call FixPath,$(TOPDIR))!g' \ + -e 's!{{TOPDIR_RELATIVE}}!$(call FixPath,$(strip \ + $(call RelativePath,$(OUTPUTDIR),$(TOPDIR))))!g' \ + -e 's!{{WORKSPACE_ROOT}}!$(call FixPath,$(WORKSPACE_ROOT))!g' \ + -e 's!{{OUTPUTDIR}}!$(call FixPath,$(OUTPUTDIR))!g' \ + -e 's!{{CONF_NAME}}!$(CONF_NAME)!g' \ + -e 's!{{COMPILER}}!$(call FixPath,$(CXX)) $(SYSROOT_CFLAGS)!g' \ + -e 's!{{MAKE}}!$(call FixPath,$(MAKE))!g' \ + -e 's!{{PATH}}!$(call FixPathList,$(PATH))!g' \ + -e 's!{{DEBUGENGINENAME}}!$(call DebugEngineName)!g' \ + -e '/{{INDEXER_EXTENSIONS}}/d' \ + -e '/{{INDEXER_SETTINGS}}/d' \ + -e '/{{EXTRA_WORKSPACE_ROOT}}/d' \ + > $2 +endef + +$(OUTPUTDIR)/jdk.code-workspace: + $(call LogWarn, Creating workspace $@) + $(call CreateFromTemplate, $(TOPDIR)/make/vscode/template-workspace.jsonc, $@) + $(call ShowIndexerNotes) + +$(OUTPUTDIR)/.vscode/tasks.json: + $(call CreateFromTemplate, $(TOPDIR)/make/vscode/template-tasks.jsonc, $@) + +$(OUTPUTDIR)/.vscode/launch.json: + $(call CreateFromTemplate, $(TOPDIR)/make/vscode/template-launch.jsonc, $@) + +TARGETS := $(OUTPUTDIR)/jdk.code-workspace $(OUTPUTDIR)/.vscode/tasks.json \ + $(OUTPUTDIR)/.vscode/launch.json + +all: $(TARGETS) + +.PHONY: all $(TARGETS) diff --git a/make/vscode/indexers/ccls-extensions.txt b/make/vscode/indexers/ccls-extensions.txt new file mode 100644 index 00000000000..4fdb2922772 --- /dev/null +++ b/make/vscode/indexers/ccls-extensions.txt @@ -0,0 +1,2 @@ + "ms-vscode.cpptools", + "ccls-project.ccls" diff --git a/make/vscode/indexers/ccls-notes.txt b/make/vscode/indexers/ccls-notes.txt new file mode 100644 index 00000000000..674894ff2f5 --- /dev/null +++ b/make/vscode/indexers/ccls-notes.txt @@ -0,0 +1,3 @@ + +* The "ccls" indexer must be present in PATH, or configured with "ccls.launch.command" in user preferences. + diff --git a/make/vscode/indexers/ccls-settings.txt b/make/vscode/indexers/ccls-settings.txt new file mode 100644 index 00000000000..394a1399e9b --- /dev/null +++ b/make/vscode/indexers/ccls-settings.txt @@ -0,0 +1,28 @@ + // Configure cpptools IntelliSense + "C_Cpp.intelliSenseCachePath": "{{OUTPUTDIR}}/.vscode", + "C_Cpp.default.compileCommands": "{{OUTPUTDIR}}/compile_commands.json", + "C_Cpp.default.cppStandard": "c++03", + "C_Cpp.default.compilerPath": "{{COMPILER}}", + + // Configure ccls + "ccls.misc.compilationDatabaseDirectory": "{{TOPDIR_RELATIVE}}", + "ccls.cache.hierarchicalPath": true, + "ccls.cache.directory": "{{OUTPUTDIR}}/.vscode/ccls", + + // Avoid issues with precompiled headers + "ccls.clang.excludeArgs": [ + // Windows / MSVC + "-Fp{{OUTPUTDIR}}/hotspot/variant-server/libjvm/objs/BUILD_LIBJVM.pch", + "-Fp{{OUTPUTDIR}}/hotspot/variant-server/libjvm/gtest/objs/BUILD_GTEST_LIBJVM.pch", + "-Yuprecompiled.hpp", + // MacOS / clang + "{{OUTPUTDIR}}/hotspot/variant-server/libjvm/objs/precompiled/precompiled.hpp.pch", + "{{OUTPUTDIR}}/hotspot/variant-server/libjvm/gtest/objs/precompiled/precompiled.hpp.pch", + "-include-pch" + ], + + // Disable conflicting features from cpptools + "C_Cpp.autocomplete": "Disabled", + "C_Cpp.errorSquiggles": "Disabled", + "C_Cpp.formatting": "Disabled", + "C_Cpp.intelliSenseEngine": "Disabled", diff --git a/make/vscode/indexers/clangd-extensions.txt b/make/vscode/indexers/clangd-extensions.txt new file mode 100644 index 00000000000..06ca0d32e4e --- /dev/null +++ b/make/vscode/indexers/clangd-extensions.txt @@ -0,0 +1,2 @@ + "ms-vscode.cpptools", + "llvm-vs-code-extensions.vscode-clangd" diff --git a/make/vscode/indexers/clangd-notes.txt b/make/vscode/indexers/clangd-notes.txt new file mode 100644 index 00000000000..46ff3438a86 --- /dev/null +++ b/make/vscode/indexers/clangd-notes.txt @@ -0,0 +1,4 @@ + +* The "clangd" indexer must be present in PATH, or configured with "clangd.path" in user preferences. +* If building with clang (default on OSX), precompiled headers must be disabled. + diff --git a/make/vscode/indexers/clangd-settings.txt b/make/vscode/indexers/clangd-settings.txt new file mode 100644 index 00000000000..b3227ce28ec --- /dev/null +++ b/make/vscode/indexers/clangd-settings.txt @@ -0,0 +1,17 @@ + // Configure cpptools IntelliSense + "C_Cpp.intelliSenseCachePath": "{{OUTPUTDIR}}/.vscode", + "C_Cpp.default.compileCommands": "{{OUTPUTDIR}}/compile_commands.json", + "C_Cpp.default.cppStandard": "c++03", + "C_Cpp.default.compilerPath": "{{COMPILER}}", + + // Configure clangd + "clangd.arguments": [ + "-background-index", + "-compile-commands-dir={{OUTPUTDIR}}" + ], + + // Disable conflicting features from cpptools + "C_Cpp.autocomplete": "Disabled", + "C_Cpp.errorSquiggles": "Disabled", + "C_Cpp.formatting": "Disabled", + "C_Cpp.intelliSenseEngine": "Disabled", diff --git a/make/vscode/indexers/cpptools-extensions.txt b/make/vscode/indexers/cpptools-extensions.txt new file mode 100644 index 00000000000..820e3670f80 --- /dev/null +++ b/make/vscode/indexers/cpptools-extensions.txt @@ -0,0 +1 @@ + "ms-vscode.cpptools" diff --git a/make/vscode/indexers/cpptools-settings.txt b/make/vscode/indexers/cpptools-settings.txt new file mode 100644 index 00000000000..155bf9c4970 --- /dev/null +++ b/make/vscode/indexers/cpptools-settings.txt @@ -0,0 +1,5 @@ + // Configure cpptools IntelliSense + "C_Cpp.intelliSenseCachePath": "{{OUTPUTDIR}}/.vscode", + "C_Cpp.default.compileCommands": "{{OUTPUTDIR}}/compile_commands.json", + "C_Cpp.default.cppStandard": "c++03", + "C_Cpp.default.compilerPath": "{{COMPILER}}", diff --git a/make/vscode/indexers/rtags-extensions.txt b/make/vscode/indexers/rtags-extensions.txt new file mode 100644 index 00000000000..c4b872db8b0 --- /dev/null +++ b/make/vscode/indexers/rtags-extensions.txt @@ -0,0 +1,2 @@ + "ms-vscode.cpptools", + "jomiller.rtags-client" diff --git a/make/vscode/indexers/rtags-settings.txt b/make/vscode/indexers/rtags-settings.txt new file mode 100644 index 00000000000..7e32633ac66 --- /dev/null +++ b/make/vscode/indexers/rtags-settings.txt @@ -0,0 +1,14 @@ + // Configure cpptools IntelliSense + "C_Cpp.intelliSenseCachePath": "{{OUTPUTDIR}}/.vscode", + "C_Cpp.default.compileCommands": "{{OUTPUTDIR}}/compile_commands.json", + "C_Cpp.default.cppStandard": "c++03", + "C_Cpp.default.compilerPath": "{{COMPILER}}", + + // Configure RTags + "rtags.misc.compilationDatabaseDirectory": "{{OUTPUTDIR}}", + + // Disable conflicting features from cpptools + "C_Cpp.autocomplete": "Disabled", + "C_Cpp.errorSquiggles": "Disabled", + "C_Cpp.formatting": "Disabled", + "C_Cpp.intelliSenseEngine": "Disabled", diff --git a/make/vscode/template-launch.jsonc b/make/vscode/template-launch.jsonc new file mode 100644 index 00000000000..a7b3510e9c2 --- /dev/null +++ b/make/vscode/template-launch.jsonc @@ -0,0 +1,55 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "gtestLauncher", + "type": "{{DEBUGENGINENAME}}", + "request": "launch", + "program": "{{OUTPUTDIR}}/hotspot/variant-server/libjvm/gtest/gtestLauncher", + "args": ["-jdk:{{OUTPUTDIR}}/jdk"], + "stopAtEntry": false, + "cwd": "{{WORKSPACE_ROOT}}", + "environment": [], + "externalConsole": false, + "preLaunchTask": "Make 'exploded-image'", + "osx": { + "MIMode": "lldb", + "internalConsoleOptions": "openOnSessionStart", + "args": ["--gtest_color=no", "-jdk:{{OUTPUTDIR}}/jdk"] + }, + "linux": { + "MIMode": "gdb", + "setupCommands": [ + { + "text": "handle SIGSEGV noprint nostop", + "description": "Disable stopping on signals handled by the JVM" + } + ] + } + }, + { + "name": "java", + "type": "{{DEBUGENGINENAME}}", + "request": "launch", + "program": "{{OUTPUTDIR}}/jdk/bin/java", + "stopAtEntry": false, + "cwd": "{{WORKSPACE_ROOT}}", + "environment": [], + "externalConsole": false, + "preLaunchTask": "Make 'exploded-image'", + "osx": { + "MIMode": "lldb", + "internalConsoleOptions": "openOnSessionStart", + }, + "linux": { + "MIMode": "gdb", + "setupCommands": [ + { + "text": "handle SIGSEGV noprint nostop", + "description": "Disable stopping on signals handled by the JVM" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/make/vscode/template-tasks.jsonc b/make/vscode/template-tasks.jsonc new file mode 100644 index 00000000000..0b7badb560e --- /dev/null +++ b/make/vscode/template-tasks.jsonc @@ -0,0 +1,55 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Update compilation database (compile_commands.json)", + "type": "shell", + "options": { + "env": { + "PATH": "{{PATH}}" + }, + "cwd": "{{WORKSPACE_ROOT}}" + }, + "command": "{{MAKE}} CONF_NAME={{CONF_NAME}} compile-commands", + "problemMatcher": [] + }, + { + "label": "Make 'hotspot'", + "type": "shell", + "options": { + "env": { + "PATH": "{{PATH}}" + }, + "cwd": "{{WORKSPACE_ROOT}}" + }, + "command": "{{MAKE}} CONF_NAME={{CONF_NAME}} hotspot", + "problemMatcher": ["$gcc"] + }, + { + "label": "Make 'exploded-image'", + "type": "shell", + "options": { + "env": { + "PATH": "{{PATH}}" + }, + "cwd": "{{WORKSPACE_ROOT}}" + }, + "command": "{{MAKE}} CONF_NAME={{CONF_NAME}} exploded-image", + "problemMatcher": ["$gcc"] + }, + { + "label": "Make 'jdk'", + "type": "shell", + "options": { + "env": { + "PATH": "{{PATH}}" + }, + "cwd": "{{WORKSPACE_ROOT}}" + }, + "command": "{{MAKE}} CONF_NAME={{CONF_NAME}} jdk", + "problemMatcher": ["$gcc"] + } + ] +} diff --git a/make/vscode/template-workspace-folder.txt b/make/vscode/template-workspace-folder.txt new file mode 100644 index 00000000000..82c15fb178a --- /dev/null +++ b/make/vscode/template-workspace-folder.txt @@ -0,0 +1,4 @@ + { + "name": "Additional sources", + "path": "{{WORKSPACE_ROOT}}" + }, diff --git a/make/vscode/template-workspace.jsonc b/make/vscode/template-workspace.jsonc new file mode 100644 index 00000000000..30533c7ce84 --- /dev/null +++ b/make/vscode/template-workspace.jsonc @@ -0,0 +1,63 @@ +{ + "folders": [ + { + "name": "Source root", + "path": "{{TOPDIR}}" + }, + // {{EXTRA_WORKSPACE_ROOT}} + { + "name": "Build artifacts", + "path": "{{OUTPUTDIR}}" + } + ], + "extensions": { + "recommendations": [ + // {{INDEXER_EXTENSIONS}} + ] + }, + "settings": { + // {{INDEXER_SETTINGS}} + + // Additional conventions + "files.associations": { + "*.gmk": "makefile" + }, + + // Having these enabled slow down task execution + "typescript.tsc.autoDetect": "off", + "gulp.autoDetect": "off", + "npm.autoDetect": "off", + "grunt.autoDetect": "off", + "jake.autoDetect": "off", + + // Certain types of files are not relevant for the file browser + "files.exclude": { + "**/.git": true, + "**/.hg": true, + "**/.DS_Store": true, + }, + + // Files that may be interesting to browse manually, but avoided during searches + "search.exclude": { + "**/*.class": true, + "**/*.jsa": true, + "**/*.vardeps": true, + "**/*.o": true, + "**/*.obj": true, + "**/*.d": true, + "**/*.d.*": true, + "**/*_batch*": true, + "**/*.marker": true, + "**/compile-commands/": true, + "**/objs": true, + "**/launcher-objs": true, + "**/*.cmdline": true, + "**/*.log": true, + ".vscode": true, + ".clangd": true + }, + + // Trailing whitespace should never be used in this project + "files.trimTrailingWhitespace": true + } +} \ No newline at end of file diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 25a65b1a298..b4fcb741a7d 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -3263,6 +3263,70 @@ int os::active_processor_count() { return _processor_count; } +#ifdef __APPLE__ +uint os::processor_id() { + static volatile int* volatile apic_to_cpu_mapping = NULL; + static volatile int next_cpu_id = 0; + + volatile int* mapping = OrderAccess::load_acquire(&apic_to_cpu_mapping); + if (mapping == NULL) { + // Calculate possible number space for APIC ids. This space is not necessarily + // in the range [0, number_of_cpus). + uint total_bits = 0; + for (uint i = 0;; ++i) { + uint eax = 0xb; // Query topology leaf + uint ebx; + uint ecx = i; + uint edx; + + __asm__ ("cpuid\n\t" : "+a" (eax), "+b" (ebx), "+c" (ecx), "+d" (edx) : ); + + uint level_type = (ecx >> 8) & 0xFF; + if (level_type == 0) { + // Invalid level; end of topology + break; + } + uint level_apic_id_shift = eax & ((1u << 5) - 1); + total_bits += level_apic_id_shift; + } + + uint max_apic_ids = 1u << total_bits; + mapping = NEW_C_HEAP_ARRAY(int, max_apic_ids, mtInternal); + + for (uint i = 0; i < max_apic_ids; ++i) { + mapping[i] = -1; + } + + if (!Atomic::replace_if_null(mapping, &apic_to_cpu_mapping)) { + FREE_C_HEAP_ARRAY(int, mapping); + mapping = OrderAccess::load_acquire(&apic_to_cpu_mapping); + } + } + + uint eax = 0xb; + uint ebx; + uint ecx = 0; + uint edx; + + asm ("cpuid\n\t" : "+a" (eax), "+b" (ebx), "+c" (ecx), "+d" (edx) : ); + + // Map from APIC id to a unique logical processor ID in the expected + // [0, num_processors) range. + + uint apic_id = edx; + int cpu_id = Atomic::load(&mapping[apic_id]); + + while (cpu_id < 0) { + if (Atomic::cmpxchg(-2, &mapping[apic_id], -1)) { + Atomic::store(Atomic::add(1, &next_cpu_id) - 1, &mapping[apic_id]); + } + cpu_id = Atomic::load(&mapping[apic_id]); + } + + return (uint)cpu_id; +} +#endif + void os::set_native_thread_name(const char *name) { #if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 // This is only supported in Snow Leopard and beyond diff --git a/src/hotspot/os/solaris/os_solaris.cpp b/src/hotspot/os/solaris/os_solaris.cpp index 86858359e32..c9213656ae7 100644 --- a/src/hotspot/os/solaris/os_solaris.cpp +++ b/src/hotspot/os/solaris/os_solaris.cpp @@ -2027,6 +2027,7 @@ void* os::signal(int signal_number, void* handler) { struct sigaction sigAct, oldSigAct; sigfillset(&(sigAct.sa_mask)); sigAct.sa_flags = SA_RESTART & ~SA_RESETHAND; + sigAct.sa_flags |= SA_SIGINFO; sigAct.sa_handler = CAST_TO_FN_PTR(sa_handler_t, handler); if (sigaction(signal_number, &sigAct, &oldSigAct)) { diff --git a/src/hotspot/share/aot/aotLoader.cpp b/src/hotspot/share/aot/aotLoader.cpp index 39e9905d103..741d24c23b2 100644 --- a/src/hotspot/share/aot/aotLoader.cpp +++ b/src/hotspot/share/aot/aotLoader.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "aot/aotCodeHeap.hpp" #include "aot/aotLoader.inline.hpp" +#include "classfile/javaClasses.hpp" #include "jvm.h" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" @@ -319,3 +320,24 @@ bool AOTLoader::reconcile_dynamic_invoke(InstanceKlass* holder, int index, Metho vmassert(success || thread->last_frame().sender(&map).is_deoptimized_frame(), "caller not deoptimized on failure"); return success; } + + +// This should be called very early during startup before any of the AOTed methods that use boxes can deoptimize. +// Deoptimization machinery expects the caches to be present and populated. +void AOTLoader::initialize_box_caches(TRAPS) { + if (!UseAOT || libraries_count() == 0) { + return; + } + TraceTime timer("AOT initialization of box caches", TRACETIME_LOG(Info, aot, startuptime)); + Symbol* box_classes[] = { java_lang_Boolean::symbol(), java_lang_Byte_ByteCache::symbol(), + java_lang_Short_ShortCache::symbol(), java_lang_Character_CharacterCache::symbol(), + java_lang_Integer_IntegerCache::symbol(), java_lang_Long_LongCache::symbol() }; + + for (unsigned i = 0; i < sizeof(box_classes) / sizeof(Symbol*); i++) { + Klass* k = SystemDictionary::resolve_or_fail(box_classes[i], true, CHECK); + InstanceKlass* ik = InstanceKlass::cast(k); + if (ik->is_not_initialized()) { + ik->initialize(CHECK); + } + } +} diff --git a/src/hotspot/share/aot/aotLoader.hpp b/src/hotspot/share/aot/aotLoader.hpp index 057ef32d3f6..df6dbed2f08 100644 --- a/src/hotspot/share/aot/aotLoader.hpp +++ b/src/hotspot/share/aot/aotLoader.hpp @@ -64,6 +64,7 @@ public: static void oops_do(OopClosure* f) NOT_AOT_RETURN; static void metadata_do(MetadataClosure* f) NOT_AOT_RETURN; static void mark_evol_dependent_methods(InstanceKlass* dependee) NOT_AOT_RETURN; + static void initialize_box_caches(TRAPS) NOT_AOT_RETURN; NOT_PRODUCT( static void print_statistics() NOT_AOT_RETURN; ) diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 76fce7466a3..0a409165f8b 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -4155,6 +4155,14 @@ int java_nio_Buffer::_limit_offset; int java_util_concurrent_locks_AbstractOwnableSynchronizer::_owner_offset; int reflect_ConstantPool::_oop_offset; int reflect_UnsafeStaticFieldAccessorImpl::_base_offset; +int java_lang_Integer_IntegerCache::_static_cache_offset; +int java_lang_Long_LongCache::_static_cache_offset; +int java_lang_Character_CharacterCache::_static_cache_offset; +int java_lang_Short_ShortCache::_static_cache_offset; +int java_lang_Byte_ByteCache::_static_cache_offset; +int java_lang_Boolean::_static_TRUE_offset; +int java_lang_Boolean::_static_FALSE_offset; + #define STACKTRACEELEMENT_FIELDS_DO(macro) \ @@ -4314,6 +4322,192 @@ void java_util_concurrent_locks_AbstractOwnableSynchronizer::serialize_offsets(S } #endif +#define INTEGER_CACHE_FIELDS_DO(macro) \ + macro(_static_cache_offset, k, "cache", java_lang_Integer_array_signature, true) + +void java_lang_Integer_IntegerCache::compute_offsets(InstanceKlass *k) { + guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized"); + INTEGER_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET); +} + +objArrayOop java_lang_Integer_IntegerCache::cache(InstanceKlass *ik) { + oop base = ik->static_field_base_raw(); + return objArrayOop(base->obj_field(_static_cache_offset)); +} + +Symbol* java_lang_Integer_IntegerCache::symbol() { + return vmSymbols::java_lang_Integer_IntegerCache(); +} + +#if INCLUDE_CDS +void java_lang_Integer_IntegerCache::serialize_offsets(SerializeClosure* f) { + INTEGER_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); +} +#endif +#undef INTEGER_CACHE_FIELDS_DO + +jint java_lang_Integer::value(oop obj) { + jvalue v; + java_lang_boxing_object::get_value(obj, &v); + return v.i; +} + +#define LONG_CACHE_FIELDS_DO(macro) \ + macro(_static_cache_offset, k, "cache", java_lang_Long_array_signature, true) + +void java_lang_Long_LongCache::compute_offsets(InstanceKlass *k) { + guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized"); + LONG_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET); +} + +objArrayOop java_lang_Long_LongCache::cache(InstanceKlass *ik) { + oop base = ik->static_field_base_raw(); + return objArrayOop(base->obj_field(_static_cache_offset)); +} + +Symbol* java_lang_Long_LongCache::symbol() { + return vmSymbols::java_lang_Long_LongCache(); +} + +#if INCLUDE_CDS +void java_lang_Long_LongCache::serialize_offsets(SerializeClosure* f) { + LONG_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); +} +#endif +#undef LONG_CACHE_FIELDS_DO + +jlong java_lang_Long::value(oop obj) { + jvalue v; + java_lang_boxing_object::get_value(obj, &v); + return v.j; +} + +#define CHARACTER_CACHE_FIELDS_DO(macro) \ + macro(_static_cache_offset, k, "cache", java_lang_Character_array_signature, true) + +void java_lang_Character_CharacterCache::compute_offsets(InstanceKlass *k) { + guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized"); + CHARACTER_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET); +} + +objArrayOop java_lang_Character_CharacterCache::cache(InstanceKlass *ik) { + oop base = ik->static_field_base_raw(); + return objArrayOop(base->obj_field(_static_cache_offset)); +} + +Symbol* java_lang_Character_CharacterCache::symbol() { + return vmSymbols::java_lang_Character_CharacterCache(); +} + +#if INCLUDE_CDS +void java_lang_Character_CharacterCache::serialize_offsets(SerializeClosure* f) { + CHARACTER_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); +} +#endif +#undef CHARACTER_CACHE_FIELDS_DO + +jchar java_lang_Character::value(oop obj) { + jvalue v; + java_lang_boxing_object::get_value(obj, &v); + return v.c; +} + +#define SHORT_CACHE_FIELDS_DO(macro) \ + macro(_static_cache_offset, k, "cache", java_lang_Short_array_signature, true) + +void java_lang_Short_ShortCache::compute_offsets(InstanceKlass *k) { + guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized"); + SHORT_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET); +} + +objArrayOop java_lang_Short_ShortCache::cache(InstanceKlass *ik) { + oop base = ik->static_field_base_raw(); + return objArrayOop(base->obj_field(_static_cache_offset)); +} + +Symbol* java_lang_Short_ShortCache::symbol() { + return vmSymbols::java_lang_Short_ShortCache(); +} + +#if INCLUDE_CDS +void java_lang_Short_ShortCache::serialize_offsets(SerializeClosure* f) { + SHORT_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); +} +#endif +#undef SHORT_CACHE_FIELDS_DO + +jshort java_lang_Short::value(oop obj) { + jvalue v; + java_lang_boxing_object::get_value(obj, &v); + return v.s; +} + +#define BYTE_CACHE_FIELDS_DO(macro) \ + macro(_static_cache_offset, k, "cache", java_lang_Byte_array_signature, true) + +void java_lang_Byte_ByteCache::compute_offsets(InstanceKlass *k) { + guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized"); + BYTE_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET); +} + +objArrayOop java_lang_Byte_ByteCache::cache(InstanceKlass *ik) { + oop base = ik->static_field_base_raw(); + return objArrayOop(base->obj_field(_static_cache_offset)); +} + +Symbol* java_lang_Byte_ByteCache::symbol() { + return vmSymbols::java_lang_Byte_ByteCache(); +} + +#if INCLUDE_CDS +void java_lang_Byte_ByteCache::serialize_offsets(SerializeClosure* f) { + BYTE_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); +} +#endif +#undef BYTE_CACHE_FIELDS_DO + +jbyte java_lang_Byte::value(oop obj) { + jvalue v; + java_lang_boxing_object::get_value(obj, &v); + return v.b; +} +#define BOOLEAN_FIELDS_DO(macro) \ + macro(_static_TRUE_offset, k, "TRUE", java_lang_Boolean_signature, true); \ + macro(_static_FALSE_offset, k, "FALSE", java_lang_Boolean_signature, true) + + +void java_lang_Boolean::compute_offsets(InstanceKlass *k) { + guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized"); + BOOLEAN_FIELDS_DO(FIELD_COMPUTE_OFFSET); +} + +oop java_lang_Boolean::get_TRUE(InstanceKlass *ik) { + oop base = ik->static_field_base_raw(); + return base->obj_field(_static_TRUE_offset); +} + +oop java_lang_Boolean::get_FALSE(InstanceKlass *ik) { + oop base = ik->static_field_base_raw(); + return base->obj_field(_static_FALSE_offset); +} + +Symbol* java_lang_Boolean::symbol() { + return vmSymbols::java_lang_Boolean(); +} + +#if INCLUDE_CDS +void java_lang_Boolean::serialize_offsets(SerializeClosure* f) { + BOOLEAN_FIELDS_DO(FIELD_SERIALIZE_OFFSET); +} +#endif +#undef BOOLEAN_CACHE_FIELDS_DO + +jboolean java_lang_Boolean::value(oop obj) { + jvalue v; + java_lang_boxing_object::get_value(obj, &v); + return v.z; +} + static int member_offset(int hardcoded_offset) { return (hardcoded_offset * heapOopSize) + instanceOopDesc::base_offset_in_bytes(); } diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp index a29928a7af2..4a279f57da8 100644 --- a/src/hotspot/share/classfile/javaClasses.hpp +++ b/src/hotspot/share/classfile/javaClasses.hpp @@ -1497,6 +1497,94 @@ class jdk_internal_misc_UnsafeConstants : AllStatic { static void serialize_offsets(SerializeClosure* f) { } }; +class java_lang_Integer : AllStatic { +public: + static jint value(oop obj); +}; + +class java_lang_Long : AllStatic { +public: + static jlong value(oop obj); +}; + +class java_lang_Character : AllStatic { +public: + static jchar value(oop obj); +}; + +class java_lang_Short : AllStatic { +public: + static jshort value(oop obj); +}; + +class java_lang_Byte : AllStatic { +public: + static jbyte value(oop obj); +}; + +class java_lang_Boolean : AllStatic { + private: + static int _static_TRUE_offset; + static int _static_FALSE_offset; + public: + static Symbol* symbol(); + static void compute_offsets(InstanceKlass* k); + static oop get_TRUE(InstanceKlass *k); + static oop get_FALSE(InstanceKlass *k); + static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; + static jboolean value(oop obj); +}; + +class java_lang_Integer_IntegerCache : AllStatic { + private: + static int _static_cache_offset; + public: + static Symbol* symbol(); + static void compute_offsets(InstanceKlass* k); + static objArrayOop cache(InstanceKlass *k); + static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; +}; + +class java_lang_Long_LongCache : AllStatic { + private: + static int _static_cache_offset; + public: + static Symbol* symbol(); + static void compute_offsets(InstanceKlass* k); + static objArrayOop cache(InstanceKlass *k); + static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; +}; + +class java_lang_Character_CharacterCache : AllStatic { + private: + static int _static_cache_offset; + public: + static Symbol* symbol(); + static void compute_offsets(InstanceKlass* k); + static objArrayOop cache(InstanceKlass *k); + static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; +}; + +class java_lang_Short_ShortCache : AllStatic { + private: + static int _static_cache_offset; + public: + static Symbol* symbol(); + static void compute_offsets(InstanceKlass* k); + static objArrayOop cache(InstanceKlass *k); + static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; +}; + +class java_lang_Byte_ByteCache : AllStatic { + private: + static int _static_cache_offset; + public: + static Symbol* symbol(); + static void compute_offsets(InstanceKlass* k); + static objArrayOop cache(InstanceKlass *k); + static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; +}; + // Use to declare fields that need to be injected into Java classes // for the JVM to use. The name_index and signature_index are // declared in vmSymbols. The may_be_java flag is used to declare diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index 59d6f5381eb..180f2920ba9 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -442,6 +442,11 @@ template(getProtectionDomain_name, "getProtectionDomain") \ template(getProtectionDomain_signature, "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \ template(java_lang_Integer_array_signature, "[Ljava/lang/Integer;") \ + template(java_lang_Long_array_signature, "[Ljava/lang/Long;") \ + template(java_lang_Character_array_signature, "[Ljava/lang/Character;") \ + template(java_lang_Short_array_signature, "[Ljava/lang/Short;") \ + template(java_lang_Byte_array_signature, "[Ljava/lang/Byte;") \ + template(java_lang_Boolean_signature, "Ljava/lang/Boolean;") \ template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \ template(module_entry_name, "module_entry") \ template(resolved_references_name, "
* Once an agent acquires an Instrumentation
instance,
* the agent may call methods on the instance at any time.
- *
+ *
* @apiNote This interface is not intended to be implemented outside of
* the java.instrument module.
*
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java
index 60ef30078cd..8500167d6b5 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,6 +43,7 @@ public final class VirtualObject implements JavaValue {
private JavaValue[] values;
private JavaKind[] slotKinds;
private final int id;
+ private boolean isAutoBox;
/**
* Creates a new {@link VirtualObject} for the given type, with the given fields. If
@@ -58,12 +59,33 @@ public final class VirtualObject implements JavaValue {
* @return a new {@link VirtualObject} instance.
*/
public static VirtualObject get(ResolvedJavaType type, int id) {
- return new VirtualObject(type, id);
+ return new VirtualObject(type, id, false);
}
- private VirtualObject(ResolvedJavaType type, int id) {
+ /**
+ * Creates a new {@link VirtualObject} for the given type, with the given fields. If
+ * {@code type} is an instance class then {@code values} provides the values for the fields
+ * returned by {@link ResolvedJavaType#getInstanceFields(boolean) getInstanceFields(true)}. If
+ * {@code type} is an array then the length of the values array determines the reallocated array
+ * length.
+ *
+ * @param type the type of the object whose allocation was removed during compilation. This can
+ * be either an instance of an array type.
+ * @param id a unique id that identifies the object within the debug information for one
+ * position in the compiled code.
+ * @param isAutoBox a flag that tells the runtime that the object may be a boxed primitive and
+ * that it possibly needs to be obtained for the box cache instead of creating
+ * a new instance.
+ * @return a new {@link VirtualObject} instance.
+ */
+ public static VirtualObject get(ResolvedJavaType type, int id, boolean isAutoBox) {
+ return new VirtualObject(type, id, isAutoBox);
+ }
+
+ private VirtualObject(ResolvedJavaType type, int id, boolean isAutoBox) {
this.type = type;
this.id = id;
+ this.isAutoBox = isAutoBox;
}
private static StringBuilder appendValue(StringBuilder buf, JavaValue value, Set
* An import declaration is {@linkplain Kind#isPersistent() persistent}.
+ *
+ * @jls 7.5 Import Declarations
*/
IMPORT(true),
@@ -91,9 +92,10 @@ public abstract class Snippet {
* annotation interfaces -- see {@link jdk.jshell.Snippet.SubKind} to
* differentiate.
*
- * @jls 7.6 Top Level Type Declarations
*
* A type declaration is {@linkplain Kind#isPersistent() persistent}.
+ *
+ * @jls 7.6 Top Level Type Declarations
*/
TYPE_DECL(true),
@@ -101,9 +103,10 @@ public abstract class Snippet {
* A method declaration.
* The snippet is an instance of {@link jdk.jshell.MethodSnippet}.
*
- * @jls 8.4 Method Declarations
*
* A method declaration is {@linkplain Kind#isPersistent() persistent}.
+ *
+ * @jls 8.4 Method Declarations
*/
METHOD(true),
@@ -116,9 +119,10 @@ public abstract class Snippet {
* variable representing an expression -- see
* {@link jdk.jshell.Snippet.SubKind}to differentiate.
*
- * @jls 8.3 Field Declarations
*
* A variable declaration is {@linkplain Kind#isPersistent() persistent}.
+ *
+ * @jls 8.3 Field Declarations
*/
VAR(true),
diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt
index 737da5ed0cd..af66f3be1d3 100644
--- a/test/hotspot/jtreg/ProblemList.txt
+++ b/test/hotspot/jtreg/ProblemList.txt
@@ -74,6 +74,7 @@ gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all
gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all
gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all
gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8193639 solaris-all
+gc/stress/TestReclaimStringsLeaksMemory.java 8224847 generic-all
#############################################################################
diff --git a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/IsMatureVsReprofileTest.java b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/IsMatureVsReprofileTest.java
index 0f7e8baa8c9..5987f35c8e9 100644
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/IsMatureVsReprofileTest.java
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/IsMatureVsReprofileTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
- * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Xbatch
+ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Xbatch -XX:CompileThresholdScaling=1.0
* compiler.jvmci.compilerToVM.IsMatureVsReprofileTest
*/
diff --git a/test/hotspot/jtreg/compiler/loopopts/LoopUnswitchingBadNodeBudget.java b/test/hotspot/jtreg/compiler/loopopts/LoopUnswitchingBadNodeBudget.java
new file mode 100644
index 00000000000..a69e65cdce7
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/loopopts/LoopUnswitchingBadNodeBudget.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 8223502
+ * @summary Node estimate for loop unswitching is not correct:
+ * assert(delta <= 2 * required) failed: Bad node estimate
+ *
+ * @requires !vm.graal.enabled
+ *
+ * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation
+ * -XX:-UseOnStackReplacement -XX:CompileOnly=LoopUnswitchingBadNodeBudget::test
+ * -XX:CompileCommand=dontinline,LoopUnswitchingBadNodeBudget::helper
+ * -XX:+UnlockExperimentalVMOptions -XX:-UseSwitchProfiling LoopUnswitchingBadNodeBudget
+ *
+ */
+
+public class LoopUnswitchingBadNodeBudget {
+
+ public static void main(String[] args) {
+ for (int i = 0; i < 20_000; i++) {
+ for (int j = 0; j < 100; j++) {
+ test(j, true, 0, 0, 0);
+ test(j, false, 0, 0, 0);
+ }
+ }
+ }
+
+ private static int test(int j, boolean flag, int k, int l, int m) {
+ int res = 0;
+ for (int i = 0; i < 24; i++) {
+ if (flag) {
+ k = k / 2;
+ l = l * 2;
+ m = m + 2;
+ }
+ switch (j) {
+ case 0: break;
+ case 1: return helper(j, k, l, m);
+ case 2: return helper(j, k, l, m);
+ case 3: return helper(j, k, l, m);
+ case 4: return helper(j, k, l, m);
+ case 5: return helper(j, k, l, m);
+ case 6: return helper(j, k, l, m);
+ case 7: return helper(j, k, l, m);
+ case 8: return helper(j, k, l, m);
+ case 9: return helper(j, k, l, m);
+ case 10: return helper(j, k, l, m);
+ case 11: return helper(j, k, l, m);
+ case 12: return helper(j, k, l, m);
+ case 13: return helper(j, k, l, m);
+ case 14: return helper(j, k, l, m);
+ case 15: return helper(j, k, l, m);
+ case 16: return helper(j, k, l, m);
+ case 17: return helper(j, k, l, m);
+ case 18: return helper(j, k, l, m);
+ case 19: return helper(j, k, l, m);
+ case 20: return helper(j, k, l, m);
+ case 21: return helper(j, k, l, m);
+ case 22: return helper(j, k, l, m);
+ case 23: return helper(j, k, l, m);
+ case 24: return helper(j, k, l, m);
+ case 25: return helper(j, k, l, m);
+ case 26: return helper(j, k, l, m);
+ case 27: return helper(j, k, l, m);
+ case 28: return helper(j, k, l, m);
+ case 29: return helper(j, k, l, m);
+ case 30: return helper(j, k, l, m);
+ case 31: return helper(j, k, l, m);
+ case 32: return helper(j, k, l, m);
+ case 33: return helper(j, k, l, m);
+ case 34: return helper(j, k, l, m);
+ case 35: return helper(j, k, l, m);
+ case 36: return helper(j, k, l, m);
+ case 37: return helper(j, k, l, m);
+ case 38: return helper(j, k, l, m);
+ case 39: return helper(j, k, l, m);
+ case 40: return helper(j, k, l, m);
+ case 41: return helper(j, k, l, m);
+ case 42: return helper(j, k, l, m);
+ case 43: return helper(j, k, l, m);
+ case 44: return helper(j, k, l, m);
+ case 45: return helper(j, k, l, m);
+ case 46: return helper(j, k, l, m);
+ case 47: return helper(j, k, l, m);
+ case 48: return helper(j, k, l, m);
+ case 49: return helper(j, k, l, m);
+ case 50: return helper(j, k, l, m);
+ case 51: return helper(j, k, l, m);
+ case 52: return helper(j, k, l, m);
+ case 53: return helper(j, k, l, m);
+ case 54: return helper(j, k, l, m);
+ case 55: return helper(j, k, l, m);
+ case 56: return helper(j, k, l, m);
+ case 57: return helper(j, k, l, m);
+ case 58: return helper(j, k, l, m);
+ case 59: return helper(j, k, l, m);
+ case 60: return helper(j, k, l, m);
+ case 61: return helper(j, k, l, m);
+ case 62: return helper(j, k, l, m);
+ case 63: return helper(j, k, l, m);
+ case 64: return helper(j, k, l, m);
+ case 65: return helper(j, k, l, m);
+ case 66: return helper(j, k, l, m);
+ case 67: return helper(j, k, l, m);
+ case 68: return helper(j, k, l, m);
+ case 69: return helper(j, k, l, m);
+ case 70: return helper(j, k, l, m);
+ case 71: return helper(j, k, l, m);
+ case 72: return helper(j, k, l, m);
+ case 73: return helper(j, k, l, m);
+ case 74: return helper(j, k, l, m);
+ case 75: return helper(j, k, l, m);
+ case 76: return helper(j, k, l, m);
+ case 77: return helper(j, k, l, m);
+ case 78: return helper(j, k, l, m);
+ case 79: return helper(j, k, l, m);
+ case 80: return helper(j, k, l, m);
+ case 81: return helper(j, k, l, m);
+ case 82: return helper(j, k, l, m);
+ case 83: return helper(j, k, l, m);
+ case 84: return helper(j, k, l, m);
+ case 85: return helper(j, k, l, m);
+ case 86: return helper(j, k, l, m);
+ case 87: return helper(j, k, l, m);
+ case 88: return helper(j, k, l, m);
+ case 89: return helper(j, k, l, m);
+ case 90: return helper(j, k, l, m);
+ case 91: return helper(j, k, l, m);
+ case 92: return helper(j, k, l, m);
+ case 93: return helper(j, k, l, m);
+ case 94: return helper(j, k, l, m);
+ case 95: return helper(j, k, l, m);
+ case 96: return helper(j, k, l, m);
+ case 97: return helper(j, k, l, m);
+ case 98: return helper(j, k, l, m);
+ case 99: return helper(j, k, l, m);
+ }
+ res += helper(j, k, l, m);
+ }
+ return res;
+ }
+
+ private static int helper(int j, int k, int l, int m) {
+ return j + k;
+ }
+}
diff --git a/test/langtools/ProblemList.txt b/test/langtools/ProblemList.txt
index d36bf5e3aef..d8e9fad98ce 100644
--- a/test/langtools/ProblemList.txt
+++ b/test/langtools/ProblemList.txt
@@ -37,7 +37,7 @@ jdk/javadoc/doclet/testIOException/TestIOException.java
jdk/jshell/UserJdiUserRemoteTest.java 8173079 linux-all
jdk/jshell/UserInputTest.java 8169536 generic-all
-## jdk/jshell/ExceptionsTest.java 8200701 windows-all
+jdk/jshell/ExceptionsTest.java 8200701 windows-all
###########################################################################
#
diff --git a/test/langtools/jdk/jshell/DropTest.java b/test/langtools/jdk/jshell/DropTest.java
index 134922ffa9c..e277d1cbeea 100644
--- a/test/langtools/jdk/jshell/DropTest.java
+++ b/test/langtools/jdk/jshell/DropTest.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8081431 8080069 8167128
+ * @bug 8081431 8080069 8167128 8199623
* @summary Test of JShell#drop().
* @build KullaTesting TestingInputStream
* @run testng DropTest
@@ -31,6 +31,7 @@
import jdk.jshell.DeclarationSnippet;
import jdk.jshell.Snippet;
+import jdk.jshell.MethodSnippet;
import jdk.jshell.VarSnippet;
import org.testng.annotations.Test;
@@ -225,4 +226,17 @@ public class DropTest extends KullaTesting {
ste(MAIN_SNIPPET, VALID, VALID, true, null),
ste(ax, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
}
+
+ // 8199623
+ public void testTwoForkedDrop() {
+ MethodSnippet p = methodKey(assertEval("void p() throws Exception { ((String) null).toString(); }"));
+ MethodSnippet n = methodKey(assertEval("void n() throws Exception { try { p(); } catch (Exception ex) { throw new RuntimeException(\"bar\", ex); }}"));
+ MethodSnippet m = methodKey(assertEval("void m() { try { n(); } catch (Exception ex) { throw new RuntimeException(\"foo\", ex); }}"));
+ MethodSnippet c = methodKey(assertEval("void c() throws Throwable { p(); }"));
+ assertDrop(p,
+ ste(p, VALID, DROPPED, true, null),
+ ste(n, VALID, RECOVERABLE_DEFINED, false, p),
+ ste(c, VALID, RECOVERABLE_DEFINED, false, p));
+ assertActiveKeys();
+ }
}
diff --git a/test/langtools/jdk/jshell/ToolSimpleTest.java b/test/langtools/jdk/jshell/ToolSimpleTest.java
index d937d9f136e..285370cfd85 100644
--- a/test/langtools/jdk/jshell/ToolSimpleTest.java
+++ b/test/langtools/jdk/jshell/ToolSimpleTest.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466 8172154 8192979 8191842 8198573 8198801 8210596 8210959 8215099
+ * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466 8172154 8192979 8191842 8198573 8198801 8210596 8210959 8215099 8199623
* @summary Simple jshell tool tests
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
@@ -270,6 +270,33 @@ public class ToolSimpleTest extends ReplToolTesting {
);
}
+ // 8199623
+ @Test
+ public void testTwoForkedDrop() {
+ test(
+ (a) -> assertCommand(a, "void p() throws Exception { ((String) null).toString(); }",
+ "| created method p()"),
+ (a) -> assertCommand(a, "void n() throws Exception { try { p(); } catch (Exception ex) { throw new IOException(\"bar\", ex); }} ",
+ "| created method n()"),
+ (a) -> assertCommand(a, "void m() { try { n(); } catch (Exception ex) { throw new RuntimeException(\"foo\", ex); }}",
+ "| created method m()"),
+ (a) -> assertCommand(a, "void c() throws Throwable { p(); }",
+ "| created method c()"),
+ (a) -> assertCommand(a, "/drop p",
+ "| dropped method p()"),
+ (a) -> assertCommand(a, "m()",
+ "| attempted to call method n() which cannot be invoked until method p() is declared"),
+ (a) -> assertCommand(a, "/meth n",
+ "| void n()\n" +
+ "| which cannot be invoked until method p() is declared"),
+ (a) -> assertCommand(a, "/meth m",
+ "| void m()"),
+ (a) -> assertCommand(a, "/meth c",
+ "| void c()\n" +
+ "| which cannot be invoked until method p() is declared")
+ );
+ }
+
@Test
public void testUnknownCommand() {
test((a) -> assertCommand(a, "/unknown",
diff --git a/test/make/TestMakeBase.gmk b/test/make/TestMakeBase.gmk
index 64dd83b9e58..71dec2277b0 100644
--- a/test/make/TestMakeBase.gmk
+++ b/test/make/TestMakeBase.gmk
@@ -361,6 +361,18 @@ $(call AssertEquals, \
RelativePath, \
)
+$(call AssertEquals, \
+ $(call RelativePath, /foo/bar/baz/banan/kung, /foo/bar/baz), \
+ ./banan/kung, \
+ RelativePath, \
+)
+
+$(call AssertEquals, \
+ $(call RelativePath, /foo/bar/baz/banan/kung, /foo/bar/baz/), \
+ ./banan/kung, \
+ RelativePath, \
+)
+
################################################################################
# Test ParseKeywordVariable