diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index d64030683e5a1..074ddce89b7be 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -242,6 +242,8 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS], WARNINGS_ENABLE_ALL_CFLAGS="-Wall -Wextra -Wformat=2 $WARNINGS_ENABLE_ADDITIONAL" WARNINGS_ENABLE_ALL_CXXFLAGS="$WARNINGS_ENABLE_ALL_CFLAGS $WARNINGS_ENABLE_ADDITIONAL_CXX" + # These warnings will never be turned on, since they generate too many + # false positives. DISABLED_WARNINGS="unused-parameter" # gcc10/11 on ppc generate lots of abi warnings about layout of aggregates containing vectors if test "x$OPENJDK_TARGET_CPU_ARCH" = "xppc"; then @@ -259,7 +261,9 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS], -Wunused-function -Wundef -Wunused-value -Woverloaded-virtual" WARNINGS_ENABLE_ALL="-Wall -Wextra -Wformat=2 $WARNINGS_ENABLE_ADDITIONAL" - DISABLED_WARNINGS="unknown-warning-option unused-parameter unused" + # These warnings will never be turned on, since they generate too many + # false positives. + DISABLED_WARNINGS="unknown-warning-option unused-parameter" ;; esac AC_SUBST(DISABLE_WARNING_PREFIX) diff --git a/make/common/TestFilesCompilation.gmk b/make/common/TestFilesCompilation.gmk index 19d1e92332f0a..b7cb4f40e5c40 100644 --- a/make/common/TestFilesCompilation.gmk +++ b/make/common/TestFilesCompilation.gmk @@ -115,8 +115,9 @@ define SetupTestFilesCompilationBody DISABLED_WARNINGS_gcc := format undef unused-but-set-variable \ unused-const-variable unused-function unused-value \ unused-variable, \ - DISABLED_WARNINGS_clang := undef format-nonliteral \ - missing-field-initializers sometimes-uninitialized, \ + DISABLED_WARNINGS_clang := format-nonliteral \ + missing-field-initializers sometimes-uninitialized undef \ + unused-but-set-variable unused-function unused-variable, \ DEFAULT_LIBCXX := false, \ JDK_LIBS := $$($1_JDK_LIBS_$$(name)), \ LIBS := $$($1_LIBS_$$(name)), \ diff --git a/make/common/modules/LauncherCommon.gmk b/make/common/modules/LauncherCommon.gmk index 487454f24ae7b..ef65f9e431f00 100644 --- a/make/common/modules/LauncherCommon.gmk +++ b/make/common/modules/LauncherCommon.gmk @@ -136,6 +136,7 @@ define SetupBuildLauncherBody CFLAGS_windows := $$($1_CFLAGS_windows), \ EXTRA_HEADER_DIRS := java.base:libjvm, \ DISABLED_WARNINGS_gcc := unused-function unused-variable, \ + DISABLED_WARNINGS_clang := unused-function, \ LDFLAGS := $$($1_LDFLAGS), \ LDFLAGS_linux := $$(call SET_EXECUTABLE_ORIGIN,/../lib), \ LDFLAGS_macosx := $$(call SET_EXECUTABLE_ORIGIN,/../lib), \ diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk index 39a8ab86acf05..7b5ee7ce48e26 100644 --- a/make/hotspot/lib/CompileJvm.gmk +++ b/make/hotspot/lib/CompileJvm.gmk @@ -95,8 +95,9 @@ DISABLED_WARNINGS_gcc := array-bounds comment delete-non-virtual-dtor \ shift-negative-value unknown-pragmas unused-but-set-variable \ unused-local-typedefs unused-variable -DISABLED_WARNINGS_clang := sometimes-uninitialized \ - missing-braces delete-non-abstract-non-virtual-dtor unknown-pragmas +DISABLED_WARNINGS_clang := delete-non-abstract-non-virtual-dtor missing-braces \ + sometimes-uninitialized unknown-pragmas unused-but-set-variable \ + unused-function unused-local-typedef unused-private-field unused-variable ifneq ($(DEBUG_LEVEL), release) # Assert macro gives warning diff --git a/make/jdk/src/classes/build/tools/taglet/JSpec.java b/make/jdk/src/classes/build/tools/taglet/JSpec.java index fda372c8b0114..34cc2bd6b5029 100644 --- a/make/jdk/src/classes/build/tools/taglet/JSpec.java +++ b/make/jdk/src/classes/build/tools/taglet/JSpec.java @@ -106,7 +106,8 @@ public JVMS() { this.idPrefix = idPrefix; } - private static final Pattern TAG_PATTERN = Pattern.compile("(?s)(.+ )?(?[1-9][0-9]*)(?
[0-9.]*)( .*)?$"); + // Note: Matches special cases like @jvms 6.5.checkcast + private static final Pattern TAG_PATTERN = Pattern.compile("(?s)(.+ )?(?[1-9][0-9]*)(?
[0-9a-z_.]*)( .*)?$"); /** * Returns the set of locations in which the tag may be used. diff --git a/make/modules/java.base/Lib.gmk b/make/modules/java.base/Lib.gmk index b41dbe4e1d642..978825ab0bde1 100644 --- a/make/modules/java.base/Lib.gmk +++ b/make/modules/java.base/Lib.gmk @@ -46,7 +46,9 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBNET, \ OPTIMIZATION := LOW, \ DISABLED_WARNINGS_gcc_net_util_md.c := format-nonliteral unused-variable, \ DISABLED_WARNINGS_gcc_NetworkInterface.c := unused-function, \ - DISABLED_WARNINGS_clang_net_util_md.c := format-nonliteral, \ + DISABLED_WARNINGS_clang_net_util_md.c := format-nonliteral \ + unused-variable, \ + DISABLED_WARNINGS_clang_NetworkInterface.c := unused-function, \ DISABLED_WARNINGS_clang_aix_DefaultProxySelector.c := \ deprecated-non-prototype, \ DISABLED_WARNINGS_clang_aix_NetworkInterface.c := gnu-pointer-arith, \ @@ -77,6 +79,8 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBNIO, \ libnio/ch \ libnio/fs \ libjvm, \ + DISABLED_WARNINGS_clang_Net.c := unused-function unused-variable, \ + DISABLED_WARNINGS_clang_UnixNativeDispatcher.c := unused-variable, \ JDK_LIBS := libjava libnet, \ LIBS_linux := $(LIBDL) -lpthread, \ LIBS_aix := $(LIBDL), \ @@ -96,7 +100,8 @@ ifeq ($(call isTargetOs, macosx), true) $(eval $(call SetupJdkLibrary, BUILD_LIBOSXSECURITY, \ NAME := osxsecurity, \ OPTIMIZATION := LOW, \ - DISABLED_WARNINGS_clang_KeystoreImpl.m := deprecated-declarations, \ + DISABLED_WARNINGS_clang_KeystoreImpl.m := deprecated-declarations \ + unused-but-set-variable unused-variable, \ JDK_LIBS := libjava, \ LIBS_macosx := -lobjc \ -framework CoreServices \ @@ -117,6 +122,7 @@ ifeq ($(call isTargetOsType, unix), true) OPTIMIZATION := LOW, \ jsig.c_CFLAGS := -DHOTSPOT_VM_DISTRO='"$(HOTSPOT_VM_DISTRO)"', \ DISABLED_WARNINGS_gcc_jsig.c := unused-but-set-variable, \ + DISABLED_WARNINGS_clang_jsig.c := unused-but-set-variable, \ LIBS_linux := $(LIBDL), \ LIBS_aix := $(LIBDL), \ )) diff --git a/make/modules/java.base/lib/CoreLibraries.gmk b/make/modules/java.base/lib/CoreLibraries.gmk index 119e3e6b87dcd..fb12547113aa3 100644 --- a/make/modules/java.base/lib/CoreLibraries.gmk +++ b/make/modules/java.base/lib/CoreLibraries.gmk @@ -36,6 +36,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBVERIFY, \ NAME := verify, \ OPTIMIZATION := $(LIBVERIFY_OPTIMIZATION), \ DISABLED_WARNINGS_gcc_check_code.c := unused-variable, \ + DISABLED_WARNINGS_clang_check_code.c := unused-variable, \ EXTRA_HEADER_DIRS := libjava, \ JDK_LIBS := libjvm, \ )) @@ -59,6 +60,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJAVA, \ java_props_md.c_CFLAGS := \ -DARCHPROPNAME='"$(OPENJDK_TARGET_CPU_OSARCH)"', \ DISABLED_WARNINGS_gcc_ProcessImpl_md.c := unused-result, \ + DISABLED_WARNINGS_clang_TimeZone_md.c := unused-variable, \ JDK_LIBS := libjvm, \ LIBS_linux := $(LIBDL), \ LIBS_aix := $(LIBDL) $(LIBM),\ @@ -93,6 +95,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBZIP, \ DISABLED_WARNINGS_gcc_zip_util.c := unused-function, \ DISABLED_WARNINGS_clang := deprecated-non-prototype, \ DISABLED_WARNINGS_clang_gzwrite.c := format-nonliteral, \ + DISABLED_WARNINGS_clang_zip_util.c := unused-function, \ JDK_LIBS := libjava libjvm, \ LIBS_unix := $(LIBZ_LIBS), \ )) @@ -112,6 +115,9 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJIMAGE, \ DISABLED_WARNINGS_gcc_imageDecompressor.cpp := unused-variable, \ DISABLED_WARNINGS_gcc_imageFile.cpp := unused-const-variable \ unused-variable, \ + DISABLED_WARNINGS_clang_imageDecompressor.cpp := unused-variable, \ + DISABLED_WARNINGS_clang_imageFile.cpp := unused-private-field \ + unused-variable, \ LDFLAGS := $(LDFLAGS_CXX_JDK), \ JDK_LIBS := libjvm, \ LIBS_unix := $(LIBDL), \ @@ -172,7 +178,9 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJLI, \ OPTIMIZATION := HIGH, \ CFLAGS := $(LIBJLI_CFLAGS) $(LIBZ_CFLAGS), \ DISABLED_WARNINGS_gcc := unused-function unused-variable, \ - DISABLED_WARNINGS_clang := format-nonliteral deprecated-non-prototype, \ + DISABLED_WARNINGS_clang := deprecated-non-prototype format-nonliteral \ + unused-function, \ + DISABLED_WARNINGS_clang_java_md_macosx.m := unused-variable, \ LIBS_unix := $(LIBZ_LIBS), \ LIBS_linux := $(LIBDL) -lpthread, \ LIBS_macosx := \ diff --git a/make/modules/java.desktop/Lib.gmk b/make/modules/java.desktop/Lib.gmk index cc12d3566be04..18f386ae6b41f 100644 --- a/make/modules/java.desktop/Lib.gmk +++ b/make/modules/java.desktop/Lib.gmk @@ -65,7 +65,10 @@ ifeq ($(call isTargetOs, aix), false) CFLAGS := $(LIBJSOUND_CFLAGS), \ CXXFLAGS := $(LIBJSOUND_CFLAGS), \ DISABLED_WARNINGS_gcc := undef unused-variable, \ - DISABLED_WARNINGS_clang := undef, \ + DISABLED_WARNINGS_clang := undef unused-variable, \ + DISABLED_WARNINGS_clang_PLATFORM_API_MacOSX_MidiUtils.c := \ + unused-but-set-variable, \ + DISABLED_WARNINGS_clang_DirectAudioDevice.c := unused-function, \ LIBS_linux := $(ALSA_LIBS), \ LIBS_macosx := \ -framework AudioToolbox \ diff --git a/make/modules/java.desktop/lib/AwtLibraries.gmk b/make/modules/java.desktop/lib/AwtLibraries.gmk index c5c698b14e87a..aaf5100d83b37 100644 --- a/make/modules/java.desktop/lib/AwtLibraries.gmk +++ b/make/modules/java.desktop/lib/AwtLibraries.gmk @@ -113,6 +113,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \ DISABLED_WARNINGS_gcc_Region.c := maybe-uninitialized, \ DISABLED_WARNINGS_gcc_SurfaceData.c := unused-value, \ DISABLED_WARNINGS_gcc_TransformHelper.c := sign-compare, \ + DISABLED_WARNINGS_clang := unused-but-set-variable unused-variable, \ DISABLED_WARNINGS_clang_awt_ImagingLib.c := deprecated-non-prototype, \ DISABLED_WARNINGS_clang_debug_trace.c := format-nonliteral, \ DISABLED_WARNINGS_clang_Trace.c := format-nonliteral, \ @@ -180,8 +181,11 @@ ifeq ($(call isTargetOs, windows macosx), false) $(X_CFLAGS), \ EXTRA_HEADER_DIRS := $(LIBAWT_HEADLESS_EXTRA_HEADER_DIRS), \ DISABLED_WARNINGS_gcc := unused-variable, \ + DISABLED_WARNINGS_clang := unused-variable, \ DISABLED_WARNINGS_gcc_X11Renderer.c := unused-function, \ DISABLED_WARNINGS_gcc_X11SurfaceData.c := unused-function, \ + DISABLED_WARNINGS_clang_X11Renderer.c := unused-function, \ + DISABLED_WARNINGS_clang_X11SurfaceData.c := unused-function, \ JDK_LIBS := libawt java.base:libjava, \ LIBS_linux := $(LIBDL) $(LIBM), \ STATIC_LIB_EXCLUDE_OBJS := $(LIBAWT_HEADLESS_STATIC_EXCLUDE_OBJS), \ @@ -237,6 +241,7 @@ ifeq ($(call isTargetOs, windows macosx)+$(ENABLE_HEADLESS_ONLY), false+false) CFLAGS := -DXAWT -DXAWT_HACK $(LIBAWT_XAWT_CFLAGS) \ $(FONTCONFIG_CFLAGS) $(CUPS_CFLAGS) $(X_CFLAGS), \ DISABLED_WARNINGS_gcc := int-to-pointer-cast unused-variable, \ + DISABLED_WARNINGS_clang := unused-variable, \ DISABLED_WARNINGS_gcc_awt_Taskbar.c := parentheses, \ DISABLED_WARNINGS_gcc_GLXSurfaceData.c := unused-function, \ DISABLED_WARNINGS_gcc_gtk3_interface.c := parentheses type-limits \ @@ -255,20 +260,22 @@ ifeq ($(call isTargetOs, windows macosx)+$(ENABLE_HEADLESS_ONLY), false+false) DISABLED_WARNINGS_gcc_XToolkit.c := unused-result, \ DISABLED_WARNINGS_gcc_XWindow.c := unused-function, \ DISABLED_WARNINGS_clang_awt_Taskbar.c := parentheses, \ - DISABLED_WARNINGS_clang_gtk3_interface.c := parentheses, \ + DISABLED_WARNINGS_clang_gtk3_interface.c := unused-function parentheses, \ + DISABLED_WARNINGS_clang_GLXSurfaceData.c := unused-function, \ DISABLED_WARNINGS_clang_OGLBufImgOps.c := format-nonliteral, \ DISABLED_WARNINGS_clang_OGLPaints.c := format-nonliteral, \ DISABLED_WARNINGS_clang_screencast_pipewire.c := format-nonliteral, \ DISABLED_WARNINGS_clang_sun_awt_X11_GtkFileDialogPeer.c := parentheses, \ + DISABLED_WARNINGS_clang_XWindow.c := unused-function, \ DISABLED_WARNINGS_clang_aix := deprecated-non-prototype, \ DISABLED_WARNINGS_clang_aix_awt_Taskbar.c := parentheses, \ DISABLED_WARNINGS_clang_aix_OGLPaints.c := format-nonliteral, \ DISABLED_WARNINGS_clang_aix_OGLBufImgOps.c := format-nonliteral, \ - DISABLED_WARNINGS_clang_aix_gtk3_interface.c := parentheses \ + DISABLED_WARNINGS_clang_aix_gtk3_interface.c := unused-function parentheses \ logical-op-parentheses, \ DISABLED_WARNINGS_clang_aix_sun_awt_X11_GtkFileDialogPeer.c := \ parentheses, \ - DISABLED_WARNINGS_clang_aix_awt_InputMethod.c := sign-compare, \ + DISABLED_WARNINGS_clang_aix_awt_InputMethod.c := unused-function sign-compare, \ JDK_LIBS := libawt java.base:libjava, \ LIBS_unix := $(LIBDL) $(LIBM) $(X_LIBS) -lX11 -lXext -lXi -lXrender \ -lXtst, \ @@ -312,9 +319,10 @@ ifeq ($(call isTargetOs, macosx), true) EXCLUDES := $(LIBAWT_LWAWT_EXCLUDES), \ OPTIMIZATION := LOW, \ EXTRA_HEADER_DIRS := $(LIBAWT_LWAWT_EXTRA_HEADER_DIRS), \ - DISABLED_WARNINGS_clang := incomplete-implementation \ - deprecated-declarations objc-method-access \ - incompatible-pointer-types extra-tokens sign-compare undef, \ + DISABLED_WARNINGS_clang := deprecated-declarations extra-tokens \ + incompatible-pointer-types incomplete-implementation \ + objc-method-access sign-compare undef unused-function \ + unused-variable, \ DISABLED_WARNINGS_clang_AWTWindow.m := bitwise-op-parentheses, \ DISABLED_WARNINGS_clang_CFileDialog.m := semicolon-before-method-body, \ DISABLED_WARNINGS_clang_CGGlyphImages.m := pointer-arith, \ diff --git a/make/modules/java.desktop/lib/ClientLibraries.gmk b/make/modules/java.desktop/lib/ClientLibraries.gmk index 51147b71af9a4..5f3ae8ce2142f 100644 --- a/make/modules/java.desktop/lib/ClientLibraries.gmk +++ b/make/modules/java.desktop/lib/ClientLibraries.gmk @@ -46,6 +46,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBMLIB_IMAGE, \ CFLAGS := -D__USE_J2D_NAMES -D__MEDIALIB_OLD_NAMES -DMLIB_NO_LIBSUNMATH \ $(LIBMLIB_IMAGE_CFLAGS), \ DISABLED_WARNINGS_gcc := unused-function, \ + DISABLED_WARNINGS_clang_mlib_ImageCreate.c := unused-function, \ LIBS_unix := $(LIBDL) $(LIBM), \ )) @@ -122,6 +123,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJAVAJPEG, \ unused-but-set-variable, \ DISABLED_WARNINGS_gcc_jcmaster.c := implicit-fallthrough, \ DISABLED_WARNINGS_gcc_jdphuff.c := shift-negative-value, \ + DISABLED_WARNINGS_clang_imageioJPEG.c := unused-but-set-variable, \ JDK_LIBS := java.base:libjava, \ LIBS := $(LIBJPEG_LIBS), \ )) @@ -230,10 +232,12 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) DISABLED_WARNINGS_clang := deprecated-non-prototype, \ DISABLED_WARNINGS_clang_dgif_lib.c := sign-compare, \ DISABLED_WARNINGS_clang_gzwrite.c := format-nonliteral, \ - DISABLED_WARNINGS_clang_splashscreen_impl.c := sign-compare, \ + DISABLED_WARNINGS_clang_splashscreen_impl.c := sign-compare \ + unused-but-set-variable unused-function, \ DISABLED_WARNINGS_clang_splashscreen_png.c := \ incompatible-pointer-types, \ - DISABLED_WARNINGS_clang_splashscreen_sys.m := deprecated-declarations, \ + DISABLED_WARNINGS_clang_splashscreen_sys.m := deprecated-declarations \ + unused-variable unused-but-set-variable, \ DISABLED_WARNINGS_microsoft_dgif_lib.c := 4018 4267, \ DISABLED_WARNINGS_microsoft_splashscreen_impl.c := 4018 4267 4244, \ DISABLED_WARNINGS_microsoft_splashscreen_png.c := 4267, \ @@ -322,7 +326,7 @@ else expansion-to-defined dangling-reference maybe-uninitialized \ calloc-transposed-args HARFBUZZ_DISABLED_WARNINGS_clang := missing-field-initializers \ - range-loop-analysis + range-loop-analysis unused-variable HARFBUZZ_DISABLED_WARNINGS_microsoft := 4267 4244 LIBFONTMANAGER_CFLAGS += $(HARFBUZZ_CFLAGS) diff --git a/make/modules/java.management/Lib.gmk b/make/modules/java.management/Lib.gmk index 052300a58b005..b75278489ad62 100644 --- a/make/modules/java.management/Lib.gmk +++ b/make/modules/java.management/Lib.gmk @@ -38,6 +38,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBMANAGEMENT, \ NAME := management, \ OPTIMIZATION := $(LIBMANAGEMENT_OPTIMIZATION), \ DISABLED_WARNINGS_gcc_VMManagementImpl.c := unused-variable, \ + DISABLED_WARNINGS_clang_VMManagementImpl.c := unused-variable, \ JDK_LIBS := java.base:libjava java.base:libjvm, \ LIBS_aix := -lperfstat,\ LIBS_windows := advapi32.lib psapi.lib, \ diff --git a/make/modules/java.security.jgss/Lib.gmk b/make/modules/java.security.jgss/Lib.gmk index 18c396ff00ea8..2c827b84109f7 100644 --- a/make/modules/java.security.jgss/Lib.gmk +++ b/make/modules/java.security.jgss/Lib.gmk @@ -34,7 +34,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJ2GSS, \ OPTIMIZATION := LOW, \ EXTRA_HEADER_DIRS := java.base:libjava, \ DISABLED_WARNINGS_gcc := undef unused-but-set-variable, \ - DISABLED_WARNINGS_clang := undef, \ + DISABLED_WARNINGS_clang := undef unused-but-set-variable, \ LIBS_unix := $(LIBDL), \ )) diff --git a/make/modules/jdk.crypto.cryptoki/Lib.gmk b/make/modules/jdk.crypto.cryptoki/Lib.gmk index 34a079168a545..ec80aaf46b42b 100644 --- a/make/modules/jdk.crypto.cryptoki/Lib.gmk +++ b/make/modules/jdk.crypto.cryptoki/Lib.gmk @@ -34,6 +34,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJ2PKCS11, \ OPTIMIZATION := LOW, \ EXTRA_HEADER_DIRS := java.base:libjava, \ DISABLED_WARNINGS_gcc_p11_md.c := unused-variable, \ + DISABLED_WARNINGS_clang_p11_md.c := unused-variable, \ DISABLED_WARNINGS_clang_p11_util.c := format-nonliteral, \ LIBS_unix := $(LIBDL), \ )) diff --git a/make/modules/jdk.hotspot.agent/Lib.gmk b/make/modules/jdk.hotspot.agent/Lib.gmk index 13343a7f4682a..f0ede594d0ce8 100644 --- a/make/modules/jdk.hotspot.agent/Lib.gmk +++ b/make/modules/jdk.hotspot.agent/Lib.gmk @@ -64,6 +64,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBSAPROC, \ DISABLED_WARNINGS_gcc_symtab.c := unused-but-set-variable, \ DISABLED_WARNINGS_clang := sign-compare, \ DISABLED_WARNINGS_clang_libproc_impl.c := format-nonliteral, \ + DISABLED_WARNINGS_clang_MacosxDebuggerLocal.m := unused-variable, \ DISABLED_WARNINGS_clang_ps_core.c := pointer-arith, \ DISABLED_WARNINGS_clang_sadis.c := format-nonliteral, \ CFLAGS := $(LIBSAPROC_CFLAGS), \ diff --git a/make/modules/jdk.jdwp.agent/Lib.gmk b/make/modules/jdk.jdwp.agent/Lib.gmk index 6f7e876e77562..53b48cc7c453b 100644 --- a/make/modules/jdk.jdwp.agent/Lib.gmk +++ b/make/modules/jdk.jdwp.agent/Lib.gmk @@ -54,17 +54,23 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJDWP, \ CFLAGS := -DJDWP_LOGGING, \ DISABLED_WARNINGS_gcc_eventFilter.c := unused-variable, \ DISABLED_WARNINGS_gcc_SDE.c := unused-function, \ - DISABLED_WARNINGS_gcc_threadControl.c := unused-but-set-variable unused-variable, \ + DISABLED_WARNINGS_gcc_threadControl.c := unused-but-set-variable \ + unused-variable, \ DISABLED_WARNINGS_gcc_utf_util.c := unused-but-set-variable, \ DISABLED_WARNINGS_clang_error_messages.c := format-nonliteral, \ + DISABLED_WARNINGS_clang_eventFilter.c := unused-variable, \ DISABLED_WARNINGS_clang_EventRequestImpl.c := self-assign, \ DISABLED_WARNINGS_clang_inStream.c := sometimes-uninitialized, \ DISABLED_WARNINGS_clang_log_messages.c := format-nonliteral, \ + DISABLED_WARNINGS_clang_SDE.c := unused-function, \ + DISABLED_WARNINGS_clang_threadControl.c := unused-but-set-variable \ + unused-variable, \ + DISABLED_WARNINGS_clang_utf_util.c := unused-but-set-variable, \ EXTRA_HEADER_DIRS := \ include \ libjdwp/export \ - java.base:libjava \ - java.base:libjvm, \ + java.base:libjava, \ + JDK_LIBS := java.base:libjvm, \ LIBS_linux := $(LIBDL), \ LIBS_macosx := -liconv, \ LIBS_aix := -liconv, \ diff --git a/make/modules/jdk.jpackage/Lib.gmk b/make/modules/jdk.jpackage/Lib.gmk index 68fb65ebf44d0..75548133019a4 100644 --- a/make/modules/jdk.jpackage/Lib.gmk +++ b/make/modules/jdk.jpackage/Lib.gmk @@ -53,8 +53,9 @@ $(eval $(call SetupJdkExecutable, BUILD_JPACKAGEAPPLAUNCHER, \ EXTRA_SRC := common, \ INCLUDE_FILES := $(JPACKAGEAPPLAUNCHER_INCLUDE_FILES), \ OPTIMIZATION := LOW, \ - DISABLED_WARNINGS_clang_LinuxPackage.c := format-nonliteral, \ DISABLED_WARNINGS_clang_JvmLauncherLib.c := format-nonliteral, \ + DISABLED_WARNINGS_clang_LinuxPackage.c := format-nonliteral, \ + DISABLED_WARNINGS_clang_Log.cpp := unused-const-variable, \ CFLAGS_FILTER_OUT := -MD, \ CXXFLAGS_FILTER_OUT := -MD, \ CFLAGS_macosx := -Wno-format-nonliteral, \ diff --git a/make/modules/jdk.management/Lib.gmk b/make/modules/jdk.management/Lib.gmk index 117a5895ac99f..a16925ca19259 100644 --- a/make/modules/jdk.management/Lib.gmk +++ b/make/modules/jdk.management/Lib.gmk @@ -45,6 +45,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBMANAGEMENT_EXT, \ NAME := management_ext, \ OPTIMIZATION := $(LIBMANAGEMENT_EXT_OPTIMIZATION), \ DISABLED_WARNINGS_gcc_DiagnosticCommandImpl.c := unused-variable, \ + DISABLED_WARNINGS_clang_DiagnosticCommandImpl.c := unused-variable, \ DISABLED_WARNINGS_clang_UnixOperatingSystem.c := format-nonliteral, \ CFLAGS := $(LIBMANAGEMENT_EXT_CFLAGS), \ JDK_LIBS := java.base:libjava java.base:libjvm, \ diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 8eb2821cc5744..fced9cfc35e57 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -2334,7 +2334,7 @@ bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { // Vector width in bytes. int Matcher::vector_width_in_bytes(BasicType bt) { // The MaxVectorSize should have been set by detecting SVE max vector register size. - int size = MIN2((UseSVE > 0) ? 256 : 16, (int)MaxVectorSize); + int size = MIN2((UseSVE > 0) ? (int)FloatRegister::sve_vl_max : (int)FloatRegister::neon_vl, (int)MaxVectorSize); // Minimum 2 values in vector if (size < 2*type2aelembytes(bt)) size = 0; // But never < 4 @@ -2373,7 +2373,7 @@ int Matcher::scalable_vector_reg_size(const BasicType bt) { // Vector ideal reg. uint Matcher::vector_ideal_reg(int len) { - if (UseSVE > 0 && 16 < len && len <= 256) { + if (UseSVE > 0 && FloatRegister::neon_vl < len && len <= FloatRegister::sve_vl_max) { return Op_VecA; } switch(len) { diff --git a/src/hotspot/cpu/aarch64/aarch64_vector.ad b/src/hotspot/cpu/aarch64/aarch64_vector.ad index 637d3de73af6f..cdbc4103df89a 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector.ad +++ b/src/hotspot/cpu/aarch64/aarch64_vector.ad @@ -155,7 +155,7 @@ source %{ } int length_in_bytes = vlen * type2aelembytes(bt); - if (UseSVE == 0 && length_in_bytes > 16) { + if (UseSVE == 0 && length_in_bytes > FloatRegister::neon_vl) { return false; } diff --git a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 index b3403ec82a1fe..020a75b51fa8f 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 @@ -145,7 +145,7 @@ source %{ } int length_in_bytes = vlen * type2aelembytes(bt); - if (UseSVE == 0 && length_in_bytes > 16) { + if (UseSVE == 0 && length_in_bytes > FloatRegister::neon_vl) { return false; } diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp index ef1b5fe2703e6..77edbd7bc0a0e 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp @@ -60,8 +60,6 @@ friend class ArrayCopyStub; void casw(Register addr, Register newval, Register cmpval); void casl(Register addr, Register newval, Register cmpval); - void poll_for_safepoint(relocInfo::relocType rtype, CodeEmitInfo* info = nullptr); - static const int max_tableswitches = 20; struct tableswitch switches[max_tableswitches]; int tableswitch_count; diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index f8b703fb4daf6..d09ef26cef995 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -6413,8 +6413,10 @@ void MacroAssembler::cache_wbsync(bool is_pre) { } void MacroAssembler::verify_sve_vector_length(Register tmp) { + if (!UseSVE || VM_Version::get_max_supported_sve_vector_length() == FloatRegister::sve_vl_min) { + return; + } // Make sure that native code does not change SVE vector length. - if (!UseSVE) return; Label verify_ok; movw(tmp, zr); sve_inc(tmp, B); diff --git a/src/hotspot/cpu/aarch64/register_aarch64.hpp b/src/hotspot/cpu/aarch64/register_aarch64.hpp index 8e340fefbb46a..ab635e1be9040 100644 --- a/src/hotspot/cpu/aarch64/register_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/register_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -166,7 +166,13 @@ class FloatRegister { max_slots_per_register = 4, save_slots_per_register = 2, slots_per_neon_register = 4, - extra_save_slots_per_neon_register = slots_per_neon_register - save_slots_per_register + extra_save_slots_per_neon_register = slots_per_neon_register - save_slots_per_register, + neon_vl = 16, + // VLmax: The maximum sve vector length is determined by the hardware + // sve_vl_min <= VLmax <= sve_vl_max. + sve_vl_min = 16, + // Maximum supported vector length across all CPUs + sve_vl_max = 256 }; class FloatRegisterImpl: public AbstractRegisterImpl { diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index c0f10adc85df9..d71162ac568ea 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "pauth_aarch64.hpp" +#include "register_aarch64.hpp" #include "runtime/arguments.hpp" #include "runtime/globals_extension.hpp" #include "runtime/java.hpp" @@ -44,6 +45,7 @@ int VM_Version::_zva_length; int VM_Version::_dcache_line_size; int VM_Version::_icache_line_size; int VM_Version::_initial_sve_vector_length; +int VM_Version::_max_supported_sve_vector_length; bool VM_Version::_rop_protection; uintptr_t VM_Version::_pac_mask; @@ -507,30 +509,37 @@ void VM_Version::initialize() { if (UseSVE > 0) { if (FLAG_IS_DEFAULT(MaxVectorSize)) { MaxVectorSize = _initial_sve_vector_length; - } else if (MaxVectorSize < 16) { - warning("SVE does not support vector length less than 16 bytes. Disabling SVE."); + } else if (MaxVectorSize < FloatRegister::sve_vl_min) { + warning("SVE does not support vector length less than %d bytes. Disabling SVE.", + FloatRegister::sve_vl_min); UseSVE = 0; - } else if ((MaxVectorSize % 16) == 0 && is_power_of_2(MaxVectorSize)) { - int new_vl = set_and_get_current_sve_vector_length(MaxVectorSize); - _initial_sve_vector_length = new_vl; - // Update MaxVectorSize to the largest supported value. - if (new_vl < 0) { - vm_exit_during_initialization( - err_msg("Current system does not support SVE vector length for MaxVectorSize: %d", - (int)MaxVectorSize)); - } else if (new_vl != MaxVectorSize) { - warning("Current system only supports max SVE vector length %d. Set MaxVectorSize to %d", - new_vl, new_vl); - } - MaxVectorSize = new_vl; - } else { + } else if (!((MaxVectorSize % FloatRegister::sve_vl_min) == 0 && is_power_of_2(MaxVectorSize))) { vm_exit_during_initialization(err_msg("Unsupported MaxVectorSize: %d", (int)MaxVectorSize)); } + + if (UseSVE > 0) { + // Acquire the largest supported vector length of this machine + _max_supported_sve_vector_length = set_and_get_current_sve_vector_length(FloatRegister::sve_vl_max); + + if (MaxVectorSize != _max_supported_sve_vector_length) { + int new_vl = set_and_get_current_sve_vector_length(MaxVectorSize); + if (new_vl < 0) { + vm_exit_during_initialization( + err_msg("Current system does not support SVE vector length for MaxVectorSize: %d", + (int)MaxVectorSize)); + } else if (new_vl != MaxVectorSize) { + warning("Current system only supports max SVE vector length %d. Set MaxVectorSize to %d", + new_vl, new_vl); + } + MaxVectorSize = new_vl; + } + _initial_sve_vector_length = MaxVectorSize; + } } if (UseSVE == 0) { // NEON int min_vector_size = 8; - int max_vector_size = 16; + int max_vector_size = FloatRegister::neon_vl; if (!FLAG_IS_DEFAULT(MaxVectorSize)) { if (!is_power_of_2(MaxVectorSize)) { vm_exit_during_initialization(err_msg("Unsupported MaxVectorSize: %d", (int)MaxVectorSize)); @@ -542,11 +551,11 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(MaxVectorSize, max_vector_size); } } else { - FLAG_SET_DEFAULT(MaxVectorSize, 16); + FLAG_SET_DEFAULT(MaxVectorSize, FloatRegister::neon_vl); } } - int inline_size = (UseSVE > 0 && MaxVectorSize >= 16) ? MaxVectorSize : 0; + int inline_size = (UseSVE > 0 && MaxVectorSize >= FloatRegister::sve_vl_min) ? MaxVectorSize : 0; if (FLAG_IS_DEFAULT(ArrayOperationPartialInlineSize)) { FLAG_SET_DEFAULT(ArrayOperationPartialInlineSize, inline_size); } else if (ArrayOperationPartialInlineSize != 0 && ArrayOperationPartialInlineSize != inline_size) { diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index f6cac72804f2c..04cf9c9c2a07c 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -46,6 +46,7 @@ class VM_Version : public Abstract_VM_Version { static int _dcache_line_size; static int _icache_line_size; static int _initial_sve_vector_length; + static int _max_supported_sve_vector_length; static bool _rop_protection; static uintptr_t _pac_mask; @@ -164,7 +165,8 @@ enum Ampere_CPU_Model { static int icache_line_size() { return _icache_line_size; } static int dcache_line_size() { return _dcache_line_size; } - static int get_initial_sve_vector_length() { return _initial_sve_vector_length; }; + static int get_initial_sve_vector_length() { return _initial_sve_vector_length; }; + static int get_max_supported_sve_vector_length() { return _max_supported_sve_vector_length; }; // Aarch64 supports fast class initialization checks static bool supports_fast_class_init_checks() { return true; } diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index 0af384a36fabe..faca90990c893 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -1737,7 +1737,7 @@ void MacroAssembler::cmpxchg_generic(ConditionRegister flag, Register dest_curre cmpxchg_loop_body(flag, dest_current_value, compare_value, exchange_value, addr_base, tmp1, tmp2, retry, failed, cmpxchgx_hint, size); - if (!weak || use_result_reg) { + if (!weak || use_result_reg || failed_ext) { if (UseStaticBranchPredictionInCompareAndSwapPPC64) { bne_predict_not_taken(CCR0, weak ? failed : retry); // StXcx_ sets CCR0. } else { diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp index 4388d0cf4d71d..4ce7eb2bf7392 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp @@ -62,8 +62,6 @@ friend class ArrayCopyStub; void caswu(Register addr, Register newval, Register cmpval); void casl(Register addr, Register newval, Register cmpval); - void poll_for_safepoint(relocInfo::relocType rtype, CodeEmitInfo* info = nullptr); - void deoptimize_trap(CodeEmitInfo *info); enum { diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index c5516336ebc00..a4eaab9b0285e 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -146,18 +146,6 @@ bool MacroAssembler::is_li32_at(address instr) { check_li32_data_dependency(instr); } -bool MacroAssembler::is_li64_at(address instr) { - return is_lui_at(instr) && // lui - is_addi_at(instr + instruction_size) && // addi - is_slli_shift_at(instr + instruction_size * 2, 12) && // Slli Rd, Rs, 12 - is_addi_at(instr + instruction_size * 3) && // addi - is_slli_shift_at(instr + instruction_size * 4, 12) && // Slli Rd, Rs, 12 - is_addi_at(instr + instruction_size * 5) && // addi - is_slli_shift_at(instr + instruction_size * 6, 8) && // Slli Rd, Rs, 8 - is_addi_at(instr + instruction_size * 7) && // addi - check_li64_data_dependency(instr); -} - bool MacroAssembler::is_lwu_to_zr(address instr) { assert_cond(instr != nullptr); return (extract_opcode(instr) == 0b0000011 && @@ -909,37 +897,9 @@ void MacroAssembler::li32(Register Rd, int32_t imm) { upper = (int32_t)upper; // lui Rd, imm[31:12] + imm[11] lui(Rd, upper); - // use addiw to distinguish li32 to li64 addiw(Rd, Rd, lower); } -void MacroAssembler::li64(Register Rd, int64_t imm) { - // Load upper 32 bits. upper = imm[63:32], but if imm[31] == 1 or - // (imm[31:20] == 0x7ff && imm[19] == 1), upper = imm[63:32] + 1. - int64_t lower = imm & 0xffffffff; - lower -= ((lower << 44) >> 44); - int64_t tmp_imm = ((uint64_t)(imm & 0xffffffff00000000)) + (uint64_t)lower; - int32_t upper = (tmp_imm - (int32_t)lower) >> 32; - - // Load upper 32 bits - int64_t up = upper, lo = upper; - lo = (lo << 52) >> 52; - up -= lo; - up = (int32_t)up; - lui(Rd, up); - addi(Rd, Rd, lo); - - // Load the rest 32 bits. - slli(Rd, Rd, 12); - addi(Rd, Rd, (int32_t)lower >> 20); - slli(Rd, Rd, 12); - lower = ((int32_t)imm << 12) >> 20; - addi(Rd, Rd, lower); - slli(Rd, Rd, 8); - lower = imm & 0xff; - addi(Rd, Rd, lower); -} - void MacroAssembler::li(Register Rd, int64_t imm) { // int64_t is in range 0x8000 0000 0000 0000 ~ 0x7fff ffff ffff ffff // li -> c.li @@ -1741,27 +1701,6 @@ static int patch_addr_in_movptr2(address instruction_address, address target) { return MacroAssembler::movptr2_instruction_size; } -static int patch_imm_in_li64(address branch, address target) { - const int LI64_INSTRUCTIONS_NUM = 8; // lui + addi + slli + addi + slli + addi + slli + addi - int64_t lower = (intptr_t)target & 0xffffffff; - lower = lower - ((lower << 44) >> 44); - int64_t tmp_imm = ((uint64_t)((intptr_t)target & 0xffffffff00000000)) + (uint64_t)lower; - int32_t upper = (tmp_imm - (int32_t)lower) >> 32; - int64_t tmp_upper = upper, tmp_lower = upper; - tmp_lower = (tmp_lower << 52) >> 52; - tmp_upper -= tmp_lower; - tmp_upper >>= 12; - // Load upper 32 bits. Upper = target[63:32], but if target[31] = 1 or (target[31:20] == 0x7ff && target[19] == 1), - // upper = target[63:32] + 1. - Assembler::patch(branch + 0, 31, 12, tmp_upper & 0xfffff); // Lui. - Assembler::patch(branch + 4, 31, 20, tmp_lower & 0xfff); // Addi. - // Load the rest 32 bits. - Assembler::patch(branch + 12, 31, 20, ((int32_t)lower >> 20) & 0xfff); // Addi. - Assembler::patch(branch + 20, 31, 20, (((intptr_t)target << 44) >> 52) & 0xfff); // Addi. - Assembler::patch(branch + 28, 31, 20, (intptr_t)target & 0xff); // Addi. - return LI64_INSTRUCTIONS_NUM * MacroAssembler::instruction_size; -} - static int patch_imm_in_li16u(address branch, uint16_t target) { Assembler::patch(branch, 31, 12, target); // patch lui only return MacroAssembler::instruction_size; @@ -1832,16 +1771,6 @@ static address get_target_of_movptr2(address insn_addr) { return ret; } -static address get_target_of_li64(address insn_addr) { - assert_cond(insn_addr != nullptr); - intptr_t target_address = (((int64_t)Assembler::sextract(Assembler::ld_instr(insn_addr), 31, 12)) & 0xfffff) << 44; // Lui. - target_address += ((int64_t)Assembler::sextract(Assembler::ld_instr(insn_addr + 4), 31, 20)) << 32; // Addi. - target_address += ((int64_t)Assembler::sextract(Assembler::ld_instr(insn_addr + 12), 31, 20)) << 20; // Addi. - target_address += ((int64_t)Assembler::sextract(Assembler::ld_instr(insn_addr + 20), 31, 20)) << 8; // Addi. - target_address += ((int64_t)Assembler::sextract(Assembler::ld_instr(insn_addr + 28), 31, 20)); // Addi. - return (address)target_address; -} - address MacroAssembler::get_target_of_li32(address insn_addr) { assert_cond(insn_addr != nullptr); intptr_t target_address = (((int64_t)Assembler::sextract(Assembler::ld_instr(insn_addr), 31, 12)) & 0xfffff) << 12; // Lui. @@ -1864,8 +1793,6 @@ int MacroAssembler::pd_patch_instruction_size(address instruction_address, addre return patch_addr_in_movptr1(instruction_address, target); } else if (MacroAssembler::is_movptr2_at(instruction_address)) { // movptr2 return patch_addr_in_movptr2(instruction_address, target); - } else if (MacroAssembler::is_li64_at(instruction_address)) { // li64 - return patch_imm_in_li64(instruction_address, target); } else if (MacroAssembler::is_li32_at(instruction_address)) { // li32 int64_t imm = (intptr_t)target; return patch_imm_in_li32(instruction_address, (int32_t)imm); @@ -1896,8 +1823,6 @@ address MacroAssembler::target_addr_for_insn(address insn_addr) { return get_target_of_movptr1(insn_addr); } else if (MacroAssembler::is_movptr2_at(insn_addr)) { // movptr2 return get_target_of_movptr2(insn_addr); - } else if (MacroAssembler::is_li64_at(insn_addr)) { // li64 - return get_target_of_li64(insn_addr); } else if (MacroAssembler::is_li32_at(insn_addr)) { // li32 return get_target_of_li32(insn_addr); } else { @@ -3605,14 +3530,18 @@ void MacroAssembler::atomic_cas( void MacroAssembler::far_jump(const Address &entry, Register tmp) { assert(CodeCache::find_blob(entry.target()) != nullptr, - "destination of far call not found in code cache"); + "destination of far jump not found in code cache"); assert(entry.rspec().type() == relocInfo::external_word_type || entry.rspec().type() == relocInfo::runtime_call_type || entry.rspec().type() == relocInfo::none, "wrong entry relocInfo type"); // Fixed length: see MacroAssembler::far_branch_size() + // We can use auipc + jr here because we know that the total size of + // the code cache cannot exceed 2Gb. relocate(entry.rspec(), [&] { - int32_t offset; - la(tmp, entry.target(), offset); + int64_t distance = entry.target() - pc(); + int32_t offset = ((int32_t)distance << 20) >> 20; + assert(is_valid_32bit_offset(distance), "Far jump using wrong instructions."); + auipc(tmp, (int32_t)distance + 0x800); jr(tmp, offset); }); } @@ -3627,8 +3556,11 @@ void MacroAssembler::far_call(const Address &entry, Register tmp) { // We can use auipc + jalr here because we know that the total size of // the code cache cannot exceed 2Gb. relocate(entry.rspec(), [&] { - assert(is_valid_32bit_offset(entry.target() - pc()), "Far call using wrong instructions."); - call(entry.target(), tmp); + int64_t distance = entry.target() - pc(); + int32_t offset = ((int32_t)distance << 20) >> 20; + assert(is_valid_32bit_offset(distance), "Far call using wrong instructions."); + auipc(tmp, (int32_t)distance + 0x800); + jalr(tmp, offset); }); } diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index b0404929f46d8..c3161beea117d 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -813,7 +813,6 @@ class MacroAssembler: public Assembler { void li16u(Register Rd, uint16_t imm); void li32(Register Rd, int32_t imm); - void li64(Register Rd, int64_t imm); void li (Register Rd, int64_t imm); // optimized load immediate // mv @@ -1706,40 +1705,6 @@ class MacroAssembler: public Assembler { extract_rs1(last_instr) == extract_rd(add); } - // the instruction sequence of li64 is as below: - // lui - // addi - // slli - // addi - // slli - // addi - // slli - // addi - static bool check_li64_data_dependency(address instr) { - address lui = instr; - address addi1 = lui + instruction_size; - address slli1 = addi1 + instruction_size; - address addi2 = slli1 + instruction_size; - address slli2 = addi2 + instruction_size; - address addi3 = slli2 + instruction_size; - address slli3 = addi3 + instruction_size; - address addi4 = slli3 + instruction_size; - return extract_rs1(addi1) == extract_rd(lui) && - extract_rs1(addi1) == extract_rd(addi1) && - extract_rs1(slli1) == extract_rd(addi1) && - extract_rs1(slli1) == extract_rd(slli1) && - extract_rs1(addi2) == extract_rd(slli1) && - extract_rs1(addi2) == extract_rd(addi2) && - extract_rs1(slli2) == extract_rd(addi2) && - extract_rs1(slli2) == extract_rd(slli2) && - extract_rs1(addi3) == extract_rd(slli2) && - extract_rs1(addi3) == extract_rd(addi3) && - extract_rs1(slli3) == extract_rd(addi3) && - extract_rs1(slli3) == extract_rd(slli3) && - extract_rs1(addi4) == extract_rd(slli3) && - extract_rs1(addi4) == extract_rd(addi4); - } - // the instruction sequence of li16u is as below: // lui // srli @@ -1784,7 +1749,6 @@ class MacroAssembler: public Assembler { } static bool is_li32_at(address instr); - static bool is_li64_at(address instr); static bool is_pc_relative_at(address branch); static bool is_membar(address addr) { diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index c9c6c4d3edf97..9ad7c35e6bdef 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -473,9 +473,9 @@ void os::init_system_properties_values() { if (pslash != nullptr) { *pslash = '\0'; // Get rid of /{client|server|hotspot}. } -#ifdef STATIC_BUILD - strcat(buf, "/lib"); -#endif + if (is_vm_statically_linked()) { + strcat(buf, "/lib"); + } Arguments::set_dll_dir(buf); @@ -1093,19 +1093,20 @@ void *os::Bsd::dlopen_helper(const char *filename, int mode, char *ebuf, int ebu #ifdef __APPLE__ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { -#ifdef STATIC_BUILD - return os::get_default_process_handle(); -#else + if (is_vm_statically_linked()) { + return os::get_default_process_handle(); + } + log_info(os)("attempting shared library load of %s", filename); return os::Bsd::dlopen_helper(filename, RTLD_LAZY, ebuf, ebuflen); -#endif // STATIC_BUILD } #else void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { -#ifdef STATIC_BUILD - return os::get_default_process_handle(); -#else + if (is_vm_statically_linked()) { + return os::get_default_process_handle(); + } + log_info(os)("attempting shared library load of %s", filename); void* result; @@ -1269,7 +1270,6 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { } return nullptr; -#endif // STATIC_BUILD } #endif // !__APPLE__ diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index dc6c7ea097c65..35c43157b1ab3 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -268,7 +268,6 @@ void FileMapHeader::print(outputStream* st) { st->print_cr("- core_region_alignment: " SIZE_FORMAT, _core_region_alignment); st->print_cr("- obj_alignment: %d", _obj_alignment); st->print_cr("- narrow_oop_base: " INTPTR_FORMAT, p2i(_narrow_oop_base)); - st->print_cr("- narrow_oop_base: " INTPTR_FORMAT, p2i(_narrow_oop_base)); st->print_cr("- narrow_oop_shift %d", _narrow_oop_shift); st->print_cr("- compact_strings: %d", _compact_strings); st->print_cr("- max_heap_size: " UINTX_FORMAT, _max_heap_size); diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index a491dd62f070e..11e070862fe2f 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -205,7 +205,7 @@ void CodeCache::initialize_heaps() { const bool cache_size_set = FLAG_IS_CMDLINE(ReservedCodeCacheSize); const size_t ps = page_size(false, 8); const size_t min_size = MAX2(os::vm_allocation_granularity(), ps); - const size_t min_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3); // Make sure we have enough space for VM internal code + const size_t min_cache_size = CompilerConfig::min_code_cache_size(); // Make sure we have enough space for VM internal code size_t cache_size = align_up(ReservedCodeCacheSize, min_size); // Prerequisites diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp index 0e6d8f6a6c91b..8fc70619abe7e 100644 --- a/src/hotspot/share/compiler/compilationPolicy.cpp +++ b/src/hotspot/share/compiler/compilationPolicy.cpp @@ -455,7 +455,7 @@ void CompilationPolicy::initialize() { c2_size = C2Compiler::initial_code_buffer_size(); #endif size_t buffer_size = c1_only ? c1_size : (c1_size/3 + 2*c2_size/3); - int max_count = (ReservedCodeCacheSize - (CodeCacheMinimumUseSpace DEBUG_ONLY(* 3))) / (int)buffer_size; + int max_count = (ReservedCodeCacheSize - (int)CompilerConfig::min_code_cache_size()) / (int)buffer_size; if (count > max_count) { // Lower the compiler count such that all buffers fit into the code cache count = MAX2(max_count, c1_only ? 1 : 2); diff --git a/src/hotspot/share/compiler/compilerDefinitions.cpp b/src/hotspot/share/compiler/compilerDefinitions.cpp index 0a04afad9aaee..ee0c73254f180 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.cpp +++ b/src/hotspot/share/compiler/compilerDefinitions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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 @@ -475,8 +475,7 @@ void CompilerConfig::set_jvmci_specific_flags() { bool CompilerConfig::check_args_consistency(bool status) { // Check lower bounds of the code cache - // Template Interpreter code is approximately 3X larger in debug builds. - uint min_code_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3); + size_t min_code_cache_size = CompilerConfig::min_code_cache_size(); if (ReservedCodeCacheSize < InitialCodeCacheSize) { jio_fprintf(defaultStream::error_stream(), "Invalid ReservedCodeCacheSize: %dK. Must be at least InitialCodeCacheSize=%dK.\n", diff --git a/src/hotspot/share/compiler/compilerDefinitions.hpp b/src/hotspot/share/compiler/compilerDefinitions.hpp index 03b7d446b1ab3..a72e82e32bd56 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.hpp +++ b/src/hotspot/share/compiler/compilerDefinitions.hpp @@ -148,6 +148,8 @@ class CompilerConfig : public AllStatic { inline static bool is_c2_or_jvmci_compiler_only(); inline static bool is_c2_or_jvmci_compiler_enabled(); + inline static size_t min_code_cache_size(); + private: static bool is_compilation_mode_selected(); static void set_compilation_policy_flags(); diff --git a/src/hotspot/share/compiler/compilerDefinitions.inline.hpp b/src/hotspot/share/compiler/compilerDefinitions.inline.hpp index d490387672dad..5557892669ddd 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.inline.hpp +++ b/src/hotspot/share/compiler/compilerDefinitions.inline.hpp @@ -25,6 +25,12 @@ #ifndef SHARE_COMPILER_COMPILERDEFINITIONS_INLINE_HPP #define SHARE_COMPILER_COMPILERDEFINITIONS_INLINE_HPP +#ifdef COMPILER1 +#include "c1/c1_Compiler.hpp" +#endif +#ifdef COMPILER2 +#include "opto/c2compiler.hpp" +#endif #include "compiler/compilerDefinitions.hpp" #include "compiler/compiler_globals.hpp" @@ -132,4 +138,13 @@ inline bool CompilerConfig::is_c2_or_jvmci_compiler_enabled() { return is_c2_enabled() || is_jvmci_compiler_enabled(); } +inline size_t CompilerConfig::min_code_cache_size() { + size_t min_code_cache_size = CodeCacheMinimumUseSpace; + // Template Interpreter code is approximately 3X larger in debug builds. + DEBUG_ONLY(min_code_cache_size *= 3); + COMPILER1_PRESENT(min_code_cache_size += Compiler::code_buffer_size()); + COMPILER2_PRESENT(min_code_cache_size += C2Compiler::initial_code_buffer_size()); + return min_code_cache_size; +} + #endif // SHARE_COMPILER_COMPILERDEFINITIONS_INLINE_HPP diff --git a/src/hotspot/share/compiler/disassembler.cpp b/src/hotspot/share/compiler/disassembler.cpp index 091f1a2410e31..6556ce4ae1df2 100644 --- a/src/hotspot/share/compiler/disassembler.cpp +++ b/src/hotspot/share/compiler/disassembler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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,6 +37,7 @@ #include "memory/universe.hpp" #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/java.hpp" #include "runtime/os.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" @@ -785,13 +786,13 @@ bool Disassembler::load_library(outputStream* st) { os::jvm_path(buf, sizeof(buf)); int jvm_offset = -1; int lib_offset = -1; -#ifdef STATIC_BUILD - char* p = strrchr(buf, '/'); - *p = '\0'; - strcat(p, "/lib/"); - lib_offset = jvm_offset = (int)strlen(buf); -#else - { + + if (is_vm_statically_linked()) { + char* p = strrchr(buf, '/'); + *p = '\0'; + strcat(p, "/lib/"); + lib_offset = jvm_offset = (int)strlen(buf); + } else { // Match "libjvm" instead of "jvm" on *nix platforms. Creates better matches. // Match "[lib]jvm[^/]*" in jvm_path. const char* base = buf; @@ -805,7 +806,6 @@ bool Disassembler::load_library(outputStream* st) { if (p != nullptr) jvm_offset = p - base + 3; // this points to 'j' in libjvm. #endif } -#endif // Find the disassembler shared library. // Search for several paths derived from libjvm, in this order: diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.cpp b/src/hotspot/share/gc/parallel/psPromotionManager.cpp index 19f688852385b..5f6629e6cc2c4 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.cpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -31,6 +31,8 @@ #include "gc/parallel/psScavenge.inline.hpp" #include "gc/shared/continuationGCSupport.inline.hpp" #include "gc/shared/gcTrace.hpp" +#include "gc/shared/partialArrayState.hpp" +#include "gc/shared/partialArrayTaskStepper.inline.hpp" #include "gc/shared/preservedMarks.inline.hpp" #include "gc/shared/taskqueue.inline.hpp" #include "logging/log.hpp" @@ -42,12 +44,14 @@ #include "memory/resourceArea.hpp" #include "oops/access.inline.hpp" #include "oops/compressedOops.inline.hpp" +#include "utilities/checkedCast.hpp" PaddedEnd* PSPromotionManager::_manager_array = nullptr; PSPromotionManager::PSScannerTasksQueueSet* PSPromotionManager::_stack_array_depth = nullptr; PreservedMarksSet* PSPromotionManager::_preserved_marks_set = nullptr; PSOldGen* PSPromotionManager::_old_gen = nullptr; MutableSpace* PSPromotionManager::_young_space = nullptr; +PartialArrayStateAllocator* PSPromotionManager::_partial_array_state_allocator = nullptr; void PSPromotionManager::initialize() { ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); @@ -62,11 +66,16 @@ void PSPromotionManager::initialize() { assert(_manager_array == nullptr, "Attempt to initialize twice"); _manager_array = PaddedArray::create_unfreeable(promotion_manager_num); + assert(_partial_array_state_allocator == nullptr, "Attempt to initialize twice"); + _partial_array_state_allocator + = new PartialArrayStateAllocator(ParallelGCThreads); + _stack_array_depth = new PSScannerTasksQueueSet(ParallelGCThreads); // Create and register the PSPromotionManager(s) for the worker threads. for(uint i=0; iregister_queue(i, _manager_array[i].claimed_stack_depth()); + _manager_array[i]._partial_array_state_allocator_index = i; } // The VMThread gets its own PSPromotionManager, which is not available // for work stealing. @@ -124,6 +133,10 @@ bool PSPromotionManager::post_scavenge(YoungGCTracer& gc_tracer) { manager->flush_labs(); manager->flush_string_dedup_requests(); } + // All PartialArrayStates have been returned to the allocator, since the + // claimed_stack_depths are all empty. Leave them there for use by future + // collections. + if (!promotion_failure_occurred) { // If there was no promotion failure, the preserved mark stacks // should be empty. @@ -172,7 +185,10 @@ void PSPromotionManager::reset_stats() { } #endif // TASKQUEUE_STATS -PSPromotionManager::PSPromotionManager() { +// Most members are initialized either by initialize() or reset(). +PSPromotionManager::PSPromotionManager() + : _partial_array_stepper(ParallelGCThreads, ParGCArrayScanChunk) +{ // We set the old lab's start array. _old_lab.set_start_array(old_gen()->start_array()); @@ -182,9 +198,11 @@ PSPromotionManager::PSPromotionManager() { _target_stack_size = GCDrainStackTargetSize; } - _array_chunk_size = ParGCArrayScanChunk; + // Initialize to a bad value; fixed by initialize(). + _partial_array_state_allocator_index = UINT_MAX; + // let's choose 1.5x the chunk size - _min_array_size_for_chunking = 3 * _array_chunk_size / 2; + _min_array_size_for_chunking = (3 * ParGCArrayScanChunk / 2); _preserved_marks = nullptr; @@ -277,37 +295,57 @@ template void PSPromotionManager::process_array_chunk_work( } } -void PSPromotionManager::process_array_chunk(PartialArrayScanTask task) { - assert(PSChunkLargeArrays, "invariant"); - - oop old = task.to_source_array(); - assert(old->is_objArray(), "invariant"); - assert(old->is_forwarded(), "invariant"); - +void PSPromotionManager::process_array_chunk(PartialArrayState* state) { TASKQUEUE_STATS_ONLY(++_array_chunks_processed); - oop const obj = old->forwardee(); - - int start; - int const end = arrayOop(old)->length(); - if (end > (int) _min_array_size_for_chunking) { - // we'll chunk more - start = end - _array_chunk_size; - assert(start > 0, "invariant"); - arrayOop(old)->set_length(start); - push_depth(ScannerTask(PartialArrayScanTask(old))); - TASKQUEUE_STATS_ONLY(++_array_chunk_pushes); + // Claim a chunk. Push additional tasks before processing the claimed + // chunk to allow other workers to steal while we're processing. + PartialArrayTaskStepper::Step step = _partial_array_stepper.next(state); + if (step._ncreate > 0) { + state->add_references(step._ncreate); + for (uint i = 0; i < step._ncreate; ++i) { + push_depth(ScannerTask(state)); + } + TASKQUEUE_STATS_ONLY(_array_chunk_pushes += step._ncreate); + } + int start = checked_cast(step._index); + int end = checked_cast(step._index + _partial_array_stepper.chunk_size()); + assert(start < end, "invariant"); + if (UseCompressedOops) { + process_array_chunk_work(state->destination(), start, end); } else { - // this is the final chunk for this array - start = 0; - int const actual_length = arrayOop(obj)->length(); - arrayOop(old)->set_length(actual_length); + process_array_chunk_work(state->destination(), start, end); } + // Release reference to state, now that we're done with it. + _partial_array_state_allocator->release(_partial_array_state_allocator_index, state); +} +void PSPromotionManager::push_objArray(oop old_obj, oop new_obj) { + assert(old_obj->is_objArray(), "precondition"); + assert(old_obj->is_forwarded(), "precondition"); + assert(old_obj->forwardee() == new_obj, "precondition"); + assert(new_obj->is_objArray(), "precondition"); + + size_t array_length = objArrayOop(new_obj)->length(); + PartialArrayTaskStepper::Step step = _partial_array_stepper.start(array_length); + + if (step._ncreate > 0) { + TASKQUEUE_STATS_ONLY(++_arrays_chunked); + PartialArrayState* state = + _partial_array_state_allocator->allocate(_partial_array_state_allocator_index, + old_obj, new_obj, + step._index, + array_length, + step._ncreate); + for (uint i = 0; i < step._ncreate; ++i) { + push_depth(ScannerTask(state)); + } + TASKQUEUE_STATS_ONLY(_array_chunk_pushes += step._ncreate); + } if (UseCompressedOops) { - process_array_chunk_work(obj, start, end); + process_array_chunk_work(new_obj, 0, checked_cast(step._index)); } else { - process_array_chunk_work(obj, start, end); + process_array_chunk_work(new_obj, 0, checked_cast(step._index)); } } diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.hpp index b7d2e0f725331..8d4122346147c 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 "gc/parallel/psPromotionLAB.hpp" #include "gc/shared/copyFailedInfo.hpp" #include "gc/shared/gcTrace.hpp" +#include "gc/shared/partialArrayTaskStepper.hpp" #include "gc/shared/preservedMarks.hpp" #include "gc/shared/stringdedup/stringDedup.hpp" #include "gc/shared/taskqueue.hpp" @@ -49,6 +50,8 @@ class MutableSpace; class PSOldGen; class ParCompactionManager; +class PartialArrayState; +class PartialArrayStateAllocator; class PSPromotionManager { friend class PSScavenge; @@ -85,7 +88,9 @@ class PSPromotionManager { uint _target_stack_size; - uint _array_chunk_size; + static PartialArrayStateAllocator* _partial_array_state_allocator; + PartialArrayTaskStepper _partial_array_stepper; + uint _partial_array_state_allocator_index; uint _min_array_size_for_chunking; PreservedMarks* _preserved_marks; @@ -101,7 +106,8 @@ class PSPromotionManager { template void process_array_chunk_work(oop obj, int start, int end); - void process_array_chunk(PartialArrayScanTask task); + void process_array_chunk(PartialArrayState* state); + void push_objArray(oop old_obj, oop new_obj); void push_depth(ScannerTask task); diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp index 390dea4976d19..f38cbaecf439c 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -276,9 +276,7 @@ inline oop PSPromotionManager::copy_unmarked_to_survivor_space(oop o, if (new_obj_size > _min_array_size_for_chunking && new_obj->is_objArray() && PSChunkLargeArrays) { - // we'll chunk it - push_depth(ScannerTask(PartialArrayScanTask(o))); - TASKQUEUE_STATS_ONLY(++_arrays_chunked; ++_array_chunk_pushes); + push_objArray(o, new_obj); } else { // we'll just push its contents push_contents(new_obj); @@ -322,9 +320,9 @@ inline void PSPromotionManager::copy_and_push_safe_barrier(T* p) { } inline void PSPromotionManager::process_popped_location_depth(ScannerTask task) { - if (task.is_partial_array_task()) { + if (task.is_partial_array_state()) { assert(PSChunkLargeArrays, "invariant"); - process_array_chunk(task.to_partial_array_task()); + process_array_chunk(task.to_partial_array_state()); } else { if (task.is_narrow_oop_ptr()) { assert(UseCompressedOops, "Error"); @@ -341,7 +339,7 @@ inline bool PSPromotionManager::steal_depth(int queue_num, ScannerTask& t) { #if TASKQUEUE_STATS void PSPromotionManager::record_steal(ScannerTask task) { - if (task.is_partial_array_task()) { + if (task.is_partial_array_state()) { ++_array_chunk_steals; } } diff --git a/src/hotspot/share/gc/shared/partialArrayState.hpp b/src/hotspot/share/gc/shared/partialArrayState.hpp index f3bfc3ed8b859..fb226e08665a0 100644 --- a/src/hotspot/share/gc/shared/partialArrayState.hpp +++ b/src/hotspot/share/gc/shared/partialArrayState.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_GC_SHARED_PARTIALARRAYSTATE_HPP #define SHARE_GC_SHARED_PARTIALARRAYSTATE_HPP +#include "memory/allocation.hpp" #include "oops/oopsHierarchy.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" @@ -109,7 +110,7 @@ class PartialArrayState { // the worker_id used in the operation. This avoids locking and such on those // data structures, at the cost of possibly doing more total arena allocation // that would be needed with a single shared arena and free-list. -class PartialArrayStateAllocator { +class PartialArrayStateAllocator : public CHeapObj { class Impl; Impl* _impl; diff --git a/src/hotspot/share/gc/shared/taskqueue.hpp b/src/hotspot/share/gc/shared/taskqueue.hpp index 2ea75e1457c48..f4a3731583bc9 100644 --- a/src/hotspot/share/gc/shared/taskqueue.hpp +++ b/src/hotspot/share/gc/shared/taskqueue.hpp @@ -573,20 +573,6 @@ class ObjArrayTask int _index; }; -// Wrapper over an oop that is a partially scanned array. -// Can be converted to a ScannerTask for placement in associated task queues. -// Refers to the partially copied source array oop. -// Temporarily retained to support ParallelGC until it adopts PartialArrayState. -class PartialArrayScanTask { - oop _src; - -public: - explicit PartialArrayScanTask(oop src_array) : _src(src_array) {} - // Trivially copyable. - - oop to_source_array() const { return _src; } -}; - class PartialArrayState; // Discriminated union over oop*, narrowOop*, and PartialArrayState. @@ -627,10 +613,6 @@ class ScannerTask { explicit ScannerTask(narrowOop* p) : _p(encode(p, NarrowOopTag)) {} - // Temporarily retained to support ParallelGC until it adopts PartialArrayState. - explicit ScannerTask(PartialArrayScanTask t) : - _p(encode(t.to_source_array(), PartialArrayTag)) {} - explicit ScannerTask(PartialArrayState* state) : _p(encode(state, PartialArrayTag)) {} @@ -646,11 +628,6 @@ class ScannerTask { return (raw_value() & NarrowOopTag) != 0; } - // Temporarily retained to support ParallelGC until it adopts PartialArrayState. - bool is_partial_array_task() const { - return (raw_value() & PartialArrayTag) != 0; - } - bool is_partial_array_state() const { return (raw_value() & PartialArrayTag) != 0; } @@ -663,11 +640,6 @@ class ScannerTask { return static_cast(decode(NarrowOopTag)); } - // Temporarily retained to support ParallelGC until it adopts PartialArrayState. - PartialArrayScanTask to_partial_array_task() const { - return PartialArrayScanTask(cast_to_oop(decode(PartialArrayTag))); - } - PartialArrayState* to_partial_array_state() const { return static_cast(decode(PartialArrayTag)); } diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index 6082af55487e2..edad228b4e3ae 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -180,6 +180,9 @@ JVM_IsContinuationsSupported(void); JNIEXPORT jboolean JNICALL JVM_IsForeignLinkerSupported(void); +JNIEXPORT jboolean JNICALL +JVM_IsStaticallyLinked(void); + JNIEXPORT void JNICALL JVM_InitializeFromArchive(JNIEnv* env, jclass cls); diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 99742a598e858..6e53705464366 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -1309,19 +1309,6 @@ Node *PhaseIdealLoop::clone_up_backedge_goo(Node *back_ctrl, Node *preheader_ctr return n; } -Node* PhaseIdealLoop::cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop) { - Node* castii = new CastIINode(ctrl, incr, TypeInt::INT, ConstraintCastNode::UnconditionalDependency); - register_new_node(castii, ctrl); - for (DUIterator_Fast imax, i = incr->fast_outs(imax); i < imax; i++) { - Node* n = incr->fast_out(i); - if (n->is_Phi() && n->in(0) == loop) { - int nrep = n->replace_edge(incr, castii, &_igvn); - return castii; - } - } - return nullptr; -} - #ifdef ASSERT void PhaseIdealLoop::ensure_zero_trip_guard_proj(Node* node, bool is_main_loop) { assert(node->is_IfProj(), "must be the zero trip guard If node"); @@ -1680,14 +1667,11 @@ void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_n // variable value and the induction variable Phi to preserve correct // dependencies. - // CastII for the main loop: - Node* castii = cast_incr_before_loop(pre_incr, min_taken, main_head); - assert(castii != nullptr, "no castII inserted"); assert(post_head->in(1)->is_IfProj(), "must be zero-trip guard If node projection of the post loop"); - copy_assertion_predicates_to_main_loop(pre_head, castii, stride, outer_loop, outer_main_head, dd_main_head, + copy_assertion_predicates_to_main_loop(pre_head, pre_incr, stride, outer_loop, outer_main_head, dd_main_head, idx_before_pre_post, idx_after_post_before_pre, min_taken, post_head->in(1), old_new); - copy_assertion_predicates_to_post_loop(outer_main_head, post_head, post_incr, stride); + copy_assertion_predicates_to_post_loop(outer_main_head, post_head, stride); // Step B4: Shorten the pre-loop to run only 1 iteration (for now). // RCE and alignment may change this later. @@ -1812,7 +1796,7 @@ void PhaseIdealLoop::insert_vector_post_loop(IdealLoopTree *loop, Node_List &old // In this case we throw away the result as we are not using it to connect anything else. CountedLoopNode *post_head = nullptr; insert_post_loop(loop, old_new, main_head, main_end, incr, limit, post_head); - copy_assertion_predicates_to_post_loop(main_head->skip_strip_mined(), post_head, incr, main_head->stride()); + copy_assertion_predicates_to_post_loop(main_head->skip_strip_mined(), post_head, main_head->stride()); // It's difficult to be precise about the trip-counts // for post loops. They are usually very short, @@ -1915,10 +1899,6 @@ Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree* loop, Node_List& old_new, } } - // CastII for the new post loop: - incr = cast_incr_before_loop(zer_opaq->in(1), zer_taken, post_head); - assert(incr != nullptr, "no castII inserted"); - return new_main_exit; } @@ -1934,12 +1914,6 @@ bool IdealLoopTree::is_invariant(Node* n) const { // to the new stride. void PhaseIdealLoop::update_main_loop_assertion_predicates(Node* ctrl, CountedLoopNode* loop_head, Node* init, const int stride_con) { - if (init->is_CastII()) { - // skip over the cast added by PhaseIdealLoop::cast_incr_before_loop() when pre/post/main loops are created because - // it can get in the way of type propagation - assert(init->as_CastII()->carry_dependency() && loop_head->skip_assertion_predicates_with_halt() == init->in(0), "casted iv phi from pre loop expected"); - init = init->in(1); - } Node* entry = ctrl; Node* prev_proj = ctrl; LoopNode* outer_loop_head = loop_head->skip_strip_mined(); @@ -1988,7 +1962,9 @@ void PhaseIdealLoop::update_main_loop_assertion_predicates(Node* ctrl, CountedLo // Go over the Assertion Predicates of the main loop and make a copy for the post loop with its initial iv value and // stride as inputs. void PhaseIdealLoop::copy_assertion_predicates_to_post_loop(LoopNode* main_loop_head, CountedLoopNode* post_loop_head, - Node* init, Node* stride) { + Node* stride) { + Node* opaq = post_loop_head->is_canonical_loop_entry(); + Node* init = opaq->in(1); Node* post_loop_entry = post_loop_head->in(LoopNode::EntryControl); Node* main_loop_entry = main_loop_head->in(LoopNode::EntryControl); IdealLoopTree* post_loop = get_loop(post_loop_head); diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 1217caa41eba4..369f446adbbd7 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -938,8 +938,6 @@ class PhaseIdealLoop : public PhaseTransform { return ctrl; } - Node* cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop); - #ifdef ASSERT void ensure_zero_trip_guard_proj(Node* node, bool is_main_loop); #endif @@ -960,7 +958,7 @@ class PhaseIdealLoop : public PhaseTransform { static bool assertion_predicate_has_loop_opaque_node(IfNode* iff); static void get_assertion_predicates(Node* predicate, Unique_Node_List& list, bool get_opaque = false); void update_main_loop_assertion_predicates(Node* ctrl, CountedLoopNode* loop_head, Node* init, int stride_con); - void copy_assertion_predicates_to_post_loop(LoopNode* main_loop_head, CountedLoopNode* post_loop_head, Node* init, + void copy_assertion_predicates_to_post_loop(LoopNode* main_loop_head, CountedLoopNode* post_loop_head, Node* stride); void initialize_assertion_predicates_for_peeled_loop(const PredicateBlock* predicate_block, LoopNode* outer_loop_head, int dd_outer_loop_head, Node* init, Node* stride, @@ -1534,6 +1532,8 @@ class PhaseIdealLoop : public PhaseTransform { // Attempt to use a conditional move instead of a phi/branch Node *conditional_move( Node *n ); + bool split_thru_phi_could_prevent_vectorization(Node* n, Node* n_blk); + // Check for aggressive application of 'split-if' optimization, // using basic block level info. void split_if_with_blocks ( VectorSet &visited, Node_Stack &nstack); diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index b838b15032f70..7f42d2d4beb42 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -1089,6 +1089,25 @@ void PhaseIdealLoop::try_move_store_after_loop(Node* n) { } } +// Split some nodes that take a counted loop phi as input at a counted +// loop can cause vectorization of some expressions to fail +bool PhaseIdealLoop::split_thru_phi_could_prevent_vectorization(Node* n, Node* n_blk) { + if (!n_blk->is_CountedLoop()) { + return false; + } + + int opcode = n->Opcode(); + + if (opcode != Op_AndI && + opcode != Op_MulI && + opcode != Op_RotateRight && + opcode != Op_RShiftI) { + return false; + } + + return n->in(1) == n_blk->as_BaseCountedLoop()->phi(); +} + //------------------------------split_if_with_blocks_pre----------------------- // Do the real work in a non-recursive function. Data nodes want to be // cloned in the pre-order so they can feed each other nicely. @@ -1175,6 +1194,10 @@ Node *PhaseIdealLoop::split_if_with_blocks_pre( Node *n ) { return n; } + if (split_thru_phi_could_prevent_vectorization(n, n_blk)) { + return n; + } + // Check for having no control input; not pinned. Allow // dominating control. if (n->in(0)) { diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index a26a82debe750..6425f5f583f36 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -3448,6 +3448,10 @@ JVM_LEAF(jboolean, JVM_IsForeignLinkerSupported(void)) return ForeignGlobals::is_foreign_linker_supported() ? JNI_TRUE : JNI_FALSE; JVM_END +JVM_ENTRY_NO_ENV(jboolean, JVM_IsStaticallyLinked(void)) + return is_vm_statically_linked() ? JNI_TRUE : JNI_FALSE; +JVM_END + // String support /////////////////////////////////////////////////////////////////////////// JVM_ENTRY(jstring, JVM_InternString(JNIEnv *env, jstring str)) diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index 63cc33222ec37..a36d12059a96a 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -2534,6 +2534,7 @@ JvmtiEnv::ClearBreakpoint(Method* method, jlocation location) { jvmtiError JvmtiEnv::SetFieldAccessWatch(fieldDescriptor* fdesc_ptr) { + JvmtiVTMSTransitionDisabler disabler; // make sure we haven't set this watch before if (fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_DUPLICATE; fdesc_ptr->set_is_field_access_watched(true); @@ -2546,6 +2547,7 @@ JvmtiEnv::SetFieldAccessWatch(fieldDescriptor* fdesc_ptr) { jvmtiError JvmtiEnv::ClearFieldAccessWatch(fieldDescriptor* fdesc_ptr) { + JvmtiVTMSTransitionDisabler disabler; // make sure we have a watch to clear if (!fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_NOT_FOUND; fdesc_ptr->set_is_field_access_watched(false); @@ -2558,6 +2560,7 @@ JvmtiEnv::ClearFieldAccessWatch(fieldDescriptor* fdesc_ptr) { jvmtiError JvmtiEnv::SetFieldModificationWatch(fieldDescriptor* fdesc_ptr) { + JvmtiVTMSTransitionDisabler disabler; // make sure we haven't set this watch before if (fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_DUPLICATE; fdesc_ptr->set_is_field_modification_watched(true); @@ -2570,6 +2573,7 @@ JvmtiEnv::SetFieldModificationWatch(fieldDescriptor* fdesc_ptr) { jvmtiError JvmtiEnv::ClearFieldModificationWatch(fieldDescriptor* fdesc_ptr) { + JvmtiVTMSTransitionDisabler disabler; // make sure we have a watch to clear if (!fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_NOT_FOUND; fdesc_ptr->set_is_field_modification_watched(false); diff --git a/src/hotspot/share/prims/jvmtiEventController.cpp b/src/hotspot/share/prims/jvmtiEventController.cpp index c9867ff164350..df14047e70030 100644 --- a/src/hotspot/share/prims/jvmtiEventController.cpp +++ b/src/hotspot/share/prims/jvmtiEventController.cpp @@ -982,8 +982,6 @@ JvmtiEventControllerPrivate::change_field_watch(jvmtiEvent event_type, bool adde added? "add" : "remove", *count_addr)); - JvmtiVTMSTransitionDisabler disabler; - if (added) { (*count_addr)++; if (*count_addr == 1) { diff --git a/src/hotspot/share/runtime/java.hpp b/src/hotspot/share/runtime/java.hpp index 9ab270e143d5a..21cbd76431fbb 100644 --- a/src/hotspot/share/runtime/java.hpp +++ b/src/hotspot/share/runtime/java.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,6 +59,9 @@ extern void vm_shutdown_during_initialization(const char* error, const char* mes extern void vm_exit_during_cds_dumping(const char* error, const char* message = nullptr); +// This is defined in linkType.cpp due to linking restraints +extern bool is_vm_statically_linked(); + /** * With the integration of the changes to handle the version string * as defined by JEP-223, most of the code related to handle the version diff --git a/src/hotspot/share/runtime/linkType.cpp b/src/hotspot/share/runtime/linkType.cpp new file mode 100644 index 0000000000000..cc13efd68c2d8 --- /dev/null +++ b/src/hotspot/share/runtime/linkType.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "runtime/java.hpp" + +// This is in a separate file since it will need to be compiled to two different +// object files, depending on if we are going to build a static or a dynamic +// library. + +bool is_vm_statically_linked(void) { +#ifdef STATIC_BUILD + return true; +#else + return false; +#endif +} diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index 8c1dff38051d9..f033f42624987 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -267,7 +267,7 @@ void mutex_init() { MUTEX_DEFN(CompileStatistics_lock , PaddedMutex , safepoint); MUTEX_DEFN(DirectivesStack_lock , PaddedMutex , nosafepoint); - MUTEX_DEFN(JvmtiThreadState_lock , PaddedMutex , safepoint); // Used by JvmtiThreadState/JvmtiEventController + MUTEX_DEFN(JvmtiVTMSTransition_lock , PaddedMonitor, safepoint); // used for Virtual Thread Mount State transition management MUTEX_DEFN(EscapeBarrier_lock , PaddedMonitor, nosafepoint); // Used to synchronize object reallocation/relocking triggered by JVMTI MUTEX_DEFN(Management_lock , PaddedMutex , safepoint); // used for JVM management @@ -354,7 +354,7 @@ void mutex_init() { // JVMCIRuntime_lock must be acquired before JVMCI_lock to avoid deadlock MUTEX_DEFL(JVMCI_lock , PaddedMonitor, JVMCIRuntime_lock); #endif - MUTEX_DEFL(JvmtiVTMSTransition_lock , PaddedMonitor, JvmtiThreadState_lock); // used for Virtual Thread Mount State transition management + MUTEX_DEFL(JvmtiThreadState_lock , PaddedMutex , JvmtiVTMSTransition_lock); // Used by JvmtiThreadState/JvmtiEventController // Allocate RecursiveMutex MultiArray_lock = new RecursiveMutex(); diff --git a/src/java.base/macosx/native/libjli/java_md_macosx.m b/src/java.base/macosx/native/libjli/java_md_macosx.m index 279a7abef1ee4..4ac2f2c10a215 100644 --- a/src/java.base/macosx/native/libjli/java_md_macosx.m +++ b/src/java.base/macosx/native/libjli/java_md_macosx.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, 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 @@ -428,9 +428,9 @@ static void MacOSXStartup(int argc, char *argv[]) { JLI_TraceLauncher("Does `%s' exist ... ", jvmpath); -#ifdef STATIC_BUILD - return JNI_TRUE; -#else + if (JLI_IsStaticallyLinked()) { + return JNI_TRUE; + } if (stat(jvmpath, &s) == 0) { JLI_TraceLauncher("yes.\n"); return JNI_TRUE; @@ -438,7 +438,6 @@ static void MacOSXStartup(int argc, char *argv[]) { JLI_TraceLauncher("no.\n"); return JNI_FALSE; } -#endif } /* @@ -451,18 +450,18 @@ static void MacOSXStartup(int argc, char *argv[]) { if (GetApplicationHome(path, pathsize)) { /* Is JRE co-located with the application? */ -#ifdef STATIC_BUILD - char jvm_cfg[MAXPATHLEN]; - JLI_Snprintf(jvm_cfg, sizeof(jvm_cfg), "%s/lib/jvm.cfg", path); - if (access(jvm_cfg, F_OK) == 0) { - return JNI_TRUE; - } -#else - JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/" JAVA_DLL, path); - if (access(libjava, F_OK) == 0) { - return JNI_TRUE; + if (JLI_IsStaticallyLinked()) { + char jvm_cfg[MAXPATHLEN]; + JLI_Snprintf(jvm_cfg, sizeof(jvm_cfg), "%s/lib/jvm.cfg", path); + if (access(jvm_cfg, F_OK) == 0) { + return JNI_TRUE; + } + } else { + JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/" JAVA_DLL, path); + if (access(libjava, F_OK) == 0) { + return JNI_TRUE; + } } -#endif /* ensure storage for path + /jre + NULL */ if ((JLI_StrLen(path) + 4 + 1) > (size_t) pathsize) { JLI_TraceLauncher("Insufficient space to store JRE path\n"); @@ -481,23 +480,24 @@ static void MacOSXStartup(int argc, char *argv[]) { Dl_info selfInfo; dladdr(&GetJREPath, &selfInfo); -#ifdef STATIC_BUILD - char jvm_cfg[MAXPATHLEN]; - char *p = NULL; - strncpy(jvm_cfg, selfInfo.dli_fname, MAXPATHLEN); - p = strrchr(jvm_cfg, '/'); *p = '\0'; - p = strrchr(jvm_cfg, '/'); - if (strcmp(p, "/.") == 0) { - *p = '\0'; - p = strrchr(jvm_cfg, '/'); *p = '\0'; - } - else *p = '\0'; - strncpy(path, jvm_cfg, pathsize); - strncat(jvm_cfg, "/lib/jvm.cfg", MAXPATHLEN); - if (access(jvm_cfg, F_OK) == 0) { - return JNI_TRUE; + if (JLI_IsStaticallyLinked()) { + char jvm_cfg[MAXPATHLEN]; + char *p = NULL; + strncpy(jvm_cfg, selfInfo.dli_fname, MAXPATHLEN); + p = strrchr(jvm_cfg, '/'); *p = '\0'; + p = strrchr(jvm_cfg, '/'); + if (strcmp(p, "/.") == 0) { + *p = '\0'; + p = strrchr(jvm_cfg, '/'); *p = '\0'; + } else { + *p = '\0'; + } + strncpy(path, jvm_cfg, pathsize); + strncat(jvm_cfg, "/lib/jvm.cfg", MAXPATHLEN); + if (access(jvm_cfg, F_OK) == 0) { + return JNI_TRUE; + } } -#endif char *realPathToSelf = realpath(selfInfo.dli_fname, path); if (realPathToSelf != path) { @@ -549,11 +549,12 @@ static void MacOSXStartup(int argc, char *argv[]) { JLI_TraceLauncher("JVM path is %s\n", jvmpath); -#ifndef STATIC_BUILD - libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL); -#else - libjvm = dlopen(NULL, RTLD_FIRST); -#endif + if (!JLI_IsStaticallyLinked()) { + libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL); + } else { + libjvm = dlopen(NULL, RTLD_FIRST); + } + if (libjvm == NULL) { JLI_ReportErrorMessage(DLL_ERROR1, __LINE__); JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); @@ -603,14 +604,13 @@ static void MacOSXStartup(int argc, char *argv[]) { char* exec_path = NULL; { Dl_info dlinfo; - -#ifdef STATIC_BUILD void *fptr; - fptr = (void *)&SetExecname; -#else - int (*fptr)(); - fptr = (int (*)())dlsym(RTLD_DEFAULT, "main"); -#endif + + if (JLI_IsStaticallyLinked()) { + fptr = (void *)&SetExecname; + } else { + fptr = dlsym(RTLD_DEFAULT, "main"); + } if (fptr == NULL) { JLI_ReportErrorMessage(DLL_ERROR3, dlerror()); return JNI_FALSE; diff --git a/src/java.base/share/classes/java/io/File.java b/src/java.base/share/classes/java/io/File.java index 55c389ddf6751..b603e15551353 100644 --- a/src/java.base/share/classes/java/io/File.java +++ b/src/java.base/share/classes/java/io/File.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2024, 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 @@ -2117,6 +2117,11 @@ static File generateFile(String prefix, String suffix, File dir) * made the name of the new file will be generated by concatenating the * prefix, five or more internally-generated characters, and the suffix. * + *

If a file with the generated name cannot be created by the + * underlying platform, then an {@code IOException} will be thrown. + * This could occur for example if the supplied prefix or suffix contains + * one or more characters not supported by the underlying file system. + * *

If the {@code directory} argument is {@code null} then the * system-dependent default temporary-file directory will be used. The * default temporary-file directory is specified by the system property diff --git a/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java b/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java index 33cfb7f7c00f7..613142077552d 100644 --- a/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java +++ b/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java @@ -102,7 +102,9 @@ sealed interface OfConstant extends AnnotationValue { * {@return the constant pool entry backing this constant element} * * @apiNote - * Different types of constant values may share the same type of entry. + * Different types of constant values may share the same type of entry + * because they have the same {@linkplain TypeKind##computational-type + * computational type}. * For example, {@link OfInt} and {@link OfChar} are both * backed by {@link IntegerEntry}. Use {@link #resolvedValue * resolvedValue()} for a value of accurate type. diff --git a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java index 1a3166f8b3259..75413011731e4 100644 --- a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java @@ -262,7 +262,7 @@ default CodeBuilder ifThen(Consumer thenHandler) { */ default CodeBuilder ifThen(Opcode opcode, Consumer thenHandler) { - if (opcode.kind() != Opcode.Kind.BRANCH || opcode.primaryTypeKind() == TypeKind.VoidType) { + if (opcode.kind() != Opcode.Kind.BRANCH || opcode.primaryTypeKind() == TypeKind.VOID) { throw new IllegalArgumentException("Illegal branch opcode: " + opcode); } @@ -312,7 +312,7 @@ default CodeBuilder ifThenElse(Consumer thenHandler, default CodeBuilder ifThenElse(Opcode opcode, Consumer thenHandler, Consumer elseHandler) { - if (opcode.kind() != Opcode.Kind.BRANCH || opcode.primaryTypeKind() == TypeKind.VoidType) { + if (opcode.kind() != Opcode.Kind.BRANCH || opcode.primaryTypeKind() == TypeKind.VOID) { throw new IllegalArgumentException("Illegal branch opcode: " + opcode); } @@ -550,83 +550,58 @@ default CodeBuilder arrayStore(TypeKind tk) { * @param fromType the source type * @param toType the target type * @return this builder - * @throws IllegalArgumentException for conversions of {@code VoidType} or {@code ReferenceType} + * @throws IllegalArgumentException for conversions of {@link TypeKind#VOID void} or + * {@link TypeKind#REFERENCE reference} * @since 23 */ default CodeBuilder conversion(TypeKind fromType, TypeKind toType) { - return switch (fromType) { - case IntType, ByteType, CharType, ShortType, BooleanType -> - switch (toType) { - case IntType -> this; - case LongType -> i2l(); - case DoubleType -> i2d(); - case FloatType -> i2f(); - case ByteType -> i2b(); - case CharType -> i2c(); - case ShortType -> i2s(); - case BooleanType -> iconst_1().iand(); - case VoidType, ReferenceType -> - throw new IllegalArgumentException(String.format("convert %s -> %s", fromType, toType)); - }; - case LongType -> - switch (toType) { - case IntType -> l2i(); - case LongType -> this; - case DoubleType -> l2d(); - case FloatType -> l2f(); - case ByteType -> l2i().i2b(); - case CharType -> l2i().i2c(); - case ShortType -> l2i().i2s(); - case BooleanType -> l2i().iconst_1().iand(); - case VoidType, ReferenceType -> - throw new IllegalArgumentException(String.format("convert %s -> %s", fromType, toType)); - }; - case DoubleType -> - switch (toType) { - case IntType -> d2i(); - case LongType -> d2l(); - case DoubleType -> this; - case FloatType -> d2f(); - case ByteType -> d2i().i2b(); - case CharType -> d2i().i2c(); - case ShortType -> d2i().i2s(); - case BooleanType -> d2i().iconst_1().iand(); - case VoidType, ReferenceType -> - throw new IllegalArgumentException(String.format("convert %s -> %s", fromType, toType)); - }; - case FloatType -> - switch (toType) { - case IntType -> f2i(); - case LongType -> f2l(); - case DoubleType -> f2d(); - case FloatType -> this; - case ByteType -> f2i().i2b(); - case CharType -> f2i().i2c(); - case ShortType -> f2i().i2s(); - case BooleanType -> f2i().iconst_1().iand(); - case VoidType, ReferenceType -> - throw new IllegalArgumentException(String.format("convert %s -> %s", fromType, toType)); - }; - case VoidType, ReferenceType -> - throw new IllegalArgumentException(String.format("convert %s -> %s", fromType, toType)); - }; - } - - /** - * Generate an instruction pushing a constant onto the operand stack - * @see Opcode.Kind#CONSTANT - * @param opcode the constant instruction opcode - * @param value the constant value - * @return this builder - * @since 23 - */ - default CodeBuilder loadConstant(Opcode opcode, ConstantDesc value) { - BytecodeHelpers.validateValue(opcode, value); - return with(switch (opcode) { - case SIPUSH, BIPUSH -> ConstantInstruction.ofArgument(opcode, ((Number)value).intValue()); - case LDC, LDC_W, LDC2_W -> ConstantInstruction.ofLoad(opcode, BytecodeHelpers.constantEntry(constantPool(), value)); - default -> ConstantInstruction.ofIntrinsic(opcode); - }); + var computationalFrom = fromType.asLoadable(); + var computationalTo = toType.asLoadable(); + if (computationalFrom != computationalTo) { + switch (computationalTo) { + case INT -> { + switch (computationalFrom) { + case FLOAT -> f2i(); + case LONG -> l2i(); + case DOUBLE -> d2i(); + default -> throw BytecodeHelpers.cannotConvertException(fromType, toType); + } + } + case FLOAT -> { + switch (computationalFrom) { + case INT -> i2f(); + case LONG -> l2f(); + case DOUBLE -> d2f(); + default -> throw BytecodeHelpers.cannotConvertException(fromType, toType); + } + } + case LONG -> { + switch (computationalFrom) { + case INT -> i2l(); + case FLOAT -> f2l(); + case DOUBLE -> d2l(); + default -> throw BytecodeHelpers.cannotConvertException(fromType, toType); + } + } + case DOUBLE -> { + switch (computationalFrom) { + case INT -> i2d(); + case FLOAT -> f2d(); + case LONG -> l2d(); + default -> throw BytecodeHelpers.cannotConvertException(fromType, toType); + } + } + } + } + if (computationalTo == TypeKind.INT && toType != TypeKind.INT) { + switch (toType) { + case BOOLEAN -> iconst_1().iand(); + case BYTE -> i2b(); + case CHAR -> i2c(); + case SHORT -> i2s(); + } + } + return this; } /** @@ -842,7 +817,7 @@ default CodeBuilder aconst_null() { * @return this builder */ default CodeBuilder aaload() { - return arrayLoad(TypeKind.ReferenceType); + return arrayLoad(TypeKind.REFERENCE); } /** @@ -850,7 +825,7 @@ default CodeBuilder aaload() { * @return this builder */ default CodeBuilder aastore() { - return arrayStore(TypeKind.ReferenceType); + return arrayStore(TypeKind.REFERENCE); } /** @@ -863,7 +838,7 @@ default CodeBuilder aastore() { * @return this builder */ default CodeBuilder aload(int slot) { - return loadLocal(TypeKind.ReferenceType, slot); + return loadLocal(TypeKind.REFERENCE, slot); } /** @@ -890,7 +865,7 @@ default CodeBuilder anewarray(ClassDesc className) { * @return this builder */ default CodeBuilder areturn() { - return return_(TypeKind.ReferenceType); + return return_(TypeKind.REFERENCE); } /** @@ -911,7 +886,7 @@ default CodeBuilder arraylength() { * @return this builder */ default CodeBuilder astore(int slot) { - return storeLocal(TypeKind.ReferenceType, slot); + return storeLocal(TypeKind.REFERENCE, slot); } /** @@ -927,7 +902,7 @@ default CodeBuilder athrow() { * @return this builder */ default CodeBuilder baload() { - return arrayLoad(TypeKind.ByteType); + return arrayLoad(TypeKind.BYTE); } /** @@ -935,16 +910,16 @@ default CodeBuilder baload() { * @return this builder */ default CodeBuilder bastore() { - return arrayStore(TypeKind.ByteType); + return arrayStore(TypeKind.BYTE); } /** - * Generate an instruction pushing a byte onto the operand stack - * @param b the byte + * Generate an instruction pushing an int in the range of byte onto the operand stack. + * @param b the int in the range of byte * @return this builder */ default CodeBuilder bipush(int b) { - return loadConstant(Opcode.BIPUSH, b); + return with(ConstantInstruction.ofArgument(Opcode.BIPUSH, b)); } /** @@ -952,7 +927,7 @@ default CodeBuilder bipush(int b) { * @return this builder */ default CodeBuilder caload() { - return arrayLoad(TypeKind.CharType); + return arrayLoad(TypeKind.CHAR); } /** @@ -960,7 +935,7 @@ default CodeBuilder caload() { * @return this builder */ default CodeBuilder castore() { - return arrayStore(TypeKind.CharType); + return arrayStore(TypeKind.CHAR); } /** @@ -1019,7 +994,7 @@ default CodeBuilder dadd() { * @return this builder */ default CodeBuilder daload() { - return arrayLoad(TypeKind.DoubleType); + return arrayLoad(TypeKind.DOUBLE); } /** @@ -1027,7 +1002,7 @@ default CodeBuilder daload() { * @return this builder */ default CodeBuilder dastore() { - return arrayStore(TypeKind.DoubleType); + return arrayStore(TypeKind.DOUBLE); } /** @@ -1080,7 +1055,7 @@ default CodeBuilder ddiv() { * @return this builder */ default CodeBuilder dload(int slot) { - return loadLocal(TypeKind.DoubleType, slot); + return loadLocal(TypeKind.DOUBLE, slot); } /** @@ -1112,7 +1087,7 @@ default CodeBuilder drem() { * @return this builder */ default CodeBuilder dreturn() { - return return_(TypeKind.DoubleType); + return return_(TypeKind.DOUBLE); } /** @@ -1125,7 +1100,7 @@ default CodeBuilder dreturn() { * @return this builder */ default CodeBuilder dstore(int slot) { - return storeLocal(TypeKind.DoubleType, slot); + return storeLocal(TypeKind.DOUBLE, slot); } /** @@ -1223,7 +1198,7 @@ default CodeBuilder fadd() { * @return this builder */ default CodeBuilder faload() { - return arrayLoad(TypeKind.FloatType); + return arrayLoad(TypeKind.FLOAT); } /** @@ -1231,7 +1206,7 @@ default CodeBuilder faload() { * @return this builder */ default CodeBuilder fastore() { - return arrayStore(TypeKind.FloatType); + return arrayStore(TypeKind.FLOAT); } /** @@ -1292,7 +1267,7 @@ default CodeBuilder fdiv() { * @return this builder */ default CodeBuilder fload(int slot) { - return loadLocal(TypeKind.FloatType, slot); + return loadLocal(TypeKind.FLOAT, slot); } /** @@ -1324,7 +1299,7 @@ default CodeBuilder frem() { * @return this builder */ default CodeBuilder freturn() { - return return_(TypeKind.FloatType); + return return_(TypeKind.FLOAT); } /** @@ -1337,7 +1312,7 @@ default CodeBuilder freturn() { * @return this builder */ default CodeBuilder fstore(int slot) { - return storeLocal(TypeKind.FloatType, slot); + return storeLocal(TypeKind.FLOAT, slot); } /** @@ -1478,7 +1453,7 @@ default CodeBuilder iadd() { * @return this builder */ default CodeBuilder iaload() { - return arrayLoad(TypeKind.IntType); + return arrayLoad(TypeKind.INT); } /** @@ -1494,7 +1469,7 @@ default CodeBuilder iand() { * @return this builder */ default CodeBuilder iastore() { - return arrayStore(TypeKind.IntType); + return arrayStore(TypeKind.INT); } /** @@ -1725,7 +1700,7 @@ default CodeBuilder iinc(int slot, int val) { * @return this builder */ default CodeBuilder iload(int slot) { - return loadLocal(TypeKind.IntType, slot); + return loadLocal(TypeKind.INT, slot); } /** @@ -1954,7 +1929,7 @@ default CodeBuilder irem() { * @return this builder */ default CodeBuilder ireturn() { - return return_(TypeKind.IntType); + return return_(TypeKind.INT); } /** @@ -1983,7 +1958,7 @@ default CodeBuilder ishr() { * @return this builder */ default CodeBuilder istore(int slot) { - return storeLocal(TypeKind.IntType, slot); + return storeLocal(TypeKind.INT, slot); } /** @@ -2057,7 +2032,7 @@ default CodeBuilder ladd() { * @return this builder */ default CodeBuilder laload() { - return arrayLoad(TypeKind.LongType); + return arrayLoad(TypeKind.LONG); } /** @@ -2073,7 +2048,7 @@ default CodeBuilder land() { * @return this builder */ default CodeBuilder lastore() { - return arrayStore(TypeKind.LongType); + return arrayStore(TypeKind.LONG); } /** @@ -2145,7 +2120,7 @@ default CodeBuilder ldiv() { * @return this builder */ default CodeBuilder lload(int slot) { - return loadLocal(TypeKind.LongType, slot); + return loadLocal(TypeKind.LONG, slot); } /** @@ -2185,7 +2160,7 @@ default CodeBuilder lrem() { * @return this builder */ default CodeBuilder lreturn() { - return return_(TypeKind.LongType); + return return_(TypeKind.LONG); } /** @@ -2214,7 +2189,7 @@ default CodeBuilder lshr() { * @return this builder */ default CodeBuilder lstore(int slot) { - return storeLocal(TypeKind.LongType, slot); + return storeLocal(TypeKind.LONG, slot); } /** @@ -2384,7 +2359,7 @@ default CodeBuilder putstatic(ClassDesc owner, String name, ClassDesc type) { * @return this builder */ default CodeBuilder return_() { - return return_(TypeKind.VoidType); + return return_(TypeKind.VOID); } /** @@ -2392,7 +2367,7 @@ default CodeBuilder return_() { * @return this builder */ default CodeBuilder saload() { - return arrayLoad(TypeKind.ShortType); + return arrayLoad(TypeKind.SHORT); } /** @@ -2400,16 +2375,16 @@ default CodeBuilder saload() { * @return this builder */ default CodeBuilder sastore() { - return arrayStore(TypeKind.ShortType); + return arrayStore(TypeKind.SHORT); } /** - * Generate an instruction pushing a short onto the operand stack - * @param s the short + * Generate an instruction pushing an int in the range of short onto the operand stack. + * @param s the int in the range of short * @return this builder */ default CodeBuilder sipush(int s) { - return loadConstant(Opcode.SIPUSH, s); + return with(ConstantInstruction.ofArgument(Opcode.SIPUSH, s)); } /** diff --git a/src/java.base/share/classes/java/lang/classfile/Opcode.java b/src/java.base/share/classes/java/lang/classfile/Opcode.java index 9128a0e79d3ab..9e4c35276cfc8 100644 --- a/src/java.base/share/classes/java/lang/classfile/Opcode.java +++ b/src/java.base/share/classes/java/lang/classfile/Opcode.java @@ -45,55 +45,55 @@ public enum Opcode { NOP(ClassFile.NOP, 1, Kind.NOP), /** Push null */ - ACONST_NULL(ClassFile.ACONST_NULL, 1, Kind.CONSTANT, TypeKind.ReferenceType, 0, ConstantDescs.NULL), + ACONST_NULL(ClassFile.ACONST_NULL, 1, Kind.CONSTANT, TypeKind.REFERENCE, 0, ConstantDescs.NULL), /** Push int constant -1 */ - ICONST_M1(ClassFile.ICONST_M1, 1, Kind.CONSTANT, TypeKind.IntType, 0, -1), + ICONST_M1(ClassFile.ICONST_M1, 1, Kind.CONSTANT, TypeKind.INT, 0, -1), /** Push int constant 0 */ - ICONST_0(ClassFile.ICONST_0, 1, Kind.CONSTANT, TypeKind.IntType, 0, 0), + ICONST_0(ClassFile.ICONST_0, 1, Kind.CONSTANT, TypeKind.INT, 0, 0), /** Push int constant 1 */ - ICONST_1(ClassFile.ICONST_1, 1, Kind.CONSTANT, TypeKind.IntType, 0, 1), + ICONST_1(ClassFile.ICONST_1, 1, Kind.CONSTANT, TypeKind.INT, 0, 1), /** Push int constant 2 */ - ICONST_2(ClassFile.ICONST_2, 1, Kind.CONSTANT, TypeKind.IntType, 0, 2), + ICONST_2(ClassFile.ICONST_2, 1, Kind.CONSTANT, TypeKind.INT, 0, 2), /** Push int constant 3 */ - ICONST_3(ClassFile.ICONST_3, 1, Kind.CONSTANT, TypeKind.IntType, 0, 3), + ICONST_3(ClassFile.ICONST_3, 1, Kind.CONSTANT, TypeKind.INT, 0, 3), /** Push int constant 4 */ - ICONST_4(ClassFile.ICONST_4, 1, Kind.CONSTANT, TypeKind.IntType, 0, 4), + ICONST_4(ClassFile.ICONST_4, 1, Kind.CONSTANT, TypeKind.INT, 0, 4), /** Push int constant 5 */ - ICONST_5(ClassFile.ICONST_5, 1, Kind.CONSTANT, TypeKind.IntType, 0, 5), + ICONST_5(ClassFile.ICONST_5, 1, Kind.CONSTANT, TypeKind.INT, 0, 5), /** Push long constant 0 */ - LCONST_0(ClassFile.LCONST_0, 1, Kind.CONSTANT, TypeKind.LongType, 0, 0L), + LCONST_0(ClassFile.LCONST_0, 1, Kind.CONSTANT, TypeKind.LONG, 0, 0L), /** Push long constant 1 */ - LCONST_1(ClassFile.LCONST_1, 1, Kind.CONSTANT, TypeKind.LongType, 0, 1L), + LCONST_1(ClassFile.LCONST_1, 1, Kind.CONSTANT, TypeKind.LONG, 0, 1L), /** Push float constant 0 */ - FCONST_0(ClassFile.FCONST_0, 1, Kind.CONSTANT, TypeKind.FloatType, 0, 0.0f), + FCONST_0(ClassFile.FCONST_0, 1, Kind.CONSTANT, TypeKind.FLOAT, 0, 0.0f), /** Push float constant 1 */ - FCONST_1(ClassFile.FCONST_1, 1, Kind.CONSTANT, TypeKind.FloatType, 0, 1.0f), + FCONST_1(ClassFile.FCONST_1, 1, Kind.CONSTANT, TypeKind.FLOAT, 0, 1.0f), /** Push float constant 2 */ - FCONST_2(ClassFile.FCONST_2, 1, Kind.CONSTANT, TypeKind.FloatType, 0, 2.0f), + FCONST_2(ClassFile.FCONST_2, 1, Kind.CONSTANT, TypeKind.FLOAT, 0, 2.0f), /** Push double constant 0 */ - DCONST_0(ClassFile.DCONST_0, 1, Kind.CONSTANT, TypeKind.DoubleType, 0, 0.0d), + DCONST_0(ClassFile.DCONST_0, 1, Kind.CONSTANT, TypeKind.DOUBLE, 0, 0.0d), /** Push double constant 1 */ - DCONST_1(ClassFile.DCONST_1, 1, Kind.CONSTANT, TypeKind.DoubleType, 0, 1.0d), + DCONST_1(ClassFile.DCONST_1, 1, Kind.CONSTANT, TypeKind.DOUBLE, 0, 1.0d), /** Push byte */ - BIPUSH(ClassFile.BIPUSH, 2, Kind.CONSTANT, TypeKind.ByteType), + BIPUSH(ClassFile.BIPUSH, 2, Kind.CONSTANT, TypeKind.BYTE), /** Push short */ - SIPUSH(ClassFile.SIPUSH, 3, Kind.CONSTANT, TypeKind.ShortType), + SIPUSH(ClassFile.SIPUSH, 3, Kind.CONSTANT, TypeKind.SHORT), /** Push item from run-time constant pool */ LDC(ClassFile.LDC, 2, Kind.CONSTANT), @@ -105,202 +105,202 @@ public enum Opcode { LDC2_W(ClassFile.LDC2_W, 3, Kind.CONSTANT), /** Load int from local variable */ - ILOAD(ClassFile.ILOAD, 2, Kind.LOAD, TypeKind.IntType, -1), + ILOAD(ClassFile.ILOAD, 2, Kind.LOAD, TypeKind.INT, -1), /** Load long from local variable */ - LLOAD(ClassFile.LLOAD, 2, Kind.LOAD, TypeKind.LongType, -1), + LLOAD(ClassFile.LLOAD, 2, Kind.LOAD, TypeKind.LONG, -1), /** Load float from local variable */ - FLOAD(ClassFile.FLOAD, 2, Kind.LOAD, TypeKind.FloatType, -1), + FLOAD(ClassFile.FLOAD, 2, Kind.LOAD, TypeKind.FLOAT, -1), /** Load double from local variable */ - DLOAD(ClassFile.DLOAD, 2, Kind.LOAD, TypeKind.DoubleType, -1), + DLOAD(ClassFile.DLOAD, 2, Kind.LOAD, TypeKind.DOUBLE, -1), /** Load reference from local variable */ - ALOAD(ClassFile.ALOAD, 2, Kind.LOAD, TypeKind.ReferenceType, -1), + ALOAD(ClassFile.ALOAD, 2, Kind.LOAD, TypeKind.REFERENCE, -1), /** Load int from local variable 0 */ - ILOAD_0(ClassFile.ILOAD_0, 1, Kind.LOAD, TypeKind.IntType, 0), + ILOAD_0(ClassFile.ILOAD_0, 1, Kind.LOAD, TypeKind.INT, 0), /** Load int from local variable 1 */ - ILOAD_1(ClassFile.ILOAD_1, 1, Kind.LOAD, TypeKind.IntType, 1), + ILOAD_1(ClassFile.ILOAD_1, 1, Kind.LOAD, TypeKind.INT, 1), /** Load int from local variable 2 */ - ILOAD_2(ClassFile.ILOAD_2, 1, Kind.LOAD, TypeKind.IntType, 2), + ILOAD_2(ClassFile.ILOAD_2, 1, Kind.LOAD, TypeKind.INT, 2), /** Load int from local variable3 */ - ILOAD_3(ClassFile.ILOAD_3, 1, Kind.LOAD, TypeKind.IntType, 3), + ILOAD_3(ClassFile.ILOAD_3, 1, Kind.LOAD, TypeKind.INT, 3), /** Load long from local variable 0 */ - LLOAD_0(ClassFile.LLOAD_0, 1, Kind.LOAD, TypeKind.LongType, 0), + LLOAD_0(ClassFile.LLOAD_0, 1, Kind.LOAD, TypeKind.LONG, 0), /** Load long from local variable 1 */ - LLOAD_1(ClassFile.LLOAD_1, 1, Kind.LOAD, TypeKind.LongType, 1), + LLOAD_1(ClassFile.LLOAD_1, 1, Kind.LOAD, TypeKind.LONG, 1), /** Load long from local variable 2 */ - LLOAD_2(ClassFile.LLOAD_2, 1, Kind.LOAD, TypeKind.LongType, 2), + LLOAD_2(ClassFile.LLOAD_2, 1, Kind.LOAD, TypeKind.LONG, 2), /** Load long from local variable 3 */ - LLOAD_3(ClassFile.LLOAD_3, 1, Kind.LOAD, TypeKind.LongType, 3), + LLOAD_3(ClassFile.LLOAD_3, 1, Kind.LOAD, TypeKind.LONG, 3), /** Load float from local variable 0 */ - FLOAD_0(ClassFile.FLOAD_0, 1, Kind.LOAD, TypeKind.FloatType, 0), + FLOAD_0(ClassFile.FLOAD_0, 1, Kind.LOAD, TypeKind.FLOAT, 0), /** Load float from local variable 1 */ - FLOAD_1(ClassFile.FLOAD_1, 1, Kind.LOAD, TypeKind.FloatType, 1), + FLOAD_1(ClassFile.FLOAD_1, 1, Kind.LOAD, TypeKind.FLOAT, 1), /** Load float from local variable 2 */ - FLOAD_2(ClassFile.FLOAD_2, 1, Kind.LOAD, TypeKind.FloatType, 2), + FLOAD_2(ClassFile.FLOAD_2, 1, Kind.LOAD, TypeKind.FLOAT, 2), /** Load float from local variable 3 */ - FLOAD_3(ClassFile.FLOAD_3, 1, Kind.LOAD, TypeKind.FloatType, 3), + FLOAD_3(ClassFile.FLOAD_3, 1, Kind.LOAD, TypeKind.FLOAT, 3), /** Load double from local variable 0 */ - DLOAD_0(ClassFile.DLOAD_0, 1, Kind.LOAD, TypeKind.DoubleType, 0), + DLOAD_0(ClassFile.DLOAD_0, 1, Kind.LOAD, TypeKind.DOUBLE, 0), /** Load double from local variable 1 */ - DLOAD_1(ClassFile.DLOAD_1, 1, Kind.LOAD, TypeKind.DoubleType, 1), + DLOAD_1(ClassFile.DLOAD_1, 1, Kind.LOAD, TypeKind.DOUBLE, 1), /** Load double from local variable 2 */ - DLOAD_2(ClassFile.DLOAD_2, 1, Kind.LOAD, TypeKind.DoubleType, 2), + DLOAD_2(ClassFile.DLOAD_2, 1, Kind.LOAD, TypeKind.DOUBLE, 2), /** Load double from local variable 3 */ - DLOAD_3(ClassFile.DLOAD_3, 1, Kind.LOAD, TypeKind.DoubleType, 3), + DLOAD_3(ClassFile.DLOAD_3, 1, Kind.LOAD, TypeKind.DOUBLE, 3), /** Load reference from local variable 0 */ - ALOAD_0(ClassFile.ALOAD_0, 1, Kind.LOAD, TypeKind.ReferenceType, 0), + ALOAD_0(ClassFile.ALOAD_0, 1, Kind.LOAD, TypeKind.REFERENCE, 0), /** Load reference from local variable 1 */ - ALOAD_1(ClassFile.ALOAD_1, 1, Kind.LOAD, TypeKind.ReferenceType, 1), + ALOAD_1(ClassFile.ALOAD_1, 1, Kind.LOAD, TypeKind.REFERENCE, 1), /** Load reference from local variable 2 */ - ALOAD_2(ClassFile.ALOAD_2, 1, Kind.LOAD, TypeKind.ReferenceType, 2), + ALOAD_2(ClassFile.ALOAD_2, 1, Kind.LOAD, TypeKind.REFERENCE, 2), /** Load reference from local variable 3 */ - ALOAD_3(ClassFile.ALOAD_3, 1, Kind.LOAD, TypeKind.ReferenceType, 3), + ALOAD_3(ClassFile.ALOAD_3, 1, Kind.LOAD, TypeKind.REFERENCE, 3), /** Load int from array */ - IALOAD(ClassFile.IALOAD, 1, Kind.ARRAY_LOAD, TypeKind.IntType), + IALOAD(ClassFile.IALOAD, 1, Kind.ARRAY_LOAD, TypeKind.INT), /** Load long from array */ - LALOAD(ClassFile.LALOAD, 1, Kind.ARRAY_LOAD, TypeKind.LongType), + LALOAD(ClassFile.LALOAD, 1, Kind.ARRAY_LOAD, TypeKind.LONG), /** Load float from array */ - FALOAD(ClassFile.FALOAD, 1, Kind.ARRAY_LOAD, TypeKind.FloatType), + FALOAD(ClassFile.FALOAD, 1, Kind.ARRAY_LOAD, TypeKind.FLOAT), /** Load double from array */ - DALOAD(ClassFile.DALOAD, 1, Kind.ARRAY_LOAD, TypeKind.DoubleType), + DALOAD(ClassFile.DALOAD, 1, Kind.ARRAY_LOAD, TypeKind.DOUBLE), /** Load reference from array */ - AALOAD(ClassFile.AALOAD, 1, Kind.ARRAY_LOAD, TypeKind.ReferenceType), + AALOAD(ClassFile.AALOAD, 1, Kind.ARRAY_LOAD, TypeKind.REFERENCE), - /** Load byte from array */ - BALOAD(ClassFile.BALOAD, 1, Kind.ARRAY_LOAD, TypeKind.ByteType), + /** Load byte or boolean from array */ + BALOAD(ClassFile.BALOAD, 1, Kind.ARRAY_LOAD, TypeKind.BYTE), /** Load char from array */ - CALOAD(ClassFile.CALOAD, 1, Kind.ARRAY_LOAD, TypeKind.CharType), + CALOAD(ClassFile.CALOAD, 1, Kind.ARRAY_LOAD, TypeKind.CHAR), /** Load short from array */ - SALOAD(ClassFile.SALOAD, 1, Kind.ARRAY_LOAD, TypeKind.ShortType), + SALOAD(ClassFile.SALOAD, 1, Kind.ARRAY_LOAD, TypeKind.SHORT), /** Store int into local variable */ - ISTORE(ClassFile.ISTORE, 2, Kind.STORE, TypeKind.IntType, -1), + ISTORE(ClassFile.ISTORE, 2, Kind.STORE, TypeKind.INT, -1), /** Store long into local variable */ - LSTORE(ClassFile.LSTORE, 2, Kind.STORE, TypeKind.LongType, -1), + LSTORE(ClassFile.LSTORE, 2, Kind.STORE, TypeKind.LONG, -1), /** Store float into local variable */ - FSTORE(ClassFile.FSTORE, 2, Kind.STORE, TypeKind.FloatType, -1), + FSTORE(ClassFile.FSTORE, 2, Kind.STORE, TypeKind.FLOAT, -1), /** Store double into local variable */ - DSTORE(ClassFile.DSTORE, 2, Kind.STORE, TypeKind.DoubleType, -1), + DSTORE(ClassFile.DSTORE, 2, Kind.STORE, TypeKind.DOUBLE, -1), /** Store reference into local variable */ - ASTORE(ClassFile.ASTORE, 2, Kind.STORE, TypeKind.ReferenceType, -1), + ASTORE(ClassFile.ASTORE, 2, Kind.STORE, TypeKind.REFERENCE, -1), /** Store int into local variable 0 */ - ISTORE_0(ClassFile.ISTORE_0, 1, Kind.STORE, TypeKind.IntType, 0), + ISTORE_0(ClassFile.ISTORE_0, 1, Kind.STORE, TypeKind.INT, 0), /** Store int into local variable 1 */ - ISTORE_1(ClassFile.ISTORE_1, 1, Kind.STORE, TypeKind.IntType, 1), + ISTORE_1(ClassFile.ISTORE_1, 1, Kind.STORE, TypeKind.INT, 1), /** Store int into local variable 2 */ - ISTORE_2(ClassFile.ISTORE_2, 1, Kind.STORE, TypeKind.IntType, 2), + ISTORE_2(ClassFile.ISTORE_2, 1, Kind.STORE, TypeKind.INT, 2), /** Store int into local variable 3 */ - ISTORE_3(ClassFile.ISTORE_3, 1, Kind.STORE, TypeKind.IntType, 3), + ISTORE_3(ClassFile.ISTORE_3, 1, Kind.STORE, TypeKind.INT, 3), /** Store long into local variable 0 */ - LSTORE_0(ClassFile.LSTORE_0, 1, Kind.STORE, TypeKind.LongType, 0), + LSTORE_0(ClassFile.LSTORE_0, 1, Kind.STORE, TypeKind.LONG, 0), /** Store long into local variable 1 */ - LSTORE_1(ClassFile.LSTORE_1, 1, Kind.STORE, TypeKind.LongType, 1), + LSTORE_1(ClassFile.LSTORE_1, 1, Kind.STORE, TypeKind.LONG, 1), /** Store long into local variable 2 */ - LSTORE_2(ClassFile.LSTORE_2, 1, Kind.STORE, TypeKind.LongType, 2), + LSTORE_2(ClassFile.LSTORE_2, 1, Kind.STORE, TypeKind.LONG, 2), /** Store long into local variable 3 */ - LSTORE_3(ClassFile.LSTORE_3, 1, Kind.STORE, TypeKind.LongType, 3), + LSTORE_3(ClassFile.LSTORE_3, 1, Kind.STORE, TypeKind.LONG, 3), /** Store float into local variable 0 */ - FSTORE_0(ClassFile.FSTORE_0, 1, Kind.STORE, TypeKind.FloatType, 0), + FSTORE_0(ClassFile.FSTORE_0, 1, Kind.STORE, TypeKind.FLOAT, 0), /** Store float into local variable 1 */ - FSTORE_1(ClassFile.FSTORE_1, 1, Kind.STORE, TypeKind.FloatType, 1), + FSTORE_1(ClassFile.FSTORE_1, 1, Kind.STORE, TypeKind.FLOAT, 1), /** Store float into local variable 2 */ - FSTORE_2(ClassFile.FSTORE_2, 1, Kind.STORE, TypeKind.FloatType, 2), + FSTORE_2(ClassFile.FSTORE_2, 1, Kind.STORE, TypeKind.FLOAT, 2), /** Store float into local variable 3 */ - FSTORE_3(ClassFile.FSTORE_3, 1, Kind.STORE, TypeKind.FloatType, 3), + FSTORE_3(ClassFile.FSTORE_3, 1, Kind.STORE, TypeKind.FLOAT, 3), /** Store double into local variable 0 */ - DSTORE_0(ClassFile.DSTORE_0, 1, Kind.STORE, TypeKind.DoubleType, 0), + DSTORE_0(ClassFile.DSTORE_0, 1, Kind.STORE, TypeKind.DOUBLE, 0), /** Store double into local variable 1 */ - DSTORE_1(ClassFile.DSTORE_1, 1, Kind.STORE, TypeKind.DoubleType, 1), + DSTORE_1(ClassFile.DSTORE_1, 1, Kind.STORE, TypeKind.DOUBLE, 1), /** Store double into local variable 2 */ - DSTORE_2(ClassFile.DSTORE_2, 1, Kind.STORE, TypeKind.DoubleType, 2), + DSTORE_2(ClassFile.DSTORE_2, 1, Kind.STORE, TypeKind.DOUBLE, 2), /** Store double into local variable 3 */ - DSTORE_3(ClassFile.DSTORE_3, 1, Kind.STORE, TypeKind.DoubleType, 3), + DSTORE_3(ClassFile.DSTORE_3, 1, Kind.STORE, TypeKind.DOUBLE, 3), /** Store reference into local variable 0 */ - ASTORE_0(ClassFile.ASTORE_0, 1, Kind.STORE, TypeKind.ReferenceType, 0), + ASTORE_0(ClassFile.ASTORE_0, 1, Kind.STORE, TypeKind.REFERENCE, 0), /** Store reference into local variable 1 */ - ASTORE_1(ClassFile.ASTORE_1, 1, Kind.STORE, TypeKind.ReferenceType, 1), + ASTORE_1(ClassFile.ASTORE_1, 1, Kind.STORE, TypeKind.REFERENCE, 1), /** Store reference into local variable 2 */ - ASTORE_2(ClassFile.ASTORE_2, 1, Kind.STORE, TypeKind.ReferenceType, 2), + ASTORE_2(ClassFile.ASTORE_2, 1, Kind.STORE, TypeKind.REFERENCE, 2), /** Store reference into local variable 3 */ - ASTORE_3(ClassFile.ASTORE_3, 1, Kind.STORE, TypeKind.ReferenceType, 3), + ASTORE_3(ClassFile.ASTORE_3, 1, Kind.STORE, TypeKind.REFERENCE, 3), /** Store into int array */ - IASTORE(ClassFile.IASTORE, 1, Kind.ARRAY_STORE, TypeKind.IntType), + IASTORE(ClassFile.IASTORE, 1, Kind.ARRAY_STORE, TypeKind.INT), /** Store into long array */ - LASTORE(ClassFile.LASTORE, 1, Kind.ARRAY_STORE, TypeKind.LongType), + LASTORE(ClassFile.LASTORE, 1, Kind.ARRAY_STORE, TypeKind.LONG), /** Store into float array */ - FASTORE(ClassFile.FASTORE, 1, Kind.ARRAY_STORE, TypeKind.FloatType), + FASTORE(ClassFile.FASTORE, 1, Kind.ARRAY_STORE, TypeKind.FLOAT), /** Store into double array */ - DASTORE(ClassFile.DASTORE, 1, Kind.ARRAY_STORE, TypeKind.DoubleType), + DASTORE(ClassFile.DASTORE, 1, Kind.ARRAY_STORE, TypeKind.DOUBLE), /** Store into reference array */ - AASTORE(ClassFile.AASTORE, 1, Kind.ARRAY_STORE, TypeKind.ReferenceType), + AASTORE(ClassFile.AASTORE, 1, Kind.ARRAY_STORE, TypeKind.REFERENCE), - /** Store into byte array */ - BASTORE(ClassFile.BASTORE, 1, Kind.ARRAY_STORE, TypeKind.ByteType), + /** Store into byte or boolean array */ + BASTORE(ClassFile.BASTORE, 1, Kind.ARRAY_STORE, TypeKind.BYTE), /** Store into char array */ - CASTORE(ClassFile.CASTORE, 1, Kind.ARRAY_STORE, TypeKind.CharType), + CASTORE(ClassFile.CASTORE, 1, Kind.ARRAY_STORE, TypeKind.CHAR), /** Store into short array */ - SASTORE(ClassFile.SASTORE, 1, Kind.ARRAY_STORE, TypeKind.ShortType), + SASTORE(ClassFile.SASTORE, 1, Kind.ARRAY_STORE, TypeKind.SHORT), /** Pop the top operand stack value */ POP(ClassFile.POP, 1, Kind.STACK), @@ -330,220 +330,220 @@ public enum Opcode { SWAP(ClassFile.SWAP, 1, Kind.STACK), /** Add int */ - IADD(ClassFile.IADD, 1, Kind.OPERATOR, TypeKind.IntType), + IADD(ClassFile.IADD, 1, Kind.OPERATOR, TypeKind.INT), /** Add long */ - LADD(ClassFile.LADD, 1, Kind.OPERATOR, TypeKind.LongType), + LADD(ClassFile.LADD, 1, Kind.OPERATOR, TypeKind.LONG), /** Add float */ - FADD(ClassFile.FADD, 1, Kind.OPERATOR, TypeKind.FloatType), + FADD(ClassFile.FADD, 1, Kind.OPERATOR, TypeKind.FLOAT), /** Add double */ - DADD(ClassFile.DADD, 1, Kind.OPERATOR, TypeKind.DoubleType), + DADD(ClassFile.DADD, 1, Kind.OPERATOR, TypeKind.DOUBLE), /** Subtract int */ - ISUB(ClassFile.ISUB, 1, Kind.OPERATOR, TypeKind.IntType), + ISUB(ClassFile.ISUB, 1, Kind.OPERATOR, TypeKind.INT), /** Subtract long */ - LSUB(ClassFile.LSUB, 1, Kind.OPERATOR, TypeKind.LongType), + LSUB(ClassFile.LSUB, 1, Kind.OPERATOR, TypeKind.LONG), /** Subtract float */ - FSUB(ClassFile.FSUB, 1, Kind.OPERATOR, TypeKind.FloatType), + FSUB(ClassFile.FSUB, 1, Kind.OPERATOR, TypeKind.FLOAT), /** Subtract double */ - DSUB(ClassFile.DSUB, 1, Kind.OPERATOR, TypeKind.DoubleType), + DSUB(ClassFile.DSUB, 1, Kind.OPERATOR, TypeKind.DOUBLE), /** Multiply int */ - IMUL(ClassFile.IMUL, 1, Kind.OPERATOR, TypeKind.IntType), + IMUL(ClassFile.IMUL, 1, Kind.OPERATOR, TypeKind.INT), /** Multiply long */ - LMUL(ClassFile.LMUL, 1, Kind.OPERATOR, TypeKind.LongType), + LMUL(ClassFile.LMUL, 1, Kind.OPERATOR, TypeKind.LONG), /** Multiply float */ - FMUL(ClassFile.FMUL, 1, Kind.OPERATOR, TypeKind.FloatType), + FMUL(ClassFile.FMUL, 1, Kind.OPERATOR, TypeKind.FLOAT), /** Multiply double */ - DMUL(ClassFile.DMUL, 1, Kind.OPERATOR, TypeKind.DoubleType), + DMUL(ClassFile.DMUL, 1, Kind.OPERATOR, TypeKind.DOUBLE), /** Divide int */ - IDIV(ClassFile.IDIV, 1, Kind.OPERATOR, TypeKind.IntType), + IDIV(ClassFile.IDIV, 1, Kind.OPERATOR, TypeKind.INT), /** Divide long */ - LDIV(ClassFile.LDIV, 1, Kind.OPERATOR, TypeKind.LongType), + LDIV(ClassFile.LDIV, 1, Kind.OPERATOR, TypeKind.LONG), /** Divide float */ - FDIV(ClassFile.FDIV, 1, Kind.OPERATOR, TypeKind.FloatType), + FDIV(ClassFile.FDIV, 1, Kind.OPERATOR, TypeKind.FLOAT), /** Divide double */ - DDIV(ClassFile.DDIV, 1, Kind.OPERATOR, TypeKind.DoubleType), + DDIV(ClassFile.DDIV, 1, Kind.OPERATOR, TypeKind.DOUBLE), /** Remainder int */ - IREM(ClassFile.IREM, 1, Kind.OPERATOR, TypeKind.IntType), + IREM(ClassFile.IREM, 1, Kind.OPERATOR, TypeKind.INT), /** Remainder long */ - LREM(ClassFile.LREM, 1, Kind.OPERATOR, TypeKind.LongType), + LREM(ClassFile.LREM, 1, Kind.OPERATOR, TypeKind.LONG), /** Remainder float */ - FREM(ClassFile.FREM, 1, Kind.OPERATOR, TypeKind.FloatType), + FREM(ClassFile.FREM, 1, Kind.OPERATOR, TypeKind.FLOAT), /** Remainder double */ - DREM(ClassFile.DREM, 1, Kind.OPERATOR, TypeKind.DoubleType), + DREM(ClassFile.DREM, 1, Kind.OPERATOR, TypeKind.DOUBLE), /** Negate int */ - INEG(ClassFile.INEG, 1, Kind.OPERATOR, TypeKind.IntType), + INEG(ClassFile.INEG, 1, Kind.OPERATOR, TypeKind.INT), /** Negate long */ - LNEG(ClassFile.LNEG, 1, Kind.OPERATOR, TypeKind.LongType), + LNEG(ClassFile.LNEG, 1, Kind.OPERATOR, TypeKind.LONG), /** Negate float */ - FNEG(ClassFile.FNEG, 1, Kind.OPERATOR, TypeKind.FloatType), + FNEG(ClassFile.FNEG, 1, Kind.OPERATOR, TypeKind.FLOAT), /** Negate double */ - DNEG(ClassFile.DNEG, 1, Kind.OPERATOR, TypeKind.DoubleType), + DNEG(ClassFile.DNEG, 1, Kind.OPERATOR, TypeKind.DOUBLE), /** Shift left int */ - ISHL(ClassFile.ISHL, 1, Kind.OPERATOR, TypeKind.IntType), + ISHL(ClassFile.ISHL, 1, Kind.OPERATOR, TypeKind.INT), /** Shift left long */ - LSHL(ClassFile.LSHL, 1, Kind.OPERATOR, TypeKind.LongType), + LSHL(ClassFile.LSHL, 1, Kind.OPERATOR, TypeKind.LONG), /** Shift right int */ - ISHR(ClassFile.ISHR, 1, Kind.OPERATOR, TypeKind.IntType), + ISHR(ClassFile.ISHR, 1, Kind.OPERATOR, TypeKind.INT), /** Shift right long */ - LSHR(ClassFile.LSHR, 1, Kind.OPERATOR, TypeKind.LongType), + LSHR(ClassFile.LSHR, 1, Kind.OPERATOR, TypeKind.LONG), /** Logical shift right int */ - IUSHR(ClassFile.IUSHR, 1, Kind.OPERATOR, TypeKind.IntType), + IUSHR(ClassFile.IUSHR, 1, Kind.OPERATOR, TypeKind.INT), /** Logical shift right long */ - LUSHR(ClassFile.LUSHR, 1, Kind.OPERATOR, TypeKind.LongType), + LUSHR(ClassFile.LUSHR, 1, Kind.OPERATOR, TypeKind.LONG), /** Boolean AND int */ - IAND(ClassFile.IAND, 1, Kind.OPERATOR, TypeKind.IntType), + IAND(ClassFile.IAND, 1, Kind.OPERATOR, TypeKind.INT), /** Boolean AND long */ - LAND(ClassFile.LAND, 1, Kind.OPERATOR, TypeKind.LongType), + LAND(ClassFile.LAND, 1, Kind.OPERATOR, TypeKind.LONG), /** Boolean OR int */ - IOR(ClassFile.IOR, 1, Kind.OPERATOR, TypeKind.IntType), + IOR(ClassFile.IOR, 1, Kind.OPERATOR, TypeKind.INT), /** Boolean OR long */ - LOR(ClassFile.LOR, 1, Kind.OPERATOR, TypeKind.LongType), + LOR(ClassFile.LOR, 1, Kind.OPERATOR, TypeKind.LONG), /** Boolean XOR int */ - IXOR(ClassFile.IXOR, 1, Kind.OPERATOR, TypeKind.IntType), + IXOR(ClassFile.IXOR, 1, Kind.OPERATOR, TypeKind.INT), /** Boolean XOR long */ - LXOR(ClassFile.LXOR, 1, Kind.OPERATOR, TypeKind.LongType), + LXOR(ClassFile.LXOR, 1, Kind.OPERATOR, TypeKind.LONG), /** Increment local variable by constant */ - IINC(ClassFile.IINC, 3, Kind.INCREMENT, TypeKind.IntType, -1), + IINC(ClassFile.IINC, 3, Kind.INCREMENT, TypeKind.INT, -1), /** Convert int to long */ - I2L(ClassFile.I2L, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.LongType), + I2L(ClassFile.I2L, 1, Kind.CONVERT, TypeKind.INT, TypeKind.LONG), /** Convert int to float */ - I2F(ClassFile.I2F, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.FloatType), + I2F(ClassFile.I2F, 1, Kind.CONVERT, TypeKind.INT, TypeKind.FLOAT), /** Convert int to double */ - I2D(ClassFile.I2D, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.DoubleType), + I2D(ClassFile.I2D, 1, Kind.CONVERT, TypeKind.INT, TypeKind.DOUBLE), /** Convert long to int */ - L2I(ClassFile.L2I, 1, Kind.CONVERT, TypeKind.LongType, TypeKind.IntType), + L2I(ClassFile.L2I, 1, Kind.CONVERT, TypeKind.LONG, TypeKind.INT), /** Convert long to float */ - L2F(ClassFile.L2F, 1, Kind.CONVERT, TypeKind.LongType, TypeKind.FloatType), + L2F(ClassFile.L2F, 1, Kind.CONVERT, TypeKind.LONG, TypeKind.FLOAT), /** Convert long to double */ - L2D(ClassFile.L2D, 1, Kind.CONVERT, TypeKind.LongType, TypeKind.DoubleType), + L2D(ClassFile.L2D, 1, Kind.CONVERT, TypeKind.LONG, TypeKind.DOUBLE), /** Convert float to int */ - F2I(ClassFile.F2I, 1, Kind.CONVERT, TypeKind.FloatType, TypeKind.IntType), + F2I(ClassFile.F2I, 1, Kind.CONVERT, TypeKind.FLOAT, TypeKind.INT), /** Convert float to long */ - F2L(ClassFile.F2L, 1, Kind.CONVERT, TypeKind.FloatType, TypeKind.LongType), + F2L(ClassFile.F2L, 1, Kind.CONVERT, TypeKind.FLOAT, TypeKind.LONG), /** Convert float to double */ - F2D(ClassFile.F2D, 1, Kind.CONVERT, TypeKind.FloatType, TypeKind.DoubleType), + F2D(ClassFile.F2D, 1, Kind.CONVERT, TypeKind.FLOAT, TypeKind.DOUBLE), /** Convert double to int */ - D2I(ClassFile.D2I, 1, Kind.CONVERT, TypeKind.DoubleType, TypeKind.IntType), + D2I(ClassFile.D2I, 1, Kind.CONVERT, TypeKind.DOUBLE, TypeKind.INT), /** Convert double to long */ - D2L(ClassFile.D2L, 1, Kind.CONVERT, TypeKind.DoubleType, TypeKind.LongType), + D2L(ClassFile.D2L, 1, Kind.CONVERT, TypeKind.DOUBLE, TypeKind.LONG), /** Convert double to float */ - D2F(ClassFile.D2F, 1, Kind.CONVERT, TypeKind.DoubleType, TypeKind.FloatType), + D2F(ClassFile.D2F, 1, Kind.CONVERT, TypeKind.DOUBLE, TypeKind.FLOAT), /** Convert int to byte */ - I2B(ClassFile.I2B, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.ByteType), + I2B(ClassFile.I2B, 1, Kind.CONVERT, TypeKind.INT, TypeKind.BYTE), /** Convert int to char */ - I2C(ClassFile.I2C, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.CharType), + I2C(ClassFile.I2C, 1, Kind.CONVERT, TypeKind.INT, TypeKind.CHAR), /** Convert int to short */ - I2S(ClassFile.I2S, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.ShortType), + I2S(ClassFile.I2S, 1, Kind.CONVERT, TypeKind.INT, TypeKind.SHORT), /** Compare long */ - LCMP(ClassFile.LCMP, 1, Kind.OPERATOR, TypeKind.LongType), + LCMP(ClassFile.LCMP, 1, Kind.OPERATOR, TypeKind.LONG), /** Compare float */ - FCMPL(ClassFile.FCMPL, 1, Kind.OPERATOR, TypeKind.FloatType), + FCMPL(ClassFile.FCMPL, 1, Kind.OPERATOR, TypeKind.FLOAT), /** Compare float */ - FCMPG(ClassFile.FCMPG, 1, Kind.OPERATOR, TypeKind.FloatType), + FCMPG(ClassFile.FCMPG, 1, Kind.OPERATOR, TypeKind.FLOAT), /** Compare double */ - DCMPL(ClassFile.DCMPL, 1, Kind.OPERATOR, TypeKind.DoubleType), + DCMPL(ClassFile.DCMPL, 1, Kind.OPERATOR, TypeKind.DOUBLE), /** Compare double */ - DCMPG(ClassFile.DCMPG, 1, Kind.OPERATOR, TypeKind.DoubleType), + DCMPG(ClassFile.DCMPG, 1, Kind.OPERATOR, TypeKind.DOUBLE), /** Branch if int comparison with zero succeeds */ - IFEQ(ClassFile.IFEQ, 3, Kind.BRANCH, TypeKind.IntType), + IFEQ(ClassFile.IFEQ, 3, Kind.BRANCH, TypeKind.INT), /** Branch if int comparison with zero succeeds */ - IFNE(ClassFile.IFNE, 3, Kind.BRANCH, TypeKind.IntType), + IFNE(ClassFile.IFNE, 3, Kind.BRANCH, TypeKind.INT), /** Branch if int comparison with zero succeeds */ - IFLT(ClassFile.IFLT, 3, Kind.BRANCH, TypeKind.IntType), + IFLT(ClassFile.IFLT, 3, Kind.BRANCH, TypeKind.INT), /** Branch if int comparison with zero succeeds */ - IFGE(ClassFile.IFGE, 3, Kind.BRANCH, TypeKind.IntType), + IFGE(ClassFile.IFGE, 3, Kind.BRANCH, TypeKind.INT), /** Branch if int comparison with zero succeeds */ - IFGT(ClassFile.IFGT, 3, Kind.BRANCH, TypeKind.IntType), + IFGT(ClassFile.IFGT, 3, Kind.BRANCH, TypeKind.INT), /** Branch if int comparison with zero succeeds */ - IFLE(ClassFile.IFLE, 3, Kind.BRANCH, TypeKind.IntType), + IFLE(ClassFile.IFLE, 3, Kind.BRANCH, TypeKind.INT), /** Branch if int comparison succeeds */ - IF_ICMPEQ(ClassFile.IF_ICMPEQ, 3, Kind.BRANCH, TypeKind.IntType), + IF_ICMPEQ(ClassFile.IF_ICMPEQ, 3, Kind.BRANCH, TypeKind.INT), /** Branch if int comparison succeeds */ - IF_ICMPNE(ClassFile.IF_ICMPNE, 3, Kind.BRANCH, TypeKind.IntType), + IF_ICMPNE(ClassFile.IF_ICMPNE, 3, Kind.BRANCH, TypeKind.INT), /** Branch if int comparison succeeds */ - IF_ICMPLT(ClassFile.IF_ICMPLT, 3, Kind.BRANCH, TypeKind.IntType), + IF_ICMPLT(ClassFile.IF_ICMPLT, 3, Kind.BRANCH, TypeKind.INT), /** Branch if int comparison succeeds */ - IF_ICMPGE(ClassFile.IF_ICMPGE, 3, Kind.BRANCH, TypeKind.IntType), + IF_ICMPGE(ClassFile.IF_ICMPGE, 3, Kind.BRANCH, TypeKind.INT), /** Branch if int comparison succeeds */ - IF_ICMPGT(ClassFile.IF_ICMPGT, 3, Kind.BRANCH, TypeKind.IntType), + IF_ICMPGT(ClassFile.IF_ICMPGT, 3, Kind.BRANCH, TypeKind.INT), /** Branch if int comparison succeeds */ - IF_ICMPLE(ClassFile.IF_ICMPLE, 3, Kind.BRANCH, TypeKind.IntType), + IF_ICMPLE(ClassFile.IF_ICMPLE, 3, Kind.BRANCH, TypeKind.INT), /** Branch if reference comparison succeeds */ - IF_ACMPEQ(ClassFile.IF_ACMPEQ, 3, Kind.BRANCH, TypeKind.ReferenceType), + IF_ACMPEQ(ClassFile.IF_ACMPEQ, 3, Kind.BRANCH, TypeKind.REFERENCE), /** Branch if reference comparison succeeds */ - IF_ACMPNE(ClassFile.IF_ACMPNE, 3, Kind.BRANCH, TypeKind.ReferenceType), + IF_ACMPNE(ClassFile.IF_ACMPNE, 3, Kind.BRANCH, TypeKind.REFERENCE), /** Branch always */ - GOTO(ClassFile.GOTO, 3, Kind.BRANCH, TypeKind.VoidType), + GOTO(ClassFile.GOTO, 3, Kind.BRANCH, TypeKind.VOID), /** * Jump subroutine is discontinued opcode @@ -564,22 +564,22 @@ public enum Opcode { LOOKUPSWITCH(ClassFile.LOOKUPSWITCH, -1, Kind.LOOKUP_SWITCH), /** Return int from method */ - IRETURN(ClassFile.IRETURN, 1, Kind.RETURN, TypeKind.IntType), + IRETURN(ClassFile.IRETURN, 1, Kind.RETURN, TypeKind.INT), /** Return long from method */ - LRETURN(ClassFile.LRETURN, 1, Kind.RETURN, TypeKind.LongType), + LRETURN(ClassFile.LRETURN, 1, Kind.RETURN, TypeKind.LONG), /** Return float from method */ - FRETURN(ClassFile.FRETURN, 1, Kind.RETURN, TypeKind.FloatType), + FRETURN(ClassFile.FRETURN, 1, Kind.RETURN, TypeKind.FLOAT), /** Return double from method */ - DRETURN(ClassFile.DRETURN, 1, Kind.RETURN, TypeKind.DoubleType), + DRETURN(ClassFile.DRETURN, 1, Kind.RETURN, TypeKind.DOUBLE), /** Return reference from method */ - ARETURN(ClassFile.ARETURN, 1, Kind.RETURN, TypeKind.ReferenceType), + ARETURN(ClassFile.ARETURN, 1, Kind.RETURN, TypeKind.REFERENCE), /** Return void from method */ - RETURN(ClassFile.RETURN, 1, Kind.RETURN, TypeKind.VoidType), + RETURN(ClassFile.RETURN, 1, Kind.RETURN, TypeKind.VOID), /** Get static field from class */ GETSTATIC(ClassFile.GETSTATIC, 3, Kind.FIELD_ACCESS), @@ -621,7 +621,7 @@ public enum Opcode { ANEWARRAY(ClassFile.ANEWARRAY, 3, Kind.NEW_REF_ARRAY), /** Get length of array */ - ARRAYLENGTH(ClassFile.ARRAYLENGTH, 1, Kind.OPERATOR, TypeKind.IntType), + ARRAYLENGTH(ClassFile.ARRAYLENGTH, 1, Kind.OPERATOR, TypeKind.INT), /** Throw exception or error */ ATHROW(ClassFile.ATHROW, 1, Kind.THROW_EXCEPTION), @@ -642,13 +642,13 @@ public enum Opcode { MULTIANEWARRAY(ClassFile.MULTIANEWARRAY, 4, Kind.NEW_MULTI_ARRAY), /** Branch if reference is null */ - IFNULL(ClassFile.IFNULL, 3, Kind.BRANCH, TypeKind.ReferenceType), + IFNULL(ClassFile.IFNULL, 3, Kind.BRANCH, TypeKind.REFERENCE), /** Branch if reference not null */ - IFNONNULL(ClassFile.IFNONNULL, 3, Kind.BRANCH, TypeKind.ReferenceType), + IFNONNULL(ClassFile.IFNONNULL, 3, Kind.BRANCH, TypeKind.REFERENCE), /** Branch always (wide index) */ - GOTO_W(ClassFile.GOTO_W, 5, Kind.BRANCH, TypeKind.VoidType), + GOTO_W(ClassFile.GOTO_W, 5, Kind.BRANCH, TypeKind.VOID), /** * Jump subroutine (wide index) is discontinued opcode @@ -657,34 +657,34 @@ public enum Opcode { JSR_W(ClassFile.JSR_W, 5, Kind.DISCONTINUED_JSR), /** Load int from local variable (wide index) */ - ILOAD_W((ClassFile.WIDE << 8) | ClassFile.ILOAD, 4, Kind.LOAD, TypeKind.IntType, -1), + ILOAD_W((ClassFile.WIDE << 8) | ClassFile.ILOAD, 4, Kind.LOAD, TypeKind.INT, -1), /** Load long from local variable (wide index) */ - LLOAD_W((ClassFile.WIDE << 8) | ClassFile.LLOAD, 4, Kind.LOAD, TypeKind.LongType, -1), + LLOAD_W((ClassFile.WIDE << 8) | ClassFile.LLOAD, 4, Kind.LOAD, TypeKind.LONG, -1), /** Load float from local variable (wide index) */ - FLOAD_W((ClassFile.WIDE << 8) | ClassFile.FLOAD, 4, Kind.LOAD, TypeKind.FloatType, -1), + FLOAD_W((ClassFile.WIDE << 8) | ClassFile.FLOAD, 4, Kind.LOAD, TypeKind.FLOAT, -1), /** Load double from local variable (wide index) */ - DLOAD_W((ClassFile.WIDE << 8) | ClassFile.DLOAD, 4, Kind.LOAD, TypeKind.DoubleType, -1), + DLOAD_W((ClassFile.WIDE << 8) | ClassFile.DLOAD, 4, Kind.LOAD, TypeKind.DOUBLE, -1), /** Load reference from local variable (wide index) */ - ALOAD_W((ClassFile.WIDE << 8) | ClassFile.ALOAD, 4, Kind.LOAD, TypeKind.ReferenceType, -1), + ALOAD_W((ClassFile.WIDE << 8) | ClassFile.ALOAD, 4, Kind.LOAD, TypeKind.REFERENCE, -1), /** Store int into local variable (wide index) */ - ISTORE_W((ClassFile.WIDE << 8) | ClassFile.ISTORE, 4, Kind.STORE, TypeKind.IntType, -1), + ISTORE_W((ClassFile.WIDE << 8) | ClassFile.ISTORE, 4, Kind.STORE, TypeKind.INT, -1), /** Store long into local variable (wide index) */ - LSTORE_W((ClassFile.WIDE << 8) | ClassFile.LSTORE, 4, Kind.STORE, TypeKind.LongType, -1), + LSTORE_W((ClassFile.WIDE << 8) | ClassFile.LSTORE, 4, Kind.STORE, TypeKind.LONG, -1), /** Store float into local variable (wide index) */ - FSTORE_W((ClassFile.WIDE << 8) | ClassFile.FSTORE, 4, Kind.STORE, TypeKind.FloatType, -1), + FSTORE_W((ClassFile.WIDE << 8) | ClassFile.FSTORE, 4, Kind.STORE, TypeKind.FLOAT, -1), /** Store double into local variable (wide index) */ - DSTORE_W((ClassFile.WIDE << 8) | ClassFile.DSTORE, 4, Kind.STORE, TypeKind.DoubleType, -1), + DSTORE_W((ClassFile.WIDE << 8) | ClassFile.DSTORE, 4, Kind.STORE, TypeKind.DOUBLE, -1), /** Store reference into local variable (wide index) */ - ASTORE_W((ClassFile.WIDE << 8) | ClassFile.ASTORE, 4, Kind.STORE, TypeKind.ReferenceType, -1), + ASTORE_W((ClassFile.WIDE << 8) | ClassFile.ASTORE, 4, Kind.STORE, TypeKind.REFERENCE, -1), /** * Return from subroutine (wide index) is discontinued opcode @@ -693,7 +693,7 @@ public enum Opcode { RET_W((ClassFile.WIDE << 8) | ClassFile.RET, 4, Kind.DISCONTINUED_RET), /** Increment local variable by constant (wide index) */ - IINC_W((ClassFile.WIDE << 8) | ClassFile.IINC, 6, Kind.INCREMENT, TypeKind.IntType, -1); + IINC_W((ClassFile.WIDE << 8) | ClassFile.IINC, 6, Kind.INCREMENT, TypeKind.INT, -1); /** * Kinds of opcodes. diff --git a/src/java.base/share/classes/java/lang/classfile/TypeKind.java b/src/java.base/share/classes/java/lang/classfile/TypeKind.java index 5ba566b3d0672..fdd8826f4eafd 100644 --- a/src/java.base/share/classes/java/lang/classfile/TypeKind.java +++ b/src/java.base/share/classes/java/lang/classfile/TypeKind.java @@ -25,107 +25,197 @@ package java.lang.classfile; +import java.lang.classfile.instruction.DiscontinuedInstruction; +import java.lang.constant.ClassDesc; +import java.lang.constant.ConstantDescs; import java.lang.invoke.TypeDescriptor; import jdk.internal.javac.PreviewFeature; +import jdk.internal.vm.annotation.Stable; /** - * Describes the types that can be part of a field or method descriptor. + * Describes the data types Java Virtual Machine operates on. + * This omits {@code returnAddress} (JVMS {@jvms 2.3.3}), + * which is only used by discontinued {@link + * DiscontinuedInstruction.JsrInstruction jsr} and {@link + * DiscontinuedInstruction.RetInstruction ret} instructions, + * and includes {@link #VOID void} (JVMS {@jvms 4.3.3}), which + * appears as a method return type. * + *

Computational Type

+ * In the {@code class} file format, local variables (JVMS {@jvms 2.6.1}), + * and the operand stack (JVMS {@jvms 2.6.2}) of the Java Virtual Machine, + * {@link #BOOLEAN boolean}, {@link #BYTE byte}, {@link #CHAR char}, + * {@link #SHORT short} types do not exist and are {@linkplain + * #asLoadable() represented} by the {@link #INT int} computational type. + * {@link #INT int}, {@link #FLOAT float}, {@link #REFERENCE reference}, + * {@code returnAddress}, {@link #LONG long}, and {@link #DOUBLE doule} + * are the computational types of the Java Virtual Machine. + * + * @jvms 2.2 Data Types + * @jvms 2.11.1 Types and the Java Virtual Machine * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public enum TypeKind { - /** the primitive type byte */ - ByteType("byte", "B", 8), - /** the primitive type short */ - ShortType("short", "S", 9), - /** the primitive type int */ - IntType("int", "I", 10), - /** the primitive type float */ - FloatType("float", "F", 6), - /** the primitive type long */ - LongType("long", "J", 11), - /** the primitive type double */ - DoubleType("double", "D", 7), - /** a reference type */ - ReferenceType("reference type", "L", -1), - /** the primitive type char */ - CharType("char", "C", 5), - /** the primitive type boolean */ - BooleanType("boolean", "Z", 4), - /** void */ - VoidType("void", "V", -1); + // Elements are grouped so frequently used switch ranges such as + // primitives (boolean - double) and computational (int - void) are together. + // This also follows the order of typed opcodes + // Begin primitive types + /** + * The primitive type {@code boolean}. Its {@linkplain ##computational-type + * computational type} is {@link #INT int}. {@code 0} represents {@code false}, + * and {@code 1} represents {@code true}. It is zero-extended to an {@code int} + * when loaded onto the operand stack and narrowed by taking the bitwise AND + * with {@code 1} when stored. + * + * @jvms 2.3.4 The {@code boolean} Type + */ + BOOLEAN(1, 4), + /** + * The primitive type {@code byte}. Its {@linkplain ##computational-type + * computational type} is {@link #INT int}. It is sign-extended to an + * {@code int} when loaded onto the operand stack and truncated when + * stored. + */ + BYTE(1, 8), + /** + * The primitive type {@code char}. Its {@linkplain ##computational-type + * computational type} is {@link #INT int}. It is zero-extended to an + * {@code int} when loaded onto the operand stack and truncated when + * stored. + */ + CHAR(1, 5), + /** + * The primitive type {@code short}. Its {@linkplain ##computational-type + * computational type} is {@link #INT int}. It is sign-extended to an + * {@code int} when loaded onto the operand stack and truncated when + * stored. + */ + SHORT(1, 9), + // Begin computational types + /** + * The primitive type {@code int}. + */ + INT(1, 10), + /** + * The primitive type {@code long}. It is of {@linkplain #slotSize() category} 2. + */ + LONG(2, 11), + /** + * The primitive type {@code float}. + */ + FLOAT(1, 6), + /** + * The primitive type {@code double}. It is of {@linkplain #slotSize() category} 2. + */ + DOUBLE(2, 7), + // End primitive types + /** + * A reference type. + * @jvms 2.4 Reference Types and Values + */ + REFERENCE(1, -1), + /** + * The {@code void} type, for absence of a value. While this is not a data type, + * this can be a method return type indicating no change in {@linkplain #slotSize() + * operand stack depth}. + * + * @jvms 4.3.3 Method Descriptors + */ + VOID(0, -1); + // End computational types - private final String name; - private final String descriptor; + private @Stable ClassDesc upperBound; + private final int slots; private final int newarrayCode; - /** {@return the human-readable name corresponding to this type} */ - public String typeName() { return name; } + TypeKind(int slots, int newarrayCode) { + this.slots = slots; + this.newarrayCode = newarrayCode; + } - /** {@return the field descriptor character corresponding to this type} */ - public String descriptor() { return descriptor; } + /** + * {@return the most specific upper bound field descriptor that can store any value + * of this type} This is the primitive class descriptor for primitive types and + * {@link #VOID void} and {@link ConstantDescs#CD_Object Object} descriptor for + * {@link #REFERENCE reference}. + */ + public ClassDesc upperBound() { + var upper = this.upperBound; + if (upper == null) + return this.upperBound = fetchUpperBound(); + return upper; + } + + private ClassDesc fetchUpperBound() { + return switch (this) { + case BOOLEAN -> ConstantDescs.CD_boolean; + case BYTE -> ConstantDescs.CD_byte; + case CHAR -> ConstantDescs.CD_char; + case SHORT -> ConstantDescs.CD_short; + case INT -> ConstantDescs.CD_int; + case FLOAT -> ConstantDescs.CD_float; + case LONG -> ConstantDescs.CD_long; + case DOUBLE -> ConstantDescs.CD_double; + case REFERENCE -> ConstantDescs.CD_Object; + case VOID -> ConstantDescs.CD_void; + }; + } /** - * {@return the code used by the {@code newarray} opcode corresponding to this type} + * {@return the code used by the {@link Opcode#NEWARRAY newarray} instruction to create an array + * of this component type, or {@code -1} if this type is not supported by {@code newarray}} * @since 23 + * @jvms 6.5.newarray newarray */ public int newarrayCode() { return newarrayCode; } /** - * {@return the number of local variable slots consumed by this type} + * {@return the number of local variable index or operand stack depth consumed by this type} + * This is also the category of this type for instructions operating on the operand stack without + * regard to type (JVMS {@jvms 2.11.1}), such as {@link Opcode#POP pop} versus {@link Opcode#POP2 + * pop2}. + * @jvms 2.6.1 Local Variables + * @jvms 2.6.2 Operand Stacks */ public int slotSize() { - return switch (this) { - case VoidType -> 0; - case LongType, DoubleType -> 2; - default -> 1; - }; + return this.slots; } /** - * Erase this type kind to the type which will be used for xLOAD, xSTORE, - * and xRETURN bytecodes - * @return the erased type kind + * {@return the {@linkplain ##computational-type computational type} for this type, or {@link #VOID void} + * for {@code void}} */ public TypeKind asLoadable() { - return switch (this) { - case BooleanType, ByteType, CharType, ShortType -> TypeKind.IntType; - default -> this; - }; - } - - TypeKind(String name, String descriptor, int newarrayCode) { - this.name = name; - this.descriptor = descriptor; - this.newarrayCode = newarrayCode; + return ordinal() < 4 ? INT : this; } /** - * {@return the type kind associated with the array type described by the - * array code used as an operand to {@code newarray}} + * {@return the component type described by the array code used as an operand to {@link Opcode#NEWARRAY + * newarray}} * @param newarrayCode the operand of the {@code newarray} instruction * @throws IllegalArgumentException if the code is invalid * @since 23 + * @jvms 6.5.newarray newarray */ public static TypeKind fromNewarrayCode(int newarrayCode) { return switch (newarrayCode) { - case 4 -> TypeKind.BooleanType; - case 5 -> TypeKind.CharType; - case 6 -> TypeKind.FloatType; - case 7 -> TypeKind.DoubleType; - case 8 -> TypeKind.ByteType; - case 9 -> TypeKind.ShortType; - case 10 -> TypeKind.IntType; - case 11 -> TypeKind.LongType; + case 4 -> BOOLEAN; + case 5 -> CHAR; + case 6 -> FLOAT; + case 7 -> DOUBLE; + case 8 -> BYTE; + case 9 -> SHORT; + case 10 -> INT; + case 11 -> LONG; default -> throw new IllegalArgumentException("Bad newarray code: " + newarrayCode); }; } /** - * {@return the type kind associated with the specified field descriptor} + * {@return the type associated with the specified field descriptor} * @param s the field descriptor * @throws IllegalArgumentException only if the descriptor is not valid */ @@ -134,27 +224,27 @@ public static TypeKind fromDescriptor(CharSequence s) { throw new IllegalArgumentException("Empty descriptor"); } return switch (s.charAt(0)) { - case '[', 'L' -> TypeKind.ReferenceType; - case 'B' -> TypeKind.ByteType; - case 'C' -> TypeKind.CharType; - case 'Z' -> TypeKind.BooleanType; - case 'S' -> TypeKind.ShortType; - case 'I' -> TypeKind.IntType; - case 'F' -> TypeKind.FloatType; - case 'J' -> TypeKind.LongType; - case 'D' -> TypeKind.DoubleType; - case 'V' -> TypeKind.VoidType; + case '[', 'L' -> REFERENCE; + case 'B' -> BYTE; + case 'C' -> CHAR; + case 'Z' -> BOOLEAN; + case 'S' -> SHORT; + case 'I' -> INT; + case 'F' -> FLOAT; + case 'J' -> LONG; + case 'D' -> DOUBLE; + case 'V' -> VOID; default -> throw new IllegalArgumentException("Bad type: " + s); }; } /** - * {@return the type kind associated with the specified field descriptor} + * {@return the type associated with the specified field descriptor} * @param descriptor the field descriptor */ public static TypeKind from(TypeDescriptor.OfField descriptor) { return descriptor.isPrimitive() // implicit null check ? fromDescriptor(descriptor.descriptorString()) - : TypeKind.ReferenceType; + : REFERENCE; } } diff --git a/src/java.base/share/classes/java/lang/classfile/components/snippet-files/PackageSnippets.java b/src/java.base/share/classes/java/lang/classfile/components/snippet-files/PackageSnippets.java index b53e921381333..2e7fb121a373b 100644 --- a/src/java.base/share/classes/java/lang/classfile/components/snippet-files/PackageSnippets.java +++ b/src/java.base/share/classes/java/lang/classfile/components/snippet-files/PackageSnippets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -181,7 +181,7 @@ byte[] classInstrumentation(ClassModel target, ClassModel instrumentor, Predicat var storeStack = new ArrayDeque(); int slot = 0; if (!mm.flags().has(AccessFlag.STATIC)) - storeStack.push(StoreInstruction.of(TypeKind.ReferenceType, slot++)); + storeStack.push(StoreInstruction.of(TypeKind.REFERENCE, slot++)); for (var pt : mm.methodTypeSymbol().parameterList()) { var tk = TypeKind.from(pt); storeStack.push(StoreInstruction.of(tk, slot)); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java index caa36c79f74c5..391dcf021eb4b 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,6 @@ public sealed interface DoubleEntry */ @Override default TypeKind typeKind() { - return TypeKind.DoubleType; + return TypeKind.DOUBLE; } } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java index df7c26c3524ee..d84cc903ea5ea 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,6 @@ public sealed interface FloatEntry */ @Override default TypeKind typeKind() { - return TypeKind.FloatType; + return TypeKind.FLOAT; } } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java index c9ddf4d3c52bf..807ce188a6acb 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,6 @@ public sealed interface IntegerEntry */ @Override default TypeKind typeKind() { - return TypeKind.IntType; + return TypeKind.INT; } } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java index 4226e2c16c119..6ae8e68787eaf 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,6 @@ public sealed interface LoadableConstantEntry extends PoolEntry * {@return the type of the constant} */ default TypeKind typeKind() { - return TypeKind.ReferenceType; + return TypeKind.REFERENCE; } } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java index b84ea055a7dc5..975df03f04343 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,6 @@ public sealed interface LongEntry */ @Override default TypeKind typeKind() { - return TypeKind.LongType; + return TypeKind.LONG; } } diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ArrayLoadInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ArrayLoadInstruction.java index 3502e87edda25..e773d2da2ccae 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ArrayLoadInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ArrayLoadInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,9 @@ public sealed interface ArrayLoadInstruction extends Instruction permits AbstractInstruction.UnboundArrayLoadInstruction { /** - * {@return the component type of the array} + * {@return the component type of the array} The {@link TypeKind#BYTE byte} + * type load instruction {@link Opcode#BALOAD baload} also operates on + * {@link TypeKind#BOOLEAN boolean} arrays. */ TypeKind typeKind(); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java index a85b994181aca..9b9ec6018d1f2 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,9 @@ public sealed interface ArrayStoreInstruction extends Instruction permits AbstractInstruction.UnboundArrayStoreInstruction { /** - * {@return the component type of the array} + * {@return the component type of the array} The {@link TypeKind#BYTE byte} + * type store instruction {@link Opcode#BASTORE bastore} also operates on + * {@link TypeKind#BOOLEAN boolean} arrays. */ TypeKind typeKind(); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ConstantInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ConstantInstruction.java index a7ba9e2a6a10f..022c45fdeef4d 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ConstantInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ConstantInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import java.lang.classfile.TypeKind; import java.lang.classfile.constantpool.LoadableConstantEntry; import jdk.internal.classfile.impl.AbstractInstruction; +import jdk.internal.classfile.impl.BytecodeHelpers; import jdk.internal.classfile.impl.Util; import jdk.internal.javac.PreviewFeature; @@ -144,16 +145,21 @@ static IntrinsicConstantInstruction ofIntrinsic(Opcode op) { /** * {@return an argument constant instruction} * - * @param op the opcode for the specific type of intrinsic constant instruction, - * which must be of kind {@link Opcode.Kind#CONSTANT} + * @param op the opcode for the specific type of argument constant instruction, + * which must be {@link Opcode#BIPUSH} or {@link Opcode#SIPUSH} * @param value the constant value * @throws IllegalArgumentException if the opcode is not {@link Opcode#BIPUSH} - * or {@link Opcode#SIPUSH} + * or {@link Opcode#SIPUSH}, or if the constant value is out of range + * for the opcode */ static ArgumentConstantInstruction ofArgument(Opcode op, int value) { - Util.checkKind(op, Opcode.Kind.CONSTANT); - if (op != Opcode.BIPUSH && op != Opcode.SIPUSH) + if (op == Opcode.BIPUSH) { + BytecodeHelpers.validateBipush(value); + } else if (op == Opcode.SIPUSH) { + BytecodeHelpers.validateSipush(value); + } else { throw new IllegalArgumentException(String.format("Wrong opcode specified; found %s, expected BIPUSH or SIPUSH", op)); + } return new AbstractInstruction.UnboundArgumentConstantInstruction(op, value); } diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java index ae3f465402d0f..cbc8f2068a8ad 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java @@ -57,7 +57,7 @@ public sealed interface NewPrimitiveArrayInstruction extends Instruction static NewPrimitiveArrayInstruction of(TypeKind typeKind) { // Implicit null-check: if (typeKind.newarrayCode() < 0) { - throw new IllegalArgumentException("Illegal component type: " + typeKind.typeName()); + throw new IllegalArgumentException("Illegal component type for primitive array: " + typeKind.name()); } return new AbstractInstruction.UnboundNewPrimitiveArrayInstruction(typeKind); } diff --git a/src/java.base/share/classes/java/lang/classfile/snippet-files/PackageSnippets.java b/src/java.base/share/classes/java/lang/classfile/snippet-files/PackageSnippets.java index b80c1c8328411..46e057210ac74 100644 --- a/src/java.base/share/classes/java/lang/classfile/snippet-files/PackageSnippets.java +++ b/src/java.base/share/classes/java/lang/classfile/snippet-files/PackageSnippets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -381,7 +381,7 @@ byte[] classInstrumentation(ClassModel target, ClassModel instrumentor, Predicat var storeStack = new ArrayDeque(); int slot = 0; if (!mm.flags().has(AccessFlag.STATIC)) - storeStack.push(StoreInstruction.of(TypeKind.ReferenceType, slot++)); + storeStack.push(StoreInstruction.of(TypeKind.REFERENCE, slot++)); for (var pt : mm.methodTypeSymbol().parameterList()) { var tk = TypeKind.from(pt); storeStack.push(StoreInstruction.of(tk, slot)); diff --git a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 17cf699c536c2..0636c2ddea5e7 100644 --- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -368,9 +368,9 @@ private void emitBoxing(CodeBuilder cob, TypeKind tk) { */ private void emitUnboxing(CodeBuilder cob, TypeKind target) { switch (target) { - case BooleanType -> emitReferenceCast(cob, Boolean.class, null); - case CharType -> emitReferenceCast(cob, Character.class, null); - case ByteType, DoubleType, FloatType, IntType, LongType, ShortType -> + case BOOLEAN -> emitReferenceCast(cob, Boolean.class, null); + case CHAR -> emitReferenceCast(cob, Character.class, null); + case BYTE, DOUBLE, FLOAT, INT, LONG, SHORT -> emitReferenceCast(cob, Number.class, null); default -> {} } @@ -443,7 +443,7 @@ else if (PROFILE_LEVEL > 0) } if (writeBack != null) { cob.dup(); - emitStoreInsn(cob, TypeKind.ReferenceType, writeBack.index()); + emitStoreInsn(cob, TypeKind.REFERENCE, writeBack.index()); } } @@ -901,7 +901,7 @@ private Name emitSelectAlternative(CodeBuilder cob, Name selectAlternativeName, // invoke selectAlternativeName.arguments[1] Class[] preForkClasses = localClasses.clone(); emitPushArgument(cob, selectAlternativeName, 1); // get 2nd argument of selectAlternative - emitStoreInsn(cob, TypeKind.ReferenceType, receiver.index()); // store the MH in the receiver slot + emitStoreInsn(cob, TypeKind.REFERENCE, receiver.index()); // store the MH in the receiver slot emitStaticInvoke(cob, invokeBasicName); // goto L_done @@ -913,7 +913,7 @@ private Name emitSelectAlternative(CodeBuilder cob, Name selectAlternativeName, // invoke selectAlternativeName.arguments[2] System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length); emitPushArgument(cob, selectAlternativeName, 2); // get 3rd argument of selectAlternative - emitStoreInsn(cob, TypeKind.ReferenceType, receiver.index()); // store the MH in the receiver slot + emitStoreInsn(cob, TypeKind.REFERENCE, receiver.index()); // store the MH in the receiver slot emitStaticInvoke(cob, invokeBasicName); // L_done: @@ -1151,7 +1151,7 @@ private Name emitTableSwitch(CodeBuilder cob, int pos, int numCases) { emitPushArgument(cob, invoker, 2); // push cases cob.getfield(CD_CasesHolder, "cases", CD_MethodHandle_array); int casesLocal = extendLocalsMap(new Class[] { MethodHandle[].class }); - emitStoreInsn(cob, TypeKind.ReferenceType, casesLocal); + emitStoreInsn(cob, TypeKind.REFERENCE, casesLocal); Label endLabel = cob.newLabel(); Label defaultLabel = cob.newLabel(); @@ -1172,7 +1172,7 @@ private Name emitTableSwitch(CodeBuilder cob, int pos, int numCases) { for (int i = 0; i < numCases; i++) { cob.labelBinding(cases.get(i).target()); // Load the particular case: - emitLoadInsn(cob, TypeKind.ReferenceType, casesLocal); + emitLoadInsn(cob, TypeKind.REFERENCE, casesLocal); cob.loadConstant(i); cob.aaload(); @@ -1311,7 +1311,7 @@ private Name emitLoop(CodeBuilder cob, int pos) { // PREINIT: emitPushArgument(cob, MethodHandleImpl.LoopClauses.class, invoker.arguments[1]); cob.getfield(CD_LoopClauses, "clauses", CD_MethodHandle_array2); - emitStoreInsn(cob, TypeKind.ReferenceType, clauseDataIndex); + emitStoreInsn(cob, TypeKind.REFERENCE, clauseDataIndex); // INIT: for (int c = 0, state = 0; c < nClauses; ++c) { @@ -1398,7 +1398,7 @@ private void emitLoopHandleInvoke(CodeBuilder cob, Name holder, int handles, int } private void emitPushClauseArray(CodeBuilder cob, int clauseDataSlot, int which) { - emitLoadInsn(cob, TypeKind.ReferenceType, clauseDataSlot); + emitLoadInsn(cob, TypeKind.REFERENCE, clauseDataSlot); cob.loadConstant(which - 1); cob.aaload(); } @@ -1497,7 +1497,7 @@ private void emitPrimCast(CodeBuilder cob, TypeKind from, TypeKind to) { // long - l2i,i2b l2i,i2s l2i,i2c l2i <-> l2f l2d // float - f2i,i2b f2i,i2s f2i,i2c f2i f2l <-> f2d // double - d2i,i2b d2i,i2s d2i,i2c d2i d2l d2f <-> - if (from != to && from != TypeKind.BooleanType) try { + if (from != to && from != TypeKind.BOOLEAN) try { cob.conversion(from, to); } catch (IllegalArgumentException e) { throw new IllegalStateException("unhandled prim cast: " + from + "2" + to); diff --git a/src/java.base/share/classes/java/lang/invoke/LambdaForm.java b/src/java.base/share/classes/java/lang/invoke/LambdaForm.java index 3f6e521b27bd9..342cbbe77e5c0 100644 --- a/src/java.base/share/classes/java/lang/invoke/LambdaForm.java +++ b/src/java.base/share/classes/java/lang/invoke/LambdaForm.java @@ -138,12 +138,12 @@ class LambdaForm { public static final int VOID_RESULT = -1, LAST_RESULT = -2; enum BasicType { - L_TYPE('L', Object.class, Wrapper.OBJECT, TypeKind.ReferenceType), // all reference types - I_TYPE('I', int.class, Wrapper.INT, TypeKind.IntType), - J_TYPE('J', long.class, Wrapper.LONG, TypeKind.LongType), - F_TYPE('F', float.class, Wrapper.FLOAT, TypeKind.FloatType), - D_TYPE('D', double.class, Wrapper.DOUBLE, TypeKind.DoubleType), // all primitive types - V_TYPE('V', void.class, Wrapper.VOID, TypeKind.VoidType); // not valid in all contexts + L_TYPE('L', Object.class, Wrapper.OBJECT, TypeKind.REFERENCE), // all reference types + I_TYPE('I', int.class, Wrapper.INT, TypeKind.INT), + J_TYPE('J', long.class, Wrapper.LONG, TypeKind.LONG), + F_TYPE('F', float.class, Wrapper.FLOAT, TypeKind.FLOAT), + D_TYPE('D', double.class, Wrapper.DOUBLE, TypeKind.DOUBLE), // all primitive types + V_TYPE('V', void.class, Wrapper.VOID, TypeKind.VOID); // not valid in all contexts static final @Stable BasicType[] ALL_TYPES = BasicType.values(); static final @Stable BasicType[] ARG_TYPES = Arrays.copyOf(ALL_TYPES, ALL_TYPES.length-1); diff --git a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index 870d4c063ec2e..44a4ef7b02029 100644 --- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -49,8 +49,6 @@ import java.lang.constant.MethodTypeDesc; import java.lang.invoke.MethodHandles.Lookup; import java.lang.ref.SoftReference; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -1419,11 +1417,11 @@ public void accept(CodeBuilder cb) { // Compute parameter variable slots int paramCount = concatArgs.parameterCount(), thisSlot = cb.receiverSlot(), - lengthSlot = cb.allocateLocal(TypeKind.IntType), - coderSlot = cb.allocateLocal(TypeKind.ByteType), - bufSlot = cb.allocateLocal(TypeKind.ReferenceType), - constantsSlot = cb.allocateLocal(TypeKind.ReferenceType), - suffixSlot = cb.allocateLocal(TypeKind.ReferenceType); + lengthSlot = cb.allocateLocal(TypeKind.INT), + coderSlot = cb.allocateLocal(TypeKind.BYTE), + bufSlot = cb.allocateLocal(TypeKind.REFERENCE), + constantsSlot = cb.allocateLocal(TypeKind.REFERENCE), + suffixSlot = cb.allocateLocal(TypeKind.REFERENCE); /* * Types other than int/long/char/boolean require local variables to store the result of stringOf. @@ -1447,7 +1445,7 @@ public void accept(CodeBuilder cb) { } else { methodTypeDesc = MTD_String_Object; } - stringSlots[i] = cb.allocateLocal(TypeKind.ReferenceType); + stringSlots[i] = cb.allocateLocal(TypeKind.REFERENCE); cb.loadLocal(TypeKind.from(cl), cb.parameterSlot(i)) .invokestatic(CD_StringConcatHelper, "stringOf", methodTypeDesc) .astore(stringSlots[i]); @@ -1464,7 +1462,7 @@ public void accept(CodeBuilder cb) { var cl = concatArgs.parameterType(i); if (maybeUTF16(cl)) { if (cl == char.class) { - cb.loadLocal(TypeKind.CharType, cb.parameterSlot(i)); + cb.loadLocal(TypeKind.CHAR, cb.parameterSlot(i)); } else { cb.aload(stringSlots[i]); } @@ -1531,7 +1529,7 @@ public void accept(CodeBuilder cb) { var kind = TypeKind.from(cl); if (needStringOf(cl)) { paramSlot = stringSlots[i]; - kind = TypeKind.ReferenceType; + kind = TypeKind.REFERENCE; } cb.loadLocal(kind, paramSlot); } @@ -1682,7 +1680,7 @@ public void accept(CodeBuilder cb) { } else if (cl == CD_char) { methodTypeDesc = PREPEND_char; } else { - kind = TypeKind.ReferenceType; + kind = TypeKind.REFERENCE; methodTypeDesc = PREPEND_String; } diff --git a/src/java.base/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java b/src/java.base/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java index 7a1419f03b109..83fefe07d5150 100644 --- a/src/java.base/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java +++ b/src/java.base/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java @@ -69,14 +69,14 @@ private static MethodRefEntry unbox(ClassDesc owner, String methodName, ClassDes } private static TypeKind primitiveTypeKindFromClass(Class type) { - if (type == Integer.class) return TypeKind.IntType; - if (type == Long.class) return TypeKind.LongType; - if (type == Boolean.class) return TypeKind.BooleanType; - if (type == Short.class) return TypeKind.ShortType; - if (type == Byte.class) return TypeKind.ByteType; - if (type == Character.class) return TypeKind.CharType; - if (type == Float.class) return TypeKind.FloatType; - if (type == Double.class) return TypeKind.DoubleType; + if (type == Integer.class) return TypeKind.INT; + if (type == Long.class) return TypeKind.LONG; + if (type == Boolean.class) return TypeKind.BOOLEAN; + if (type == Short.class) return TypeKind.SHORT; + if (type == Byte.class) return TypeKind.BYTE; + if (type == Character.class) return TypeKind.CHAR; + if (type == Float.class) return TypeKind.FLOAT; + if (type == Double.class) return TypeKind.DOUBLE; return null; } @@ -94,27 +94,27 @@ static void widen(CodeBuilder cob, TypeKind ws, TypeKind wt) { static void box(CodeBuilder cob, TypeKind tk) { switch (tk) { - case BooleanType -> cob.invokestatic(BoxHolder.BOX_BOOLEAN); - case ByteType -> cob.invokestatic(BoxHolder.BOX_BYTE); - case CharType -> cob.invokestatic(BoxHolder.BOX_CHAR); - case DoubleType -> cob.invokestatic(BoxHolder.BOX_DOUBLE); - case FloatType -> cob.invokestatic(BoxHolder.BOX_FLOAT); - case IntType -> cob.invokestatic(BoxHolder.BOX_INT); - case LongType -> cob.invokestatic(BoxHolder.BOX_LONG); - case ShortType -> cob.invokestatic(BoxHolder.BOX_SHORT); + case BOOLEAN -> cob.invokestatic(BoxHolder.BOX_BOOLEAN); + case BYTE -> cob.invokestatic(BoxHolder.BOX_BYTE); + case CHAR -> cob.invokestatic(BoxHolder.BOX_CHAR); + case DOUBLE -> cob.invokestatic(BoxHolder.BOX_DOUBLE); + case FLOAT -> cob.invokestatic(BoxHolder.BOX_FLOAT); + case INT -> cob.invokestatic(BoxHolder.BOX_INT); + case LONG -> cob.invokestatic(BoxHolder.BOX_LONG); + case SHORT -> cob.invokestatic(BoxHolder.BOX_SHORT); } } static void unbox(CodeBuilder cob, TypeKind to) { switch (to) { - case BooleanType -> cob.invokevirtual(BoxHolder.UNBOX_BOOLEAN); - case ByteType -> cob.invokevirtual(BoxHolder.UNBOX_BYTE); - case CharType -> cob.invokevirtual(BoxHolder.UNBOX_CHAR); - case DoubleType -> cob.invokevirtual(BoxHolder.UNBOX_DOUBLE); - case FloatType -> cob.invokevirtual(BoxHolder.UNBOX_FLOAT); - case IntType -> cob.invokevirtual(BoxHolder.UNBOX_INT); - case LongType -> cob.invokevirtual(BoxHolder.UNBOX_LONG); - case ShortType -> cob.invokevirtual(BoxHolder.UNBOX_SHORT); + case BOOLEAN -> cob.invokevirtual(BoxHolder.UNBOX_BOOLEAN); + case BYTE -> cob.invokevirtual(BoxHolder.UNBOX_BYTE); + case CHAR -> cob.invokevirtual(BoxHolder.UNBOX_CHAR); + case DOUBLE -> cob.invokevirtual(BoxHolder.UNBOX_DOUBLE); + case FLOAT -> cob.invokevirtual(BoxHolder.UNBOX_FLOAT); + case INT -> cob.invokevirtual(BoxHolder.UNBOX_INT); + case LONG -> cob.invokevirtual(BoxHolder.UNBOX_LONG); + case SHORT -> cob.invokevirtual(BoxHolder.UNBOX_SHORT); } } diff --git a/src/java.base/share/classes/java/text/MessageFormat.java b/src/java.base/share/classes/java/text/MessageFormat.java index b2dd7a51251ae..58872834567d5 100644 --- a/src/java.base/share/classes/java/text/MessageFormat.java +++ b/src/java.base/share/classes/java/text/MessageFormat.java @@ -692,7 +692,10 @@ private void applyPatternImpl(String pattern) { * represents the current state of this {@code MessageFormat}} * * The string is constructed from internal information and therefore - * does not necessarily equal the previously applied pattern. + * does not necessarily equal the previously applied pattern. The order of + * {@code FormatStyle} matching is not guaranteed. That is, a {@code + * FormatStyle} produced may not be equivalent to the corresponding style passed, + * in the instance that multiple styles are equivalent. * * @implSpec The implementation in {@link MessageFormat} returns a * string that, when passed to a {@code MessageFormat()} constructor diff --git a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java index 2de1d17e7c18c..95ac1b2e46fc2 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java @@ -277,6 +277,40 @@ private static void signalNextIfShared(Node h) { } } + /** + * Repeatedly invokes acquire, if its execution throws an Error or a Runtime Exception, + * using an Unsafe.park-based backoff + * @param node which to reacquire + * @param arg the acquire argument + */ + private final void reacquire(Node node, long arg) { + try { + acquire(node, arg, false, false, false, 0L); + } catch (Error | RuntimeException firstEx) { + // While we currently do not emit an JFR events in this situation, mainly + // because the conditions under which this happens are such that it + // cannot be presumed to be possible to actually allocate an event, and + // using a preconstructed one would have limited value in serviceability. + // Having said that, the following place would be the more appropriate + // place to put such logic: + // emit JFR event + + for (long nanos = 1L;;) { + U.park(false, nanos); // must use Unsafe park to sleep + if (nanos < 1L << 30) // max about 1 second + nanos <<= 1; + + try { + acquire(node, arg, false, false, false, 0L); + } catch (Error | RuntimeException ignored) { + continue; + } + + throw firstEx; + } + } + } + /** * Main acquire method, invoked by all exported acquire methods. * @@ -1299,7 +1333,7 @@ else if ((node.status & COND) != 0) { } LockSupport.setCurrentBlocker(null); node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (interrupted) Thread.currentThread().interrupt(); } @@ -1346,7 +1380,7 @@ public final void await() throws InterruptedException { } LockSupport.setCurrentBlocker(null); node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (interrupted) { if (cancelled) { unlinkCancelledWaiters(node); @@ -1389,7 +1423,7 @@ public final long awaitNanos(long nanosTimeout) LockSupport.parkNanos(this, nanos); } node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (cancelled) { unlinkCancelledWaiters(node); if (interrupted) @@ -1433,7 +1467,7 @@ public final boolean awaitUntil(Date deadline) LockSupport.parkUntil(this, abstime); } node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (cancelled) { unlinkCancelledWaiters(node); if (interrupted) @@ -1478,7 +1512,7 @@ public final boolean await(long time, TimeUnit unit) LockSupport.parkNanos(this, nanos); } node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (cancelled) { unlinkCancelledWaiters(node); if (interrupted) diff --git a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java index 2ea0d3ed3b091..6794bab3110b8 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java @@ -656,6 +656,40 @@ private static void signalNextIfShared(Node h) { } } + /** + * Repeatedly invokes acquire, if its execution throws an Error or a Runtime Exception, + * using an Unsafe.park-based backoff + * @param node which to reacquire + * @param arg the acquire argument + */ + private final void reacquire(Node node, int arg) { + try { + acquire(node, arg, false, false, false, 0L); + } catch (Error | RuntimeException firstEx) { + // While we currently do not emit an JFR events in this situation, mainly + // because the conditions under which this happens are such that it + // cannot be presumed to be possible to actually allocate an event, and + // using a preconstructed one would have limited value in serviceability. + // Having said that, the following place would be the more appropriate + // place to put such logic: + // emit JFR event + + for (long nanos = 1L;;) { + U.park(false, nanos); // must use Unsafe park to sleep + if (nanos < 1L << 30) // max about 1 second + nanos <<= 1; + + try { + acquire(node, arg, false, false, false, 0L); + } catch (Error | RuntimeException ignored) { + continue; + } + + throw firstEx; + } + } + } + /** * Main acquire method, invoked by all exported acquire methods. * @@ -1678,7 +1712,7 @@ else if ((node.status & COND) != 0) { } LockSupport.setCurrentBlocker(null); node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (interrupted) Thread.currentThread().interrupt(); } @@ -1725,7 +1759,7 @@ public final void await() throws InterruptedException { } LockSupport.setCurrentBlocker(null); node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (interrupted) { if (cancelled) { unlinkCancelledWaiters(node); @@ -1768,7 +1802,7 @@ public final long awaitNanos(long nanosTimeout) LockSupport.parkNanos(this, nanos); } node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (cancelled) { unlinkCancelledWaiters(node); if (interrupted) @@ -1812,7 +1846,7 @@ public final boolean awaitUntil(Date deadline) LockSupport.parkUntil(this, abstime); } node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (cancelled) { unlinkCancelledWaiters(node); if (interrupted) @@ -1857,7 +1891,7 @@ public final boolean await(long time, TimeUnit unit) LockSupport.parkNanos(this, nanos); } node.clearStatus(); - acquire(node, savedState, false, false, false, 0L); + reacquire(node, savedState); if (cancelled) { unlinkCancelledWaiters(node); if (interrupted) diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BytecodeHelpers.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BytecodeHelpers.java index 170772542ff15..e52d198e1f423 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BytecodeHelpers.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BytecodeHelpers.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,124 +51,170 @@ public class BytecodeHelpers { private BytecodeHelpers() { } + public static IllegalArgumentException cannotConvertException(TypeKind from, TypeKind to) { + return new IllegalArgumentException(String.format("convert %s -> %s", from, to)); + } + public static Opcode loadOpcode(TypeKind tk, int slot) { return switch (tk) { - case IntType, ShortType, ByteType, CharType, BooleanType -> switch (slot) { - case 0 -> Opcode.ILOAD_0; - case 1 -> Opcode.ILOAD_1; - case 2 -> Opcode.ILOAD_2; - case 3 -> Opcode.ILOAD_3; - default -> (slot < 256) ? Opcode.ILOAD : Opcode.ILOAD_W; - }; - case LongType -> switch (slot) { - case 0 -> Opcode.LLOAD_0; - case 1 -> Opcode.LLOAD_1; - case 2 -> Opcode.LLOAD_2; - case 3 -> Opcode.LLOAD_3; - default -> (slot < 256) ? Opcode.LLOAD : Opcode.LLOAD_W; - }; - case DoubleType -> switch (slot) { - case 0 -> Opcode.DLOAD_0; - case 1 -> Opcode.DLOAD_1; - case 2 -> Opcode.DLOAD_2; - case 3 -> Opcode.DLOAD_3; - default -> (slot < 256) ? Opcode.DLOAD : Opcode.DLOAD_W; - }; - case FloatType -> switch (slot) { - case 0 -> Opcode.FLOAD_0; - case 1 -> Opcode.FLOAD_1; - case 2 -> Opcode.FLOAD_2; - case 3 -> Opcode.FLOAD_3; - default -> (slot < 256) ? Opcode.FLOAD : Opcode.FLOAD_W; - }; - case ReferenceType -> switch (slot) { - case 0 -> Opcode.ALOAD_0; - case 1 -> Opcode.ALOAD_1; - case 2 -> Opcode.ALOAD_2; - case 3 -> Opcode.ALOAD_3; - default -> (slot < 256) ? Opcode.ALOAD : Opcode.ALOAD_W; - }; - case VoidType -> throw new IllegalArgumentException("void"); + case INT, SHORT, BYTE, CHAR, BOOLEAN + -> iload(slot); + case LONG -> lload(slot); + case DOUBLE -> dload(slot); + case FLOAT -> fload(slot); + case REFERENCE -> aload(slot); + case VOID -> throw new IllegalArgumentException("void"); + }; + } + + public static Opcode aload(int slot) { + return switch (slot) { + case 0 -> Opcode.ALOAD_0; + case 1 -> Opcode.ALOAD_1; + case 2 -> Opcode.ALOAD_2; + case 3 -> Opcode.ALOAD_3; + default -> (slot < 256) ? Opcode.ALOAD : Opcode.ALOAD_W; + }; + } + + public static Opcode fload(int slot) { + return switch (slot) { + case 0 -> Opcode.FLOAD_0; + case 1 -> Opcode.FLOAD_1; + case 2 -> Opcode.FLOAD_2; + case 3 -> Opcode.FLOAD_3; + default -> (slot < 256) ? Opcode.FLOAD : Opcode.FLOAD_W; + }; + } + + public static Opcode dload(int slot) { + return switch (slot) { + case 0 -> Opcode.DLOAD_0; + case 1 -> Opcode.DLOAD_1; + case 2 -> Opcode.DLOAD_2; + case 3 -> Opcode.DLOAD_3; + default -> (slot < 256) ? Opcode.DLOAD : Opcode.DLOAD_W; + }; + } + + public static Opcode lload(int slot) { + return switch (slot) { + case 0 -> Opcode.LLOAD_0; + case 1 -> Opcode.LLOAD_1; + case 2 -> Opcode.LLOAD_2; + case 3 -> Opcode.LLOAD_3; + default -> (slot < 256) ? Opcode.LLOAD : Opcode.LLOAD_W; + }; + } + + public static Opcode iload(int slot) { + return switch (slot) { + case 0 -> Opcode.ILOAD_0; + case 1 -> Opcode.ILOAD_1; + case 2 -> Opcode.ILOAD_2; + case 3 -> Opcode.ILOAD_3; + default -> (slot < 256) ? Opcode.ILOAD : Opcode.ILOAD_W; }; } public static Opcode storeOpcode(TypeKind tk, int slot) { return switch (tk) { - case IntType, ShortType, ByteType, CharType, BooleanType -> switch (slot) { - case 0 -> Opcode.ISTORE_0; - case 1 -> Opcode.ISTORE_1; - case 2 -> Opcode.ISTORE_2; - case 3 -> Opcode.ISTORE_3; - default -> (slot < 256) ? Opcode.ISTORE : Opcode.ISTORE_W; - }; - case LongType -> switch (slot) { - case 0 -> Opcode.LSTORE_0; - case 1 -> Opcode.LSTORE_1; - case 2 -> Opcode.LSTORE_2; - case 3 -> Opcode.LSTORE_3; - default -> (slot < 256) ? Opcode.LSTORE : Opcode.LSTORE_W; - }; - case DoubleType -> switch (slot) { - case 0 -> Opcode.DSTORE_0; - case 1 -> Opcode.DSTORE_1; - case 2 -> Opcode.DSTORE_2; - case 3 -> Opcode.DSTORE_3; - default -> (slot < 256) ? Opcode.DSTORE : Opcode.DSTORE_W; - }; - case FloatType -> switch (slot) { - case 0 -> Opcode.FSTORE_0; - case 1 -> Opcode.FSTORE_1; - case 2 -> Opcode.FSTORE_2; - case 3 -> Opcode.FSTORE_3; - default -> (slot < 256) ? Opcode.FSTORE : Opcode.FSTORE_W; - }; - case ReferenceType -> switch (slot) { - case 0 -> Opcode.ASTORE_0; - case 1 -> Opcode.ASTORE_1; - case 2 -> Opcode.ASTORE_2; - case 3 -> Opcode.ASTORE_3; - default -> (slot < 256) ? Opcode.ASTORE : Opcode.ASTORE_W; - }; - case VoidType -> throw new IllegalArgumentException("void"); + case INT, SHORT, BYTE, CHAR, BOOLEAN + -> istore(slot); + case LONG -> lstore(slot); + case DOUBLE -> dstore(slot); + case FLOAT -> fstore(slot); + case REFERENCE -> astore(slot); + case VOID -> throw new IllegalArgumentException("void"); + }; + } + + public static Opcode astore(int slot) { + return switch (slot) { + case 0 -> Opcode.ASTORE_0; + case 1 -> Opcode.ASTORE_1; + case 2 -> Opcode.ASTORE_2; + case 3 -> Opcode.ASTORE_3; + default -> (slot < 256) ? Opcode.ASTORE : Opcode.ASTORE_W; + }; + } + + public static Opcode fstore(int slot) { + return switch (slot) { + case 0 -> Opcode.FSTORE_0; + case 1 -> Opcode.FSTORE_1; + case 2 -> Opcode.FSTORE_2; + case 3 -> Opcode.FSTORE_3; + default -> (slot < 256) ? Opcode.FSTORE : Opcode.FSTORE_W; + }; + } + + public static Opcode dstore(int slot) { + return switch (slot) { + case 0 -> Opcode.DSTORE_0; + case 1 -> Opcode.DSTORE_1; + case 2 -> Opcode.DSTORE_2; + case 3 -> Opcode.DSTORE_3; + default -> (slot < 256) ? Opcode.DSTORE : Opcode.DSTORE_W; + }; + } + + public static Opcode lstore(int slot) { + return switch (slot) { + case 0 -> Opcode.LSTORE_0; + case 1 -> Opcode.LSTORE_1; + case 2 -> Opcode.LSTORE_2; + case 3 -> Opcode.LSTORE_3; + default -> (slot < 256) ? Opcode.LSTORE : Opcode.LSTORE_W; + }; + } + + public static Opcode istore(int slot) { + return switch (slot) { + case 0 -> Opcode.ISTORE_0; + case 1 -> Opcode.ISTORE_1; + case 2 -> Opcode.ISTORE_2; + case 3 -> Opcode.ISTORE_3; + default -> (slot < 256) ? Opcode.ISTORE : Opcode.ISTORE_W; }; } public static Opcode returnOpcode(TypeKind tk) { return switch (tk) { - case ByteType, ShortType, IntType, CharType, BooleanType -> Opcode.IRETURN; - case FloatType -> Opcode.FRETURN; - case LongType -> Opcode.LRETURN; - case DoubleType -> Opcode.DRETURN; - case ReferenceType -> Opcode.ARETURN; - case VoidType -> Opcode.RETURN; + case BYTE, SHORT, INT, CHAR, BOOLEAN -> Opcode.IRETURN; + case FLOAT -> Opcode.FRETURN; + case LONG -> Opcode.LRETURN; + case DOUBLE -> Opcode.DRETURN; + case REFERENCE -> Opcode.ARETURN; + case VOID -> Opcode.RETURN; }; } public static Opcode arrayLoadOpcode(TypeKind tk) { return switch (tk) { - case ByteType, BooleanType -> Opcode.BALOAD; - case ShortType -> Opcode.SALOAD; - case IntType -> Opcode.IALOAD; - case FloatType -> Opcode.FALOAD; - case LongType -> Opcode.LALOAD; - case DoubleType -> Opcode.DALOAD; - case ReferenceType -> Opcode.AALOAD; - case CharType -> Opcode.CALOAD; - case VoidType -> throw new IllegalArgumentException("void not an allowable array type"); + case BYTE, BOOLEAN -> Opcode.BALOAD; + case SHORT -> Opcode.SALOAD; + case INT -> Opcode.IALOAD; + case FLOAT -> Opcode.FALOAD; + case LONG -> Opcode.LALOAD; + case DOUBLE -> Opcode.DALOAD; + case REFERENCE -> Opcode.AALOAD; + case CHAR -> Opcode.CALOAD; + case VOID -> throw new IllegalArgumentException("void not an allowable array type"); }; } public static Opcode arrayStoreOpcode(TypeKind tk) { return switch (tk) { - case ByteType, BooleanType -> Opcode.BASTORE; - case ShortType -> Opcode.SASTORE; - case IntType -> Opcode.IASTORE; - case FloatType -> Opcode.FASTORE; - case LongType -> Opcode.LASTORE; - case DoubleType -> Opcode.DASTORE; - case ReferenceType -> Opcode.AASTORE; - case CharType -> Opcode.CASTORE; - case VoidType -> throw new IllegalArgumentException("void not an allowable array type"); + case BYTE, BOOLEAN -> Opcode.BASTORE; + case SHORT -> Opcode.SASTORE; + case INT -> Opcode.IASTORE; + case FLOAT -> Opcode.FASTORE; + case LONG -> Opcode.LASTORE; + case DOUBLE -> Opcode.DASTORE; + case REFERENCE -> Opcode.AASTORE; + case CHAR -> Opcode.CASTORE; + case VOID -> throw new IllegalArgumentException("void not an allowable array type"); }; } @@ -195,75 +242,55 @@ public static Opcode reverseBranchOpcode(Opcode op) { public static Opcode convertOpcode(TypeKind from, TypeKind to) { return switch (from) { - case IntType -> + case INT -> switch (to) { - case LongType -> Opcode.I2L; - case FloatType -> Opcode.I2F; - case DoubleType -> Opcode.I2D; - case ByteType -> Opcode.I2B; - case CharType -> Opcode.I2C; - case ShortType -> Opcode.I2S; - default -> throw new IllegalArgumentException(String.format("convert %s -> %s", from, to)); + case LONG -> Opcode.I2L; + case FLOAT -> Opcode.I2F; + case DOUBLE -> Opcode.I2D; + case BYTE -> Opcode.I2B; + case CHAR -> Opcode.I2C; + case SHORT -> Opcode.I2S; + default -> throw cannotConvertException(from, to); }; - case LongType -> + case LONG -> switch (to) { - case FloatType -> Opcode.L2F; - case DoubleType -> Opcode.L2D; - case IntType -> Opcode.L2I; - default -> throw new IllegalArgumentException(String.format("convert %s -> %s", from, to)); + case FLOAT -> Opcode.L2F; + case DOUBLE -> Opcode.L2D; + case INT -> Opcode.L2I; + default -> throw cannotConvertException(from, to); }; - case DoubleType -> + case DOUBLE -> switch (to) { - case FloatType -> Opcode.D2F; - case LongType -> Opcode.D2L; - case IntType -> Opcode.D2I; - default -> throw new IllegalArgumentException(String.format("convert %s -> %s", from, to)); + case FLOAT -> Opcode.D2F; + case LONG -> Opcode.D2L; + case INT -> Opcode.D2I; + default -> throw cannotConvertException(from, to); }; - case FloatType -> + case FLOAT -> switch (to) { - case LongType -> Opcode.F2L; - case DoubleType -> Opcode.F2D; - case IntType -> Opcode.F2I; - default -> throw new IllegalArgumentException(String.format("convert %s -> %s", from, to)); + case LONG -> Opcode.F2L; + case DOUBLE -> Opcode.F2D; + case INT -> Opcode.F2I; + default -> throw cannotConvertException(from, to); }; - default -> throw new IllegalArgumentException(String.format("convert %s -> %s", from, to)); + default -> throw cannotConvertException(from, to); }; } - static void validateSipush(long value) { - if (value < Short.MIN_VALUE || Short.MAX_VALUE < value) + public static void validateSipush(int value) { + if (value != (short) value) throw new IllegalArgumentException( "SIPUSH: value must be within: Short.MIN_VALUE <= value <= Short.MAX_VALUE, found: " .concat(Long.toString(value))); } - static void validateBipush(long value) { - if (value < Byte.MIN_VALUE || Byte.MAX_VALUE < value) + public static void validateBipush(int value) { + if (value != (byte) value) throw new IllegalArgumentException( "BIPUSH: value must be within: Byte.MIN_VALUE <= value <= Byte.MAX_VALUE, found: " .concat(Long.toString(value))); } - static void validateSipush(ConstantDesc d) { - if (d instanceof Integer iVal) { - validateSipush(iVal.longValue()); - } else if (d instanceof Long lVal) { - validateSipush(lVal.longValue()); - } else { - throw new IllegalArgumentException("SIPUSH: not an integral number: ".concat(d.toString())); - } - } - - static void validateBipush(ConstantDesc d) { - if (d instanceof Integer iVal) { - validateBipush(iVal.longValue()); - } else if (d instanceof Long lVal) { - validateBipush(lVal.longValue()); - } else { - throw new IllegalArgumentException("BIPUSH: not an integral number: ".concat(d.toString())); - } - } - public static MethodHandleEntry handleDescToHandleInfo(ConstantPoolBuilder constantPool, DirectMethodHandleDesc bootstrapMethod) { ClassEntry bsOwner = constantPool.classEntry(bootstrapMethod.owner()); NameAndTypeEntry bsNameAndType = constantPool.nameAndTypeEntry(constantPool.utf8Entry(bootstrapMethod.methodName()), @@ -294,32 +321,6 @@ static ConstantDynamicEntry handleConstantDescToHandleInfo(ConstantPoolBuilder c desc.constantType())); } - public static void validateValue(Opcode opcode, ConstantDesc v) { - switch (opcode) { - case ACONST_NULL -> { - if (v != null && v != ConstantDescs.NULL) - throw new IllegalArgumentException("value must be null or ConstantDescs.NULL with opcode ACONST_NULL"); - } - case SIPUSH -> - validateSipush(v); - case BIPUSH -> - validateBipush(v); - case LDC, LDC_W, LDC2_W -> { - if (v == null) - throw new IllegalArgumentException("`null` must use ACONST_NULL"); - } - default -> { - var exp = opcode.constantValue(); - if (exp == null) - throw new IllegalArgumentException("Can not use Opcode: " + opcode + " with constant()"); - if (v == null || !(v.equals(exp) || (exp instanceof Long l && v.equals(l.intValue())))) { - var t = (exp instanceof Long) ? "L" : (exp instanceof Float) ? "f" : (exp instanceof Double) ? "d" : ""; - throw new IllegalArgumentException("value must be " + exp + t + " with opcode " + opcode.name()); - } - } - } - } - public static Opcode ldcOpcode(LoadableConstantEntry entry) { return entry.typeKind().slotSize() == 2 ? Opcode.LDC2_W : entry.index() > 0xff ? Opcode.LDC_W diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java index 2a648e27568f1..837cf3366be83 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java @@ -851,7 +851,7 @@ private static MapNode codeToTree(CodeAttribute com, Verbosity verbosity) { "type", newo.className().name().stringValue())); case NewPrimitiveArrayInstruction newa -> in.with(leafs( "dimensions", 1, - "descriptor", newa.typeKind().typeName())); + "descriptor", newa.typeKind().upperBound().displayName())); case NewReferenceArrayInstruction newa -> in.with(leafs( "dimensions", 1, "descriptor", newa.componentType().name().stringValue())); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassRemapperImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassRemapperImpl.java index 9b5e7639fa2a4..1d1d028531ecb 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassRemapperImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassRemapperImpl.java @@ -258,8 +258,7 @@ public CodeTransform asCodeTransform() { cob.localVariableType(c.slot(), c.name().stringValue(), mapSignature(c.signatureSymbol()), c.startScope(), c.endScope()); case LoadConstantInstruction ldc -> - cob.loadConstant(ldc.opcode(), - mapConstantValue(ldc.constantValue())); + cob.ldc(mapConstantValue(ldc.constantValue())); case RuntimeVisibleTypeAnnotationsAttribute aa -> cob.with(RuntimeVisibleTypeAnnotationsAttribute.of( mapTypeAnnotations(aa.annotations()))); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeLocalsShifterImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeLocalsShifterImpl.java index a68225fbf2751..9c2554c054c40 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeLocalsShifterImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeLocalsShifterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ public void accept(CodeBuilder cob, CodeElement coe) { shift(cob, si.slot(), si.typeKind())); case IncrementInstruction ii -> cob.iinc( - shift(cob, ii.slot(), TypeKind.IntType), + shift(cob, ii.slot(), TypeKind.INT), ii.constant()); case LocalVariable lv -> cob.localVariable( @@ -73,7 +73,7 @@ public void accept(CodeBuilder cob, CodeElement coe) { shift(cob, lvt.slot(), (lvt.signatureSymbol() instanceof Signature.BaseTypeSig bsig) ? TypeKind.fromDescriptor(bsig.signatureString()) - : TypeKind.ReferenceType), + : TypeKind.REFERENCE), lvt.name(), lvt.signature(), lvt.startScope(), @@ -83,7 +83,7 @@ public void accept(CodeBuilder cob, CodeElement coe) { } private int shift(CodeBuilder cob, int slot, TypeKind tk) { - if (tk == TypeKind.VoidType) throw new IllegalArgumentException("Illegal local void type"); + if (tk == TypeKind.VOID) throw new IllegalArgumentException("Illegal local void type"); if (slot >= fixed) { int key = 2*slot - fixed + tk.slotSize() - 1; if (key >= locals.length) locals = Arrays.copyOf(locals, key + 20); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeStackTrackerImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeStackTrackerImpl.java index 2b87821b742bf..9288f9fa2a90b 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeStackTrackerImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeStackTrackerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -146,7 +146,7 @@ public Optional maxStackSize() { private void push(TypeKind type) { if (stack != null) { - if (type != TypeKind.VoidType) stack.push(type); + if (type != TypeKind.VOID) stack.push(type); } else { maxSize = null; } @@ -228,15 +228,15 @@ public void accept(CodeBuilder cb, CodeElement el) { case MonitorInstruction i -> pop(1); case NewMultiArrayInstruction i -> { - pop(i.dimensions());push(TypeKind.ReferenceType); + pop(i.dimensions());push(TypeKind.REFERENCE); } case NewObjectInstruction i -> - push(TypeKind.ReferenceType); + push(TypeKind.REFERENCE); case NewPrimitiveArrayInstruction i -> { - pop(1);push(TypeKind.ReferenceType); + pop(1);push(TypeKind.REFERENCE); } case NewReferenceArrayInstruction i -> { - pop(1);push(TypeKind.ReferenceType); + pop(1);push(TypeKind.REFERENCE); } case NopInstruction i -> {} case OperatorInstruction i -> { @@ -329,15 +329,15 @@ public void accept(CodeBuilder cb, CodeElement el) { case TypeCheckInstruction i -> { switch (i.opcode()) { case CHECKCAST -> { - pop(1);push(TypeKind.ReferenceType); + pop(1);push(TypeKind.REFERENCE); } case INSTANCEOF -> { - pop(1);push(TypeKind.IntType); + pop(1);push(TypeKind.INT); } } } case ExceptionCatch i -> - map.put(i.handler(), new Stack(new Item(TypeKind.ReferenceType, null), 1, 1)); + map.put(i.handler(), new Stack(new Item(TypeKind.REFERENCE, null), 1, 1)); case LabelTarget i -> stack = map.getOrDefault(i.label(), stack); default -> {} diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java index 1d2cbb5c84b05..1b950f28d004b 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Alibaba Group Holding Limited. 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 +64,8 @@ import static java.lang.classfile.Opcode.*; +import static jdk.internal.classfile.impl.BytecodeHelpers.*; + public final class DirectCodeBuilder extends AbstractDirectBuilder implements TerminalCodeBuilder { @@ -828,21 +831,6 @@ public CodeBuilder branch(Opcode op, Label target) { return this; } - @Override - public CodeBuilder loadConstant(Opcode opcode, ConstantDesc value) { - BytecodeHelpers.validateValue(opcode, value); - // avoid non-local enum switch for bootstrap - if (opcode == BIPUSH || opcode == SIPUSH) { - writeArgumentConstant(opcode, ((Number) value).intValue()); - } else if (opcode == LDC || opcode == LDC_W || opcode == LDC2_W) { - writeLoadConstant(opcode, BytecodeHelpers.constantEntry(constantPool(), value)); - } else { - // intrinsics - writeBytecode(opcode); - } - return this; - } - @Override public CodeBuilder nop() { writeBytecode(NOP); @@ -855,6 +843,12 @@ public CodeBuilder aconst_null() { return this; } + @Override + public CodeBuilder aload(int slot) { + writeLocalVar(BytecodeHelpers.aload(slot), slot); + return this; + } + @Override public CodeBuilder anewarray(ClassEntry entry) { writeNewReferenceArray(entry); @@ -867,6 +861,12 @@ public CodeBuilder arraylength() { return this; } + @Override + public CodeBuilder astore(int slot) { + writeLocalVar(BytecodeHelpers.astore(slot), slot); + return this; + } + @Override public CodeBuilder athrow() { writeBytecode(ATHROW); @@ -940,6 +940,12 @@ public CodeBuilder ddiv() { return this; } + @Override + public CodeBuilder dload(int slot) { + writeLocalVar(BytecodeHelpers.dload(slot), slot); + return this; + } + @Override public CodeBuilder dmul() { writeBytecode(DMUL); @@ -958,6 +964,12 @@ public CodeBuilder drem() { return this; } + @Override + public CodeBuilder dstore(int slot) { + writeLocalVar(BytecodeHelpers.dstore(slot), slot); + return this; + } + @Override public CodeBuilder dsub() { writeBytecode(DSUB); @@ -1060,6 +1072,12 @@ public CodeBuilder fdiv() { return this; } + @Override + public CodeBuilder fload(int slot) { + writeLocalVar(BytecodeHelpers.fload(slot), slot); + return this; + } + @Override public CodeBuilder fmul() { writeBytecode(FMUL); @@ -1078,6 +1096,12 @@ public CodeBuilder frem() { return this; } + @Override + public CodeBuilder fstore(int slot) { + writeLocalVar(BytecodeHelpers.fstore(slot), slot); + return this; + } + @Override public CodeBuilder fsub() { writeBytecode(FSUB); @@ -1186,6 +1210,12 @@ public CodeBuilder iinc(int slot, int val) { return this; } + @Override + public CodeBuilder iload(int slot) { + writeLocalVar(BytecodeHelpers.iload(slot), slot); + return this; + } + @Override public CodeBuilder imul() { writeBytecode(IMUL); @@ -1270,6 +1300,12 @@ public CodeBuilder ishr() { return this; } + @Override + public CodeBuilder istore(int slot) { + writeLocalVar(BytecodeHelpers.istore(slot), slot); + return this; + } + @Override public CodeBuilder isub() { writeBytecode(ISUB); @@ -1354,6 +1390,12 @@ public CodeBuilder ldiv() { return this; } + @Override + public CodeBuilder lload(int slot) { + writeLocalVar(BytecodeHelpers.lload(slot), slot); + return this; + } + @Override public CodeBuilder lmul() { writeBytecode(LMUL); @@ -1390,6 +1432,12 @@ public CodeBuilder lshr() { return this; } + @Override + public CodeBuilder lstore(int slot) { + writeLocalVar(BytecodeHelpers.lstore(slot), slot); + return this; + } + @Override public CodeBuilder lsub() { writeBytecode(LSUB); @@ -1436,7 +1484,7 @@ public CodeBuilder new_(ClassEntry clazz) { public CodeBuilder newarray(TypeKind typeKind) { int atype = typeKind.newarrayCode(); // implicit null check if (atype < 0) - throw new IllegalArgumentException("Illegal component type: " + typeKind.typeName()); + throw new IllegalArgumentException("Illegal component type: ".concat(typeKind.upperBound().displayName())); writeNewPrimitiveArray(atype); return this; } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/ParserVerifier.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/ParserVerifier.java index 77f56b322ddf9..ed735b41e0e78 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/ParserVerifier.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/ParserVerifier.java @@ -230,12 +230,12 @@ private void verifyAttribute(AttributedElement ae, Attribute a, List cve instanceof IntegerEntry; - case DoubleType -> cve instanceof DoubleEntry; - case FloatType -> cve instanceof FloatEntry; - case LongType -> cve instanceof LongEntry; - case ReferenceType -> type.equals(ConstantDescs.CD_String) && cve instanceof StringEntry; - case VoidType -> false; + case BOOLEAN, BYTE, CHAR, INT, SHORT -> cve instanceof IntegerEntry; + case DOUBLE -> cve instanceof DoubleEntry; + case FLOAT -> cve instanceof FloatEntry; + case LONG -> cve instanceof LongEntry; + case REFERENCE -> type.equals(ConstantDescs.CD_String) && cve instanceof StringEntry; + case VOID -> false; }) { errors.add(new VerifyError("Bad constant value type in %s".formatted(toString(ae)))); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java index 75be22ac454fa..5d43c28a66711 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java @@ -51,6 +51,7 @@ import jdk.internal.misc.ScopedMemoryAccess; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; +import jdk.internal.util.Architecture; import jdk.internal.util.ArraysSupport; import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.ForceInline; @@ -188,10 +189,52 @@ public Stream elements(MemoryLayout elementLayout) { return StreamSupport.stream(spliterator(elementLayout), false); } + // FILL_NATIVE_THRESHOLD must be a power of two and should be greater than 2^3 + // Update the value for Aarch64 once 8338975 is fixed. + private static final long FILL_NATIVE_THRESHOLD = 1L << (Architecture.isAARCH64() ? 10 : 5); + @Override - public final MemorySegment fill(byte value){ - checkAccess(0, length, false); - SCOPED_MEMORY_ACCESS.setMemory(sessionImpl(), unsafeGetBase(), unsafeGetOffset(), length, value); + @ForceInline + public final MemorySegment fill(byte value) { + checkReadOnly(false); + if (length == 0) { + // Implicit state check + checkValidState(); + } else if (length < FILL_NATIVE_THRESHOLD) { + // 0 <= length < FILL_NATIVE_LIMIT : 0...0X...XXXX + + // Handle smaller segments directly without transitioning to native code + final long u = Byte.toUnsignedLong(value); + final long longValue = u << 56 | u << 48 | u << 40 | u << 32 | u << 24 | u << 16 | u << 8 | u; + + int offset = 0; + // 0...0X...X000 + final int limit = (int) (length & (FILL_NATIVE_THRESHOLD - 8)); + for (; offset < limit; offset += 8) { + SCOPED_MEMORY_ACCESS.putLong(sessionImpl(), unsafeGetBase(), unsafeGetOffset() + offset, longValue); + } + int remaining = (int) length - limit; + // 0...0X00 + if (remaining >= 4) { + SCOPED_MEMORY_ACCESS.putInt(sessionImpl(), unsafeGetBase(), unsafeGetOffset() + offset, (int) longValue); + offset += 4; + remaining -= 4; + } + // 0...00X0 + if (remaining >= 2) { + SCOPED_MEMORY_ACCESS.putShort(sessionImpl(), unsafeGetBase(), unsafeGetOffset() + offset, (short) longValue); + offset += 2; + remaining -= 2; + } + // 0...000X + if (remaining == 1) { + SCOPED_MEMORY_ACCESS.putByte(sessionImpl(), unsafeGetBase(), unsafeGetOffset() + offset, value); + } + // We have now fully handled 0...0X...XXXX + } else { + // Handle larger segments via native calls + SCOPED_MEMORY_ACCESS.setMemory(sessionImpl(), unsafeGetBase(), unsafeGetOffset(), length, value); + } return this; } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java index 6109f59f2d8ca..bc5f63fd50ef7 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java @@ -273,10 +273,10 @@ private void specialize() { int numScopes = 0; for (int i = 0; i < callerMethodType.parameterCount(); i++) { if (shouldAcquire(i)) { - int scopeLocal = cb.allocateLocal(ReferenceType); + int scopeLocal = cb.allocateLocal(REFERENCE); initialScopeSlots[numScopes++] = scopeLocal; cb.loadConstant(null); - cb.storeLocal(ReferenceType, scopeLocal); // need to initialize all scope locals here in case an exception occurs + cb.storeLocal(REFERENCE, scopeLocal); // need to initialize all scope locals here in case an exception occurs } } scopeSlots = Arrays.copyOf(initialScopeSlots, numScopes); // fit to size @@ -292,16 +292,16 @@ private void specialize() { } else { cb.getstatic(CD_SharedUtils, "DUMMY_ARENA", CD_Arena); } - contextIdx = cb.allocateLocal(ReferenceType); - cb.storeLocal(ReferenceType, contextIdx); + contextIdx = cb.allocateLocal(REFERENCE); + cb.storeLocal(REFERENCE, contextIdx); // in case the call needs a return buffer, allocate it here. // for upcalls the VM wrapper stub allocates the buffer. if (callingSequence.needsReturnBuffer() && callingSequence.forDowncall()) { emitLoadInternalAllocator(); emitAllocateCall(callingSequence.returnBufferSize(), 1); - returnBufferIdx = cb.allocateLocal(ReferenceType); - cb.storeLocal(ReferenceType, returnBufferIdx); + returnBufferIdx = cb.allocateLocal(REFERENCE); + cb.storeLocal(REFERENCE, returnBufferIdx); } Label tryStart = cb.newLabel(); @@ -324,7 +324,7 @@ private void specialize() { // for downcalls, recipes have an input value, which we set up here if (callingSequence.needsReturnBuffer() && i == 0) { assert returnBufferIdx != -1; - cb.loadLocal(ReferenceType, returnBufferIdx); + cb.loadLocal(REFERENCE, returnBufferIdx); pushType(MemorySegment.class); } else { emitGetInput(); @@ -339,8 +339,8 @@ private void specialize() { if (callingSequence.needsReturnBuffer() && i == 0) { // return buffer ptr is wrapped in a MemorySegment above, but not passed to the leaf handle popType(MemorySegment.class); - returnBufferIdx = cb.allocateLocal(ReferenceType); - cb.storeLocal(ReferenceType, returnBufferIdx); + returnBufferIdx = cb.allocateLocal(REFERENCE); + cb.storeLocal(REFERENCE, returnBufferIdx); } else { // for upcalls the recipe result is an argument to the leaf handle emitSetOutput(typeStack.pop()); @@ -355,7 +355,7 @@ private void specialize() { if (callingSequence.forDowncall()) { cb.loadConstant(CLASS_DATA_DESC); } else { - cb.loadLocal(ReferenceType, 0); // load target arg + cb.loadLocal(REFERENCE, 0); // load target arg } cb.checkcast(CD_MethodHandle); // load all the leaf args @@ -506,7 +506,7 @@ private void emitAcquireScope() { boolean hasOtherScopes = curScopeLocalIdx != 0; for (int i = 0; i < curScopeLocalIdx; i++) { cb.dup(); // dup for comparison - cb.loadLocal(ReferenceType, scopeSlots[i]); + cb.loadLocal(REFERENCE, scopeSlots[i]); cb.if_acmpeq(skipAcquire); } @@ -515,7 +515,7 @@ private void emitAcquireScope() { int nextScopeLocal = scopeSlots[curScopeLocalIdx++]; // call acquire first here. So that if it fails, we don't call release cb.invokevirtual(CD_MemorySessionImpl, "acquire0", MTD_ACQUIRE0); // call acquire on the other - cb.storeLocal(ReferenceType, nextScopeLocal); // store off one to release later + cb.storeLocal(REFERENCE, nextScopeLocal); // store off one to release later if (hasOtherScopes) { // avoid ASM generating a bunch of nops for the dead code cb.goto_(end); @@ -529,9 +529,9 @@ private void emitAcquireScope() { private void emitReleaseScopes() { for (int scopeLocal : scopeSlots) { - cb.loadLocal(ReferenceType, scopeLocal); + cb.loadLocal(REFERENCE, scopeLocal); cb.ifThen(Opcode.IFNONNULL, ifCb -> { - ifCb.loadLocal(ReferenceType, scopeLocal); + ifCb.loadLocal(REFERENCE, scopeLocal); ifCb.invokevirtual(CD_MemorySessionImpl, "release0", MTD_RELEASE0); }); } @@ -551,7 +551,7 @@ private void emitRestoreReturnValue(Class loadType) { private void emitLoadInternalSession() { assert contextIdx != -1; - cb.loadLocal(ReferenceType, contextIdx); + cb.loadLocal(REFERENCE, contextIdx); cb.checkcast(CD_Arena); cb.invokeinterface(CD_Arena, "scope", MTD_SCOPE); cb.checkcast(CD_MemorySessionImpl); @@ -559,12 +559,12 @@ private void emitLoadInternalSession() { private void emitLoadInternalAllocator() { assert contextIdx != -1; - cb.loadLocal(ReferenceType, contextIdx); + cb.loadLocal(REFERENCE, contextIdx); } private void emitCloseContext() { assert contextIdx != -1; - cb.loadLocal(ReferenceType, contextIdx); + cb.loadLocal(REFERENCE, contextIdx); cb.checkcast(CD_Arena); cb.invokeinterface(CD_Arena, "close", MTD_CLOSE); } @@ -585,7 +585,7 @@ private void emitBoxAddress(BoxAddress boxAddress) { private void emitAllocBuffer(Allocate binding) { if (callingSequence.forDowncall()) { assert returnAllocatorIdx != -1; - cb.loadLocal(ReferenceType, returnAllocatorIdx); + cb.loadLocal(REFERENCE, returnAllocatorIdx); } else { emitLoadInternalAllocator(); } @@ -618,10 +618,10 @@ private void emitBufferStore(BufferStore bufferStore) { } else { assert storeType == long.class; // chunking only for int and long } - int longValueIdx = cb.allocateLocal(LongType); - cb.storeLocal(LongType, longValueIdx); - int writeAddrIdx = cb.allocateLocal(ReferenceType); - cb.storeLocal(ReferenceType, writeAddrIdx); + int longValueIdx = cb.allocateLocal(LONG); + cb.storeLocal(LONG, longValueIdx); + int writeAddrIdx = cb.allocateLocal(REFERENCE); + cb.storeLocal(REFERENCE, writeAddrIdx); int remaining = byteWidth; int chunkOffset = 0; @@ -648,7 +648,7 @@ private void emitBufferStore(BufferStore bufferStore) { //int writeChunk = (int) (((0xFFFF_FFFFL << shiftAmount) & longValue) >>> shiftAmount); int shiftAmount = chunkOffset * Byte.SIZE; mask = mask << shiftAmount; - cb.loadLocal(LongType, longValueIdx); + cb.loadLocal(LONG, longValueIdx); cb.loadConstant(mask); cb.land(); if (shiftAmount != 0) { @@ -662,7 +662,7 @@ private void emitBufferStore(BufferStore bufferStore) { // chunk done, now write it //writeAddress.set(JAVA_SHORT_UNALIGNED, offset, writeChunk); - cb.loadLocal(ReferenceType, writeAddrIdx); + cb.loadLocal(REFERENCE, writeAddrIdx); ClassDesc valueLayoutType = emitLoadLayoutConstant(chunkStoreType); long writeOffset = offset + SharedUtils.pickChunkOffset(chunkOffset, byteWidth, chunkSize); cb.loadConstant(writeOffset); @@ -694,7 +694,7 @@ private void emitVMStore(VMStore vmStore) { cb.storeLocal(storeTypeKind, valueIdx); // store away the stored value, need it later assert returnBufferIdx != -1; - cb.loadLocal(ReferenceType, returnBufferIdx); + cb.loadLocal(REFERENCE, returnBufferIdx); ClassDesc valueLayoutType = emitLoadLayoutConstant(storeType); cb.loadConstant(retBufOffset); cb.loadLocal(storeTypeKind, valueIdx); @@ -714,7 +714,7 @@ private void emitVMLoad(VMLoad vmLoad) { emitRestoreReturnValue(loadType); } else { assert returnBufferIdx != -1; - cb.loadLocal(ReferenceType, returnBufferIdx); + cb.loadLocal(REFERENCE, returnBufferIdx); ClassDesc valueLayoutType = emitLoadLayoutConstant(loadType); cb.loadConstant(retBufOffset); MethodTypeDesc descriptor = MethodTypeDesc.of(classDesc(loadType), valueLayoutType, CD_long); @@ -814,12 +814,12 @@ private void emitBufferLoad(BufferLoad bufferLoad) { cb.invokeinterface(CD_MemorySegment, "get", descriptor); } else { // chunked - int readAddrIdx = cb.allocateLocal(ReferenceType); - cb.storeLocal(ReferenceType, readAddrIdx); + int readAddrIdx = cb.allocateLocal(REFERENCE); + cb.storeLocal(REFERENCE, readAddrIdx); cb.loadConstant(0L); // result - int resultIdx = cb.allocateLocal(LongType); - cb.storeLocal(LongType, resultIdx); + int resultIdx = cb.allocateLocal(LONG); + cb.storeLocal(LONG, resultIdx); int remaining = byteWidth; int chunkOffset = 0; @@ -848,7 +848,7 @@ private void emitBufferLoad(BufferLoad bufferLoad) { throw new IllegalStateException("Unexpected chunk size for chunked write: " + chunkSize); } // read from segment - cb.loadLocal(ReferenceType, readAddrIdx); + cb.loadLocal(REFERENCE, readAddrIdx); ClassDesc valueLayoutType = emitLoadLayoutConstant(chunkType); MethodTypeDesc descriptor = MethodTypeDesc.of(classDesc(chunkType), valueLayoutType, CD_long); long readOffset = offset + SharedUtils.pickChunkOffset(chunkOffset, byteWidth, chunkSize); @@ -863,15 +863,15 @@ private void emitBufferLoad(BufferLoad bufferLoad) { cb.lshl(); } // add to result - cb.loadLocal(LongType, resultIdx); + cb.loadLocal(LONG, resultIdx); cb.lor(); - cb.storeLocal(LongType, resultIdx); + cb.storeLocal(LONG, resultIdx); remaining -= chunkSize; chunkOffset += chunkSize; } while (remaining != 0); - cb.loadLocal(LongType, resultIdx); + cb.loadLocal(LONG, resultIdx); if (loadType == int.class) { cb.l2i(); } else { @@ -897,13 +897,13 @@ private void emitCopyBuffer(Copy copy) { emitLoadInternalAllocator(); emitAllocateCall(size, alignment); cb.dup(); - int storeIdx = cb.allocateLocal(ReferenceType); - cb.storeLocal(ReferenceType, storeIdx); + int storeIdx = cb.allocateLocal(REFERENCE); + cb.storeLocal(REFERENCE, storeIdx); cb.loadConstant(0L); cb.loadConstant(size); cb.invokestatic(CD_MemorySegment, "copy", MTD_COPY, true); - cb.loadLocal(ReferenceType, storeIdx); + cb.loadLocal(REFERENCE, storeIdx); pushType(MemorySegment.class); } @@ -982,11 +982,11 @@ private void emitDup(Class type) { private void emitConstZero(TypeKind kind) { switch (kind) { - case BooleanType, ByteType, ShortType, CharType, IntType -> cb.iconst_0(); - case LongType -> cb.lconst_0(); - case FloatType -> cb.fconst_0(); - case DoubleType -> cb.dconst_0(); - case ReferenceType -> cb.aconst_null(); + case BOOLEAN, BYTE, SHORT, CHAR, INT -> cb.iconst_0(); + case LONG -> cb.lconst_0(); + case FLOAT -> cb.fconst_0(); + case DOUBLE -> cb.dconst_0(); + case REFERENCE -> cb.aconst_null(); } } } diff --git a/src/java.base/share/native/libjli/jli_util.h b/src/java.base/share/native/libjli/jli_util.h index cacb0d65cb0f3..4bd72abc2db74 100644 --- a/src/java.base/share/native/libjli/jli_util.h +++ b/src/java.base/share/native/libjli/jli_util.h @@ -113,6 +113,9 @@ JLI_SetTraceLauncher(); jboolean JLI_IsTraceLauncher(); +// This is defined in link_type.c due to linking restraints +jboolean JLI_IsStaticallyLinked(); + /* * JLI_List - a dynamic list of char* */ diff --git a/src/java.base/share/native/libjli/link_type.c b/src/java.base/share/native/libjli/link_type.c new file mode 100644 index 0000000000000..aa060ddb00e29 --- /dev/null +++ b/src/java.base/share/native/libjli/link_type.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024, 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. + */ + +#include "jni.h" + +// This is in a separate file since it will need to be compiled to two different +// object files, depending on if we are going to build a static or a dynamic +// library. + +jboolean JLI_IsStaticallyLinked(void) { +#ifdef STATIC_BUILD + return JNI_TRUE; +#else + return JNI_FALSE; +#endif +} diff --git a/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c b/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c index 57d911e35de0a..acc7f0c73c903 100644 --- a/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c +++ b/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c @@ -661,11 +661,8 @@ pid_t unix_getParentPidAndTimings(JNIEnv *env, pid_t pid, void unix_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) { psinfo_t psinfo; - char fn[32]; - char exePath[PATH_MAX]; char prargs[PRARGSZ + 1]; jstring cmdexe = NULL; - int ret; /* * Now try to open /proc/%d/psinfo diff --git a/src/java.base/unix/native/libjava/TimeZone_md.c b/src/java.base/unix/native/libjava/TimeZone_md.c index 988c4bd2646f9..bc55f099bd95a 100644 --- a/src/java.base/unix/native/libjava/TimeZone_md.c +++ b/src/java.base/unix/native/libjava/TimeZone_md.c @@ -41,8 +41,6 @@ #include "TimeZone_md.h" #include "path_util.h" -static char *isFileIdentical(char* buf, size_t size, char *pathname); - #define fileopen fopen #define filegets fgets #define fileclose fclose @@ -59,11 +57,8 @@ static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime"; static const char popularZones[][4] = {"UTC", "GMT"}; -#if defined(_AIX) -static const char *ETC_ENVIRONMENT_FILE = "/etc/environment"; -#endif - #if defined(__linux__) || defined(MACOSX) +static char *isFileIdentical(char* buf, size_t size, char *pathname); /* * remove repeated path separators ('/') in the given 'path'. @@ -356,6 +351,7 @@ getPlatformTimeZoneID() } #elif defined(_AIX) +static const char *ETC_ENVIRONMENT_FILE = "/etc/environment"; static char * getPlatformTimeZoneID() diff --git a/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c b/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c index 4907200db72e8..908b7cca653cc 100644 --- a/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c +++ b/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c @@ -493,9 +493,6 @@ static StatusWindow *createStatusWindow(Window parent) { XWindowAttributes xwa; XWindowAttributes xxwa; /* Variable for XCreateFontSet()*/ - char **mclr; - int mccr = 0; - char *dsr; unsigned long bg, fg, light, dim; int x, y, off_x, off_y, xx, yy; unsigned int w, h, bw, depth; diff --git a/src/java.desktop/unix/native/common/awt/CUPSfuncs.c b/src/java.desktop/unix/native/common/awt/CUPSfuncs.c index 216da01e0cd62..173d44d96c845 100644 --- a/src/java.desktop/unix/native/common/awt/CUPSfuncs.c +++ b/src/java.desktop/unix/native/common/awt/CUPSfuncs.c @@ -202,7 +202,6 @@ Java_sun_print_CUPSPrinter_getCupsDefaultPrinter(JNIEnv *env, cups_dest_t *dests; char *defaultPrinter = NULL; int num_dests = j2d_cupsGetDests(&dests); - int i = 0; cups_dest_t *dest = j2d_cupsGetDest(NULL, NULL, num_dests, dests); if (dest != NULL) { defaultPrinter = dest->name; diff --git a/src/java.desktop/unix/native/common/awt/X11Color.c b/src/java.desktop/unix/native/common/awt/X11Color.c index 6d3f4e7b246e9..2d3fd48091489 100644 --- a/src/java.desktop/unix/native/common/awt/X11Color.c +++ b/src/java.desktop/unix/native/common/awt/X11Color.c @@ -338,7 +338,7 @@ awt_allocate_colors(AwtGraphicsConfigDataPtr awt_data) unsigned char reds[256], greens[256], blues[256]; int indices[256]; Colormap cm; - int i, j, k, cmapsize, nfree, depth, bpp; + int i, k, cmapsize, nfree, depth, bpp; int allocatedColorsNum, unavailableColorsNum; XPixmapFormatValues *pPFV; int numpfv; @@ -878,7 +878,6 @@ awt_allocate_colors(AwtGraphicsConfigDataPtr awt_data) jobject getColorSpace(JNIEnv* env, jint csID) { jclass clazz; - jobject cspaceL; jmethodID mid; clazz = (*env)->FindClass(env,"java/awt/color/ColorSpace"); @@ -1033,7 +1032,6 @@ jobject awtJNI_GetColorModel(JNIEnv *env, AwtGraphicsConfigDataPtr aData) jobject validBits = NULL; ColorEntry *c; int i, allocAllGray, b, allvalid, paletteSize; - jlong pData; if (aData->awt_visInfo.depth == 12) { paletteSize = MAX_PALETTE12_SIZE; @@ -1233,11 +1231,10 @@ jobject awtJNI_GetColorModel(JNIEnv *env, AwtGraphicsConfigDataPtr aData) void awt_allocate_systemrgbcolors (jint *rgbColors, int num_colors, AwtGraphicsConfigDataPtr awtData) { - int i, pixel; - for (i = 0; i < num_colors; i++) - pixel = alloc_col (awt_display, awtData->awt_cmap, red (rgbColors [i]), - green (rgbColors [i]), blue (rgbColors [i]), -1, - awtData); + for (int i = 0; i < num_colors; i++) + alloc_col (awt_display, awtData->awt_cmap, red (rgbColors [i]), + green (rgbColors [i]), blue (rgbColors [i]), -1, + awtData); } int diff --git a/src/java.desktop/unix/native/common/awt/fontpath.c b/src/java.desktop/unix/native/common/awt/fontpath.c index b270a3fc94d7f..2da0ec0328bee 100644 --- a/src/java.desktop/unix/native/common/awt/fontpath.c +++ b/src/java.desktop/unix/native/common/awt/fontpath.c @@ -100,7 +100,6 @@ typedef struct { jboolean isDisplayLocal(JNIEnv *env) { static jboolean isLocal = False; static jboolean isLocalSet = False; - jboolean ret; if (! isLocalSet) { jclass geCls = (*env)->FindClass(env, "java/awt/GraphicsEnvironment"); @@ -134,7 +133,7 @@ jboolean isDisplayLocal(JNIEnv *env) { static char **getX11FontPath () { char **x11Path, **fontdirs; - int i, pos, slen, nPaths, numDirs; + int i, pos, slen, nPaths; x11Path = XGetFontPath (awt_display, &nPaths); @@ -533,7 +532,6 @@ static char **getFontConfigLocations() { char **fontdirs; int numdirs = 0; - FcInitLoadConfigFuncType FcInitLoadConfig; FcPatternBuildFuncType FcPatternBuild; FcObjectSetFuncType FcObjectSetBuild; FcFontListFuncType FcFontList; @@ -543,14 +541,10 @@ static char **getFontConfigLocations() { FcObjectSetDestroyFuncType FcObjectSetDestroy; FcFontSetDestroyFuncType FcFontSetDestroy; - FcConfig *fontconfig; FcPattern *pattern; FcObjectSet *objset; FcFontSet *fontSet; - FcStrList *strList; - FcChar8 *str; - int i, f, found, len=0; - char **fontPath; + int i, f, found; void* libfontconfig = openFontConfig(); diff --git a/src/java.desktop/unix/native/common/java2d/x11/X11FontScaler_md.c b/src/java.desktop/unix/native/common/java2d/x11/X11FontScaler_md.c index 2ab6f287b690f..521b7cfef3ab4 100644 --- a/src/java.desktop/unix/native/common/java2d/x11/X11FontScaler_md.c +++ b/src/java.desktop/unix/native/common/java2d/x11/X11FontScaler_md.c @@ -43,8 +43,6 @@ static GC pixmapGC = 0; static Pixmap pixmap = 0; -static Atom psAtom = 0; -static Atom fullNameAtom = 0; static int pixmapWidth = 0; static int pixmapHeight = 0; @@ -127,9 +125,9 @@ JNIEXPORT int JNICALL AWTCountFonts(char* xlfd) { } JNIEXPORT void JNICALL AWTLoadFont(char* name, AWTFont *pReturn) { - JNIEnv *env; *pReturn = NULL; #ifndef HEADLESS + JNIEnv *env; FONT_AWT_LOCK(); *pReturn = (AWTFont)XLoadQueryFont(awt_display, name); AWT_UNLOCK(); @@ -268,7 +266,7 @@ JNIEXPORT jlong JNICALL AWTFontGenerateImage(AWTFont pFont, AWTChar2b* xChar) { XCharStruct xcs; XImage *ximage; int h, i, j, nbytes; - unsigned char *srcRow, *dstRow, *dstByte; + unsigned char *srcRow, *dstRow; int wholeByteCount, remainingBitsCount; unsigned int imageSize; JNIEnv *env; diff --git a/src/java.desktop/unix/native/common/java2d/x11/X11Renderer.c b/src/java.desktop/unix/native/common/java2d/x11/X11Renderer.c index 871c129ca913d..216fe8090ff2e 100644 --- a/src/java.desktop/unix/native/common/java2d/x11/X11Renderer.c +++ b/src/java.desktop/unix/native/common/java2d/x11/X11Renderer.c @@ -571,7 +571,6 @@ Java_sun_java2d_x11_X11Renderer_XDoPath #ifndef HEADLESS X11SDOps *xsdo = (X11SDOps *) pXSData; jarray typesArray; - jobject pointArray; jarray coordsArray; jint numTypes; jint fillRule; diff --git a/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c b/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c index 36d6feb6029a7..e62ccff4653a2 100644 --- a/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c +++ b/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c @@ -882,11 +882,9 @@ static void X11SD_GetRasInfo(JNIEnv *env, } else #endif /* MITSHM */ if (xpriv->lockType == X11SD_LOCK_BY_XIMAGE) { - int x, y, w, h; + int x, y; x = pRasInfo->bounds.x1; y = pRasInfo->bounds.y1; - w = pRasInfo->bounds.x2 - x; - h = pRasInfo->bounds.y2 - y; xpriv->img = X11SD_GetImage(env, xsdo, &pRasInfo->bounds, lockFlags); if (xpriv->img) { diff --git a/src/java.desktop/unix/native/common/java2d/x11/X11TextRenderer_md.c b/src/java.desktop/unix/native/common/java2d/x11/X11TextRenderer_md.c index c7aff6f34c84f..d50ef00f94532 100644 --- a/src/java.desktop/unix/native/common/java2d/x11/X11TextRenderer_md.c +++ b/src/java.desktop/unix/native/common/java2d/x11/X11TextRenderer_md.c @@ -213,7 +213,7 @@ AWTDrawGlyphList(JNIEnv *env, jobject xtr, XImage *theImage; Pixmap thePixmap; XGCValues xgcv; - int scan, screen; + int screen; AwtGraphicsConfigDataPtr cData; X11SDOps *xsdo = (X11SDOps *)jlong_to_ptr(dstData); jint cx1, cy1, cx2, cy2; @@ -236,8 +236,6 @@ AWTDrawGlyphList(JNIEnv *env, jobject xtr, thePixmap = cData->monoPixmap; theGC = cData->monoPixmapGC; - scan = theImage->bytes_per_line; - xgcv.fill_style = FillStippled; xgcv.stipple = thePixmap; xgcv.ts_x_origin = bounds->x1; diff --git a/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c b/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c index b2dedca351c5f..389e25caaec0c 100644 --- a/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c +++ b/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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 @@ -116,44 +116,41 @@ AWT_OnLoad(JavaVM *vm, void *reserved) } jvm = vm; -#ifndef STATIC_BUILD - /* Get address of this library and the directory containing it. */ - dladdr((void *)AWT_OnLoad, &dlinfo); - realpath((char *)dlinfo.dli_fname, buf); - len = strlen(buf); - p = strrchr(buf, '/'); -#endif + /* * The code below is responsible for * loading appropriate awt library, i.e. libawt_xawt or libawt_headless */ #ifdef MACOSX - tk = LWAWT_PATH; + tk = LWAWT_PATH; #else - tk = XAWT_PATH; -#endif + tk = XAWT_PATH; -#ifndef MACOSX if (AWTIsHeadless()) { tk = HEADLESS_PATH; } #endif -#ifndef STATIC_BUILD - /* Calculate library name to load */ - strncpy(p, tk, MAXPATHLEN-len-1); -#endif + if (!JVM_IsStaticallyLinked()) { + /* Get address of this library and the directory containing it. */ + dladdr((void *)AWT_OnLoad, &dlinfo); + realpath((char *)dlinfo.dli_fname, buf); + len = strlen(buf); + p = strrchr(buf, '/'); -#ifndef STATIC_BUILD - jstring jbuf = JNU_NewStringPlatform(env, buf); - CHECK_EXCEPTION_FATAL(env, "Could not allocate library name"); - JNU_CallStaticMethodByName(env, NULL, "java/lang/System", "load", - "(Ljava/lang/String;)V", - jbuf); + /* Calculate library name to load */ + strncpy(p, tk, MAXPATHLEN-len-1); + + jstring jbuf = JNU_NewStringPlatform(env, buf); + CHECK_EXCEPTION_FATAL(env, "Could not allocate library name"); + JNU_CallStaticMethodByName(env, NULL, "java/lang/System", "load", + "(Ljava/lang/String;)V", + jbuf); + + awtHandle = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL); + } - awtHandle = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL); -#endif return JNI_VERSION_1_2; } diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c index aa2e88940dcae..33d2aeb66bbc1 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c @@ -304,7 +304,6 @@ getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) { AwtGraphicsConfigDataPtr *graphicsConfigs; AwtGraphicsConfigDataPtr defaultConfig; int ind; - char errmsg[128]; int xinawareScreen; void* xrenderLibHandle = NULL; XRenderFindVisualFormatFunc* xrenderFindVisualFormat = NULL; @@ -722,7 +721,6 @@ awt_init_Display(JNIEnv *env, jobject this) jclass klass; Display *dpy; char errmsg[128]; - int i; if (awt_display) { return awt_display; @@ -872,7 +870,6 @@ extern int mitShmPermissionMask; void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) { XShmSegmentInfo shminfo; int XShmMajor, XShmMinor; - int a, b, c; AWT_LOCK(); if (canUseShmExt != UNSET_MITSHM) { @@ -1154,7 +1151,7 @@ JNIEnv *env, jobject this, jint visualNum, jint screen) AwtGraphicsConfigData *adata = NULL; AwtScreenData asd = x11Screens[screen]; - int i, n; + int i; int depth; XImage * tempImage; diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.c b/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.c index e2e3cd1180948..93c1f4d0c1a3f 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.c @@ -793,8 +793,6 @@ static list_ptr make_region_list(Display *disp, Window win, XRectangle *bbox, XRectangle clip; int image_only; - int count=0 ; - *hasNonDefault = False; XUnionRectWithRegion( bbox, bbox_region, bbox_region); XGetWindowAttributes( disp, win, &win_attrs); @@ -823,8 +821,6 @@ static list_ptr make_region_list(Display *disp, Window win, XRectangle *bbox, malloc( sizeof( image_region_type)))) { return (list_ptr) NULL; } - count++; - new_reg->visible_region = XCreateRegion(); new_reg->win = base_src->win; new_reg->vis = base_src->vis; diff --git a/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c b/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c index e990cd9014a04..5a008d10a482c 100644 --- a/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c +++ b/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c @@ -209,7 +209,7 @@ FreeColors(Display * display, Screen * screen, int numColors, } static void SplashCenter(Splash * splash) { - Atom type, atom, actual_type; + Atom atom, actual_type; int status, actual_format; unsigned long nitems, bytes_after; CARD16 *prop = NULL; @@ -251,8 +251,6 @@ static void SplashUpdateSizeHints(Splash * splash) { void SplashCreateWindow(Splash * splash) { - XSizeHints sizeHints; - XSetWindowAttributes attr; attr.backing_store = NotUseful; @@ -740,11 +738,10 @@ void SplashCreateThread(Splash * splash) { pthread_t thr; pthread_attr_t attr; - int rc; int rslt = pthread_attr_init(&attr); if (rslt != 0) return; - rc = pthread_create(&thr, &attr, SplashScreenThread, (void *) splash); + pthread_create(&thr, &attr, SplashScreenThread, (void *) splash); pthread_attr_destroy(&attr); } diff --git a/src/java.management/share/classes/java/lang/management/ManagementFactory.java b/src/java.management/share/classes/java/lang/management/ManagementFactory.java index b1ac1d0391e54..a95102cd1258b 100644 --- a/src/java.management/share/classes/java/lang/management/ManagementFactory.java +++ b/src/java.management/share/classes/java/lang/management/ManagementFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,7 +95,6 @@ *

* An application can access a platform MXBean in the following ways: *

1. Direct access to an MXBean interface

- *
*
    *
  • Get an MXBean instance by calling the * {@link #getPlatformMXBean(Class) getPlatformMXBean} or @@ -130,7 +129,6 @@ * for details. *
  • *
- *
* *

* The {@link #getPlatformManagementInterfaces getPlatformManagementInterfaces} diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/NaiveHuffman.java b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/NaiveHuffman.java deleted file mode 100644 index 8a076ca67cb6b..0000000000000 --- a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/NaiveHuffman.java +++ /dev/null @@ -1,691 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.internal.net.http.hpack; - -import java.io.IOException; -import java.nio.ByteBuffer; - -import static java.lang.String.format; - -/** - * Huffman coding table. - * - *

Instances of this class are safe for use by multiple threads. - * - * @since 9 - */ -public final class NaiveHuffman { - - // TODO: check if reset is done in both reader and writer - - static final class Reader implements Huffman.Reader { - - private Node curr; // position in the trie - private int len; // length of the path from the root to 'curr' - private int p; // byte probe - - { - reset(); - } - - @Override - public void read(ByteBuffer source, - Appendable destination, - boolean isLast) throws IOException { - read(source, destination, true, isLast); - } - - // Takes 'isLast' rather than returns whether the reading is done or - // not, for more informative exceptions. - void read(ByteBuffer source, - Appendable destination, - boolean reportEOS, /* reportEOS is exposed for tests */ - boolean isLast) throws IOException { - Node c = curr; - int l = len; - /* - Since ByteBuffer is itself stateful, its position is - remembered here NOT as a part of Reader's state, - but to set it back in the case of a failure - */ - int pos = source.position(); - - while (source.hasRemaining()) { - int d = source.get(); - for (; p != 0; p >>= 1) { - c = c.getChild(p & d); - l++; - if (c.isLeaf()) { - if (reportEOS && c.isEOSPath) { - throw new IOException("Encountered EOS"); - } - char ch; - try { - ch = c.getChar(); - } catch (IllegalStateException e) { - source.position(pos); // do we need this? - throw new IOException(e); - } - try { - destination.append(ch); - } catch (IOException e) { - source.position(pos); // do we need this? - throw e; - } - c = INSTANCE.root; - l = 0; - } - curr = c; - len = l; - } - resetProbe(); - pos++; - } - if (!isLast) { - return; // it's too early to jump to any conclusions, let's wait - } - if (c.isLeaf()) { - return; // it's perfectly ok, no extra padding bits - } - if (c.isEOSPath && len <= 7) { - return; // it's ok, some extra padding bits - } - if (c.isEOSPath) { - throw new IOException( - "Padding is too long (len=" + len + ") " + - "or unexpected end of data"); - } - throw new IOException( - "Not a EOS prefix padding or unexpected end of data"); - } - - @Override - public void reset() { - curr = INSTANCE.root; - len = 0; - resetProbe(); - } - - private void resetProbe() { - p = 0x80; - } - } - - static final class Writer implements Huffman.Writer { - - private int pos; // position in 'source' - private int avail = 8; // number of least significant bits available in 'curr' - private int curr; // next byte to put to the destination - private int rem; // number of least significant bits in 'code' yet to be processed - private int code; // current code being written - - private CharSequence source; - private int end; - - @Override - public Writer from(CharSequence input, int start, int end) { - if (start < 0 || end < 0 || end > input.length() || start > end) { - throw new IndexOutOfBoundsException( - String.format("input.length()=%s, start=%s, end=%s", - input.length(), start, end)); - } - pos = start; - this.end = end; - this.source = input; - return this; - } - - @Override - public boolean write(ByteBuffer destination) { - for (; pos < end; pos++) { - if (rem == 0) { - Code desc = INSTANCE.codeOf(source.charAt(pos)); - rem = desc.length; - code = desc.code; - } - while (rem > 0) { - if (rem < avail) { - curr |= (code << (avail - rem)); - avail -= rem; - rem = 0; - } else { - int c = (curr | (code >>> (rem - avail))); - if (destination.hasRemaining()) { - destination.put((byte) c); - } else { - return false; - } - curr = c; - code <<= (32 - rem + avail); // throw written bits off the cliff (is this Sparta?) - code >>>= (32 - rem + avail); // return to the position - rem -= avail; - curr = 0; - avail = 8; - } - } - } - - if (avail < 8) { // have to pad - if (destination.hasRemaining()) { - destination.put((byte) (curr | (INSTANCE.EOS.code >>> (INSTANCE.EOS.length - avail)))); - avail = 8; - } else { - return false; - } - } - - return true; - } - - @Override - public Writer reset() { - source = null; - end = -1; - pos = -1; - avail = 8; - curr = 0; - code = 0; - return this; - } - - @Override - public int lengthOf(CharSequence value, int start, int end) { - return INSTANCE.lengthOf(value, start, end); - } - } - - /** - * Shared instance. - */ - public static final NaiveHuffman INSTANCE = new NaiveHuffman(); - - private final Code EOS = new Code(0x3fffffff, 30); - private final Code[] codes = new Code[257]; - private final Node root = new Node() { - @Override - public String toString() { return "root"; } - }; - - // TODO: consider builder and immutable trie - private NaiveHuffman() { - // @formatter:off - addChar(0, 0x1ff8, 13); - addChar(1, 0x7fffd8, 23); - addChar(2, 0xfffffe2, 28); - addChar(3, 0xfffffe3, 28); - addChar(4, 0xfffffe4, 28); - addChar(5, 0xfffffe5, 28); - addChar(6, 0xfffffe6, 28); - addChar(7, 0xfffffe7, 28); - addChar(8, 0xfffffe8, 28); - addChar(9, 0xffffea, 24); - addChar(10, 0x3ffffffc, 30); - addChar(11, 0xfffffe9, 28); - addChar(12, 0xfffffea, 28); - addChar(13, 0x3ffffffd, 30); - addChar(14, 0xfffffeb, 28); - addChar(15, 0xfffffec, 28); - addChar(16, 0xfffffed, 28); - addChar(17, 0xfffffee, 28); - addChar(18, 0xfffffef, 28); - addChar(19, 0xffffff0, 28); - addChar(20, 0xffffff1, 28); - addChar(21, 0xffffff2, 28); - addChar(22, 0x3ffffffe, 30); - addChar(23, 0xffffff3, 28); - addChar(24, 0xffffff4, 28); - addChar(25, 0xffffff5, 28); - addChar(26, 0xffffff6, 28); - addChar(27, 0xffffff7, 28); - addChar(28, 0xffffff8, 28); - addChar(29, 0xffffff9, 28); - addChar(30, 0xffffffa, 28); - addChar(31, 0xffffffb, 28); - addChar(32, 0x14, 6); - addChar(33, 0x3f8, 10); - addChar(34, 0x3f9, 10); - addChar(35, 0xffa, 12); - addChar(36, 0x1ff9, 13); - addChar(37, 0x15, 6); - addChar(38, 0xf8, 8); - addChar(39, 0x7fa, 11); - addChar(40, 0x3fa, 10); - addChar(41, 0x3fb, 10); - addChar(42, 0xf9, 8); - addChar(43, 0x7fb, 11); - addChar(44, 0xfa, 8); - addChar(45, 0x16, 6); - addChar(46, 0x17, 6); - addChar(47, 0x18, 6); - addChar(48, 0x0, 5); - addChar(49, 0x1, 5); - addChar(50, 0x2, 5); - addChar(51, 0x19, 6); - addChar(52, 0x1a, 6); - addChar(53, 0x1b, 6); - addChar(54, 0x1c, 6); - addChar(55, 0x1d, 6); - addChar(56, 0x1e, 6); - addChar(57, 0x1f, 6); - addChar(58, 0x5c, 7); - addChar(59, 0xfb, 8); - addChar(60, 0x7ffc, 15); - addChar(61, 0x20, 6); - addChar(62, 0xffb, 12); - addChar(63, 0x3fc, 10); - addChar(64, 0x1ffa, 13); - addChar(65, 0x21, 6); - addChar(66, 0x5d, 7); - addChar(67, 0x5e, 7); - addChar(68, 0x5f, 7); - addChar(69, 0x60, 7); - addChar(70, 0x61, 7); - addChar(71, 0x62, 7); - addChar(72, 0x63, 7); - addChar(73, 0x64, 7); - addChar(74, 0x65, 7); - addChar(75, 0x66, 7); - addChar(76, 0x67, 7); - addChar(77, 0x68, 7); - addChar(78, 0x69, 7); - addChar(79, 0x6a, 7); - addChar(80, 0x6b, 7); - addChar(81, 0x6c, 7); - addChar(82, 0x6d, 7); - addChar(83, 0x6e, 7); - addChar(84, 0x6f, 7); - addChar(85, 0x70, 7); - addChar(86, 0x71, 7); - addChar(87, 0x72, 7); - addChar(88, 0xfc, 8); - addChar(89, 0x73, 7); - addChar(90, 0xfd, 8); - addChar(91, 0x1ffb, 13); - addChar(92, 0x7fff0, 19); - addChar(93, 0x1ffc, 13); - addChar(94, 0x3ffc, 14); - addChar(95, 0x22, 6); - addChar(96, 0x7ffd, 15); - addChar(97, 0x3, 5); - addChar(98, 0x23, 6); - addChar(99, 0x4, 5); - addChar(100, 0x24, 6); - addChar(101, 0x5, 5); - addChar(102, 0x25, 6); - addChar(103, 0x26, 6); - addChar(104, 0x27, 6); - addChar(105, 0x6, 5); - addChar(106, 0x74, 7); - addChar(107, 0x75, 7); - addChar(108, 0x28, 6); - addChar(109, 0x29, 6); - addChar(110, 0x2a, 6); - addChar(111, 0x7, 5); - addChar(112, 0x2b, 6); - addChar(113, 0x76, 7); - addChar(114, 0x2c, 6); - addChar(115, 0x8, 5); - addChar(116, 0x9, 5); - addChar(117, 0x2d, 6); - addChar(118, 0x77, 7); - addChar(119, 0x78, 7); - addChar(120, 0x79, 7); - addChar(121, 0x7a, 7); - addChar(122, 0x7b, 7); - addChar(123, 0x7ffe, 15); - addChar(124, 0x7fc, 11); - addChar(125, 0x3ffd, 14); - addChar(126, 0x1ffd, 13); - addChar(127, 0xffffffc, 28); - addChar(128, 0xfffe6, 20); - addChar(129, 0x3fffd2, 22); - addChar(130, 0xfffe7, 20); - addChar(131, 0xfffe8, 20); - addChar(132, 0x3fffd3, 22); - addChar(133, 0x3fffd4, 22); - addChar(134, 0x3fffd5, 22); - addChar(135, 0x7fffd9, 23); - addChar(136, 0x3fffd6, 22); - addChar(137, 0x7fffda, 23); - addChar(138, 0x7fffdb, 23); - addChar(139, 0x7fffdc, 23); - addChar(140, 0x7fffdd, 23); - addChar(141, 0x7fffde, 23); - addChar(142, 0xffffeb, 24); - addChar(143, 0x7fffdf, 23); - addChar(144, 0xffffec, 24); - addChar(145, 0xffffed, 24); - addChar(146, 0x3fffd7, 22); - addChar(147, 0x7fffe0, 23); - addChar(148, 0xffffee, 24); - addChar(149, 0x7fffe1, 23); - addChar(150, 0x7fffe2, 23); - addChar(151, 0x7fffe3, 23); - addChar(152, 0x7fffe4, 23); - addChar(153, 0x1fffdc, 21); - addChar(154, 0x3fffd8, 22); - addChar(155, 0x7fffe5, 23); - addChar(156, 0x3fffd9, 22); - addChar(157, 0x7fffe6, 23); - addChar(158, 0x7fffe7, 23); - addChar(159, 0xffffef, 24); - addChar(160, 0x3fffda, 22); - addChar(161, 0x1fffdd, 21); - addChar(162, 0xfffe9, 20); - addChar(163, 0x3fffdb, 22); - addChar(164, 0x3fffdc, 22); - addChar(165, 0x7fffe8, 23); - addChar(166, 0x7fffe9, 23); - addChar(167, 0x1fffde, 21); - addChar(168, 0x7fffea, 23); - addChar(169, 0x3fffdd, 22); - addChar(170, 0x3fffde, 22); - addChar(171, 0xfffff0, 24); - addChar(172, 0x1fffdf, 21); - addChar(173, 0x3fffdf, 22); - addChar(174, 0x7fffeb, 23); - addChar(175, 0x7fffec, 23); - addChar(176, 0x1fffe0, 21); - addChar(177, 0x1fffe1, 21); - addChar(178, 0x3fffe0, 22); - addChar(179, 0x1fffe2, 21); - addChar(180, 0x7fffed, 23); - addChar(181, 0x3fffe1, 22); - addChar(182, 0x7fffee, 23); - addChar(183, 0x7fffef, 23); - addChar(184, 0xfffea, 20); - addChar(185, 0x3fffe2, 22); - addChar(186, 0x3fffe3, 22); - addChar(187, 0x3fffe4, 22); - addChar(188, 0x7ffff0, 23); - addChar(189, 0x3fffe5, 22); - addChar(190, 0x3fffe6, 22); - addChar(191, 0x7ffff1, 23); - addChar(192, 0x3ffffe0, 26); - addChar(193, 0x3ffffe1, 26); - addChar(194, 0xfffeb, 20); - addChar(195, 0x7fff1, 19); - addChar(196, 0x3fffe7, 22); - addChar(197, 0x7ffff2, 23); - addChar(198, 0x3fffe8, 22); - addChar(199, 0x1ffffec, 25); - addChar(200, 0x3ffffe2, 26); - addChar(201, 0x3ffffe3, 26); - addChar(202, 0x3ffffe4, 26); - addChar(203, 0x7ffffde, 27); - addChar(204, 0x7ffffdf, 27); - addChar(205, 0x3ffffe5, 26); - addChar(206, 0xfffff1, 24); - addChar(207, 0x1ffffed, 25); - addChar(208, 0x7fff2, 19); - addChar(209, 0x1fffe3, 21); - addChar(210, 0x3ffffe6, 26); - addChar(211, 0x7ffffe0, 27); - addChar(212, 0x7ffffe1, 27); - addChar(213, 0x3ffffe7, 26); - addChar(214, 0x7ffffe2, 27); - addChar(215, 0xfffff2, 24); - addChar(216, 0x1fffe4, 21); - addChar(217, 0x1fffe5, 21); - addChar(218, 0x3ffffe8, 26); - addChar(219, 0x3ffffe9, 26); - addChar(220, 0xffffffd, 28); - addChar(221, 0x7ffffe3, 27); - addChar(222, 0x7ffffe4, 27); - addChar(223, 0x7ffffe5, 27); - addChar(224, 0xfffec, 20); - addChar(225, 0xfffff3, 24); - addChar(226, 0xfffed, 20); - addChar(227, 0x1fffe6, 21); - addChar(228, 0x3fffe9, 22); - addChar(229, 0x1fffe7, 21); - addChar(230, 0x1fffe8, 21); - addChar(231, 0x7ffff3, 23); - addChar(232, 0x3fffea, 22); - addChar(233, 0x3fffeb, 22); - addChar(234, 0x1ffffee, 25); - addChar(235, 0x1ffffef, 25); - addChar(236, 0xfffff4, 24); - addChar(237, 0xfffff5, 24); - addChar(238, 0x3ffffea, 26); - addChar(239, 0x7ffff4, 23); - addChar(240, 0x3ffffeb, 26); - addChar(241, 0x7ffffe6, 27); - addChar(242, 0x3ffffec, 26); - addChar(243, 0x3ffffed, 26); - addChar(244, 0x7ffffe7, 27); - addChar(245, 0x7ffffe8, 27); - addChar(246, 0x7ffffe9, 27); - addChar(247, 0x7ffffea, 27); - addChar(248, 0x7ffffeb, 27); - addChar(249, 0xffffffe, 28); - addChar(250, 0x7ffffec, 27); - addChar(251, 0x7ffffed, 27); - addChar(252, 0x7ffffee, 27); - addChar(253, 0x7ffffef, 27); - addChar(254, 0x7fffff0, 27); - addChar(255, 0x3ffffee, 26); - addEOS (256, EOS.code, EOS.length); - // @formatter:on - } - - - /** - * Calculates the number of bytes required to represent the given {@code - * CharSequence} with the Huffman coding. - * - * @param value - * characters - * - * @return number of bytes - * - * @throws NullPointerException - * if the value is null - */ - public int lengthOf(CharSequence value) { - return lengthOf(value, 0, value.length()); - } - - /** - * Calculates the number of bytes required to represent a subsequence of the - * given {@code CharSequence} with the Huffman coding. - * - * @param value - * characters - * @param start - * the start index, inclusive - * @param end - * the end index, exclusive - * - * @return number of bytes - * - * @throws NullPointerException - * if the value is null - * @throws IndexOutOfBoundsException - * if any invocation of {@code value.charAt(i)}, where - * {@code start <= i < end} would throw an IndexOutOfBoundsException - */ - public int lengthOf(CharSequence value, int start, int end) { - int len = 0; - for (int i = start; i < end; i++) { - char c = value.charAt(i); - len += INSTANCE.codeOf(c).length; - } - // Integer division with ceiling, assumption: - assert (len / 8 + (len % 8 != 0 ? 1 : 0)) == (len + 7) / 8 : len; - return (len + 7) / 8; - } - - private void addChar(int c, int code, int bitLength) { - addLeaf(c, code, bitLength, false); - codes[c] = new Code(code, bitLength); - } - - private void addEOS(int c, int code, int bitLength) { - addLeaf(c, code, bitLength, true); - codes[c] = new Code(code, bitLength); - } - - private void addLeaf(int c, int code, int bitLength, boolean isEOS) { - if (bitLength < 1) { - throw new IllegalArgumentException("bitLength < 1"); - } - Node curr = root; - for (int p = 1 << bitLength - 1; p != 0 && !curr.isLeaf(); p = p >> 1) { - curr.isEOSPath |= isEOS; // If it's already true, it can't become false - curr = curr.addChildIfAbsent(p & code); - } - curr.isEOSPath |= isEOS; // The last one needs to have this property as well - if (curr.isLeaf()) { - throw new IllegalStateException("Specified code is already taken"); - } - curr.setChar((char) c); - } - - private Code codeOf(char c) { - if (c > 255) { - throw new IllegalArgumentException("char=" + ((int) c)); - } - return codes[c]; - } - - // - // For debugging/testing purposes - // - Node getRoot() { - return root; - } - - // - // Guarantees: - // - // if (isLeaf() == true) => getChar() is a legal call - // if (isLeaf() == false) => getChild(i) is a legal call (though it can - // return null) - // - static class Node { - - Node left; - Node right; - boolean isEOSPath; - - boolean charIsSet; - char c; - - Node getChild(int selector) { - if (isLeaf()) { - throw new IllegalStateException("This is a leaf node"); - } - Node result = selector == 0 ? left : right; - if (result == null) { - throw new IllegalStateException(format( - "Node doesn't have a child (selector=%s)", selector)); - } - return result; - } - - boolean isLeaf() { - return charIsSet; - } - - char getChar() { - if (!isLeaf()) { - throw new IllegalStateException("This node is not a leaf node"); - } - return c; - } - - void setChar(char c) { - if (charIsSet) { - throw new IllegalStateException( - "This node has been taken already"); - } - if (left != null || right != null) { - throw new IllegalStateException("The node cannot be made " - + "a leaf as it's already has a child"); - } - this.c = c; - charIsSet = true; - } - - Node addChildIfAbsent(int i) { - if (charIsSet) { - throw new IllegalStateException("The node cannot have a child " - + "as it's already a leaf node"); - } - Node child; - if (i == 0) { - if ((child = left) == null) { - child = left = new Node(); - } - } else { - if ((child = right) == null) { - child = right = new Node(); - } - } - return child; - } - - @Override - public String toString() { - if (isLeaf()) { - if (isEOSPath) { - return "EOS"; - } else { - return format("char: (%3s) '%s'", (int) c, c); - } - } - return "/\\"; - } - } - - // TODO: value-based class? - // FIXME: can we re-use Node instead of this class? - private static final class Code { - - final int code; - final int length; - - private Code(int code, int length) { - this.code = code; - this.length = length; - } - - public int getCode() { - return code; - } - - public int getLength() { - return length; - } - - @Override - public String toString() { - long p = 1 << length; - return Long.toBinaryString(code + p).substring(1) - + ", length=" + length; - } - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/CodeWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/CodeWriter.java index 8b518b14b6e72..519a5adcf6278 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/CodeWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/CodeWriter.java @@ -155,7 +155,7 @@ public void writeInstr(int pc, Instruction ins, CodeAttribute lr) { case NewObjectInstruction instr -> printConstantPoolRef(instr.className()); case NewPrimitiveArrayInstruction instr -> - print(" " + instr.typeKind().typeName()); + print(" " + instr.typeKind().upperBound().displayName()); case NewReferenceArrayInstruction instr -> printConstantPoolRef(instr.componentType()); case TableSwitchInstruction instr -> { diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/transport.c b/src/jdk.jdwp.agent/share/native/libjdwp/transport.c index 273bb7ad9c148..f67e9da47ea94 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/transport.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/transport.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ * questions. */ +#include "jvm.h" #include "util.h" #include "utf_util.h" #include "transport.h" @@ -121,7 +122,11 @@ static void * loadTransportLibrary(const char *libdir, const char *name) { char buf[MAXPATHLEN*2+100]; -#ifndef STATIC_BUILD + + if (JVM_IsStaticallyLinked()) { + return (dbgsysLoadLibrary(NULL, buf, sizeof(buf))); + } + void *handle; char libname[MAXPATHLEN+2]; const char *plibdir; @@ -145,9 +150,6 @@ loadTransportLibrary(const char *libdir, const char *name) /* dlopen (unix) / LoadLibrary (windows) the transport library */ handle = dbgsysLoadLibrary(libname, buf, sizeof(buf)); return handle; -#else - return (dbgsysLoadLibrary(NULL, buf, sizeof(buf))); -#endif } /* diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java index 1ce7054916ccd..7cc399019e697 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, 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 @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Objects; final class ChunkInputStream extends InputStream { private final Iterator chunks; @@ -85,10 +86,7 @@ public int read() throws IOException { if (r != -1) { return r; } - stream.close(); - currentChunk.release(); - stream = null; - currentChunk = null; + closeStream(); } if (!nextStream()) { return -1; @@ -97,14 +95,55 @@ public int read() throws IOException { } @Override - public void close() throws IOException { + public int read(byte[] buf, int off, int len) throws IOException { + Objects.checkFromIndexSize(off, len, buf.length); + if (len == 0) { + return 0; + } + + int totalRead = 0; + while (len > 0) { + if (stream == null) { + closeChunk(); + if (!nextStream()) { + return totalRead > 0 ? totalRead : -1; + } + } + int read = stream.read(buf, off, len); + if (read > -1) { + totalRead += read; + len -= read; + if (len == 0) { + return totalRead; + } + off += read; + } else { + closeStream(); + } + } + return totalRead; + } + + private void closeStream() throws IOException { if (stream != null) { stream.close(); stream = null; } - while (currentChunk != null) { + closeChunk(); + } + + private void closeChunk() { + if (currentChunk != null) { currentChunk.release(); currentChunk = null; + } + } + + @Override + public void close() throws IOException { + closeStream(); + while (currentChunk != null) { + closeChunk(); if (!nextChunk()) { return; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java index 5521336f93859..71dc97d114e2c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java @@ -562,7 +562,7 @@ void updateStaticCommit(BlockCodeBuilder blockCodeBuilder, Label excluded) { // write begin event getEventConfiguration(blockCodeBuilder); // stack: [EW], [EW], [EventConfiguration] - blockCodeBuilder.loadConstant(Opcode.LDC2_W, eventTypeId); + blockCodeBuilder.loadConstant(eventTypeId); // stack: [EW], [EW], [EventConfiguration] [long] invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.BEGIN_EVENT.method()); // stack: [EW], [integer] @@ -676,7 +676,7 @@ void updateInstanceCommit(BlockCodeBuilder blockCodeBuilder, Label end, Label ex // stack: [EW] [EW] getEventConfiguration(blockCodeBuilder); // stack: [EW] [EW] [EC] - blockCodeBuilder.loadConstant(Opcode.LDC2_W, eventTypeId); + blockCodeBuilder.loadConstant(eventTypeId); invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.BEGIN_EVENT.method()); // stack: [EW] [int] blockCodeBuilder.ifeq(excluded); diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java index 96b7c76f24ddd..1a9404b210d5e 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java @@ -1562,7 +1562,7 @@ void hashForModule(String name, byte[] hash) { cob.aload(BUILDER_VAR) .loadConstant(name) .loadConstant(hash.length) - .newarray(TypeKind.ByteType); + .newarray(TypeKind.BYTE); for (int i = 0; i < hash.length; i++) { cob.dup() // arrayref .loadConstant(i) diff --git a/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java b/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java index b1d86a743a5c3..cb8b3bdf0a620 100644 --- a/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java +++ b/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java @@ -47,6 +47,8 @@ * {@code null} unless it's stated otherwise. * * @see java.lang.management.ManagementFactory#getPlatformMXBeans(Class) + * + * @since 1.6 */ public interface HotSpotDiagnosticMXBean extends PlatformManagedObject { /** diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 2414f3d090a18..e5ac630c3384b 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -73,8 +73,6 @@ compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInf compiler/floatingpoint/TestSubnormalFloat.java 8317810 generic-i586 compiler/floatingpoint/TestSubnormalDouble.java 8317810 generic-i586 -compiler/startup/StartupOutput.java 8326615 generic-x64 - compiler/codecache/CodeCacheFullCountTest.java 8332954 generic-all compiler/interpreter/Test6833129.java 8335266 generic-i586 @@ -119,6 +117,7 @@ runtime/ErrorHandling/TestDwarf.java#checkDecoder 8305489 linux-all runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le runtime/Thread/TestAlwaysPreTouchStacks.java 8335167 macosx-aarch64 runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64 +runtime/exceptionMsgs/NoClassDefFoundError/NoClassDefFoundErrorTest.java 8339316 generic-all applications/jcstress/copy.java 8229852 linux-all diff --git a/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java b/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java index 0c4fb5a66ae93..d0b45333fb8b3 100644 --- a/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java +++ b/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -187,8 +187,17 @@ public static void main(String[] args) throws Exception { // Fails if not enough space for VM internal code long minUseSpace = WHITE_BOX.getUintxVMFlag("CodeCacheMinimumUseSpace"); - // minimum size: CodeCacheMinimumUseSpace DEBUG_ONLY(* 3) - long minSize = (Platform.isDebugBuild() ? 3 : 1) * minUseSpace; + long nMethodSizeLimit = WHITE_BOX.getIntxVMFlag("NMethodSizeLimit"); + long codeEntryAlignment = WHITE_BOX.getIntxVMFlag("CodeEntryAlignment"); + long c1MinCodeCacheSize = 11 * nMethodSizeLimit / 10; + long c2MinCodeCacheSize = 2048 /* PhaseOutput::MAX_inst_size */ + + 128 /* PhaseOutput::MAX_stubs_size */ + + 4 * 1024 /* initial_const_capacity */ + + 2 * Math.max(64, codeEntryAlignment) /* 2 * CodeSection::end_slop() */ + + 2 * 128 /* sizeof(relocInfo) * PhaseOutput::MAX_locs_size */; + // minimum size: CompilerConfig::min_code_cache_size = + // CodeCacheMinimumUseSpace DEBUG_ONLY(* 3) + Compiler::code_buffer_size() + C2Compiler::initial_code_buffer_size()) + long minSize = minUseSpace * (Platform.isDebugBuild() ? 3 : 1) + c1MinCodeCacheSize + c2MinCodeCacheSize; pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+SegmentedCodeCache", "-XX:NonNMethodCodeHeapSize=" + minSize, "-XX:ReservedCodeCacheSize=" + minSize, diff --git a/test/jdk/java/foreign/TestFill.java b/test/jdk/java/foreign/TestFill.java new file mode 100644 index 0000000000000..e5f69587f2f6c --- /dev/null +++ b/test/jdk/java/foreign/TestFill.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2024, 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 + * @summary Test MemorySegment::fill + * @run junit TestFill + */ + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.lang.foreign.Arena; +import java.lang.foreign.ValueLayout; +import java.util.Arrays; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +final class TestFill { + + // Make sure negative values are treated as expected + private static final byte VALUE = -71; + + @ParameterizedTest + @MethodSource("sizes") + void testFill(int len) { + int offset = 16; + int expandedLen = offset + MAX_SIZE + offset; + + // Make sure fill only affects the intended region XXXXXX + // + // ................XXXXXX................ + // | offset | len | offset | + + try (var arena = Arena.ofConfined()) { + var segment = arena.allocate(expandedLen); + var slice = segment.asSlice(offset, len); + slice.fill(VALUE); + + var expected = new byte[expandedLen]; + Arrays.fill(expected, offset, offset + len, VALUE); + + // This checks the actual fill region as well as potential under and overflows + assertArrayEquals(expected, segment.toArray(ValueLayout.JAVA_BYTE)); + } + } + + @ParameterizedTest + @MethodSource("values") + void testValues(int value) { + int size = 0b1111; + try (var arena = Arena.ofConfined()) { + var segment = arena.allocate(size); + segment.fill((byte) value); + assertTrue(segment.elements(ValueLayout.JAVA_BYTE) + .map(s -> s.get(ValueLayout.JAVA_BYTE, 0)) + .allMatch(v -> v == value), "Failed to fill with value " + value); + } + } + + @ParameterizedTest + @MethodSource("sizes") + void testReadOnly(int len) { + try (var arena = Arena.ofConfined()) { + var segment = arena.allocate(10).asReadOnly(); + assertThrows(IllegalArgumentException.class, () -> segment.fill(VALUE)); + } + } + + @ParameterizedTest + @MethodSource("sizes") + void testConfinement(int len) { + try (var arena = Arena.ofConfined()) { + var segment = arena.allocate(10); + AtomicReference ex = new AtomicReference<>(); + CompletableFuture future = CompletableFuture.runAsync(() -> { + try { + segment.fill(VALUE); + } catch (RuntimeException e) { + ex.set(e); + } + }); + future.join(); + assertInstanceOf(WrongThreadException.class, ex.get()); + } + } + + @ParameterizedTest + @MethodSource("sizes") + void testScope(int len) { + var arena = Arena.ofConfined(); + var segment = arena.allocate(len); + arena.close(); + assertThrows(IllegalStateException.class, () -> segment.fill(VALUE)); + } + + private static final int MAX_SIZE = 1 << 10; + + private static Stream sizes() { + return IntStream.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 23, 32, 63, 128, 256, 511, MAX_SIZE) + .boxed() + .map(Arguments::of); + } + + private static Stream values() { + return IntStream.rangeClosed(Byte.MIN_VALUE, Byte.MAX_VALUE) + .boxed() + .map(Arguments::of); + } + +} diff --git a/test/jdk/java/lang/String/concat/HiddenClassUnloading.java b/test/jdk/java/lang/String/concat/HiddenClassUnloading.java index 9e682f38ef552..fef6455a05f97 100644 --- a/test/jdk/java/lang/String/concat/HiddenClassUnloading.java +++ b/test/jdk/java/lang/String/concat/HiddenClassUnloading.java @@ -43,7 +43,7 @@ public static void main(String[] args) throws Throwable { long initUnloadedClassCount = ManagementFactory.getClassLoadingMXBean().getUnloadedClassCount(); - for (int i = 0; i < 2000; i++) { + for (int i = 0; i < 12000; i++) { int radix = types.length; String str = Integer.toString(i, radix); int length = str.length(); diff --git a/test/jdk/java/net/httpclient/DependentPromiseActionsTest.java b/test/jdk/java/net/httpclient/DependentPromiseActionsTest.java index 4e17408ee6f50..32c594808a9c4 100644 --- a/test/jdk/java/net/httpclient/DependentPromiseActionsTest.java +++ b/test/jdk/java/net/httpclient/DependentPromiseActionsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,6 +73,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Flow; import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiPredicate; @@ -112,6 +113,7 @@ public class DependentPromiseActionsTest implements HttpServerAdapters { static volatile boolean tasksFailed; static final AtomicLong serverCount = new AtomicLong(); static final AtomicLong clientCount = new AtomicLong(); + static final AtomicInteger requestCount = new AtomicInteger(); static final long start = System.nanoTime(); public static String now() { long now = System.nanoTime() - start; @@ -244,14 +246,17 @@ HttpClient newHttpClient(boolean share) { } @Test(dataProvider = "noStalls") - public void testNoStalls(String uri, boolean sameClient) + public void testNoStalls(String rootUri, boolean sameClient) throws Exception { + if (!FAILURES.isEmpty()) return; HttpClient client = null; - out.printf("%ntestNoStalls(%s, %b)%n", uri, sameClient); + out.printf("%ntestNoStalls(%s, %b)%n", rootUri, sameClient); for (int i=0; i< ITERATION_COUNT; i++) { if (!sameClient || client == null) client = newHttpClient(sameClient); + String uri = rootUri + "/" + requestCount.incrementAndGet(); + out.printf("\tsending request %s%n", uri); HttpRequest req = HttpRequest.newBuilder(URI.create(uri)) .build(); BodyHandler> handler = @@ -331,6 +336,10 @@ private void testDependent(String name, String uri, boolean sameClient, SubscriberType subscriberType) throws Exception { + if (!FAILURES.isEmpty()) { + out.printf("%s: skipping test - previous failure detected%n", name); + return; + } out.printf("%n%s%s%n", now(), name); try { testDependent(uri, sameClient, handlers, finisher, @@ -341,7 +350,7 @@ private void testDependent(String name, String uri, boolean sameClient, } } - private void testDependent(String uri, boolean sameClient, + private void testDependent(String rootUri, boolean sameClient, Supplier> handlers, Finisher finisher, Extractor extractor, @@ -354,6 +363,8 @@ private void testDependent(String uri, boolean sameClient, if (!sameClient || client == null) client = newHttpClient(sameClient); + String uri = rootUri + "/" + requestCount.incrementAndGet(); + out.printf("\tsending request %s%n", uri); HttpRequest req = HttpRequest. newBuilder(URI.create(uri)) .build(); @@ -363,7 +374,13 @@ private void testDependent(String uri, boolean sameClient, System.out.println("try stalling in " + where); CompletableFuture> responseCF = client.sendAsync(req, handler, promiseHandler); - assert subscriberType == SubscriberType.LAZZY || !responseCF.isDone(); + // The body of the main response can be received before the body + // of the push promise handlers are received. + // The body of the main response doesn't stall, so the cf of + // the main response may be done here even for EAGER subscribers. + // We cannot make any assumption on the state of the main response + // cf here, so the only thing we can do is to call the finisher + // which will wait for them all. finisher.finish(where, responseCF, promiseHandler, extractor); } } diff --git a/test/jdk/java/net/httpclient/ProxyServer.java b/test/jdk/java/net/httpclient/ProxyServer.java index e07badd2bb7aa..7de14a79225a5 100644 --- a/test/jdk/java/net/httpclient/ProxyServer.java +++ b/test/jdk/java/net/httpclient/ProxyServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -195,6 +195,9 @@ class Connection { volatile InputStream clientIn, serverIn; volatile OutputStream clientOut, serverOut; + boolean proxyInClosed; // only accessed from synchronized block + boolean proxyOutClosed; // only accessed from synchronized block + final static int CR = 13; final static int LF = 10; @@ -594,9 +597,7 @@ synchronized void proxyCommon(boolean log) throws IOException { if (log) System.out.printf("Proxy Forwarding [request body]: total %d%n", body); } - closing = true; - serverSocket.close(); - clientSocket.close(); + closeClientIn(); } catch (IOException e) { if (!closing && debug) { System.out.println("Proxy: " + e); @@ -615,9 +616,7 @@ synchronized void proxyCommon(boolean log) throws IOException { if (log) System.out.printf("Proxy Forwarding [response]: %s%n", new String(bb, 0, n, UTF_8)); if (log) System.out.printf("Proxy Forwarding [response]: total %d%n", resp); } - closing = true; - serverSocket.close(); - clientSocket.close(); + closeClientOut(); } catch (IOException e) { if (!closing && debug) { System.out.println("Proxy: " + e); @@ -641,6 +640,28 @@ void doTunnel(String dest) throws IOException { proxyCommon(false); } + synchronized void closeClientIn() throws IOException { + closing = true; + proxyInClosed = true; + clientSocket.shutdownInput(); + serverSocket.shutdownOutput(); + if (proxyOutClosed) { + serverSocket.close(); + clientSocket.close(); + } + } + + synchronized void closeClientOut() throws IOException { + closing = true; + proxyOutClosed = true; + serverSocket.shutdownInput(); + clientSocket.shutdownOutput(); + if (proxyInClosed) { + serverSocket.close(); + clientSocket.close(); + } + } + @Override public String toString() { return "Proxy connection " + id + ", client sock:" + clientSocket; diff --git a/test/jdk/jdk/classfile/AdaptCodeTest.java b/test/jdk/jdk/classfile/AdaptCodeTest.java index ca9145d688521..80c526c63c736 100644 --- a/test/jdk/jdk/classfile/AdaptCodeTest.java +++ b/test/jdk/jdk/classfile/AdaptCodeTest.java @@ -95,7 +95,7 @@ void testSevenOfThirteenIterator() throws Exception { if ((val instanceof Integer) && ((Integer) val) == 13) { val = 7; } - codeB.loadConstant(i.opcode(), val); + codeB.loadConstant(val); } default -> codeB.with(codeE); } diff --git a/test/jdk/jdk/classfile/AdvancedTransformationsTest.java b/test/jdk/jdk/classfile/AdvancedTransformationsTest.java index 6c7194271a477..450f1279810d6 100644 --- a/test/jdk/jdk/classfile/AdvancedTransformationsTest.java +++ b/test/jdk/jdk/classfile/AdvancedTransformationsTest.java @@ -85,10 +85,10 @@ void testShiftLocals() throws Exception { mb.transformCode(com, new CodeTransform() { @Override public void atStart(CodeBuilder builder) { - builder.allocateLocal(TypeKind.ReferenceType); - builder.allocateLocal(TypeKind.LongType); - builder.allocateLocal(TypeKind.IntType); - builder.allocateLocal(TypeKind.DoubleType); + builder.allocateLocal(TypeKind.REFERENCE); + builder.allocateLocal(TypeKind.LONG); + builder.allocateLocal(TypeKind.INT); + builder.allocateLocal(TypeKind.DOUBLE); } @Override public void accept(CodeBuilder builder, CodeElement element) { @@ -324,7 +324,7 @@ private static byte[] instrument(ClassModel target, ClassModel instrumentor, Pre var storeStack = new ArrayDeque(); int slot = 0; if (!mm.flags().has(AccessFlag.STATIC)) - storeStack.push(StoreInstruction.of(TypeKind.ReferenceType, slot++)); + storeStack.push(StoreInstruction.of(TypeKind.REFERENCE, slot++)); for (var pt : mm.methodTypeSymbol().parameterList()) { var tk = TypeKind.from(pt); storeStack.push(StoreInstruction.of(tk, slot)); diff --git a/test/jdk/jdk/classfile/ArrayTest.java b/test/jdk/jdk/classfile/ArrayTest.java index 56b6d39a593c8..15293a1f33b16 100644 --- a/test/jdk/jdk/classfile/ArrayTest.java +++ b/test/jdk/jdk/classfile/ArrayTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,7 +88,7 @@ void testArrayNew() throws Exception { case 4: { NewPrimitiveArrayInstruction nai = (NewPrimitiveArrayInstruction) im; assertEquals(nai.opcode(), Opcode.NEWARRAY); - assertEquals(nai.typeKind(), TypeKind.DoubleType); + assertEquals(nai.typeKind(), TypeKind.DOUBLE); break; } } diff --git a/test/jdk/jdk/classfile/BuilderBlockTest.java b/test/jdk/jdk/classfile/BuilderBlockTest.java index 30a44491e6cea..5d9e70c5a30c7 100644 --- a/test/jdk/jdk/classfile/BuilderBlockTest.java +++ b/test/jdk/jdk/classfile/BuilderBlockTest.java @@ -259,9 +259,9 @@ void testAllocateLocal() { ClassFile.of().build(ClassDesc.of("Foo"), cb -> { cb.withMethod("foo", MethodTypeDesc.ofDescriptor("(IJI)V"), ClassFile.ACC_STATIC, mb -> mb.withCode(xb -> { - int slot1 = xb.allocateLocal(TypeKind.IntType); - int slot2 = xb.allocateLocal(TypeKind.LongType); - int slot3 = xb.allocateLocal(TypeKind.IntType); + int slot1 = xb.allocateLocal(TypeKind.INT); + int slot2 = xb.allocateLocal(TypeKind.LONG); + int slot3 = xb.allocateLocal(TypeKind.INT); assertEquals(slot1, 4); assertEquals(slot2, 5); @@ -277,15 +277,15 @@ void testAllocateLocalBlock() { cb.withMethod("foo", MethodTypeDesc.ofDescriptor("(IJI)V"), ClassFile.ACC_STATIC, mb -> mb.withCode(xb -> { xb.block(bb -> { - int slot1 = bb.allocateLocal(TypeKind.IntType); - int slot2 = bb.allocateLocal(TypeKind.LongType); - int slot3 = bb.allocateLocal(TypeKind.IntType); + int slot1 = bb.allocateLocal(TypeKind.INT); + int slot2 = bb.allocateLocal(TypeKind.LONG); + int slot3 = bb.allocateLocal(TypeKind.INT); assertEquals(slot1, 4); assertEquals(slot2, 5); assertEquals(slot3, 7); }); - int slot4 = xb.allocateLocal(TypeKind.IntType); + int slot4 = xb.allocateLocal(TypeKind.INT); assertEquals(slot4, 4); xb.return_(); })); @@ -299,20 +299,20 @@ void testAllocateLocalIfThen() { mb -> mb.withCode(xb -> { xb.iconst_0(); xb.ifThenElse(bb -> { - int slot1 = bb.allocateLocal(TypeKind.IntType); - int slot2 = bb.allocateLocal(TypeKind.LongType); - int slot3 = bb.allocateLocal(TypeKind.IntType); + int slot1 = bb.allocateLocal(TypeKind.INT); + int slot2 = bb.allocateLocal(TypeKind.LONG); + int slot3 = bb.allocateLocal(TypeKind.INT); assertEquals(slot1, 4); assertEquals(slot2, 5); assertEquals(slot3, 7); }, bb -> { - int slot1 = bb.allocateLocal(TypeKind.IntType); + int slot1 = bb.allocateLocal(TypeKind.INT); assertEquals(slot1, 4); }); - int slot4 = xb.allocateLocal(TypeKind.IntType); + int slot4 = xb.allocateLocal(TypeKind.INT); assertEquals(slot4, 4); xb.return_(); })); @@ -335,7 +335,7 @@ public void accept(CodeBuilder cob, CodeElement coe) { && se.utf8().equalsString("Output")) { assertFalse(foundItem); foundItem = true; - var i = cob.allocateLocal(TypeKind.IntType); + var i = cob.allocateLocal(TypeKind.INT); assertEquals(7, i, "Allocated new int slot"); } } @@ -373,8 +373,8 @@ void testAllocateLocalTransformingBufferedCode() throws IOException { ClassTransform bufferingTransform = (clb, cle) -> { if (cle instanceof MethodModel mm && mm.methodName().equalsString("work")) { clb.withMethodBody(mm.methodName(), mm.methodType(), mm.flags().flagsMask(), cob -> { - int d = cob.allocateLocal(TypeKind.IntType); - int e = cob.allocateLocal(TypeKind.IntType); + int d = cob.allocateLocal(TypeKind.INT); + int e = cob.allocateLocal(TypeKind.INT); assertEquals(5, d); assertEquals(6, e); diff --git a/test/jdk/jdk/classfile/BuilderTryCatchTest.java b/test/jdk/jdk/classfile/BuilderTryCatchTest.java index 192125c4bb6f2..3de1255916342 100644 --- a/test/jdk/jdk/classfile/BuilderTryCatchTest.java +++ b/test/jdk/jdk/classfile/BuilderTryCatchTest.java @@ -187,7 +187,7 @@ void testEmptyTry() { cb.withMethod("main", MethodTypeDesc.of(CD_String, CD_String.arrayType()), ACC_PUBLIC | ACC_STATIC, mb -> { mb.withCode(xb -> { - int stringSlot = xb.allocateLocal(TypeKind.ReferenceType); + int stringSlot = xb.allocateLocal(TypeKind.REFERENCE); xb.loadConstant("S"); xb.astore(stringSlot); @@ -218,12 +218,12 @@ void testLocalAllocation() throws Throwable { cb.withMethod("main", MethodTypeDesc.of(CD_String, CD_String.arrayType()), ACC_PUBLIC | ACC_STATIC, mb -> { mb.withCode(xb -> { - int stringSlot = xb.allocateLocal(TypeKind.ReferenceType); + int stringSlot = xb.allocateLocal(TypeKind.REFERENCE); xb.loadConstant("S"); xb.astore(stringSlot); xb.trying(tb -> { - int intSlot = tb.allocateLocal(TypeKind.IntType); + int intSlot = tb.allocateLocal(TypeKind.INT); tb.aload(0); tb.loadConstant(0); @@ -240,7 +240,7 @@ void testLocalAllocation() throws Throwable { catchBuilder.catching(CD_IOOBE, tb -> { tb.pop(); - int doubleSlot = tb.allocateLocal(TypeKind.DoubleType); + int doubleSlot = tb.allocateLocal(TypeKind.DOUBLE); tb.loadConstant(Math.PI); tb.dstore(doubleSlot); @@ -250,7 +250,7 @@ void testLocalAllocation() throws Throwable { }).catchingAll(tb -> { tb.pop(); - int refSlot = tb.allocateLocal(TypeKind.ReferenceType); + int refSlot = tb.allocateLocal(TypeKind.REFERENCE); tb.loadConstant("REF"); tb.astore(refSlot); @@ -281,7 +281,7 @@ static byte[] generateTryCatchMethod(Consumer c) { cb.withMethod("main", MethodTypeDesc.of(CD_String, CD_String.arrayType()), ACC_PUBLIC | ACC_STATIC, mb -> { mb.withCode(xb -> { - int stringSlot = xb.allocateLocal(TypeKind.ReferenceType); + int stringSlot = xb.allocateLocal(TypeKind.REFERENCE); xb.loadConstant("S"); xb.astore(stringSlot); diff --git a/test/jdk/jdk/classfile/LDCTest.java b/test/jdk/jdk/classfile/LDCTest.java index 7379218840e30..207d53e88204c 100644 --- a/test/jdk/jdk/classfile/LDCTest.java +++ b/test/jdk/jdk/classfile/LDCTest.java @@ -64,9 +64,9 @@ void testLDCisConvertedToLDCW() throws Exception { for (int i = 0; i <= 256/2 + 2; i++) { // two entries per String StringEntry s = cpb.stringEntry("string" + i); } - c0.loadConstant(LDC, "string0") - .loadConstant(LDC, "string131") - .loadConstant(LDC, "string50") + c0.ldc("string0") + .ldc("string131") + .ldc("string50") .loadConstant(-0.0f) .loadConstant(-0.0d) //non-LDC test cases diff --git a/test/jdk/jdk/classfile/OpcodesValidationTest.java b/test/jdk/jdk/classfile/OpcodesValidationTest.java index f44bdfd272559..2470fcf132c54 100644 --- a/test/jdk/jdk/classfile/OpcodesValidationTest.java +++ b/test/jdk/jdk/classfile/OpcodesValidationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,107 +23,29 @@ /* * @test - * @summary Testing ClassFile constant instruction opcodes. + * @summary Testing ClassFile constant instruction argument validation. * @run junit OpcodesValidationTest */ -import java.lang.constant.ClassDesc; -import java.lang.constant.ConstantDesc; -import static java.lang.constant.ConstantDescs.CD_void; -import java.lang.constant.MethodTypeDesc; +import java.lang.classfile.instruction.ConstantInstruction; +import org.junit.jupiter.api.Test; -import java.lang.reflect.AccessFlag; -import java.lang.classfile.ClassFile; -import java.lang.classfile.Opcode; -import org.junit.jupiter.api.*; -import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.Assertions.*; import static java.lang.classfile.Opcode.*; -import java.util.stream.Stream; -public class OpcodesValidationTest { - - record Case(Opcode opcode, Object constant) {} - - static Stream positiveCases() { - return Stream.of( - new Case(ACONST_NULL, null), - new Case(SIPUSH, (int)Short.MIN_VALUE), - new Case(SIPUSH, (int)Short.MAX_VALUE), - new Case(BIPUSH, (int)Byte.MIN_VALUE), - new Case(BIPUSH, (int)Byte.MAX_VALUE), - new Case(ICONST_M1, -1), - new Case(ICONST_0, 0), - new Case(ICONST_1, 1), - new Case(ICONST_2, 2), - new Case(ICONST_3, 3), - new Case(ICONST_4, 4), - new Case(ICONST_5, 5), - new Case(LCONST_0, 0l), - new Case(LCONST_0, 0), - new Case(LCONST_1, 1l), - new Case(LCONST_1, 1), - new Case(FCONST_0, 0.0f), - new Case(FCONST_1, 1.0f), - new Case(FCONST_2, 2.0f), - new Case(DCONST_0, 0.0d), - new Case(DCONST_1, 1.0d) - ); - } - - static Stream negativeCases() { - return Stream.of( - new Case(ACONST_NULL, 0), - new Case(SIPUSH, (int)Short.MIN_VALUE - 1), - new Case(SIPUSH, (int)Short.MAX_VALUE + 1), - new Case(BIPUSH, (int)Byte.MIN_VALUE - 1), - new Case(BIPUSH, (int)Byte.MAX_VALUE + 1), - new Case(ICONST_M1, -1l), - new Case(ICONST_0, 0l), - new Case(ICONST_1, 1l), - new Case(ICONST_2, 2l), - new Case(ICONST_3, 3l), - new Case(ICONST_4, 4l), - new Case(ICONST_5, 5l), - new Case(LCONST_0, null), - new Case(LCONST_0, 1l), - new Case(LCONST_1, 1.0d), - new Case(LCONST_1, 0), - new Case(FCONST_0, 0.0d), - new Case(FCONST_1, 1.01f), - new Case(FCONST_2, 2), - new Case(DCONST_0, 0.0f), - new Case(DCONST_1, 1.0f), - new Case(DCONST_1, 1) - ); - } - - @TestFactory - Stream testPositiveCases() { - return positiveCases().map(c -> dynamicTest(c.toString(), () -> testPositiveCase(c.opcode, c.constant))); - } - - private void testPositiveCase(Opcode opcode, Object constant) { - ClassFile.of().build(ClassDesc.of("MyClass"), - cb -> cb.withFlags(AccessFlag.PUBLIC) - .withMethod("", MethodTypeDesc.of(CD_void), 0, - mb -> mb.withCode( - codeb -> codeb.loadConstant(opcode, (ConstantDesc) constant)))); - } - - - @TestFactory - Stream testNegativeCases() { - return negativeCases().map(c -> dynamicTest( - c.toString(), - () -> assertThrows(IllegalArgumentException.class, () -> testNegativeCase(c.opcode, c.constant)) - )); - } - - private void testNegativeCase(Opcode opcode, Object constant) { - ClassFile.of().build(ClassDesc.of("MyClass"), - cb -> cb.withFlags(AccessFlag.PUBLIC) - .withMethod("", MethodTypeDesc.of(CD_void), 0, - mb -> mb .withCode( - codeb -> codeb.loadConstant(opcode, (ConstantDesc)constant)))); +class OpcodesValidationTest { + + @Test + void testArgumentConstant() { + assertDoesNotThrow(() -> ConstantInstruction.ofArgument(SIPUSH, 0)); + assertDoesNotThrow(() -> ConstantInstruction.ofArgument(SIPUSH, Short.MIN_VALUE)); + assertDoesNotThrow(() -> ConstantInstruction.ofArgument(SIPUSH, Short.MAX_VALUE)); + assertDoesNotThrow(() -> ConstantInstruction.ofArgument(BIPUSH, 0)); + assertDoesNotThrow(() -> ConstantInstruction.ofArgument(BIPUSH, Byte.MIN_VALUE)); + assertDoesNotThrow(() -> ConstantInstruction.ofArgument(BIPUSH, Byte.MAX_VALUE)); + + assertThrows(IllegalArgumentException.class, () -> ConstantInstruction.ofArgument(SIPUSH, (int)Short.MIN_VALUE - 1)); + assertThrows(IllegalArgumentException.class, () -> ConstantInstruction.ofArgument(SIPUSH, (int)Short.MAX_VALUE + 1)); + assertThrows(IllegalArgumentException.class, () -> ConstantInstruction.ofArgument(BIPUSH, (int)Byte.MIN_VALUE - 1)); + assertThrows(IllegalArgumentException.class, () -> ConstantInstruction.ofArgument(BIPUSH, (int)Byte.MAX_VALUE + 1)); } } diff --git a/test/jdk/jdk/classfile/StackTrackerTest.java b/test/jdk/jdk/classfile/StackTrackerTest.java index ba47223107941..b4e82ab0c4b20 100644 --- a/test/jdk/jdk/classfile/StackTrackerTest.java +++ b/test/jdk/jdk/classfile/StackTrackerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,29 +45,29 @@ class StackTrackerTest { void testStackTracker() { ClassFile.of().build(ClassDesc.of("Foo"), clb -> clb.withMethodBody("m", MethodTypeDesc.of(ConstantDescs.CD_Void), 0, cob -> { - var stackTracker = CodeStackTracker.of(DoubleType, FloatType); //initial stack tracker pre-set + var stackTracker = CodeStackTracker.of(DOUBLE, FLOAT); //initial stack tracker pre-set cob.transforming(stackTracker, stcb -> { - assertIterableEquals(stackTracker.stack().get(), List.of(DoubleType, FloatType)); + assertIterableEquals(stackTracker.stack().get(), List.of(DOUBLE, FLOAT)); stcb.aload(0); - assertIterableEquals(stackTracker.stack().get(), List.of(ReferenceType, DoubleType, FloatType)); + assertIterableEquals(stackTracker.stack().get(), List.of(REFERENCE, DOUBLE, FLOAT)); stcb.lconst_0(); - assertIterableEquals(stackTracker.stack().get(), List.of(LongType, ReferenceType, DoubleType, FloatType)); + assertIterableEquals(stackTracker.stack().get(), List.of(LONG, REFERENCE, DOUBLE, FLOAT)); stcb.trying(tryb -> { - assertIterableEquals(stackTracker.stack().get(), List.of(LongType, ReferenceType, DoubleType, FloatType)); + assertIterableEquals(stackTracker.stack().get(), List.of(LONG, REFERENCE, DOUBLE, FLOAT)); tryb.iconst_1(); - assertIterableEquals(stackTracker.stack().get(), List.of(IntType, LongType, ReferenceType, DoubleType, FloatType)); + assertIterableEquals(stackTracker.stack().get(), List.of(INT, LONG, REFERENCE, DOUBLE, FLOAT)); tryb.ifThen(thb -> { - assertIterableEquals(stackTracker.stack().get(), List.of(LongType, ReferenceType, DoubleType, FloatType)); + assertIterableEquals(stackTracker.stack().get(), List.of(LONG, REFERENCE, DOUBLE, FLOAT)); thb.loadConstant(ClassDesc.of("Phee")); - assertIterableEquals(stackTracker.stack().get(), List.of(ReferenceType, LongType, ReferenceType, DoubleType, FloatType)); + assertIterableEquals(stackTracker.stack().get(), List.of(REFERENCE, LONG, REFERENCE, DOUBLE, FLOAT)); thb.athrow(); assertFalse(stackTracker.stack().isPresent()); }); - assertIterableEquals(stackTracker.stack().get(), List.of(LongType, ReferenceType, DoubleType, FloatType)); + assertIterableEquals(stackTracker.stack().get(), List.of(LONG, REFERENCE, DOUBLE, FLOAT)); tryb.return_(); assertFalse(stackTracker.stack().isPresent()); }, catchb -> catchb.catching(ClassDesc.of("Phee"), cb -> { - assertIterableEquals(stackTracker.stack().get(), List.of(ReferenceType)); + assertIterableEquals(stackTracker.stack().get(), List.of(REFERENCE)); cb.athrow(); assertFalse(stackTracker.stack().isPresent()); })); diff --git a/test/jdk/jdk/classfile/TempConstantPoolBuilderTest.java b/test/jdk/jdk/classfile/TempConstantPoolBuilderTest.java index f2debf041e4d1..44a67362cd23b 100644 --- a/test/jdk/jdk/classfile/TempConstantPoolBuilderTest.java +++ b/test/jdk/jdk/classfile/TempConstantPoolBuilderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,8 +38,6 @@ import static java.lang.constant.ConstantDescs.CD_Object; import static java.lang.constant.ConstantDescs.CD_void; import java.lang.constant.MethodTypeDesc; -import static java.lang.classfile.Opcode.INVOKESPECIAL; -import static java.lang.classfile.TypeKind.VoidType; class TempConstantPoolBuilderTest { diff --git a/test/jdk/jdk/classfile/Utf8EntryTest.java b/test/jdk/jdk/classfile/Utf8EntryTest.java index 8281575576112..d18495f917a12 100644 --- a/test/jdk/jdk/classfile/Utf8EntryTest.java +++ b/test/jdk/jdk/classfile/Utf8EntryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,6 @@ import java.util.function.UnaryOperator; import static java.lang.constant.ConstantDescs.CD_void; -import static java.lang.classfile.TypeKind.VoidType; class Utf8EntryTest { diff --git a/test/jdk/jdk/classfile/helpers/ClassRecord.java b/test/jdk/jdk/classfile/helpers/ClassRecord.java index ce22037ccda6b..329e41fa0f484 100644 --- a/test/jdk/jdk/classfile/helpers/ClassRecord.java +++ b/test/jdk/jdk/classfile/helpers/ClassRecord.java @@ -520,7 +520,7 @@ private static List instructions(Supplier - new ConstantPoolEntryRecord.CpClassRecord("[" + cins.typeKind().descriptor()).hashCode() + 1; + new ConstantPoolEntryRecord.CpClassRecord("[" + cins.typeKind().upperBound().descriptorString()).hashCode() + 1; case TypeCheckInstruction cins -> ConstantPoolEntryRecord.ofCPEntry(cins.type()).hashCode(); case ConstantInstruction.LoadConstantInstruction cins -> { diff --git a/test/jdk/jdk/classfile/helpers/InstructionModelToCodeBuilder.java b/test/jdk/jdk/classfile/helpers/InstructionModelToCodeBuilder.java index d7d9e9c267f51..d865ddad5edb2 100644 --- a/test/jdk/jdk/classfile/helpers/InstructionModelToCodeBuilder.java +++ b/test/jdk/jdk/classfile/helpers/InstructionModelToCodeBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -77,7 +77,7 @@ public static void toBuilder(CodeElement model, CodeBuilder cb) { case OperatorInstruction im -> cb.with(OperatorInstruction.of(im.opcode())); case ConstantInstruction im -> - cb.loadConstant(im.opcode(), im.constantValue()); + cb.loadConstant(im.constantValue()); case MonitorInstruction im -> cb.with(MonitorInstruction.of(im.opcode())); case NopInstruction im -> diff --git a/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java b/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java index b769898d785e0..c1d9781b6ce65 100644 --- a/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java +++ b/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java @@ -219,27 +219,27 @@ public void accept(CodeBuilder cob, CodeElement coe) { switch (coe) { case ArrayLoadInstruction i -> { switch (i.typeKind()) { - case ByteType -> cob.baload(); - case ShortType -> cob.saload(); - case IntType -> cob.iaload(); - case FloatType -> cob.faload(); - case LongType -> cob.laload(); - case DoubleType -> cob.daload(); - case ReferenceType -> cob.aaload(); - case CharType -> cob.caload(); + case BYTE -> cob.baload(); + case SHORT -> cob.saload(); + case INT -> cob.iaload(); + case FLOAT -> cob.faload(); + case LONG -> cob.laload(); + case DOUBLE -> cob.daload(); + case REFERENCE -> cob.aaload(); + case CHAR -> cob.caload(); default -> throw new AssertionError("Should not reach here"); } } case ArrayStoreInstruction i -> { switch (i.typeKind()) { - case ByteType -> cob.bastore(); - case ShortType -> cob.sastore(); - case IntType -> cob.iastore(); - case FloatType -> cob.fastore(); - case LongType -> cob.lastore(); - case DoubleType -> cob.dastore(); - case ReferenceType -> cob.aastore(); - case CharType -> cob.castore(); + case BYTE -> cob.bastore(); + case SHORT -> cob.sastore(); + case INT -> cob.iastore(); + case FLOAT -> cob.fastore(); + case LONG -> cob.lastore(); + case DOUBLE -> cob.dastore(); + case REFERENCE -> cob.aastore(); + case CHAR -> cob.castore(); default -> throw new AssertionError("Should not reach here"); } } @@ -304,38 +304,38 @@ else switch (i.constantValue()) { } case ConvertInstruction i -> { switch (i.fromType()) { - case DoubleType -> { + case DOUBLE -> { switch (i.toType()) { - case FloatType -> cob.d2f(); - case IntType -> cob.d2i(); - case LongType -> cob.d2l(); + case FLOAT -> cob.d2f(); + case INT -> cob.d2i(); + case LONG -> cob.d2l(); default -> throw new AssertionError("Should not reach here"); } } - case FloatType -> { + case FLOAT -> { switch (i.toType()) { - case DoubleType -> cob.f2d(); - case IntType -> cob.f2i(); - case LongType -> cob.f2l(); + case DOUBLE -> cob.f2d(); + case INT -> cob.f2i(); + case LONG -> cob.f2l(); default -> throw new AssertionError("Should not reach here"); } } - case IntType -> { + case INT -> { switch (i.toType()) { - case ByteType -> cob.i2b(); - case CharType -> cob.i2c(); - case DoubleType -> cob.i2d(); - case FloatType -> cob.i2f(); - case LongType -> cob.i2l(); - case ShortType -> cob.i2s(); + case BYTE -> cob.i2b(); + case CHAR -> cob.i2c(); + case DOUBLE -> cob.i2d(); + case FLOAT -> cob.i2f(); + case LONG -> cob.i2l(); + case SHORT -> cob.i2s(); default -> throw new AssertionError("Should not reach here"); } } - case LongType -> { + case LONG -> { switch (i.toType()) { - case DoubleType -> cob.l2d(); - case FloatType -> cob.l2f(); - case IntType -> cob.l2i(); + case DOUBLE -> cob.l2d(); + case FLOAT -> cob.l2f(); + case INT -> cob.l2i(); default -> throw new AssertionError("Should not reach here"); } } @@ -410,21 +410,21 @@ else switch (i.constantValue()) { } case LoadInstruction i -> { switch (i.typeKind()) { - case IntType -> cob.iload(i.slot()); - case FloatType -> cob.fload(i.slot()); - case LongType -> cob.lload(i.slot()); - case DoubleType -> cob.dload(i.slot()); - case ReferenceType -> cob.aload(i.slot()); + case INT -> cob.iload(i.slot()); + case FLOAT -> cob.fload(i.slot()); + case LONG -> cob.lload(i.slot()); + case DOUBLE -> cob.dload(i.slot()); + case REFERENCE -> cob.aload(i.slot()); default -> throw new AssertionError("Should not reach here"); } } case StoreInstruction i -> { switch (i.typeKind()) { - case IntType -> cob.istore(i.slot()); - case FloatType -> cob.fstore(i.slot()); - case LongType -> cob.lstore(i.slot()); - case DoubleType -> cob.dstore(i.slot()); - case ReferenceType -> cob.astore(i.slot()); + case INT -> cob.istore(i.slot()); + case FLOAT -> cob.fstore(i.slot()); + case LONG -> cob.lstore(i.slot()); + case DOUBLE -> cob.dstore(i.slot()); + case REFERENCE -> cob.astore(i.slot()); default -> throw new AssertionError("Should not reach here"); } } @@ -515,12 +515,12 @@ else switch (i.constantValue()) { } case ReturnInstruction i -> { switch (i.typeKind()) { - case IntType -> cob.ireturn(); - case FloatType -> cob.freturn(); - case LongType -> cob.lreturn(); - case DoubleType -> cob.dreturn(); - case ReferenceType -> cob.areturn(); - case VoidType -> cob.return_(); + case INT -> cob.ireturn(); + case FLOAT -> cob.freturn(); + case LONG -> cob.lreturn(); + case DOUBLE -> cob.dreturn(); + case REFERENCE -> cob.areturn(); + case VOID -> cob.return_(); default -> throw new AssertionError("Should not reach here"); } } diff --git a/test/jdk/jdk/jfr/api/consumer/TestChunkInputStreamBulkRead.java b/test/jdk/jdk/jfr/api/consumer/TestChunkInputStreamBulkRead.java new file mode 100644 index 0000000000000..15bf1b7707c6d --- /dev/null +++ b/test/jdk/jdk/jfr/api/consumer/TestChunkInputStreamBulkRead.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024, Palantir Technologies, Inc. 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 TestChunkInputStreamBulkRead + * @key jfr + * @requires vm.hasJFR + * @library /test/lib + * @run main/othervm jdk.jfr.api.consumer.TestChunkInputStreamBulkRead + */ +package jdk.jfr.api.consumer; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import jdk.jfr.Recording; +import jdk.test.lib.Asserts; + +public class TestChunkInputStreamBulkRead { + + public static void main(String[] args) throws Exception { + try (Recording r = new Recording()) { + r.start(); + try (Recording s = new Recording()) { + s.start(); + s.stop(); + } + r.stop(); + try (InputStream stream = r.getStream(null, null); + ByteArrayOutputStream output = new ByteArrayOutputStream()) { + long read = stream.transferTo(output); + System.out.printf("Read %d bytes from JFR stream%n", read); + Asserts.assertEquals(r.getSize(), read); + + byte[] actual = output.toByteArray(); + Asserts.assertEqualsByteArray(r.getStream(null, null).readAllBytes(), actual); + + Path dumpFile = Paths.get("recording.jfr").toAbsolutePath().normalize(); + r.dump(dumpFile); + System.out.printf("Dumped recording to %s (%d bytes)%n", dumpFile, Files.size(dumpFile)); + Asserts.assertEqualsByteArray(Files.readAllBytes(dumpFile), actual); + } + } + } +} diff --git a/test/jdk/sun/java2d/Disposer/TestDisposerRace.java b/test/jdk/sun/java2d/Disposer/TestDisposerRace.java index e22e59799515c..b78966f1200b2 100644 --- a/test/jdk/sun/java2d/Disposer/TestDisposerRace.java +++ b/test/jdk/sun/java2d/Disposer/TestDisposerRace.java @@ -23,6 +23,7 @@ import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; import javax.swing.SwingUtilities; import sun.java2d.Disposer; @@ -39,16 +40,23 @@ public final class TestDisposerRace { private static final AtomicInteger recordsCount = new AtomicInteger(); private static volatile boolean disposerDone = false; + private static final String KO_OVERFLOW = "Some records have not been disposed!"; + private static final String KO_UNDERFLOW = "Disposed more records than were added!"; + public static void main(String[] args) throws Exception { - TestDisposerRace test = new TestDisposerRace(); - test.run(); + new TestDisposerRace().run(); checkRecordsCountIsSane(); if (recordsCount.get() > 0) { + System.err.println(KO_OVERFLOW); // In case the next line fails to allocate due to OOME throw new RuntimeException("Some records (" + recordsCount + ") have not been disposed"); } } + interface ThrowingRunnable { + void run() throws E; + } + TestDisposerRace() { addRecordsToDisposer(30_000); } @@ -56,14 +64,14 @@ public static void main(String[] args) throws Exception { void run() throws Exception { generateOOME(); for (int i = 0; i < 1000; ++i) { - SwingUtilities.invokeAndWait(Disposer::pollRemove); - if (i % 10 == 0) { - // Adding records will race with the diposer trying to remove them + retryOnOOME(() -> SwingUtilities.invokeAndWait(Disposer::pollRemove)); + + // Adding records will race with the diposer trying to remove them + if (i % 10 == 0) addRecordsToDisposer(1000); - } } - Disposer.addObjectRecord(new Object(), new FinalDisposerRecord()); + retryOnOOME(() -> Disposer.addObjectRecord(new Object(), new FinalDisposerRecord())); while (!disposerDone) { generateOOME(); @@ -72,18 +80,45 @@ void run() throws Exception { private static void checkRecordsCountIsSane() { if (recordsCount.get() < 0) { - throw new RuntimeException("Disposed more records than were added"); + throw new RuntimeException(KO_UNDERFLOW); + } + } + + private static T retryOnOOME(Supplier allocator) { + for(;;) { + try { + return allocator.get(); + } catch (OutOfMemoryError ignored1) { + try { + Thread.sleep(1); // Give GC a little chance to run + } catch (InterruptedException ignored2) {} + } + } + } + + private static void retryOnOOME(ThrowingRunnable tr) throws E { + for(;;) { + try { + tr.run(); + break; + } catch (OutOfMemoryError ignored1) { + try { + Thread.sleep(1); // Give GC a little chance to run + } catch (InterruptedException ignored2) {} + } } } private void addRecordsToDisposer(int count) { checkRecordsCountIsSane(); - recordsCount.addAndGet(count); + MyDisposerRecord disposerRecord = retryOnOOME(MyDisposerRecord::new); - MyDisposerRecord disposerRecord = new MyDisposerRecord(); - for (int i = 0; i < count; i++) { - Disposer.addObjectRecord(new Object(), disposerRecord); + while(count > 0) { + recordsCount.incrementAndGet(); // pre-add to make sure it doesn't go negative + var o = retryOnOOME(Object::new); + retryOnOOME(() -> Disposer.addObjectRecord(o, disposerRecord)); + --count; } } @@ -106,8 +141,8 @@ private static void giveGCAChance() { } private static void generateOOME() throws Exception { - final List leak = new LinkedList<>(); try { + final List leak = new LinkedList<>(); while (true) { leak.add(new byte[1024 * 1024]); } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/TestFill.java b/test/micro/org/openjdk/bench/java/lang/foreign/TestFill.java new file mode 100644 index 0000000000000..78719f03bc377 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/TestFill.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package org.openjdk.bench.java.lang.foreign; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(Scope.Thread) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(value = 3) +public class TestFill { + + @Param({"0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", "10", "11", "12", "13", "14", "15", + "16", "17", "18", "19", "20", "21", "22", "23", + "24", "25", "26", "27", "28", "29", "30", "31", + "32", "128", "256", "384", "511", "512"}) + public int ELEM_SIZE; + + byte[] array; + MemorySegment heapSegment; + MemorySegment nativeSegment; + MemorySegment unalignedSegment; + ByteBuffer buffer; + + @Setup + public void setup() { + array = new byte[ELEM_SIZE]; + heapSegment = MemorySegment.ofArray(array); + nativeSegment = Arena.ofAuto().allocate(ELEM_SIZE, 8); + unalignedSegment = Arena.ofAuto().allocate(ELEM_SIZE + 1, 8).asSlice(1); + buffer = ByteBuffer.wrap(array); + } + + @Benchmark + public void arrays_fill() { + Arrays.fill(array, (byte) 0); + } + + @Benchmark + public void heap_segment_fill() { + heapSegment.fill((byte) 0); + } + + @Benchmark + public void native_segment_fill() { + nativeSegment.fill((byte) 0); + } + + @Benchmark + public void unaligned_segment_fill() { + unalignedSegment.fill((byte) 0); + } + +} diff --git a/test/micro/org/openjdk/bench/jdk/classfile/Write.java b/test/micro/org/openjdk/bench/jdk/classfile/Write.java index e5304f0e51c77..b8bc9605559d9 100644 --- a/test/micro/org/openjdk/bench/jdk/classfile/Write.java +++ b/test/micro/org/openjdk/bench/jdk/classfile/Write.java @@ -24,7 +24,6 @@ import java.lang.reflect.AccessFlag; import java.lang.classfile.ClassFile; -import java.lang.classfile.TypeKind; import java.lang.classfile.attribute.SourceFileAttribute; import jdk.internal.org.objectweb.asm.*; import org.openjdk.jmh.annotations.*; @@ -142,9 +141,9 @@ public byte[] jdkTree() { cb.withVersion(52, 0); cb.with(SourceFileAttribute.of(cb.constantPool().utf8Entry(("MyClass.java")))) .withMethod(INIT_NAME, MTD_void, 0, mb -> mb - .withCode(codeb -> codeb.loadLocal(TypeKind.ReferenceType, 0) + .withCode(codeb -> codeb.loadLocal(REFERENCE, 0) .invoke(INVOKESPECIAL, CD_Object, INIT_NAME, MTD_void, false) - .return_(VoidType) + .return_(VOID) ) ); for (int xi = 0; xi < 40; ++xi) { @@ -190,7 +189,7 @@ public byte[] jdkTreePrimitive() { cb.withVersion(52, 0); cb.with(SourceFileAttribute.of(cb.constantPool().utf8Entry(("MyClass.java")))) .withMethod(INIT_NAME, MTD_void, 0, - mb -> mb.withCode(codeb -> codeb.loadLocal(ReferenceType, 0) + mb -> mb.withCode(codeb -> codeb.loadLocal(REFERENCE, 0) .invokespecial(CD_Object, INIT_NAME, MTD_void, false) .return_() )