diff --git a/.gitignore b/.gitignore index b57addfccc9..2d82e0d943c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ NashornProfile.txt /.cache /.gdbinit /.lldbinit +**/core.[0-9]* diff --git a/make/RunTests.gmk b/make/RunTests.gmk index 616341a8901..44d387080df 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -530,21 +530,34 @@ define SetupRunGtestTestBody $$(call LogWarn, Test report is stored in $$(strip \ $$(subst $$(TOPDIR)/, , $$($1_TEST_RESULTS_DIR)))) $$(if $$(wildcard $$($1_RESULT_FILE)), \ - $$(eval $1_TOTAL := $$(shell $$(AWK) '/==========.* tests? from .* \ - test (cases?|suites?) ran/ { print $$$$2 }' $$($1_RESULT_FILE))) \ - $$(if $$($1_TOTAL), , $$(eval $1_TOTAL := 0)) \ + $$(eval $1_RUN := $$(shell $$(AWK) \ + '/==========.* tests? from .* test (cases?|suites?) ran/ { print $$$$2 }' \ + $$($1_RESULT_FILE))) \ + $$(if $$($1_RUN), , $$(eval $1_RUN := 0)) \ $$(eval $1_PASSED := $$(shell $$(AWK) '/\[ PASSED \] .* tests?./ \ { print $$$$4 }' $$($1_RESULT_FILE))) \ $$(if $$($1_PASSED), , $$(eval $1_PASSED := 0)) \ + $$(eval $1_SKIPPED := $$(shell $$(AWK) \ + '/YOU HAVE [0-9]+ DISABLED TEST/ { \ + if (match($$$$0, /[0-9]+/, arr)) { \ + print arr[0]; \ + found=1; \ + } \ + if (!found) { print 0; } \ + }' \ + $$($1_RESULT_FILE))) \ $$(eval $1_FAILED := $$(shell $$(AWK) '/\[ FAILED \] .* tests?, \ listed below/ { print $$$$4 }' $$($1_RESULT_FILE))) \ $$(if $$($1_FAILED), , $$(eval $1_FAILED := 0)) \ $$(eval $1_ERROR := $$(shell \ - $$(EXPR) $$($1_TOTAL) - $$($1_PASSED) - $$($1_FAILED))) \ + $$(EXPR) $$($1_RUN) - $$($1_PASSED) - $$($1_FAILED))) \ + $$(eval $1_TOTAL := $$(shell \ + $$(EXPR) $$($1_RUN) + $$($1_SKIPPED))) \ , \ $$(eval $1_PASSED := 0) \ $$(eval $1_FAILED := 0) \ $$(eval $1_ERROR := 1) \ + $$(eval $1_SKIPPED := 0) \ $$(eval $1_TOTAL := 1) \ ) @@ -668,6 +681,7 @@ define SetupRunMicroTestBody $$(eval $1_ERROR := 1) \ $$(eval $1_TOTAL := 1) \ ) + $$(eval $1_SKIPPED := 0) $1: run-test-$1 parse-test-$1 @@ -1036,23 +1050,64 @@ define SetupRunJtregTestBody $$(call LogWarn, Finished running test '$$($1_TEST)') $$(call LogWarn, Test report is stored in $$(strip \ $$(subst $$(TOPDIR)/, , $$($1_TEST_RESULTS_DIR)))) + + # Read jtreg documentation to learn on the test stats categories: + # https://github.com/openjdk/jtreg/blob/master/src/share/doc/javatest/regtest/faq.md#what-do-all-those-numbers-in-the-test-results-line-mean + # In jtreg, "skipped:" category accounts for tests that threw jtreg.SkippedException at runtime. + # At the same time these tests contribute to "passed:" tests. + # In here we don't want that and so we substract number of "skipped:" from "passed:". + $$(if $$(wildcard $$($1_RESULT_FILE)), \ - $$(eval $1_PASSED := $$(shell $$(AWK) '{ gsub(/[,;]/, ""); \ + $$(eval $1_PASSED_AND_RUNTIME_SKIPPED := $$(shell $$(AWK) '{ gsub(/[,;]/, ""); \ for (i=1; i<=NF; i++) { if ($$$$i == "passed:") \ print $$$$(i+1) } }' $$($1_RESULT_FILE))) \ - $$(if $$($1_PASSED), , $$(eval $1_PASSED := 0)) \ + $$(if $$($1_PASSED_AND_RUNTIME_SKIPPED), , $$(eval $1_PASSED_AND_RUNTIME_SKIPPED := 0)) \ $$(eval $1_FAILED := $$(shell $$(AWK) '{gsub(/[,;]/, ""); \ for (i=1; i<=NF; i++) { if ($$$$i == "failed:") \ print $$$$(i+1) } }' $$($1_RESULT_FILE))) \ $$(if $$($1_FAILED), , $$(eval $1_FAILED := 0)) \ + $$(eval $1_RUNTIME_SKIPPED := $$(shell $$(AWK) '{gsub(/[,;]/, ""); \ + for (i=1; i<=NF; i++) { if ($$$$i == "skipped:") \ + print $$$$(i+1) } }' $$($1_RESULT_FILE))) \ + $$(if $$($1_RUNTIME_SKIPPED), , $$(eval $1_RUNTIME_SKIPPED := 0)) \ + $$(eval $1_SKIPPED := $$(shell \ + $$(AWK) \ + 'BEGIN { \ + overall_skipped = 0; \ + patterns[1] = "skipped"; \ + patterns[2] = "excluded"; \ + patterns[3] = "not in match-list"; \ + patterns[4] = "did not match keywords"; \ + patterns[5] = "did not meet module requirements"; \ + patterns[6] = "did not meet platform requirements"; \ + patterns[7] = "did not match prior status"; \ + patterns[8] = "did not meet time-limit requirements"; \ + } { \ + split($$$$0, arr, ";"); \ + for (item in arr) { \ + for (p in patterns) { \ + if (match(arr[item], patterns[p] ": [0-9]+")) { \ + overall_skipped += substr(arr[item], RSTART + length(patterns[p]) + 2, RLENGTH); \ + } \ + } \ + } \ + print overall_skipped; \ + }' \ + $$($1_RESULT_FILE) \ + )) \ $$(eval $1_ERROR := $$(shell $$(AWK) '{gsub(/[,;]/, ""); \ for (i=1; i<=NF; i++) { if ($$$$i == "error:") \ print $$$$(i+1) } }' $$($1_RESULT_FILE))) \ $$(if $$($1_ERROR), , $$(eval $1_ERROR := 0)) \ + \ + $$(eval $1_PASSED := $$(shell \ + $$(EXPR) $$($1_PASSED_AND_RUNTIME_SKIPPED) - $$($1_RUNTIME_SKIPPED))) \ $$(eval $1_TOTAL := $$(shell \ - $$(EXPR) $$($1_PASSED) + $$($1_FAILED) + $$($1_ERROR))) \ + $$(EXPR) $$($1_PASSED) + $$($1_FAILED) + $$($1_ERROR) + $$($1_SKIPPED))) \ , \ - $$(eval $1_PASSED := 0) \ + $$(eval $1_PASSED_AND_RUNTIME_SKIPPED := 0) \ + $$(eval $1_RUNTIME_SKIPPED := 0) \ + $$(eval $1_SKIPPED := 0) \ $$(eval $1_FAILED := 0) \ $$(eval $1_ERROR := 1) \ $$(eval $1_TOTAL := 1) \ @@ -1111,8 +1166,6 @@ define SetupRunSpecialTestBody || $$(ECHO) $$$$? > $$($1_EXITCODE) \ )) - $1_RESULT_FILE := $$($1_TEST_RESULTS_DIR)/gtest.txt - # We can not parse the various "special" tests. parse-test-$1: run-test-$1 $$(call LogWarn, Finished running test '$$($1_TEST)') @@ -1122,6 +1175,7 @@ define SetupRunSpecialTestBody $$(eval $1_PASSED := $$(shell \ if [ `$(CAT) $$($1_EXITCODE)` = "0" ]; then $(ECHO) 1; else $(ECHO) 0; fi \ )) + $$(eval $1_SKIPPED := 0) $$(eval $1_FAILED := $$(shell \ if [ `$(CAT) $$($1_EXITCODE)` = "0" ]; then $(ECHO) 0; else $(ECHO) 1; fi \ )) @@ -1231,8 +1285,8 @@ run-test-report: post-run-test $(ECHO) >> $(TEST_SUMMARY) ============================== $(ECHO) >> $(TEST_SUMMARY) Test summary $(ECHO) >> $(TEST_SUMMARY) ============================== - $(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s %5s %5s %5s %5s %2s\n" " " \ - TEST TOTAL PASS FAIL ERROR " " + $(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s %5s %5s %5s %5s %5s %2s\n" " " \ + TEST TOTAL PASS FAIL ERROR SKIP " " $(foreach test, $(TESTS_TO_RUN), \ $(eval TEST_ID := $(shell $(ECHO) $(strip $(test)) | \ $(TR) -cs '[a-z][A-Z][0-9]\n' '[_*1000]')) \ @@ -1244,15 +1298,15 @@ run-test-report: post-run-test , \ $(eval TEST_NAME := $(test)) \ ) \ - $(if $(filter $($(TEST_ID)_PASSED), $($(TEST_ID)_TOTAL)), \ - $(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s %5d %5d %5d %5d %2s\n" \ - " " "$(TEST_NAME)" $($(TEST_ID)_TOTAL) $($(TEST_ID)_PASSED) \ - $($(TEST_ID)_FAILED) $($(TEST_ID)_ERROR) " " $(NEWLINE) \ - , \ - $(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s %5d %5d %5d %5d %2s\n" \ + $(if $(filter-out 0, $($(TEST_ID)_FAILED) $($(TEST_ID)_ERROR)), \ + $(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s %5d %5d %5d %5d %5d %2s\n" \ ">>" "$(TEST_NAME)" $($(TEST_ID)_TOTAL) $($(TEST_ID)_PASSED) \ - $($(TEST_ID)_FAILED) $($(TEST_ID)_ERROR) "<<" $(NEWLINE) \ + $($(TEST_ID)_FAILED) $($(TEST_ID)_ERROR) $($(TEST_ID)_SKIPPED) "<<" $(NEWLINE) \ $(eval TEST_FAILURE := true) \ + , \ + $(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s %5d %5d %5d %5d %5d %2s\n" \ + " " "$(TEST_NAME)" $($(TEST_ID)_TOTAL) $($(TEST_ID)_PASSED) \ + $($(TEST_ID)_FAILED) $($(TEST_ID)_ERROR) $($(TEST_ID)_SKIPPED) " " $(NEWLINE) \ ) \ ) $(ECHO) >> $(TEST_SUMMARY) ============================== diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index 857e2b65e57..73786587735 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -482,6 +482,16 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER], else DEBUG_CFLAGS_JDK="-DDEBUG" + if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang ; then + INIT_PATTERN_FLAG="-ftrivial-auto-var-init=pattern" + FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [$INIT_PATTERN_FLAG], + IF_TRUE: [ + DEBUG_CFLAGS_JDK="$DEBUG_CFLAGS_JDK $INIT_PATTERN_FLAG" + DEBUG_CFLAGS_JVM="$INIT_PATTERN_FLAG" + ] + ) + fi + if test "x$TOOLCHAIN_TYPE" = xclang && test "x$OPENJDK_TARGET_OS" = xaix; then DEBUG_CFLAGS_JVM="-fpic -mcmodel=large" fi diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 58997d6a438..c934739a5ad 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -207,7 +207,8 @@ var getJibProfiles = function (input) { // Exclude list to use when Jib creates a source bundle data.src_bundle_excludes = [ "build", "{,**/}webrev*", "{,**/}.hg", "{,**/}JTwork*", "{,**/}JTreport*", - "{,**/}.git" + "{,**/}.git", + "{,**/}core.[0-9]*" ]; // Include list to use when creating a minimal jib source bundle which // contains just the jib configuration files. diff --git a/make/hotspot/lib/CompileGtest.gmk b/make/hotspot/lib/CompileGtest.gmk index 5c576cbbf0d..d2cdc7685c9 100644 --- a/make/hotspot/lib/CompileGtest.gmk +++ b/make/hotspot/lib/CompileGtest.gmk @@ -104,6 +104,7 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBJVM, \ undef stringop-overflow, \ DISABLED_WARNINGS_gcc_test_metaspace_misc.cpp := unused-const-variable, \ DISABLED_WARNINGS_gcc_test_threadCpuLoad.cpp := address, \ + DISABLED_WARNINGS_gcc_test_tribool.cpp := uninitialized, \ DISABLED_WARNINGS_clang := $(DISABLED_WARNINGS_clang) \ undef switch format-nonliteral tautological-undefined-compare \ self-assign-overloaded, \ diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk index b2c59505f9a..6b5edc85b23 100644 --- a/make/hotspot/lib/CompileJvm.gmk +++ b/make/hotspot/lib/CompileJvm.gmk @@ -89,6 +89,7 @@ CFLAGS_VM_VERSION := \ -DHOTSPOT_VM_DISTRO='"$(HOTSPOT_VM_DISTRO)"' \ -DCPU='"$(OPENJDK_TARGET_CPU_VM_VERSION)"' \ -DHOTSPOT_BUILD_TIME='"$(HOTSPOT_BUILD_TIME)"' \ + -DJVM_VARIANT='"$(JVM_VARIANT)"' \ # ################################################################################ diff --git a/make/hotspot/lib/JvmFeatures.gmk b/make/hotspot/lib/JvmFeatures.gmk index c2aea13a30e..ea951313272 100644 --- a/make/hotspot/lib/JvmFeatures.gmk +++ b/make/hotspot/lib/JvmFeatures.gmk @@ -223,11 +223,9 @@ ifeq ($(call check-jvm-feature, opt-size), true) frame_ppc.cpp \ frame_s390.cpp \ frame_x86.cpp \ - genCollectedHeap.cpp \ generation.cpp \ growableArray.cpp \ handles.cpp \ - hashtable.cpp \ heap.cpp \ icache.cpp \ icache_arm.cpp \ @@ -245,7 +243,6 @@ ifeq ($(call check-jvm-feature, opt-size), true) linkResolver.cpp \ klass.cpp \ klassVtable.cpp \ - markSweep.cpp \ memRegion.cpp \ memoryPool.cpp \ method.cpp \ diff --git a/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java b/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java index 61395f982b2..d8752bca142 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -198,7 +198,6 @@ Map<String, Object> getTargetMap() throws Exception { String[] cldrBundles = getCLDRPath().split(","); // myMap contains resources for id. - @SuppressWarnings("unchecked") Map<String, Object> myMap = new HashMap<>(); int index; for (index = 0; index < cldrBundles.length; index++) { diff --git a/make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java b/make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java index d2d7e94fc98..6d5dde0d181 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -1079,7 +1079,6 @@ private String getTarget(String path, String calType, String context, String wid } @Override - @SuppressWarnings("fallthrough") public void endElement(String uri, String localName, String qName) throws SAXException { assert qName.equals(currentContainer.getqName()) : "current=" + currentContainer.getqName() + ", param=" + qName; switch (qName) { diff --git a/make/modules/java.base/gensrc/GensrcScopedMemoryAccess.gmk b/make/modules/java.base/gensrc/GensrcScopedMemoryAccess.gmk index 1ed3fb3db79..00fba64394b 100644 --- a/make/modules/java.base/gensrc/GensrcScopedMemoryAccess.gmk +++ b/make/modules/java.base/gensrc/GensrcScopedMemoryAccess.gmk @@ -42,6 +42,17 @@ define GenerateScopedOp $1_Type := $2 + ifeq ($$($1_Type), Boolean) + $1_type := boolean + $1_BoxType := $$($1_Type) + + $1_rawType := $$($1_type) + $1_RawType := $$($1_Type) + $1_RawBoxType := $$($1_BoxType) + + $1_ARGS += -KCAS + endif + ifeq ($$($1_Type), Byte) $1_type := byte $1_BoxType := $$($1_Type) @@ -50,6 +61,7 @@ define GenerateScopedOp $1_RawType := $$($1_Type) $1_RawBoxType := $$($1_BoxType) + $1_ARGS += -KCAS $1_ARGS += -Kbyte endif @@ -60,6 +72,8 @@ define GenerateScopedOp $1_rawType := $$($1_type) $1_RawType := $$($1_Type) $1_RawBoxType := $$($1_BoxType) + + $1_ARGS += -KCAS $1_ARGS += -KUnaligned endif @@ -70,6 +84,8 @@ define GenerateScopedOp $1_rawType := $$($1_type) $1_RawType := $$($1_Type) $1_RawBoxType := $$($1_BoxType) + + $1_ARGS += -KCAS $1_ARGS += -KUnaligned endif @@ -82,8 +98,6 @@ define GenerateScopedOp $1_RawBoxType := $$($1_BoxType) $1_ARGS += -KCAS - $1_ARGS += -KAtomicAdd - $1_ARGS += -KBitwise $1_ARGS += -KUnaligned endif @@ -96,8 +110,6 @@ define GenerateScopedOp $1_RawBoxType := $$($1_BoxType) $1_ARGS += -KCAS - $1_ARGS += -KAtomicAdd - $1_ARGS += -KBitwise $1_ARGS += -KUnaligned endif @@ -133,7 +145,7 @@ define GenerateScopedOp $1_ARGS += -KBitwise endif - ifneq ($$(findstring $$($1_Type), Byte Short Char), ) + ifneq ($$(findstring $$($1_Type), Boolean Byte Short Char), ) $1_ARGS += -KShorterThanInt endif endef @@ -141,7 +153,7 @@ endef ################################################################################ # Setup a rule for generating the ScopedMemoryAccess java class -SCOPE_MEMORY_ACCESS_TYPES := Byte Short Char Int Long Float Double +SCOPE_MEMORY_ACCESS_TYPES := Boolean Byte Short Char Int Long Float Double $(foreach t, $(SCOPE_MEMORY_ACCESS_TYPES), \ $(eval $(call GenerateScopedOp,BIN_$t,$t))) diff --git a/make/modules/java.base/gensrc/GensrcVarHandles.gmk b/make/modules/java.base/gensrc/GensrcVarHandles.gmk index 42ba318e626..9b3b8a3f8d5 100644 --- a/make/modules/java.base/gensrc/GensrcVarHandles.gmk +++ b/make/modules/java.base/gensrc/GensrcVarHandles.gmk @@ -184,6 +184,18 @@ define GenerateVarHandleMemorySegment $1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandleSegmentAs$$($1_Type)s.java + ifeq ($$($1_Type), Boolean) + $1_type := boolean + $1_BoxType := $$($1_Type) + + $1_rawType := $$($1_type) + $1_RawType := $$($1_Type) + $1_RawBoxType := $$($1_BoxType) + + $1_ARGS += -Kbyte + $1_ARGS += -KShorterThanInt + endif + ifeq ($$($1_Type), Byte) $1_type := byte $1_BoxType := $$($1_Type) @@ -193,6 +205,7 @@ define GenerateVarHandleMemorySegment $1_RawBoxType := $$($1_BoxType) $1_ARGS += -Kbyte + $1_ARGS += -KShorterThanInt endif ifeq ($$($1_Type), Short) @@ -202,6 +215,8 @@ define GenerateVarHandleMemorySegment $1_rawType := $$($1_type) $1_RawType := $$($1_Type) $1_RawBoxType := $$($1_BoxType) + + $1_ARGS += -KShorterThanInt endif ifeq ($$($1_Type), Char) @@ -211,6 +226,8 @@ define GenerateVarHandleMemorySegment $1_rawType := $$($1_type) $1_RawType := $$($1_Type) $1_RawBoxType := $$($1_BoxType) + + $1_ARGS += -KShorterThanInt endif ifeq ($$($1_Type), Int) @@ -287,7 +304,7 @@ $(foreach t, $(VARHANDLES_BYTE_ARRAY_TYPES), \ $(eval $(call GenerateVarHandleByteArray,VAR_HANDLE_BYTE_ARRAY_$t,$t))) # List the types to generate source for, with capitalized first letter -VARHANDLES_MEMORY_SEGMENT_TYPES := Byte Short Char Int Long Float Double +VARHANDLES_MEMORY_SEGMENT_TYPES := Boolean Byte Short Char Int Long Float Double $(foreach t, $(VARHANDLES_MEMORY_SEGMENT_TYPES), \ $(eval $(call GenerateVarHandleMemorySegment,VAR_HANDLE_MEMORY_SEGMENT_$t,$t))) diff --git a/make/modules/jdk.incubator.vector/Lib.gmk b/make/modules/jdk.incubator.vector/Lib.gmk index 6d1259cfe60..5c979ae8191 100644 --- a/make/modules/jdk.incubator.vector/Lib.gmk +++ b/make/modules/jdk.incubator.vector/Lib.gmk @@ -53,6 +53,7 @@ ifeq ($(call isTargetOs, linux)+$(call isTargetCpu, riscv64)+$(INCLUDE_COMPILER2 DISABLED_WARNINGS_gcc := unused-function sign-compare tautological-compare ignored-qualifiers, \ DISABLED_WARNINGS_clang := unused-function sign-compare tautological-compare ignored-qualifiers, \ CFLAGS := -march=rv64gcv, \ + CFLAGS_FILTER_OUT := -ftrivial-auto-var-init=pattern, \ )) TARGETS += $(BUILD_LIBSLEEF) @@ -67,6 +68,7 @@ ifeq ($(call isTargetOs, linux)+$(call isTargetCpu, aarch64)+$(INCLUDE_COMPILER2 DISABLED_WARNINGS_gcc := unused-function sign-compare tautological-compare ignored-qualifiers, \ DISABLED_WARNINGS_clang := unused-function sign-compare tautological-compare ignored-qualifiers, \ vector_math_sve.c_CFLAGS := $(SVE_CFLAGS), \ + CFLAGS_FILTER_OUT := -ftrivial-auto-var-init=pattern, \ )) TARGETS += $(BUILD_LIBSLEEF) diff --git a/make/test/JtregNativeHotspot.gmk b/make/test/JtregNativeHotspot.gmk index a11e358fa96..e8ef302f24f 100644 --- a/make/test/JtregNativeHotspot.gmk +++ b/make/test/JtregNativeHotspot.gmk @@ -883,7 +883,6 @@ ifeq ($(call isTargetOs, windows), true) BUILD_HOTSPOT_JTREG_EXECUTABLES_CFLAGS_exeFPRegs := -MT BUILD_HOTSPOT_JTREG_EXCLUDE += exesigtest.c libterminatedThread.c libTestJNI.c libCompleteExit.c libMonitorWithDeadObjectTest.c libTestPsig.c exeGetCreatedJavaVMs.c libTestUnloadedClass.cpp BUILD_HOTSPOT_JTREG_LIBRARIES_JDK_LIBS_libnativeStack := java.base:libjvm - BUILD_HOTSPOT_JTREG_LIBRARIES_JDK_LIBS_libVThreadEventTest := java.base:libjvm else BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbootclssearch_agent += -lpthread BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsystemclssearch_agent += -lpthread @@ -1524,7 +1523,6 @@ else BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMonitorWithDeadObjectTest += -lpthread BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libnativeStack += -lpthread BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libTestUnloadedClass += -lpthread - BUILD_HOTSPOT_JTREG_LIBRARIES_JDK_LIBS_libVThreadEventTest := java.base:libjvm BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exeGetCreatedJavaVMs := -lpthread BUILD_HOTSPOT_JTREG_EXECUTABLES_JDK_LIBS_exeGetCreatedJavaVMs := java.base:libjvm diff --git a/src/hotspot/cpu/aarch64/abstractInterpreter_aarch64.cpp b/src/hotspot/cpu/aarch64/abstractInterpreter_aarch64.cpp index a3c729fdd56..b543c96f3b8 100644 --- a/src/hotspot/cpu/aarch64/abstractInterpreter_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/abstractInterpreter_aarch64.cpp @@ -149,7 +149,8 @@ void AbstractInterpreter::layout_activation(Method* method, #ifdef ASSERT if (caller->is_interpreted_frame()) { - assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement"); + assert(locals <= caller->interpreter_frame_expression_stack(), "bad placement"); + assert(locals >= interpreter_frame->sender_sp() + max_locals - 1, "bad placement"); } #endif diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index a5e0e2665af..c91a136e7d5 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2024, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -2552,6 +2552,11 @@ template<typename R, typename... Rx> ldst_sstr(T, index, a, op1, op2, Vt, Vt2, Vt3, Vt4); \ } + INSN1(ld1, 0b001101010, 0b0000); + INSN2(ld2, 0b001101011, 0b0000); + INSN3(ld3, 0b001101010, 0b0010); + INSN4(ld4, 0b001101011, 0b0010); + INSN1(st1, 0b001101000, 0b0000); INSN2(st2, 0b001101001, 0b0000); INSN3(st3, 0b001101000, 0b0010); @@ -2586,6 +2591,7 @@ template<typename R, typename... Rx> void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \ guarantee(T != T1Q && T != T1D, "incorrect arrangement"); \ if (!acceptT2D) guarantee(T != T2D, "incorrect arrangement"); \ + if (opc2 == 0b101101) guarantee(T != T8B && T != T16B, "incorrect arrangement"); \ starti; \ f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24); \ f((int)T >> 1, 23, 22), f(1, 21), rf(Vm, 16), f(opc2, 15, 10); \ @@ -2609,6 +2615,8 @@ template<typename R, typename... Rx> INSN(minv, 0, 0b011011, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(smaxp, 0, 0b101001, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(sminp, 0, 0b101011, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S + INSN(sqdmulh,0, 0b101101, false); // accepted arrangements: T4H, T8H, T2S, T4S + INSN(shsubv, 0, 0b001001, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S #undef INSN diff --git a/src/hotspot/cpu/aarch64/runtime_aarch64.cpp b/src/hotspot/cpu/aarch64/runtime_aarch64.cpp index 635c074eadc..ba676573f39 100644 --- a/src/hotspot/cpu/aarch64/runtime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/runtime_aarch64.cpp @@ -63,7 +63,8 @@ void OptoRuntime::generate_uncommon_trap_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools - CodeBuffer buffer("uncommon_trap_blob", 2048, 1024); + const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id); + CodeBuffer buffer(name, 2048, 1024); MacroAssembler* masm = new MacroAssembler(&buffer); assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); @@ -282,7 +283,8 @@ void OptoRuntime::generate_exception_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools - CodeBuffer buffer("exception_blob", 2048, 1024); + const char* name = OptoRuntime::stub_name(OptoStubId::exception_id); + CodeBuffer buffer(name, 2048, 1024); MacroAssembler* masm = new MacroAssembler(&buffer); // TODO check various assumptions made here diff --git a/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp b/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp index 1830bdf4a88..a893aacaaf2 100644 --- a/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp @@ -44,7 +44,7 @@ do_arch_blob, \ do_arch_entry, \ do_arch_entry_init) \ - do_arch_blob(compiler, 30000 ZGC_ONLY(+10000)) \ + do_arch_blob(compiler, 55000 ZGC_ONLY(+5000)) \ do_stub(compiler, vector_iota_indices) \ do_arch_entry(aarch64, compiler, vector_iota_indices, \ vector_iota_indices, vector_iota_indices) \ @@ -109,7 +109,7 @@ do_arch_blob, \ do_arch_entry, \ do_arch_entry_init) \ - do_arch_blob(final, 20000 ZGC_ONLY(+100000)) \ + do_arch_blob(final, 20000 ZGC_ONLY(+60000)) \ do_stub(final, copy_byte_f) \ do_arch_entry(aarch64, final, copy_byte_f, copy_byte_f, \ copy_byte_f) \ diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index 5bb3c4c74aa..b4dd5146558 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -4085,6 +4085,95 @@ class StubGenerator: public StubCodeGenerator { return start; } + // Execute one round of keccak of two computations in parallel. + // One of the states should be loaded into the lower halves of + // the vector registers v0-v24, the other should be loaded into + // the upper halves of those registers. The ld1r instruction loads + // the round constant into both halves of register v31. + // Intermediate results c0...c5 and d0...d5 are computed + // in registers v25...v30. + // All vector instructions that are used operate on both register + // halves in parallel. + // If only a single computation is needed, one can only load the lower halves. + void keccak_round(Register rscratch1) { + __ eor3(v29, __ T16B, v4, v9, v14); // c4 = a4 ^ a9 ^ a14 + __ eor3(v26, __ T16B, v1, v6, v11); // c1 = a1 ^ a16 ^ a11 + __ eor3(v28, __ T16B, v3, v8, v13); // c3 = a3 ^ a8 ^a13 + __ eor3(v25, __ T16B, v0, v5, v10); // c0 = a0 ^ a5 ^ a10 + __ eor3(v27, __ T16B, v2, v7, v12); // c2 = a2 ^ a7 ^ a12 + __ eor3(v29, __ T16B, v29, v19, v24); // c4 ^= a19 ^ a24 + __ eor3(v26, __ T16B, v26, v16, v21); // c1 ^= a16 ^ a21 + __ eor3(v28, __ T16B, v28, v18, v23); // c3 ^= a18 ^ a23 + __ eor3(v25, __ T16B, v25, v15, v20); // c0 ^= a15 ^ a20 + __ eor3(v27, __ T16B, v27, v17, v22); // c2 ^= a17 ^ a22 + + __ rax1(v30, __ T2D, v29, v26); // d0 = c4 ^ rol(c1, 1) + __ rax1(v26, __ T2D, v26, v28); // d2 = c1 ^ rol(c3, 1) + __ rax1(v28, __ T2D, v28, v25); // d4 = c3 ^ rol(c0, 1) + __ rax1(v25, __ T2D, v25, v27); // d1 = c0 ^ rol(c2, 1) + __ rax1(v27, __ T2D, v27, v29); // d3 = c2 ^ rol(c4, 1) + + __ eor(v0, __ T16B, v0, v30); // a0 = a0 ^ d0 + __ xar(v29, __ T2D, v1, v25, (64 - 1)); // a10' = rol((a1^d1), 1) + __ xar(v1, __ T2D, v6, v25, (64 - 44)); // a1 = rol(a6^d1), 44) + __ xar(v6, __ T2D, v9, v28, (64 - 20)); // a6 = rol((a9^d4), 20) + __ xar(v9, __ T2D, v22, v26, (64 - 61)); // a9 = rol((a22^d2), 61) + __ xar(v22, __ T2D, v14, v28, (64 - 39)); // a22 = rol((a14^d4), 39) + __ xar(v14, __ T2D, v20, v30, (64 - 18)); // a14 = rol((a20^d0), 18) + __ xar(v31, __ T2D, v2, v26, (64 - 62)); // a20' = rol((a2^d2), 62) + __ xar(v2, __ T2D, v12, v26, (64 - 43)); // a2 = rol((a12^d2), 43) + __ xar(v12, __ T2D, v13, v27, (64 - 25)); // a12 = rol((a13^d3), 25) + __ xar(v13, __ T2D, v19, v28, (64 - 8)); // a13 = rol((a19^d4), 8) + __ xar(v19, __ T2D, v23, v27, (64 - 56)); // a19 = rol((a23^d3), 56) + __ xar(v23, __ T2D, v15, v30, (64 - 41)); // a23 = rol((a15^d0), 41) + __ xar(v15, __ T2D, v4, v28, (64 - 27)); // a15 = rol((a4^d4), 27) + __ xar(v28, __ T2D, v24, v28, (64 - 14)); // a4' = rol((a24^d4), 14) + __ xar(v24, __ T2D, v21, v25, (64 - 2)); // a24 = rol((a21^d1), 2) + __ xar(v8, __ T2D, v8, v27, (64 - 55)); // a21' = rol((a8^d3), 55) + __ xar(v4, __ T2D, v16, v25, (64 - 45)); // a8' = rol((a16^d1), 45) + __ xar(v16, __ T2D, v5, v30, (64 - 36)); // a16 = rol((a5^d0), 36) + __ xar(v5, __ T2D, v3, v27, (64 - 28)); // a5 = rol((a3^d3), 28) + __ xar(v27, __ T2D, v18, v27, (64 - 21)); // a3' = rol((a18^d3), 21) + __ xar(v3, __ T2D, v17, v26, (64 - 15)); // a18' = rol((a17^d2), 15) + __ xar(v25, __ T2D, v11, v25, (64 - 10)); // a17' = rol((a11^d1), 10) + __ xar(v26, __ T2D, v7, v26, (64 - 6)); // a11' = rol((a7^d2), 6) + __ xar(v30, __ T2D, v10, v30, (64 - 3)); // a7' = rol((a10^d0), 3) + + __ bcax(v20, __ T16B, v31, v22, v8); // a20 = a20' ^ (~a21 & a22') + __ bcax(v21, __ T16B, v8, v23, v22); // a21 = a21' ^ (~a22 & a23) + __ bcax(v22, __ T16B, v22, v24, v23); // a22 = a22 ^ (~a23 & a24) + __ bcax(v23, __ T16B, v23, v31, v24); // a23 = a23 ^ (~a24 & a20') + __ bcax(v24, __ T16B, v24, v8, v31); // a24 = a24 ^ (~a20' & a21') + + __ ld1r(v31, __ T2D, __ post(rscratch1, 8)); // rc = round_constants[i] + + __ bcax(v17, __ T16B, v25, v19, v3); // a17 = a17' ^ (~a18' & a19) + __ bcax(v18, __ T16B, v3, v15, v19); // a18 = a18' ^ (~a19 & a15') + __ bcax(v19, __ T16B, v19, v16, v15); // a19 = a19 ^ (~a15 & a16) + __ bcax(v15, __ T16B, v15, v25, v16); // a15 = a15 ^ (~a16 & a17') + __ bcax(v16, __ T16B, v16, v3, v25); // a16 = a16 ^ (~a17' & a18') + + __ bcax(v10, __ T16B, v29, v12, v26); // a10 = a10' ^ (~a11' & a12) + __ bcax(v11, __ T16B, v26, v13, v12); // a11 = a11' ^ (~a12 & a13) + __ bcax(v12, __ T16B, v12, v14, v13); // a12 = a12 ^ (~a13 & a14) + __ bcax(v13, __ T16B, v13, v29, v14); // a13 = a13 ^ (~a14 & a10') + __ bcax(v14, __ T16B, v14, v26, v29); // a14 = a14 ^ (~a10' & a11') + + __ bcax(v7, __ T16B, v30, v9, v4); // a7 = a7' ^ (~a8' & a9) + __ bcax(v8, __ T16B, v4, v5, v9); // a8 = a8' ^ (~a9 & a5) + __ bcax(v9, __ T16B, v9, v6, v5); // a9 = a9 ^ (~a5 & a6) + __ bcax(v5, __ T16B, v5, v30, v6); // a5 = a5 ^ (~a6 & a7) + __ bcax(v6, __ T16B, v6, v4, v30); // a6 = a6 ^ (~a7 & a8') + + __ bcax(v3, __ T16B, v27, v0, v28); // a3 = a3' ^ (~a4' & a0) + __ bcax(v4, __ T16B, v28, v1, v0); // a4 = a4' ^ (~a0 & a1) + __ bcax(v0, __ T16B, v0, v2, v1); // a0 = a0 ^ (~a1 & a2) + __ bcax(v1, __ T16B, v1, v27, v2); // a1 = a1 ^ (~a2 & a3) + __ bcax(v2, __ T16B, v2, v28, v27); // a2 = a2 ^ (~a3 & a4') + + __ eor(v0, __ T16B, v0, v31); // a0 = a0 ^ rc + } + // Arguments: // // Inputs: @@ -4189,7 +4278,7 @@ class StubGenerator: public StubCodeGenerator { __ cbzw(c_rarg5, rounds24_loop); __ tbnz(block_size, 5, shake128); - // block_size == 144, bit5 == 0, SHA3-244 + // block_size == 144, bit5 == 0, SHA3-224 __ ldrd(v28, __ post(buf, 8)); __ eor(v17, __ T8B, v17, v28); __ b(rounds24_loop); @@ -4218,82 +4307,7 @@ class StubGenerator: public StubCodeGenerator { __ BIND(rounds24_loop); __ subw(rscratch2, rscratch2, 1); - __ eor3(v29, __ T16B, v4, v9, v14); - __ eor3(v26, __ T16B, v1, v6, v11); - __ eor3(v28, __ T16B, v3, v8, v13); - __ eor3(v25, __ T16B, v0, v5, v10); - __ eor3(v27, __ T16B, v2, v7, v12); - __ eor3(v29, __ T16B, v29, v19, v24); - __ eor3(v26, __ T16B, v26, v16, v21); - __ eor3(v28, __ T16B, v28, v18, v23); - __ eor3(v25, __ T16B, v25, v15, v20); - __ eor3(v27, __ T16B, v27, v17, v22); - - __ rax1(v30, __ T2D, v29, v26); - __ rax1(v26, __ T2D, v26, v28); - __ rax1(v28, __ T2D, v28, v25); - __ rax1(v25, __ T2D, v25, v27); - __ rax1(v27, __ T2D, v27, v29); - - __ eor(v0, __ T16B, v0, v30); - __ xar(v29, __ T2D, v1, v25, (64 - 1)); - __ xar(v1, __ T2D, v6, v25, (64 - 44)); - __ xar(v6, __ T2D, v9, v28, (64 - 20)); - __ xar(v9, __ T2D, v22, v26, (64 - 61)); - __ xar(v22, __ T2D, v14, v28, (64 - 39)); - __ xar(v14, __ T2D, v20, v30, (64 - 18)); - __ xar(v31, __ T2D, v2, v26, (64 - 62)); - __ xar(v2, __ T2D, v12, v26, (64 - 43)); - __ xar(v12, __ T2D, v13, v27, (64 - 25)); - __ xar(v13, __ T2D, v19, v28, (64 - 8)); - __ xar(v19, __ T2D, v23, v27, (64 - 56)); - __ xar(v23, __ T2D, v15, v30, (64 - 41)); - __ xar(v15, __ T2D, v4, v28, (64 - 27)); - __ xar(v28, __ T2D, v24, v28, (64 - 14)); - __ xar(v24, __ T2D, v21, v25, (64 - 2)); - __ xar(v8, __ T2D, v8, v27, (64 - 55)); - __ xar(v4, __ T2D, v16, v25, (64 - 45)); - __ xar(v16, __ T2D, v5, v30, (64 - 36)); - __ xar(v5, __ T2D, v3, v27, (64 - 28)); - __ xar(v27, __ T2D, v18, v27, (64 - 21)); - __ xar(v3, __ T2D, v17, v26, (64 - 15)); - __ xar(v25, __ T2D, v11, v25, (64 - 10)); - __ xar(v26, __ T2D, v7, v26, (64 - 6)); - __ xar(v30, __ T2D, v10, v30, (64 - 3)); - - __ bcax(v20, __ T16B, v31, v22, v8); - __ bcax(v21, __ T16B, v8, v23, v22); - __ bcax(v22, __ T16B, v22, v24, v23); - __ bcax(v23, __ T16B, v23, v31, v24); - __ bcax(v24, __ T16B, v24, v8, v31); - - __ ld1r(v31, __ T2D, __ post(rscratch1, 8)); - - __ bcax(v17, __ T16B, v25, v19, v3); - __ bcax(v18, __ T16B, v3, v15, v19); - __ bcax(v19, __ T16B, v19, v16, v15); - __ bcax(v15, __ T16B, v15, v25, v16); - __ bcax(v16, __ T16B, v16, v3, v25); - - __ bcax(v10, __ T16B, v29, v12, v26); - __ bcax(v11, __ T16B, v26, v13, v12); - __ bcax(v12, __ T16B, v12, v14, v13); - __ bcax(v13, __ T16B, v13, v29, v14); - __ bcax(v14, __ T16B, v14, v26, v29); - - __ bcax(v7, __ T16B, v30, v9, v4); - __ bcax(v8, __ T16B, v4, v5, v9); - __ bcax(v9, __ T16B, v9, v6, v5); - __ bcax(v5, __ T16B, v5, v30, v6); - __ bcax(v6, __ T16B, v6, v4, v30); - - __ bcax(v3, __ T16B, v27, v0, v28); - __ bcax(v4, __ T16B, v28, v1, v0); - __ bcax(v0, __ T16B, v0, v2, v1); - __ bcax(v1, __ T16B, v1, v27, v2); - __ bcax(v2, __ T16B, v2, v28, v27); - - __ eor(v0, __ T16B, v0, v31); + keccak_round(rscratch1); __ cbnzw(rscratch2, rounds24_loop); @@ -4312,11 +4326,102 @@ class StubGenerator: public StubCodeGenerator { __ st1(v20, v21, v22, v23, __ T1D, __ post(state, 32)); __ st1(v24, __ T1D, state); + // restore callee-saved registers + __ ldpd(v14, v15, Address(sp, 48)); + __ ldpd(v12, v13, Address(sp, 32)); + __ ldpd(v10, v11, Address(sp, 16)); + __ ldpd(v8, v9, __ post(sp, 64)); + + __ ret(lr); + + return start; + } + + // Inputs: + // c_rarg0 - long[] state0 + // c_rarg1 - long[] state1 + address generate_double_keccak() { + static const uint64_t round_consts[24] = { + 0x0000000000000001L, 0x0000000000008082L, 0x800000000000808AL, + 0x8000000080008000L, 0x000000000000808BL, 0x0000000080000001L, + 0x8000000080008081L, 0x8000000000008009L, 0x000000000000008AL, + 0x0000000000000088L, 0x0000000080008009L, 0x000000008000000AL, + 0x000000008000808BL, 0x800000000000008BL, 0x8000000000008089L, + 0x8000000000008003L, 0x8000000000008002L, 0x8000000000000080L, + 0x000000000000800AL, 0x800000008000000AL, 0x8000000080008081L, + 0x8000000000008080L, 0x0000000080000001L, 0x8000000080008008L + }; + + // Implements the double_keccak() method of the + // sun.secyrity.provider.SHA3Parallel class + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "double_keccak"); + address start = __ pc(); + __ enter(); + + Register state0 = c_rarg0; + Register state1 = c_rarg1; + + Label rounds24_loop; + + // save callee-saved registers + __ stpd(v8, v9, __ pre(sp, -64)); + __ stpd(v10, v11, Address(sp, 16)); + __ stpd(v12, v13, Address(sp, 32)); + __ stpd(v14, v15, Address(sp, 48)); + + // load states + __ add(rscratch1, state0, 32); + __ ld4(v0, v1, v2, v3, __ D, 0, state0); + __ ld4(v4, v5, v6, v7, __ D, 0, __ post(rscratch1, 32)); + __ ld4(v8, v9, v10, v11, __ D, 0, __ post(rscratch1, 32)); + __ ld4(v12, v13, v14, v15, __ D, 0, __ post(rscratch1, 32)); + __ ld4(v16, v17, v18, v19, __ D, 0, __ post(rscratch1, 32)); + __ ld4(v20, v21, v22, v23, __ D, 0, __ post(rscratch1, 32)); + __ ld1(v24, __ D, 0, rscratch1); + __ add(rscratch1, state1, 32); + __ ld4(v0, v1, v2, v3, __ D, 1, state1); + __ ld4(v4, v5, v6, v7, __ D, 1, __ post(rscratch1, 32)); + __ ld4(v8, v9, v10, v11, __ D, 1, __ post(rscratch1, 32)); + __ ld4(v12, v13, v14, v15, __ D, 1, __ post(rscratch1, 32)); + __ ld4(v16, v17, v18, v19, __ D, 1, __ post(rscratch1, 32)); + __ ld4(v20, v21, v22, v23, __ D, 1, __ post(rscratch1, 32)); + __ ld1(v24, __ D, 1, rscratch1); + + // 24 keccak rounds + __ movw(rscratch2, 24); + + // load round_constants base + __ lea(rscratch1, ExternalAddress((address) round_consts)); + + __ BIND(rounds24_loop); + __ subw(rscratch2, rscratch2, 1); + keccak_round(rscratch1); + __ cbnzw(rscratch2, rounds24_loop); + + __ st4(v0, v1, v2, v3, __ D, 0, __ post(state0, 32)); + __ st4(v4, v5, v6, v7, __ D, 0, __ post(state0, 32)); + __ st4(v8, v9, v10, v11, __ D, 0, __ post(state0, 32)); + __ st4(v12, v13, v14, v15, __ D, 0, __ post(state0, 32)); + __ st4(v16, v17, v18, v19, __ D, 0, __ post(state0, 32)); + __ st4(v20, v21, v22, v23, __ D, 0, __ post(state0, 32)); + __ st1(v24, __ D, 0, state0); + __ st4(v0, v1, v2, v3, __ D, 1, __ post(state1, 32)); + __ st4(v4, v5, v6, v7, __ D, 1, __ post(state1, 32)); + __ st4(v8, v9, v10, v11, __ D, 1, __ post(state1, 32)); + __ st4(v12, v13, v14, v15, __ D, 1, __ post(state1, 32)); + __ st4(v16, v17, v18, v19, __ D, 1, __ post(state1, 32)); + __ st4(v20, v21, v22, v23, __ D, 1, __ post(state1, 32)); + __ st1(v24, __ D, 1, state1); + + // restore callee-saved vector registers __ ldpd(v14, v15, Address(sp, 48)); __ ldpd(v12, v13, Address(sp, 32)); __ ldpd(v10, v11, Address(sp, 16)); __ ldpd(v8, v9, __ post(sp, 64)); + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 __ ret(lr); return start; @@ -4560,6 +4665,961 @@ class StubGenerator: public StubCodeGenerator { return start; } + void dilithium_load16zetas(int o0, Register zetas) { + __ ldpq(as_FloatRegister(o0), as_FloatRegister(o0 + 1), __ post (zetas, 32)); + __ ldpq(as_FloatRegister(o0 + 2), as_FloatRegister(o0 + 3), __ post (zetas, 32)); + + } + + void dilithium_load32zetas(Register zetas) { + dilithium_load16zetas(16, zetas); + dilithium_load16zetas(20, zetas); + } + + // 2x16 32-bit Montgomery multiplications in parallel + // See the montMul() method of the sun.security.provider.ML_DSA class. + // Here MONT_R_BITS is 32, so the right shift by it is implicit. + // The constants qInv = MONT_Q_INV_MOD_R and q = MONT_Q are loaded in + // (all 32-bit chunks of) vector registers v30 and v31, resp. + // The inputs are b[i]s in v0-v7 and c[i]s v16-v23 and + // the results are a[i]s in v16-v23, four 32-bit values in each register + // and we do a_i = b_i * c_i * 2^-32 mod MONT_Q for all + void dilithium_montmul32(bool by_constant) { + FloatRegister vr0 = by_constant ? v29 : v0; + FloatRegister vr1 = by_constant ? v29 : v1; + FloatRegister vr2 = by_constant ? v29 : v2; + FloatRegister vr3 = by_constant ? v29 : v3; + FloatRegister vr4 = by_constant ? v29 : v4; + FloatRegister vr5 = by_constant ? v29 : v5; + FloatRegister vr6 = by_constant ? v29 : v6; + FloatRegister vr7 = by_constant ? v29 : v7; + + __ sqdmulh(v24, __ T4S, vr0, v16); // aHigh = hi32(2 * b * c) + __ mulv(v16, __ T4S, vr0, v16); // aLow = lo32(b * c) + __ sqdmulh(v25, __ T4S, vr1, v17); + __ mulv(v17, __ T4S, vr1, v17); + __ sqdmulh(v26, __ T4S, vr2, v18); + __ mulv(v18, __ T4S, vr2, v18); + __ sqdmulh(v27, __ T4S, vr3, v19); + __ mulv(v19, __ T4S, vr3, v19); + + __ mulv(v16, __ T4S, v16, v30); // m = aLow * qinv + __ mulv(v17, __ T4S, v17, v30); + __ mulv(v18, __ T4S, v18, v30); + __ mulv(v19, __ T4S, v19, v30); + + __ sqdmulh(v16, __ T4S, v16, v31); // n = hi32(2 * m * q) + __ sqdmulh(v17, __ T4S, v17, v31); + __ sqdmulh(v18, __ T4S, v18, v31); + __ sqdmulh(v19, __ T4S, v19, v31); + + __ shsubv(v16, __ T4S, v24, v16); // a = (aHigh - n) / 2 + __ shsubv(v17, __ T4S, v25, v17); + __ shsubv(v18, __ T4S, v26, v18); + __ shsubv(v19, __ T4S, v27, v19); + + __ sqdmulh(v24, __ T4S, vr4, v20); + __ mulv(v20, __ T4S, vr4, v20); + __ sqdmulh(v25, __ T4S, vr5, v21); + __ mulv(v21, __ T4S, vr5, v21); + __ sqdmulh(v26, __ T4S, vr6, v22); + __ mulv(v22, __ T4S, vr6, v22); + __ sqdmulh(v27, __ T4S, vr7, v23); + __ mulv(v23, __ T4S, vr7, v23); + + __ mulv(v20, __ T4S, v20, v30); + __ mulv(v21, __ T4S, v21, v30); + __ mulv(v22, __ T4S, v22, v30); + __ mulv(v23, __ T4S, v23, v30); + + __ sqdmulh(v20, __ T4S, v20, v31); + __ sqdmulh(v21, __ T4S, v21, v31); + __ sqdmulh(v22, __ T4S, v22, v31); + __ sqdmulh(v23, __ T4S, v23, v31); + + __ shsubv(v20, __ T4S, v24, v20); + __ shsubv(v21, __ T4S, v25, v21); + __ shsubv(v22, __ T4S, v26, v22); + __ shsubv(v23, __ T4S, v27, v23); + } + + // Do the addition and subtraction done in the ntt algorithm. + // See sun.security.provider.ML_DSA.implDilithiumAlmostNttJava() + void dilithium_add_sub32() { + __ addv(v24, __ T4S, v0, v16); // coeffs[j] = coeffs[j] + tmp; + __ addv(v25, __ T4S, v1, v17); + __ addv(v26, __ T4S, v2, v18); + __ addv(v27, __ T4S, v3, v19); + __ addv(v28, __ T4S, v4, v20); + __ addv(v29, __ T4S, v5, v21); + __ addv(v30, __ T4S, v6, v22); + __ addv(v31, __ T4S, v7, v23); + + __ subv(v0, __ T4S, v0, v16); // coeffs[j + l] = coeffs[j] - tmp; + __ subv(v1, __ T4S, v1, v17); + __ subv(v2, __ T4S, v2, v18); + __ subv(v3, __ T4S, v3, v19); + __ subv(v4, __ T4S, v4, v20); + __ subv(v5, __ T4S, v5, v21); + __ subv(v6, __ T4S, v6, v22); + __ subv(v7, __ T4S, v7, v23); + } + + // Do the same computation that + // dilithium_montmul32() and dilithium_add_sub32() does, + // except for only 4x4 32-bit vector elements and with + // different register usage. + void dilithium_montmul_sub_add16() { + __ sqdmulh(v24, __ T4S, v1, v16); + __ mulv(v16, __ T4S, v1, v16); + __ sqdmulh(v25, __ T4S, v3, v17); + __ mulv(v17, __ T4S, v3, v17); + __ sqdmulh(v26, __ T4S, v5, v18); + __ mulv(v18, __ T4S, v5, v18); + __ sqdmulh(v27, __ T4S, v7, v19); + __ mulv(v19, __ T4S, v7, v19); + + __ mulv(v16, __ T4S, v16, v30); + __ mulv(v17, __ T4S, v17, v30); + __ mulv(v18, __ T4S, v18, v30); + __ mulv(v19, __ T4S, v19, v30); + + __ sqdmulh(v16, __ T4S, v16, v31); + __ sqdmulh(v17, __ T4S, v17, v31); + __ sqdmulh(v18, __ T4S, v18, v31); + __ sqdmulh(v19, __ T4S, v19, v31); + + __ shsubv(v16, __ T4S, v24, v16); + __ shsubv(v17, __ T4S, v25, v17); + __ shsubv(v18, __ T4S, v26, v18); + __ shsubv(v19, __ T4S, v27, v19); + + __ subv(v1, __ T4S, v0, v16); + __ subv(v3, __ T4S, v2, v17); + __ subv(v5, __ T4S, v4, v18); + __ subv(v7, __ T4S, v6, v19); + + __ addv(v0, __ T4S, v0, v16); + __ addv(v2, __ T4S, v2, v17); + __ addv(v4, __ T4S, v4, v18); + __ addv(v6, __ T4S, v6, v19); + } + + // At these levels, the indices that correspond to the 'j's (and 'j+l's) + // in the Java implementation come in sequences of at least 8, so we + // can use ldpq to collect the corresponding data into pairs of vector + // registers. + // We collect the coefficients corresponding to the 'j+l' indexes into + // the vector registers v0-v7, the zetas into the vector registers v16-v23 + // then we do the (Montgomery) multiplications by the zetas in parallel + // into v16-v23, load the coeffs corresponding to the 'j' indexes into + // v0-v7, then do the additions into v24-v31 and the subtractions into + // v0-v7 and finally save the results back to the coeffs array. + void dilithiumNttLevel0_4(const Register dilithiumConsts, + const Register coeffs, const Register zetas) { + int c1 = 0; + int c2 = 512; + int startIncr; + int incr1 = 32; + int incr2 = 64; + int incr3 = 96; + + for (int level = 0; level < 5; level++) { + int c1Start = c1; + int c2Start = c2; + if (level == 3) { + incr1 = 32; + incr2 = 128; + incr3 = 160; + } else if (level == 4) { + incr1 = 64; + incr2 = 128; + incr3 = 192; + } + + for (int i = 0; i < 4; i++) { + __ ldpq(v30, v31, Address(dilithiumConsts, 0)); // qInv, q + __ ldpq(v0, v1, Address(coeffs, c2Start)); + __ ldpq(v2, v3, Address(coeffs, c2Start + incr1)); + __ ldpq(v4, v5, Address(coeffs, c2Start + incr2)); + __ ldpq(v6, v7, Address(coeffs, c2Start + incr3)); + dilithium_load32zetas(zetas); + dilithium_montmul32(false); + __ ldpq(v0, v1, Address(coeffs, c1Start)); + __ ldpq(v2, v3, Address(coeffs, c1Start + incr1)); + __ ldpq(v4, v5, Address(coeffs, c1Start + incr2)); + __ ldpq(v6, v7, Address(coeffs, c1Start + incr3)); + dilithium_add_sub32(); + __ stpq(v24, v25, Address(coeffs, c1Start)); + __ stpq(v26, v27, Address(coeffs, c1Start + incr1)); + __ stpq(v28, v29, Address(coeffs, c1Start + incr2)); + __ stpq(v30, v31, Address(coeffs, c1Start + incr3)); + __ stpq(v0, v1, Address(coeffs, c2Start)); + __ stpq(v2, v3, Address(coeffs, c2Start + incr1)); + __ stpq(v4, v5, Address(coeffs, c2Start + incr2)); + __ stpq(v6, v7, Address(coeffs, c2Start + incr3)); + + int k = 4 * level + i; + + if (k > 7) { + startIncr = 256; + } else if (k == 5) { + startIncr = 384; + } else { + startIncr = 128; + } + + c1Start += startIncr; + c2Start += startIncr; + } + + c2 /= 2; + } + } + + // Dilithium NTT function except for the final "normalization" to |coeff| < Q. + // Implements the method + // static int implDilithiumAlmostNtt(int[] coeffs, int zetas[]) {} + // of the Java class sun.security.provider + // + // coeffs (int[256]) = c_rarg0 + // zetas (int[256]) = c_rarg1 + address generate_dilithiumAlmostNtt() { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = StubGenStubId::dilithiumAlmostNtt_id; + StubCodeMark mark(this, stub_id); + address start = __ pc(); + __ enter(); + + const Register coeffs = c_rarg0; + const Register zetas = c_rarg1; + + const Register tmpAddr = r9; + const Register dilithiumConsts = r10; + const Register result = r11; + + __ add(result, coeffs, 0); + __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + + // Each level represents one iteration of the outer for loop of the Java version + + // level 0-4 + dilithiumNttLevel0_4(dilithiumConsts, coeffs, zetas); + + // level 5 + for (int i = 0; i < 1024; i += 256) { + __ ldpq(v30, v31, Address(dilithiumConsts, 0)); // qInv, q + __ ldr(v0, __ Q, Address(coeffs, i + 16)); + __ ldr(v1, __ Q, Address(coeffs, i + 48)); + __ ldr(v2, __ Q, Address(coeffs, i + 80)); + __ ldr(v3, __ Q, Address(coeffs, i + 112)); + __ ldr(v4, __ Q, Address(coeffs, i + 144)); + __ ldr(v5, __ Q, Address(coeffs, i + 176)); + __ ldr(v6, __ Q, Address(coeffs, i + 208)); + __ ldr(v7, __ Q, Address(coeffs, i + 240)); + dilithium_load32zetas(zetas); + dilithium_montmul32(false); + __ ldr(v0, __ Q, Address(coeffs, i)); + __ ldr(v1, __ Q, Address(coeffs, i + 32)); + __ ldr(v2, __ Q, Address(coeffs, i + 64)); + __ ldr(v3, __ Q, Address(coeffs, i + 96)); + __ ldr(v4, __ Q, Address(coeffs, i + 128)); + __ ldr(v5, __ Q, Address(coeffs, i + 160)); + __ ldr(v6, __ Q, Address(coeffs, i + 192)); + __ ldr(v7, __ Q, Address(coeffs, i + 224)); + dilithium_add_sub32(); + __ str(v24, __ Q, Address(coeffs, i)); + __ str(v25, __ Q, Address(coeffs, i + 32)); + __ str(v26, __ Q, Address(coeffs, i + 64)); + __ str(v27, __ Q, Address(coeffs, i + 96)); + __ str(v28, __ Q, Address(coeffs, i + 128)); + __ str(v29, __ Q, Address(coeffs, i + 160)); + __ str(v30, __ Q, Address(coeffs, i + 192)); + __ str(v31, __ Q, Address(coeffs, i + 224)); + __ str(v0, __ Q, Address(coeffs, i + 16)); + __ str(v1, __ Q, Address(coeffs, i + 48)); + __ str(v2, __ Q, Address(coeffs, i + 80)); + __ str(v3, __ Q, Address(coeffs, i + 112)); + __ str(v4, __ Q, Address(coeffs, i + 144)); + __ str(v5, __ Q, Address(coeffs, i + 176)); + __ str(v6, __ Q, Address(coeffs, i + 208)); + __ str(v7, __ Q, Address(coeffs, i + 240)); + } + + // level 6 + for (int i = 0; i < 1024; i += 128) { + __ ldpq(v30, v31, Address(dilithiumConsts, 0)); // qInv, q + __ add(tmpAddr, coeffs, i); + __ ld2(v0, v1, __ T2D, tmpAddr); + __ add(tmpAddr, coeffs, i + 32); + __ ld2(v2, v3, __ T2D, tmpAddr); + __ add(tmpAddr, coeffs, i + 64); + __ ld2(v4, v5, __ T2D, tmpAddr); + __ add(tmpAddr, coeffs, i + 96); + __ ld2(v6, v7, __ T2D, tmpAddr); + dilithium_load16zetas(16, zetas); + dilithium_montmul_sub_add16(); + __ add(tmpAddr, coeffs, i); + __ st2(v0, v1, __ T2D, tmpAddr); + __ add(tmpAddr, coeffs, i + 32); + __ st2(v2, v3, __ T2D, tmpAddr); + __ add(tmpAddr, coeffs, i + 64); + __ st2(v4, v5, __ T2D, tmpAddr); + __ add(tmpAddr, coeffs, i + 96); + __ st2(v6, v7, __ T2D, tmpAddr); + } + + // level 7 + for (int i = 0; i < 1024; i += 128) { + __ ldpq(v30, v31, Address(dilithiumConsts, 0)); // qInv, q + __ add(tmpAddr, coeffs, i); + __ ld2(v0, v1, __ T4S, tmpAddr); + __ add(tmpAddr, coeffs, i + 32); + __ ld2(v2, v3, __ T4S, tmpAddr); + __ add(tmpAddr, coeffs, i + 64); + __ ld2(v4, v5, __ T4S, tmpAddr); + __ add(tmpAddr, coeffs, i + 96); + __ ld2(v6, v7, __ T4S, tmpAddr); + dilithium_load16zetas(16, zetas); + dilithium_montmul_sub_add16(); + __ add(tmpAddr, coeffs, i); + __ st2(v0, v1, __ T4S, tmpAddr); + __ add(tmpAddr, coeffs, i + 32); + __ st2(v2, v3, __ T4S, tmpAddr); + __ add(tmpAddr, coeffs, i + 64); + __ st2(v4, v5, __ T4S, tmpAddr); + __ add(tmpAddr, coeffs, i + 96); + __ st2(v6, v7, __ T4S, tmpAddr); + } + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + + } + + // Do the computations that can be found in the body of the loop in + // sun.security.provider.ML_DSA.implDilithiumAlmostInverseNttJava() + // for 16 coefficients in parallel: + // tmp = coeffs[j]; + // coeffs[j] = (tmp + coeffs[j + l]); + // coeffs[j + l] = montMul(tmp - coeffs[j + l], -MONT_ZETAS_FOR_NTT[m]); + // coefss[j]s are loaded in v0, v2, v4 and v6, + // coeffs[j + l]s in v1, v3, v5 and v7, + // the corresponding zetas in v16, v17, v18 and v19. + void dilithium_sub_add_montmul16() { + __ subv(v20, __ T4S, v0, v1); + __ subv(v21, __ T4S, v2, v3); + __ subv(v22, __ T4S, v4, v5); + __ subv(v23, __ T4S, v6, v7); + + __ addv(v0, __ T4S, v0, v1); + __ addv(v2, __ T4S, v2, v3); + __ addv(v4, __ T4S, v4, v5); + __ addv(v6, __ T4S, v6, v7); + + __ sqdmulh(v24, __ T4S, v20, v16); // aHigh = hi32(2 * b * c) + __ mulv(v1, __ T4S, v20, v16); // aLow = lo32(b * c) + __ sqdmulh(v25, __ T4S, v21, v17); + __ mulv(v3, __ T4S, v21, v17); + __ sqdmulh(v26, __ T4S, v22, v18); + __ mulv(v5, __ T4S, v22, v18); + __ sqdmulh(v27, __ T4S, v23, v19); + __ mulv(v7, __ T4S, v23, v19); + + __ mulv(v1, __ T4S, v1, v30); // m = (aLow * q) + __ mulv(v3, __ T4S, v3, v30); + __ mulv(v5, __ T4S, v5, v30); + __ mulv(v7, __ T4S, v7, v30); + + __ sqdmulh(v1, __ T4S, v1, v31); // n = hi32(2 * m * q) + __ sqdmulh(v3, __ T4S, v3, v31); + __ sqdmulh(v5, __ T4S, v5, v31); + __ sqdmulh(v7, __ T4S, v7, v31); + + __ shsubv(v1, __ T4S, v24, v1); // a = (aHigh - n) / 2 + __ shsubv(v3, __ T4S, v25, v3); + __ shsubv(v5, __ T4S, v26, v5); + __ shsubv(v7, __ T4S, v27, v7); + } + + // At these levels, the indices that correspond to the 'j's (and 'j+l's) + // in the Java implementation come in sequences of at least 8, so we + // can use ldpq to collect the corresponding data into pairs of vector + // registers + // We collect the coefficients that correspond to the 'j's into v0-v7 + // the coefficiets that correspond to the 'j+l's into v16-v23 then + // do the additions into v24-v31 and the subtractions into v0-v7 then + // save the result of the additions, load the zetas into v16-v23 + // do the (Montgomery) multiplications by zeta in parallel into v16-v23 + // finally save the results back to the coeffs array + void dilithiumInverseNttLevel3_7(const Register dilithiumConsts, + const Register coeffs, const Register zetas) { + int c1 = 0; + int c2 = 32; + int startIncr; + int incr1; + int incr2; + int incr3; + + for (int level = 3; level < 8; level++) { + int c1Start = c1; + int c2Start = c2; + if (level == 3) { + incr1 = 64; + incr2 = 128; + incr3 = 192; + } else if (level == 4) { + incr1 = 32; + incr2 = 128; + incr3 = 160; + } else { + incr1 = 32; + incr2 = 64; + incr3 = 96; + } + + for (int i = 0; i < 4; i++) { + __ ldpq(v0, v1, Address(coeffs, c1Start)); + __ ldpq(v2, v3, Address(coeffs, c1Start + incr1)); + __ ldpq(v4, v5, Address(coeffs, c1Start + incr2)); + __ ldpq(v6, v7, Address(coeffs, c1Start + incr3)); + __ ldpq(v16, v17, Address(coeffs, c2Start)); + __ ldpq(v18, v19, Address(coeffs, c2Start + incr1)); + __ ldpq(v20, v21, Address(coeffs, c2Start + incr2)); + __ ldpq(v22, v23, Address(coeffs, c2Start + incr3)); + dilithium_add_sub32(); + __ stpq(v24, v25, Address(coeffs, c1Start)); + __ stpq(v26, v27, Address(coeffs, c1Start + incr1)); + __ stpq(v28, v29, Address(coeffs, c1Start + incr2)); + __ stpq(v30, v31, Address(coeffs, c1Start + incr3)); + __ ldpq(v30, v31, Address(dilithiumConsts, 0)); // qInv, q + dilithium_load32zetas(zetas); + dilithium_montmul32(false); + __ stpq(v16, v17, Address(coeffs, c2Start)); + __ stpq(v18, v19, Address(coeffs, c2Start + incr1)); + __ stpq(v20, v21, Address(coeffs, c2Start + incr2)); + __ stpq(v22, v23, Address(coeffs, c2Start + incr3)); + + int k = 4 * level + i; + + if (k < 24) { + startIncr = 256; + } else if (k == 25) { + startIncr = 384; + } else { + startIncr = 128; + } + + c1Start += startIncr; + c2Start += startIncr; + } + + c2 *= 2; + } + } + + // Dilithium Inverse NTT function except the final mod Q division by 2^256. + // Implements the method + // static int implDilithiumAlmostInverseNtt(int[] coeffs, int[] zetas) {} of + // the sun.security.provider.ML_DSA class. + // + // coeffs (int[256]) = c_rarg0 + // zetas (int[256]) = c_rarg1 + address generate_dilithiumAlmostInverseNtt() { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = StubGenStubId::dilithiumAlmostInverseNtt_id; + StubCodeMark mark(this, stub_id); + address start = __ pc(); + __ enter(); + + const Register coeffs = c_rarg0; + const Register zetas = c_rarg1; + + const Register tmpAddr = r9; + const Register dilithiumConsts = r10; + const Register result = r11; + + __ add(result, coeffs, 0); + __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + + // Each level represents one iteration of the outer for loop of the Java version + // level0 + for (int i = 0; i < 1024; i += 128) { + __ ldpq(v30, v31, Address(dilithiumConsts, 0)); // qInv, q + __ add(tmpAddr, coeffs, i); + __ ld2(v0, v1, __ T4S, tmpAddr); + __ add(tmpAddr, coeffs, i + 32); + __ ld2(v2, v3, __ T4S, tmpAddr); + __ add(tmpAddr, coeffs, i + 64); + __ ld2(v4, v5, __ T4S, tmpAddr); + __ add(tmpAddr, coeffs, i + 96); + __ ld2(v6, v7, __ T4S, tmpAddr); + dilithium_load16zetas(16, zetas); + dilithium_sub_add_montmul16(); + __ add(tmpAddr, coeffs, i); + __ st2(v0, v1, __ T4S, tmpAddr); + __ add(tmpAddr, coeffs, i + 32); + __ st2(v2, v3, __ T4S, tmpAddr); + __ add(tmpAddr, coeffs, i + 64); + __ st2(v4, v5, __ T4S, tmpAddr); + __ add(tmpAddr, coeffs, i + 96); + __ st2(v6, v7, __ T4S, tmpAddr); + } + + // level 1 + for (int i = 0; i < 1024; i += 128) { + __ add(tmpAddr, coeffs, i); + __ ld2(v0, v1, __ T2D, tmpAddr); + __ add(tmpAddr, coeffs, i + 32); + __ ld2(v2, v3, __ T2D, tmpAddr); + __ add(tmpAddr, coeffs, i + 64); + __ ld2(v4, v5, __ T2D, tmpAddr); + __ add(tmpAddr, coeffs, i + 96); + __ ld2(v6, v7, __ T2D, tmpAddr); + dilithium_load16zetas(16, zetas); + dilithium_sub_add_montmul16(); + __ add(tmpAddr, coeffs, i); + __ st2(v0, v1, __ T2D, tmpAddr); + __ add(tmpAddr, coeffs, i + 32); + __ st2(v2, v3, __ T2D, tmpAddr); + __ add(tmpAddr, coeffs, i + 64); + __ st2(v4, v5, __ T2D, tmpAddr); + __ add(tmpAddr, coeffs, i + 96); + __ st2(v6, v7, __ T2D, tmpAddr); + } + + //level 2 + for (int i = 0; i < 1024; i += 256) { + __ ldr(v0, __ Q, Address(coeffs, i)); + __ ldr(v1, __ Q, Address(coeffs, i + 32)); + __ ldr(v2, __ Q, Address(coeffs, i + 64)); + __ ldr(v3, __ Q, Address(coeffs, i + 96)); + __ ldr(v4, __ Q, Address(coeffs, i + 128)); + __ ldr(v5, __ Q, Address(coeffs, i + 160)); + __ ldr(v6, __ Q, Address(coeffs, i + 192)); + __ ldr(v7, __ Q, Address(coeffs, i + 224)); + __ ldr(v16, __ Q, Address(coeffs, i + 16)); + __ ldr(v17, __ Q, Address(coeffs, i + 48)); + __ ldr(v18, __ Q, Address(coeffs, i + 80)); + __ ldr(v19, __ Q, Address(coeffs, i + 112)); + __ ldr(v20, __ Q, Address(coeffs, i + 144)); + __ ldr(v21, __ Q, Address(coeffs, i + 176)); + __ ldr(v22, __ Q, Address(coeffs, i + 208)); + __ ldr(v23, __ Q, Address(coeffs, i + 240)); + dilithium_add_sub32(); + __ str(v24, __ Q, Address(coeffs, i)); + __ str(v25, __ Q, Address(coeffs, i + 32)); + __ str(v26, __ Q, Address(coeffs, i + 64)); + __ str(v27, __ Q, Address(coeffs, i + 96)); + __ str(v28, __ Q, Address(coeffs, i + 128)); + __ str(v29, __ Q, Address(coeffs, i + 160)); + __ str(v30, __ Q, Address(coeffs, i + 192)); + __ str(v31, __ Q, Address(coeffs, i + 224)); + dilithium_load32zetas(zetas); + __ ldpq(v30, v31, Address(dilithiumConsts, 0)); // qInv, q + dilithium_montmul32(false); + __ str(v16, __ Q, Address(coeffs, i + 16)); + __ str(v17, __ Q, Address(coeffs, i + 48)); + __ str(v18, __ Q, Address(coeffs, i + 80)); + __ str(v19, __ Q, Address(coeffs, i + 112)); + __ str(v20, __ Q, Address(coeffs, i + 144)); + __ str(v21, __ Q, Address(coeffs, i + 176)); + __ str(v22, __ Q, Address(coeffs, i + 208)); + __ str(v23, __ Q, Address(coeffs, i + 240)); + } + + // level 3-7 + dilithiumInverseNttLevel3_7(dilithiumConsts, coeffs, zetas); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + + } + + // Dilithium multiply polynomials in the NTT domain. + // Straightforward implementation of the method + // static int implDilithiumNttMult( + // int[] result, int[] ntta, int[] nttb {} of + // the sun.security.provider.ML_DSA class. + // + // result (int[256]) = c_rarg0 + // poly1 (int[256]) = c_rarg1 + // poly2 (int[256]) = c_rarg2 + address generate_dilithiumNttMult() { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = StubGenStubId::dilithiumNttMult_id; + StubCodeMark mark(this, stub_id); + address start = __ pc(); + __ enter(); + + Label L_loop; + + const Register result = c_rarg0; + const Register poly1 = c_rarg1; + const Register poly2 = c_rarg2; + + const Register dilithiumConsts = r10; + const Register len = r11; + + __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + + __ ldpq(v30, v31, Address(dilithiumConsts, 0)); // qInv, q + __ ldr(v29, __ Q, Address(dilithiumConsts, 48)); // rSquare + + __ mov(len, zr); + __ add(len, len, 1024); + + __ BIND(L_loop); + + __ ldpq(v0, v1, __ post(poly1, 32)); + __ ldpq(v2, v3, __ post(poly1, 32)); + __ ldpq(v4, v5, __ post(poly1, 32)); + __ ldpq(v6, v7, __ post(poly1, 32)); + __ ldpq(v16, v17, __ post(poly2, 32)); + __ ldpq(v18, v19, __ post(poly2, 32)); + __ ldpq(v20, v21, __ post(poly2, 32)); + __ ldpq(v22, v23, __ post(poly2, 32)); + dilithium_montmul32(false); + dilithium_montmul32(true); + __ stpq(v16, v17, __ post(result, 32)); + __ stpq(v18, v19, __ post(result, 32)); + __ stpq(v20, v21, __ post(result, 32)); + __ stpq(v22, v23, __ post(result, 32)); + + __ sub(len, len, 128); + __ cmp(len, (u1)128); + __ br(Assembler::GE, L_loop); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + + } + + // Dilithium Motgomery multiply an array by a constant. + // A straightforward implementation of the method + // static int implDilithiumMontMulByConstant(int[] coeffs, int constant) {} + // of the sun.security.provider.MLDSA class + // + // coeffs (int[256]) = c_rarg0 + // constant (int) = c_rarg1 + address generate_dilithiumMontMulByConstant() { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = StubGenStubId::dilithiumMontMulByConstant_id; + StubCodeMark mark(this, stub_id); + address start = __ pc(); + __ enter(); + + Label L_loop; + + const Register coeffs = c_rarg0; + const Register constant = c_rarg1; + + const Register dilithiumConsts = r10; + const Register result = r11; + const Register len = r12; + + __ add(result, coeffs, 0); + __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + + __ ldpq(v30, v31, Address(dilithiumConsts, 0)); // qInv, q + __ dup(v29, __ T4S, constant); + __ mov(len, zr); + __ add(len, len, 1024); + + __ BIND(L_loop); + + __ ldpq(v16, v17, __ post(coeffs, 32)); + __ ldpq(v18, v19, __ post(coeffs, 32)); + __ ldpq(v20, v21, __ post(coeffs, 32)); + __ ldpq(v22, v23, __ post(coeffs, 32)); + dilithium_montmul32(true); + __ stpq(v16, v17, __ post(result, 32)); + __ stpq(v18, v19, __ post(result, 32)); + __ stpq(v20, v21, __ post(result, 32)); + __ stpq(v22, v23, __ post(result, 32)); + + __ sub(len, len, 128); + __ cmp(len, (u1)128); + __ br(Assembler::GE, L_loop); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + } + + // Dilithium decompose poly. + // Implements the method + // static int implDilithiumDecomposePoly(int[] coeffs, int constant) {} + // of the sun.security.provider.ML_DSA class + // + // input (int[256]) = c_rarg0 + // lowPart (int[256]) = c_rarg1 + // highPart (int[256]) = c_rarg2 + // twoGamma2 (int) = c_rarg3 + // multiplier (int) = c_rarg4 + address generate_dilithiumDecomposePoly() { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = StubGenStubId::dilithiumDecomposePoly_id; + StubCodeMark mark(this, stub_id); + address start = __ pc(); + __ enter(); + + Label L_loop; + + const Register input = c_rarg0; + const Register lowPart = c_rarg1; + const Register highPart = c_rarg2; + const Register twoGamma2 = c_rarg3; + const Register multiplier = c_rarg4; + + const Register len = r9; + const Register dilithiumConsts = r10; + const Register tmp = r11; + + __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + + // save callee-saved registers + __ stpd(v8, v9, __ pre(sp, -64)); + __ stpd(v10, v11, Address(sp, 16)); + __ stpd(v12, v13, Address(sp, 32)); + __ stpd(v14, v15, Address(sp, 48)); + + + __ mov(tmp, zr); + __ add(tmp, tmp, 1); + __ dup(v25, __ T4S, tmp); // 1 + __ ldr(v30, __ Q, Address(dilithiumConsts, 16)); // q + __ ldr(v31, __ Q, Address(dilithiumConsts, 64)); // addend for mod q reduce + __ dup(v28, __ T4S, twoGamma2); // 2 * gamma2 + __ dup(v29, __ T4S, multiplier); // multiplier for mod 2 * gamma reduce + __ subv(v26, __ T4S, v30, v25); // q - 1 + __ sshr(v27, __ T4S, v28, 1); // gamma2 + + __ mov(len, zr); + __ add(len, len, 1024); + + __ BIND(L_loop); + + __ ld4(v0, v1, v2, v3, __ T4S, __ post(input, 64)); + + // rplus in v0 + // rplus = rplus - ((rplus + 5373807) >> 23) * dilithium_q; + __ addv(v4, __ T4S, v0, v31); + __ addv(v5, __ T4S, v1, v31); + __ addv(v6, __ T4S, v2, v31); + __ addv(v7, __ T4S, v3, v31); + + __ sshr(v4, __ T4S, v4, 23); + __ sshr(v5, __ T4S, v5, 23); + __ sshr(v6, __ T4S, v6, 23); + __ sshr(v7, __ T4S, v7, 23); + + __ mulv(v4, __ T4S, v4, v30); + __ mulv(v5, __ T4S, v5, v30); + __ mulv(v6, __ T4S, v6, v30); + __ mulv(v7, __ T4S, v7, v30); + + __ subv(v0, __ T4S, v0, v4); + __ subv(v1, __ T4S, v1, v5); + __ subv(v2, __ T4S, v2, v6); + __ subv(v3, __ T4S, v3, v7); + + // rplus in v0 + // rplus = rplus + ((rplus >> 31) & dilithium_q); + __ sshr(v4, __ T4S, v0, 31); + __ sshr(v5, __ T4S, v1, 31); + __ sshr(v6, __ T4S, v2, 31); + __ sshr(v7, __ T4S, v3, 31); + + __ andr(v4, __ T16B, v4, v30); + __ andr(v5, __ T16B, v5, v30); + __ andr(v6, __ T16B, v6, v30); + __ andr(v7, __ T16B, v7, v30); + + __ addv(v0, __ T4S, v0, v4); + __ addv(v1, __ T4S, v1, v5); + __ addv(v2, __ T4S, v2, v6); + __ addv(v3, __ T4S, v3, v7); + + // rplus in v0 + // int quotient = (rplus * multiplier) >> 22; + __ mulv(v4, __ T4S, v0, v29); + __ mulv(v5, __ T4S, v1, v29); + __ mulv(v6, __ T4S, v2, v29); + __ mulv(v7, __ T4S, v3, v29); + + __ sshr(v4, __ T4S, v4, 22); + __ sshr(v5, __ T4S, v5, 22); + __ sshr(v6, __ T4S, v6, 22); + __ sshr(v7, __ T4S, v7, 22); + + // quotient in v4 + // int r0 = rplus - quotient * twoGamma2; + __ mulv(v8, __ T4S, v4, v28); + __ mulv(v9, __ T4S, v5, v28); + __ mulv(v10, __ T4S, v6, v28); + __ mulv(v11, __ T4S, v7, v28); + + __ subv(v8, __ T4S, v0, v8); + __ subv(v9, __ T4S, v1, v9); + __ subv(v10, __ T4S, v2, v10); + __ subv(v11, __ T4S, v3, v11); + + // r0 in v8 + // int mask = (twoGamma2 - r0) >> 22; + __ subv(v12, __ T4S, v28, v8); + __ subv(v13, __ T4S, v28, v9); + __ subv(v14, __ T4S, v28, v10); + __ subv(v15, __ T4S, v28, v11); + + __ sshr(v12, __ T4S, v12, 22); + __ sshr(v13, __ T4S, v13, 22); + __ sshr(v14, __ T4S, v14, 22); + __ sshr(v15, __ T4S, v15, 22); + + // mask in v12 + // r0 -= (mask & twoGamma2); + __ andr(v16, __ T16B, v12, v28); + __ andr(v17, __ T16B, v13, v28); + __ andr(v18, __ T16B, v14, v28); + __ andr(v19, __ T16B, v15, v28); + + __ subv(v8, __ T4S, v8, v16); + __ subv(v9, __ T4S, v9, v17); + __ subv(v10, __ T4S, v10, v18); + __ subv(v11, __ T4S, v11, v19); + + // r0 in v8 + // quotient += (mask & 1); + __ andr(v16, __ T16B, v12, v25); + __ andr(v17, __ T16B, v13, v25); + __ andr(v18, __ T16B, v14, v25); + __ andr(v19, __ T16B, v15, v25); + + __ addv(v4, __ T4S, v4, v16); + __ addv(v5, __ T4S, v5, v17); + __ addv(v6, __ T4S, v6, v18); + __ addv(v7, __ T4S, v7, v19); + + // mask = (twoGamma2 / 2 - r0) >> 31; + __ subv(v12, __ T4S, v27, v8); + __ subv(v13, __ T4S, v27, v9); + __ subv(v14, __ T4S, v27, v10); + __ subv(v15, __ T4S, v27, v11); + + __ sshr(v12, __ T4S, v12, 31); + __ sshr(v13, __ T4S, v13, 31); + __ sshr(v14, __ T4S, v14, 31); + __ sshr(v15, __ T4S, v15, 31); + + // r0 -= (mask & twoGamma2); + __ andr(v16, __ T16B, v12, v28); + __ andr(v17, __ T16B, v13, v28); + __ andr(v18, __ T16B, v14, v28); + __ andr(v19, __ T16B, v15, v28); + + __ subv(v8, __ T4S, v8, v16); + __ subv(v9, __ T4S, v9, v17); + __ subv(v10, __ T4S, v10, v18); + __ subv(v11, __ T4S, v11, v19); + + // quotient += (mask & 1); + __ andr(v16, __ T16B, v12, v25); + __ andr(v17, __ T16B, v13, v25); + __ andr(v18, __ T16B, v14, v25); + __ andr(v19, __ T16B, v15, v25); + + __ addv(v4, __ T4S, v4, v16); + __ addv(v5, __ T4S, v5, v17); + __ addv(v6, __ T4S, v6, v18); + __ addv(v7, __ T4S, v7, v19); + + // int r1 = rplus - r0 - (dilithium_q - 1); + __ subv(v16, __ T4S, v0, v8); + __ subv(v17, __ T4S, v1, v9); + __ subv(v18, __ T4S, v2, v10); + __ subv(v19, __ T4S, v3, v11); + + __ subv(v16, __ T4S, v16, v26); + __ subv(v17, __ T4S, v17, v26); + __ subv(v18, __ T4S, v18, v26); + __ subv(v19, __ T4S, v19, v26); + + // r1 in v16 + // r1 = (r1 | (-r1)) >> 31; // 0 if rplus - r0 == (dilithium_q - 1), -1 otherwise + __ negr(v20, __ T4S, v16); + __ negr(v21, __ T4S, v17); + __ negr(v22, __ T4S, v18); + __ negr(v23, __ T4S, v19); + + __ orr(v16, __ T16B, v16, v20); + __ orr(v17, __ T16B, v17, v21); + __ orr(v18, __ T16B, v18, v22); + __ orr(v19, __ T16B, v19, v23); + + __ sshr(v0, __ T4S, v16, 31); + __ sshr(v1, __ T4S, v17, 31); + __ sshr(v2, __ T4S, v18, 31); + __ sshr(v3, __ T4S, v19, 31); + + // r1 in v0 + // r0 += ~r1; + __ notr(v20, __ T16B, v0); + __ notr(v21, __ T16B, v1); + __ notr(v22, __ T16B, v2); + __ notr(v23, __ T16B, v3); + + __ addv(v8, __ T4S, v8, v20); + __ addv(v9, __ T4S, v9, v21); + __ addv(v10, __ T4S, v10, v22); + __ addv(v11, __ T4S, v11, v23); + + // r0 in v8 + // r1 = r1 & quotient; + __ andr(v0, __ T16B, v4, v0); + __ andr(v1, __ T16B, v5, v1); + __ andr(v2, __ T16B, v6, v2); + __ andr(v3, __ T16B, v7, v3); + + // r1 in v0 + // lowPart[m] = r0; + // highPart[m] = r1; + __ st4(v8, v9, v10, v11, __ T4S, __ post(lowPart, 64)); + __ st4(v0, v1, v2, v3, __ T4S, __ post(highPart, 64)); + + + __ sub(len, len, 64); + __ cmp(len, (u1)64); + __ br(Assembler::GE, L_loop); + + // restore callee-saved vector registers + __ ldpd(v14, v15, Address(sp, 48)); + __ ldpd(v12, v13, Address(sp, 32)); + __ ldpd(v10, v11, Address(sp, 16)); + __ ldpd(v8, v9, __ post(sp, 64)); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + } + /** * Arguments: * @@ -9097,6 +10157,14 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_chacha20Block = generate_chacha20Block_qrpar(); } + if (UseDilithiumIntrinsics) { + StubRoutines::_dilithiumAlmostNtt = generate_dilithiumAlmostNtt(); + StubRoutines::_dilithiumAlmostInverseNtt = generate_dilithiumAlmostInverseNtt(); + StubRoutines::_dilithiumNttMult = generate_dilithiumNttMult(); + StubRoutines::_dilithiumMontMulByConstant = generate_dilithiumMontMulByConstant(); + StubRoutines::_dilithiumDecomposePoly = generate_dilithiumDecomposePoly(); + } + if (UseBASE64Intrinsics) { StubRoutines::_base64_encodeBlock = generate_base64_encodeBlock(); StubRoutines::_base64_decodeBlock = generate_base64_decodeBlock(); @@ -9139,6 +10207,7 @@ class StubGenerator: public StubCodeGenerator { } if (UseSHA3Intrinsics) { StubRoutines::_sha3_implCompress = generate_sha3_implCompress(StubGenStubId::sha3_implCompress_id); + StubRoutines::_double_keccak = generate_double_keccak(); StubRoutines::_sha3_implCompressMB = generate_sha3_implCompress(StubGenStubId::sha3_implCompressMB_id); } diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp index 3fa1616bf65..536583ff40c 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp @@ -48,6 +48,15 @@ STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY, DEFINE_ARCH_ENTRY_INIT) bool StubRoutines::aarch64::_completed = false; +ATTRIBUTE_ALIGNED(64) uint32_t StubRoutines::aarch64::_dilithiumConsts[] = +{ + 58728449, 58728449, 58728449, 58728449, // montQInvModR + 8380417, 8380417, 8380417, 8380417, // dilithium_q + 16382, 16382, 16382, 16382, // toMont((dilithium_n)^-1 (mod dilithium_q)) + 2365951, 2365951, 2365951, 2365951, // montRSquareModQ + 5373807, 5373807, 5373807, 5373807 // addend for modular reduce +}; + /** * crc_table[] from jdk/src/share/native/java/util/zip/zlib-1.2.5/crc32.h */ diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp index a5ed87cdca4..857bb2ff10a 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -110,6 +110,7 @@ class aarch64 { } private: + static uint32_t _dilithiumConsts[]; static juint _crc_table[]; static jubyte _adler_table[]; // begin trigonometric tables block. See comments in .cpp file diff --git a/src/hotspot/cpu/aarch64/vmStructs_aarch64.hpp b/src/hotspot/cpu/aarch64/vmStructs_aarch64.hpp index ceb40dce921..bf9c965213c 100644 --- a/src/hotspot/cpu/aarch64/vmStructs_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vmStructs_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,17 +30,17 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \ static_field(VM_Version, _rop_protection, bool) \ static_field(VM_Version, _pac_mask, uintptr_t) -#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) \ declare_toplevel_type(VM_Version) -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) #define DECLARE_INT_CPU_FEATURE_CONSTANT(id, name, bit) GENERATE_VM_INT_CONSTANT_ENTRY(VM_Version::CPU_##id) #define VM_INT_CPU_FEATURE_CONSTANTS CPU_FEATURE_FLAGS(DECLARE_INT_CPU_FEATURE_CONSTANT) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index bca39ae9db2..91930f6bc26 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -417,6 +417,17 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false); } + if (_features & CPU_ASIMD) { + if (FLAG_IS_DEFAULT(UseDilithiumIntrinsics)) { + UseDilithiumIntrinsics = true; + } + } else if (UseDilithiumIntrinsics) { + if (!FLAG_IS_DEFAULT(UseDilithiumIntrinsics)) { + warning("Dilithium intrinsic requires ASIMD instructions"); + } + FLAG_SET_DEFAULT(UseDilithiumIntrinsics, false); + } + if (FLAG_IS_DEFAULT(UseBASE64Intrinsics)) { UseBASE64Intrinsics = true; } diff --git a/src/hotspot/cpu/arm/abstractInterpreter_arm.cpp b/src/hotspot/cpu/arm/abstractInterpreter_arm.cpp index 075db4736f1..978011491a0 100644 --- a/src/hotspot/cpu/arm/abstractInterpreter_arm.cpp +++ b/src/hotspot/cpu/arm/abstractInterpreter_arm.cpp @@ -131,6 +131,15 @@ void AbstractInterpreter::layout_activation(Method* method, intptr_t* locals = interpreter_frame->sender_sp() + max_locals - 1; +#ifdef ASSERT + if (caller->is_interpreted_frame()) { + // Test exact placement on top of caller args + intptr_t* l2 = caller->interpreter_frame_last_sp() + caller_actual_parameters - 1; + assert(l2 <= caller->interpreter_frame_expression_stack(), "bad placement"); + assert(l2 >= locals, "bad placement"); + } +#endif + interpreter_frame->interpreter_frame_set_locals(locals); BasicObjectLock* montop = interpreter_frame->interpreter_frame_monitor_begin(); BasicObjectLock* monbot = montop - moncount; diff --git a/src/hotspot/cpu/arm/frame_arm.inline.hpp b/src/hotspot/cpu/arm/frame_arm.inline.hpp index 801b2f6177c..92a48f22f8c 100644 --- a/src/hotspot/cpu/arm/frame_arm.inline.hpp +++ b/src/hotspot/cpu/arm/frame_arm.inline.hpp @@ -62,7 +62,7 @@ inline void frame::init(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, add if (original_pc != nullptr) { _pc = original_pc; assert(_cb->as_nmethod()->insts_contains_inclusive(_pc), - "original PC must be in the main code section of the the compiled method (or must be immediately following it)"); + "original PC must be in the main code section of the compiled method (or must be immediately following it)"); _deopt_state = is_deoptimized; } else { _deopt_state = not_deoptimized; diff --git a/src/hotspot/cpu/arm/runtime_arm.cpp b/src/hotspot/cpu/arm/runtime_arm.cpp index cf4b398cf1f..ac6e1be0395 100644 --- a/src/hotspot/cpu/arm/runtime_arm.cpp +++ b/src/hotspot/cpu/arm/runtime_arm.cpp @@ -47,11 +47,12 @@ void OptoRuntime::generate_uncommon_trap_blob() { ResourceMark rm; // setup code generation tools + const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id); #ifdef _LP64 - CodeBuffer buffer("uncommon_trap_blob", 2700, 512); + CodeBuffer buffer(name, 2700, 512); #else // Measured 8/7/03 at 660 in 32bit debug build - CodeBuffer buffer("uncommon_trap_blob", 2000, 512); + CodeBuffer buffer(name, 2000, 512); #endif // bypassed when code generation useless MacroAssembler* masm = new MacroAssembler(&buffer); @@ -206,7 +207,8 @@ void OptoRuntime::generate_exception_blob() { // setup code generation tools // Measured 8/7/03 at 256 in 32bit debug build - CodeBuffer buffer("exception_blob", 600, 512); + const char* name = OptoRuntime::stub_name(OptoStubId::exception_id); + CodeBuffer buffer(name, 600, 512); MacroAssembler* masm = new MacroAssembler(&buffer); int framesize_in_words = 2; // FP + LR diff --git a/src/hotspot/cpu/arm/vmStructs_arm.hpp b/src/hotspot/cpu/arm/vmStructs_arm.hpp index 4ce78d517e8..453938a824e 100644 --- a/src/hotspot/cpu/arm/vmStructs_arm.hpp +++ b/src/hotspot/cpu/arm/vmStructs_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, 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 @@ -29,7 +29,7 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ \ /******************************/ \ /* JavaCallWrapper */ \ @@ -39,10 +39,10 @@ /******************************/ \ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) -#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) #endif // CPU_ARM_VMSTRUCTS_ARM_HPP diff --git a/src/hotspot/cpu/ppc/abstractInterpreter_ppc.cpp b/src/hotspot/cpu/ppc/abstractInterpreter_ppc.cpp index cc094ad4f99..beadce33637 100644 --- a/src/hotspot/cpu/ppc/abstractInterpreter_ppc.cpp +++ b/src/hotspot/cpu/ppc/abstractInterpreter_ppc.cpp @@ -128,6 +128,15 @@ void AbstractInterpreter::layout_activation(Method* method, caller->interpreter_frame_esp() + caller_actual_parameters : caller->sp() + method->max_locals() - 1 + (frame::java_abi_size / Interpreter::stackElementSize); +#ifdef ASSERT + if (caller->is_interpreted_frame()) { + assert(locals_base <= caller->interpreter_frame_expression_stack(), "bad placement"); + const int caller_abi_bytesize = (is_bottom_frame ? frame::top_ijava_frame_abi_size : frame::parent_ijava_frame_abi_size); + intptr_t* l2 = caller->sp() + method->max_locals() - 1 + (caller_abi_bytesize / Interpreter::stackElementSize); + assert(locals_base >= l2, "bad placement"); + } +#endif + intptr_t* monitor_base = caller->sp() - frame::ijava_state_size / Interpreter::stackElementSize; intptr_t* monitor = monitor_base - (moncount * frame::interpreter_frame_monitor_size()); intptr_t* esp_base = monitor - 1; diff --git a/src/hotspot/cpu/ppc/compiledIC_ppc.cpp b/src/hotspot/cpu/ppc/compiledIC_ppc.cpp index c8cb68e3eb4..8a29da66436 100644 --- a/src/hotspot/cpu/ppc/compiledIC_ppc.cpp +++ b/src/hotspot/cpu/ppc/compiledIC_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2012, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,9 +29,6 @@ #include "memory/resourceArea.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/safepoint.hpp" -#ifdef COMPILER2 -#include "opto/matcher.hpp" -#endif // ---------------------------------------------------------------------------- @@ -78,7 +75,6 @@ const int IC_pos_in_java_to_interp_stub = 8; #define __ masm-> address CompiledDirectCall::emit_to_interp_stub(MacroAssembler *masm, address mark/* = nullptr*/) { -#ifdef COMPILER2 if (mark == nullptr) { // Get the mark within main instrs section which is set to the address of the call. mark = __ inst_mark(); @@ -108,7 +104,7 @@ address CompiledDirectCall::emit_to_interp_stub(MacroAssembler *masm, address ma // - call __ calculate_address_from_global_toc(reg_scratch, __ method_toc()); AddressLiteral ic = __ allocate_metadata_address((Metadata *)nullptr); - bool success = __ load_const_from_method_toc(as_Register(Matcher::inline_cache_reg_encode()), + bool success = __ load_const_from_method_toc(R19_inline_cache_reg, ic, reg_scratch, /*fixed_size*/ true); if (!success) { return nullptr; // CodeCache is full @@ -134,13 +130,9 @@ address CompiledDirectCall::emit_to_interp_stub(MacroAssembler *masm, address ma assert(!is_NativeCallTrampolineStub_at(__ addr_at(stub_start_offset)), "must not confuse java_to_interp with trampoline stubs"); - // End the stub. + // End the stub. __ end_a_stub(); return stub; -#else - ShouldNotReachHere(); - return nullptr; -#endif } #undef __ diff --git a/src/hotspot/cpu/ppc/frame_ppc.cpp b/src/hotspot/cpu/ppc/frame_ppc.cpp index 38c26e5e497..6b6a792117d 100644 --- a/src/hotspot/cpu/ppc/frame_ppc.cpp +++ b/src/hotspot/cpu/ppc/frame_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2024 SAP SE. All rights reserved. + * Copyright (c) 2012, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -195,6 +195,15 @@ bool frame::safe_for_sender(JavaThread *thread) { return false; } + if (sender_pc() == nullptr) { + // Likely the return pc was not yet stored to stack. We rather discard this + // sample also because we would hit an assertion in frame::setup(). We can + // find any other random value if the return pc was not yet stored to + // stack. We rely on consistency checks to handle this (see + // e.g. find_initial_Java_frame()) + return false; + } + return true; } diff --git a/src/hotspot/cpu/ppc/runtime_ppc.cpp b/src/hotspot/cpu/ppc/runtime_ppc.cpp index c5990e01e0d..6ab29ac98b2 100644 --- a/src/hotspot/cpu/ppc/runtime_ppc.cpp +++ b/src/hotspot/cpu/ppc/runtime_ppc.cpp @@ -71,7 +71,8 @@ void OptoRuntime::generate_exception_blob() { // Allocate space for the code. ResourceMark rm; // Setup code generation tools. - CodeBuffer buffer("exception_blob", 2048, 1024); + const char* name = OptoRuntime::stub_name(OptoStubId::exception_id); + CodeBuffer buffer(name, 2048, 1024); InterpreterMacroAssembler* masm = new InterpreterMacroAssembler(&buffer); address start = __ pc(); diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp index f7e1410d10f..4bdd8667c62 100644 --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp @@ -3104,7 +3104,8 @@ void OptoRuntime::generate_uncommon_trap_blob() { // Allocate space for the code. ResourceMark rm; // Setup code generation tools. - CodeBuffer buffer("uncommon_trap_blob", 2048, 1024); + const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id); + CodeBuffer buffer(name, 2048, 1024); InterpreterMacroAssembler* masm = new InterpreterMacroAssembler(&buffer); address start = __ pc(); diff --git a/src/hotspot/cpu/ppc/vmStructs_ppc.hpp b/src/hotspot/cpu/ppc/vmStructs_ppc.hpp index c1bdc1b1eb5..efe7fb9ad7b 100644 --- a/src/hotspot/cpu/ppc/vmStructs_ppc.hpp +++ b/src/hotspot/cpu/ppc/vmStructs_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,12 +30,12 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) -#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) #endif // CPU_PPC_VMSTRUCTS_PPC_HPP diff --git a/src/hotspot/cpu/riscv/abstractInterpreter_riscv.cpp b/src/hotspot/cpu/riscv/abstractInterpreter_riscv.cpp index 843a58e28d7..00a6877684a 100644 --- a/src/hotspot/cpu/riscv/abstractInterpreter_riscv.cpp +++ b/src/hotspot/cpu/riscv/abstractInterpreter_riscv.cpp @@ -141,7 +141,8 @@ void AbstractInterpreter::layout_activation(Method* method, #ifdef ASSERT if (caller->is_interpreted_frame()) { - assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement"); + assert(locals <= caller->interpreter_frame_expression_stack(), "bad placement"); + assert(locals >= interpreter_frame->sender_sp() + max_locals - 1, "bad placement"); } #endif diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index e52cf7565be..dc33691586b 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -1382,15 +1382,183 @@ void C2_MacroAssembler::string_indexof_linearscan(Register haystack, Register ne bind(DONE); } +// Compare longwords +void C2_MacroAssembler::string_compare_long_same_encoding(Register result, Register str1, Register str2, + const bool isLL, Register cnt1, Register cnt2, + Register tmp1, Register tmp2, Register tmp3, + const int STUB_THRESHOLD, Label *STUB, Label *SHORT_STRING, Label *DONE) { + Label TAIL_CHECK, TAIL, NEXT_WORD, DIFFERENCE; + + const int base_offset = isLL ? arrayOopDesc::base_offset_in_bytes(T_BYTE) + : arrayOopDesc::base_offset_in_bytes(T_CHAR); + assert((base_offset % (UseCompactObjectHeaders ? 4 : + (UseCompressedClassPointers ? 8 : 4))) == 0, "Must be"); + + const int minCharsInWord = isLL ? wordSize : wordSize / 2; + + // load first parts of strings and finish initialization while loading + beq(str1, str2, *DONE); + // Alignment + if (AvoidUnalignedAccesses && (base_offset % 8) != 0) { + lwu(tmp1, Address(str1)); + lwu(tmp2, Address(str2)); + bne(tmp1, tmp2, DIFFERENCE); + addi(str1, str1, 4); + addi(str2, str2, 4); + subi(cnt2, cnt2, minCharsInWord / 2); + + // A very short string + mv(t0, minCharsInWord); + ble(cnt2, t0, *SHORT_STRING); + } +#ifdef ASSERT + if (AvoidUnalignedAccesses) { + Label align_ok; + orr(t0, str1, str2); + andi(t0, t0, 0x7); + beqz(t0, align_ok); + stop("bad alignment"); + bind(align_ok); + } +#endif + // load 8 bytes once to compare + ld(tmp1, Address(str1)); + ld(tmp2, Address(str2)); + mv(t0, STUB_THRESHOLD); + bge(cnt2, t0, *STUB); + subi(cnt2, cnt2, minCharsInWord); + beqz(cnt2, TAIL_CHECK); + // convert cnt2 from characters to bytes + if (!isLL) { + slli(cnt2, cnt2, 1); + } + add(str2, str2, cnt2); + add(str1, str1, cnt2); + sub(cnt2, zr, cnt2); + addi(cnt2, cnt2, 8); + bne(tmp1, tmp2, DIFFERENCE); + bgez(cnt2, TAIL); + + // main loop + bind(NEXT_WORD); + // 8-byte aligned loads when AvoidUnalignedAccesses is enabled + add(t0, str1, cnt2); + ld(tmp1, Address(t0)); + add(t0, str2, cnt2); + ld(tmp2, Address(t0)); + addi(cnt2, cnt2, 8); + bne(tmp1, tmp2, DIFFERENCE); + bltz(cnt2, NEXT_WORD); + + bind(TAIL); + load_long_misaligned(tmp1, Address(str1), tmp3, isLL ? 1 : 2); + load_long_misaligned(tmp2, Address(str2), tmp3, isLL ? 1 : 2); + + bind(TAIL_CHECK); + beq(tmp1, tmp2, *DONE); + + // Find the first different characters in the longwords and + // compute their difference. + bind(DIFFERENCE); + xorr(tmp3, tmp1, tmp2); + // count bits of trailing zero chars + ctzc_bits(result, tmp3, isLL); + srl(tmp1, tmp1, result); + srl(tmp2, tmp2, result); + if (isLL) { + zext(tmp1, tmp1, 8); + zext(tmp2, tmp2, 8); + } else { + zext(tmp1, tmp1, 16); + zext(tmp2, tmp2, 16); + } + sub(result, tmp1, tmp2); + + j(*DONE); +} + +// Compare longwords +void C2_MacroAssembler::string_compare_long_different_encoding(Register result, Register str1, Register str2, + bool isLU, Register cnt1, Register cnt2, + Register tmp1, Register tmp2, Register tmp3, + const int STUB_THRESHOLD, Label *STUB, Label *DONE) { + Label TAIL, NEXT_WORD, DIFFERENCE; + + const int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); + assert((base_offset % (UseCompactObjectHeaders ? 4 : + (UseCompressedClassPointers ? 8 : 4))) == 0, "Must be"); + + Register strL = isLU ? str1 : str2; + Register strU = isLU ? str2 : str1; + Register tmpL = tmp1, tmpU = tmp2; + + // load first parts of strings and finish initialization while loading + mv(t0, STUB_THRESHOLD); + bge(cnt2, t0, *STUB); + lwu(tmpL, Address(strL)); + load_long_misaligned(tmpU, Address(strU), tmp3, (base_offset % 8) != 0 ? 4 : 8); + subi(cnt2, cnt2, 4); + add(strL, strL, cnt2); + sub(cnt1, zr, cnt2); + slli(cnt2, cnt2, 1); + add(strU, strU, cnt2); + inflate_lo32(tmp3, tmpL); + mv(tmpL, tmp3); + sub(cnt2, zr, cnt2); + addi(cnt1, cnt1, 4); + addi(cnt2, cnt2, 8); + bne(tmpL, tmpU, DIFFERENCE); + bgez(cnt2, TAIL); + + // main loop + bind(NEXT_WORD); + add(t0, strL, cnt1); + lwu(tmpL, Address(t0)); + add(t0, strU, cnt2); + load_long_misaligned(tmpU, Address(t0), tmp3, (base_offset % 8) != 0 ? 4 : 8); + addi(cnt1, cnt1, 4); + inflate_lo32(tmp3, tmpL); + mv(tmpL, tmp3); + addi(cnt2, cnt2, 8); + bne(tmpL, tmpU, DIFFERENCE); + bltz(cnt2, NEXT_WORD); + + bind(TAIL); + load_int_misaligned(tmpL, Address(strL), tmp3, false); + load_long_misaligned(tmpU, Address(strU), tmp3, 2); + inflate_lo32(tmp3, tmpL); + mv(tmpL, tmp3); + + beq(tmpL, tmpU, *DONE); + + // Find the first different characters in the longwords and + // compute their difference. + bind(DIFFERENCE); + xorr(tmp3, tmpL, tmpU); + // count bits of trailing zero chars + ctzc_bits(result, tmp3); + srl(tmpL, tmpL, result); + srl(tmpU, tmpU, result); + zext(tmpL, tmpL, 16); + zext(tmpU, tmpU, 16); + if (isLU) { + sub(result, tmpL, tmpU); + } else { + sub(result, tmpU, tmpL); + } + + j(*DONE); +} + // Compare strings. void C2_MacroAssembler::string_compare(Register str1, Register str2, Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2, Register tmp3, int ae) { - Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB, - DIFFERENCE, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT, - SHORT_LOOP_START, TAIL_CHECK, L; + Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, STUB, + SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT, + SHORT_LOOP_START, L; const int STUB_THRESHOLD = 64 + 8; bool isLL = ae == StrIntrinsicNode::LL; @@ -1409,14 +1577,6 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2, load_chr_insn str1_load_chr = str1_isL ? (load_chr_insn)&MacroAssembler::lbu : (load_chr_insn)&MacroAssembler::lhu; load_chr_insn str2_load_chr = str2_isL ? (load_chr_insn)&MacroAssembler::lbu : (load_chr_insn)&MacroAssembler::lhu; - int base_offset1 = arrayOopDesc::base_offset_in_bytes(T_BYTE); - int base_offset2 = arrayOopDesc::base_offset_in_bytes(T_CHAR); - - assert((base_offset1 % (UseCompactObjectHeaders ? 4 : - (UseCompressedClassPointers ? 8 : 4))) == 0, "Must be"); - assert((base_offset2 % (UseCompactObjectHeaders ? 4 : - (UseCompressedClassPointers ? 8 : 4))) == 0, "Must be"); - BLOCK_COMMENT("string_compare {"); // Bizarrely, the counts are passed in bytes, regardless of whether they @@ -1434,154 +1594,23 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2, mv(cnt2, cnt1); bind(L); - // Load 4 bytes once to compare for alignment before main loop. Note that this - // is only possible for LL/UU case. We need to resort to load_long_misaligned - // for both LU and UL cases. - if (str1_isL == str2_isL) { // LL or UU - beq(str1, str2, DONE); - int base_offset = isLL ? base_offset1 : base_offset2; - if (AvoidUnalignedAccesses && (base_offset % 8) != 0) { - mv(t0, minCharsInWord / 2); - ble(cnt2, t0, SHORT_STRING); - lwu(tmp1, Address(str1)); - lwu(tmp2, Address(str2)); - bne(tmp1, tmp2, DIFFERENCE); - addi(str1, str1, 4); - addi(str2, str2, 4); - subi(cnt2, cnt2, minCharsInWord / 2); - } - } - // A very short string mv(t0, minCharsInWord); ble(cnt2, t0, SHORT_STRING); // Compare longwords - // load first parts of strings and finish initialization while loading { if (str1_isL == str2_isL) { // LL or UU -#ifdef ASSERT - if (AvoidUnalignedAccesses) { - Label align_ok; - orr(t0, str1, str2); - andi(t0, t0, 0x7); - beqz(t0, align_ok); - stop("bad alignment"); - bind(align_ok); - } -#endif - // load 8 bytes once to compare - ld(tmp1, Address(str1)); - ld(tmp2, Address(str2)); - mv(t0, STUB_THRESHOLD); - bge(cnt2, t0, STUB); - subi(cnt2, cnt2, minCharsInWord); - beqz(cnt2, TAIL_CHECK); - // convert cnt2 from characters to bytes - if (!str1_isL) { - slli(cnt2, cnt2, 1); - } - add(str2, str2, cnt2); - add(str1, str1, cnt2); - sub(cnt2, zr, cnt2); - } else if (isLU) { // LU case - mv(t0, STUB_THRESHOLD); - bge(cnt2, t0, STUB); - lwu(tmp1, Address(str1)); - load_long_misaligned(tmp2, Address(str2), tmp3, (base_offset2 % 8) != 0 ? 4 : 8); - subi(cnt2, cnt2, 4); - add(str1, str1, cnt2); - sub(cnt1, zr, cnt2); - slli(cnt2, cnt2, 1); - add(str2, str2, cnt2); - inflate_lo32(tmp3, tmp1); - mv(tmp1, tmp3); - sub(cnt2, zr, cnt2); - addi(cnt1, cnt1, 4); - } else { // UL case - mv(t0, STUB_THRESHOLD); - bge(cnt2, t0, STUB); - load_long_misaligned(tmp1, Address(str1), tmp3, (base_offset2 % 8) != 0 ? 4 : 8); - lwu(tmp2, Address(str2)); - subi(cnt2, cnt2, 4); - slli(t0, cnt2, 1); - sub(cnt1, zr, t0); - add(str1, str1, t0); - add(str2, str2, cnt2); - inflate_lo32(tmp3, tmp2); - mv(tmp2, tmp3); - sub(cnt2, zr, cnt2); - addi(cnt1, cnt1, 8); - } - addi(cnt2, cnt2, isUL ? 4 : 8); - bne(tmp1, tmp2, DIFFERENCE); - bgez(cnt2, TAIL); - - // main loop - bind(NEXT_WORD); - if (str1_isL == str2_isL) { // LL or UU - // 8-byte aligned loads when AvoidUnalignedAccesses is enabled - add(t0, str1, cnt2); - ld(tmp1, Address(t0)); - add(t0, str2, cnt2); - ld(tmp2, Address(t0)); - addi(cnt2, cnt2, 8); - } else if (isLU) { // LU case - add(t0, str1, cnt1); - lwu(tmp1, Address(t0)); - add(t0, str2, cnt2); - load_long_misaligned(tmp2, Address(t0), tmp3, (base_offset2 % 8) != 0 ? 4 : 8); - addi(cnt1, cnt1, 4); - inflate_lo32(tmp3, tmp1); - mv(tmp1, tmp3); - addi(cnt2, cnt2, 8); - } else { // UL case - add(t0, str2, cnt2); - lwu(tmp2, Address(t0)); - add(t0, str1, cnt1); - load_long_misaligned(tmp1, Address(t0), tmp3, (base_offset2 % 8) != 0 ? 4 : 8); - inflate_lo32(tmp3, tmp2); - mv(tmp2, tmp3); - addi(cnt1, cnt1, 8); - addi(cnt2, cnt2, 4); + string_compare_long_same_encoding(result, + str1, str2, isLL, + cnt1, cnt2, tmp1, tmp2, tmp3, + STUB_THRESHOLD, &STUB, &SHORT_STRING, &DONE); + } else { // LU or UL + string_compare_long_different_encoding(result, + str1, str2, isLU, + cnt1, cnt2, tmp1, tmp2, tmp3, + STUB_THRESHOLD, &STUB, &DONE); } - bne(tmp1, tmp2, DIFFERENCE); - bltz(cnt2, NEXT_WORD); - bind(TAIL); - if (str1_isL == str2_isL) { // LL or UU - load_long_misaligned(tmp1, Address(str1), tmp3, isLL ? 1 : 2); - load_long_misaligned(tmp2, Address(str2), tmp3, isLL ? 1 : 2); - } else if (isLU) { // LU case - load_int_misaligned(tmp1, Address(str1), tmp3, false); - load_long_misaligned(tmp2, Address(str2), tmp3, 2); - inflate_lo32(tmp3, tmp1); - mv(tmp1, tmp3); - } else { // UL case - load_int_misaligned(tmp2, Address(str2), tmp3, false); - load_long_misaligned(tmp1, Address(str1), tmp3, 2); - inflate_lo32(tmp3, tmp2); - mv(tmp2, tmp3); - } - bind(TAIL_CHECK); - beq(tmp1, tmp2, DONE); - - // Find the first different characters in the longwords and - // compute their difference. - bind(DIFFERENCE); - xorr(tmp3, tmp1, tmp2); - // count bits of trailing zero chars - ctzc_bits(result, tmp3, isLL); - srl(tmp1, tmp1, result); - srl(tmp2, tmp2, result); - if (isLL) { - zext(tmp1, tmp1, 8); - zext(tmp2, tmp2, 8); - } else { - zext(tmp1, tmp1, 16); - zext(tmp2, tmp2, 16); - } - sub(result, tmp1, tmp2); - j(DONE); } bind(STUB); @@ -2135,9 +2164,6 @@ void C2_MacroAssembler::enc_cmove(int cmpFlag, Register op1, Register op2, Regis // Set dst to NaN if any NaN input. void C2_MacroAssembler::minmax_fp(FloatRegister dst, FloatRegister src1, FloatRegister src2, bool is_double, bool is_min) { - assert_different_registers(dst, src1); - assert_different_registers(dst, src2); - Label Done, Compare; is_double ? fclass_d(t0, src1) @@ -2287,7 +2313,7 @@ void C2_MacroAssembler::float16_to_float(FloatRegister dst, Register src, Regist mv(t0, 0x7c00); andr(tmp, src, t0); // jump to stub processing NaN and Inf cases. - beq(t0, tmp, stub->entry()); + beq(t0, tmp, stub->entry(), true); // non-NaN or non-Inf cases, just use built-in instructions. fmv_h_x(dst, src); @@ -2330,7 +2356,7 @@ void C2_MacroAssembler::float_to_float16(Register dst, FloatRegister src, FloatR // replace fclass with feq as performance optimization. feq_s(t0, src, src); // jump to stub processing NaN cases. - beqz(t0, stub->entry()); + beqz(t0, stub->entry(), true); // non-NaN cases, just use built-in instructions. fcvt_h_s(ftmp, src); @@ -2391,7 +2417,7 @@ void C2_MacroAssembler::float16_to_float_v(VectorRegister dst, VectorRegister sr vfwcvt_f_f_v(dst, src); // jump to stub processing NaN and Inf cases if there is any of them in the vector-wide. - bnez(t0, stub->entry()); + bnez(t0, stub->entry(), true); bind(stub->continuation()); } @@ -2445,7 +2471,7 @@ void C2_MacroAssembler::float_to_float16_v(VectorRegister dst, VectorRegister sr vfncvt_f_f_w(dst, src); // jump to stub processing NaN cases. - bnez(t0, stub->entry()); + bnez(t0, stub->entry(), true); bind(stub->continuation()); } @@ -2639,7 +2665,7 @@ void C2_MacroAssembler::string_compare_v(Register str1, Register str2, Register int minCharsInWord = encLL ? wordSize : wordSize / 2; - BLOCK_COMMENT("string_compare {"); + BLOCK_COMMENT("string_compare_v {"); // for Latin strings, 1 byte for 1 character // for UTF16 strings, 2 bytes for 1 character @@ -2699,6 +2725,8 @@ void C2_MacroAssembler::string_compare_v(Register str1, Register str2, Register sub(result, tmp1, tmp2); bind(DONE); + + BLOCK_COMMENT("} string_compare_v"); } void C2_MacroAssembler::byte_array_inflate_v(Register src, Register dst, Register len, Register tmp) { diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp index c79c360d2eb..72f3c1460f3 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp @@ -39,6 +39,15 @@ VectorRegister vrs, bool is_latin, Label& DONE, Assembler::LMUL lmul); + void string_compare_long_same_encoding(Register result, Register str1, Register str2, + const bool isLL, Register cnt1, Register cnt2, + Register tmp1, Register tmp2, Register tmp3, + const int STUB_THRESHOLD, Label *STUB, Label *SHORT_STRING, Label *DONE); + void string_compare_long_different_encoding(Register result, Register str1, Register str2, + bool isLU, Register cnt1, Register cnt2, + Register tmp1, Register tmp2, Register tmp3, + const int STUB_THRESHOLD, Label *STUB, Label *DONE); + public: // Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file. void fast_lock(Register object, Register box, diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 4276595ffcc..d3daef7664d 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -2300,7 +2300,7 @@ static int patch_offset_in_jal(address branch, int64_t offset) { static int patch_offset_in_conditional_branch(address branch, int64_t offset) { assert(Assembler::is_simm13(offset) && ((offset % 2) == 0), - "offset is too large to be patched in one beq/bge/bgeu/blt/bltu/bne instruction!\n"); + "offset (%ld) is too large to be patched in one beq/bge/bgeu/blt/bltu/bne instruction!\n", offset); Assembler::patch(branch, 31, 31, (offset >> 12) & 0x1); // offset[12] ==> branch[31] Assembler::patch(branch, 30, 25, (offset >> 5) & 0x3f); // offset[10:5] ==> branch[30:25] Assembler::patch(branch, 7, 7, (offset >> 11) & 0x1); // offset[11] ==> branch[7] @@ -2892,7 +2892,6 @@ void MacroAssembler::revb(Register Rd, Register Rs, Register tmp1, Register tmp2 slli(tmp1, tmp1, 8); } srli(Rd, Rs, 56); - zext(Rd, Rd, 8); orr(Rd, tmp1, Rd); } diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index b8660afb5fd..00ebeabe3e2 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -4097,21 +4097,19 @@ pipe_class fp_div_d(fRegD dst, fRegD src1, fRegD src2) FPU : S5; %} -pipe_class fp_sqrt_s(fRegF dst, fRegF src1, fRegF src2) +pipe_class fp_sqrt_s(fRegF dst, fRegF src) %{ single_instruction; - src1 : S1(read); - src2 : S2(read); + src : S1(read); dst : S5(write); DECODE : ID; FPU : S5; %} -pipe_class fp_sqrt_d(fRegD dst, fRegD src1, fRegD src2) +pipe_class fp_sqrt_d(fRegD dst, fRegD src) %{ single_instruction; - src1 : S1(read); - src2 : S2(read); + src : S1(read); dst : S5(write); DECODE : ID; FPU : S5; @@ -7287,7 +7285,7 @@ instruct nmaddD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{ // Math.max(FF)F instruct maxF_reg_reg(fRegF dst, fRegF src1, fRegF src2, rFlagsReg cr) %{ match(Set dst (MaxF src1 src2)); - effect(TEMP_DEF dst, KILL cr); + effect(KILL cr); format %{ "maxF $dst, $src1, $src2" %} @@ -7303,7 +7301,7 @@ instruct maxF_reg_reg(fRegF dst, fRegF src1, fRegF src2, rFlagsReg cr) %{ // Math.min(FF)F instruct minF_reg_reg(fRegF dst, fRegF src1, fRegF src2, rFlagsReg cr) %{ match(Set dst (MinF src1 src2)); - effect(TEMP_DEF dst, KILL cr); + effect(KILL cr); format %{ "minF $dst, $src1, $src2" %} @@ -7319,7 +7317,7 @@ instruct minF_reg_reg(fRegF dst, fRegF src1, fRegF src2, rFlagsReg cr) %{ // Math.max(DD)D instruct maxD_reg_reg(fRegD dst, fRegD src1, fRegD src2, rFlagsReg cr) %{ match(Set dst (MaxD src1 src2)); - effect(TEMP_DEF dst, KILL cr); + effect(KILL cr); format %{ "maxD $dst, $src1, $src2" %} @@ -7335,7 +7333,7 @@ instruct maxD_reg_reg(fRegD dst, fRegD src1, fRegD src2, rFlagsReg cr) %{ // Math.min(DD)D instruct minD_reg_reg(fRegD dst, fRegD src1, fRegD src2, rFlagsReg cr) %{ match(Set dst (MinD src1 src2)); - effect(TEMP_DEF dst, KILL cr); + effect(KILL cr); format %{ "minD $dst, $src1, $src2" %} diff --git a/src/hotspot/cpu/riscv/runtime_riscv.cpp b/src/hotspot/cpu/riscv/runtime_riscv.cpp index a0879b68053..0a838896a02 100644 --- a/src/hotspot/cpu/riscv/runtime_riscv.cpp +++ b/src/hotspot/cpu/riscv/runtime_riscv.cpp @@ -61,7 +61,8 @@ void OptoRuntime::generate_uncommon_trap_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools - CodeBuffer buffer("uncommon_trap_blob", 2048, 1024); + const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id); + CodeBuffer buffer(name, 2048, 1024); MacroAssembler* masm = new MacroAssembler(&buffer); assert_cond(masm != nullptr); @@ -279,7 +280,8 @@ void OptoRuntime::generate_exception_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools - CodeBuffer buffer("exception_blob", 2048, 1024); + const char* name = OptoRuntime::stub_name(OptoStubId::exception_id); + CodeBuffer buffer(name, 2048, 1024); MacroAssembler* masm = new MacroAssembler(&buffer); assert_cond(masm != nullptr); diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index 01ed7fcac9f..249b871bd00 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -2431,23 +2431,6 @@ class StubGenerator: public StubCodeGenerator { return start; } - // code for comparing 16 bytes of strings with same encoding - void compare_string_16_bytes_same(Label &DIFF1, Label &DIFF2) { - const Register result = x10, str1 = x11, cnt1 = x12, str2 = x13, tmp1 = x28, tmp2 = x29, tmp4 = x7, tmp5 = x31; - __ ld(tmp5, Address(str1)); - __ addi(str1, str1, 8); - __ xorr(tmp4, tmp1, tmp2); - __ ld(cnt1, Address(str2)); - __ addi(str2, str2, 8); - __ bnez(tmp4, DIFF1); - __ ld(tmp1, Address(str1)); - __ addi(str1, str1, 8); - __ xorr(tmp4, tmp5, cnt1); - __ ld(tmp2, Address(str2)); - __ addi(str2, str2, 8); - __ bnez(tmp4, DIFF2); - } - // code for comparing 8 characters of strings with Latin1 and Utf16 encoding void compare_string_8_x_LU(Register tmpL, Register tmpU, Register strL, Register strU, Label& DIFF) { @@ -2702,7 +2685,20 @@ class StubGenerator: public StubCodeGenerator { __ push_reg(spilled_regs, sp); __ bltz(cnt2, TAIL); __ bind(SMALL_LOOP); - compare_string_16_bytes_same(DIFF, DIFF2); + // compare 16 bytes of strings with same encoding + __ ld(tmp5, Address(str1)); + __ addi(str1, str1, 8); + __ xorr(tmp4, tmp1, tmp2); + __ ld(cnt1, Address(str2)); + __ addi(str2, str2, 8); + __ bnez(tmp4, DIFF); + __ ld(tmp1, Address(str1)); + __ addi(str1, str1, 8); + __ xorr(tmp4, tmp5, cnt1); + __ ld(tmp2, Address(str2)); + __ addi(str2, str2, 8); + __ bnez(tmp4, DIFF2); + __ subi(cnt2, cnt2, isLL ? 16 : 8); __ bgez(cnt2, SMALL_LOOP); __ bind(TAIL); diff --git a/src/hotspot/cpu/riscv/vmStructs_riscv.hpp b/src/hotspot/cpu/riscv/vmStructs_riscv.hpp index 6c89133de02..ba250f77268 100644 --- a/src/hotspot/cpu/riscv/vmStructs_riscv.hpp +++ b/src/hotspot/cpu/riscv/vmStructs_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,13 +30,13 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) -#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) #endif // CPU_RISCV_VMSTRUCTS_RISCV_HPP diff --git a/src/hotspot/cpu/s390/abstractInterpreter_s390.cpp b/src/hotspot/cpu/s390/abstractInterpreter_s390.cpp index 37aa9d9a0e8..e815542a51e 100644 --- a/src/hotspot/cpu/s390/abstractInterpreter_s390.cpp +++ b/src/hotspot/cpu/s390/abstractInterpreter_s390.cpp @@ -182,6 +182,13 @@ void AbstractInterpreter::layout_activation(Method* method, intptr_t* sender_sp; if (caller->is_interpreted_frame()) { sender_sp = caller->interpreter_frame_top_frame_sp(); +#ifdef ASSERT + assert(locals_base <= caller->interpreter_frame_expression_stack(), "bad placement"); + // Test caller-aligned placement vs callee-aligned + intptr_t* l2 = (caller->sp() + method->max_locals() - 1 + + frame::z_parent_ijava_frame_abi_size / Interpreter::stackElementSize); + assert(locals_base >= l2, "bad placement"); +#endif } else if (caller->is_compiled_frame()) { sender_sp = caller->fp() - caller->cb()->frame_size(); // The bottom frame's sender_sp is its caller's unextended_sp. diff --git a/src/hotspot/cpu/s390/runtime_s390.cpp b/src/hotspot/cpu/s390/runtime_s390.cpp index dfaf73b9a7c..a0714619d87 100644 --- a/src/hotspot/cpu/s390/runtime_s390.cpp +++ b/src/hotspot/cpu/s390/runtime_s390.cpp @@ -70,7 +70,8 @@ void OptoRuntime::generate_exception_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools - CodeBuffer buffer("exception_blob", 2048, 1024); + const char* name = OptoRuntime::stub_name(OptoStubId::exception_id); + CodeBuffer buffer(name, 2048, 1024); MacroAssembler* masm = new MacroAssembler(&buffer); Register handle_exception = Z_ARG5; diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp index 9716a5d71b3..69a9b22778d 100644 --- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp +++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp @@ -2766,7 +2766,8 @@ void OptoRuntime::generate_uncommon_trap_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools - CodeBuffer buffer("uncommon_trap_blob", 2048, 1024); + const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id); + CodeBuffer buffer(name, 2048, 1024); InterpreterMacroAssembler* masm = new InterpreterMacroAssembler(&buffer); Register unroll_block_reg = Z_tmp_1; diff --git a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp index c40be5edec7..06ff4b363f5 100644 --- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp @@ -2006,8 +2006,20 @@ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(Abstract return __ addr_at(entry_off); } +address TemplateInterpreterGenerator::generate_currentThread() { + uint64_t entry_off = __ offset(); + + __ z_lg(Z_RET, Address(Z_thread, JavaThread::threadObj_offset())); + __ resolve_oop_handle(Z_RET); + + // Restore caller sp for c2i case. + __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started. + __ z_br(Z_R14); + + return __ addr_at(entry_off); +} + // Not supported -address TemplateInterpreterGenerator::generate_currentThread() { return nullptr; } address TemplateInterpreterGenerator::generate_Float_intBitsToFloat_entry() { return nullptr; } address TemplateInterpreterGenerator::generate_Float_floatToRawIntBits_entry() { return nullptr; } address TemplateInterpreterGenerator::generate_Double_longBitsToDouble_entry() { return nullptr; } diff --git a/src/hotspot/cpu/s390/vmStructs_s390.hpp b/src/hotspot/cpu/s390/vmStructs_s390.hpp index 1f65002977a..100fc97560e 100644 --- a/src/hotspot/cpu/s390/vmStructs_s390.hpp +++ b/src/hotspot/cpu/s390/vmStructs_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,12 +30,12 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) -#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) #endif // CPU_S390_VMSTRUCTS_S390_HPP diff --git a/src/hotspot/cpu/x86/abstractInterpreter_x86.cpp b/src/hotspot/cpu/x86/abstractInterpreter_x86.cpp index 68ac5b6ca9a..6680b8c4c03 100644 --- a/src/hotspot/cpu/x86/abstractInterpreter_x86.cpp +++ b/src/hotspot/cpu/x86/abstractInterpreter_x86.cpp @@ -87,7 +87,10 @@ void AbstractInterpreter::layout_activation(Method* method, #ifdef ASSERT if (caller->is_interpreted_frame()) { - assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement"); + // Test exact placement on top of caller args + intptr_t* l2 = caller->interpreter_frame_last_sp() + caller_actual_parameters - 1; + assert(l2 <= caller->interpreter_frame_expression_stack(), "bad placement"); + assert(l2 >= locals, "bad placement"); } #endif diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 90cdce25fc6..b58b849f727 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -6256,15 +6256,21 @@ void C2_MacroAssembler::vector_count_leading_zeros_int_avx(XMMRegister dst, XMMR // Since IEEE 754 floating point format represents mantissa in 1.0 format // hence biased exponent can be used to compute leading zero count as per // following formula:- - // LZCNT = 32 - (biased_exp - 127) + // LZCNT = 31 - (biased_exp - 127) // Special handling has been introduced for Zero, Max_Int and -ve source values. // Broadcast 0xFF vpcmpeqd(xtmp1, xtmp1, xtmp1, vec_enc); vpsrld(xtmp1, xtmp1, 24, vec_enc); + // Remove the bit to the right of the highest set bit ensuring that the conversion to float cannot round up to a higher + // power of 2, which has a higher exponent than the input. This transformation is valid as only the highest set bit + // contributes to the leading number of zeros. + vpsrld(xtmp2, src, 1, vec_enc); + vpandn(xtmp3, xtmp2, src, vec_enc); + // Extract biased exponent. - vcvtdq2ps(dst, src, vec_enc); + vcvtdq2ps(dst, xtmp3, vec_enc); vpsrld(dst, dst, 23, vec_enc); vpand(dst, dst, xtmp1, vec_enc); @@ -6273,7 +6279,7 @@ void C2_MacroAssembler::vector_count_leading_zeros_int_avx(XMMRegister dst, XMMR // Exponent = biased_exp - 127 vpsubd(dst, dst, xtmp1, vec_enc); - // Exponent = Exponent + 1 + // Exponent_plus_one = Exponent + 1 vpsrld(xtmp3, xtmp1, 6, vec_enc); vpaddd(dst, dst, xtmp3, vec_enc); @@ -6286,7 +6292,7 @@ void C2_MacroAssembler::vector_count_leading_zeros_int_avx(XMMRegister dst, XMMR vpslld(xtmp1, xtmp3, 5, vec_enc); // Exponent is 32 if corresponding source lane contains max_int value. vpcmpeqd(xtmp2, dst, xtmp1, vec_enc); - // LZCNT = 32 - exponent + // LZCNT = 32 - exponent_plus_one vpsubd(dst, xtmp1, dst, vec_enc); // Replace LZCNT with a value 1 if corresponding source lane diff --git a/src/hotspot/cpu/x86/runtime_x86_32.cpp b/src/hotspot/cpu/x86/runtime_x86_32.cpp index bcba6093871..4148f98f81c 100644 --- a/src/hotspot/cpu/x86/runtime_x86_32.cpp +++ b/src/hotspot/cpu/x86/runtime_x86_32.cpp @@ -45,7 +45,8 @@ void OptoRuntime::generate_uncommon_trap_blob() { // allocate space for the code ResourceMark rm; // setup code generation tools - CodeBuffer buffer("uncommon_trap_blob", 512, 512); + const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id); + CodeBuffer buffer(name, 512, 512); MacroAssembler* masm = new MacroAssembler(&buffer); enum frame_layout { @@ -255,7 +256,8 @@ void OptoRuntime::generate_exception_blob() { // allocate space for the code ResourceMark rm; // setup code generation tools - CodeBuffer buffer("exception_blob", 512, 512); + const char* name = OptoRuntime::stub_name(OptoStubId::exception_id); + CodeBuffer buffer(name, 512, 512); MacroAssembler* masm = new MacroAssembler(&buffer); OopMapSet *oop_maps = new OopMapSet(); diff --git a/src/hotspot/cpu/x86/runtime_x86_64.cpp b/src/hotspot/cpu/x86/runtime_x86_64.cpp index d7d8fc1895b..464b0eeac6c 100644 --- a/src/hotspot/cpu/x86/runtime_x86_64.cpp +++ b/src/hotspot/cpu/x86/runtime_x86_64.cpp @@ -59,7 +59,8 @@ void OptoRuntime::generate_uncommon_trap_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools - CodeBuffer buffer("uncommon_trap_blob", 2048, 1024); + const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id); + CodeBuffer buffer(name, 2048, 1024); MacroAssembler* masm = new MacroAssembler(&buffer); assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); @@ -264,7 +265,8 @@ void OptoRuntime::generate_exception_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools - CodeBuffer buffer("exception_blob", 2048, 1024); + const char* name = OptoRuntime::stub_name(OptoStubId::exception_id); + CodeBuffer buffer(name, 2048, 1024); MacroAssembler* masm = new MacroAssembler(&buffer); diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index 3915983bda2..b80c0c7626b 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -102,24 +102,23 @@ class RegisterSaver { ymm_off = xmm_off + (XSAVE_AREA_YMM_BEGIN - XSAVE_AREA_BEGIN)/BytesPerInt, DEF_YMM_OFFS(0), DEF_YMM_OFFS(1), - // 2..15 are implied in range usage - r31_off = xmm_off + (XSAVE_AREA_EGPRS - XSAVE_AREA_BEGIN)/BytesPerInt, - r31H_off, - r30_off, r30H_off, - r29_off, r29H_off, - r28_off, r28H_off, - r27_off, r27H_off, - r26_off, r26H_off, - r25_off, r25H_off, - r24_off, r24H_off, - r23_off, r23H_off, - r22_off, r22H_off, - r21_off, r21H_off, - r20_off, r20H_off, - r19_off, r19H_off, - r18_off, r18H_off, + r16_off = xmm_off + (XSAVE_AREA_EGPRS - XSAVE_AREA_BEGIN)/BytesPerInt, + r16H_off, r17_off, r17H_off, - r16_off, r16H_off, + r18_off, r18H_off, + r19_off, r19H_off, + r20_off, r20H_off, + r21_off, r21H_off, + r22_off, r22H_off, + r23_off, r23H_off, + r24_off, r24H_off, + r25_off, r25H_off, + r26_off, r26H_off, + r27_off, r27H_off, + r28_off, r28H_off, + r29_off, r29H_off, + r30_off, r30H_off, + r31_off, r31H_off, opmask_off = xmm_off + (XSAVE_AREA_OPMASK_BEGIN - XSAVE_AREA_BEGIN)/BytesPerInt, DEF_OPMASK_OFFS(0), DEF_OPMASK_OFFS(1), @@ -266,7 +265,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ if (UseAPX) { int base_addr = XSAVE_AREA_EGPRS; off = 0; - for(int n = 16; n < Register::number_of_registers; n++) { + for (int n = 16; n < Register::number_of_registers; n++) { __ movq(Address(rsp, base_addr+(off++*8)), as_Register(n)); } } diff --git a/src/hotspot/cpu/x86/vmStructs_x86.hpp b/src/hotspot/cpu/x86/vmStructs_x86.hpp index 4569bd9a216..d894d8b09a7 100644 --- a/src/hotspot/cpu/x86/vmStructs_x86.hpp +++ b/src/hotspot/cpu/x86/vmStructs_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, 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 @@ -29,17 +29,17 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) -#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) \ -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) \ LP64_ONLY(declare_constant(frame::arg_reg_save_area_bytes)) \ declare_constant(frame::interpreter_frame_sender_sp_offset) \ declare_constant(frame::interpreter_frame_last_sp_offset) -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) #define DECLARE_LONG_CPU_FEATURE_CONSTANT(id, name, bit) GENERATE_VM_LONG_CONSTANT_ENTRY(VM_Version::CPU_##id) #define VM_LONG_CPU_FEATURE_CONSTANTS CPU_FEATURE_FLAGS(DECLARE_LONG_CPU_FEATURE_CONSTANT) diff --git a/src/hotspot/cpu/zero/vmStructs_zero.hpp b/src/hotspot/cpu/zero/vmStructs_zero.hpp index 64a9300e25c..9100c765e7e 100644 --- a/src/hotspot/cpu/zero/vmStructs_zero.hpp +++ b/src/hotspot/cpu/zero/vmStructs_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright 2007 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,12 +30,12 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) -#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) #endif // CPU_ZERO_VMSTRUCTS_ZERO_HPP diff --git a/src/hotspot/os/aix/vmStructs_aix.hpp b/src/hotspot/os/aix/vmStructs_aix.hpp index fb4b6409aaa..c79c9477fff 100644 --- a/src/hotspot/os/aix/vmStructs_aix.hpp +++ b/src/hotspot/os/aix/vmStructs_aix.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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 @@ -29,14 +29,14 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ +#define VM_STRUCTS_OS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ /******************************/ \ nonstatic_field(OSThread, _thread_id, pthread_t) \ -#define VM_TYPES_OS(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ +#define VM_TYPES_OS(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) \ \ /**********************/ \ /* Posix Thread IDs */ \ @@ -44,9 +44,9 @@ \ declare_unsigned_integer_type(pthread_t) -#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant) -#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant) #define VM_ADDRESSES_OS(declare_address, declare_preprocessor_address, declare_function) diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index c538c54e86f..faa3efa2384 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -242,16 +242,6 @@ static char cpu_arch[] = "ppc"; #error Add appropriate cpu_arch setting #endif -// JVM variant -#if defined(ZERO) - #define JVM_VARIANT "zero" -#elif defined(COMPILER2) - #define JVM_VARIANT "server" -#else - #define JVM_VARIANT "client" -#endif - - void os::Bsd::initialize_system_info() { int mib[2]; size_t len; @@ -1558,7 +1548,7 @@ void os::jvm_path(char *buf, jint buflen) { // Add the appropriate JVM variant subdir len = strlen(buf); jrelib_p = buf + len; - snprintf(jrelib_p, buflen-len, "/%s", JVM_VARIANT); + snprintf(jrelib_p, buflen-len, "/%s", Abstract_VM_Version::vm_variant()); if (0 != access(buf, F_OK)) { snprintf(jrelib_p, buflen-len, "%s", ""); } diff --git a/src/hotspot/os/bsd/vmStructs_bsd.hpp b/src/hotspot/os/bsd/vmStructs_bsd.hpp index b29067a9024..e07f1cd7dd0 100644 --- a/src/hotspot/os/bsd/vmStructs_bsd.hpp +++ b/src/hotspot/os/bsd/vmStructs_bsd.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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,7 +31,7 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ +#define VM_STRUCTS_OS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ @@ -39,7 +39,7 @@ nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ nonstatic_field(OSThread, _unique_thread_id, uint64_t) -#define VM_TYPES_OS(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ +#define VM_TYPES_OS(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) \ \ /**********************/ \ /* Thread IDs */ \ @@ -47,9 +47,9 @@ \ declare_unsigned_integer_type(OSThread::thread_id_t) -#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant) -#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant) #define VM_ADDRESSES_OS(declare_address, declare_preprocessor_address, declare_function) \ declare_preprocessor_address("RTLD_DEFAULT", RTLD_DEFAULT) diff --git a/src/hotspot/os/linux/cgroupUtil_linux.cpp b/src/hotspot/os/linux/cgroupUtil_linux.cpp index bc0e018d6be..b52ef87dcae 100644 --- a/src/hotspot/os/linux/cgroupUtil_linux.cpp +++ b/src/hotspot/os/linux/cgroupUtil_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Red Hat, Inc. + * Copyright (c) 2024, 2025, Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,12 +49,18 @@ int CgroupUtil::processor_count(CgroupCpuController* cpu_ctrl, int host_cpus) { } void CgroupUtil::adjust_controller(CgroupMemoryController* mem) { + assert(mem->cgroup_path() != nullptr, "invariant"); + if (strstr(mem->cgroup_path(), "../") != nullptr) { + log_warning(os, container)("Cgroup memory controller path at '%s' seems to have moved to '%s', detected limits won't be accurate", + mem->mount_point(), mem->cgroup_path()); + mem->set_subsystem_path("/"); + return; + } if (!mem->needs_hierarchy_adjustment()) { // nothing to do return; } log_trace(os, container)("Adjusting controller path for memory: %s", mem->subsystem_path()); - assert(mem->cgroup_path() != nullptr, "invariant"); char* orig = os::strdup(mem->cgroup_path()); char* cg_path = os::strdup(orig); char* last_slash; @@ -62,7 +68,8 @@ void CgroupUtil::adjust_controller(CgroupMemoryController* mem) { julong phys_mem = os::Linux::physical_memory(); char* limit_cg_path = nullptr; jlong limit = mem->read_memory_limit_in_bytes(phys_mem); - jlong lowest_limit = phys_mem; + jlong lowest_limit = limit < 0 ? phys_mem : limit; + julong orig_limit = ((julong)lowest_limit) != phys_mem ? lowest_limit : phys_mem; while ((last_slash = strrchr(cg_path, '/')) != cg_path) { *last_slash = '\0'; // strip path // update to shortened path and try again @@ -83,7 +90,7 @@ void CgroupUtil::adjust_controller(CgroupMemoryController* mem) { limit_cg_path = os::strdup("/"); } assert(lowest_limit >= 0, "limit must be positive"); - if ((julong)lowest_limit != phys_mem) { + if ((julong)lowest_limit != orig_limit) { // we've found a lower limit anywhere in the hierarchy, // set the path to the limit path assert(limit_cg_path != nullptr, "limit path must be set"); @@ -93,6 +100,7 @@ void CgroupUtil::adjust_controller(CgroupMemoryController* mem) { mem->subsystem_path(), lowest_limit); } else { + log_trace(os, container)("Lowest limit was: " JLONG_FORMAT, lowest_limit); log_trace(os, container)("No lower limit found for memory in hierarchy %s, " "adjusting to original path %s", mem->mount_point(), orig); @@ -104,19 +112,26 @@ void CgroupUtil::adjust_controller(CgroupMemoryController* mem) { } void CgroupUtil::adjust_controller(CgroupCpuController* cpu) { + assert(cpu->cgroup_path() != nullptr, "invariant"); + if (strstr(cpu->cgroup_path(), "../") != nullptr) { + log_warning(os, container)("Cgroup cpu controller path at '%s' seems to have moved to '%s', detected limits won't be accurate", + cpu->mount_point(), cpu->cgroup_path()); + cpu->set_subsystem_path("/"); + return; + } if (!cpu->needs_hierarchy_adjustment()) { // nothing to do return; } log_trace(os, container)("Adjusting controller path for cpu: %s", cpu->subsystem_path()); - assert(cpu->cgroup_path() != nullptr, "invariant"); char* orig = os::strdup(cpu->cgroup_path()); char* cg_path = os::strdup(orig); char* last_slash; assert(cg_path[0] == '/', "cgroup path must start with '/'"); int host_cpus = os::Linux::active_processor_count(); int cpus = CgroupUtil::processor_count(cpu, host_cpus); - int lowest_limit = host_cpus; + int lowest_limit = cpus < host_cpus ? cpus: host_cpus; + int orig_limit = lowest_limit != host_cpus ? lowest_limit : host_cpus; char* limit_cg_path = nullptr; while ((last_slash = strrchr(cg_path, '/')) != cg_path) { *last_slash = '\0'; // strip path @@ -138,7 +153,7 @@ void CgroupUtil::adjust_controller(CgroupCpuController* cpu) { limit_cg_path = os::strdup(cg_path); } assert(lowest_limit >= 0, "limit must be positive"); - if (lowest_limit != host_cpus) { + if (lowest_limit != orig_limit) { // we've found a lower limit anywhere in the hierarchy, // set the path to the limit path assert(limit_cg_path != nullptr, "limit path must be set"); @@ -148,6 +163,7 @@ void CgroupUtil::adjust_controller(CgroupCpuController* cpu) { cpu->subsystem_path(), lowest_limit); } else { + log_trace(os, container)("Lowest limit was: %d", lowest_limit); log_trace(os, container)("No lower limit found for cpu in hierarchy %s, " "adjusting to original path %s", cpu->mount_point(), orig); diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp index a6ac2822b25..8d9c3edb72a 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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,47 @@ /* * Set directory to subsystem specific files based * on the contents of the mountinfo and cgroup files. + * + * The method determines whether it runs in + * - host mode + * - container mode + * + * In the host mode, _root is equal to "/" and + * the subsystem path is equal to the _mount_point path + * joined with cgroup_path. + * + * In the container mode, it can be two possibilities: + * - private namespace (cgroupns=private) + * - host namespace (cgroupns=host, default mode in cgroup V1 hosts) + * + * Private namespace is equivalent to the host mode, i.e. + * the subsystem path is set by concatenating + * _mount_point and cgroup_path. + * + * In the host namespace, _root is equal to host's cgroup path + * of the control group to which the containerized process + * belongs to at the moment of creation. The mountinfo and + * cgroup files are mirrored from the host, while the subsystem + * specific files are mapped directly at _mount_point, i.e. + * at /sys/fs/cgroup/<controller>/, the subsystem path is + * then set equal to _mount_point. + * + * A special case of the subsystem path is when a cgroup path + * includes a subgroup, when a containerized process was associated + * with an existing cgroup, that is different from cgroup + * in which the process has been created. + * Here, the _root is equal to the host's initial cgroup path, + * cgroup_path will be equal to host's new cgroup path. + * As host cgroup hierarchies are not accessible in the container, + * it needs to be determined which part of cgroup path + * is accessible inside container, i.e. mapped under + * /sys/fs/cgroup/<controller>/<subgroup>. + * In Docker default setup, host's cgroup path can be + * of the form: /docker/<CONTAINER_ID>/<subgroup>, + * from which only <subgroup> is mapped. + * The method trims cgroup path from left, until the subgroup + * component is found. The subsystem path will be set to + * the _mount_point joined with the subgroup path. */ void CgroupV1Controller::set_subsystem_path(const char* cgroup_path) { if (_cgroup_path != nullptr) { @@ -49,28 +90,36 @@ void CgroupV1Controller::set_subsystem_path(const char* cgroup_path) { _cgroup_path = os::strdup(cgroup_path); stringStream ss; if (_root != nullptr && cgroup_path != nullptr) { + ss.print_raw(_mount_point); if (strcmp(_root, "/") == 0) { - ss.print_raw(_mount_point); + // host processes and containers with cgroupns=private if (strcmp(cgroup_path,"/") != 0) { ss.print_raw(cgroup_path); } - _path = os::strdup(ss.base()); } else { - if (strcmp(_root, cgroup_path) == 0) { - ss.print_raw(_mount_point); - _path = os::strdup(ss.base()); - } else { - char *p = strstr((char*)cgroup_path, _root); - if (p != nullptr && p == _root) { - if (strlen(cgroup_path) > strlen(_root)) { - ss.print_raw(_mount_point); - const char* cg_path_sub = cgroup_path + strlen(_root); - ss.print_raw(cg_path_sub); - _path = os::strdup(ss.base()); + // containers with cgroupns=host, default setting is _root==cgroup_path + if (strcmp(_root, cgroup_path) != 0) { + if (*cgroup_path != '\0' && strcmp(cgroup_path, "/") != 0) { + // When moved to a subgroup, between subgroups, the path suffix will change. + const char *suffix = cgroup_path; + while (suffix != nullptr) { + stringStream pp; + pp.print_raw(_mount_point); + pp.print_raw(suffix); + if (os::file_exists(pp.base())) { + ss.print_raw(suffix); + if (suffix != cgroup_path) { + log_trace(os, container)("set_subsystem_path: cgroup v1 path reduced to: %s.", suffix); + } + break; + } + log_trace(os, container)("set_subsystem_path: skipped non-existent directory: %s.", suffix); + suffix = strchr(suffix + 1, '/'); } } } } + _path = os::strdup(ss.base()); } } diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp index 62e8cac3a62..cbadbb9db02 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Red Hat Inc. + * Copyright (c) 2020, 2025, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -292,6 +292,10 @@ jlong memory_swap_limit_value(CgroupV2Controller* ctrl) { } void CgroupV2Controller::set_subsystem_path(const char* cgroup_path) { + if (_cgroup_path != nullptr) { + os::free(_cgroup_path); + } + _cgroup_path = os::strdup(cgroup_path); if (_path != nullptr) { os::free(_path); } diff --git a/src/hotspot/os/linux/vmStructs_linux.hpp b/src/hotspot/os/linux/vmStructs_linux.hpp index 2696a891f56..90bc6517a3f 100644 --- a/src/hotspot/os/linux/vmStructs_linux.hpp +++ b/src/hotspot/os/linux/vmStructs_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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,7 +31,7 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ +#define VM_STRUCTS_OS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ @@ -39,7 +39,7 @@ nonstatic_field(OSThread, _thread_id, pid_t) \ nonstatic_field(OSThread, _pthread_id, pthread_t) -#define VM_TYPES_OS(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ +#define VM_TYPES_OS(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) \ \ /**********************/ \ /* Posix Thread IDs */ \ @@ -48,9 +48,9 @@ declare_integer_type(pid_t) \ declare_unsigned_integer_type(pthread_t) -#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant) -#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant) #define VM_ADDRESSES_OS(declare_address, declare_preprocessor_address, declare_function) \ declare_preprocessor_address("RTLD_DEFAULT", RTLD_DEFAULT) diff --git a/src/hotspot/os/windows/vmStructs_windows.hpp b/src/hotspot/os/windows/vmStructs_windows.hpp index 26ad17bb166..7d457c82fe8 100644 --- a/src/hotspot/os/windows/vmStructs_windows.hpp +++ b/src/hotspot/os/windows/vmStructs_windows.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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 @@ -29,7 +29,7 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ +#define VM_STRUCTS_OS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ @@ -38,13 +38,13 @@ nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ unchecked_nonstatic_field(OSThread, _thread_handle, sizeof(HANDLE)) /* NOTE: no type */ -#define VM_TYPES_OS(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ +#define VM_TYPES_OS(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) \ \ declare_unsigned_integer_type(OSThread::thread_id_t) -#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant) -#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant) #define VM_ADDRESSES_OS(declare_address, declare_preprocessor_address, declare_function) diff --git a/src/hotspot/os_cpu/aix_ppc/vmStructs_aix_ppc.hpp b/src/hotspot/os_cpu/aix_ppc/vmStructs_aix_ppc.hpp deleted file mode 100644 index d09b0125f25..00000000000 --- a/src/hotspot/os_cpu/aix_ppc/vmStructs_aix_ppc.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2013 SAP SE. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_CPU_AIX_PPC_VMSTRUCTS_AIX_PPC_HPP -#define OS_CPU_AIX_PPC_VMSTRUCTS_AIX_PPC_HPP - -// These are the OS and CPU-specific fields, types and integer -// constants required by the Serviceability Agent. This file is -// referenced by vmStructs.cpp. - -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) - -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#endif // OS_CPU_AIX_PPC_VMSTRUCTS_AIX_PPC_HPP diff --git a/src/hotspot/os_cpu/bsd_aarch64/vmStructs_bsd_aarch64.hpp b/src/hotspot/os_cpu/bsd_aarch64/vmStructs_bsd_aarch64.hpp deleted file mode 100644 index 24d5c0f4dc6..00000000000 --- a/src/hotspot/os_cpu/bsd_aarch64/vmStructs_bsd_aarch64.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, Red Hat Inc. All rights reserved. - * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_CPU_BSD_AARCH64_VMSTRUCTS_BSD_AARCH64_HPP -#define OS_CPU_BSD_AARCH64_VMSTRUCTS_BSD_AARCH64_HPP - -// These are the OS and CPU-specific fields, types and integer -// constants required by the Serviceability Agent. This file is -// referenced by vmStructs.cpp. - -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) - -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#endif // OS_CPU_BSD_AARCH64_VMSTRUCTS_BSD_AARCH64_HPP diff --git a/src/hotspot/os_cpu/bsd_x86/vmStructs_bsd_x86.hpp b/src/hotspot/os_cpu/bsd_x86/vmStructs_bsd_x86.hpp deleted file mode 100644 index 4f6c4414f5f..00000000000 --- a/src/hotspot/os_cpu/bsd_x86/vmStructs_bsd_x86.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_CPU_BSD_X86_VMSTRUCTS_BSD_X86_HPP -#define OS_CPU_BSD_X86_VMSTRUCTS_BSD_X86_HPP - -// These are the OS and CPU-specific fields, types and integer -// constants required by the Serviceability Agent. This file is -// referenced by vmStructs.cpp. - -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) - -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#endif // OS_CPU_BSD_X86_VMSTRUCTS_BSD_X86_HPP diff --git a/src/hotspot/os_cpu/bsd_zero/vmStructs_bsd_zero.hpp b/src/hotspot/os_cpu/bsd_zero/vmStructs_bsd_zero.hpp deleted file mode 100644 index ea3771b7ce6..00000000000 --- a/src/hotspot/os_cpu/bsd_zero/vmStructs_bsd_zero.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007 Red Hat, Inc. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_CPU_BSD_ZERO_VMSTRUCTS_BSD_ZERO_HPP -#define OS_CPU_BSD_ZERO_VMSTRUCTS_BSD_ZERO_HPP - -// These are the OS and CPU-specific fields, types and integer -// constants required by the Serviceability Agent. This file is -// referenced by vmStructs.cpp. - -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) - -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#endif // OS_CPU_BSD_ZERO_VMSTRUCTS_BSD_ZERO_HPP diff --git a/src/hotspot/os_cpu/linux_aarch64/vmStructs_linux_aarch64.hpp b/src/hotspot/os_cpu/linux_aarch64/vmStructs_linux_aarch64.hpp deleted file mode 100644 index 6cc6d73be77..00000000000 --- a/src/hotspot/os_cpu/linux_aarch64/vmStructs_linux_aarch64.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, Red Hat Inc. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_CPU_LINUX_AARCH64_VMSTRUCTS_LINUX_AARCH64_HPP -#define OS_CPU_LINUX_AARCH64_VMSTRUCTS_LINUX_AARCH64_HPP - -// These are the OS and CPU-specific fields, types and integer -// constants required by the Serviceability Agent. This file is -// referenced by vmStructs.cpp. - -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) - -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#endif // OS_CPU_LINUX_AARCH64_VMSTRUCTS_LINUX_AARCH64_HPP diff --git a/src/hotspot/os_cpu/linux_arm/vmStructs_linux_arm.hpp b/src/hotspot/os_cpu/linux_arm/vmStructs_linux_arm.hpp deleted file mode 100644 index a1b73bdee8f..00000000000 --- a/src/hotspot/os_cpu/linux_arm/vmStructs_linux_arm.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_CPU_LINUX_ARM_VMSTRUCTS_LINUX_ARM_HPP -#define OS_CPU_LINUX_ARM_VMSTRUCTS_LINUX_ARM_HPP - -// These are the OS and CPU-specific fields, types and integer -// constants required by the Serviceability Agent. This file is -// referenced by vmStructs.cpp. - -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) - -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#endif // OS_CPU_LINUX_ARM_VMSTRUCTS_LINUX_ARM_HPP diff --git a/src/hotspot/os_cpu/linux_ppc/vmStructs_linux_ppc.hpp b/src/hotspot/os_cpu/linux_ppc/vmStructs_linux_ppc.hpp deleted file mode 100644 index 46288cdeaab..00000000000 --- a/src/hotspot/os_cpu/linux_ppc/vmStructs_linux_ppc.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2013 SAP SE. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_CPU_LINUX_PPC_VMSTRUCTS_LINUX_PPC_HPP -#define OS_CPU_LINUX_PPC_VMSTRUCTS_LINUX_PPC_HPP - -// These are the OS and CPU-specific fields, types and integer -// constants required by the Serviceability Agent. This file is -// referenced by vmStructs.cpp. - -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) - -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#endif // OS_CPU_LINUX_PPC_VMSTRUCTS_LINUX_PPC_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/vmStructs_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/vmStructs_linux_riscv.hpp deleted file mode 100644 index b39a329335a..00000000000 --- a/src/hotspot/os_cpu/linux_riscv/vmStructs_linux_riscv.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_CPU_LINUX_RISCV_VM_VMSTRUCTS_LINUX_RISCV_HPP -#define OS_CPU_LINUX_RISCV_VM_VMSTRUCTS_LINUX_RISCV_HPP - -// These are the OS and CPU-specific fields, types and integer -// constants required by the Serviceability Agent. This file is -// referenced by vmStructs.cpp. - -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) - -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#endif // OS_CPU_LINUX_RISCV_VM_VMSTRUCTS_LINUX_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_s390/vmStructs_linux_s390.hpp b/src/hotspot/os_cpu/linux_s390/vmStructs_linux_s390.hpp deleted file mode 100644 index a52bc722579..00000000000 --- a/src/hotspot/os_cpu/linux_s390/vmStructs_linux_s390.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_CPU_LINUX_S390_VMSTRUCTS_LINUX_S390_HPP -#define OS_CPU_LINUX_S390_VMSTRUCTS_LINUX_S390_HPP - -// These are the OS and CPU-specific fields, types and integer -// constants required by the Serviceability Agent. This file is -// referenced by vmStructs.cpp. - -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) - -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#endif // OS_CPU_LINUX_S390_VMSTRUCTS_LINUX_S390_HPP diff --git a/src/hotspot/os_cpu/linux_x86/vmStructs_linux_x86.hpp b/src/hotspot/os_cpu/linux_x86/vmStructs_linux_x86.hpp deleted file mode 100644 index ddba9daf131..00000000000 --- a/src/hotspot/os_cpu/linux_x86/vmStructs_linux_x86.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_CPU_LINUX_X86_VMSTRUCTS_LINUX_X86_HPP -#define OS_CPU_LINUX_X86_VMSTRUCTS_LINUX_X86_HPP - -// These are the OS and CPU-specific fields, types and integer -// constants required by the Serviceability Agent. This file is -// referenced by vmStructs.cpp. - -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) - -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#endif // OS_CPU_LINUX_X86_VMSTRUCTS_LINUX_X86_HPP diff --git a/src/hotspot/os_cpu/linux_zero/vmStructs_linux_zero.hpp b/src/hotspot/os_cpu/linux_zero/vmStructs_linux_zero.hpp deleted file mode 100644 index 271193cd705..00000000000 --- a/src/hotspot/os_cpu/linux_zero/vmStructs_linux_zero.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007 Red Hat, Inc. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_CPU_LINUX_ZERO_VMSTRUCTS_LINUX_ZERO_HPP -#define OS_CPU_LINUX_ZERO_VMSTRUCTS_LINUX_ZERO_HPP - -// These are the OS and CPU-specific fields, types and integer -// constants required by the Serviceability Agent. This file is -// referenced by vmStructs.cpp. - -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) - -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#endif // OS_CPU_LINUX_ZERO_VMSTRUCTS_LINUX_ZERO_HPP diff --git a/src/hotspot/os_cpu/windows_aarch64/vmStructs_windows_aarch64.hpp b/src/hotspot/os_cpu/windows_aarch64/vmStructs_windows_aarch64.hpp deleted file mode 100644 index 18a5588b743..00000000000 --- a/src/hotspot/os_cpu/windows_aarch64/vmStructs_windows_aarch64.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2020, Microsoft Corporation. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_CPU_WINDOWS_AARCH64_VMSTRUCTS_WINDOWS_AARCH64_HPP -#define OS_CPU_WINDOWS_AARCH64_VMSTRUCTS_WINDOWS_AARCH64_HPP - -// These are the OS and CPU-specific fields, types and integer -// constants required by the Serviceability Agent. This file is -// referenced by vmStructs.cpp. - -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) - -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#endif // OS_CPU_WINDOWS_AARCH64_VMSTRUCTS_WINDOWS_AARCH64_HPP diff --git a/src/hotspot/os_cpu/windows_x86/vmStructs_windows_x86.hpp b/src/hotspot/os_cpu/windows_x86/vmStructs_windows_x86.hpp deleted file mode 100644 index 4ed62839d51..00000000000 --- a/src/hotspot/os_cpu/windows_x86/vmStructs_windows_x86.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_CPU_WINDOWS_X86_VMSTRUCTS_WINDOWS_X86_HPP -#define OS_CPU_WINDOWS_X86_VMSTRUCTS_WINDOWS_X86_HPP - -// These are the OS and CPU-specific fields, types and integer -// constants required by the Serviceability Agent. This file is -// referenced by vmStructs.cpp. - -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) - -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - -#endif // OS_CPU_WINDOWS_X86_VMSTRUCTS_WINDOWS_X86_HPP diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index a9e613d7b40..c614f7af1c0 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -1856,14 +1856,14 @@ void InsEncode::output(FILE *fp) { fprintf(fp,"InsEncode: "); _encoding.reset(); - while ( (encoding = (NameAndList*)_encoding.iter()) != 0 ) { + while ( (encoding = (NameAndList*)_encoding.iter()) != nullptr ) { // Output the encoding being used fprintf(fp,"%s(", encoding->name() ); // Output its parameter list, if any bool first_param = true; encoding->reset(); - while ( (parameter = encoding->iter()) != 0 ) { + while ( (parameter = encoding->iter()) != nullptr ) { // Output the ',' between parameters if ( ! first_param ) fprintf(fp,", "); first_param = false; @@ -3307,7 +3307,7 @@ void ComponentList::output(FILE *fp) { MatchNode::MatchNode(ArchDesc &ad, const char *result, const char *mexpr, const char *opType, MatchNode *lChild, MatchNode *rChild) : _AD(ad), _result(result), _name(mexpr), _opType(opType), - _lChild(lChild), _rChild(rChild), _internalop(0), _numleaves(0), + _lChild(lChild), _rChild(rChild), _internalop(nullptr), _numleaves(0), _commutative_id(0) { _numleaves = (lChild ? lChild->_numleaves : 0) + (rChild ? rChild->_numleaves : 0); @@ -3316,14 +3316,14 @@ MatchNode::MatchNode(ArchDesc &ad, const char *result, const char *mexpr, MatchNode::MatchNode(ArchDesc &ad, MatchNode& mnode) : _AD(ad), _result(mnode._result), _name(mnode._name), _opType(mnode._opType), _lChild(mnode._lChild), _rChild(mnode._rChild), - _internalop(0), _numleaves(mnode._numleaves), + _internalop(nullptr), _numleaves(mnode._numleaves), _commutative_id(mnode._commutative_id) { } MatchNode::MatchNode(ArchDesc &ad, MatchNode& mnode, int clone) : _AD(ad), _result(mnode._result), _name(mnode._name), _opType(mnode._opType), - _internalop(0), _numleaves(mnode._numleaves), + _internalop(nullptr), _numleaves(mnode._numleaves), _commutative_id(mnode._commutative_id) { if (mnode._lChild) { _lChild = new MatchNode(ad, *mnode._lChild, clone); @@ -3626,7 +3626,7 @@ void MatchNode::dump() { } void MatchNode::output(FILE *fp) { - if (_lChild==0 && _rChild==0) { + if (_lChild==nullptr && _rChild==nullptr) { fprintf(fp," %s",_name); // operand } else { diff --git a/src/hotspot/share/adlc/formssel.hpp b/src/hotspot/share/adlc/formssel.hpp index 61d0fb40f18..dca1a50991b 100644 --- a/src/hotspot/share/adlc/formssel.hpp +++ b/src/hotspot/share/adlc/formssel.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, 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 @@ -973,8 +973,8 @@ class MatchNode : public Form { int _commutative_id; // id of commutative operation // Public Methods - MatchNode(ArchDesc &ad, const char *result = 0, const char *expr = 0, - const char *opType=0, MatchNode *lChild=nullptr, + MatchNode(ArchDesc &ad, const char *result = nullptr, const char *expr = nullptr, + const char *opType=nullptr, MatchNode *lChild=nullptr, MatchNode *rChild=nullptr); MatchNode(ArchDesc &ad, MatchNode& mNode); // Shallow copy constructor; MatchNode(ArchDesc &ad, MatchNode& mNode, int clone); // Construct clone diff --git a/src/hotspot/share/c1/c1_Compilation.cpp b/src/hotspot/share/c1/c1_Compilation.cpp index 42bb2b04334..dccc4759004 100644 --- a/src/hotspot/share/c1/c1_Compilation.cpp +++ b/src/hotspot/share/c1/c1_Compilation.cpp @@ -410,6 +410,8 @@ int Compilation::compile_java_method() { env()->dump_replay_data(env()->compile_id()); } + DEBUG_ONLY(CompilationMemoryStatistic::do_test_allocations();) + { PhaseTraceTime timeit(_t_codeemit); return emit_code_body(); diff --git a/src/hotspot/share/c1/c1_Runtime1.hpp b/src/hotspot/share/c1/c1_Runtime1.hpp index bab4505a275..25a0c11c55d 100644 --- a/src/hotspot/share/c1/c1_Runtime1.hpp +++ b/src/hotspot/share/c1/c1_Runtime1.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, 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 @@ -53,7 +53,6 @@ enum class C1StubId :int { #undef C1_STUB_ID_ENUM_DECLARE class Runtime1: public AllStatic { - friend class VMStructs; friend class ArrayCopyStub; public: diff --git a/src/hotspot/share/cds/aotClassInitializer.cpp b/src/hotspot/share/cds/aotClassInitializer.cpp index 5b022cae244..c5ad36ac315 100644 --- a/src/hotspot/share/cds/aotClassInitializer.cpp +++ b/src/hotspot/share/cds/aotClassInitializer.cpp @@ -107,7 +107,7 @@ bool AOTClassInitializer::can_archive_initialized_mirror(InstanceKlass* ik) { // Automatic selection for aot-inited classes // ========================================== // - // When CDSConfig::is_initing_classes_at_dump_time() is enabled, + // When CDSConfig::is_initing_classes_at_dump_time is enabled, // AOTArtifactFinder::find_artifacts() finds the classes of all // heap objects that are reachable from HeapShared::_run_time_special_subgraph, // and mark these classes as aot-inited. This preserves the initialized @@ -266,7 +266,7 @@ bool AOTClassInitializer::can_archive_initialized_mirror(InstanceKlass* ik) { } } - if (CDSConfig::is_dumping_invokedynamic()) { + if (CDSConfig::is_dumping_method_handles()) { // This table was created with the help of CDSHeapVerifier. // Also, some $Holder classes are needed. E.g., Invokers.<clinit> explicitly // initializes Invokers$Holder. Since Invokers.<clinit> won't be executed diff --git a/src/hotspot/share/cds/aotClassLinker.cpp b/src/hotspot/share/cds/aotClassLinker.cpp index a1cacd735dd..dc539eb3d55 100644 --- a/src/hotspot/share/cds/aotClassLinker.cpp +++ b/src/hotspot/share/cds/aotClassLinker.cpp @@ -142,7 +142,7 @@ bool AOTClassLinker::try_add_candidate(InstanceKlass* ik) { if (ik->is_hidden()) { assert(ik->shared_class_loader_type() != ClassLoader::OTHER, "must have been set"); - if (!CDSConfig::is_dumping_invokedynamic()) { + if (!CDSConfig::is_dumping_method_handles()) { return false; } if (HeapShared::is_lambda_proxy_klass(ik)) { diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index 21e97457a87..48e843e473f 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -786,6 +786,7 @@ void ArchiveBuilder::make_klasses_shareable() { const char* aotlinked_msg = ""; const char* inited_msg = ""; Klass* k = get_buffered_addr(klasses()->at(i)); + bool inited = false; k->remove_java_mirror(); #ifdef _LP64 if (UseCompactObjectHeaders) { @@ -810,7 +811,7 @@ void ArchiveBuilder::make_klasses_shareable() { InstanceKlass* ik = InstanceKlass::cast(k); InstanceKlass* src_ik = get_source_addr(ik); bool aotlinked = AOTClassLinker::is_candidate(src_ik); - bool inited = ik->has_aot_initialized_mirror(); + inited = ik->has_aot_initialized_mirror(); ADD_COUNT(num_instance_klasses); if (CDSConfig::is_dumping_dynamic_archive()) { // For static dump, class loader type are already set. @@ -833,7 +834,7 @@ void ArchiveBuilder::make_klasses_shareable() { type = "bad"; assert(0, "shouldn't happen"); } - if (CDSConfig::is_dumping_invokedynamic()) { + if (CDSConfig::is_dumping_method_handles()) { assert(HeapShared::is_archivable_hidden_klass(ik), "sanity"); } else { // Legacy CDS support for lambda proxies @@ -891,7 +892,11 @@ void ArchiveBuilder::make_klasses_shareable() { aotlinked_msg = " aot-linked"; } if (inited) { - inited_msg = " inited"; + if (InstanceKlass::cast(k)->static_field_size() == 0) { + inited_msg = " inited (no static fields)"; + } else { + inited_msg = " inited"; + } } MetaspaceShared::rewrite_nofast_bytecodes_and_calculate_fingerprints(Thread::current(), ik); diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index 17c3dc6f0bf..c0b6d2c685c 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -48,7 +48,6 @@ bool CDSConfig::_is_using_optimized_module_handling = true; bool CDSConfig::_is_dumping_full_module_graph = true; bool CDSConfig::_is_using_full_module_graph = true; bool CDSConfig::_has_aot_linked_classes = false; -bool CDSConfig::_has_archived_invokedynamic = false; bool CDSConfig::_old_cds_flags_used = false; bool CDSConfig::_new_aot_flags_used = false; bool CDSConfig::_disable_heap_dumping = false; @@ -77,9 +76,16 @@ int CDSConfig::get_status() { void CDSConfig::initialize() { if (is_dumping_static_archive() && !is_dumping_final_static_archive()) { - if (RequireSharedSpaces) { - warning("Cannot dump shared archive while using shared archive"); - } + // Note: -Xshare and -XX:AOTMode flags are mutually exclusive. + // - Classic workflow: -Xshare:on and -Xshare:dump cannot take effect at the same time. + // - JEP 483 workflow: -XX:AOTMode:record and -XX:AOTMode=on cannot take effect at the same time. + // So we can never come to here with RequireSharedSpaces==true. + assert(!RequireSharedSpaces, "sanity"); + + // If dumping the classic archive, or making an AOT training run (dumping a preimage archive), + // for sanity, parse all classes from classfiles. + // TODO: in the future, if we want to support re-training on top of an existing AOT cache, this + // needs to be changed. UseSharedSpaces = false; } @@ -98,12 +104,10 @@ void CDSConfig::initialize() { char* CDSConfig::default_archive_path() { if (_default_archive_path == nullptr) { - char jvm_path[JVM_MAXPATHLEN]; - os::jvm_path(jvm_path, sizeof(jvm_path)); - char *end = strrchr(jvm_path, *os::file_separator()); - if (end != nullptr) *end = '\0'; stringStream tmp; - tmp.print("%s%sclasses", jvm_path, os::file_separator()); + const char* subdir = WINDOWS_ONLY("bin") NOT_WINDOWS("lib"); + tmp.print("%s%s%s%s%s%sclasses", Arguments::get_java_home(), os::file_separator(), subdir, + os::file_separator(), Abstract_VM_Version::vm_variant(), os::file_separator()); #ifdef _LP64 if (!UseCompressedOops) { tmp.print_raw("_nocoops"); @@ -763,8 +767,13 @@ bool CDSConfig::is_dumping_invokedynamic() { return AOTInvokeDynamicLinking && is_dumping_aot_linked_classes() && is_dumping_heap(); } -bool CDSConfig::is_loading_invokedynamic() { - return UseSharedSpaces && is_using_full_module_graph() && _has_archived_invokedynamic; +// When we are dumping aot-linked classes and we are able to write archived heap objects, we automatically +// enable the archiving of MethodHandles. This will in turn enable the archiving of MethodTypes and hidden +// classes that are used in the implementation of MethodHandles. +// Archived MethodHandles are required for higher-level optimizations such as AOT resolution of invokedynamic +// and dynamic proxies. +bool CDSConfig::is_dumping_method_handles() { + return is_initing_classes_at_dump_time(); } #endif // INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/cds/cdsConfig.hpp b/src/hotspot/share/cds/cdsConfig.hpp index 4c05a54f0d8..63f445993db 100644 --- a/src/hotspot/share/cds/cdsConfig.hpp +++ b/src/hotspot/share/cds/cdsConfig.hpp @@ -41,7 +41,6 @@ class CDSConfig : public AllStatic { static bool _is_dumping_full_module_graph; static bool _is_using_full_module_graph; static bool _has_aot_linked_classes; - static bool _has_archived_invokedynamic; static bool _module_patching_disables_cds; static bool _java_base_module_patching_disables_cds; @@ -168,8 +167,7 @@ class CDSConfig : public AllStatic { static bool is_initing_classes_at_dump_time() NOT_CDS_JAVA_HEAP_RETURN_(false); static bool is_dumping_invokedynamic() NOT_CDS_JAVA_HEAP_RETURN_(false); - static bool is_loading_invokedynamic() NOT_CDS_JAVA_HEAP_RETURN_(false); - static void set_has_archived_invokedynamic() { CDS_JAVA_HEAP_ONLY(_has_archived_invokedynamic = true); } + static bool is_dumping_method_handles() NOT_CDS_JAVA_HEAP_RETURN_(false); // full_module_graph (requires optimized_module_handling) static bool is_dumping_full_module_graph() { return CDS_ONLY(_is_dumping_full_module_graph) NOT_CDS(false); } diff --git a/src/hotspot/share/cds/cdsHeapVerifier.cpp b/src/hotspot/share/cds/cdsHeapVerifier.cpp index f9e613a74ce..729637f47c2 100644 --- a/src/hotspot/share/cds/cdsHeapVerifier.cpp +++ b/src/hotspot/share/cds/cdsHeapVerifier.cpp @@ -106,6 +106,8 @@ CDSHeapVerifier::CDSHeapVerifier() : _archived_objs(0), _problems(0) ADD_EXCL("java/lang/System", "bootLayer"); // A + ADD_EXCL("java/util/Collections", "EMPTY_LIST"); // E + // A dummy object used by HashSet. The value doesn't matter and it's never // tested for equality. ADD_EXCL("java/util/HashSet", "PRESENT"); // E @@ -127,7 +129,7 @@ CDSHeapVerifier::CDSHeapVerifier() : _archived_objs(0), _problems(0) ADD_EXCL("sun/invoke/util/ValueConversions", "ONE_INT", // E "ZERO_INT"); // E - if (CDSConfig::is_dumping_invokedynamic()) { + if (CDSConfig::is_dumping_method_handles()) { ADD_EXCL("java/lang/invoke/InvokerBytecodeGenerator", "MEMBERNAME_FACTORY", // D "CD_Object_array", // E same as <...>ConstantUtils.CD_Object_array::CD_Object "INVOKER_SUPER_DESC"); // E same as java.lang.constant.ConstantDescs::CD_Object diff --git a/src/hotspot/share/cds/classListParser.cpp b/src/hotspot/share/cds/classListParser.cpp index fec3ebc2028..6ea19c48bf4 100644 --- a/src/hotspot/share/cds/classListParser.cpp +++ b/src/hotspot/share/cds/classListParser.cpp @@ -631,7 +631,7 @@ void ClassListParser::resolve_indy(JavaThread* current, Symbol* class_name_symbo } void ClassListParser::resolve_indy_impl(Symbol* class_name_symbol, TRAPS) { - if (CDSConfig::is_dumping_invokedynamic()) { + if (CDSConfig::is_dumping_method_handles()) { // The CP entry for the invokedynamic instruction will be resolved. // No need to do the following. return; diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index e34b1342f34..a342007b764 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -300,7 +300,6 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment, _has_aot_linked_classes = CDSConfig::is_dumping_aot_linked_classes(); _has_full_module_graph = CDSConfig::is_dumping_full_module_graph(); _has_valhalla_patched_classes = CDSConfig::is_valhalla_preview(); - _has_archived_invokedynamic = CDSConfig::is_dumping_invokedynamic(); // The following fields are for sanity checks for whether this archive // will function correctly with this JVM and the bootclasspath it's @@ -378,7 +377,6 @@ void FileMapHeader::print(outputStream* st) { st->print_cr("- has_valhalla_patched_classes %d", _has_valhalla_patched_classes); _must_match.print(st); st->print_cr("- has_aot_linked_classes %d", _has_aot_linked_classes); - st->print_cr("- has_archived_invokedynamic %d", _has_archived_invokedynamic); } bool FileMapInfo::validate_class_location() { @@ -2041,10 +2039,6 @@ bool FileMapHeader::validate() { if (!_has_full_module_graph) { CDSConfig::stop_using_full_module_graph("archive was created without full module graph"); } - - if (_has_archived_invokedynamic) { - CDSConfig::set_has_archived_invokedynamic(); - } } return true; diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index 381fa615abb..c8f1752a1db 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -172,7 +172,6 @@ class FileMapHeader: private CDSFileMapHeaderBase { bool _has_full_module_graph; // Does this CDS archive contain the full archived module graph? bool _has_valhalla_patched_classes; // Is this archived dumped with --enable-preview -XX:+EnableValhalla? CDSMustMatchFlags _must_match; // These flags must be the same between dumptime and runtime - bool _has_archived_invokedynamic; // Does the archive have aot-linked invokedynamic CP entries? HeapRootSegments _heap_root_segments; // Heap root segments info size_t _heap_oopmap_start_pos; // The first bit in the oopmap corresponds to this position in the heap. size_t _heap_ptrmap_start_pos; // The first bit in the ptrmap corresponds to this position in the heap. diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index 42bb6b3024d..83f6098b2cd 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -141,8 +141,7 @@ GrowableArrayCHeap<oop, mtClassShared>* HeapShared::_pending_roots = nullptr; GrowableArrayCHeap<OopHandle, mtClassShared>* HeapShared::_root_segments; int HeapShared::_root_segment_max_size_elems; OopHandle HeapShared::_scratch_basic_type_mirrors[T_VOID+1]; -MetaspaceObjToOopHandleTable* HeapShared::_scratch_java_mirror_table = nullptr; -MetaspaceObjToOopHandleTable* HeapShared::_scratch_references_table = nullptr; +MetaspaceObjToOopHandleTable* HeapShared::_scratch_objects_table = nullptr; static bool is_subgraph_root_class_of(ArchivableStaticFieldInfo fields[], InstanceKlass* ik) { for (int i = 0; fields[i].valid(); i++) { @@ -393,20 +392,19 @@ class MetaspaceObjToOopHandleTable: public ResourceHashtable<MetaspaceObj*, OopH void HeapShared::add_scratch_resolved_references(ConstantPool* src, objArrayOop dest) { if (SystemDictionaryShared::is_builtin_loader(src->pool_holder()->class_loader_data())) { - _scratch_references_table->set_oop(src, dest); + _scratch_objects_table->set_oop(src, dest); } } objArrayOop HeapShared::scratch_resolved_references(ConstantPool* src) { - return (objArrayOop)_scratch_references_table->get_oop(src); + return (objArrayOop)_scratch_objects_table->get_oop(src); } void HeapShared::init_dumping() { - _scratch_java_mirror_table = new (mtClass)MetaspaceObjToOopHandleTable(); - _scratch_references_table = new (mtClass)MetaspaceObjToOopHandleTable(); + _scratch_objects_table = new (mtClass)MetaspaceObjToOopHandleTable(); } -void HeapShared::init_scratch_objects(TRAPS) { +void HeapShared::init_scratch_objects_for_basic_type_mirrors(TRAPS) { for (int i = T_BOOLEAN; i < T_VOID+1; i++) { BasicType bt = (BasicType)i; if (!is_reference_type(bt)) { @@ -448,24 +446,24 @@ oop HeapShared::scratch_java_mirror(BasicType t) { } oop HeapShared::scratch_java_mirror(Klass* k) { - return _scratch_java_mirror_table->get_oop(k); + return _scratch_objects_table->get_oop(k); } void HeapShared::set_scratch_java_mirror(Klass* k, oop mirror) { - _scratch_java_mirror_table->set_oop(k, mirror); + _scratch_objects_table->set_oop(k, mirror); } void HeapShared::remove_scratch_objects(Klass* k) { // Klass is being deallocated. Java mirror can still be alive, and it should not // point to dead klass. We need to break the link from mirror to the Klass. // See how InstanceKlass::deallocate_contents does it for normal mirrors. - oop mirror = _scratch_java_mirror_table->get_oop(k); + oop mirror = _scratch_objects_table->get_oop(k); if (mirror != nullptr) { java_lang_Class::set_klass(mirror, nullptr); } - _scratch_java_mirror_table->remove_oop(k); + _scratch_objects_table->remove_oop(k); if (k->is_instance_klass()) { - _scratch_references_table->remove(InstanceKlass::cast(k)->constants()); + _scratch_objects_table->remove(InstanceKlass::cast(k)->constants()); } } @@ -492,7 +490,7 @@ bool HeapShared::is_string_concat_klass(InstanceKlass* ik) { } bool HeapShared::is_archivable_hidden_klass(InstanceKlass* ik) { - return CDSConfig::is_dumping_invokedynamic() && + return CDSConfig::is_dumping_method_handles() && (is_lambda_form_klass(ik) || is_lambda_proxy_klass(ik) || is_string_concat_klass(ik)); } @@ -782,7 +780,7 @@ void KlassSubGraphInfo::add_subgraph_object_klass(Klass* orig_k) { if (orig_k->is_instance_klass()) { #ifdef ASSERT InstanceKlass* ik = InstanceKlass::cast(orig_k); - if (CDSConfig::is_dumping_invokedynamic()) { + if (CDSConfig::is_dumping_method_handles()) { assert(ik->class_loader() == nullptr || HeapShared::is_lambda_proxy_klass(ik), "we can archive only instances of boot classes or lambda proxy classes"); @@ -835,7 +833,7 @@ void KlassSubGraphInfo::check_allowed_klass(InstanceKlass* ik) { } const char* lambda_msg = ""; - if (CDSConfig::is_dumping_invokedynamic()) { + if (CDSConfig::is_dumping_method_handles()) { lambda_msg = ", or a lambda proxy class"; if (HeapShared::is_lambda_proxy_klass(ik) && (ik->class_loader() == nullptr || @@ -1108,7 +1106,7 @@ void HeapShared::resolve_classes_for_subgraph_of(JavaThread* current, Klass* k) } void HeapShared::initialize_java_lang_invoke(TRAPS) { - if (CDSConfig::is_loading_invokedynamic() || CDSConfig::is_dumping_invokedynamic()) { + if (CDSConfig::is_using_aot_linked_classes() || CDSConfig::is_dumping_method_handles()) { resolve_or_init("java/lang/invoke/Invokers$Holder", true, CHECK); resolve_or_init("java/lang/invoke/MethodHandle", true, CHECK); resolve_or_init("java/lang/invoke/MethodHandleNatives", true, CHECK); diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp index ba2fe5be775..9ad09882410 100644 --- a/src/hotspot/share/cds/heapShared.hpp +++ b/src/hotspot/share/cds/heapShared.hpp @@ -284,8 +284,7 @@ class HeapShared: AllStatic { static GrowableArrayCHeap<OopHandle, mtClassShared>* _root_segments; static int _root_segment_max_size_elems; static OopHandle _scratch_basic_type_mirrors[T_VOID+1]; - static MetaspaceObjToOopHandleTable* _scratch_java_mirror_table; - static MetaspaceObjToOopHandleTable* _scratch_references_table; + static MetaspaceObjToOopHandleTable* _scratch_objects_table; static void init_seen_objects_table() { assert(_seen_objects_table == nullptr, "must be"); @@ -406,7 +405,7 @@ class HeapShared: AllStatic { static objArrayOop scratch_resolved_references(ConstantPool* src); static void add_scratch_resolved_references(ConstantPool* src, objArrayOop dest) NOT_CDS_JAVA_HEAP_RETURN; static void init_dumping() NOT_CDS_JAVA_HEAP_RETURN; - static void init_scratch_objects(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; + static void init_scratch_objects_for_basic_type_mirrors(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; static void init_box_classes(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; static bool is_heap_region(int idx) { CDS_JAVA_HEAP_ONLY(return (idx == MetaspaceShared::hp);) diff --git a/src/hotspot/share/cds/lambdaFormInvokers.cpp b/src/hotspot/share/cds/lambdaFormInvokers.cpp index fc1917086f3..ab22b4775b7 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.cpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.cpp @@ -95,7 +95,7 @@ void LambdaFormInvokers::regenerate_holder_classes(TRAPS) { return; } - if (CDSConfig::is_dumping_static_archive() && CDSConfig::is_dumping_invokedynamic()) { + if (CDSConfig::is_dumping_static_archive() && CDSConfig::is_dumping_method_handles()) { // Work around JDK-8310831, as some methods in lambda form holder classes may not get generated. log_info(cds)("Archived MethodHandles may refer to lambda form holder classes. Cannot regenerate."); return; diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index 5b6f6190add..a45c46cdcb4 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -153,7 +153,7 @@ static bool shared_base_valid(char* shared_base) { // We check user input for SharedBaseAddress at dump time. // At CDS runtime, "shared_base" will be the (attempted) mapping start. It will also - // be the encoding base, since the the headers of archived base objects (and with Lilliput, + // be the encoding base, since the headers of archived base objects (and with Lilliput, // the prototype mark words) carry pre-computed narrow Klass IDs that refer to the mapping // start as base. // @@ -638,7 +638,7 @@ void VM_PopulateDumpSharedSpace::doit() { DEBUG_ONLY(SystemDictionaryShared::NoClassLoadingMark nclm); _pending_method_handle_intrinsics = new (mtClassShared) GrowableArray<Method*>(256, mtClassShared); - if (CDSConfig::is_dumping_aot_linked_classes()) { + if (CDSConfig::is_dumping_method_handles()) { // When dumping AOT-linked classes, some classes may have direct references to a method handle // intrinsic. The easiest thing is to save all of them into the AOT cache. SystemDictionary::get_all_method_handle_intrinsics(_pending_method_handle_intrinsics); @@ -987,7 +987,7 @@ void MetaspaceShared::preload_and_dump_impl(StaticArchiveBuilder& builder, TRAPS HeapShared::reset_archived_object_states(CHECK); } - if (CDSConfig::is_dumping_invokedynamic()) { + if (CDSConfig::is_dumping_method_handles()) { // This assert means that the MethodType and MethodTypeForm tables won't be // updated concurrently when we are saving their contents into a side table. assert(CDSConfig::allow_only_single_java_thread(), "Required"); @@ -997,12 +997,15 @@ void MetaspaceShared::preload_and_dump_impl(StaticArchiveBuilder& builder, TRAPS vmSymbols::createArchivedObjects(), vmSymbols::void_method_signature(), CHECK); + } + if (CDSConfig::is_initing_classes_at_dump_time()) { // java.lang.Class::reflectionFactory cannot be archived yet. We set this field // to null, and it will be initialized again at runtime. log_debug(cds)("Resetting Class::reflectionFactory"); TempNewSymbol method_name = SymbolTable::new_symbol("resetArchivedStates"); Symbol* method_sig = vmSymbols::void_method_signature(); + JavaValue result(T_VOID); JavaCalls::call_static(&result, vmClasses::Class_klass(), method_name, method_sig, CHECK); diff --git a/src/hotspot/share/ci/ciClassList.hpp b/src/hotspot/share/ci/ciClassList.hpp index 39e9bd3ffc2..f3427e68294 100644 --- a/src/hotspot/share/ci/ciClassList.hpp +++ b/src/hotspot/share/ci/ciClassList.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, 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 @@ -78,13 +78,11 @@ class ciTypeArrayKlass; // Everyone gives access to ciObjectFactory #define CI_PACKAGE_ACCESS \ friend class ciObjectFactory; \ -friend class VMStructs; // These are the packages that have access to ciEnv // Any more access must be given explicitly. #define CI_PACKAGE_ACCESS_TO \ friend class ciObjectFactory; \ -friend class VMStructs; \ friend class ciCallSite; \ friend class ciConstantPoolCache; \ friend class ciField; \ diff --git a/src/hotspot/share/ci/ciConstant.hpp b/src/hotspot/share/ci/ciConstant.hpp index 1d0f60407ed..f07d0a170df 100644 --- a/src/hotspot/share/ci/ciConstant.hpp +++ b/src/hotspot/share/ci/ciConstant.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ // // This class represents a constant value. class ciConstant { - friend class VMStructs; private: friend class ciEnv; friend class ciField; diff --git a/src/hotspot/share/ci/ciEnv.cpp b/src/hotspot/share/ci/ciEnv.cpp index ce08884af95..929868eee5f 100644 --- a/src/hotspot/share/ci/ciEnv.cpp +++ b/src/hotspot/share/ci/ciEnv.cpp @@ -107,7 +107,7 @@ static bool firstEnv = true; // ------------------------------------------------------------------ // ciEnv::ciEnv ciEnv::ciEnv(CompileTask* task) - : _ciEnv_arena(mtCompiler) { + : _ciEnv_arena(mtCompiler, Arena::Tag::tag_cienv) { VM_ENTRY_MARK; // Set up ciEnv::current immediately, for the sake of ciObjectFactory, etc. @@ -239,7 +239,7 @@ class RecordLocation { } }; -ciEnv::ciEnv(Arena* arena) : _ciEnv_arena(mtCompiler) { +ciEnv::ciEnv(Arena* arena) : _ciEnv_arena(mtCompiler, Arena::Tag::tag_cienv) { ASSERT_IN_VM; // Set up ciEnv::current immediately, for the sake of ciObjectFactory, etc. diff --git a/src/hotspot/share/ci/ciObjectFactory.cpp b/src/hotspot/share/ci/ciObjectFactory.cpp index 62b8dfb7938..698fe8e472c 100644 --- a/src/hotspot/share/ci/ciObjectFactory.cpp +++ b/src/hotspot/share/ci/ciObjectFactory.cpp @@ -111,7 +111,7 @@ void ciObjectFactory::initialize() { // This Arena is long lived and exists in the resource mark of the // compiler thread that initializes the initial ciObjectFactory which // creates the shared ciObjects that all later ciObjectFactories use. - Arena* arena = new (mtCompiler) Arena(mtCompiler); + Arena* arena = new (mtCompiler) Arena(mtCompiler, Arena::Tag::tag_cienv); ciEnv initial(arena); ciEnv* env = ciEnv::current(); env->_factory->init_shared_objects(); diff --git a/src/hotspot/share/ci/ciObjectFactory.hpp b/src/hotspot/share/ci/ciObjectFactory.hpp index a944e534002..f09de642e8b 100644 --- a/src/hotspot/share/ci/ciObjectFactory.hpp +++ b/src/hotspot/share/ci/ciObjectFactory.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,6 @@ // which ensures that for each oop, at most one ciObject is created. // This invariant allows efficient implementation of ciObject. class ciObjectFactory : public ArenaObj { - friend class VMStructs; friend class ciEnv; private: diff --git a/src/hotspot/share/ci/ciTypeFlow.cpp b/src/hotspot/share/ci/ciTypeFlow.cpp index e7152a9808f..c42c0fef98e 100644 --- a/src/hotspot/share/ci/ciTypeFlow.cpp +++ b/src/hotspot/share/ci/ciTypeFlow.cpp @@ -523,8 +523,8 @@ bool ciTypeFlow::StateVector::meet_exception(ciInstanceKlass* exc, bool different = false; // Meet locals from incoming array. - Cell limit = local(_outer->max_locals()-1); - for (Cell c = start_cell(); c <= limit; c = next_cell(c)) { + Cell limit = local_limit_cell(); + for (Cell c = start_cell(); c < limit; c = next_cell(c)) { ciType* t1 = type_at(c); ciType* t2 = incoming->type_at(c); if (!t1->equals(t2)) { diff --git a/src/hotspot/share/ci/ciTypeFlow.hpp b/src/hotspot/share/ci/ciTypeFlow.hpp index a58c4c21e34..6b2616a09b0 100644 --- a/src/hotspot/share/ci/ciTypeFlow.hpp +++ b/src/hotspot/share/ci/ciTypeFlow.hpp @@ -213,9 +213,12 @@ class ciTypeFlow : public ArenaObj { return (Cell)(outer()->max_locals() + stack_size()); } + Cell local_limit_cell() const { return (Cell) outer()->max_locals(); } + // Cell creation Cell local(int lnum) const { assert(lnum < outer()->max_locals(), "index check"); + assert(Cell_0 <= lnum && lnum <= Cell_max, "out of Cell's range"); return (Cell)(lnum); } diff --git a/src/hotspot/share/classfile/compactHashtable.cpp b/src/hotspot/share/classfile/compactHashtable.cpp index 5a3c6998904..8d50e8136a3 100644 --- a/src/hotspot/share/classfile/compactHashtable.cpp +++ b/src/hotspot/share/classfile/compactHashtable.cpp @@ -72,19 +72,6 @@ CompactHashtableWriter::~CompactHashtableWriter() { FREE_C_HEAP_ARRAY(GrowableArray<Entry>*, _buckets); } -size_t CompactHashtableWriter::estimate_size(int num_entries) { - int num_buckets = calculate_num_buckets(num_entries); - size_t bucket_bytes = ArchiveBuilder::ro_array_bytesize<u4>(num_buckets + 1); - - // In worst case, we have no VALUE_ONLY_BUCKET_TYPE, so each entry takes 2 slots - int entries_space = 2 * num_entries; - size_t entry_bytes = ArchiveBuilder::ro_array_bytesize<u4>(entries_space); - - return bucket_bytes - + entry_bytes - + SimpleCompactHashtable::calculate_header_size(); -} - // Add a symbol entry to the temporary hash table void CompactHashtableWriter::add(unsigned int hash, u4 value) { int index = hash % _num_buckets; diff --git a/src/hotspot/share/classfile/compactHashtable.hpp b/src/hotspot/share/classfile/compactHashtable.hpp index 73e9f7fc092..2985f0f9a1a 100644 --- a/src/hotspot/share/classfile/compactHashtable.hpp +++ b/src/hotspot/share/classfile/compactHashtable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, 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 @@ -134,8 +134,6 @@ class CompactHashtableWriter: public StackObj { public: void dump(SimpleCompactHashtable *cht, const char* table_name); - - static size_t estimate_size(int num_entries); }; #endif // INCLUDE_CDS @@ -243,7 +241,6 @@ template < bool (*EQUALS)(V value, K key, int len) > class CompactHashtable : public SimpleCompactHashtable { - friend class VMStructs; V decode(u4 offset) const { return DECODE(_base_address, offset); diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 8deaf5ab58e..e8dabe378bf 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -5469,7 +5469,7 @@ void JavaClasses::serialize_offsets(SerializeClosure* soc) { bool JavaClasses::is_supported_for_archiving(oop obj) { Klass* klass = obj->klass(); - if (!CDSConfig::is_dumping_invokedynamic()) { + if (!CDSConfig::is_dumping_method_handles()) { // These are supported by CDS only when CDSConfig::is_dumping_invokedynamic() is enabled. if (klass == vmClasses::ResolvedMethodName_klass() || klass == vmClasses::MemberName_klass()) { diff --git a/src/hotspot/share/classfile/moduleEntry.hpp b/src/hotspot/share/classfile/moduleEntry.hpp index 9ad7bde8954..c2d07a78512 100644 --- a/src/hotspot/share/classfile/moduleEntry.hpp +++ b/src/hotspot/share/classfile/moduleEntry.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -207,7 +207,6 @@ class ModuleEntry : public CHeapObj<mtModule> { void load_from_archive(ClassLoaderData* loader_data); void restore_archived_oops(ClassLoaderData* loader_data); void clear_archived_oops(); - void update_oops_in_archived_module(int root_oop_index); static void verify_archived_module_entries() PRODUCT_RETURN; #endif }; diff --git a/src/hotspot/share/classfile/stringTable.hpp b/src/hotspot/share/classfile/stringTable.hpp index 0d58e09f208..15539009f66 100644 --- a/src/hotspot/share/classfile/stringTable.hpp +++ b/src/hotspot/share/classfile/stringTable.hpp @@ -40,7 +40,6 @@ class SerializeClosure; class StringTableConfig; class StringTable : AllStatic { - friend class VMStructs; friend class StringTableConfig; static volatile bool _has_work; diff --git a/src/hotspot/share/classfile/symbolTable.cpp b/src/hotspot/share/classfile/symbolTable.cpp index 3cb453aaecb..04640b672f6 100644 --- a/src/hotspot/share/classfile/symbolTable.cpp +++ b/src/hotspot/share/classfile/symbolTable.cpp @@ -705,13 +705,6 @@ void SymbolTable::copy_shared_symbol_table(GrowableArray<Symbol*>* symbols, } } -size_t SymbolTable::estimate_size_for_archive() { - if (_items_count > (size_t)max_jint) { - fatal("Too many symbols to be archived: %zu", _items_count); - } - return CompactHashtableWriter::estimate_size(int(_items_count)); -} - void SymbolTable::write_to_archive(GrowableArray<Symbol*>* symbols) { CompactHashtableWriter writer(int(_items_count), ArchiveBuilder::symbol_stats()); copy_shared_symbol_table(symbols, &writer); diff --git a/src/hotspot/share/classfile/symbolTable.hpp b/src/hotspot/share/classfile/symbolTable.hpp index a1e585e97de..cc861812dc3 100644 --- a/src/hotspot/share/classfile/symbolTable.hpp +++ b/src/hotspot/share/classfile/symbolTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, 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 @@ class constantPoolHandle; class SymbolClosure; class SymbolTable : public AllStatic { - friend class VMStructs; friend class Symbol; friend class ClassFileParser; friend class SymbolTableConfig; @@ -161,7 +160,6 @@ class SymbolTable : public AllStatic { static void copy_shared_symbol_table(GrowableArray<Symbol*>* symbols, CompactHashtableWriter* ch_table); public: - static size_t estimate_size_for_archive() NOT_CDS_RETURN_(0); static void write_to_archive(GrowableArray<Symbol*>* symbols) NOT_CDS_RETURN; static void serialize_shared_table_header(SerializeClosure* soc, bool is_static_archive = true) NOT_CDS_RETURN; diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index b54d102e089..cc9a3c080eb 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -80,7 +80,6 @@ class SystemDictionary : AllStatic { friend class AOTLinkedClassBulkLoader; friend class BootstrapInfo; friend class vmClasses; - friend class VMStructs; public: diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 2f7887c2d46..8b815cf9cb7 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -295,7 +295,7 @@ bool SystemDictionaryShared::check_for_exclusion_impl(InstanceKlass* k) { if (!k->is_hidden() && k->shared_classpath_index() < 0 && is_builtin(k)) { if (k->name()->starts_with("java/lang/invoke/BoundMethodHandle$Species_")) { // This class is dynamically generated by the JDK - if (CDSConfig::is_dumping_aot_linked_classes()) { + if (CDSConfig::is_dumping_method_handles()) { k->set_shared_classpath_index(0); } else { ResourceMark rm; @@ -587,7 +587,7 @@ void SystemDictionaryShared::validate_before_archiving(InstanceKlass* k) { guarantee(!info->is_excluded(), "Should not attempt to archive excluded class %s", name); if (is_builtin(k)) { if (k->is_hidden()) { - if (!CDSConfig::is_dumping_invokedynamic()) { + if (!CDSConfig::is_dumping_method_handles()) { assert(is_registered_lambda_proxy_class(k), "unexpected hidden class %s", name); } } @@ -1223,45 +1223,6 @@ bool SystemDictionaryShared::is_supported_invokedynamic(BootstrapInfo* bsi) { return false; } -class EstimateSizeForArchive : StackObj { - size_t _shared_class_info_size; - int _num_builtin_klasses; - int _num_unregistered_klasses; - -public: - EstimateSizeForArchive() { - _shared_class_info_size = 0; - _num_builtin_klasses = 0; - _num_unregistered_klasses = 0; - } - - void do_entry(InstanceKlass* k, DumpTimeClassInfo& info) { - if (!info.is_excluded()) { - size_t byte_size = info.runtime_info_bytesize(); - _shared_class_info_size += align_up(byte_size, SharedSpaceObjectAlignment); - } - } - - size_t total() { - return _shared_class_info_size; - } -}; - -size_t SystemDictionaryShared::estimate_size_for_archive() { - EstimateSizeForArchive est; - _dumptime_table->iterate_all_live_classes(&est); - size_t total_size = est.total() + - CompactHashtableWriter::estimate_size(_dumptime_table->count_of(true)) + - CompactHashtableWriter::estimate_size(_dumptime_table->count_of(false)); - - size_t bytesize = align_up(sizeof(RunTimeLambdaProxyClassInfo), SharedSpaceObjectAlignment); - total_size += - (bytesize * _dumptime_lambda_proxy_class_dictionary->_count) + - CompactHashtableWriter::estimate_size(_dumptime_lambda_proxy_class_dictionary->_count); - - return total_size; -} - unsigned int SystemDictionaryShared::hash_for_shared_dictionary(address ptr) { if (ArchiveBuilder::is_active()) { uintx offset = ArchiveBuilder::current()->any_to_offset(ptr); diff --git a/src/hotspot/share/classfile/systemDictionaryShared.hpp b/src/hotspot/share/classfile/systemDictionaryShared.hpp index 7286bdad3fd..c7f38880837 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.hpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp @@ -294,7 +294,6 @@ class SystemDictionaryShared: public SystemDictionary { static void set_excluded_locked(InstanceKlass* k); static bool warn_excluded(InstanceKlass* k, const char* reason); static void dumptime_classes_do(class MetaspaceClosure* it); - static size_t estimate_size_for_archive(); static void write_to_archive(bool is_static_archive = true); static void adjust_lambda_proxy_class_dictionary(); static void serialize_dictionary_headers(class SerializeClosure* soc, diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp index 89e0105f834..95194d76d11 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.cpp +++ b/src/hotspot/share/classfile/vmIntrinsics.cpp @@ -480,6 +480,7 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { case vmIntrinsics::_sha5_implCompress: if (!UseSHA512Intrinsics) return true; break; + case vmIntrinsics::_double_keccak: case vmIntrinsics::_sha3_implCompress: if (!UseSHA3Intrinsics) return true; break; @@ -492,6 +493,13 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { case vmIntrinsics::_chacha20Block: if (!UseChaCha20Intrinsics) return true; break; + case vmIntrinsics::_dilithiumAlmostNtt: + case vmIntrinsics::_dilithiumAlmostInverseNtt: + case vmIntrinsics::_dilithiumNttMult: + case vmIntrinsics::_dilithiumMontMulByConstant: + case vmIntrinsics::_dilithiumDecomposePoly: + if (!UseDilithiumIntrinsics) return true; + break; case vmIntrinsics::_base64_encodeBlock: case vmIntrinsics::_base64_decodeBlock: if (!UseBASE64Intrinsics) return true; diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index 3608eac91c7..61d4b81d411 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -519,6 +519,12 @@ class methodHandle; do_class(sun_security_provider_sha3, "sun/security/provider/SHA3") \ do_intrinsic(_sha3_implCompress, sun_security_provider_sha3, implCompress_name, implCompress_signature, F_R) \ \ + /* support for sun.security.provider.SHAKE128Parallel */ \ + do_class(sun_security_provider_sha3_parallel, "sun/security/provider/SHA3Parallel") \ + do_intrinsic(_double_keccak, sun_security_provider_sha3_parallel, double_keccak_name, double_keccak_signature, F_S) \ + do_name( double_keccak_name, "doubleKeccak") \ + do_signature(double_keccak_signature, "([J[J)I") \ + \ /* support for sun.security.provider.DigestBase */ \ do_class(sun_security_provider_digestbase, "sun/security/provider/DigestBase") \ do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, countPositives_signature, F_R) \ @@ -564,6 +570,26 @@ class methodHandle; do_name(chacha20Block_name, "implChaCha20Block") \ do_signature(chacha20Block_signature, "([I[B)I") \ \ + /* support for sun.security.provider.ML_DSA */ \ + do_class(sun_security_provider_ML_DSA, "sun/security/provider/ML_DSA") \ + do_signature(IaII_signature, "([II)I") \ + do_signature(IaIaI_signature, "([I[I)I") \ + do_signature(IaIaIaI_signature, "([I[I[I)I") \ + do_signature(IaIaIaIII_signature, "([I[I[III)I") \ + do_intrinsic(_dilithiumAlmostNtt, sun_security_provider_ML_DSA, dilithiumAlmostNtt_name, IaIaI_signature, F_S) \ + do_name(dilithiumAlmostNtt_name, "implDilithiumAlmostNtt") \ + do_intrinsic(_dilithiumAlmostInverseNtt, sun_security_provider_ML_DSA, \ + dilithiumAlmostInverseNtt_name, IaIaI_signature, F_S) \ + do_name(dilithiumAlmostInverseNtt_name, "implDilithiumAlmostInverseNtt") \ + do_intrinsic(_dilithiumNttMult, sun_security_provider_ML_DSA, dilithiumNttMult_name, IaIaIaI_signature, F_S) \ + do_name(dilithiumNttMult_name, "implDilithiumNttMult") \ + do_intrinsic(_dilithiumMontMulByConstant, sun_security_provider_ML_DSA, \ + dilithiumMontMulByConstant_name, IaII_signature, F_S) \ + do_name(dilithiumMontMulByConstant_name, "implDilithiumMontMulByConstant") \ + do_intrinsic(_dilithiumDecomposePoly, sun_security_provider_ML_DSA, \ + dilithiumDecomposePoly_name, IaIaIaIII_signature, F_S) \ + do_name(dilithiumDecomposePoly_name, "implDilithiumDecomposePoly") \ + \ /* support for java.util.zip */ \ do_class(java_util_zip_CRC32, "java/util/zip/CRC32") \ do_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \ diff --git a/src/hotspot/share/compiler/compilationMemStatInternals.hpp b/src/hotspot/share/compiler/compilationMemStatInternals.hpp new file mode 100644 index 00000000000..a6050823771 --- /dev/null +++ b/src/hotspot/share/compiler/compilationMemStatInternals.hpp @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2024, 2025, Red Hat, Inc. and/or its affiliates. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_COMPILER_COMPILATIONMEMSTATINTERNALS_HPP +#define SHARE_COMPILER_COMPILATIONMEMSTATINTERNALS_HPP + +#include "compiler/compilationMemoryStatistic.hpp" +#include "compiler/compilerDefinitions.hpp" +#include "memory/allocation.hpp" +#include "memory/arena.hpp" +#include "utilities/globalDefinitions.hpp" + +#ifdef COMPILER2 +#include "opto/phase.hpp" +#endif + +class CompileTask; +class Method; +class Symbol; +class outputStream; + +#ifdef COMPILER2 +constexpr int phase_trc_id_max = (int)Phase::PhaseTraceId::max_phase_timers; +constexpr int phase_trc_id_none = (int)Phase::PhaseTraceId::_t_none; +#else +// In minimal builds, the ArenaCounterTable is just a single-dimension vector of arena tags (see below) +constexpr int phase_trc_id_max = 1; +constexpr int phase_trc_id_none = 0; +#endif +inline void check_phase_trace_id(int v) { assert(v >= 0 && v < phase_trc_id_max, "OOB (%d)", v); } + +constexpr int arena_tag_max = (int)Arena::Tag::tag_count; +inline void check_arena_tag(int v) { assert(v >= 0 && v < arena_tag_max, "OOB (%d)", v); } + +// A two-dimensional table, containing byte counters per arena type and +// per compilation phase. +class ArenaCounterTable { + size_t _v[phase_trc_id_max][arena_tag_max]; +public: + ArenaCounterTable(); + void copy_from(const ArenaCounterTable& other); + inline size_t at(int phase_trc_id, int arena_tag) const; + inline void add(size_t size, int phase_trc_id, int arena_tag); + inline void sub(size_t size, int phase_trc_id, int arena_tag); + void print_on(outputStream* ss) const; + void summarize(size_t out[arena_tag_max]) const; +}; + +struct PhaseInfo { + int id, num; + const char* text; +}; + +// A stack keeping track of the current compilation phase. Fixed-width for simplicity +// (we should never go beyond 5 or so in depth). +class PhaseInfoStack { + static constexpr int max_depth = 16; + int _depth; + PhaseInfo _stack[max_depth]; +public: + inline PhaseInfoStack(); + inline bool empty() const { return _depth == 0; } + inline void push(PhaseInfo info); + inline void pop(); + inline const PhaseInfo& top() const; + inline int depth() const { return _depth; } +}; + +// A very simple fixed-width FIFO buffer, used for the phase timeline +template <typename T, int size> +class SimpleFifo { + STATIC_ASSERT((size * 2) < INT_MAX); + T _v[size]; + int _pos; + int _oldest; + uint64_t _lost; + + int current_pos() const { return _pos; } + static int pos_to_index(int pos) { return pos % size; } + T& at(int pos) { return *(_v + pos_to_index(pos)); } + +public: + SimpleFifo() : _pos(0), _oldest(0), _lost(0UL) {} + T& current() { return at(current_pos()); } + T& last() { assert(!empty(), "sanity"); return at(current_pos() - 1); } + bool empty() const { return _pos == _oldest; } + uint64_t lost() const { return _lost; } + + void advance() { + _pos ++; + if (_pos >= size) { + _oldest ++; + _lost ++; + } + if (_pos == INT_MAX) { + _pos -= size; + _oldest -= size; + } + } + + void revert() { + assert(!empty(), "sanity"); + _pos--; + } + + template<typename F> + void iterate_all(F f) const { + for (int i = _oldest; i < _pos; i++) { + const int index = pos_to_index(i); + f(_v[index]); + } + } + + void copy_from(const SimpleFifo& other) { + memcpy(_v, other._v, sizeof(_v)); + _pos = other._pos; + _lost = other._lost; + _oldest = other._oldest; + } +}; + +// Holds a table of n entries; each entry keeping start->end footprints when +// a phase started and ended; each entry also keeping the phase-local peak (if +// a phase caused a temporary spike in footprint that vanished before the phase +// ended). +// Handling nested phases: for this structure, there is always a phase active; +// if a phase ends, we "restart" the parent phase (which often is the +// "outside any phase" phase). +class FootprintTimeline { +public: + static constexpr unsigned max_num_phases = 256; // beyond that we wrap, keeping just the last n phases +private: + template <typename T, typename dT> + struct C { + T start, peak, cur; + void init(T v) { start = cur = peak = v; } + void update(T v) { cur = v; if (v > peak) peak = v; } + dT end_delta() const { return (dT)cur - (dT)start; } + // Returns the peak size during this phase: how high usage rose above either + // start or end of phase. The background is that we want to know the max. memory + // consumption during this phase, but that may not be reflected by the start or the + // end counters if an Arena was created during the phase and only lived temporarily. + size_t temporary_peak_size() const { return MIN2(peak - cur, peak - start); } + }; + struct Entry { + PhaseInfo info; + int level; + C<size_t, ssize_t> _bytes; + C<unsigned, signed int> _live_nodes; + }; + SimpleFifo<Entry, max_num_phases> _fifo; + DEBUG_ONLY(bool _inbetween_phases;) +public: + FootprintTimeline(); + void copy_from(const FootprintTimeline& other); + inline void on_footprint_change(size_t cur_abs, unsigned cur_nodes); + void on_phase_end(size_t cur_abs, unsigned cur_nodes); + void on_phase_start(PhaseInfo info, size_t cur_abs, unsigned cur_nodes, int level); + void print_on(outputStream* st) const; +}; + +// We keep the name of the involved symbols in Symbol (made permanent) instead of resolving them to string and +// storing those. That significantly reduces footprint for the result store and delays resolving until printing +// time, which may be never. +class FullMethodName { + Symbol* _k; + Symbol* _m; + Symbol* _s; +public: + FullMethodName(); + FullMethodName(const Method* m); + FullMethodName(const FullMethodName& o); + FullMethodName& operator=(const FullMethodName& o); + void make_permanent(); + void print_on(outputStream* st) const; + char* as_C_string(char* buf, size_t len) const; + bool operator== (const FullMethodName& b) const; + DEBUG_ONLY(bool is_test_class() const;) +}; + +// ArenaState is the central data structure holding all statistics and temp data during +// a single compilation. It is created on demand (if memstat is active) and tied to the +// CompilerThread. +class ArenaStatCounter : public CHeapObj<mtCompiler> { + + FullMethodName _fmn; + + // from directives + const bool _should_print_memstat; + const bool _should_crash_on_memlimit; + + // Bytes total now + size_t _current; + // Bytes total at last global peak + size_t _peak; + // Bytes per arena/phase, now + ArenaCounterTable _counters_current; + // Bytes per arena/phase when we last reached the global peak + ArenaCounterTable _counters_at_global_peak; + + // Number of live nodes now (C2 only) + unsigned _live_nodes_current; + // Number of live nodes at global peak (C2 only) + unsigned _live_nodes_at_global_peak; + + // MemLimit handling + const size_t _limit; + bool _hit_limit; + bool _limit_in_process; + + // Keep track of current C2 phase + int _phase_counter; + PhaseInfoStack _phase_info_stack; + + // Keep track of C2 phase allocations over time + FootprintTimeline _timeline; + + const CompilerType _comp_type; + const int _comp_id; + + DEBUG_ONLY(bool _is_test_class;) + + int retrieve_live_node_count() const; + +public: + ArenaStatCounter(const CompileTask* task, size_t limit); + + void on_phase_start(PhaseInfo info); + void on_phase_end(); + + // Account an arena allocation. Returns true if new peak reached. + bool on_arena_chunk_allocation(size_t size, int arena_tag, uint64_t* stamp); + + // Account an arena deallocation. + void on_arena_chunk_deallocation(size_t size, uint64_t stamp); + + void print_peak_state_on(outputStream* st) const; + void print_error_state_on(outputStream* st) const; + + size_t limit() const { return _limit; } + bool hit_limit() const { return _hit_limit; } + bool limit_in_process() const { return _limit_in_process; } + void set_limit_in_process(bool v) { _limit_in_process = v; } + + const FullMethodName& fmn() const { return _fmn; } + bool should_print_memstat() { return _should_print_memstat; }; + bool should_crash_on_memlimit() const { return _should_crash_on_memlimit; }; + + CompilerType comp_type() const { return _comp_type; } + int comp_id() const { return _comp_id; } + DEBUG_ONLY(bool is_test_class() const { return _is_test_class; }) + + // Bytes total at last global peak + size_t peak() const { return _peak; } + + // Bytes per arena/phase when we last reached the global peak + const ArenaCounterTable& counters_at_global_peak() const { return _counters_at_global_peak; } + const FootprintTimeline& timeline() const { return _timeline; } + // Number of live nodes at global peak (C2 only) + unsigned live_nodes_at_global_peak() const { return _live_nodes_at_global_peak; } + + int advance_phase_counter() { return ++_phase_counter; } +}; + +#endif // SHARE_COMPILER_COMPILATIONMEMSTATINTERNALS_HPP diff --git a/src/hotspot/share/compiler/compilationMemStatInternals.inline.hpp b/src/hotspot/share/compiler/compilationMemStatInternals.inline.hpp new file mode 100644 index 00000000000..94be8606ac9 --- /dev/null +++ b/src/hotspot/share/compiler/compilationMemStatInternals.inline.hpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Red Hat, Inc. and/or its affiliates. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_COMPILATIONMEMSTATINTERNALS_INLINE_HPP +#define SHARE_COMPILATIONMEMSTATINTERNALS_INLINE_HPP + +#include "compiler/compilationMemStatInternals.hpp" + +inline PhaseInfoStack::PhaseInfoStack() : _depth(0) {} + +inline void PhaseInfoStack::push(PhaseInfo info) { +#ifdef ASSERT + check_phase_trace_id(info.id); + if (_depth == 0) { + assert(info.id == phase_trc_id_none, "first entry must be none"); + } else { + assert(info.id != phase_trc_id_none, "subsequent entries must not be none"); + } + assert(_depth < max_depth, "Sanity"); +#endif // ASSERT + _stack[_depth] = info; + if (_depth < max_depth) { + _depth++; + } +} + +inline void PhaseInfoStack::pop() { +#ifdef ASSERT + assert(!empty(), "Sanity "); + const PhaseInfo to_be_popped = top(); + if (_depth == 1) { + assert(to_be_popped.id == phase_trc_id_none, "first entry must be none"); + } else { + assert(to_be_popped.id != phase_trc_id_none, "subsequent entries must not be none"); + } +#endif // ASSERT + if (_depth > 0) { + _depth--; + } +} + +inline const PhaseInfo& PhaseInfoStack::top() const { + assert(!empty(), "Sanity"); + return _stack[_depth - 1]; +} + +inline size_t ArenaCounterTable::at(int phase_trc_id, int arena_tag) const { + check_phase_trace_id(phase_trc_id); + check_arena_tag(arena_tag); + return _v[phase_trc_id][arena_tag]; +} + +inline void ArenaCounterTable::add(size_t size, int phase_trc_id, int arena_tag) { + check_arena_tag(arena_tag); + const size_t old = at(phase_trc_id, arena_tag); + _v[phase_trc_id][arena_tag] += size; + assert(at(phase_trc_id, arena_tag) >= old, "Overflow"); +} + +inline void ArenaCounterTable::sub(size_t size, int phase_trc_id, int arena_tag) { + check_arena_tag(arena_tag); + assert(at(phase_trc_id, arena_tag) >= size, "Underflow (%zu %zu)", at(phase_trc_id, arena_tag), size); + _v[phase_trc_id][arena_tag] -= size; +} + +inline void FootprintTimeline::on_footprint_change(size_t cur_abs, unsigned cur_nodes) { + assert(!_inbetween_phases, "no phase started?"); + Entry& e = _fifo.current(); + e._bytes.update(cur_abs); + e._live_nodes.update(cur_nodes); +} + +#endif // SHARE_COMPILATIONMEMSTATINTERNALS_INLINE_HPP diff --git a/src/hotspot/share/compiler/compilationMemoryStatistic.cpp b/src/hotspot/share/compiler/compilationMemoryStatistic.cpp index 89d0b60212e..41991567c9a 100644 --- a/src/hotspot/share/compiler/compilationMemoryStatistic.cpp +++ b/src/hotspot/share/compiler/compilationMemoryStatistic.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2023, 2024, Red Hat, Inc. and/or its affiliates. + * Copyright (c) 2023, 2025, Red Hat, Inc. and/or its affiliates. * 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,413 +23,778 @@ * */ -#include "logging/log.hpp" -#include "logging/logStream.hpp" -#ifdef COMPILER1 -#include "c1/c1_Compilation.hpp" -#endif +#include "code/nmethod.hpp" #include "compiler/abstractCompiler.hpp" -#include "compiler/compilationMemoryStatistic.hpp" +#include "compiler/compilationMemStatInternals.inline.hpp" +#include "compiler/compilerDefinitions.inline.hpp" #include "compiler/compilerDirectives.hpp" -#include "compiler/compileTask.hpp" -#include "compiler/compilerDefinitions.hpp" +#include "compiler/compilerOracle.hpp" #include "compiler/compilerThread.hpp" +#include "compiler/compileTask.hpp" +#include "logging/log.hpp" +#include "logging/logStream.hpp" #include "memory/arena.hpp" -#include "memory/resourceArea.hpp" #include "nmt/nmtCommon.hpp" +#include "oops/method.inline.hpp" #include "oops/symbol.hpp" -#ifdef COMPILER2 -#include "opto/node.hpp" // compile.hpp is not self-contained -#include "opto/compile.hpp" -#endif +#include "runtime/atomic.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" +#include "utilities/checkedCast.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/ostream.hpp" -#include "utilities/quickSort.hpp" -#include "utilities/resourceHash.hpp" -ArenaStatCounter::ArenaStatCounter() { - reset(); -} +#ifdef COMPILER1 +#include "c1/c1_Compilation.hpp" +#endif + +#ifdef COMPILER2 +#include "opto/compile.hpp" +#include "opto/node.hpp" // compile.hpp is not self-contained +#endif -void ArenaStatCounter::reset() { - _current = 0; - _peak = 0; - _current_by_tag.clear(); - _peak_by_tag.clear(); - _limit = 0; - _hit_limit = false; - _limit_in_process = false; - _live_nodes_at_peak = 0; - _active = false; +static const char* phase_trc_id_to_string(int phase_trc_id) { + return COMPILER2_PRESENT(Phase::get_phase_trace_id_text((Phase::PhaseTraceId)phase_trc_id)) + NOT_COMPILER2(""); } -void ArenaStatCounter::start(size_t limit) { - reset(); - _active = true; - _limit = limit; +// If crash option on memlimit is enabled and an oom occurred, the stats for the +// first offending compilation. +static ArenaStatCounter* volatile _arenastat_oom_crash = nullptr; + +// Arena-chunk stamping +union chunkstamp_t { + uint64_t raw; + struct { + uint32_t tracked; + uint16_t arena_tag; + uint16_t phase_id; + }; +}; +STATIC_ASSERT(sizeof(chunkstamp_t) == sizeof(chunkstamp_t::raw)); + +ArenaCounterTable::ArenaCounterTable() { + memset(_v, 0, sizeof(_v)); } -void ArenaStatCounter::end() { - _limit = 0; - _hit_limit = false; - _active = false; +void ArenaCounterTable::copy_from(const ArenaCounterTable& other) { + memcpy(_v, other._v, sizeof(_v)); } -void ArenaStatCounter::update_c2_node_count() { - assert(_active, "compilaton has not yet started"); -#ifdef COMPILER2 - CompilerThread* const th = Thread::current()->as_Compiler_thread(); - const CompileTask* const task = th->task(); - if (task != nullptr && - th->task()->compiler() != nullptr && - th->task()->compiler()->type() == compiler_c2) { - const Compile* const comp = Compile::current(); - if (comp != nullptr) { - _live_nodes_at_peak = comp->live_nodes(); +void ArenaCounterTable::summarize(size_t out[arena_tag_max]) const { + memset(out, 0, arena_tag_max * sizeof(size_t)); + for (int i = 0; i < phase_trc_id_max; i++) { + for (int j = 0; j < arena_tag_max; j++) { + out[j] += _v[i][j]; } } -#endif } -// Account an arena allocation or de-allocation. -bool ArenaStatCounter::account(ssize_t delta, int tag) { - assert(_active, "compilaton has not yet started"); - bool rc = false; -#ifdef ASSERT - // Note: if this fires, we free more arena memory under the scope of the - // CompilationMemoryHistoryMark than we allocate. This cannot be since we - // assume arena allocations in CompilerThread to be stack bound and symmetric. - assert(delta >= 0 || ((ssize_t)_current + delta) >= 0, - "Negative overflow (d=%zd %zu %zu)", delta, _current, _peak); -#endif - // Update totals - _current += delta; - _current_by_tag.add(tag, delta); - // Did we reach a peak? - if (_current > _peak) { - _peak = _current; - assert(delta > 0, "Sanity (%zu %zu)", _current, _peak); - update_c2_node_count(); - _peak_by_tag = _current_by_tag; - rc = true; - // Did we hit the memory limit? - if (!_hit_limit && _limit > 0 && _peak > _limit) { - _hit_limit = true; +void ArenaCounterTable::print_on(outputStream* st) const { + bool header_printed = false; + for (int phase_trc_id = 0; phase_trc_id < phase_trc_id_max; phase_trc_id++) { + size_t sum = 0; + for (int arena_tag = 0; arena_tag < arena_tag_max; arena_tag++) { + sum += at(phase_trc_id, arena_tag); + } + if (sum > 0) { // omit phases that did not contribute to allocation load + if (!header_printed) { + st->print("%-24s %10s", "Phase", "Total"); + for (int arena_tag = 0; arena_tag < arena_tag_max; arena_tag++) { + st->print("%10s", Arena::tag_name[arena_tag]); + } + st->cr(); + header_printed = true; + } + st->print("%-24s ", phase_trc_id_to_string(phase_trc_id)); + st->print("%10zu", sum); + for (int arena_tag = 0; arena_tag < arena_tag_max; arena_tag++) { + const size_t v = at(phase_trc_id, arena_tag); + st->print("%10zu", v); + } + st->cr(); } } - return rc; } -void ArenaStatCounter::print_on(outputStream* st) const { - st->print("%zu [", _peak); - for (int tag = 0; tag < _peak_by_tag.element_count(); tag++) { - if (_peak_by_tag.counter(tag) > 0) { - st->print("%s %zu ", _peak_by_tag.tag_name(tag), _peak_by_tag.counter(tag)); +// When reporting phase footprint movements, if phase-local peak over start as well over end +// was larger than this threshold, we report it. +static constexpr size_t significant_peak_threshold = M; + +FootprintTimeline::FootprintTimeline() { + DEBUG_ONLY(_inbetween_phases = true;) +} + +void FootprintTimeline::copy_from(const FootprintTimeline& other) { + _fifo.copy_from(other._fifo); + DEBUG_ONLY(_inbetween_phases = other._inbetween_phases;) +} + +void FootprintTimeline::print_on(outputStream* st) const { + const int start_indent = st->indentation(); + if (!_fifo.empty()) { + // .123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789 + st->print_cr("Phase seq. number Bytes Nodes"); + unsigned from = 0; + if (_fifo.lost() > 0) { + st->print_cr(" (" UINT64_FORMAT " older entries lost)", _fifo.lost()); } + int last_level = 0; + int last_num = 0; // see if we are regressing + auto printer = [&](const Entry& e) { + int col = start_indent; + check_phase_trace_id(e.info.id); + st->print("%*s", e.level, + ((e.level < last_level) ? "<" : ((e.level > last_level) ? ">" : " ")) + ); + last_level = e.level; + st->print("%d ", e.info.num); + if (e.info.num < last_num) { + st->print("(cont.) "); + } + last_num = e.info.num; + col += 15; st->fill_to(col); + st->print("%24s", e.info.text); + col += 25; st->fill_to(col); + char tmp[64]; + os::snprintf(tmp, sizeof(tmp), "%9zu (%+zd)", e._bytes.cur, e._bytes.end_delta()); + st->print("%s ", tmp); // end + col += 21; st->fill_to(col); + os::snprintf(tmp, sizeof(tmp), "%6u (%+d)", e._live_nodes.cur, e._live_nodes.end_delta()); + st->print("%s ", tmp); // end + if (e._bytes.temporary_peak_size() > significant_peak_threshold) { + col += 20; st->fill_to(col); + st->print(" significant temporary peak: %zu (%+zd)", e._bytes.peak, (ssize_t)e._bytes.peak - e._bytes.start); // peak + } + st->cr(); + }; + _fifo.iterate_all(printer); } - st->print("]"); -#ifdef ASSERT - st->print(" (%zu->%zu)", _peak, _current); -#endif } -////////////////////////// -// Backend +void FootprintTimeline::on_phase_end(size_t cur_abs, unsigned cur_nodes) { + const Entry& old = _fifo.current(); -class FullMethodName { - Symbol* const _k; - Symbol* const _m; - Symbol* const _s; + // One last counter update in old phase: + // We see all allocations, so cur_abs given should correspond to our topmost cur. + // But the same does not hold for nodes, since we only get updated when node allocation + // would cause a new arena chunk to be born. Node allocations that don't cause arena + // chunks (the vast majority) fly by us. + assert(old._bytes.cur == cur_abs, "miscount"); + on_footprint_change(cur_abs, cur_nodes); -public: + // Close old, open new entry + _fifo.advance(); - FullMethodName(const Method* m) : - _k(m->klass_name()), _m(m->name()), _s(m->signature()) {}; - FullMethodName(const FullMethodName& o) : _k(o._k), _m(o._m), _s(o._s) {} + DEBUG_ONLY(_inbetween_phases = true;) +} - void make_permanent() { - _k->make_permanent(); - _m->make_permanent(); - _s->make_permanent(); +void FootprintTimeline::on_phase_start(PhaseInfo info, size_t cur_abs, unsigned cur_nodes, int level) { + if (!_fifo.empty() && _fifo.last().info.id == info.id && _fifo.last().level == level) { + // Two phases with the same id are collapsed if they were not interleaved by another phase + _fifo.revert(); + // We now just continue bookkeeping into the last entry + } else { + // seed current entry + Entry& e = _fifo.current(); + e._bytes.init(cur_abs); + e._live_nodes.init(cur_nodes); + e.info = info; + e.level = level; } + DEBUG_ONLY(_inbetween_phases = false;) +} + +FullMethodName::FullMethodName() : _k(nullptr), _m(nullptr), _s(nullptr) {} + +FullMethodName::FullMethodName(const Method* m) : + _k(m->klass_name()), _m(m->name()), _s(m->signature()) {}; - static unsigned compute_hash(const FullMethodName& n) { - return Symbol::compute_hash(n._k) ^ - Symbol::compute_hash(n._m) ^ - Symbol::compute_hash(n._s); +FullMethodName::FullMethodName(const FullMethodName& o) : _k(o._k), _m(o._m), _s(o._s) {} + +FullMethodName& FullMethodName::operator=(const FullMethodName& o) { + _k = o._k; _m = o._m; _s = o._s; + return *this; +} + +void FullMethodName::make_permanent() { + _k->make_permanent(); + _m->make_permanent(); + _s->make_permanent(); +} + +void FullMethodName::print_on(outputStream* st) const { + char tmp[1024]; + st->print_raw(_k->as_C_string(tmp, sizeof(tmp))); + st->print_raw("::"); + st->print_raw(_m->as_C_string(tmp, sizeof(tmp))); + st->put('('); + st->print_raw(_s->as_C_string(tmp, sizeof(tmp))); + st->put(')'); +} + +char* FullMethodName::as_C_string(char* buf, size_t len) const { + stringStream ss(buf, len); + print_on(&ss); + return buf; +} + +bool FullMethodName::operator== (const FullMethodName& b) const { + return _k == b._k && _m == b._m && _s == b._s; +} + +#ifdef ASSERT +bool FullMethodName::is_test_class() const { + char tmp[1024]; + _k->as_C_string(tmp, sizeof(tmp)); + return strstr(tmp, "CompileCommandPrintMemStat") != nullptr || + strstr(tmp, "CompileCommandMemLimit") != nullptr; +} +#endif // ASSERT + +ArenaStatCounter::ArenaStatCounter(const CompileTask* task, size_t limit) : + _fmn(task->method()), + _should_print_memstat(task->directive()->should_print_memstat()), + _should_crash_on_memlimit(task->directive()->should_crash_at_mem_limit()), + _current(0), _peak(0), _live_nodes_current(0), _live_nodes_at_global_peak(0), + _limit(limit), _hit_limit(false), _limit_in_process(false), + _phase_counter(0), _comp_type(task->compiler()->type()), _comp_id(task->compile_id()) + DEBUG_ONLY(COMMA _is_test_class(false)) +{ + _fmn.make_permanent(); +#ifdef ASSERT + // If the class name matches the JTreg test class, we are in test mode and + // will do some test allocations to test the statistic + _is_test_class = _fmn.is_test_class(); +#endif // ASSERT +} + +void ArenaStatCounter::on_phase_start(PhaseInfo info) { + // Update node counter + _live_nodes_current = retrieve_live_node_count(); + + // For the timeline, when nesting TracePhase happens, we maintain the illusion of a flat succession of + // separate phases. Thus, { TracePhase p1; { TracePhase p2; }} will be seen as: + // P1 starts -> P1 ends -> P2 starts -> P2 ends -> P1 starts -> P1 ends + // In other words, when a child phase interrupts a parent phase, it "ends" the parent phase, which will + // be "restarted" when the child phase ends. + // This is the only way to get a per-phase timeline that makes any sort of sense. + if (!_phase_info_stack.empty()) { + _timeline.on_phase_end(_current, _live_nodes_current); } + _phase_info_stack.push(info); + _timeline.on_phase_start(info, _current, _live_nodes_current, _phase_info_stack.depth()); +} - char* as_C_string(char* buf, size_t len) const { - stringStream ss(buf, len); - ResourceMark rm; - ss.print_raw(_k->as_C_string()); - ss.print_raw("::"); - ss.print_raw(_m->as_C_string()); - ss.put('('); - ss.print_raw(_s->as_C_string()); - ss.put(')'); - return buf; +void ArenaStatCounter::on_phase_end() { + PhaseInfo top = _phase_info_stack.top(); + _phase_info_stack.pop(); + _live_nodes_current = retrieve_live_node_count(); + _timeline.on_phase_end(_current, _live_nodes_current); + if (!_phase_info_stack.empty()) { + // "restart" parent phase in timeline + _timeline.on_phase_start(_phase_info_stack.top(), _current, _live_nodes_current, _phase_info_stack.depth()); } - bool operator== (const FullMethodName& b) const { - return _k == b._k && _m == b._m && _s == b._s; +} + +int ArenaStatCounter::retrieve_live_node_count() const { + int result = 0; +#ifdef COMPILER2 + if (_comp_type == compiler_c2) { + // Update C2 node count + // Careful, Compile::current() may be null in a short time window when Compile itself + // is still being constructed. + if (Compile::current() != nullptr) { + result = Compile::current()->live_nodes(); + } } -}; +#endif // COMPILER2 + return result; +} + +// Account an arena allocation. Returns true if new peak reached. +bool ArenaStatCounter::on_arena_chunk_allocation(size_t size, int arena_tag, uint64_t* stamp) { + bool rc = false; + + const size_t old_current = _current; + _current += size; + assert(_current >= old_current, "Overflow"); + + const int phase_trc_id = _phase_info_stack.top().id; + _counters_current.add(size, phase_trc_id, arena_tag); + _live_nodes_current = retrieve_live_node_count(); + + _timeline.on_footprint_change(_current, _live_nodes_current); + + // Did we reach a global peak? + if (_current > _peak) { + _peak = _current; + // snapshot all current counters + _counters_at_global_peak.copy_from(_counters_current); + // snapshot live nodes + _live_nodes_at_global_peak = _live_nodes_current; + // Did we hit the memory limit? + if (!_hit_limit && _limit > 0 && _peak > _limit) { + _hit_limit = true; + } + // report peak back + rc = true; + } + + // calculate arena chunk stamp + chunkstamp_t cs; + cs.tracked = 1; + cs.arena_tag = checked_cast<uint16_t>(arena_tag); + cs.phase_id = checked_cast<uint16_t>(_phase_info_stack.top().id); + *stamp = cs.raw; + + return rc; +} + +void ArenaStatCounter::on_arena_chunk_deallocation(size_t size, uint64_t stamp) { + assert(_current >= size, "Underflow (%zu %zu)", size, _current); + + // Extract tag and phase id from stamp + chunkstamp_t cs; + cs.raw = stamp; + assert(cs.tracked == 1, "Sanity"); + const int arena_tag = cs.arena_tag; + assert(arena_tag >= 0 && arena_tag < arena_tag_max, "Arena Tag OOB (%d)", arena_tag_max); + const int phase_trc_id(cs.phase_id); + assert(phase_trc_id >= 0 && phase_trc_id < phase_trc_id_max, "Phase trace id OOB (%d)", phase_trc_id); + + _current -= size; + _counters_current.sub(size, phase_trc_id, arena_tag); + _live_nodes_current = retrieve_live_node_count(); + _timeline.on_footprint_change(_current, _live_nodes_current); +} + +// Used for logging, not for the report table generated with jcmd Compiler.memory +void ArenaStatCounter::print_peak_state_on(outputStream* st) const { + st->print("Total Usage: %zu ", _peak); + if (_peak > 0) { +#ifdef COMPILER2 + // C1: print allocations broken down by arena types + if (_comp_type == CompilerType::compiler_c1) { + st->print("["); + size_t sums[arena_tag_max]; + _counters_at_global_peak.summarize(sums); + bool print_comma = false; + for (int i = 0; i < arena_tag_max; i++) { + if (sums[i] > 0) { + if (print_comma) { + st->print_raw(", "); + } + st->print("%s %zu", Arena::tag_name[i], sums[i]); + print_comma = true; + } + } + st->print_cr("]"); + } +#endif // COMPILER1 +#ifdef COMPILER2 + // C2: print counters and timeline on multiple lines, indented + if (_comp_type == CompilerType::compiler_c2) { + streamIndentor si(st, 4); + st->cr(); + st->print_cr("--- Arena Usage by Arena Type and compilation phase, at arena usage peak of %zu ---", _peak); + { + streamIndentor si(st, 4); + _counters_at_global_peak.print_on(st); + } + st->print_cr("--- Allocation timelime by phase ---"); + { + streamIndentor si(st, 4); + _timeline.print_on(st); + } + st->print_cr("---"); + } +#endif + } else { + st->cr(); + } +} + +class MemStatEntry : public CHeapObj<mtCompiler> { -// Note: not mtCompiler since we don't want to change what we measure -class MemStatEntry : public CHeapObj<mtInternal> { - const FullMethodName _method; - CompilerType _comptype; + FullMethodName _fmn; + CompilerType _comp_type; + int _comp_id; double _time; - // How often this has been recompiled. - int _num_recomp; // Compiling thread. Only for diagnostic purposes. Thread may not be alive anymore. const Thread* _thread; // active limit for this compilation, if any size_t _limit; - - // peak usage, bytes, over all arenas - size_t _total; - // usage per arena tag when total peaked - ArenaCountersByTag _peak_by_tag; - // number of nodes (c2 only) when total peaked - unsigned _live_nodes_at_peak; + // true if the compilation hit the limit + bool _hit_limit; + // result as reported by compiler const char* _result; + // Bytes total at global peak + size_t _peak; + // Bytes per arena tag. + size_t _peak_composition_per_arena_tag[arena_tag_max]; + // Number of live nodes at global peak (C2 only) + unsigned _live_nodes_at_global_peak; + + struct Details { + ArenaCounterTable counters_at_global_peak; + FootprintTimeline timeline; + }; + + Details* _detail_stats; + + MemStatEntry(const MemStatEntry& e); // deny + public: - MemStatEntry(FullMethodName method) - : _method(method), _comptype(compiler_c1), - _time(0), _num_recomp(0), _thread(nullptr), _limit(0), - _total(0), _live_nodes_at_peak(0), - _result(nullptr) { - _peak_by_tag.clear(); + MemStatEntry() + : _comp_type(compiler_none), _comp_id(-1), + _time(0), _thread(nullptr), _limit(0), _hit_limit(false), + _result(nullptr), _peak(0), _live_nodes_at_global_peak(0), + _detail_stats(nullptr) { } - void set_comptype(CompilerType comptype) { _comptype = comptype; } + ~MemStatEntry() { + clean_details(); + } + + void set_comp_id(int comp_id) { _comp_id = comp_id; } + void set_comptype(CompilerType comptype) { _comp_type = comptype; } void set_current_time() { _time = os::elapsedTime(); } void set_current_thread() { _thread = Thread::current(); } void set_limit(size_t limit) { _limit = limit; } - void inc_recompilation() { _num_recomp++; } - void set_total(size_t n) { _total = n; } - void set_peak_by_tag(ArenaCountersByTag peak_by_tag) { _peak_by_tag = peak_by_tag; } - void set_live_nodes_at_peak(unsigned n) { _live_nodes_at_peak = n; } + void set_from_state(const ArenaStatCounter* state, bool store_details) { + _fmn = state->fmn(); + _comp_type = state->comp_type(); + _comp_id = state->comp_id(); + _limit = state->limit(); + _hit_limit = state->hit_limit(); + _peak = state->peak(); + _live_nodes_at_global_peak = state->live_nodes_at_global_peak(); + state->counters_at_global_peak().summarize(_peak_composition_per_arena_tag); +#ifdef COMPILER2 + assert(_detail_stats == nullptr, "should have been cleaned"); + if (store_details) { + _detail_stats = NEW_C_HEAP_OBJ(Details, mtCompiler); + _detail_stats->counters_at_global_peak.copy_from(state->counters_at_global_peak()); + _detail_stats->timeline.copy_from(state->timeline()); + } +#endif // COMPILER2 + } - void set_result(const char* s) { _result = s; } + void clean_details() { + if (_detail_stats != nullptr) { + FREE_C_HEAP_ARRAY(Details, _detail_stats); + _detail_stats = nullptr; + } + } - size_t total() const { return _total; } + void reset() { + clean_details(); + _comp_type = CompilerType::compiler_none; + _comp_id = -1; + _limit = _peak = 0; + _live_nodes_at_global_peak = 0; + memset(_peak_composition_per_arena_tag, 0, sizeof(_peak_composition_per_arena_tag)); + } + + void set_result(const char* s) { _result = s; } + + size_t peak() const { return _peak; } + bool is_c1() const { return _comp_type == CompilerType::compiler_c1; } + bool is_c2() const { return _comp_type == CompilerType::compiler_c2; } static void print_legend(outputStream* st) { #define LEGEND_KEY_FMT "%11s" st->print_cr("Legend:"); - st->print_cr(" " LEGEND_KEY_FMT ": %s", "total", "memory allocated via arenas while compiling"); - for (int tag = 0; tag < Arena::tag_count(); tag++) { + st->print_cr(" " LEGEND_KEY_FMT ": %s", "ctype", "compiler type"); + st->print_cr(" " LEGEND_KEY_FMT ": %s", "total", "peak memory allocated via arenas while compiling"); + for (int tag = 0; tag < arena_tag_max; tag++) { st->print_cr(" " LEGEND_KEY_FMT ": %s", Arena::tag_name[tag], Arena::tag_desc[tag]); } - st->print_cr(" " LEGEND_KEY_FMT ": %s", "result", "Result: 'ok' finished successfully, 'oom' hit memory limit, 'err' compilation failed"); st->print_cr(" " LEGEND_KEY_FMT ": %s", "#nodes", "...how many nodes (c2 only)"); - st->print_cr(" " LEGEND_KEY_FMT ": %s", "limit", "memory limit, if set"); - st->print_cr(" " LEGEND_KEY_FMT ": %s", "time", "time taken for last compilation (sec)"); - st->print_cr(" " LEGEND_KEY_FMT ": %s", "type", "compiler type"); - st->print_cr(" " LEGEND_KEY_FMT ": %s", "#rc", "how often recompiled"); + st->print_cr(" " LEGEND_KEY_FMT ": %s", "result", "Result reported by compiler"); + st->print_cr(" " LEGEND_KEY_FMT ": %s", "limit", "memory limit; followed by \"*\" if the limit was hit"); + st->print_cr(" " LEGEND_KEY_FMT ": %s", "time", "timestamp"); + st->print_cr(" " LEGEND_KEY_FMT ": %s", "id", "compile id"); st->print_cr(" " LEGEND_KEY_FMT ": %s", "thread", "compiler thread"); #undef LEGEND_KEY_FMT } static void print_header(outputStream* st) { + st->print("%-6s", "ctyp"); + #define SIZE_FMT "%-10s" st->print(SIZE_FMT, "total"); - for (int tag = 0; tag < Arena::tag_count(); tag++) { + for (int tag = 0; tag < arena_tag_max; tag++) { st->print(SIZE_FMT, Arena::tag_name[tag]); } -#define HDR_FMT1 "%-8s%-8s%-8s%-8s" -#define HDR_FMT2 "%-6s%-4s%-19s%s" +#define HDR_FMT1 "%-8s%-8s%-10s%-8s" +#define HDR_FMT2 "%-6s%-19s%s" - st->print(HDR_FMT1, "result", "#nodes", "limit", "time"); - st->print(HDR_FMT2, "type", "#rc", "thread", "method"); - st->print_cr(""); + st->print(HDR_FMT1, "#nodes", "result", "limit", "time"); + st->print(HDR_FMT2, "id", "thread", "method"); } - void print_on(outputStream* st, bool human_readable) const { - int col = 0; + void print_brief_oneline(outputStream* st) const { + int col = st->indentation(); + + // Type + st->print("%2s ", compilertype2name(_comp_type)); + col += 6; st->fill_to(col); // Total - if (human_readable) { - st->print(PROPERFMT " ", PROPERFMTARGS(_total)); - } else { - st->print("%zu ", _total); - } + size_t v = _peak; + st->print("%zu ", v); col += 10; st->fill_to(col); - for (int tag = 0; tag < Arena::tag_count(); tag++) { - if (human_readable) { - st->print(PROPERFMT " ", PROPERFMTARGS(_peak_by_tag.counter(tag))); - } else { - st->print("%zu ", _peak_by_tag.counter(tag)); - } + for (int tag = 0; tag < arena_tag_max; tag++) { + v = _peak_composition_per_arena_tag[tag]; + st->print("%zu ", v); col += 10; st->fill_to(col); } - // result? - st->print("%s ", _result ? _result : ""); - col += 8; st->fill_to(col); - // Number of Nodes when memory peaked - if (_live_nodes_at_peak > 0) { - st->print("%u ", _live_nodes_at_peak); + if (_live_nodes_at_global_peak > 0) { + st->print("%u ", _live_nodes_at_global_peak); } else { st->print("-"); } col += 8; st->fill_to(col); + // result? + st->print("%s ", _result ? _result : ""); + col += 8; st->fill_to(col); + // Limit if (_limit > 0) { - st->print(PROPERFMT " ", PROPERFMTARGS(_limit)); + st->print("%zu%s ", _limit, _hit_limit ? "*" : ""); } else { st->print("-"); } - col += 8; st->fill_to(col); + col += 10; st->fill_to(col); // TimeStamp st->print("%.3f ", _time); col += 8; st->fill_to(col); - // Type - st->print("%s ", compilertype2name(_comptype)); + // Compile ID + st->print("%d ", _comp_id); col += 6; st->fill_to(col); - // Recomp - st->print("%u ", _num_recomp); - col += 4; st->fill_to(col); - // Thread st->print(PTR_FORMAT " ", p2i(_thread)); // MethodName char buf[1024]; - st->print("%s ", _method.as_C_string(buf, sizeof(buf))); + st->print("%s ", _fmn.as_C_string(buf, sizeof(buf))); + st->cr(); } - int compare_by_size(const MemStatEntry* b) const { - const size_t x1 = b->_total; - const size_t x2 = _total; - return x1 < x2 ? -1 : x1 == x2 ? 0 : 1; + void print_detailed(outputStream* st) const { + int col = 0; + + constexpr int indent1 = 40; + constexpr int indent2 = 50; + + char buf[1024]; + st->print_cr("Method : %s", _fmn.as_C_string(buf, sizeof(buf))); + st->print_cr("Compiler : %2s", compilertype2name(_comp_type)); + st->print( "Arena Usage at peak : %zu", _peak); + if (_peak > M) { + st->print(" (%.2fM)", ((double)_peak/(double)M)); + } + st->cr(); + if (_comp_type == CompilerType::compiler_c2) { + st->print_cr("Nodes at peak : %u", _live_nodes_at_global_peak); + } + st->print_cr("Compile ID : %d", _comp_id); + st->print( "Result : %s", _result); + if (strcmp(_result, "oom") == 0) { + st->print(" (memory limit was: %zu)", _limit); + } + st->cr(); + st->print_cr("Thread : " PTR_FORMAT, p2i(_thread)); + st->print_cr("Timestamp : %.3f", _time); + + if (_detail_stats != nullptr) { + st->cr(); + st->print_cr("Arena Usage by Arena Type and compilation phase, at arena usage peak of %zu:", _peak); + _detail_stats->counters_at_global_peak.print_on(st); + st->cr(); + st->print_cr("Allocation timelime by phase:"); + _detail_stats->timeline.print_on(st); + } else { + st->cr(); + st->print_cr("Arena Usage by Arena Type, at arena usage peak of %zu:", _peak); + for (int tag = 0; tag < arena_tag_max; tag++) { + const size_t v = _peak_composition_per_arena_tag[tag]; + if (v > 0) { + st->print_cr("%-36s: %zu ", Arena::tag_desc[tag], v); + } + } + } } }; -// The MemStatTable contains records of memory usage of all compilations. It is printed, -// as memory summary, either with jcmd Compiler.memory, or - if the "print" suboption has -// been given with the MemStat compile command - as summary printout at VM exit. -// For any given compiled method, we only keep the memory statistics of the most recent -// compilation, but on a per-compiler basis. If one needs statistics of prior compilations, -// one needs to look into the log produced by the "print" suboption. +class MemStatStore : public CHeapObj<mtCompiler> { -class MemStatTableKey { - const FullMethodName _fmn; - const CompilerType _comptype; -public: - MemStatTableKey(FullMethodName fmn, CompilerType comptype) : - _fmn(fmn), _comptype(comptype) {} - MemStatTableKey(const MemStatTableKey& o) : - _fmn(o._fmn), _comptype(o._comptype) {} - bool operator== (const MemStatTableKey& other) const { - return _fmn == other._fmn && _comptype == other._comptype; + // Total number of entries. Reaching this limit, we discard the least interesting (smallest allocation size) first. + static constexpr int max_entries = 64; + + struct { + size_t s; MemStatEntry* e; + } _entries[max_entries]; + + struct iteration_result { unsigned num, num_c1, num_c2, num_filtered_out; }; + template<typename F> + void iterate_sorted_filtered(F f, size_t minsize, int max_num_printed, iteration_result& result) const { + assert_lock_strong(NMTCompilationCostHistory_lock); + const unsigned stop_after = max_num_printed == -1 ? UINT_MAX : (unsigned)max_num_printed; + result.num = result.num_c1 = result.num_c2 = result.num_filtered_out = 0; + for (int i = 0; _entries[i].e != nullptr && i < max_entries && result.num < stop_after; i++) { + if (_entries[i].s >= minsize) { + f(_entries[i].e); + result.num++; + result.num_c1 += _entries[i].e->is_c1() ? 1 : 0; + result.num_c2 += _entries[i].e->is_c2() ? 1 : 0; + } else { + result.num_filtered_out++; + } + } } - static unsigned compute_hash(const MemStatTableKey& n) { - return FullMethodName::compute_hash(n._fmn) + (unsigned)n._comptype; + + void print_footer(outputStream* st, size_t minsize, const iteration_result& result) const { + if (result.num > 0) { + st->print_cr("Total: %u (C1: %u, C2: %u)", result.num, result.num_c1, result.num_c2); + } else { + st->print_cr("No entries."); + } + if (result.num_filtered_out > 0) { + st->print_cr(" (%d compilations smaller than %zu omitted)", result.num_filtered_out, minsize); + } } -}; -class MemStatTable : - public ResourceHashtable<MemStatTableKey, MemStatEntry*, 7919, AnyObj::C_HEAP, - mtInternal, MemStatTableKey::compute_hash> -{ public: - void add(const FullMethodName& fmn, CompilerType comptype, - size_t total, ArenaCountersByTag peak_by_tag, - unsigned live_nodes_at_peak, size_t limit, const char* result) { - assert_lock_strong(NMTCompilationCostHistory_lock); - MemStatTableKey key(fmn, comptype); - MemStatEntry** pe = get(key); - MemStatEntry* e = nullptr; - if (pe == nullptr) { - e = new MemStatEntry(fmn); - put(key, e); - } else { - // Update existing entry - e = *pe; - assert(e != nullptr, "Sanity"); + MemStatStore() { + memset(_entries, 0, sizeof(_entries)); + } + + void add(const ArenaStatCounter* state, const char* result) { + + const size_t size = state->peak(); + + // search insert point + int i = 0; + while (i < max_entries && _entries[i].s > size) { + i++; + } + if (i == max_entries) { + return; + } + MemStatEntry* e = _entries[max_entries - 1].e; // recycle last one + if (e == nullptr) { + e = new MemStatEntry(); } + memmove(_entries + i + 1, _entries + i, sizeof(_entries[0]) * (max_entries - i - 1)); + + e->reset(); e->set_current_time(); e->set_current_thread(); - e->set_comptype(comptype); - e->inc_recompilation(); - e->set_total(total); - e->set_peak_by_tag(peak_by_tag); - e->set_live_nodes_at_peak(live_nodes_at_peak); - e->set_limit(limit); e->set_result(result); + + // Since we don't have phases in C1, for now we just avoid saving details for C1. + const bool save_details = state->comp_type() == CompilerType::compiler_c2; + e->set_from_state(state, save_details); + + _entries[i].s = e->peak(); + _entries[i].e = e; } - // Returns a C-heap-allocated SortMe array containing all entries from the table, - // optionally filtered by entry size - MemStatEntry** calc_flat_array(int& num, size_t min_size) { + void print_table(outputStream* st, bool legend, size_t minsize, int max_num_printed) const { assert_lock_strong(NMTCompilationCostHistory_lock); - const int num_all = number_of_entries(); - MemStatEntry** flat = NEW_C_HEAP_ARRAY(MemStatEntry*, num_all, mtInternal); - int i = 0; - auto do_f = [&] (const MemStatTableKey& ignored, MemStatEntry* e) { - if (e->total() >= min_size) { - flat[i] = e; - assert(i < num_all, "Sanity"); - i ++; - } - }; - iterate_all(do_f); - if (min_size == 0) { - assert(i == num_all, "Sanity"); - } else { - assert(i <= num_all, "Sanity"); + if (legend) { + MemStatEntry::print_legend(st); + st->cr(); } - num = i; - return flat; + + MemStatEntry::print_header(st); + st->cr(); + + iteration_result itres; + auto printer = [&](const MemStatEntry* e) { + e->print_brief_oneline(st); + }; + iterate_sorted_filtered(printer, minsize, max_num_printed, itres); + print_footer(st, minsize, itres); + } + + void print_details(outputStream* st, size_t minsize, int max_num_printed) const { + assert_lock_strong(NMTCompilationCostHistory_lock); + iteration_result itres; + auto printer = [&](const MemStatEntry* e) { + e->print_detailed(st); + st->cr(); + st->print_cr("------------------------"); + st->cr(); + }; + iterate_sorted_filtered(printer, minsize, max_num_printed, itres); } }; bool CompilationMemoryStatistic::_enabled = false; - -static MemStatTable* _the_table = nullptr; +static MemStatStore* _the_store = nullptr; void CompilationMemoryStatistic::initialize() { - assert(_enabled == false && _the_table == nullptr, "Only once"); - _the_table = new (mtCompiler) MemStatTable; + assert(_enabled == false && _the_store == nullptr, "Only once"); + _the_store = new MemStatStore; _enabled = true; log_info(compilation, alloc)("Compilation memory statistic enabled"); } void CompilationMemoryStatistic::on_start_compilation(const DirectiveSet* directive) { assert(enabled(), "Not enabled?"); + assert(directive->should_collect_memstat(), "Don't call if not needed"); + CompilerThread* const th = Thread::current()->as_Compiler_thread(); + CompileTask* const task = th->task(); const size_t limit = directive->mem_limit(); - Thread::current()->as_Compiler_thread()->arena_stat()->start(limit); + // Create new ArenaStat object and hook it into the thread + assert(th->arena_stat() == nullptr, "Sanity"); + ArenaStatCounter* const arena_stat = new ArenaStatCounter(task, limit); + th->set_arenastat(arena_stat); + // Start a "root" phase + PhaseInfo info; + info.id = phase_trc_id_none; + info.num = 0; + info.text = "(outside)"; + arena_stat->on_phase_start(info); } void CompilationMemoryStatistic::on_end_compilation() { assert(enabled(), "Not enabled?"); - ResourceMark rm; CompilerThread* const th = Thread::current()->as_Compiler_thread(); ArenaStatCounter* const arena_stat = th->arena_stat(); + if (arena_stat == nullptr) { // not started + return; + } + + // Mark end of compilation by clearing out the arena state object in the CompilerThread. + // Do this before the final "phase end". + th->set_arenastat(nullptr); + + // End final outer phase. + arena_stat->on_phase_end(); + CompileTask* const task = th->task(); - const CompilerType ct = task->compiler()->type(); + assert(task->compile_id() == arena_stat->comp_id(), "Different compilation?"); const Method* const m = th->task()->method(); - FullMethodName fmn(m); - fmn.make_permanent(); const DirectiveSet* directive = th->task()->directive(); assert(directive->should_collect_memstat(), "Should only be called if memstat is enabled for this method"); @@ -438,7 +803,7 @@ void CompilationMemoryStatistic::on_end_compilation() { // Store memory used in task, for later processing by JFR task->set_arena_bytes(arena_stat->peak()); - // Store result + // Store result (ok, failed, oom...) // For this to work, we must call on_end_compilation() at a point where // Compile|Compilation already handed over the failure string to ciEnv, // but ciEnv must still be alive. @@ -453,24 +818,22 @@ void CompilationMemoryStatistic::on_end_compilation() { { MutexLocker ml(NMTCompilationCostHistory_lock, Mutex::_no_safepoint_check_flag); - assert(_the_table != nullptr, "not initialized"); - - _the_table->add(fmn, ct, - arena_stat->peak(), // total - arena_stat->peak_by_tag(), - arena_stat->live_nodes_at_peak(), - arena_stat->limit(), - result); + assert(_the_store != nullptr, "not initialized"); + _the_store->add(arena_stat, result); } + if (print) { - char buf[1024]; - fmn.as_C_string(buf, sizeof(buf)); - tty->print("%s Arena usage %s: ", compilertype2name(ct), buf); - arena_stat->print_on(tty); - tty->cr(); + // Pre-assemble string to prevent tearing + stringStream ss; + StreamAutoIndentor sai(&ss); + ss.print("%s (%d) (%s) Arena usage ", compilertype2name(arena_stat->comp_type()), arena_stat->comp_id(), result); + arena_stat->fmn().print_on(&ss); + ss.print_raw(": "); + arena_stat->print_peak_state_on(&ss); + tty->print_raw(ss.base()); } - arena_stat->end(); // reset things + delete arena_stat; } static void inform_compilation_about_oom(CompilerType ct) { @@ -508,124 +871,178 @@ static void inform_compilation_about_oom(CompilerType ct) { } } -void CompilationMemoryStatistic::on_arena_change(ssize_t diff, const Arena* arena) { +void CompilationMemoryStatistic::on_arena_chunk_allocation(size_t size, int arena_tag, uint64_t* stamp) { + assert(enabled(), "Not enabled?"); - CompilerThread* const th = Thread::current()->as_Compiler_thread(); + assert(arena_tag >= 0 && arena_tag < arena_tag_max, "Arena Tag OOB (%d)", arena_tag_max); + CompilerThread* const th = Thread::current()->as_Compiler_thread(); ArenaStatCounter* const arena_stat = th->arena_stat(); - if (arena_stat->limit_in_process()) { - return; // avoid recursion on limit hit + if (arena_stat == nullptr || // not started + arena_stat->limit_in_process()) { // limit handling in process, prevent recursion + return; } - bool hit_limit_before = arena_stat->hit_limit(); + // Compiler can be slow to bailout, so we may hit memlimit more than once + const bool hit_limit_before = arena_stat->hit_limit(); - if (arena_stat->is_active() && arena_stat->account(diff, (int)arena->get_tag())) { // new peak? + if (arena_stat->on_arena_chunk_allocation(size, arena_tag, stamp)) { // new peak? // Limit handling if (arena_stat->hit_limit()) { char name[1024] = ""; - bool print = false; - bool crash = false; - CompilerType ct = compiler_none; - + const CompilerType ct = arena_stat->comp_type(); + const bool print = arena_stat->should_print_memstat(); + const bool crash = arena_stat->should_crash_on_memlimit(); arena_stat->set_limit_in_process(true); // prevent recursive limit hits + arena_stat->fmn().as_C_string(name, sizeof(name)); + + inform_compilation_about_oom(ct); - // get some more info - const CompileTask* const task = th->task(); - if (task != nullptr) { - ct = task->compiler()->type(); - const DirectiveSet* directive = task->directive(); - print = directive->should_print_memstat(); - crash = directive->should_crash_at_mem_limit(); - const Method* m = th->task()->method(); - if (m != nullptr) { - FullMethodName(m).as_C_string(name, sizeof(name)); + if (crash) { + // Store this ArenaStat. If other threads also run into OOMs, let them sleep. + // We will never return, so the global store will not contain this info. We will + // print the stored ArenaStat in hs-err (see print_error_report) + if (Atomic::cmpxchg(&_arenastat_oom_crash, (ArenaStatCounter*) nullptr, arena_stat) != nullptr) { + os::infinite_sleep(); } } - char message[1024] = ""; + stringStream short_msg; - // build up message if we need it later + // We print to tty if either print is enabled or if we are to crash on MemLimit hit. + // If printing/crashing are not enabled, we just quietly abort the compilation. The + // compilation is marked as "oom" in the compilation memory result store. if (print || crash) { - stringStream ss(message, sizeof(message)); - if (ct != compiler_none && name[0] != '\0') { - ss.print("%s %s: ", compilertype2name(ct), name); - } - ss.print("Hit MemLimit %s(limit: %zu now: %zu)", + short_msg.print("%s (%d) %s: ", compilertype2name(ct), arena_stat->comp_id(), name); + short_msg.print("Hit MemLimit %s- limit: %zu now: %zu", (hit_limit_before ? "again " : ""), arena_stat->limit(), arena_stat->peak()); - } - - // log if needed - if (print) { - tty->print_raw(message); + tty->print_raw(short_msg.base()); tty->cr(); } - // Crash out if needed if (crash) { - report_fatal(OOM_HOTSPOT_ARENA, __FILE__, __LINE__, "%s", message); - } else { - inform_compilation_about_oom(ct); + // Before crashing, if C2, end current phase. That causes its info (which is the most important) to + // be added to the phase timeline. + if (arena_stat->comp_type() == CompilerType::compiler_c2) { + arena_stat->on_phase_end(); + } + // print extended message to tty (mirrors the one that should show up in the hs-err file, just for good measure) + tty->print_cr("Details:"); + arena_stat->print_peak_state_on(tty); + tty->cr(); + // abort VM + report_fatal(OOM_HOTSPOT_ARENA, __FILE__, __LINE__, "%s", short_msg.base()); } arena_stat->set_limit_in_process(false); - } + } // end Limit handling } } -static inline ssize_t diff_entries_by_size(const MemStatEntry* e1, const MemStatEntry* e2) { - return e1->compare_by_size(e2); -} - -void CompilationMemoryStatistic::print_all_by_size(outputStream* st, bool human_readable, size_t min_size) { +void CompilationMemoryStatistic::on_arena_chunk_deallocation(size_t size, uint64_t stamp) { + assert(enabled(), "Not enabled?"); + CompilerThread* const th = Thread::current()->as_Compiler_thread(); + ArenaStatCounter* const arena_stat = th->arena_stat(); + if (arena_stat == nullptr) { // not started + return; + } + if (arena_stat->limit_in_process()) { + return; // avoid recursion on limit hit + } - MutexLocker ml(NMTCompilationCostHistory_lock, Mutex::_no_safepoint_check_flag); + arena_stat->on_arena_chunk_deallocation(size, stamp); +} - st->cr(); - st->print_cr("Compilation memory statistics"); +void CompilationMemoryStatistic::on_phase_start(int phase_trc_id, const char* text) { + assert(enabled(), "Not enabled?"); + assert(phase_trc_id >= 0 && phase_trc_id < phase_trc_id_max, "Phase trace id OOB (%d)", phase_trc_id); + CompilerThread* const th = Thread::current()->as_Compiler_thread(); + ArenaStatCounter* const arena_stat = th->arena_stat(); + if (arena_stat == nullptr) { // not started + return; + } + PhaseInfo info; + info.id = phase_trc_id; + info.num = arena_stat->advance_phase_counter(); + info.text = text; + arena_stat->on_phase_start(info); +} - if (!enabled()) { - st->print_cr("(unavailable)"); +void CompilationMemoryStatistic::on_phase_end() { + assert(enabled(), "Not enabled?"); + CompilerThread* const th = Thread::current()->as_Compiler_thread(); + ArenaStatCounter* const arena_stat = th->arena_stat(); + if (arena_stat == nullptr) { // not started return; } + arena_stat->on_phase_end(); +} - st->cr(); +static bool check_before_reporting(outputStream* st) { + if (!CompilationMemoryStatistic::enabled()) { + st->print_cr("Compilation memory statistics disabled."); + return false; + } + if (_the_store == nullptr) { + st->print_cr("Compilation memory statistics not yet initialized. "); + return false; + } + return true; +} - MemStatEntry::print_legend(st); - st->cr(); +bool CompilationMemoryStatistic::in_oom_crash() { + return Atomic::load(&_arenastat_oom_crash) != nullptr; +} - if (min_size > 0) { - st->print_cr(" (cutoff: %zu bytes)", min_size); +void CompilationMemoryStatistic::print_error_report(outputStream* st) { + if (!check_before_reporting(st)) { + return; } - st->cr(); + StreamAutoIndentor sai(tty); + streamIndentor si(tty, 4); + const ArenaStatCounter* const oom_stats = Atomic::load(&_arenastat_oom_crash); + if (oom_stats != nullptr) { + // we crashed due to a compiler limit hit. Lead with a printout of the offending stats + // in detail. + st->print_cr("Compiler Memory Statistic, hit OOM limit; offending compilation:"); + oom_stats->fmn().print_on(st); + st->cr(); + oom_stats->print_peak_state_on(st); + st->cr(); + } + st->print_cr("Compiler Memory Statistic, 10 most expensive compilations:"); + print_all_by_size(st, false, false, 0, 10); +} - MemStatEntry::print_header(st); +void CompilationMemoryStatistic::print_final_report(outputStream* st) { + if (!check_before_reporting(st)) { + return; + } + st->print_cr("Compiler Memory Statistic, 10 most expensive compilations:"); + StreamAutoIndentor sai(st); + streamIndentor si(st, 4); + print_all_by_size(st, false, false, 0, 10); +} - MemStatEntry** filtered = nullptr; +void CompilationMemoryStatistic::print_jcmd_report(outputStream* st, bool verbose, bool legend, size_t minsize) { + if (!check_before_reporting(st)) { + return; + } + st->print_cr("Compiler Memory Statistic"); + StreamAutoIndentor sai(st); + streamIndentor si(st, 4); + print_all_by_size(st, verbose, legend, minsize, -1); +} - if (_the_table != nullptr) { - // We sort with quicksort - int num = 0; - filtered = _the_table->calc_flat_array(num, min_size); - if (min_size > 0) { - st->print_cr("(%d/%d)", num, _the_table->number_of_entries()); - } - if (num > 0) { - QuickSort::sort(filtered, num, diff_entries_by_size); - // Now print. Has to happen under lock protection too, since entries may be changed. - for (int i = 0; i < num; i ++) { - filtered[i]->print_on(st, human_readable); - } - } else { - st->print_cr("No entries."); - } +void CompilationMemoryStatistic::print_all_by_size(outputStream* st, bool verbose, bool legend, size_t minsize, int max_num_printed) { + MutexLocker ml(NMTCompilationCostHistory_lock, Mutex::_no_safepoint_check_flag); + if (verbose) { + _the_store->print_details(st, minsize, max_num_printed); } else { - st->print_cr("Not initialized."); + _the_store->print_table(st, legend, minsize, max_num_printed); } - st->cr(); - - FREE_C_HEAP_ARRAY(Entry, filtered); } const char* CompilationMemoryStatistic::failure_reason_memlimit() { @@ -633,12 +1050,50 @@ const char* CompilationMemoryStatistic::failure_reason_memlimit() { return s; } +#ifdef ASSERT +void CompilationMemoryStatistic::do_test_allocations() { + + CompilerThread* const th = Thread::current()->as_Compiler_thread(); + ArenaStatCounter* const arena_stat = th->arena_stat(); + if (arena_stat == nullptr || !arena_stat->is_test_class()) { // not started or not the JTREG test + return; + } + const CompilerType ctyp = th->task()->compiler()->type(); + + // Note: all allocations in here need to be tagged as mtCompiler to be recognized + // by the compilation memstat. ResourceArea in a CompilerThread is already tagged + // mtCompiler (special handling for compiler threads). + +#ifdef COMPILER2 + if (ctyp == CompilerType::compiler_c2) { + { + Compile::TracePhase tp(Phase::_t_testPhase1); + Arena ar(MemTag::mtCompiler, Arena::Tag::tag_reglive); + ar.Amalloc(2 * M); // phase-local peak + } + { + Compile::TracePhase tp(Phase::_t_testPhase2); + NEW_RESOURCE_ARRAY(char, 32 * M); // leaked (until compilation end) + } + } // C2 +#endif // COMPILER2 + +#ifdef COMPILER1 + if (ctyp == CompilerType::compiler_c1) { + NEW_RESOURCE_ARRAY(char, 32 * M); // leaked (until compilation end) + } +#endif // COMPILER2 + +} +#endif // ASSERT + CompilationMemoryStatisticMark::CompilationMemoryStatisticMark(const DirectiveSet* directive) : _active(directive->should_collect_memstat()) { if (_active) { CompilationMemoryStatistic::on_start_compilation(directive); } } + CompilationMemoryStatisticMark::~CompilationMemoryStatisticMark() { if (_active) { CompilationMemoryStatistic::on_end_compilation(); diff --git a/src/hotspot/share/compiler/compilationMemoryStatistic.hpp b/src/hotspot/share/compiler/compilationMemoryStatistic.hpp index d9cbfabde1b..2de5b0e9abb 100644 --- a/src/hotspot/share/compiler/compilationMemoryStatistic.hpp +++ b/src/hotspot/share/compiler/compilationMemoryStatistic.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2023, Red Hat, Inc. and/or its affiliates. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Red Hat, Inc. and/or its affiliates. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,114 +26,49 @@ #ifndef SHARE_COMPILER_COMPILATIONMEMORYSTATISTIC_HPP #define SHARE_COMPILER_COMPILATIONMEMORYSTATISTIC_HPP -#include "compiler/compilerDefinitions.hpp" #include "memory/allocation.hpp" #include "memory/allStatic.hpp" -#include "memory/arena.hpp" #include "utilities/globalDefinitions.hpp" -class outputStream; -class Symbol; class DirectiveSet; +class outputStream; -// Helper class to wrap the array of arena tags for easier processing -class ArenaCountersByTag { -private: - size_t _counter[Arena::tag_count()]; - -public: - int element_count() const { return Arena::tag_count(); } - const char* tag_name(int tag) const { return Arena::tag_name[tag]; } - - size_t counter(int tag) const { - assert(tag < element_count(), "invalid tag %d", tag); - return _counter[tag]; - } - - void add(int tag, size_t value) { - assert(tag < element_count(), "invalid tag %d", tag); - _counter[tag] += value; - } - - void clear() { - memset(_counter, 0, sizeof(size_t) * element_count()); - } -}; - -// Counters for allocations from arenas during compilation -class ArenaStatCounter : public CHeapObj<mtCompiler> { - // Current bytes, total - size_t _current; - // bytes at last peak, total - size_t _peak; - // Current bytes used by arenas per tag - ArenaCountersByTag _current_by_tag; - // Peak composition: - ArenaCountersByTag _peak_by_tag; - // MemLimit handling - size_t _limit; - bool _hit_limit; - bool _limit_in_process; - - // When to start accounting - bool _active; - - // Number of live nodes when total peaked (c2 only) - unsigned _live_nodes_at_peak; - - void update_c2_node_count(); - - void reset(); - -public: - ArenaStatCounter(); - - // Size of peak since last compilation - size_t peak() const { return _peak; } - - // Peak details - ArenaCountersByTag peak_by_tag() const { return _peak_by_tag; } - unsigned live_nodes_at_peak() const { return _live_nodes_at_peak; } - - // Mark the start and end of a compilation. - void start(size_t limit); - void end(); - - // Account an arena allocation or de-allocation. - // Returns true if new peak reached - bool account(ssize_t delta, int tag); +class CompilationMemoryStatistic : public AllStatic { + friend class CompilationMemoryStatisticMark; + static bool _enabled; // set to true if memstat is active for any method. - void set_live_nodes_at_peak(unsigned i) { _live_nodes_at_peak = i; } + // Private, should only be called via CompilationMemoryStatisticMark + static void on_start_compilation(const DirectiveSet* directive); - void print_on(outputStream* st) const; + // Private, should only be called via CompilationMemoryStatisticMark + static void on_end_compilation(); - size_t limit() const { return _limit; } - bool hit_limit() const { return _hit_limit; } - bool limit_in_process() const { return _limit_in_process; } - void set_limit_in_process(bool v) { _limit_in_process = v; } - bool is_active() const { return _active; } -}; + static void print_all_by_size(outputStream* st, bool verbose, bool legend, size_t minsize, int max_num_printed); -class CompilationMemoryStatistic : public AllStatic { - static bool _enabled; public: static void initialize(); // true if CollectMemStat or PrintMemStat has been enabled for any method static bool enabled() { return _enabled; } - static void on_start_compilation(const DirectiveSet* directive); + // true if we are in a fatal error inited by hitting the MemLimit + static bool in_oom_crash(); + + static void on_phase_start(int phase_trc_id, const char* text); + static void on_phase_end(); + static void on_arena_chunk_allocation(size_t size, int arenatag, uint64_t* stamp); + static void on_arena_chunk_deallocation(size_t size, uint64_t stamp); + + static void print_final_report(outputStream* st); + static void print_error_report(outputStream* st); + static void print_jcmd_report(outputStream* st, bool verbose, bool legend, size_t minsize); - // Called at end of compilation. Records the arena usage peak. Also takes over - // status information from ciEnv (compilation failed, oom'ed or went okay). ciEnv::_failure_reason - // must be set at this point (so place CompilationMemoryStatisticMark correctly). - static void on_end_compilation(); - static void on_arena_change(ssize_t diff, const Arena* arena); - static void print_all_by_size(outputStream* st, bool human_readable, size_t minsize); // For compilers static const char* failure_reason_memlimit(); + + DEBUG_ONLY(static void do_test_allocations();) }; // RAII object to wrap one compilation -class CompilationMemoryStatisticMark { +class CompilationMemoryStatisticMark : public StackObj { const bool _active; public: CompilationMemoryStatisticMark(const DirectiveSet* directive); diff --git a/src/hotspot/share/compiler/compilerOracle.cpp b/src/hotspot/share/compiler/compilerOracle.cpp index 8e296226fee..e7ef9703191 100644 --- a/src/hotspot/share/compiler/compilerOracle.cpp +++ b/src/hotspot/share/compiler/compilerOracle.cpp @@ -121,7 +121,6 @@ class TypedMethodOptionMatcher; static TypedMethodOptionMatcher* option_list = nullptr; static bool any_set = false; -static bool print_final_memstat_report = false; // A filter for quick lookup if an option is set static bool option_filter[static_cast<int>(CompileCommandEnum::Unknown) + 1] = { 0 }; @@ -482,10 +481,6 @@ bool CompilerOracle::should_collect_memstat() { return has_command(CompileCommandEnum::MemStat) || has_command(CompileCommandEnum::MemLimit); } -bool CompilerOracle::should_print_final_memstat_report() { - return print_final_memstat_report; -} - bool CompilerOracle::should_log(const methodHandle& method) { if (!LogCompilation) return false; if (!has_command(CompileCommandEnum::Log)) { @@ -711,7 +706,6 @@ static bool parseMemStat(const char* line, uintx& value, int& bytes_read, char* }); IF_ENUM_STRING("print", { value = (uintx)MemStatAction::print; - print_final_memstat_report = true; }); #undef IF_ENUM_STRING diff --git a/src/hotspot/share/compiler/compilerOracle.hpp b/src/hotspot/share/compiler/compilerOracle.hpp index 0e55ca416e0..943cd2c9734 100644 --- a/src/hotspot/share/compiler/compilerOracle.hpp +++ b/src/hotspot/share/compiler/compilerOracle.hpp @@ -166,7 +166,6 @@ class CompilerOracle : AllStatic { // Tells whether there are any methods to (collect|collect+print) memory statistics for static bool should_collect_memstat(); - static bool should_print_final_memstat_report(); // Tags the method as blackhole candidate, if possible. static void tag_blackhole_if_possible(const methodHandle& method); diff --git a/src/hotspot/share/compiler/compilerThread.cpp b/src/hotspot/share/compiler/compilerThread.cpp index a72fc48b9a1..55dd8383ac4 100644 --- a/src/hotspot/share/compiler/compilerThread.cpp +++ b/src/hotspot/share/compiler/compilerThread.cpp @@ -22,7 +22,6 @@ * */ -#include "compiler/compilationMemoryStatistic.hpp" #include "compiler/compileBroker.hpp" #include "compiler/compileTask.hpp" #include "compiler/compilerThread.hpp" @@ -40,7 +39,7 @@ CompilerThread::CompilerThread(CompileQueue* queue, _buffer_blob = nullptr; _can_call_java = false; _compiler = nullptr; - _arena_stat = CompilationMemoryStatistic::enabled() ? new ArenaStatCounter : nullptr; + _arena_stat = nullptr; #ifndef PRODUCT _ideal_graph_printer = nullptr; @@ -50,7 +49,8 @@ CompilerThread::CompilerThread(CompileQueue* queue, CompilerThread::~CompilerThread() { // Delete objects which were allocated on heap. delete _counters; - delete _arena_stat; + // arenastat should have been deleted at the end of the compilation + assert(_arena_stat == nullptr, "Should be null"); } void CompilerThread::set_compiler(AbstractCompiler* c) { diff --git a/src/hotspot/share/compiler/compilerThread.hpp b/src/hotspot/share/compiler/compilerThread.hpp index 3531fb6d72d..e20e3017d1f 100644 --- a/src/hotspot/share/compiler/compilerThread.hpp +++ b/src/hotspot/share/compiler/compilerThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, 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 @@ -85,6 +85,7 @@ class CompilerThread : public JavaThread { CompileQueue* queue() const { return _queue; } CompilerCounters* counters() const { return _counters; } ArenaStatCounter* arena_stat() const { return _arena_stat; } + void set_arenastat(ArenaStatCounter* v) { _arena_stat = v; } // Get/set the thread's compilation environment. ciEnv* env() { return _env; } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp index 2e48e438fc9..ce4738d784e 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp @@ -268,7 +268,7 @@ class G1ConcurrentRefine::RemSetSamplingClosure : public G1HeapRegionClosure { size_t sampled_code_root_rs_length() const { return _sampled_code_root_rs_length; } }; -// Adjust the target length (in regions) of the young gen, based on the the +// Adjust the target length (in regions) of the young gen, based on the // current length of the remembered sets. // // At the end of the GC G1 determines the length of the young gen based on diff --git a/src/hotspot/share/gc/g1/g1SurvRateGroup.cpp b/src/hotspot/share/gc/g1/g1SurvRateGroup.cpp index d5fd50c4523..f858b93b13d 100644 --- a/src/hotspot/share/gc/g1/g1SurvRateGroup.cpp +++ b/src/hotspot/share/gc/g1/g1SurvRateGroup.cpp @@ -68,26 +68,23 @@ void G1SurvRateGroup::stop_adding_regions() { _accum_surv_rate_pred = REALLOC_C_HEAP_ARRAY(double, _accum_surv_rate_pred, _num_added_regions, mtGC); _surv_rate_predictors = REALLOC_C_HEAP_ARRAY(TruncatedSeq*, _surv_rate_predictors, _num_added_regions, mtGC); - // Assume that the prediction for the newly added regions is the same as the - // ones at the (current) end of the array. Particularly predictions at the end - // of this array fairly seldom get updated, so having a better initial value - // that is at least somewhat related to the actual application is preferable. - double new_pred = _stats_arrays_length > 1 - ? _accum_surv_rate_pred[_stats_arrays_length - 1] - _accum_surv_rate_pred[_stats_arrays_length - 2] - : InitialSurvivorRate; - for (uint i = _stats_arrays_length; i < _num_added_regions; ++i) { // Initialize predictors and accumulated survivor rate predictions. _surv_rate_predictors[i] = new TruncatedSeq(10); if (i == 0) { _surv_rate_predictors[i]->add(InitialSurvivorRate); - _accum_surv_rate_pred[i] = 0.0; + _accum_surv_rate_pred[i] = InitialSurvivorRate; } else { - _surv_rate_predictors[i]->add(_surv_rate_predictors[i-1]->last()); - _accum_surv_rate_pred[i] = _accum_surv_rate_pred[i-1] + new_pred; + // Assume that the prediction for the newly added regions is the same as the + // ones at the (current) end of the array. Particularly predictions at the end + // of this array fairly seldom get updated, so having a better initial value + // that is at least somewhat related to the actual application is preferable. + double next_pred = _surv_rate_predictors[i-1]->last(); + _surv_rate_predictors[i]->add(next_pred); + _accum_surv_rate_pred[i] = _accum_surv_rate_pred[i-1] + next_pred; } } - _last_pred = new_pred; + _last_pred = _surv_rate_predictors[_num_added_regions-1]->last(); _stats_arrays_length = _num_added_regions; } diff --git a/src/hotspot/share/gc/shared/gcCause.hpp b/src/hotspot/share/gc/shared/gcCause.hpp index bd819e8f5c9..ef96bf21567 100644 --- a/src/hotspot/share/gc/shared/gcCause.hpp +++ b/src/hotspot/share/gc/shared/gcCause.hpp @@ -74,6 +74,7 @@ class GCCause : public AllStatic { _shenandoah_stop_vm, _shenandoah_allocation_failure_evac, + _shenandoah_humongous_allocation_failure, _shenandoah_concurrent_gc, _shenandoah_upgrade_to_full_gc, diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp index 7a624d4d4a4..5280e9b2ac4 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp @@ -241,6 +241,7 @@ bool ShenandoahAdaptiveHeuristics::should_start_gc() { ", allocated: %zu", available, capacity, allocated); if (_start_gc_is_pending) { + log_trigger("GC start is already pending"); return true; } diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp index 0393a2bb366..cf1a76ff4ff 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp @@ -60,7 +60,6 @@ int ShenandoahOldHeuristics::compare_by_index(RegionData a, RegionData b) { ShenandoahOldHeuristics::ShenandoahOldHeuristics(ShenandoahOldGeneration* generation, ShenandoahGenerationalHeap* gen_heap) : ShenandoahHeuristics(generation), _heap(gen_heap), - _old_gen(generation), _first_pinned_candidate(NOT_FOUND), _last_old_collection_candidate(0), _next_old_collection_candidate(0), @@ -567,9 +566,9 @@ void ShenandoahOldHeuristics::set_trigger_if_old_is_fragmented(size_t first_old_ // allocation request will require a STW full GC. size_t allowed_old_gen_span = num_regions - (ShenandoahGenerationalHumongousReserve * num_regions) / 100; - size_t old_available = _old_gen->available() / HeapWordSize; + size_t old_available = _old_generation->available() / HeapWordSize; size_t region_size_words = ShenandoahHeapRegion::region_size_words(); - size_t old_unaffiliated_available = _old_gen->free_unaffiliated_regions() * region_size_words; + size_t old_unaffiliated_available = _old_generation->free_unaffiliated_regions() * region_size_words; assert(old_available >= old_unaffiliated_available, "sanity"); size_t old_fragmented_available = old_available - old_unaffiliated_available; @@ -603,12 +602,12 @@ void ShenandoahOldHeuristics::set_trigger_if_old_is_fragmented(size_t first_old_ } void ShenandoahOldHeuristics::set_trigger_if_old_is_overgrown() { - size_t old_used = _old_gen->used() + _old_gen->get_humongous_waste(); - size_t trigger_threshold = _old_gen->usage_trigger_threshold(); + size_t old_used = _old_generation->used() + _old_generation->get_humongous_waste(); + size_t trigger_threshold = _old_generation->usage_trigger_threshold(); // Detects unsigned arithmetic underflow assert(old_used <= _heap->capacity(), "Old used (%zu, %zu) must not be more than heap capacity (%zu)", - _old_gen->used(), _old_gen->get_humongous_waste(), _heap->capacity()); + _old_generation->used(), _old_generation->get_humongous_waste(), _heap->capacity()); if (old_used > trigger_threshold) { _growth_trigger = true; } @@ -620,13 +619,32 @@ void ShenandoahOldHeuristics::evaluate_triggers(size_t first_old_region, size_t set_trigger_if_old_is_overgrown(); } +bool ShenandoahOldHeuristics::should_resume_old_cycle() { + // If we are preparing to mark old, or if we are already marking old, then try to continue that work. + if (_old_generation->is_concurrent_mark_in_progress()) { + assert(_old_generation->state() == ShenandoahOldGeneration::MARKING, "Unexpected old gen state: %s", _old_generation->state_name()); + log_trigger("Resume marking old"); + return true; + } + + if (_old_generation->is_preparing_for_mark()) { + assert(_old_generation->state() == ShenandoahOldGeneration::FILLING, "Unexpected old gen state: %s", _old_generation->state_name()); + log_trigger("Resume preparing to mark old"); + return true; + } + + return false; +} + bool ShenandoahOldHeuristics::should_start_gc() { - // Cannot start a new old-gen GC until previous one has finished. - // - // Future refinement: under certain circumstances, we might be more sophisticated about this choice. - // For example, we could choose to abandon the previous old collection before it has completed evacuations. - ShenandoahHeap* heap = ShenandoahHeap::heap(); - if (!_old_generation->can_start_gc() || heap->collection_set()->has_old_regions()) { + + const ShenandoahHeap* heap = ShenandoahHeap::heap(); + if (_old_generation->is_doing_mixed_evacuations()) { + // Do not try to start an old cycle if we are waiting for old regions to be evacuated (we need + // a young cycle for this). Note that the young heuristic has a feature to expedite old evacuations. + // Future refinement: under certain circumstances, we might be more sophisticated about this choice. + // For example, we could choose to abandon the previous old collection before it has completed evacuations. + log_debug(gc)("Not starting an old cycle because we are waiting for mixed evacuations"); return false; } diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp index d77380926b6..8d3fec746ba 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp @@ -53,7 +53,6 @@ class ShenandoahOldHeuristics : public ShenandoahHeuristics { static uint NOT_FOUND; ShenandoahGenerationalHeap* _heap; - ShenandoahOldGeneration* _old_gen; // After final marking of the old generation, this heuristic will select // a set of candidate regions to be included in subsequent mixed collections. @@ -186,6 +185,9 @@ class ShenandoahOldHeuristics : public ShenandoahHeuristics { bool should_start_gc() override; + // Returns true if the old generation needs to prepare for marking, or continue marking. + bool should_resume_old_cycle(); + void record_success_concurrent() override; void record_success_degenerated() override; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp index cd1949b19ad..d635781f90f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp @@ -29,6 +29,7 @@ #include "gc/shared/tlab_globals.hpp" #include "gc/shared/workerPolicy.hpp" #include "gc/shenandoah/shenandoahArguments.hpp" +#include "gc/shenandoah/shenandoahCardTable.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" @@ -187,6 +188,11 @@ void ShenandoahArguments::initialize() { FLAG_SET_DEFAULT(TLABAllocationWeight, 90); } + if (GCCardSizeInBytes < ShenandoahMinCardSizeInBytes) { + vm_exit_during_initialization( + err_msg("GCCardSizeInBytes ( %u ) must be >= %u\n", GCCardSizeInBytes, (unsigned int) ShenandoahMinCardSizeInBytes)); + } + FullGCForwarding::initialize_flags(MaxHeapSize); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp index 37470067ed9..17a89f631c6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp @@ -90,7 +90,7 @@ bool ShenandoahBarrierSet::need_keep_alive_barrier(DecoratorSet decorators, Basi void ShenandoahBarrierSet::on_slowpath_allocation_exit(JavaThread* thread, oop new_obj) { #if COMPILER2_OR_JVMCI assert(!ReduceInitialCardMarks || !ShenandoahCardBarrier || ShenandoahGenerationalHeap::heap()->is_in_young(new_obj), - "Error: losing card mark on initialzing store to old gen"); + "Allocating new object outside of young generation: " INTPTR_FORMAT, p2i(new_obj)); #endif // COMPILER2_OR_JVMCI assert(thread->deferred_card_mark().is_empty(), "We don't use this"); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCardTable.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCardTable.hpp index f30ce09668a..b012da09c7a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCardTable.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCardTable.hpp @@ -30,6 +30,8 @@ #include "oops/oopsHierarchy.hpp" #include "utilities/macros.hpp" +#define ShenandoahMinCardSizeInBytes 128 + class ShenandoahCardTable: public CardTable { friend class VMStructs; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp index 782db285c2a..0169795d6f6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp @@ -123,25 +123,28 @@ void ShenandoahCollectorPolicy::record_shutdown() { _in_shutdown.set(); } -bool ShenandoahCollectorPolicy::is_at_shutdown() { +bool ShenandoahCollectorPolicy::is_at_shutdown() const { return _in_shutdown.is_set(); } -bool is_explicit_gc(GCCause::Cause cause) { +bool ShenandoahCollectorPolicy::is_explicit_gc(GCCause::Cause cause) { return GCCause::is_user_requested_gc(cause) - || GCCause::is_serviceability_requested_gc(cause); + || GCCause::is_serviceability_requested_gc(cause) + || cause == GCCause::_wb_full_gc + || cause == GCCause::_wb_young_gc; } bool is_implicit_gc(GCCause::Cause cause) { return cause != GCCause::_no_gc && cause != GCCause::_shenandoah_concurrent_gc && cause != GCCause::_allocation_failure - && !is_explicit_gc(cause); + && !ShenandoahCollectorPolicy::is_explicit_gc(cause); } #ifdef ASSERT bool is_valid_request(GCCause::Cause cause) { - return is_explicit_gc(cause) + return ShenandoahCollectorPolicy::is_explicit_gc(cause) + || ShenandoahCollectorPolicy::is_shenandoah_gc(cause) || cause == GCCause::_metadata_GC_clear_soft_refs || cause == GCCause::_codecache_GC_aggressive || cause == GCCause::_codecache_GC_threshold @@ -153,6 +156,22 @@ bool is_valid_request(GCCause::Cause cause) { } #endif +bool ShenandoahCollectorPolicy::is_shenandoah_gc(GCCause::Cause cause) { + return cause == GCCause::_allocation_failure + || cause == GCCause::_shenandoah_stop_vm + || cause == GCCause::_shenandoah_allocation_failure_evac + || cause == GCCause::_shenandoah_humongous_allocation_failure + || cause == GCCause::_shenandoah_concurrent_gc + || cause == GCCause::_shenandoah_upgrade_to_full_gc; +} + + +bool ShenandoahCollectorPolicy::is_allocation_failure(GCCause::Cause cause) { + return cause == GCCause::_allocation_failure + || cause == GCCause::_shenandoah_allocation_failure_evac + || cause == GCCause::_shenandoah_humongous_allocation_failure; +} + bool ShenandoahCollectorPolicy::is_requested_gc(GCCause::Cause cause) { return is_explicit_gc(cause) || is_implicit_gc(cause); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.hpp index 2c92d91ac99..68579508de5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.hpp @@ -77,9 +77,9 @@ class ShenandoahCollectorPolicy : public CHeapObj<mtGC> { void record_collection_cause(GCCause::Cause cause); void record_shutdown(); - bool is_at_shutdown(); + bool is_at_shutdown() const; - ShenandoahTracer* tracer() {return _tracer;} + ShenandoahTracer* tracer() const {return _tracer;} void print_gc_stats(outputStream* out) const; @@ -90,15 +90,18 @@ class ShenandoahCollectorPolicy : public CHeapObj<mtGC> { // If the heuristics find that the number of consecutive degenerated cycles is above // ShenandoahFullGCThreshold, then they will initiate a Full GC upon an allocation // failure. - inline size_t consecutive_degenerated_gc_count() const { + size_t consecutive_degenerated_gc_count() const { return _consecutive_degenerated_gcs; } + static bool is_allocation_failure(GCCause::Cause cause); + static bool is_shenandoah_gc(GCCause::Cause cause); static bool is_requested_gc(GCCause::Cause cause); + static bool is_explicit_gc(GCCause::Cause cause); static bool should_run_full_gc(GCCause::Cause cause); static bool should_handle_requested_gc(GCCause::Cause cause); - inline size_t consecutive_young_gc_count() const { + size_t consecutive_young_gc_count() const { return _consecutive_young_gcs; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index beff760cdfe..49aa4b3610d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -241,6 +241,12 @@ bool ShenandoahConcurrentGC::collect(GCCause::Cause cause) { if (heap->mode()->is_generational()) { ShenandoahGenerationalHeap::heap()->complete_concurrent_cycle(); } + + // Instead of always resetting immediately before the start of a new GC, we can often reset at the end of the + // previous GC. This allows us to start the next GC cycle more quickly after a trigger condition is detected, + // reducing the likelihood that GC will degenerate. + entry_reset_after_collect(); + return true; } @@ -363,17 +369,6 @@ void ShenandoahConcurrentGC::entry_reset() { msg); op_reset(); } - - if (_do_old_gc_bootstrap) { - static const char* msg = "Concurrent reset (Old)"; - ShenandoahConcurrentPhase gc_phase(msg, ShenandoahPhaseTimings::conc_reset_old); - ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(), - ShenandoahWorkerPolicy::calc_workers_for_conc_reset(), - msg); - EventMark em("%s", msg); - - heap->old_generation()->prepare_gc(); - } } void ShenandoahConcurrentGC::entry_scan_remembered_set() { @@ -583,12 +578,29 @@ void ShenandoahConcurrentGC::entry_cleanup_complete() { op_cleanup_complete(); } +void ShenandoahConcurrentGC::entry_reset_after_collect() { + ShenandoahHeap* const heap = ShenandoahHeap::heap(); + TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters()); + const char* msg = conc_reset_after_collect_event_message(); + ShenandoahConcurrentPhase gc_phase(msg, ShenandoahPhaseTimings::conc_reset_after_collect); + EventMark em("%s", msg); + + op_reset_after_collect(); +} + void ShenandoahConcurrentGC::op_reset() { ShenandoahHeap* const heap = ShenandoahHeap::heap(); if (ShenandoahPacing) { heap->pacer()->setup_for_reset(); } - _generation->prepare_gc(); + // If it is old GC bootstrap cycle, always clear bitmap for global gen + // to ensure bitmap for old gen is clear for old GC cycle after this. + if (_do_old_gc_bootstrap) { + assert(!heap->is_prepare_for_old_mark_in_progress(), "Cannot reset old without making it parsable"); + heap->global_generation()->prepare_gc(); + } else { + _generation->prepare_gc(); + } } class ShenandoahInitMarkUpdateRegionStateClosure : public ShenandoahHeapRegionClosure { @@ -688,6 +700,11 @@ void ShenandoahConcurrentGC::op_init_mark() { if (ShenandoahPacing) { heap->pacer()->setup_for_mark(); } + + { + ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::init_propagate_gc_state); + heap->propagate_gc_state_to_all_threads(); + } } void ShenandoahConcurrentGC::op_mark_roots() { @@ -755,6 +772,11 @@ void ShenandoahConcurrentGC::op_final_mark() { } } } + + { + ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_mark_propagate_gc_state); + heap->propagate_gc_state_to_all_threads(); + } } bool ShenandoahConcurrentGC::has_in_place_promotions(ShenandoahHeap* heap) { @@ -1158,6 +1180,11 @@ void ShenandoahConcurrentGC::op_final_update_refs() { } heap->rebuild_free_set(true /*concurrent*/); + + { + ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_update_refs_propagate_gc_state); + heap->propagate_gc_state_to_all_threads(); + } } void ShenandoahConcurrentGC::op_final_roots() { @@ -1182,6 +1209,11 @@ void ShenandoahConcurrentGC::op_final_roots() { if (VerifyAfterGC) { Universe::verify(); } + + { + ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_roots_propagate_gc_state); + heap->propagate_gc_state_to_all_threads(); + } } void ShenandoahConcurrentGC::op_cleanup_complete() { @@ -1191,6 +1223,24 @@ void ShenandoahConcurrentGC::op_cleanup_complete() { ShenandoahHeap::heap()->recycle_trash(); } +void ShenandoahConcurrentGC::op_reset_after_collect() { + ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(), + ShenandoahWorkerPolicy::calc_workers_for_conc_reset(), + "reset after collection."); + + ShenandoahHeap* const heap = ShenandoahHeap::heap(); + if (heap->mode()->is_generational()) { + // If we are in the midst of an old gc bootstrap or an old marking, we want to leave the mark bit map of + // the young generation intact. In particular, reference processing in the old generation may potentially + // need the reachability of a young generation referent of a Reference object in the old generation. + if (!_do_old_gc_bootstrap && !heap->is_concurrent_old_mark_in_progress()) { + heap->young_generation()->reset_mark_bitmap<false>(); + } + } else { + _generation->reset_mark_bitmap<false>(); + } +} + bool ShenandoahConcurrentGC::check_cancellation_and_abort(ShenandoahDegenPoint point) { if (ShenandoahHeap::heap()->cancelled_gc()) { _degen_point = point; @@ -1240,6 +1290,14 @@ const char* ShenandoahConcurrentGC::conc_reset_event_message() const { } } +const char* ShenandoahConcurrentGC::conc_reset_after_collect_event_message() const { + if (ShenandoahHeap::heap()->unload_classes()) { + SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent reset after collect", " (unload classes)"); + } else { + SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent reset after collect", ""); + } +} + const char* ShenandoahConcurrentGC::final_roots_event_message() const { if (ShenandoahHeap::heap()->unload_classes()) { SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Pause Final Roots", " (unload classes)"); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp index b4c858bb245..81e7e943af3 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp @@ -118,10 +118,14 @@ class ShenandoahConcurrentGC : public ShenandoahGC { void op_final_update_refs(); void op_final_roots(); void op_cleanup_complete(); + void op_reset_after_collect(); // Check GC cancellation and abort concurrent GC bool check_cancellation_and_abort(ShenandoahDegenPoint point); + // Called when concurrent GC succeeds. + void entry_reset_after_collect(); + private: void start_mark(); @@ -134,6 +138,7 @@ class ShenandoahConcurrentGC : public ShenandoahGC { const char* final_roots_event_message() const; const char* conc_mark_event_message() const; const char* conc_reset_event_message() const; + const char* conc_reset_after_collect_event_message() const; const char* conc_weak_refs_event_message() const; const char* conc_weak_roots_event_message() const; const char* conc_cleanup_event_message() const; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp index 1ddfb6b7054..4848a69a6f3 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp @@ -50,7 +50,6 @@ ShenandoahControlThread::ShenandoahControlThread() : void ShenandoahControlThread::run_service() { ShenandoahHeap* const heap = ShenandoahHeap::heap(); - const GCMode default_mode = concurrent_normal; const GCCause::Cause default_cause = GCCause::_shenandoah_concurrent_gc; int sleep = ShenandoahControlIntervalMin; @@ -59,9 +58,14 @@ void ShenandoahControlThread::run_service() { ShenandoahCollectorPolicy* const policy = heap->shenandoah_policy(); ShenandoahHeuristics* const heuristics = heap->heuristics(); - while (!in_graceful_shutdown() && !should_terminate()) { + while (!should_terminate()) { + const GCCause::Cause cancelled_cause = heap->cancelled_cause(); + if (cancelled_cause == GCCause::_shenandoah_stop_vm) { + break; + } + // Figure out if we have pending requests. - const bool alloc_failure_pending = _alloc_failure_gc.is_set(); + const bool alloc_failure_pending = ShenandoahCollectorPolicy::is_allocation_failure(cancelled_cause); const bool is_gc_requested = _gc_requested.is_set(); const GCCause::Cause requested_gc_cause = _requested_gc_cause; @@ -254,11 +258,6 @@ void ShenandoahControlThread::run_service() { } os::naked_short_sleep(sleep); } - - // Wait for the actual stop(), can't leave run_service() earlier. - while (!should_terminate()) { - os::naked_short_sleep(ShenandoahControlIntervalMin); - } } void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cause) { @@ -322,19 +321,24 @@ void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cau bool ShenandoahControlThread::check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point) { ShenandoahHeap* heap = ShenandoahHeap::heap(); if (heap->cancelled_gc()) { - assert (is_alloc_failure_gc() || in_graceful_shutdown(), "Cancel GC either for alloc failure GC, or gracefully exiting"); - if (!in_graceful_shutdown()) { + if (heap->cancelled_cause() == GCCause::_shenandoah_stop_vm) { + return true; + } + + if (ShenandoahCollectorPolicy::is_allocation_failure(heap->cancelled_cause())) { assert (_degen_point == ShenandoahGC::_degenerated_outside_cycle, "Should not be set yet: %s", ShenandoahGC::degen_point_to_string(_degen_point)); _degen_point = point; + return true; } - return true; + + fatal("Unexpected reason for cancellation: %s", GCCause::to_string(heap->cancelled_cause())); } return false; } void ShenandoahControlThread::stop_service() { - // Nothing to do here. + ShenandoahHeap::heap()->cancel_gc(GCCause::_shenandoah_stop_vm); } void ShenandoahControlThread::service_stw_full_cycle(GCCause::Cause cause) { @@ -363,6 +367,11 @@ void ShenandoahControlThread::request_gc(GCCause::Cause cause) { } void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) { + if (should_terminate()) { + log_info(gc)("Control thread is terminating, no more GCs"); + return; + } + // For normal requested GCs (System.gc) we want to block the caller. However, // for whitebox requested GC, we want to initiate the GC and return immediately. // The whitebox caller thread will arrange for itself to wait until the GC notifies @@ -385,7 +394,7 @@ void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) { MonitorLocker ml(&_gc_waiters_lock); size_t current_gc_id = get_gc_id(); size_t required_gc_id = current_gc_id + 1; - while (current_gc_id < required_gc_id) { + while (current_gc_id < required_gc_id && !should_terminate()) { // Although setting gc request is under _gc_waiters_lock, but read side (run_service()) // does not take the lock. We need to enforce following order, so that read side sees // latest requested gc cause when the flag is set. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahController.cpp b/src/hotspot/share/gc/shenandoah/shenandoahController.cpp index a4d5a572349..c430981bfe6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahController.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahController.cpp @@ -25,6 +25,8 @@ #include "gc/shared/gc_globals.hpp" #include "gc/shenandoah/shenandoahController.hpp" + +#include "shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" @@ -37,14 +39,6 @@ size_t ShenandoahController::reset_allocs_seen() { return Atomic::xchg(&_allocs_seen, (size_t)0, memory_order_relaxed); } -void ShenandoahController::prepare_for_graceful_shutdown() { - _graceful_shutdown.set(); -} - -bool ShenandoahController::in_graceful_shutdown() { - return _graceful_shutdown.is_set(); -} - void ShenandoahController::update_gc_id() { Atomic::inc(&_gc_id); } @@ -53,59 +47,38 @@ size_t ShenandoahController::get_gc_id() { return Atomic::load(&_gc_id); } -void ShenandoahController::handle_alloc_failure(ShenandoahAllocRequest& req, bool block) { - ShenandoahHeap* heap = ShenandoahHeap::heap(); - +void ShenandoahController::handle_alloc_failure(const ShenandoahAllocRequest& req, bool block) { assert(current()->is_Java_thread(), "expect Java thread here"); - bool is_humongous = ShenandoahHeapRegion::requires_humongous(req.size()); - if (try_set_alloc_failure_gc(is_humongous)) { - // Only report the first allocation failure - log_info(gc)("Failed to allocate %s, %zu%s", - req.type_string(), - byte_size_in_proper_unit(req.size() * HeapWordSize), proper_unit_for_byte_size(req.size() * HeapWordSize)); + const bool is_humongous = ShenandoahHeapRegion::requires_humongous(req.size()); + const GCCause::Cause cause = is_humongous ? GCCause::_shenandoah_humongous_allocation_failure : GCCause::_allocation_failure; - // Now that alloc failure GC is scheduled, we can abort everything else - heap->cancel_gc(GCCause::_allocation_failure); + ShenandoahHeap* const heap = ShenandoahHeap::heap(); + if (heap->cancel_gc(cause)) { + log_info(gc)("Failed to allocate %s, " PROPERFMT, req.type_string(), PROPERFMTARGS(req.size() * HeapWordSize)); + request_gc(cause); } - if (block) { MonitorLocker ml(&_alloc_failure_waiters_lock); - while (is_alloc_failure_gc()) { + while (!should_terminate() && ShenandoahCollectorPolicy::is_allocation_failure(heap->cancelled_cause())) { ml.wait(); } } } void ShenandoahController::handle_alloc_failure_evac(size_t words) { - ShenandoahHeap* heap = ShenandoahHeap::heap(); - bool is_humongous = ShenandoahHeapRegion::requires_humongous(words); - if (try_set_alloc_failure_gc(is_humongous)) { - // Only report the first allocation failure - log_info(gc)("Failed to allocate %zu%s for evacuation", - byte_size_in_proper_unit(words * HeapWordSize), proper_unit_for_byte_size(words * HeapWordSize)); - } + ShenandoahHeap* const heap = ShenandoahHeap::heap(); + const bool is_humongous = ShenandoahHeapRegion::requires_humongous(words); + const GCCause::Cause cause = is_humongous ? GCCause::_shenandoah_humongous_allocation_failure : GCCause::_shenandoah_allocation_failure_evac; - // Forcefully report allocation failure - heap->cancel_gc(GCCause::_shenandoah_allocation_failure_evac); + if (heap->cancel_gc(cause)) { + log_info(gc)("Failed to allocate " PROPERFMT " for evacuation", PROPERFMTARGS(words * HeapWordSize)); + } } void ShenandoahController::notify_alloc_failure_waiters() { - _alloc_failure_gc.unset(); - _humongous_alloc_failure_gc.unset(); MonitorLocker ml(&_alloc_failure_waiters_lock); ml.notify_all(); } - -bool ShenandoahController::try_set_alloc_failure_gc(bool is_humongous) { - if (is_humongous) { - _humongous_alloc_failure_gc.try_set(); - } - return _alloc_failure_gc.try_set(); -} - -bool ShenandoahController::is_alloc_failure_gc() { - return _alloc_failure_gc.is_set(); -} diff --git a/src/hotspot/share/gc/shenandoah/shenandoahController.hpp b/src/hotspot/share/gc/shenandoah/shenandoahController.hpp index 6c28ff4e969..83cde94f509 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahController.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahController.hpp @@ -36,27 +36,25 @@ */ class ShenandoahController: public ConcurrentGCThread { private: - ShenandoahSharedFlag _graceful_shutdown; - shenandoah_padding(0); volatile size_t _allocs_seen; shenandoah_padding(1); + // A monotonically increasing GC count. volatile size_t _gc_id; shenandoah_padding(2); protected: - ShenandoahSharedFlag _alloc_failure_gc; - ShenandoahSharedFlag _humongous_alloc_failure_gc; - // While we could have a single lock for these, it may risk unblocking // GC waiters when alloc failure GC cycle finishes. We want instead // to make complete explicit cycle for demanding customers. Monitor _alloc_failure_waiters_lock; Monitor _gc_waiters_lock; + // Increments the internal GC count. + void update_gc_id(); + public: ShenandoahController(): - ConcurrentGCThread(), _allocs_seen(0), _gc_id(0), _alloc_failure_waiters_lock(Mutex::safepoint-2, "ShenandoahAllocFailureGC_lock", true), @@ -68,38 +66,25 @@ class ShenandoahController: public ConcurrentGCThread { virtual void request_gc(GCCause::Cause cause) = 0; // This cancels the collection cycle and has an option to block - // until another cycle runs and clears the alloc failure gc flag. - void handle_alloc_failure(ShenandoahAllocRequest& req, bool block); + // until another cycle completes successfully. + void handle_alloc_failure(const ShenandoahAllocRequest& req, bool block); // Invoked for allocation failures during evacuation. This cancels // the collection cycle without blocking. void handle_alloc_failure_evac(size_t words); - // Return true if setting the flag which indicates allocation failure succeeds. - bool try_set_alloc_failure_gc(bool is_humongous); - // Notify threads waiting for GC to complete. void notify_alloc_failure_waiters(); - // True if allocation failure flag has been set. - bool is_alloc_failure_gc(); - // This is called for every allocation. The control thread accumulates // this value when idle. During the gc cycle, the control resets it // and reports it to the pacer. void pacing_notify_alloc(size_t words); - size_t reset_allocs_seen(); - - // These essentially allows to cancel a collection cycle for the - // purpose of shutting down the JVM, without trying to start a degenerated - // cycle. - void prepare_for_graceful_shutdown(); - bool in_graceful_shutdown(); + // Zeros out the number of allocations seen since the last GC cycle. + size_t reset_allocs_seen(); - // Returns the internal gc count used by the control thread. Probably - // doesn't need to be exposed. + // Return the value of a monotonic increasing GC count, maintained by the control thread. size_t get_gc_id(); - void update_gc_id(); }; #endif // SHARE_GC_SHENANDOAH_SHENANDOAHCONTROLLER_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp index 17af519392e..4d250a98fe6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp @@ -49,7 +49,8 @@ ShenandoahDegenGC::ShenandoahDegenGC(ShenandoahDegenPoint degen_point, Shenandoa ShenandoahGC(), _degen_point(degen_point), _generation(generation), - _abbreviated(false) { + _abbreviated(false), + _consecutive_degen_with_bad_progress(0) { } bool ShenandoahDegenGC::collect(GCCause::Cause cause) { @@ -83,6 +84,10 @@ void ShenandoahDegenGC::entry_degenerated() { heap->set_degenerated_gc_in_progress(true); op_degenerated(); heap->set_degenerated_gc_in_progress(false); + { + ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::degen_gc_propagate_gc_state); + heap->propagate_gc_state_to_all_threads(); + } } void ShenandoahDegenGC::op_degenerated() { @@ -301,9 +306,24 @@ void ShenandoahDegenGC::op_degenerated() { metrics.snap_after(); - // Check for futility and fail. There is no reason to do several back-to-back Degenerated cycles, - // because that probably means the heap is overloaded and/or fragmented. + // The most common scenario for lack of good progress following a degenerated GC is an accumulation of floating + // garbage during the most recently aborted concurrent GC effort. With generational GC, it is far more effective to + // reclaim this floating garbage with another degenerated cycle (which focuses on young generation and might require + // a pause of 200 ms) rather than a full GC cycle (which may require over 2 seconds with a 10 GB old generation). + // + // In generational mode, we'll only upgrade to full GC if we've done two degen cycles in a row and both indicated + // bad progress. In non-generational mode, we'll preserve the original behavior, which is to upgrade to full + // immediately following a degenerated cycle with bad progress. This preserves original behavior of non-generational + // Shenandoah so as to avoid introducing "surprising new behavior." It also makes less sense with non-generational + // Shenandoah to replace a full GC with a degenerated GC, because both have similar pause times in non-generational + // mode. if (!metrics.is_good_progress(_generation)) { + _consecutive_degen_with_bad_progress++; + } else { + _consecutive_degen_with_bad_progress = 0; + } + if (!heap->mode()->is_generational() || + ((heap->shenandoah_policy()->consecutive_degenerated_gc_count() > 1) && (_consecutive_degen_with_bad_progress >= 2))) { heap->cancel_gc(GCCause::_shenandoah_upgrade_to_full_gc); op_degenerated_futile(); } else { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.hpp b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.hpp index 971bd67eb0d..a2598fe4e8e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.hpp @@ -36,6 +36,7 @@ class ShenandoahDegenGC : public ShenandoahGC { const ShenandoahDegenPoint _degen_point; ShenandoahGeneration* _generation; bool _abbreviated; + size_t _consecutive_degen_with_bad_progress; public: ShenandoahDegenGC(ShenandoahDegenPoint degen_point, ShenandoahGeneration* generation); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp index 5f8543ca751..91a71adbe1c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp @@ -130,6 +130,11 @@ void ShenandoahFullGC::op_full(GCCause::Cause cause) { // Regardless if progress was made, we record that we completed a "successful" full GC. heap->global_generation()->heuristics()->record_success_full(); heap->shenandoah_policy()->record_success_full(); + + { + ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::full_gc_propagate_gc_state); + heap->propagate_gc_state_to_all_threads(); + } } void ShenandoahFullGC::do_it(GCCause::Cause gc_cause) { @@ -192,16 +197,11 @@ void ShenandoahFullGC::do_it(GCCause::Cause gc_cause) { update_roots(true /*full_gc*/); } - // d. Reset the bitmaps for new marking - heap->global_generation()->reset_mark_bitmap(); - assert(heap->marking_context()->is_bitmap_clear(), "sanity"); - assert(!heap->global_generation()->is_mark_complete(), "sanity"); - - // e. Abandon reference discovery and clear all discovered references. + // d. Abandon reference discovery and clear all discovered references. ShenandoahReferenceProcessor* rp = heap->global_generation()->ref_processor(); rp->abandon_partial_discovery(); - // f. Sync pinned region status from the CP marks + // e. Sync pinned region status from the CP marks heap->sync_pinned_region_status(); if (heap->mode()->is_generational()) { @@ -282,30 +282,15 @@ void ShenandoahFullGC::do_it(GCCause::Cause gc_cause) { } } -class ShenandoahPrepareForMarkClosure: public ShenandoahHeapRegionClosure { -private: - ShenandoahMarkingContext* const _ctx; - -public: - ShenandoahPrepareForMarkClosure() : _ctx(ShenandoahHeap::heap()->marking_context()) {} - - void heap_region_do(ShenandoahHeapRegion *r) override { - _ctx->capture_top_at_mark_start(r); - r->clear_live_data(); - } - - bool is_thread_safe() override { return true; } -}; - void ShenandoahFullGC::phase1_mark_heap() { GCTraceTime(Info, gc, phases) time("Phase 1: Mark live objects", _gc_timer); ShenandoahGCPhase mark_phase(ShenandoahPhaseTimings::full_gc_mark); ShenandoahHeap* heap = ShenandoahHeap::heap(); - ShenandoahPrepareForMarkClosure prepare_for_mark; - ShenandoahExcludeRegionClosure<FREE> cl(&prepare_for_mark); - heap->parallel_heap_region_iterate(&cl); + heap->global_generation()->reset_mark_bitmap<true, true>(); + assert(heap->marking_context()->is_bitmap_clear(), "sanity"); + assert(!heap->global_generation()->is_mark_complete(), "sanity"); heap->set_unload_classes(heap->global_generation()->heuristics()->can_unload_classes()); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp index d00d5168ee7..a6f67b809d7 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp @@ -41,53 +41,44 @@ #include "utilities/quickSort.hpp" - -class ShenandoahResetUpdateRegionStateClosure : public ShenandoahHeapRegionClosure { +template <bool PREPARE_FOR_CURRENT_CYCLE, bool FULL_GC = false> +class ShenandoahResetBitmapClosure final : public ShenandoahHeapRegionClosure { private: - ShenandoahHeap* _heap; - ShenandoahMarkingContext* const _ctx; + ShenandoahHeap* _heap; + ShenandoahMarkingContext* _ctx; + public: - ShenandoahResetUpdateRegionStateClosure() : - _heap(ShenandoahHeap::heap()), - _ctx(_heap->marking_context()) {} + explicit ShenandoahResetBitmapClosure() : + ShenandoahHeapRegionClosure(), _heap(ShenandoahHeap::heap()), _ctx(_heap->marking_context()) {} - void heap_region_do(ShenandoahHeapRegion* r) override { - if (r->is_active()) { - // Reset live data and set TAMS optimistically. We would recheck these under the pause - // anyway to capture any updates that happened since now. - _ctx->capture_top_at_mark_start(r); - r->clear_live_data(); + void heap_region_do(ShenandoahHeapRegion* region) override { + assert(!_heap->is_uncommit_in_progress(), "Cannot uncommit bitmaps while resetting them."); + if (PREPARE_FOR_CURRENT_CYCLE) { + if (region->need_bitmap_reset() && _heap->is_bitmap_slice_committed(region)) { + _ctx->clear_bitmap(region); + } else { + region->set_needs_bitmap_reset(); + } + // Capture Top At Mark Start for this generation. + if (FULL_GC || region->is_active()) { + // Reset live data and set TAMS optimistically. We would recheck these under the pause + // anyway to capture any updates that happened since now. + _ctx->capture_top_at_mark_start(region); + region->clear_live_data(); + } + } else { + if (_heap->is_bitmap_slice_committed(region)) { + _ctx->clear_bitmap(region); + region->unset_needs_bitmap_reset(); + } else { + region->set_needs_bitmap_reset(); + } } } bool is_thread_safe() override { return true; } }; -class ShenandoahResetBitmapTask : public WorkerTask { -private: - ShenandoahRegionIterator _regions; - ShenandoahGeneration* _generation; - -public: - ShenandoahResetBitmapTask(ShenandoahGeneration* generation) : - WorkerTask("Shenandoah Reset Bitmap"), _generation(generation) {} - - void work(uint worker_id) { - ShenandoahHeap* heap = ShenandoahHeap::heap(); - assert(!heap->is_uncommit_in_progress(), "Cannot uncommit bitmaps while resetting them."); - ShenandoahHeapRegion* region = _regions.next(); - ShenandoahMarkingContext* const ctx = heap->marking_context(); - while (region != nullptr) { - auto const affiliation = region->affiliation(); - bool needs_reset = affiliation == FREE || _generation->contains(affiliation); - if (needs_reset && heap->is_bitmap_slice_committed(region)) { - ctx->clear_bitmap(region); - } - region = _regions.next(); - } - } -}; - // Copy the write-version of the card-table into the read-version, clearing the // write-copy. class ShenandoahMergeWriteTable: public ShenandoahHeapRegionClosure { @@ -225,15 +216,20 @@ void ShenandoahGeneration::log_status(const char *msg) const { PROPERFMTARGS(v_soft_max_capacity), PROPERFMTARGS(v_max_capacity), PROPERFMTARGS(v_available)); } +template <bool PREPARE_FOR_CURRENT_CYCLE, bool FULL_GC> void ShenandoahGeneration::reset_mark_bitmap() { ShenandoahHeap* heap = ShenandoahHeap::heap(); heap->assert_gc_workers(heap->workers()->active_workers()); set_mark_incomplete(); - ShenandoahResetBitmapTask task(this); - heap->workers()->run_task(&task); + ShenandoahResetBitmapClosure<PREPARE_FOR_CURRENT_CYCLE, FULL_GC> closure; + parallel_heap_region_iterate_free(&closure); } +// Explicit specializations +template void ShenandoahGeneration::reset_mark_bitmap<true, false>(); +template void ShenandoahGeneration::reset_mark_bitmap<true, true>(); +template void ShenandoahGeneration::reset_mark_bitmap<false, false>(); // The ideal is to swap the remembered set so the safepoint effort is no more than a few pointer manipulations. // However, limitations in the implementation of the mutator write-barrier make it difficult to simply change the @@ -265,12 +261,7 @@ void ShenandoahGeneration::merge_write_table() { } void ShenandoahGeneration::prepare_gc() { - - reset_mark_bitmap(); - - // Capture Top At Mark Start for this generation (typically young) and reset mark bitmap. - ShenandoahResetUpdateRegionStateClosure cl; - parallel_heap_region_iterate_free(&cl); + reset_mark_bitmap<true>(); } void ShenandoahGeneration::parallel_heap_region_iterate_free(ShenandoahHeapRegionClosure* cl) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp index 2f1102edbd7..1dc777777aa 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp @@ -159,6 +159,7 @@ class ShenandoahGeneration : public CHeapObj<mtGC>, public ShenandoahSpaceInfo { void log_status(const char* msg) const; // Used directly by FullGC + template <bool FOR_CURRENT_CYCLE, bool FULL_GC = false> void reset_mark_bitmap(); // Used by concurrent and degenerated GC to reset remembered set. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index db4b517a1f5..cabe51edc51 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -24,7 +24,6 @@ * */ -#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahConcurrentGC.hpp" @@ -45,294 +44,301 @@ #include "memory/metaspaceUtils.hpp" #include "memory/metaspaceStats.hpp" #include "runtime/atomic.hpp" +#include "utilities/events.hpp" ShenandoahGenerationalControlThread::ShenandoahGenerationalControlThread() : - ShenandoahController(), - _control_lock(Mutex::nosafepoint - 2, "ShenandoahControlGC_lock", true), - _regulator_lock(Mutex::nosafepoint - 2, "ShenandoahRegulatorGC_lock", true), + _control_lock(Mutex::nosafepoint - 2, "ShenandoahGCRequest_lock", true), _requested_gc_cause(GCCause::_no_gc), - _requested_generation(GLOBAL), - _degen_point(ShenandoahGC::_degenerated_outside_cycle), - _degen_generation(nullptr), - _mode(none) { + _requested_generation(nullptr), + _gc_mode(none), + _degen_point(ShenandoahGC::_degenerated_unset), + _heap(ShenandoahGenerationalHeap::heap()), + _age_period(0) { shenandoah_assert_generational(); set_name("Shenandoah Control Thread"); create_and_start(); } void ShenandoahGenerationalControlThread::run_service() { - ShenandoahGenerationalHeap* const heap = ShenandoahGenerationalHeap::heap(); - const GCMode default_mode = concurrent_normal; - ShenandoahGenerationType generation = GLOBAL; - - uint age_period = 0; + const int64_t wait_ms = ShenandoahPacing ? ShenandoahControlIntervalMin : 0; + ShenandoahGCRequest request; + while (!should_terminate()) { - ShenandoahCollectorPolicy* const policy = heap->shenandoah_policy(); + // This control loop iteration has seen this much allocation. + const size_t allocs_seen = reset_allocs_seen(); - // Heuristics are notified of allocation failures here and other outcomes - // of the cycle. They're also used here to control whether the Nth consecutive - // degenerated cycle should be 'promoted' to a full cycle. The decision to - // trigger a cycle or not is evaluated on the regulator thread. - ShenandoahHeuristics* global_heuristics = heap->global_generation()->heuristics(); - while (!in_graceful_shutdown() && !should_terminate()) { // Figure out if we have pending requests. - const bool alloc_failure_pending = _alloc_failure_gc.is_set(); - const bool humongous_alloc_failure_pending = _humongous_alloc_failure_gc.is_set(); + check_for_request(request); - GCCause::Cause cause = Atomic::xchg(&_requested_gc_cause, GCCause::_no_gc); + if (request.cause == GCCause::_shenandoah_stop_vm) { + break; + } - const bool is_gc_requested = ShenandoahCollectorPolicy::is_requested_gc(cause); + if (request.cause != GCCause::_no_gc) { + run_gc_cycle(request); + } else { + // Report to pacer that we have seen this many words allocated + if (ShenandoahPacing && (allocs_seen > 0)) { + _heap->pacer()->report_alloc(allocs_seen); + } + } - // This control loop iteration has seen this much allocation. - const size_t allocs_seen = reset_allocs_seen(); + // If the cycle was cancelled, continue the next iteration to deal with it. Otherwise, + // if there was no other cycle requested, cleanup and wait for the next request. + if (!_heap->cancelled_gc()) { + MonitorLocker ml(&_control_lock, Mutex::_no_safepoint_check_flag); + if (_requested_gc_cause == GCCause::_no_gc) { + set_gc_mode(ml, none); + ml.wait(wait_ms); + } + } + } - // Check if we have seen a new target for soft max heap size. - const bool soft_max_changed = heap->check_soft_max_changed(); + // In case any threads are waiting for a cycle to happen, notify them so they observe the shutdown. + notify_gc_waiters(); + notify_alloc_failure_waiters(); + set_gc_mode(stopped); +} - // Choose which GC mode to run in. The block below should select a single mode. - set_gc_mode(none); - ShenandoahGC::ShenandoahDegenPoint degen_point = ShenandoahGC::_degenerated_unset; +void ShenandoahGenerationalControlThread::stop_service() { + log_debug(gc, thread)("Stopping control thread"); + MonitorLocker ml(&_control_lock, Mutex::_no_safepoint_check_flag); + _heap->cancel_gc(GCCause::_shenandoah_stop_vm); + _requested_gc_cause = GCCause::_shenandoah_stop_vm; + notify_cancellation(ml, GCCause::_shenandoah_stop_vm); + // We can't wait here because it may interfere with the active cycle's ability + // to reach a safepoint (this runs on a java thread). +} - if (alloc_failure_pending) { - // Allocation failure takes precedence: we have to deal with it first thing - cause = GCCause::_allocation_failure; +void ShenandoahGenerationalControlThread::check_for_request(ShenandoahGCRequest& request) { + // Hold the lock while we read request cause and generation + MonitorLocker ml(&_control_lock, Mutex::_no_safepoint_check_flag); + if (_heap->cancelled_gc()) { + // The previous request was cancelled. Either it was cancelled for an allocation + // failure (degenerated cycle), or old marking was cancelled to run a young collection. + // In either case, the correct generation for the next cycle can be determined by + // the cancellation cause. + request.cause = _heap->cancelled_cause(); + if (request.cause == GCCause::_shenandoah_concurrent_gc) { + request.generation = _heap->young_generation(); + _heap->clear_cancelled_gc(false); + } + } else { + request.cause = _requested_gc_cause; + request.generation = _requested_generation; - // Consume the degen point, and seed it with default value - degen_point = _degen_point; - _degen_point = ShenandoahGC::_degenerated_outside_cycle; + // Only clear these if we made a request from them. In the case of a cancelled gc, + // we do not want to inadvertently lose this pending request. + _requested_gc_cause = GCCause::_no_gc; + _requested_generation = nullptr; + } - if (degen_point == ShenandoahGC::_degenerated_outside_cycle) { - _degen_generation = heap->young_generation(); - } else { - assert(_degen_generation != nullptr, "Need to know which generation to resume"); - } + if (request.cause == GCCause::_no_gc || request.cause == GCCause::_shenandoah_stop_vm) { + return; + } - ShenandoahHeuristics* heuristics = _degen_generation->heuristics(); - generation = _degen_generation->type(); - bool old_gen_evacuation_failed = heap->old_generation()->clear_failed_evacuation(); + GCMode mode; + if (ShenandoahCollectorPolicy::is_allocation_failure(request.cause)) { + mode = prepare_for_allocation_failure_gc(request); + } else if (ShenandoahCollectorPolicy::is_explicit_gc(request.cause)) { + mode = prepare_for_explicit_gc(request); + } else { + mode = prepare_for_concurrent_gc(request); + } + set_gc_mode(ml, mode); +} - heuristics->log_trigger("Handle Allocation Failure"); +ShenandoahGenerationalControlThread::GCMode ShenandoahGenerationalControlThread::prepare_for_allocation_failure_gc(ShenandoahGCRequest &request) { - // Do not bother with degenerated cycle if old generation evacuation failed or if humongous allocation failed - if (ShenandoahDegeneratedGC && heuristics->should_degenerate_cycle() && - !old_gen_evacuation_failed && !humongous_alloc_failure_pending) { - heuristics->record_allocation_failure_gc(); - policy->record_alloc_failure_to_degenerated(degen_point); - set_gc_mode(stw_degenerated); - } else { - heuristics->record_allocation_failure_gc(); - policy->record_alloc_failure_to_full(); - generation = GLOBAL; - set_gc_mode(stw_full); - } - } else if (is_gc_requested) { - generation = GLOBAL; - global_heuristics->log_trigger("GC request (%s)", GCCause::to_string(cause)); - global_heuristics->record_requested_gc(); + if (_degen_point == ShenandoahGC::_degenerated_unset) { + _degen_point = ShenandoahGC::_degenerated_outside_cycle; + request.generation = _heap->young_generation(); + } else if (request.generation->is_old()) { + // This means we degenerated during the young bootstrap for the old generation + // cycle. The following degenerated cycle should therefore also be young. + request.generation = _heap->young_generation(); + } - if (ShenandoahCollectorPolicy::should_run_full_gc(cause)) { - set_gc_mode(stw_full); - } else { - set_gc_mode(default_mode); - // Unload and clean up everything - heap->set_unload_classes(global_heuristics->can_unload_classes()); - } - } else { - // We should only be here if the regulator requested a cycle or if - // there is an old generation mark in progress. - if (cause == GCCause::_shenandoah_concurrent_gc) { - if (_requested_generation == OLD && heap->old_generation()->is_doing_mixed_evacuations()) { - // If a request to start an old cycle arrived while an old cycle was running, but _before_ - // it chose any regions for evacuation we don't want to start a new old cycle. Rather, we want - // the heuristic to run a young collection so that we can evacuate some old regions. - assert(!heap->is_concurrent_old_mark_in_progress(), "Should not be running mixed collections and concurrent marking"); - generation = YOUNG; - } else { - generation = _requested_generation; - } + ShenandoahHeuristics* heuristics = request.generation->heuristics(); + bool old_gen_evacuation_failed = _heap->old_generation()->clear_failed_evacuation(); - // preemption was requested or this is a regular cycle - set_gc_mode(default_mode); + heuristics->log_trigger("Handle Allocation Failure"); - // Don't start a new old marking if there is one already in progress - if (generation == OLD && heap->is_concurrent_old_mark_in_progress()) { - set_gc_mode(servicing_old); - } + // Do not bother with degenerated cycle if old generation evacuation failed or if humongous allocation failed + if (ShenandoahDegeneratedGC && heuristics->should_degenerate_cycle() && + !old_gen_evacuation_failed && request.cause != GCCause::_shenandoah_humongous_allocation_failure) { + heuristics->record_allocation_failure_gc(); + _heap->shenandoah_policy()->record_alloc_failure_to_degenerated(_degen_point); + return stw_degenerated; + } else { + heuristics->record_allocation_failure_gc(); + _heap->shenandoah_policy()->record_alloc_failure_to_full(); + request.generation = _heap->global_generation(); + return stw_full; + } +} - if (generation == GLOBAL) { - heap->set_unload_classes(global_heuristics->should_unload_classes()); - } else { - heap->set_unload_classes(false); - } - } else if (heap->is_concurrent_old_mark_in_progress() || heap->is_prepare_for_old_mark_in_progress()) { - // Nobody asked us to do anything, but we have an old-generation mark or old-generation preparation for - // mixed evacuation in progress, so resume working on that. - log_info(gc)("Resume old GC: marking is%s in progress, preparing is%s in progress", - heap->is_concurrent_old_mark_in_progress() ? "" : " NOT", - heap->is_prepare_for_old_mark_in_progress() ? "" : " NOT"); - - cause = GCCause::_shenandoah_concurrent_gc; - generation = OLD; - set_gc_mode(servicing_old); - heap->set_unload_classes(false); - } - } +ShenandoahGenerationalControlThread::GCMode ShenandoahGenerationalControlThread::prepare_for_explicit_gc(ShenandoahGCRequest &request) const { + ShenandoahHeuristics* global_heuristics = _heap->global_generation()->heuristics(); + request.generation = _heap->global_generation(); + global_heuristics->log_trigger("GC request (%s)", GCCause::to_string(request.cause)); + global_heuristics->record_requested_gc(); - const bool gc_requested = (gc_mode() != none); - assert (!gc_requested || cause != GCCause::_no_gc, "GC cause should be set"); + if (ShenandoahCollectorPolicy::should_run_full_gc(request.cause)) { + return stw_full;; + } else { + // Unload and clean up everything. Note that this is an _explicit_ request and so does not use + // the same `should_unload_classes` call as the regulator's concurrent gc request. + _heap->set_unload_classes(global_heuristics->can_unload_classes()); + return concurrent_normal; + } +} - if (gc_requested) { - // Cannot uncommit bitmap slices during concurrent reset - ShenandoahNoUncommitMark forbid_region_uncommit(heap); +ShenandoahGenerationalControlThread::GCMode ShenandoahGenerationalControlThread::prepare_for_concurrent_gc(const ShenandoahGCRequest &request) const { + assert(!(request.generation->is_old() && _heap->old_generation()->is_doing_mixed_evacuations()), + "Old heuristic should not request cycles while it waits for mixed evacuations"); - // Blow away all soft references on this cycle, if handling allocation failure, - // either implicit or explicit GC request, or we are requested to do so unconditionally. - if (generation == GLOBAL && (alloc_failure_pending || is_gc_requested || ShenandoahAlwaysClearSoftRefs)) { - heap->soft_ref_policy()->set_should_clear_all_soft_refs(true); - } + if (request.generation->is_global()) { + ShenandoahHeuristics* global_heuristics = _heap->global_generation()->heuristics(); + _heap->set_unload_classes(global_heuristics->should_unload_classes()); + } else { + _heap->set_unload_classes(false); + } - // GC is starting, bump the internal ID - update_gc_id(); - - heap->reset_bytes_allocated_since_gc_start(); - - MetaspaceCombinedStats meta_sizes = MetaspaceUtils::get_combined_statistics(); - - // If GC was requested, we are sampling the counters even without actual triggers - // from allocation machinery. This captures GC phases more accurately. - heap->set_forced_counters_update(true); - - // If GC was requested, we better dump freeset data for performance debugging - heap->free_set()->log_status_under_lock(); - - // In case this is a degenerated cycle, remember whether original cycle was aging. - const bool was_aging_cycle = heap->is_aging_cycle(); - heap->set_aging_cycle(false); - - switch (gc_mode()) { - case concurrent_normal: { - // At this point: - // if (generation == YOUNG), this is a normal YOUNG cycle - // if (generation == OLD), this is a bootstrap OLD cycle - // if (generation == GLOBAL), this is a GLOBAL cycle triggered by System.gc() - // In all three cases, we want to age old objects if this is an aging cycle - if (age_period-- == 0) { - heap->set_aging_cycle(true); - age_period = ShenandoahAgingCyclePeriod - 1; - } - service_concurrent_normal_cycle(heap, generation, cause); - break; - } - case stw_degenerated: { - heap->set_aging_cycle(was_aging_cycle); - service_stw_degenerated_cycle(cause, degen_point); - break; - } - case stw_full: { - if (age_period-- == 0) { - heap->set_aging_cycle(true); - age_period = ShenandoahAgingCyclePeriod - 1; - } - service_stw_full_cycle(cause); - break; - } - case servicing_old: { - assert(generation == OLD, "Expected old generation here"); - GCIdMark gc_id_mark; - service_concurrent_old_cycle(heap, cause); - break; - } - default: - ShouldNotReachHere(); - } + // preemption was requested or this is a regular cycle + return request.generation->is_old() ? servicing_old : concurrent_normal; +} - // If this was the requested GC cycle, notify waiters about it - if (is_gc_requested) { - notify_gc_waiters(); - } +void ShenandoahGenerationalControlThread::maybe_set_aging_cycle() { + if (_age_period-- == 0) { + _heap->set_aging_cycle(true); + _age_period = ShenandoahAgingCyclePeriod - 1; + } else { + _heap->set_aging_cycle(false); + } +} - // If this was the allocation failure GC cycle, notify waiters about it - if (alloc_failure_pending) { - notify_alloc_failure_waiters(); - } +void ShenandoahGenerationalControlThread::run_gc_cycle(const ShenandoahGCRequest& request) { - // Report current free set state at the end of cycle, whether - // it is a normal completion, or the abort. - heap->free_set()->log_status_under_lock(); + log_debug(gc, thread)("Starting GC (%s): %s, %s", gc_mode_name(gc_mode()), GCCause::to_string(request.cause), request.generation->name()); + assert(gc_mode() != none, "GC mode cannot be none here"); - // Notify Universe about new heap usage. This has implications for - // global soft refs policy, and we better report it every time heap - // usage goes down. - heap->update_capacity_and_used_at_gc(); + // Blow away all soft references on this cycle, if handling allocation failure, + // either implicit or explicit GC request, or we are requested to do so unconditionally. + if (request.generation->is_global() && (ShenandoahCollectorPolicy::is_allocation_failure(request.cause) || ShenandoahCollectorPolicy::is_explicit_gc(request.cause) || ShenandoahAlwaysClearSoftRefs)) { + _heap->soft_ref_policy()->set_should_clear_all_soft_refs(true); + } - // Signal that we have completed a visit to all live objects. - heap->record_whole_heap_examined_timestamp(); + // GC is starting, bump the internal ID + update_gc_id(); - // Disable forced counters update, and update counters one more time - // to capture the state at the end of GC session. - heap->handle_force_counters_update(); - heap->set_forced_counters_update(false); + _heap->reset_bytes_allocated_since_gc_start(); - // Retract forceful part of soft refs policy - heap->soft_ref_policy()->set_should_clear_all_soft_refs(false); + MetaspaceCombinedStats meta_sizes = MetaspaceUtils::get_combined_statistics(); - // Clear metaspace oom flag, if current cycle unloaded classes - if (heap->unload_classes()) { - global_heuristics->clear_metaspace_oom(); - } + // If GC was requested, we are sampling the counters even without actual triggers + // from allocation machinery. This captures GC phases more accurately. + _heap->set_forced_counters_update(true); - process_phase_timings(heap); + // If GC was requested, we better dump freeset data for performance debugging + _heap->free_set()->log_status_under_lock(); - // Print Metaspace change following GC (if logging is enabled). - MetaspaceUtils::print_metaspace_change(meta_sizes); + { + // Cannot uncommit bitmap slices during concurrent reset + ShenandoahNoUncommitMark forbid_region_uncommit(_heap); - // GC is over, we are at idle now - if (ShenandoahPacing) { - heap->pacer()->setup_for_idle(); + switch (gc_mode()) { + case concurrent_normal: { + service_concurrent_normal_cycle(request); + break; } - } else { - // Report to pacer that we have seen this many words allocated - if (ShenandoahPacing && (allocs_seen > 0)) { - heap->pacer()->report_alloc(allocs_seen); + case stw_degenerated: { + service_stw_degenerated_cycle(request); + break; } - } - - // Check if we have seen a new target for soft max heap size or if a gc was requested. - // Either of these conditions will attempt to uncommit regions. - if (ShenandoahUncommit) { - if (heap->check_soft_max_changed()) { - heap->notify_soft_max_changed(); - } else if (is_gc_requested) { - heap->notify_explicit_gc_requested(); + case stw_full: { + service_stw_full_cycle(request.cause); + break; + } + case servicing_old: { + assert(request.generation->is_old(), "Expected old generation here"); + GCIdMark gc_id_mark; + service_concurrent_old_cycle(request); + break; } + default: + ShouldNotReachHere(); } + } - // Wait for ShenandoahControlIntervalMax unless there was an allocation failure or another request was made mid-cycle. - if (!is_alloc_failure_gc() && _requested_gc_cause == GCCause::_no_gc) { - // The timed wait is necessary because this thread has a responsibility to send - // 'alloc_words' to the pacer when it does not perform a GC. - MonitorLocker lock(&_control_lock, Mutex::_no_safepoint_check_flag); - lock.wait(ShenandoahControlIntervalMax); - } + // If this was the requested GC cycle, notify waiters about it + if (ShenandoahCollectorPolicy::is_explicit_gc(request.cause)) { + notify_gc_waiters(); } - set_gc_mode(stopped); + // If this was an allocation failure GC cycle, notify waiters about it + if (ShenandoahCollectorPolicy::is_allocation_failure(request.cause)) { + notify_alloc_failure_waiters(); + } - // Wait for the actual stop(), can't leave run_service() earlier. - while (!should_terminate()) { - os::naked_short_sleep(ShenandoahControlIntervalMin); + // Report current free set state at the end of cycle, whether + // it is a normal completion, or the abort. + _heap->free_set()->log_status_under_lock(); + + // Notify Universe about new heap usage. This has implications for + // global soft refs policy, and we better report it every time heap + // usage goes down. + _heap->update_capacity_and_used_at_gc(); + + // Signal that we have completed a visit to all live objects. + _heap->record_whole_heap_examined_timestamp(); + + // Disable forced counters update, and update counters one more time + // to capture the state at the end of GC session. + _heap->handle_force_counters_update(); + _heap->set_forced_counters_update(false); + + // Retract forceful part of soft refs policy + _heap->soft_ref_policy()->set_should_clear_all_soft_refs(false); + + // Clear metaspace oom flag, if current cycle unloaded classes + if (_heap->unload_classes()) { + _heap->global_generation()->heuristics()->clear_metaspace_oom(); + } + + process_phase_timings(); + + // Print Metaspace change following GC (if logging is enabled). + MetaspaceUtils::print_metaspace_change(meta_sizes); + + // GC is over, we are at idle now + if (ShenandoahPacing) { + _heap->pacer()->setup_for_idle(); } + + // Check if we have seen a new target for soft max heap size or if a gc was requested. + // Either of these conditions will attempt to uncommit regions. + if (ShenandoahUncommit) { + if (_heap->check_soft_max_changed()) { + _heap->notify_soft_max_changed(); + } else if (ShenandoahCollectorPolicy::is_explicit_gc(request.cause)) { + _heap->notify_explicit_gc_requested(); + } + } + + log_debug(gc, thread)("Completed GC (%s): %s, %s, cancelled: %s", + gc_mode_name(gc_mode()), GCCause::to_string(request.cause), request.generation->name(), GCCause::to_string(_heap->cancelled_cause())); } -void ShenandoahGenerationalControlThread::process_phase_timings(const ShenandoahGenerationalHeap* heap) { +void ShenandoahGenerationalControlThread::process_phase_timings() const { // Commit worker statistics to cycle data - heap->phase_timings()->flush_par_workers_to_cycle(); + _heap->phase_timings()->flush_par_workers_to_cycle(); if (ShenandoahPacing) { - heap->pacer()->flush_stats_to_cycle(); + _heap->pacer()->flush_stats_to_cycle(); } - ShenandoahEvacuationTracker* evac_tracker = heap->evac_tracker(); + ShenandoahEvacuationTracker* evac_tracker = _heap->evac_tracker(); ShenandoahCycleStats evac_stats = evac_tracker->flush_cycle_to_global(); // Print GC stats for current cycle @@ -341,17 +347,17 @@ void ShenandoahGenerationalControlThread::process_phase_timings(const Shenandoah if (lt.is_enabled()) { ResourceMark rm; LogStream ls(lt); - heap->phase_timings()->print_cycle_on(&ls); + _heap->phase_timings()->print_cycle_on(&ls); evac_tracker->print_evacuations_on(&ls, &evac_stats.workers, &evac_stats.mutators); if (ShenandoahPacing) { - heap->pacer()->print_cycle_on(&ls); + _heap->pacer()->print_cycle_on(&ls); } } } // Commit statistics to globals - heap->phase_timings()->flush_cycle_to_global(); + _heap->phase_timings()->flush_cycle_to_global(); } // Young and old concurrent cycles are initiated by the regulator. Implicit @@ -379,46 +385,27 @@ void ShenandoahGenerationalControlThread::process_phase_timings(const Shenandoah // | v v | // +---> Global Degen +--------------------> Full <----+ // -void ShenandoahGenerationalControlThread::service_concurrent_normal_cycle(ShenandoahGenerationalHeap* heap, - const ShenandoahGenerationType generation, - GCCause::Cause cause) { +void ShenandoahGenerationalControlThread::service_concurrent_normal_cycle(const ShenandoahGCRequest& request) { GCIdMark gc_id_mark; - switch (generation) { - case YOUNG: { - // Run a young cycle. This might or might not, have interrupted an ongoing - // concurrent mark in the old generation. We need to think about promotions - // in this case. Promoted objects should be above the TAMS in the old regions - // they end up in, but we have to be sure we don't promote into any regions - // that are in the cset. - log_info(gc, ergo)("Start GC cycle (Young)"); - service_concurrent_cycle(heap->young_generation(), cause, false); - break; - } - case OLD: { - log_info(gc, ergo)("Start GC cycle (Old)"); - service_concurrent_old_cycle(heap, cause); - break; - } - case GLOBAL: { - log_info(gc, ergo)("Start GC cycle (Global)"); - service_concurrent_cycle(heap->global_generation(), cause, false); - break; - } - default: - ShouldNotReachHere(); + log_info(gc, ergo)("Start GC cycle (%s)", request.generation->name()); + if (request.generation->is_old()) { + service_concurrent_old_cycle(request); + } else { + service_concurrent_cycle(request.generation, request.cause, false); } } -void ShenandoahGenerationalControlThread::service_concurrent_old_cycle(ShenandoahGenerationalHeap* heap, GCCause::Cause &cause) { - ShenandoahOldGeneration* old_generation = heap->old_generation(); - ShenandoahYoungGeneration* young_generation = heap->young_generation(); +void ShenandoahGenerationalControlThread::service_concurrent_old_cycle(const ShenandoahGCRequest& request) { + ShenandoahOldGeneration* old_generation = _heap->old_generation(); + ShenandoahYoungGeneration* young_generation = _heap->young_generation(); ShenandoahOldGeneration::State original_state = old_generation->state(); - TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters()); + TraceCollectorStats tcs(_heap->monitoring_support()->concurrent_collection_counters()); switch (original_state) { case ShenandoahOldGeneration::FILLING: { - ShenandoahGCSession session(cause, old_generation); + ShenandoahGCSession session(request.cause, old_generation); + assert(gc_mode() == servicing_old, "Filling should be servicing old"); _allow_old_preemption.set(); old_generation->entry_coalesce_and_fill(); _allow_old_preemption.unset(); @@ -430,7 +417,7 @@ void ShenandoahGenerationalControlThread::service_concurrent_old_cycle(Shenandoa // acknowledge the cancellation request, the subsequent young cycle will observe // the request and essentially cancel itself. if (check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle)) { - log_info(gc)("Preparation for old generation cycle was cancelled"); + log_info(gc, thread)("Preparation for old generation cycle was cancelled"); return; } @@ -448,20 +435,16 @@ void ShenandoahGenerationalControlThread::service_concurrent_old_cycle(Shenandoa // task queues but it will not traverse them. set_gc_mode(bootstrapping_old); young_generation->set_old_gen_task_queues(old_generation->task_queues()); - ShenandoahGCSession session(cause, young_generation); - service_concurrent_cycle(heap, young_generation, cause, true); - process_phase_timings(heap); - if (heap->cancelled_gc()) { + service_concurrent_cycle(young_generation, request.cause, true); + process_phase_timings(); + if (_heap->cancelled_gc()) { // Young generation bootstrap cycle has failed. Concurrent mark for old generation // is going to resume after degenerated bootstrap cycle completes. log_info(gc)("Bootstrap cycle for old generation was cancelled"); return; } - // Reset the degenerated point. Normally this would happen at the top - // of the control loop, but here we have just completed a young cycle - // which has bootstrapped the old concurrent marking. - _degen_point = ShenandoahGC::_degenerated_outside_cycle; + assert(_degen_point == ShenandoahGC::_degenerated_unset, "Degen point should not be set if gc wasn't cancelled"); // From here we will 'resume' the old concurrent mark. This will skip reset // and init mark for the concurrent mark. All of that work will have been @@ -470,17 +453,17 @@ void ShenandoahGenerationalControlThread::service_concurrent_old_cycle(Shenandoa old_generation->transition_to(ShenandoahOldGeneration::MARKING); } case ShenandoahOldGeneration::MARKING: { - ShenandoahGCSession session(cause, old_generation); - bool marking_complete = resume_concurrent_old_cycle(old_generation, cause); + ShenandoahGCSession session(request.cause, old_generation); + bool marking_complete = resume_concurrent_old_cycle(old_generation, request.cause); if (marking_complete) { assert(old_generation->state() != ShenandoahOldGeneration::MARKING, "Should not still be marking"); if (original_state == ShenandoahOldGeneration::MARKING) { - heap->mmu_tracker()->record_old_marking_increment(true); - heap->log_heap_status("At end of Concurrent Old Marking finishing increment"); + _heap->mmu_tracker()->record_old_marking_increment(true); + _heap->log_heap_status("At end of Concurrent Old Marking finishing increment"); } } else if (original_state == ShenandoahOldGeneration::MARKING) { - heap->mmu_tracker()->record_old_marking_increment(false); - heap->log_heap_status("At end of Concurrent Old Marking increment"); + _heap->mmu_tracker()->record_old_marking_increment(false); + _heap->log_heap_status("At end of Concurrent Old Marking increment"); } break; } @@ -490,21 +473,19 @@ void ShenandoahGenerationalControlThread::service_concurrent_old_cycle(Shenandoa } bool ShenandoahGenerationalControlThread::resume_concurrent_old_cycle(ShenandoahOldGeneration* generation, GCCause::Cause cause) { - assert(ShenandoahHeap::heap()->is_concurrent_old_mark_in_progress(), "Old mark should be in progress"); + assert(_heap->is_concurrent_old_mark_in_progress(), "Old mark should be in progress"); log_debug(gc)("Resuming old generation with " UINT32_FORMAT " marking tasks queued", generation->task_queues()->tasks()); - ShenandoahHeap* heap = ShenandoahHeap::heap(); - // We can only tolerate being cancelled during concurrent marking or during preparation for mixed // evacuation. This flag here (passed by reference) is used to control precisely where the regulator // is allowed to cancel a GC. ShenandoahOldGC gc(generation, _allow_old_preemption); if (gc.collect(cause)) { - heap->notify_gc_progress(); + _heap->notify_gc_progress(); generation->record_success_concurrent(false); } - if (heap->cancelled_gc()) { + if (_heap->cancelled_gc()) { // It's possible the gc cycle was cancelled after the last time // the collection checked for cancellation. In which case, the // old gc cycle is still completed, and we have to deal with this @@ -515,89 +496,84 @@ bool ShenandoahGenerationalControlThread::resume_concurrent_old_cycle(Shenandoah // cycle, then we are not actually going to a degenerated cycle, // so the degenerated point doesn't matter here. check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle); - if (_requested_gc_cause == GCCause::_shenandoah_concurrent_gc) { - heap->shenandoah_policy()->record_interrupted_old(); + if (cause == GCCause::_shenandoah_concurrent_gc) { + _heap->shenandoah_policy()->record_interrupted_old(); } return false; } return true; } -void ShenandoahGenerationalControlThread::service_concurrent_cycle(ShenandoahGeneration* generation, GCCause::Cause cause, bool do_old_gc_bootstrap) { - // Normal cycle goes via all concurrent phases. If allocation failure (af) happens during - // any of the concurrent phases, it first degrades to Degenerated GC and completes GC there. - // If second allocation failure happens during Degenerated GC cycle (for example, when GC - // tries to evac something and no memory is available), cycle degrades to Full GC. - // - // There are also a shortcut through the normal cycle: immediate garbage shortcut, when - // heuristics says there are no regions to compact, and all the collection comes from immediately - // reclaimable regions. - // - // ................................................................................................ - // - // (immediate garbage shortcut) Concurrent GC - // /-------------------------------------------\ - // | | - // | | - // | | - // | v - // [START] ----> Conc Mark ----o----> Conc Evac --o--> Conc Update-Refs ---o----> [END] - // | | | ^ - // | (af) | (af) | (af) | - // ..................|....................|.................|..............|....................... - // | | | | - // | | | | Degenerated GC - // v v v | - // STW Mark ----------> STW Evac ----> STW Update-Refs ----->o - // | | | ^ - // | (af) | (af) | (af) | - // ..................|....................|.................|..............|....................... - // | | | | - // | v | | Full GC - // \------------------->o<----------------/ | - // | | - // v | - // Full GC --------------------------/ - // - if (check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle)) return; +// Normal cycle goes via all concurrent phases. If allocation failure (af) happens during +// any of the concurrent phases, it first degrades to Degenerated GC and completes GC there. +// If second allocation failure happens during Degenerated GC cycle (for example, when GC +// tries to evac something and no memory is available), cycle degrades to Full GC. +// +// There are also a shortcut through the normal cycle: immediate garbage shortcut, when +// heuristics says there are no regions to compact, and all the collection comes from immediately +// reclaimable regions. +// +// ................................................................................................ +// +// (immediate garbage shortcut) Concurrent GC +// /-------------------------------------------\ +// | | +// | | +// | | +// | v +// [START] ----> Conc Mark ----o----> Conc Evac --o--> Conc Update-Refs ---o----> [END] +// | | | ^ +// | (af) | (af) | (af) | +// ..................|....................|.................|..............|....................... +// | | | | +// | | | | Degenerated GC +// v v v | +// STW Mark ----------> STW Evac ----> STW Update-Refs ----->o +// | | | ^ +// | (af) | (af) | (af) | +// ..................|....................|.................|..............|....................... +// | | | | +// | v | | Full GC +// \------------------->o<----------------/ | +// | | +// v | +// Full GC --------------------------/ +// +void ShenandoahGenerationalControlThread::service_concurrent_cycle(ShenandoahGeneration* generation, + GCCause::Cause cause, + bool do_old_gc_bootstrap) { + // At this point: + // if (generation == YOUNG), this is a normal young cycle or a bootstrap cycle + // if (generation == GLOBAL), this is a GLOBAL cycle + // In either case, we want to age old objects if this is an aging cycle + maybe_set_aging_cycle(); - ShenandoahHeap* heap = ShenandoahHeap::heap(); ShenandoahGCSession session(cause, generation); - TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters()); - - service_concurrent_cycle(heap, generation, cause, do_old_gc_bootstrap); -} + TraceCollectorStats tcs(_heap->monitoring_support()->concurrent_collection_counters()); -void ShenandoahGenerationalControlThread::service_concurrent_cycle(ShenandoahHeap* heap, - ShenandoahGeneration* generation, - GCCause::Cause& cause, - bool do_old_gc_bootstrap) { assert(!generation->is_old(), "Old GC takes a different control path"); ShenandoahConcurrentGC gc(generation, do_old_gc_bootstrap); if (gc.collect(cause)) { // Cycle is complete - heap->notify_gc_progress(); + _heap->notify_gc_progress(); generation->record_success_concurrent(gc.abbreviated()); } else { - assert(heap->cancelled_gc(), "Must have been cancelled"); + assert(_heap->cancelled_gc(), "Must have been cancelled"); check_cancellation_or_degen(gc.degen_point()); - - // Concurrent young-gen collection degenerates to young - // collection. Same for global collections. - _degen_generation = generation; } + const char* msg; - ShenandoahMmuTracker* mmu_tracker = heap->mmu_tracker(); + ShenandoahMmuTracker* mmu_tracker = _heap->mmu_tracker(); if (generation->is_young()) { - if (heap->cancelled_gc()) { + if (_heap->cancelled_gc()) { msg = (do_old_gc_bootstrap) ? "At end of Interrupted Concurrent Bootstrap GC" : "At end of Interrupted Concurrent Young GC"; } else { // We only record GC results if GC was successful msg = (do_old_gc_bootstrap) ? "At end of Concurrent Bootstrap GC" : "At end of Concurrent Young GC"; - if (heap->collection_set()->has_old_regions()) { + if (_heap->collection_set()->has_old_regions()) { mmu_tracker->record_mixed(get_gc_id()); } else if (do_old_gc_bootstrap) { mmu_tracker->record_bootstrap(get_gc_id()); @@ -608,7 +584,7 @@ void ShenandoahGenerationalControlThread::service_concurrent_cycle(ShenandoahHea } else { assert(generation->is_global(), "If not young, must be GLOBAL"); assert(!do_old_gc_bootstrap, "Do not bootstrap with GLOBAL GC"); - if (heap->cancelled_gc()) { + if (_heap->cancelled_gc()) { msg = "At end of Interrupted Concurrent GLOBAL GC"; } else { // We only record GC results if GC was successful @@ -616,39 +592,27 @@ void ShenandoahGenerationalControlThread::service_concurrent_cycle(ShenandoahHea mmu_tracker->record_global(get_gc_id()); } } - heap->log_heap_status(msg); + _heap->log_heap_status(msg); } bool ShenandoahGenerationalControlThread::check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point) { - ShenandoahHeap* heap = ShenandoahHeap::heap(); - if (!heap->cancelled_gc()) { + if (!_heap->cancelled_gc()) { return false; } - if (in_graceful_shutdown()) { + if (_heap->cancelled_cause() == GCCause::_shenandoah_stop_vm + || _heap->cancelled_cause() == GCCause::_shenandoah_concurrent_gc) { + log_debug(gc, thread)("Cancellation detected, reason: %s", GCCause::to_string(_heap->cancelled_cause())); return true; } - assert(_degen_point == ShenandoahGC::_degenerated_outside_cycle, - "Should not be set yet: %s", ShenandoahGC::degen_point_to_string(_degen_point)); - - if (is_alloc_failure_gc()) { + if (ShenandoahCollectorPolicy::is_allocation_failure(_heap->cancelled_cause())) { + assert(_degen_point == ShenandoahGC::_degenerated_unset, + "Should not be set yet: %s", ShenandoahGC::degen_point_to_string(_degen_point)); _degen_point = point; - _preemption_requested.unset(); - return true; - } - - if (_preemption_requested.is_set()) { - assert(_requested_generation == YOUNG, "Only young GCs may preempt old."); - _preemption_requested.unset(); - - // Old generation marking is only cancellable during concurrent marking. - // Once final mark is complete, the code does not check again for cancellation. - // If old generation was cancelled for an allocation failure, we wouldn't - // make it to this case. The calling code is responsible for forcing a - // cancellation due to allocation failure into a degenerated cycle. - _degen_point = point; - heap->clear_cancelled_gc(false /* clear oom handler */); + log_debug(gc, thread)("Cancellation detected:, reason: %s, degen point: %s", + GCCause::to_string(_heap->cancelled_cause()), + ShenandoahGC::degen_point_to_string(_degen_point)); return true; } @@ -656,38 +620,32 @@ bool ShenandoahGenerationalControlThread::check_cancellation_or_degen(Shenandoah return false; } -void ShenandoahGenerationalControlThread::stop_service() { - // Nothing to do here. -} - void ShenandoahGenerationalControlThread::service_stw_full_cycle(GCCause::Cause cause) { - ShenandoahHeap* const heap = ShenandoahHeap::heap(); - GCIdMark gc_id_mark; - ShenandoahGCSession session(cause, heap->global_generation()); - + ShenandoahGCSession session(cause, _heap->global_generation()); + maybe_set_aging_cycle(); ShenandoahFullGC gc; gc.collect(cause); + _degen_point = ShenandoahGC::_degenerated_unset; } -void ShenandoahGenerationalControlThread::service_stw_degenerated_cycle(GCCause::Cause cause, - ShenandoahGC::ShenandoahDegenPoint point) { - assert(point != ShenandoahGC::_degenerated_unset, "Degenerated point should be set"); - ShenandoahHeap* const heap = ShenandoahHeap::heap(); +void ShenandoahGenerationalControlThread::service_stw_degenerated_cycle(const ShenandoahGCRequest& request) { + assert(_degen_point != ShenandoahGC::_degenerated_unset, "Degenerated point should be set"); GCIdMark gc_id_mark; - ShenandoahGCSession session(cause, _degen_generation); + ShenandoahGCSession session(request.cause, request.generation); - ShenandoahDegenGC gc(point, _degen_generation); - gc.collect(cause); + ShenandoahDegenGC gc(_degen_point, request.generation); + gc.collect(request.cause); + _degen_point = ShenandoahGC::_degenerated_unset; - assert(heap->young_generation()->task_queues()->is_empty(), "Unexpected young generation marking tasks"); - if (_degen_generation->is_global()) { - assert(heap->old_generation()->task_queues()->is_empty(), "Unexpected old generation marking tasks"); - assert(heap->global_generation()->task_queues()->is_empty(), "Unexpected global generation marking tasks"); + assert(_heap->young_generation()->task_queues()->is_empty(), "Unexpected young generation marking tasks"); + if (request.generation->is_global()) { + assert(_heap->old_generation()->task_queues()->is_empty(), "Unexpected old generation marking tasks"); + assert(_heap->global_generation()->task_queues()->is_empty(), "Unexpected global generation marking tasks"); } else { - assert(_degen_generation->is_young(), "Expected degenerated young cycle, if not global."); - ShenandoahOldGeneration* old = heap->old_generation(); + assert(request.generation->is_young(), "Expected degenerated young cycle, if not global."); + ShenandoahOldGeneration* old = _heap->old_generation(); if (old->is_bootstrapping()) { old->transition_to(ShenandoahOldGeneration::MARKING); } @@ -695,72 +653,87 @@ void ShenandoahGenerationalControlThread::service_stw_degenerated_cycle(GCCause: } void ShenandoahGenerationalControlThread::request_gc(GCCause::Cause cause) { - if (ShenandoahCollectorPolicy::should_handle_requested_gc(cause)) { + if (ShenandoahCollectorPolicy::is_allocation_failure(cause)) { + // GC should already be cancelled. Here we are just notifying the control thread to + // wake up and handle the cancellation request, so we don't need to set _requested_gc_cause. + notify_cancellation(cause); + } else if (ShenandoahCollectorPolicy::should_handle_requested_gc(cause)) { handle_requested_gc(cause); } } -bool ShenandoahGenerationalControlThread::request_concurrent_gc(ShenandoahGenerationType generation) { - if (_preemption_requested.is_set() || _requested_gc_cause != GCCause::_no_gc || ShenandoahHeap::heap()->cancelled_gc()) { +bool ShenandoahGenerationalControlThread::request_concurrent_gc(ShenandoahGeneration* generation) { + if (_heap->cancelled_gc()) { // Ignore subsequent requests from the heuristics - log_debug(gc, thread)("Reject request for concurrent gc: preemption_requested: %s, gc_requested: %s, gc_cancelled: %s", - BOOL_TO_STR(_preemption_requested.is_set()), + log_debug(gc, thread)("Reject request for concurrent gc: gc_requested: %s, gc_cancelled: %s", GCCause::to_string(_requested_gc_cause), - BOOL_TO_STR(ShenandoahHeap::heap()->cancelled_gc())); + BOOL_TO_STR(_heap->cancelled_gc())); return false; } - if (gc_mode() == none) { - GCCause::Cause existing = Atomic::cmpxchg(&_requested_gc_cause, GCCause::_no_gc, GCCause::_shenandoah_concurrent_gc); - if (existing != GCCause::_no_gc) { - log_debug(gc, thread)("Reject request for concurrent gc because another gc is pending: %s", GCCause::to_string(existing)); + MonitorLocker ml(&_control_lock, Mutex::_no_safepoint_check_flag); + if (gc_mode() == servicing_old) { + if (!preempt_old_marking(generation)) { + log_debug(gc, thread)("Cannot start young, old collection is not preemptible"); return false; } - _requested_generation = generation; - notify_control_thread(); - - MonitorLocker ml(&_regulator_lock, Mutex::_no_safepoint_check_flag); - while (gc_mode() == none) { + // Cancel the old GC and wait for the control thread to start servicing the new request. + log_info(gc)("Preempting old generation mark to allow %s GC", generation->name()); + while (gc_mode() == servicing_old) { + ShenandoahHeap::heap()->cancel_gc(GCCause::_shenandoah_concurrent_gc); + notify_cancellation(ml, GCCause::_shenandoah_concurrent_gc); ml.wait(); } return true; } - if (preempt_old_marking(generation)) { - assert(gc_mode() == servicing_old, "Expected to be servicing old, but was: %s.", gc_mode_name(gc_mode())); - GCCause::Cause existing = Atomic::cmpxchg(&_requested_gc_cause, GCCause::_no_gc, GCCause::_shenandoah_concurrent_gc); - if (existing != GCCause::_no_gc) { - log_debug(gc, thread)("Reject request to interrupt old gc because another gc is pending: %s", GCCause::to_string(existing)); - return false; - } - - log_info(gc)("Preempting old generation mark to allow %s GC", shenandoah_generation_name(generation)); - _requested_generation = generation; - _preemption_requested.set(); - ShenandoahHeap::heap()->cancel_gc(GCCause::_shenandoah_concurrent_gc); - notify_control_thread(); + if (gc_mode() == none) { + while (gc_mode() == none) { + if (_requested_gc_cause != GCCause::_no_gc) { + log_debug(gc, thread)("Reject request for concurrent gc because another gc is pending: %s", GCCause::to_string(_requested_gc_cause)); + return false; + } - MonitorLocker ml(&_regulator_lock, Mutex::_no_safepoint_check_flag); - while (gc_mode() == servicing_old) { + notify_control_thread(ml, GCCause::_shenandoah_concurrent_gc, generation); ml.wait(); } return true; } + log_debug(gc, thread)("Reject request for concurrent gc: mode: %s, allow_old_preemption: %s", gc_mode_name(gc_mode()), BOOL_TO_STR(_allow_old_preemption.is_set())); return false; } -void ShenandoahGenerationalControlThread::notify_control_thread() { - MonitorLocker locker(&_control_lock, Mutex::_no_safepoint_check_flag); - _control_lock.notify(); +void ShenandoahGenerationalControlThread::notify_control_thread(GCCause::Cause cause, ShenandoahGeneration* generation) { + MonitorLocker ml(&_control_lock, Mutex::_no_safepoint_check_flag); + notify_control_thread(ml, cause, generation); +} + +void ShenandoahGenerationalControlThread::notify_control_thread(MonitorLocker& ml, GCCause::Cause cause, ShenandoahGeneration* generation) { + assert(_control_lock.is_locked(), "Request lock must be held here"); + log_debug(gc, thread)("Notify control (%s): %s, %s", gc_mode_name(gc_mode()), GCCause::to_string(cause), generation->name()); + _requested_gc_cause = cause; + _requested_generation = generation; + ml.notify(); +} + +void ShenandoahGenerationalControlThread::notify_cancellation(GCCause::Cause cause) { + MonitorLocker ml(&_control_lock, Mutex::_no_safepoint_check_flag); + notify_cancellation(ml, cause); +} + +void ShenandoahGenerationalControlThread::notify_cancellation(MonitorLocker& ml, GCCause::Cause cause) { + assert(_heap->cancelled_gc(), "GC should already be cancelled"); + log_debug(gc,thread)("Notify control (%s): %s", gc_mode_name(gc_mode()), GCCause::to_string(cause)); + ml.notify(); } -bool ShenandoahGenerationalControlThread::preempt_old_marking(ShenandoahGenerationType generation) { - return (generation == YOUNG) && _allow_old_preemption.try_unset(); +bool ShenandoahGenerationalControlThread::preempt_old_marking(ShenandoahGeneration* generation) { + return generation->is_young() && _allow_old_preemption.try_unset(); } void ShenandoahGenerationalControlThread::handle_requested_gc(GCCause::Cause cause) { @@ -769,8 +742,7 @@ void ShenandoahGenerationalControlThread::handle_requested_gc(GCCause::Cause cau // The whitebox caller thread will arrange for itself to wait until the GC notifies // it that has reached the requested breakpoint (phase in the GC). if (cause == GCCause::_wb_breakpoint) { - Atomic::xchg(&_requested_gc_cause, cause); - notify_control_thread(); + notify_control_thread(cause, ShenandoahHeap::heap()->global_generation()); return; } @@ -785,17 +757,10 @@ void ShenandoahGenerationalControlThread::handle_requested_gc(GCCause::Cause cau MonitorLocker ml(&_gc_waiters_lock); size_t current_gc_id = get_gc_id(); - size_t required_gc_id = current_gc_id + 1; - while (current_gc_id < required_gc_id) { - // This races with the regulator thread to start a concurrent gc and the - // control thread to clear it at the start of a cycle. Threads here are - // allowed to escalate a heuristic's request for concurrent gc. - GCCause::Cause existing = Atomic::xchg(&_requested_gc_cause, cause); - if (existing != GCCause::_no_gc) { - log_debug(gc, thread)("GC request supersedes existing request: %s", GCCause::to_string(existing)); - } - - notify_control_thread(); + const size_t required_gc_id = current_gc_id + 1; + while (current_gc_id < required_gc_id && !should_terminate()) { + // Make requests to run a global cycle until at least one is completed + notify_control_thread(cause, ShenandoahHeap::heap()->global_generation()); ml.wait(); current_gc_id = get_gc_id(); } @@ -806,7 +771,7 @@ void ShenandoahGenerationalControlThread::notify_gc_waiters() { ml.notify_all(); } -const char* ShenandoahGenerationalControlThread::gc_mode_name(ShenandoahGenerationalControlThread::GCMode mode) { +const char* ShenandoahGenerationalControlThread::gc_mode_name(GCMode mode) { switch (mode) { case none: return "idle"; case concurrent_normal: return "normal"; @@ -819,11 +784,16 @@ const char* ShenandoahGenerationalControlThread::gc_mode_name(ShenandoahGenerati } } -void ShenandoahGenerationalControlThread::set_gc_mode(ShenandoahGenerationalControlThread::GCMode new_mode) { - if (_mode != new_mode) { - log_debug(gc)("Transition from: %s to: %s", gc_mode_name(_mode), gc_mode_name(new_mode)); - MonitorLocker ml(&_regulator_lock, Mutex::_no_safepoint_check_flag); - _mode = new_mode; +void ShenandoahGenerationalControlThread::set_gc_mode(GCMode new_mode) { + MonitorLocker ml(&_control_lock, Mutex::_no_safepoint_check_flag); + set_gc_mode(ml, new_mode); +} + +void ShenandoahGenerationalControlThread::set_gc_mode(MonitorLocker& ml, GCMode new_mode) { + if (_gc_mode != new_mode) { + log_debug(gc, thread)("Transition from: %s to: %s", gc_mode_name(_gc_mode), gc_mode_name(new_mode)); + EventMark event("Control thread transition from: %s, to %s", gc_mode_name(_gc_mode), gc_mode_name(new_mode)); + _gc_mode = new_mode; ml.notify_all(); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp index 46072b98255..1586205742a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp @@ -28,10 +28,9 @@ #include "gc/shared/gcCause.hpp" #include "gc/shenandoah/shenandoahController.hpp" -#include "gc/shenandoah/shenandoahGenerationType.hpp" #include "gc/shenandoah/shenandoahGC.hpp" -#include "gc/shenandoah/shenandoahPadding.hpp" #include "gc/shenandoah/shenandoahSharedVariables.hpp" +#include "runtime/mutexLocker.hpp" class ShenandoahOldGeneration; class ShenandoahGeneration; @@ -52,21 +51,43 @@ class ShenandoahGenerationalControlThread: public ShenandoahController { stopped } GCMode; + class ShenandoahGCRequest { + public: + ShenandoahGCRequest() : generation(nullptr), cause(GCCause::_no_gc) {} + ShenandoahGeneration* generation; + GCCause::Cause cause; + }; + private: + // This lock is used to coordinate setting the _requested_gc_cause, _requested generation + // and _gc_mode. It is important that these be changed together and have a consistent view. Monitor _control_lock; - Monitor _regulator_lock; - - ShenandoahSharedFlag _allow_old_preemption; - ShenandoahSharedFlag _preemption_requested; + // Represents a normal (non cancellation) gc request. This can be set by mutators (System.gc, + // whitebox gc, etc.) or by the regulator thread when the heuristics want to start a cycle. GCCause::Cause _requested_gc_cause; - volatile ShenandoahGenerationType _requested_generation; + + // This is the generation the request should operate on. + ShenandoahGeneration* _requested_generation; + + // The mode is read frequently by requesting threads and only ever written by the control thread. + // This may be read without taking the _control_lock, but should be read again under the lock + // before making any state changes (double-checked locking idiom). + volatile GCMode _gc_mode; + + // Only the control thread knows the correct degeneration point. This is used to have the + // control thread resume a STW cycle from the point where the concurrent cycle was cancelled. ShenandoahGC::ShenandoahDegenPoint _degen_point; - ShenandoahGeneration* _degen_generation; - shenandoah_padding(0); - volatile GCMode _mode; - shenandoah_padding(1); + // A reference to the heap + ShenandoahGenerationalHeap* _heap; + + // This is used to keep track of whether to age objects during the current cycle. + uint _age_period; + + // This is true when the old generation cycle is in an interruptible phase (i.e., marking or + // preparing for mark). + ShenandoahSharedFlag _allow_old_preemption; public: ShenandoahGenerationalControlThread(); @@ -77,54 +98,68 @@ class ShenandoahGenerationalControlThread: public ShenandoahController { void request_gc(GCCause::Cause cause) override; // Return true if the request to start a concurrent GC for the given generation succeeded. - bool request_concurrent_gc(ShenandoahGenerationType generation); + bool request_concurrent_gc(ShenandoahGeneration* generation); - GCMode gc_mode() { - return _mode; + // Returns the current state of the control thread + GCMode gc_mode() const { + return _gc_mode; } private: - // Returns true if the cycle has been cancelled or degenerated. bool check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point); + // Executes one GC cycle + void run_gc_cycle(const ShenandoahGCRequest& request); + // Returns true if the old generation marking completed (i.e., final mark executed for old generation). bool resume_concurrent_old_cycle(ShenandoahOldGeneration* generation, GCCause::Cause cause); + + // Various service methods handle different gc cycle types void service_concurrent_cycle(ShenandoahGeneration* generation, GCCause::Cause cause, bool reset_old_bitmap_specially); void service_stw_full_cycle(GCCause::Cause cause); - void service_stw_degenerated_cycle(GCCause::Cause cause, ShenandoahGC::ShenandoahDegenPoint point); + void service_stw_degenerated_cycle(const ShenandoahGCRequest& request); + void service_concurrent_normal_cycle(const ShenandoahGCRequest& request); + void service_concurrent_old_cycle(const ShenandoahGCRequest& request); void notify_gc_waiters(); - // Handle GC request. - // Blocks until GC is over. + // Blocks until at least one global GC cycle is complete. void handle_requested_gc(GCCause::Cause cause); - bool is_explicit_gc(GCCause::Cause cause) const; - bool is_implicit_gc(GCCause::Cause cause) const; - // Returns true if the old generation marking was interrupted to allow a young cycle. - bool preempt_old_marking(ShenandoahGenerationType generation); + bool preempt_old_marking(ShenandoahGeneration* generation); - void process_phase_timings(const ShenandoahGenerationalHeap* heap); - - void service_concurrent_normal_cycle(ShenandoahGenerationalHeap* heap, - ShenandoahGenerationType generation, - GCCause::Cause cause); - - void service_concurrent_old_cycle(ShenandoahGenerationalHeap* heap, - GCCause::Cause &cause); + // Flushes cycle timings to global timings and prints the phase timings for the last completed cycle. + void process_phase_timings() const; + // Set the gc mode and post a notification if it has changed. The overloaded variant should be used + // when the _control_lock is already held. void set_gc_mode(GCMode new_mode); + void set_gc_mode(MonitorLocker& ml, GCMode new_mode); + // Return printable name for the given gc mode. static const char* gc_mode_name(GCMode mode); - void notify_control_thread(); + // Takes the request lock and updates the requested cause and generation, then notifies the control thread. + // The overloaded variant should be used when the _control_lock is already held. + void notify_control_thread(GCCause::Cause cause, ShenandoahGeneration* generation); + void notify_control_thread(MonitorLocker& ml, GCCause::Cause cause, ShenandoahGeneration* generation); + + // Notifies the control thread, but does not update the requested cause or generation. + // The overloaded variant should be used when the _control_lock is already held. + void notify_cancellation(GCCause::Cause cause); + void notify_cancellation(MonitorLocker& ml, GCCause::Cause cause); + + // Configure the heap to age objects and regions if the aging period has elapsed. + void maybe_set_aging_cycle(); - void service_concurrent_cycle(ShenandoahHeap* heap, - ShenandoahGeneration* generation, - GCCause::Cause &cause, - bool do_old_gc_bootstrap); + // Take the _control_lock and check for a request to run a gc cycle. If a request is found, + // the `prepare` methods are used to configure the heap and update heuristics accordingly. + void check_for_request(ShenandoahGCRequest& request); + GCMode prepare_for_allocation_failure_gc(ShenandoahGCRequest &request); + GCMode prepare_for_explicit_gc(ShenandoahGCRequest &request) const; + GCMode prepare_for_concurrent_gc(const ShenandoahGCRequest &request) const; }; #endif // SHARE_GC_SHENANDOAH_SHENANDOAHGENERATIONALCONTROLTHREAD_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 68b83cbf75a..fc1ff230688 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -583,6 +583,7 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) : { // Initialize GC mode early, many subsequent initialization procedures depend on it initialize_mode(); + _cancelled_gc.set(GCCause::_no_gc); } #ifdef _MSC_VER @@ -993,13 +994,13 @@ HeapWord* ShenandoahHeap::allocate_memory(ShenandoahAllocRequest& req) { // a) We experienced a GC that had good progress, or // b) We experienced at least one Full GC (whether or not it had good progress) - size_t original_count = shenandoah_policy()->full_gc_count(); - while ((result == nullptr) && (original_count == shenandoah_policy()->full_gc_count())) { + const size_t original_count = shenandoah_policy()->full_gc_count(); + while (result == nullptr && should_retry_allocation(original_count)) { control_thread()->handle_alloc_failure(req, true); result = allocate_memory_under_lock(req, in_new_region); } if (result != nullptr) { - // If our allocation request has been satisifed after it initially failed, we count this as good gc progress + // If our allocation request has been satisfied after it initially failed, we count this as good gc progress notify_gc_progress(); } if (log_develop_is_enabled(Debug, gc, alloc)) { @@ -1050,6 +1051,11 @@ HeapWord* ShenandoahHeap::allocate_memory(ShenandoahAllocRequest& req) { return result; } +inline bool ShenandoahHeap::should_retry_allocation(size_t original_full_gc_count) const { + return shenandoah_policy()->full_gc_count() == original_full_gc_count + && !shenandoah_policy()->is_at_shutdown(); +} + HeapWord* ShenandoahHeap::allocate_memory_under_lock(ShenandoahAllocRequest& req, bool& in_new_region) { // If we are dealing with mutator allocation, then we may need to block for safepoint. // We cannot block for safepoint for GC allocations, because there is a high chance @@ -2120,9 +2126,9 @@ size_t ShenandoahHeap::tlab_used(Thread* thread) const { return _free_set->used(); } -bool ShenandoahHeap::try_cancel_gc() { - jbyte prev = _cancelled_gc.cmpxchg(CANCELLED, CANCELLABLE); - return prev == CANCELLABLE; +bool ShenandoahHeap::try_cancel_gc(GCCause::Cause cause) { + jbyte prev = _cancelled_gc.cmpxchg(cause, GCCause::_no_gc); + return prev == GCCause::_no_gc; } void ShenandoahHeap::cancel_concurrent_mark() { @@ -2136,13 +2142,15 @@ void ShenandoahHeap::cancel_concurrent_mark() { ShenandoahBarrierSet::satb_mark_queue_set().abandon_partial_marking(); } -void ShenandoahHeap::cancel_gc(GCCause::Cause cause) { - if (try_cancel_gc()) { +bool ShenandoahHeap::cancel_gc(GCCause::Cause cause) { + if (try_cancel_gc(cause)) { FormatBuffer<> msg("Cancelling GC: %s", GCCause::to_string(cause)); - log_info(gc)("%s", msg.buffer()); + log_info(gc,thread)("%s", msg.buffer()); Events::log(Thread::current(), "%s", msg.buffer()); _cancel_requested_time = os::elapsedTime(); + return true; } + return false; } uint ShenandoahHeap::max_workers() { @@ -2155,18 +2163,10 @@ void ShenandoahHeap::stop() { // Step 0. Notify policy to disable event recording and prevent visiting gc threads during shutdown _shenandoah_policy->record_shutdown(); - // Step 0a. Stop reporting on gc thread cpu utilization + // Step 1. Stop reporting on gc thread cpu utilization mmu_tracker()->stop(); - // Step 1. Notify control thread that we are in shutdown. - // Note that we cannot do that with stop(), because stop() is blocking and waits for the actual shutdown. - // Doing stop() here would wait for the normal GC cycle to complete, never falling through to cancel below. - control_thread()->prepare_for_graceful_shutdown(); - - // Step 2. Notify GC workers that we are cancelling GC. - cancel_gc(GCCause::_shenandoah_stop_vm); - - // Step 3. Wait until GC worker exits normally. + // Step 2. Wait until GC worker exits normally (this will cancel any ongoing GC). control_thread()->stop(); // Stop 4. Shutdown uncommit thread. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index 785e1742b0c..33d2db0b2f1 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -430,35 +430,38 @@ class ShenandoahHeap : public CollectedHeap { private: void manage_satb_barrier(bool active); - enum CancelState { - // Normal state. GC has not been cancelled and is open for cancellation. - // Worker threads can suspend for safepoint. - CANCELLABLE, - - // GC has been cancelled. Worker threads can not suspend for - // safepoint but must finish their work as soon as possible. - CANCELLED - }; - + // Records the time of the first successful cancellation request. This is used to measure + // the responsiveness of the heuristic when starting a cycle. double _cancel_requested_time; - ShenandoahSharedEnumFlag<CancelState> _cancelled_gc; + + // Indicates the reason the current GC has been cancelled (GCCause::_no_gc means the gc is not cancelled). + ShenandoahSharedEnumFlag<GCCause::Cause> _cancelled_gc; // Returns true if cancel request was successfully communicated. // Returns false if some other thread already communicated cancel // request. A true return value does not mean GC has been // cancelled, only that the process of cancelling GC has begun. - bool try_cancel_gc(); + bool try_cancel_gc(GCCause::Cause cause); public: + // True if gc has been cancelled inline bool cancelled_gc() const; + + // Used by workers in the GC cycle to detect cancellation and honor STS requirements inline bool check_cancelled_gc_and_yield(bool sts_active = true); + // This indicates the reason the last GC cycle was cancelled. + inline GCCause::Cause cancelled_cause() const; + + // Clears the cancellation cause and optionally resets the oom handler (cancelling an + // old mark does _not_ touch the oom handler). inline void clear_cancelled_gc(bool clear_oom_handler = true); void cancel_concurrent_mark(); - void cancel_gc(GCCause::Cause cause); -public: + // Returns true if and only if this call caused a gc to be cancelled. + bool cancel_gc(GCCause::Cause cause); + // Returns true if the soft maximum heap has been changed using management APIs. bool check_soft_max_changed(); @@ -690,6 +693,9 @@ class ShenandoahHeap : public CollectedHeap { HeapWord* allocate_from_gclab_slow(Thread* thread, size_t size); HeapWord* allocate_new_gclab(size_t min_size, size_t word_size, size_t* actual_size); + // We want to retry an unsuccessful attempt at allocation until at least a full gc. + bool should_retry_allocation(size_t original_full_gc_count) const; + public: HeapWord* allocate_memory(ShenandoahAllocRequest& request); HeapWord* mem_allocate(size_t size, bool* what) override; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp index 461447cf9ba..13c203d423c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp @@ -252,7 +252,7 @@ inline void ShenandoahHeap::atomic_clear_oop(narrowOop* addr, narrowOop compare) } inline bool ShenandoahHeap::cancelled_gc() const { - return _cancelled_gc.get() == CANCELLED; + return _cancelled_gc.get() != GCCause::_no_gc; } inline bool ShenandoahHeap::check_cancelled_gc_and_yield(bool sts_active) { @@ -264,8 +264,12 @@ inline bool ShenandoahHeap::check_cancelled_gc_and_yield(bool sts_active) { return cancelled_gc(); } +inline GCCause::Cause ShenandoahHeap::cancelled_cause() const { + return _cancelled_gc.get(); +} + inline void ShenandoahHeap::clear_cancelled_gc(bool clear_oom_handler) { - _cancelled_gc.set(CANCELLABLE); + _cancelled_gc.set(GCCause::_no_gc); if (_cancel_requested_time > 0) { log_debug(gc)("GC cancellation took %.3fs", (os::elapsedTime() - _cancel_requested_time)); _cancel_requested_time = 0; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp index 42237a0ab06..2c70cecf705 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp @@ -76,10 +76,11 @@ ShenandoahHeapRegion::ShenandoahHeapRegion(HeapWord* start, size_t index, bool c _live_data(0), _critical_pins(0), _update_watermark(start), - _age(0) + _age(0), #ifdef SHENANDOAH_CENSUS_NOISE - , _youth(0) + _youth(0), #endif // SHENANDOAH_CENSUS_NOISE + _needs_bitmap_reset(false) { assert(Universe::on_page_boundary(_bottom) && Universe::on_page_boundary(_end), diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp index 3dc8febbad4..4c99364bc6e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp @@ -266,6 +266,8 @@ class ShenandoahHeapRegion { ShenandoahSharedFlag _recycling; // Used to indicate that the region is being recycled; see try_recycle*(). + bool _needs_bitmap_reset; + public: ShenandoahHeapRegion(HeapWord* start, size_t index, bool committed); @@ -477,6 +479,18 @@ class ShenandoahHeapRegion { CENSUS_NOISE(void clear_youth() { _youth = 0; }) + inline bool need_bitmap_reset() const { + return _needs_bitmap_reset; + } + + inline void set_needs_bitmap_reset() { + _needs_bitmap_reset = true; + } + + inline void unset_needs_bitmap_reset() { + _needs_bitmap_reset = false; + } + private: void decrement_humongous_waste() const; void do_commit(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp index 708d27db165..2f5abf99200 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp @@ -78,6 +78,11 @@ void ShenandoahOldGC::op_final_mark() { if (VerifyAfterGC) { Universe::verify(); } + + { + ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_mark_propagate_gc_state); + heap->propagate_gc_state_to_all_threads(); + } } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp index 38887217255..9b030905b6d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp @@ -495,7 +495,7 @@ const char* ShenandoahOldGeneration::state_name(State state) { void ShenandoahOldGeneration::transition_to(State new_state) { if (_state != new_state) { - log_debug(gc)("Old generation transition from %s to %s", state_name(_state), state_name(new_state)); + log_debug(gc, thread)("Old generation transition from %s to %s", state_name(_state), state_name(new_state)); EventMark event("Old was %s, now is %s", state_name(_state), state_name(new_state)); validate_transition(new_state); _state = new_state; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp index 7a8fed9f548..20c59cce69b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp @@ -50,6 +50,7 @@ class outputStream; #define SHENANDOAH_PHASE_DO(f) \ f(conc_reset, "Concurrent Reset") \ + f(conc_reset_after_collect, "Concurrent Reset After Collect") \ f(conc_reset_old, "Concurrent Reset (OLD)") \ f(init_mark_gross, "Pause Init Mark (G)") \ f(init_mark, "Pause Init Mark (N)") \ @@ -57,6 +58,7 @@ class outputStream; f(init_swap_rset, " Swap Remembered Set") \ f(init_transfer_satb, " Transfer Old From SATB") \ f(init_update_region_states, " Update Region States") \ + f(init_propagate_gc_state, " Propagate GC State") \ \ f(init_scan_rset, "Concurrent Scan Remembered Set") \ SHENANDOAH_PAR_PHASE_DO(init_scan_rset_, " RS: ", f) \ @@ -70,6 +72,7 @@ class outputStream; f(final_mark_gross, "Pause Final Mark (G)") \ f(final_mark, "Pause Final Mark (N)") \ f(finish_mark, " Finish Mark") \ + f(final_mark_propagate_gc_state, " Propagate GC State") \ SHENANDOAH_PAR_PHASE_DO(finish_mark_, " FM: ", f) \ f(purge, " System Purge") \ SHENANDOAH_PAR_PHASE_DO(purge_cu_par_, " CU: ", f) \ @@ -107,6 +110,7 @@ class outputStream; f(promote_in_place, "Concurrent Promote Regions") \ f(final_roots_gross, "Pause Final Roots (G)") \ f(final_roots, "Pause Final Roots (N)") \ + f(final_roots_propagate_gc_state, " Propagate GC State") \ \ f(init_update_refs_gross, "Pause Init Update Refs (G)") \ f(init_update_refs, "Pause Init Update Refs (N)") \ @@ -121,6 +125,7 @@ class outputStream; f(final_update_refs_update_region_states, " Update Region States") \ f(final_update_refs_trash_cset, " Trash Collection Set") \ f(final_update_refs_rebuild_freeset, " Rebuild Free Set") \ + f(final_update_refs_propagate_gc_state, " Propagate GC State") \ \ f(conc_cleanup_complete, "Concurrent Cleanup") \ f(conc_coalesce_and_fill, "Concurrent Coalesce and Fill") \ @@ -157,6 +162,7 @@ class outputStream; f(degen_gc_promote_regions, " Degen Promote Regions") \ f(degen_gc_coalesce_and_fill, " Degen Coalesce and Fill") \ SHENANDOAH_PAR_PHASE_DO(degen_coalesce_, " DC&F", f) \ + f(degen_gc_propagate_gc_state, " Propagate GC State") \ \ f(full_gc_gross, "Pause Full GC (G)") \ f(full_gc, "Pause Full GC (N)") \ @@ -188,6 +194,7 @@ class outputStream; f(full_gc_copy_objects_rebuild, " Rebuild Region Sets") \ f(full_gc_reconstruct_remembered_set, " Reconstruct Remembered Set") \ f(full_gc_heapdump_post, " Post Heap Dump") \ + f(full_gc_propagate_gc_state, " Propagate GC State") \ \ f(pacing, "Pacing") \ \ diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp index a684e8ff228..f9e6f714c7f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp @@ -33,15 +33,14 @@ #include "logging/log.hpp" ShenandoahRegulatorThread::ShenandoahRegulatorThread(ShenandoahGenerationalControlThread* control_thread) : - ConcurrentGCThread(), + _heap(ShenandoahHeap::heap()), _control_thread(control_thread), _sleep(ShenandoahControlIntervalMin), _last_sleep_adjust_time(os::elapsedTime()) { shenandoah_assert_generational(); - ShenandoahHeap* heap = ShenandoahHeap::heap(); - _old_heuristics = heap->old_generation()->heuristics(); - _young_heuristics = heap->young_generation()->heuristics(); - _global_heuristics = heap->global_generation()->heuristics(); + _old_heuristics = _heap->old_generation()->heuristics(); + _young_heuristics = _heap->young_generation()->heuristics(); + _global_heuristics = _heap->global_generation()->heuristics(); set_name("Shenandoah Regulator Thread"); create_and_start(); @@ -62,7 +61,7 @@ void ShenandoahRegulatorThread::regulate_young_and_old_cycles() { ShenandoahGenerationalControlThread::GCMode mode = _control_thread->gc_mode(); if (mode == ShenandoahGenerationalControlThread::none) { if (should_start_metaspace_gc()) { - if (request_concurrent_gc(GLOBAL)) { + if (request_concurrent_gc(_heap->global_generation())) { // Some of vmTestbase/metaspace tests depend on following line to count GC cycles _global_heuristics->log_trigger("%s", GCCause::to_string(GCCause::_metadata_GC_threshold)); _global_heuristics->cancel_trigger_request(); @@ -74,10 +73,15 @@ void ShenandoahRegulatorThread::regulate_young_and_old_cycles() { if (start_old_cycle()) { log_debug(gc)("Heuristics request for old collection accepted"); _young_heuristics->cancel_trigger_request(); - } else if (request_concurrent_gc(YOUNG)) { + _old_heuristics->cancel_trigger_request(); + } else if (request_concurrent_gc(_heap->young_generation())) { log_debug(gc)("Heuristics request for young collection accepted"); _young_heuristics->cancel_trigger_request(); } + } else if (_old_heuristics->should_resume_old_cycle() || _old_heuristics->should_start_gc()) { + if (request_concurrent_gc(_heap->old_generation())) { + log_debug(gc)("Heuristics request to resume old collection accepted"); + } } } } else if (mode == ShenandoahGenerationalControlThread::servicing_old) { @@ -131,19 +135,19 @@ void ShenandoahRegulatorThread::regulator_sleep() { } } -bool ShenandoahRegulatorThread::start_old_cycle() { - return _old_heuristics->should_start_gc() && request_concurrent_gc(OLD); +bool ShenandoahRegulatorThread::start_old_cycle() const { + return _old_heuristics->should_start_gc() && request_concurrent_gc(_heap->old_generation()); } -bool ShenandoahRegulatorThread::start_young_cycle() { - return _young_heuristics->should_start_gc() && request_concurrent_gc(YOUNG); +bool ShenandoahRegulatorThread::start_young_cycle() const { + return _young_heuristics->should_start_gc() && request_concurrent_gc(_heap->young_generation()); } -bool ShenandoahRegulatorThread::start_global_cycle() { - return _global_heuristics->should_start_gc() && request_concurrent_gc(GLOBAL); +bool ShenandoahRegulatorThread::start_global_cycle() const { + return _global_heuristics->should_start_gc() && request_concurrent_gc(_heap->global_generation()); } -bool ShenandoahRegulatorThread::request_concurrent_gc(ShenandoahGenerationType generation) { +bool ShenandoahRegulatorThread::request_concurrent_gc(ShenandoahGeneration* generation) const { double now = os::elapsedTime(); bool accepted = _control_thread->request_concurrent_gc(generation); if (LogTarget(Debug, gc, thread)::is_enabled() && accepted) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp index f9f7e25f97c..a72d6004beb 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp @@ -26,8 +26,11 @@ #include "gc/shared/concurrentGCThread.hpp" +class ShenandoahHeap; class ShenandoahHeuristics; +class ShenandoahGeneration; class ShenandoahGenerationalControlThread; +class ShenandoahOldHeuristics; /* * The purpose of this class (and thread) is to allow us to continue @@ -58,9 +61,10 @@ class ShenandoahRegulatorThread: public ConcurrentGCThread { void regulate_young_and_global_cycles(); // These return true if a cycle was started. - bool start_old_cycle(); - bool start_young_cycle(); - bool start_global_cycle(); + bool start_old_cycle() const; + bool start_young_cycle() const; + bool start_global_cycle() const; + bool resume_old_cycle(); // The generational mode can only unload classes in a global cycle. The regulator // thread itself will trigger a global cycle if metaspace is out of memory. @@ -70,11 +74,12 @@ class ShenandoahRegulatorThread: public ConcurrentGCThread { void regulator_sleep(); // Provides instrumentation to track how long it takes to acknowledge a request. - bool request_concurrent_gc(ShenandoahGenerationType generation); + bool request_concurrent_gc(ShenandoahGeneration* generation) const; + ShenandoahHeap* _heap; ShenandoahGenerationalControlThread* _control_thread; ShenandoahHeuristics* _young_heuristics; - ShenandoahHeuristics* _old_heuristics; + ShenandoahOldHeuristics* _old_heuristics; ShenandoahHeuristics* _global_heuristics; uint _sleep; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp index b9f52909cbe..109e940e2bd 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp @@ -475,7 +475,7 @@ HeapWord* ShenandoahScanRemembered::addr_for_cluster(size_t cluster_no) { void ShenandoahScanRemembered::roots_do(OopIterateClosure* cl) { ShenandoahHeap* heap = ShenandoahHeap::heap(); bool old_bitmap_stable = heap->old_generation()->is_mark_complete(); - log_info(gc, remset)("Scan remembered set using bitmap: %s", BOOL_TO_STR(old_bitmap_stable)); + log_debug(gc, remset)("Scan remembered set using bitmap: %s", BOOL_TO_STR(old_bitmap_stable)); for (size_t i = 0, n = heap->num_regions(); i < n; ++i) { ShenandoahHeapRegion* region = heap->get_region(i); if (region->is_old() && region->is_active() && !region->is_cset()) { @@ -653,7 +653,7 @@ ShenandoahScanRememberedTask::ShenandoahScanRememberedTask(ShenandoahObjToScanQu WorkerTask("Scan Remembered Set"), _queue_set(queue_set), _old_queue_set(old_queue_set), _rp(rp), _work_list(work_list), _is_concurrent(is_concurrent) { bool old_bitmap_stable = ShenandoahHeap::heap()->old_generation()->is_mark_complete(); - log_info(gc, remset)("Scan remembered set using bitmap: %s", BOOL_TO_STR(old_bitmap_stable)); + log_debug(gc, remset)("Scan remembered set using bitmap: %s", BOOL_TO_STR(old_bitmap_stable)); } void ShenandoahScanRememberedTask::work(uint worker_id) { @@ -727,7 +727,6 @@ size_t ShenandoahRegionChunkIterator::calc_regular_group_size() { // half of the remaining heap, the third processes half of what remains and so on. The smallest chunk size // is represented by _smallest_chunk_size_words. We do not divide work any smaller than this. // - size_t group_size = _heap->num_regions() / 2; return group_size; } @@ -773,6 +772,7 @@ size_t ShenandoahRegionChunkIterator::calc_num_groups() { // Any remaining regions will be treated as if they are part of the most recently created group. This group will // have more than _regular_group_size chunks within it. } + assert (num_groups <= _maximum_groups, "Cannot have more than %zu groups", _maximum_groups); return num_groups; } @@ -784,21 +784,31 @@ size_t ShenandoahRegionChunkIterator::calc_total_chunks() { size_t current_group_span = _first_group_chunk_size_b4_rebalance * _regular_group_size; size_t smallest_group_span = smallest_chunk_size_words() * _regular_group_size; - // The first group gets special handling because the first chunk size can be no larger than _largest_chunk_size_words + // The first group gets special handling because the first chunk size can be no larger than _maximum_chunk_size_words if (region_size_words > _maximum_chunk_size_words) { // In the case that we shrink the first group's chunk size, certain other groups will also be subsumed within the first group size_t effective_chunk_size = _first_group_chunk_size_b4_rebalance; + uint coalesced_groups = 0; while (effective_chunk_size >= _maximum_chunk_size_words) { + // Each iteration of this loop subsumes one original group into a new rebalanced initial group. num_chunks += current_group_span / _maximum_chunk_size_words; unspanned_heap_size -= current_group_span; effective_chunk_size /= 2; current_group_span /= 2; + coalesced_groups++; } + assert(effective_chunk_size * 2 == _maximum_chunk_size_words, + "We assume _first_group_chunk_size_b4_rebalance is _maximum_chunk_size_words * a power of two"); + _largest_chunk_size_words = _maximum_chunk_size_words; + _adjusted_num_groups = _num_groups - (coalesced_groups - 1); } else { num_chunks = _regular_group_size; unspanned_heap_size -= current_group_span; + _largest_chunk_size_words = current_group_span / num_chunks; + _adjusted_num_groups = _num_groups; current_group_span /= 2; } + size_t spanned_groups = 1; while (unspanned_heap_size > 0) { if (current_group_span <= unspanned_heap_size) { @@ -856,11 +866,12 @@ ShenandoahRegionChunkIterator::ShenandoahRegionChunkIterator(ShenandoahHeap* hea size_t expected_chunk_size_words = _clusters_in_smallest_chunk * CardTable::card_size_in_words() * ShenandoahCardCluster::CardsPerCluster; assert(smallest_chunk_size_words() == expected_chunk_size_words, "_smallest_chunk_size (%zu) is not valid because it does not equal (%zu)", smallest_chunk_size_words(), expected_chunk_size_words); -#endif assert(_num_groups <= _maximum_groups, "The number of remembered set scanning groups must be less than or equal to maximum groups"); - assert(smallest_chunk_size_words() << (_maximum_groups - 1) == _maximum_chunk_size_words, - "Maximum number of groups needs to span maximum chunk size to smallest chunk size"); + assert(smallest_chunk_size_words() << (_adjusted_num_groups - 1) == _largest_chunk_size_words, + "The number of groups (%zu) needs to span smallest chunk size (%zu) to largest chunk size (%zu)", + _adjusted_num_groups, smallest_chunk_size_words(), _largest_chunk_size_words); +#endif size_t words_in_region = ShenandoahHeapRegion::region_size_words(); _region_index[0] = 0; @@ -883,7 +894,7 @@ ShenandoahRegionChunkIterator::ShenandoahRegionChunkIterator(ShenandoahHeap* hea } size_t previous_group_span = _group_entries[0] * _group_chunk_size[0]; - for (size_t i = 1; i < _num_groups; i++) { + for (size_t i = 1; i < _adjusted_num_groups; i++) { _group_chunk_size[i] = _group_chunk_size[i-1] / 2; size_t chunks_in_group = _regular_group_size; size_t this_group_span = _group_chunk_size[i] * chunks_in_group; @@ -893,19 +904,19 @@ ShenandoahRegionChunkIterator::ShenandoahRegionChunkIterator(ShenandoahHeap* hea _group_entries[i] = _group_entries[i-1] + _regular_group_size; previous_group_span = total_span_of_groups; } - if (_group_entries[_num_groups-1] < _total_chunks) { - assert((_total_chunks - _group_entries[_num_groups-1]) * _group_chunk_size[_num_groups-1] + previous_group_span == + if (_group_entries[_adjusted_num_groups-1] < _total_chunks) { + assert((_total_chunks - _group_entries[_adjusted_num_groups-1]) * _group_chunk_size[_adjusted_num_groups-1] + previous_group_span == heap->num_regions() * words_in_region, "Total region chunks (%zu" ") do not span total heap regions (%zu)", _total_chunks, _heap->num_regions()); - previous_group_span += (_total_chunks - _group_entries[_num_groups-1]) * _group_chunk_size[_num_groups-1]; - _group_entries[_num_groups-1] = _total_chunks; + previous_group_span += (_total_chunks - _group_entries[_adjusted_num_groups-1]) * _group_chunk_size[_adjusted_num_groups-1]; + _group_entries[_adjusted_num_groups-1] = _total_chunks; } assert(previous_group_span == heap->num_regions() * words_in_region, "Total region chunks (%zu" ") do not span total heap regions (%zu): %zu does not equal %zu", _total_chunks, _heap->num_regions(), previous_group_span, heap->num_regions() * words_in_region); // Not necessary, but keeps things tidy - for (size_t i = _num_groups; i < _maximum_groups; i++) { + for (size_t i = _adjusted_num_groups; i < _maximum_groups; i++) { _region_index[i] = 0; _group_offset[i] = 0; _group_entries[i] = _group_entries[i-1]; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp index 2a0713bf4ed..e28f2f03052 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp @@ -196,11 +196,14 @@ class ShenandoahDirectCardMarkRememberedSet: public CHeapObj<mtGC> { // Use symbolic constants defined in cardTable.hpp // CardTable::card_shift = 9; - // CardTable::card_size = 512; - // CardTable::card_size_in_words = 64; + // CardTable::card_size = 512; (default value 512, a power of 2 >= 128) + // CardTable::card_size_in_words = 64; (default value 64, a power of 2 >= 16) // CardTable::clean_card_val() // CardTable::dirty_card_val() + // See shenandoahCardTable.hpp + // ShenandoahMinCardSizeInBytes 128 + const size_t LogCardValsPerIntPtr; // the number of card values (entries) in an intptr_t const size_t LogCardSizeInWords; // the size of a card in heap word units @@ -399,7 +402,7 @@ class ShenandoahCardCluster: public CHeapObj<mtGC> { ShenandoahCardCluster(ShenandoahDirectCardMarkRememberedSet* rs) { _rs = rs; - _object_starts = NEW_C_HEAP_ARRAY(crossing_info, rs->total_cards(), mtGC); + _object_starts = NEW_C_HEAP_ARRAY(crossing_info, rs->total_cards() + 1, mtGC); // the +1 is to account for card table guarding entry for (size_t i = 0; i < rs->total_cards(); i++) { _object_starts[i].short_word = 0; } @@ -888,14 +891,14 @@ class ShenandoahRegionChunkIterator : public StackObj { // The largest chunk size is 4 MiB, measured in words. Otherwise, remembered set scanning may become too unbalanced. // If the largest chunk size is too small, there is too much overhead sifting out assignments to individual worker threads. static const size_t _maximum_chunk_size_words = (4 * 1024 * 1024) / HeapWordSize; - static const size_t _clusters_in_smallest_chunk = 4; + size_t _largest_chunk_size_words; + // smallest_chunk_size is 4 clusters. Each cluster spans 128 KiB. // This is computed from CardTable::card_size_in_words() * ShenandoahCardCluster::CardsPerCluster; static size_t smallest_chunk_size_words() { - return _clusters_in_smallest_chunk * CardTable::card_size_in_words() * - ShenandoahCardCluster::CardsPerCluster; + return _clusters_in_smallest_chunk * CardTable::card_size_in_words() * ShenandoahCardCluster::CardsPerCluster; } // The total remembered set scanning effort is divided into chunks of work that are assigned to individual worker tasks. @@ -910,19 +913,30 @@ class ShenandoahRegionChunkIterator : public StackObj { // The first group "effectively" processes chunks of size 1 MiB (or smaller for smaller region sizes). // The last group processes chunks of size 128 KiB. There are four groups total. - // group[0] is 4 MiB chunk size (_maximum_chunk_size_words) - // group[1] is 2 MiB chunk size - // group[2] is 1 MiB chunk size - // group[3] is 512 KiB chunk size - // group[4] is 256 KiB chunk size - // group[5] is 128 Kib shunk size (_smallest_chunk_size_words = 4 * 64 * 64 - static const size_t _maximum_groups = 6; + // group[ 0] is 4 MiB chunk size (_maximum_chunk_size_words) + // group[ 1] is 2 MiB chunk size + // group[ 2] is 1 MiB chunk size + // group[ 3] is 512 KiB chunk size + // group[ 4] is 256 KiB chunk size + // group[ 5] is 128 KiB chunk size + // group[ 6] is 64 KiB chunk size + // group[ 7] is 32 KiB chunk size + // group[ 8] is 16 KiB chunk size + // group[ 9] is 8 KiB chunk size + // group[10] is 4 KiB chunk size + // Note: 4 KiB is smallest possible chunk_size, computed from: + // _clusters_in_smallest_chunk * MinimumCardSizeInWords * ShenandoahCardCluster::CardsPerCluster, which is + // 4 * 16 * 64 = 4096 + + // We set aside arrays to represent the maximum number of groups that may be required for any heap configuration + static const size_t _maximum_groups = 11; const ShenandoahHeap* _heap; const size_t _regular_group_size; // Number of chunks in each group const size_t _first_group_chunk_size_b4_rebalance; const size_t _num_groups; // Number of groups in this configuration + size_t _adjusted_num_groups; // Rebalancing may coalesce groups const size_t _total_chunks; shenandoah_padding(0); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUncommitThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahUncommitThread.cpp index 5f9bc7c9b91..ec708b198e7 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUncommitThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUncommitThread.cpp @@ -31,8 +31,7 @@ ShenandoahUncommitThread::ShenandoahUncommitThread(ShenandoahHeap* heap) : _heap(heap), - _stop_lock(Mutex::safepoint - 2, "ShenandoahUncommitStop_lock", true), - _uncommit_lock(Mutex::safepoint - 2, "ShenandoahUncommitCancel_lock", true) { + _uncommit_lock(Mutex::safepoint - 2, "ShenandoahUncommit_lock", true) { set_name("Shenandoah Uncommit Thread"); create_and_start(); @@ -68,11 +67,10 @@ void ShenandoahUncommitThread::run_service() { uncommit(shrink_before, shrink_until); } } - { - MonitorLocker locker(&_stop_lock, Mutex::_no_safepoint_check_flag); - if (!_stop_requested.is_set()) { - timed_out = locker.wait(poll_interval); - } + + if (!should_terminate()) { + MonitorLocker locker(&_uncommit_lock, Mutex::_no_safepoint_check_flag); + timed_out = locker.wait(poll_interval); } } } @@ -104,7 +102,7 @@ bool ShenandoahUncommitThread::has_work(double shrink_before, size_t shrink_unti void ShenandoahUncommitThread::notify_soft_max_changed() { assert(is_uncommit_allowed(), "Only notify if uncommit is allowed"); if (_soft_max_changed.try_set()) { - MonitorLocker locker(&_stop_lock, Mutex::_no_safepoint_check_flag); + MonitorLocker locker(&_uncommit_lock, Mutex::_no_safepoint_check_flag); locker.notify_all(); } } @@ -112,7 +110,7 @@ void ShenandoahUncommitThread::notify_soft_max_changed() { void ShenandoahUncommitThread::notify_explicit_gc_requested() { assert(is_uncommit_allowed(), "Only notify if uncommit is allowed"); if (_explicit_gc_requested.try_set()) { - MonitorLocker locker(&_stop_lock, Mutex::_no_safepoint_check_flag); + MonitorLocker locker(&_uncommit_lock, Mutex::_no_safepoint_check_flag); locker.notify_all(); } } @@ -125,33 +123,64 @@ void ShenandoahUncommitThread::uncommit(double shrink_before, size_t shrink_unti assert(ShenandoahUncommit, "should be enabled"); assert(_uncommit_in_progress.is_unset(), "Uncommit should not be in progress"); - if (!is_uncommit_allowed()) { + { + // Final check, under the lock, if uncommit is allowed. + MonitorLocker locker(&_uncommit_lock, Mutex::_no_safepoint_check_flag); + if (is_uncommit_allowed()) { + _uncommit_in_progress.set(); + } + } + + // If not allowed to start, do nothing. + if (!_uncommit_in_progress.is_set()) { return; } + // From here on, uncommit is in progress. Attempts to stop the uncommit must wait + // until the cancellation request is acknowledged and uncommit is no longer in progress. const char* msg = "Concurrent uncommit"; + const double start = os::elapsedTime(); EventMark em("%s", msg); - double start = os::elapsedTime(); log_info(gc, start)("%s", msg); - _uncommit_in_progress.set(); + // This is the number of regions uncommitted during this increment of uncommit work. + const size_t uncommitted_region_count = do_uncommit_work(shrink_before, shrink_until); + + { + MonitorLocker locker(&_uncommit_lock, Mutex::_no_safepoint_check_flag); + _uncommit_in_progress.unset(); + locker.notify_all(); + } + if (uncommitted_region_count > 0) { + _heap->notify_heap_changed(); + } + + const double elapsed = os::elapsedTime() - start; + log_info(gc)("%s " PROPERFMT " (" PROPERFMT ") %.3fms", + msg, PROPERFMTARGS(uncommitted_region_count * ShenandoahHeapRegion::region_size_bytes()), PROPERFMTARGS(_heap->capacity()), + elapsed * MILLIUNITS); +} + +size_t ShenandoahUncommitThread::do_uncommit_work(double shrink_before, size_t shrink_until) const { + size_t count = 0; // Application allocates from the beginning of the heap, and GC allocates at // the end of it. It is more efficient to uncommit from the end, so that applications // could enjoy the near committed regions. GC allocations are much less frequent, // and therefore can accept the committing costs. - size_t count = 0; for (size_t i = _heap->num_regions(); i > 0; i--) { if (!is_uncommit_allowed()) { + // GC wants to start, so the uncommit operation must stop break; } ShenandoahHeapRegion* r = _heap->get_region(i - 1); if (r->is_empty_committed() && (r->empty_time() < shrink_before)) { SuspendibleThreadSetJoiner sts_joiner; - ShenandoahHeapLocker locker(_heap->lock()); + ShenandoahHeapLocker heap_locker(_heap->lock()); if (r->is_empty_committed()) { if (_heap->committed() < shrink_until + ShenandoahHeapRegion::region_size_bytes()) { + // We have uncommitted enough regions to hit the target heap committed size break; } @@ -161,26 +190,13 @@ void ShenandoahUncommitThread::uncommit(double shrink_before, size_t shrink_unti } SpinPause(); // allow allocators to take the lock } - - { - MonitorLocker locker(&_uncommit_lock, Mutex::_no_safepoint_check_flag); - _uncommit_in_progress.unset(); - locker.notify_all(); - } - - if (count > 0) { - _heap->notify_heap_changed(); - } - - double elapsed = os::elapsedTime() - start; - log_info(gc)("%s " PROPERFMT " (" PROPERFMT ") %.3fms", - msg, PROPERFMTARGS(count * ShenandoahHeapRegion::region_size_bytes()), PROPERFMTARGS(_heap->capacity()), - elapsed * MILLIUNITS); + return count; } + void ShenandoahUncommitThread::stop_service() { - MonitorLocker locker(&_stop_lock, Mutex::_safepoint_check_flag); - _stop_requested.set(); + MonitorLocker locker(&_uncommit_lock, Mutex::_safepoint_check_flag); + _uncommit_allowed.unset(); locker.notify_all(); } @@ -193,5 +209,6 @@ void ShenandoahUncommitThread::forbid_uncommit() { } void ShenandoahUncommitThread::allow_uncommit() { + MonitorLocker locker(&_uncommit_lock, Mutex::_no_safepoint_check_flag); _uncommit_allowed.set(); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUncommitThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahUncommitThread.hpp index 6c4e26e4e0f..caffd2ef87b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUncommitThread.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUncommitThread.hpp @@ -38,18 +38,12 @@ class ShenandoahUncommitThread : public ConcurrentGCThread { // Indicates that an explicit gc has been requested ShenandoahSharedFlag _explicit_gc_requested; - // Indicates that the thread should stop and terminate - ShenandoahSharedFlag _stop_requested; - // Indicates whether it is safe to uncommit regions ShenandoahSharedFlag _uncommit_allowed; // Indicates that regions are being actively uncommitted ShenandoahSharedFlag _uncommit_in_progress; - // This lock is used to coordinate stopping and terminating this thread - Monitor _stop_lock; - // This lock is used to coordinate allowing or forbidding regions to be uncommitted Monitor _uncommit_lock; @@ -66,6 +60,12 @@ class ShenandoahUncommitThread : public ConcurrentGCThread { // True if the control thread has allowed this thread to uncommit regions bool is_uncommit_allowed() const; + // Iterate over and uncommit eligible regions until committed heap falls below + // `shrink_until` bytes. A region is eligible for uncommit if the timestamp at which + // it was last made empty is before `shrink_before` seconds since jvm start. + // Returns the number of regions uncommitted. May be interrupted by `forbid_uncommit`. + size_t do_uncommit_work(double shrink_before, size_t shrink_until) const; + public: explicit ShenandoahUncommitThread(ShenandoahHeap* heap); @@ -85,7 +85,7 @@ class ShenandoahUncommitThread : public ConcurrentGCThread { void allow_uncommit(); // True if uncommit is in progress - bool is_uncommit_in_progress() { + bool is_uncommit_in_progress() const { return _uncommit_in_progress.is_set(); } protected: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.cpp index 30a677fc126..bb9c3498a06 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.cpp @@ -81,47 +81,40 @@ void VM_ShenandoahInitMark::doit() { ShenandoahGCPauseMark mark(_gc_id, "Init Mark", SvcGCMarker::CONCURRENT); set_active_generation(); _gc->entry_init_mark(); - ShenandoahHeap::heap()->propagate_gc_state_to_all_threads(); } void VM_ShenandoahFinalMarkStartEvac::doit() { ShenandoahGCPauseMark mark(_gc_id, "Final Mark", SvcGCMarker::CONCURRENT); set_active_generation(); _gc->entry_final_mark(); - ShenandoahHeap::heap()->propagate_gc_state_to_all_threads(); } void VM_ShenandoahFullGC::doit() { ShenandoahGCPauseMark mark(_gc_id, "Full GC", SvcGCMarker::FULL); set_active_generation(); _full_gc->entry_full(_gc_cause); - ShenandoahHeap::heap()->propagate_gc_state_to_all_threads(); } void VM_ShenandoahDegeneratedGC::doit() { ShenandoahGCPauseMark mark(_gc_id, "Degenerated GC", SvcGCMarker::CONCURRENT); set_active_generation(); _gc->entry_degenerated(); - ShenandoahHeap::heap()->propagate_gc_state_to_all_threads(); } void VM_ShenandoahInitUpdateRefs::doit() { ShenandoahGCPauseMark mark(_gc_id, "Init Update Refs", SvcGCMarker::CONCURRENT); set_active_generation(); _gc->entry_init_update_refs(); - ShenandoahHeap::heap()->propagate_gc_state_to_all_threads(); } void VM_ShenandoahFinalUpdateRefs::doit() { ShenandoahGCPauseMark mark(_gc_id, "Final Update Refs", SvcGCMarker::CONCURRENT); set_active_generation(); _gc->entry_final_update_refs(); - ShenandoahHeap::heap()->propagate_gc_state_to_all_threads(); } void VM_ShenandoahFinalRoots::doit() { ShenandoahGCPauseMark mark(_gc_id, "Final Roots", SvcGCMarker::CONCURRENT); set_active_generation(); _gc->entry_final_roots(); - ShenandoahHeap::heap()->propagate_gc_state_to_all_threads(); } diff --git a/src/hotspot/share/gc/z/zIndexDistributor.hpp b/src/hotspot/share/gc/z/zIndexDistributor.hpp index 94f146176d6..d4b9edcb5b4 100644 --- a/src/hotspot/share/gc/z/zIndexDistributor.hpp +++ b/src/hotspot/share/gc/z/zIndexDistributor.hpp @@ -24,6 +24,8 @@ #ifndef SHARE_GC_Z_ZINDEXDISTRIBUTOR_HPP #define SHARE_GC_Z_ZINDEXDISTRIBUTOR_HPP +#include <utilities/globalDefinitions.hpp> + class ZIndexDistributor { private: void* _strategy; @@ -39,6 +41,10 @@ class ZIndexDistributor { template <typename Function> void do_indices(Function function); + + // Returns a count that is max_count or larger and upholds the requirements + // for using the ZIndexDistributor strategy specfied by ZIndexDistributorStrategy + static size_t get_count(size_t max_count); }; #endif // SHARE_GC_Z_ZINDEXDISTRIBUTOR_HPP diff --git a/src/hotspot/share/gc/z/zIndexDistributor.inline.hpp b/src/hotspot/share/gc/z/zIndexDistributor.inline.hpp index c582be8fcee..163dd2ad685 100644 --- a/src/hotspot/share/gc/z/zIndexDistributor.inline.hpp +++ b/src/hotspot/share/gc/z/zIndexDistributor.inline.hpp @@ -32,11 +32,13 @@ #include "runtime/os.hpp" #include "runtime/thread.hpp" #include "utilities/align.hpp" +#include "utilities/powerOfTwo.hpp" class ZIndexDistributorStriped : public CHeapObj<mtGC> { static const int MemSize = 4096; + static const int StripeCount = MemSize / ZCacheLineSize; - const int _max_index; + const int _count; // For claiming a stripe volatile int _claim_stripe; // For claiming inside a stripe @@ -51,8 +53,8 @@ class ZIndexDistributorStriped : public CHeapObj<mtGC> { } public: - ZIndexDistributorStriped(int max_index) - : _max_index(max_index), + ZIndexDistributorStriped(int count) + : _count(count), _claim_stripe(0), _mem() { memset(_mem, 0, MemSize + ZCacheLineSize); @@ -60,11 +62,10 @@ class ZIndexDistributorStriped : public CHeapObj<mtGC> { template <typename Function> void do_indices(Function function) { - const int count = MemSize / ZCacheLineSize; - const int stripe_max = _max_index / count; + const int stripe_max = _count / StripeCount; // Use claiming - for (int i; (i = claim_stripe()) < count;) { + for (int i; (i = claim_stripe()) < StripeCount;) { for (int index; (index = Atomic::fetch_then_add(claim_addr(i), 1, memory_order_relaxed)) < stripe_max;) { if (!function(i * stripe_max + index)) { return; @@ -73,7 +74,7 @@ class ZIndexDistributorStriped : public CHeapObj<mtGC> { } // Use stealing - for (int i = 0; i < count; i++) { + for (int i = 0; i < StripeCount; i++) { for (int index; (index = Atomic::fetch_then_add(claim_addr(i), 1, memory_order_relaxed)) < stripe_max;) { if (!function(i * stripe_max + index)) { return; @@ -81,6 +82,11 @@ class ZIndexDistributorStriped : public CHeapObj<mtGC> { } } } + + static size_t get_count(size_t max_count) { + // Must be multiple of the StripeCount + return align_up(max_count, StripeCount); + } }; class ZIndexDistributorClaimTree : public CHeapObj<mtGC> { @@ -290,6 +296,12 @@ class ZIndexDistributorClaimTree : public CHeapObj<mtGC> { claim_and_do(function, indices, 0 /* level */); steal_and_do(function, indices, 0 /* level */); } + + static size_t get_count(size_t max_count) { + // Must be at least claim_level_size(ClaimLevels) and a power of two + const size_t min_count = claim_level_size(ClaimLevels); + return round_up_power_of_2(MAX2(max_count, min_count)); + } }; // Using dynamically allocated objects just to be able to evaluate @@ -328,4 +340,17 @@ inline void ZIndexDistributor::do_indices(Function function) { }; } +inline size_t ZIndexDistributor::get_count(size_t max_count) { + size_t required_count; + switch (ZIndexDistributorStrategy) { + case 0: required_count = ZIndexDistributorClaimTree::get_count(max_count); break; + case 1: required_count = ZIndexDistributorStriped::get_count(max_count); break; + default: fatal("Unknown ZIndexDistributorStrategy"); + }; + + assert(max_count <= required_count, "unsupported max_count: %zu", max_count); + + return required_count; +} + #endif // SHARE_GC_Z_ZINDEXDISTRIBUTOR_INLINE_HPP diff --git a/src/hotspot/share/gc/z/zLiveMap.inline.hpp b/src/hotspot/share/gc/z/zLiveMap.inline.hpp index 54589e45c45..9a5529dac04 100644 --- a/src/hotspot/share/gc/z/zLiveMap.inline.hpp +++ b/src/hotspot/share/gc/z/zLiveMap.inline.hpp @@ -222,7 +222,7 @@ inline BitMap::idx_t ZLiveMap::find_base_bit_in_segment(BitMap::idx_t start, Bit } // The bitmaps contain pairs of bits to deal with strongly marked vs only - // finalizable marked. Align down to get the the first bit position. + // finalizable marked. Align down to get the first bit position. return bit & ~BitMap::idx_t(1); } diff --git a/src/hotspot/share/gc/z/zMemory.cpp b/src/hotspot/share/gc/z/zMemory.cpp index 14578c2db8a..8ccde9f45a2 100644 --- a/src/hotspot/share/gc/z/zMemory.cpp +++ b/src/hotspot/share/gc/z/zMemory.cpp @@ -100,6 +100,18 @@ zoffset ZMemoryManager::peek_low_address() const { return zoffset(UINTPTR_MAX); } +zoffset_end ZMemoryManager::peak_high_address_end() const { + ZLocker<ZLock> locker(&_lock); + + const ZMemory* const area = _freelist.last(); + if (area != nullptr) { + return area->end(); + } + + // Out of memory + return zoffset_end(UINTPTR_MAX); +} + zoffset ZMemoryManager::alloc_low_address(size_t size) { ZLocker<ZLock> locker(&_lock); diff --git a/src/hotspot/share/gc/z/zMemory.hpp b/src/hotspot/share/gc/z/zMemory.hpp index ce9100f8026..229d5a7c50c 100644 --- a/src/hotspot/share/gc/z/zMemory.hpp +++ b/src/hotspot/share/gc/z/zMemory.hpp @@ -86,6 +86,7 @@ class ZMemoryManager { void register_callbacks(const Callbacks& callbacks); zoffset peek_low_address() const; + zoffset_end peak_high_address_end() const; zoffset alloc_low_address(size_t size); zoffset alloc_low_address_at_most(size_t size, size_t* allocated); zoffset alloc_high_address(size_t size); diff --git a/src/hotspot/share/gc/z/zPageTable.cpp b/src/hotspot/share/gc/z/zPageTable.cpp index 9a4bbc85d04..d960270c451 100644 --- a/src/hotspot/share/gc/z/zPageTable.cpp +++ b/src/hotspot/share/gc/z/zPageTable.cpp @@ -23,13 +23,22 @@ #include "gc/z/zAddress.hpp" #include "gc/z/zGranuleMap.inline.hpp" +#include "gc/z/zIndexDistributor.inline.hpp" #include "gc/z/zPage.inline.hpp" #include "gc/z/zPageTable.inline.hpp" #include "runtime/orderAccess.hpp" #include "utilities/debug.hpp" +static size_t get_max_offset_for_map() { + // The page table has (ZAddressOffsetMax >> ZGranuleSizeShift) slots + const size_t max_count = ZAddressOffsetMax >> ZGranuleSizeShift; + const size_t required_count = ZIndexDistributor::get_count(max_count); + + return required_count << ZGranuleSizeShift; +} + ZPageTable::ZPageTable() - : _map(ZAddressOffsetMax) {} + : _map(get_max_offset_for_map()) {} void ZPageTable::insert(ZPage* page) { const zoffset offset = page->start(); diff --git a/src/hotspot/share/gc/z/zPageTable.hpp b/src/hotspot/share/gc/z/zPageTable.hpp index e809a0ac0ca..fadf550d996 100644 --- a/src/hotspot/share/gc/z/zPageTable.hpp +++ b/src/hotspot/share/gc/z/zPageTable.hpp @@ -45,6 +45,8 @@ class ZPageTable { public: ZPageTable(); + int count() const; + ZPage* get(zaddress addr) const; ZPage* get(volatile zpointer* p) const; diff --git a/src/hotspot/share/gc/z/zPageTable.inline.hpp b/src/hotspot/share/gc/z/zPageTable.inline.hpp index 79a2d297df8..583017d5c9c 100644 --- a/src/hotspot/share/gc/z/zPageTable.inline.hpp +++ b/src/hotspot/share/gc/z/zPageTable.inline.hpp @@ -32,6 +32,15 @@ #include "gc/z/zPage.inline.hpp" #include "gc/z/zPageAllocator.inline.hpp" +#include <limits> + +inline int ZPageTable::count() const { + const size_t size = _map._size; + assert(size <= std::numeric_limits<int>::max(), "Invalid page table size"); + + return static_cast<int>(size); +} + inline ZPage* ZPageTable::get(zaddress addr) const { assert(!is_null(addr), "Invalid address"); return _map.get(ZAddress::offset(addr)); @@ -64,7 +73,7 @@ inline bool ZPageTableIterator::next(ZPage** page) { inline ZPageTableParallelIterator::ZPageTableParallelIterator(const ZPageTable* table) : _table(table), - _index_distributor(int(ZAddressOffsetMax >> ZGranuleSizeShift)) {} + _index_distributor(table->count()) {} template <typename Function> inline void ZPageTableParallelIterator::do_pages(Function function) { diff --git a/src/hotspot/share/gc/z/zRelocate.cpp b/src/hotspot/share/gc/z/zRelocate.cpp index 805044f9deb..213452e8d05 100644 --- a/src/hotspot/share/gc/z/zRelocate.cpp +++ b/src/hotspot/share/gc/z/zRelocate.cpp @@ -669,9 +669,9 @@ class ZRelocateWork : public StackObj { // moved them over to the current bitmap. // // If the young generation runs multiple cycles while the old generation is - // relocating, then the first cycle will have consume the the old remset, + // relocating, then the first cycle will have consumed the old remset, // bits and moved associated objects to a new old page. The old relocation - // could find either the the two bitmaps. So, either it will find the original + // could find either of the two bitmaps. So, either it will find the original // remset bits for the page, or it will find an empty bitmap for the page. It // doesn't matter for correctness, because the young generation marking has // already taken care of the bits. @@ -865,7 +865,7 @@ class ZRelocateWork : public StackObj { start_in_place_relocation_prepare_remset(from_page); if (promotion) { - // Register the the promotion + // Register the promotion ZGeneration::young()->in_place_relocate_promote(from_page, to_page); ZGeneration::young()->register_in_place_relocate_promoted(from_page); } diff --git a/src/hotspot/share/gc/z/zUncoloredRoot.hpp b/src/hotspot/share/gc/z/zUncoloredRoot.hpp index e980bd70eb2..c007176e5c2 100644 --- a/src/hotspot/share/gc/z/zUncoloredRoot.hpp +++ b/src/hotspot/share/gc/z/zUncoloredRoot.hpp @@ -51,7 +51,7 @@ // The zaddress_unsafe type is used to hold uncolored oops that the GC needs // to process before it is safe to use. E.g. the original object might have // been relocated and the address needs to be updated. The zaddress type -// denotes that this pointer refers the the correct address of the object. +// denotes that this pointer refers to the correct address of the object. class ZUncoloredRoot : public AllStatic { private: diff --git a/src/hotspot/share/gc/z/zVirtualMemory.cpp b/src/hotspot/share/gc/z/zVirtualMemory.cpp index ccc30626a3f..21152cf4db6 100644 --- a/src/hotspot/share/gc/z/zVirtualMemory.cpp +++ b/src/hotspot/share/gc/z/zVirtualMemory.cpp @@ -48,6 +48,9 @@ ZVirtualMemoryManager::ZVirtualMemoryManager(size_t max_capacity) return; } + // Set ZAddressOffsetMax to the highest address end available after reservation + ZAddressOffsetMax = untype(highest_available_address_end()); + // Initialize platform specific parts after reserving address space pd_initialize_after_reserve(); diff --git a/src/hotspot/share/gc/z/zVirtualMemory.hpp b/src/hotspot/share/gc/z/zVirtualMemory.hpp index a2df86262ea..57a377ab61b 100644 --- a/src/hotspot/share/gc/z/zVirtualMemory.hpp +++ b/src/hotspot/share/gc/z/zVirtualMemory.hpp @@ -77,6 +77,7 @@ class ZVirtualMemoryManager { size_t reserved() const; zoffset lowest_available_address() const; + zoffset_end highest_available_address_end() const; ZVirtualMemory alloc(size_t size, bool force_low_address); void free(const ZVirtualMemory& vmem); diff --git a/src/hotspot/share/gc/z/zVirtualMemory.inline.hpp b/src/hotspot/share/gc/z/zVirtualMemory.inline.hpp index 972e51a143b..9d5fe7dd57a 100644 --- a/src/hotspot/share/gc/z/zVirtualMemory.inline.hpp +++ b/src/hotspot/share/gc/z/zVirtualMemory.inline.hpp @@ -65,4 +65,8 @@ inline zoffset ZVirtualMemoryManager::lowest_available_address() const { return _manager.peek_low_address(); } +inline zoffset_end ZVirtualMemoryManager::highest_available_address_end() const { + return _manager.peak_high_address_end(); +} + #endif // SHARE_GC_Z_ZVIRTUALMEMORY_INLINE_HPP diff --git a/src/hotspot/share/interpreter/bytecode.hpp b/src/hotspot/share/interpreter/bytecode.hpp index 870fcb7784e..de83cfe5d71 100644 --- a/src/hotspot/share/interpreter/bytecode.hpp +++ b/src/hotspot/share/interpreter/bytecode.hpp @@ -226,6 +226,8 @@ class Bytecode_invoke: public Bytecode_member_ref { bool has_appendix(); + bool has_member_arg() const; + int size_of_parameters() const; private: diff --git a/src/hotspot/share/interpreter/bytecode.inline.hpp b/src/hotspot/share/interpreter/bytecode.inline.hpp index 43e0cf2991d..139f477d397 100644 --- a/src/hotspot/share/interpreter/bytecode.inline.hpp +++ b/src/hotspot/share/interpreter/bytecode.inline.hpp @@ -28,6 +28,7 @@ #include "interpreter/bytecode.hpp" #include "oops/cpCache.inline.hpp" +#include "prims/methodHandles.hpp" inline bool Bytecode_invoke::has_appendix() { if (invoke_code() == Bytecodes::_invokedynamic) { @@ -37,4 +38,13 @@ inline bool Bytecode_invoke::has_appendix() { } } +inline bool Bytecode_invoke::has_member_arg() const { + // NOTE: We could resolve the call and use the resolved adapter method here, but this function + // is used by deoptimization, where resolving could lead to problems, so we avoid that here + // by doing things symbolically. + // + // invokedynamic instructions don't have a class but obviously don't have a MemberName appendix. + return !is_invokedynamic() && MethodHandles::has_member_arg(klass(), name()); +} + #endif // SHARE_INTERPRETER_BYTECODE_INLINE_HPP diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index 24515d3ff9b..90e8fe7187a 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp @@ -388,6 +388,7 @@ Handle CodeInstaller::read_oop(HotSpotCompiledCodeStream* stream, u1 tag, JVMCI_ ScopeValue* CodeInstaller::get_scope_value(HotSpotCompiledCodeStream* stream, u1 tag, BasicType type, ScopeValue* &second, JVMCI_TRAPS) { second = nullptr; + bool stack_slot_is_s2 = true; switch (tag) { case ILLEGAL: { if (type != T_ILLEGAL) { @@ -436,11 +437,17 @@ ScopeValue* CodeInstaller::get_scope_value(HotSpotCompiledCodeStream* stream, u1 return value; } } + case STACK_SLOT4_PRIMITIVE: + case STACK_SLOT4_NARROW_OOP: + case STACK_SLOT4_OOP: + case STACK_SLOT4_VECTOR: + stack_slot_is_s2 = false; + // fall through case STACK_SLOT_PRIMITIVE: case STACK_SLOT_NARROW_OOP: case STACK_SLOT_OOP: case STACK_SLOT_VECTOR: { - jint offset = (jshort) stream->read_s2("offset"); + jint offset = stack_slot_is_s2 ? (jshort) stream->read_s2("offset") : stream->read_s4("offset4"); if (stream->read_bool("addRawFrameSize")) { offset += _total_frame_size; } @@ -854,7 +861,7 @@ void CodeInstaller::initialize_fields(HotSpotCompiledCodeStream* stream, u1 code if (!is_set(code_flags, HCC_HAS_DEOPT_RESCUE_SLOT)) { _orig_pc_offset = -1; } else { - _orig_pc_offset = stream->read_s2("offset"); + _orig_pc_offset = stream->read_s4("offset"); if (stream->read_bool("addRawFrameSize")) { _orig_pc_offset += _total_frame_size; } diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp index b493c48e348..a8279e99dc2 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp @@ -207,6 +207,10 @@ class CodeInstaller : public StackObj { STACK_SLOT_OOP, STACK_SLOT_NARROW_OOP, STACK_SLOT_VECTOR, + STACK_SLOT4_PRIMITIVE, + STACK_SLOT4_OOP, + STACK_SLOT4_NARROW_OOP, + STACK_SLOT4_VECTOR, VIRTUAL_OBJECT_ID, VIRTUAL_OBJECT_ID2, NULL_CONSTANT, diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index cfefd0cf967..0f80cee8abb 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -394,7 +394,13 @@ static_field(StubRoutines, _sha512_implCompress, address) \ static_field(StubRoutines, _sha512_implCompressMB, address) \ static_field(StubRoutines, _sha3_implCompress, address) \ + static_field(StubRoutines, _double_keccak, address) \ static_field(StubRoutines, _sha3_implCompressMB, address) \ + static_field(StubRoutines, _dilithiumAlmostNtt, address) \ + static_field(StubRoutines, _dilithiumAlmostInverseNtt, address) \ + static_field(StubRoutines, _dilithiumNttMult, address) \ + static_field(StubRoutines, _dilithiumMontMulByConstant, address) \ + static_field(StubRoutines, _dilithiumDecomposePoly, address) \ static_field(StubRoutines, _updateBytesCRC32, address) \ static_field(StubRoutines, _crc_table_adr, address) \ static_field(StubRoutines, _crc32c_table_addr, address) \ @@ -579,6 +585,10 @@ declare_constant(CodeInstaller::STACK_SLOT_OOP) \ declare_constant(CodeInstaller::STACK_SLOT_NARROW_OOP) \ declare_constant(CodeInstaller::STACK_SLOT_VECTOR) \ + declare_constant(CodeInstaller::STACK_SLOT4_PRIMITIVE) \ + declare_constant(CodeInstaller::STACK_SLOT4_OOP) \ + declare_constant(CodeInstaller::STACK_SLOT4_NARROW_OOP) \ + declare_constant(CodeInstaller::STACK_SLOT4_VECTOR) \ declare_constant(CodeInstaller::VIRTUAL_OBJECT_ID) \ declare_constant(CodeInstaller::VIRTUAL_OBJECT_ID2) \ declare_constant(CodeInstaller::NULL_CONSTANT) \ @@ -711,6 +721,7 @@ declare_constant(Deoptimization::Reason_constraint) \ declare_constant(Deoptimization::Reason_div0_check) \ declare_constant(Deoptimization::Reason_loop_limit_check) \ + declare_constant(Deoptimization::Reason_auto_vectorization_check) \ declare_constant(Deoptimization::Reason_type_checked_inlining) \ declare_constant(Deoptimization::Reason_optimized_type_check) \ declare_constant(Deoptimization::Reason_aliasing) \ @@ -945,7 +956,7 @@ #ifdef AARCH64 -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ static_field(VM_Version, _zva_length, int) \ static_field(StubRoutines::aarch64, _count_positives, address) \ static_field(StubRoutines::aarch64, _count_positives_long, address) \ @@ -959,11 +970,11 @@ #ifdef X86 -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \ static_field(VM_Version, _has_intel_jcc_erratum, bool) -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) \ LP64_ONLY(declare_constant(frame::arg_reg_save_area_bytes)) \ declare_constant(frame::interpreter_frame_sender_sp_offset) \ declare_constant(frame::interpreter_frame_last_sp_offset) @@ -977,15 +988,15 @@ * Dummy defines for architectures that don't use these. */ #ifndef VM_STRUCTS_CPU -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) #endif #ifndef VM_INT_CONSTANTS_CPU -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) #endif #ifndef VM_LONG_CONSTANTS_CPU -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) #endif #ifndef VM_ADDRESSES_OS @@ -1012,10 +1023,7 @@ VMStructEntry JVMCIVMStructs::localHotSpotVMStructs[] = { GENERATE_STATIC_VM_STRUCT_ENTRY, GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, - GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY) + GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY) #if INCLUDE_G1GC VM_STRUCTS_JVMCI_G1GC(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, @@ -1040,10 +1048,7 @@ VMIntConstantEntry JVMCIVMStructs::localHotSpotVMIntConstants[] = { GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) VM_INT_CONSTANTS_CPU(GENERATE_VM_INT_CONSTANT_ENTRY, - GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, - GENERATE_C1_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) + GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) #if INCLUDE_G1GC VM_INT_CONSTANTS_JVMCI_G1GC(GENERATE_VM_INT_CONSTANT_ENTRY, @@ -1066,10 +1071,7 @@ VMLongConstantEntry JVMCIVMStructs::localHotSpotVMLongConstants[] = { GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) VM_LONG_CONSTANTS_CPU(GENERATE_VM_LONG_CONSTANT_ENTRY, - GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, - GENERATE_C1_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) + GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) #ifdef VM_LONG_CPU_FEATURE_CONSTANTS VM_LONG_CPU_FEATURE_CONSTANTS #endif @@ -1125,10 +1127,7 @@ void JVMCIVMStructs::init() { CHECK_STATIC_VM_STRUCT_ENTRY, CHECK_NO_OP, CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_C2_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_NO_OP, - CHECK_NO_OP); + CHECK_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY) #if INCLUDE_G1GC VM_STRUCTS_JVMCI_G1GC(CHECK_NONSTATIC_VM_STRUCT_ENTRY, diff --git a/src/hotspot/share/memory/arena.cpp b/src/hotspot/share/memory/arena.cpp index 055c6405590..d03c0776f61 100644 --- a/src/hotspot/share/memory/arena.cpp +++ b/src/hotspot/share/memory/arena.cpp @@ -45,13 +45,13 @@ STATIC_ASSERT(is_aligned((int)Chunk::size, ARENA_AMALLOC_ALIGNMENT)); const char* Arena::tag_name[] = { -#define ARENA_TAG_STRING(name, str, desc) XSTR(name), +#define ARENA_TAG_STRING(name, desc) XSTR(name), DO_ARENA_TAG(ARENA_TAG_STRING) #undef ARENA_TAG_STRING }; const char* Arena::tag_desc[] = { -#define ARENA_TAG_DESC(name, str, desc) XSTR(desc), +#define ARENA_TAG_DESC(name, desc) XSTR(desc), DO_ARENA_TAG(ARENA_TAG_DESC) #undef ARENA_TAG_DESC }; @@ -118,11 +118,19 @@ class ChunkPool { } // Returns an initialized and null-terminated Chunk of requested size - static Chunk* allocate_chunk(size_t length, AllocFailType alloc_failmode); + static Chunk* allocate_chunk(Arena* arena, size_t length, AllocFailType alloc_failmode); static void deallocate_chunk(Chunk* p); }; -Chunk* ChunkPool::allocate_chunk(size_t length, AllocFailType alloc_failmode) { +static bool on_compiler_thread() { +#if defined(COMPILER1) || defined(COMPILER2) + return Thread::current_or_null() != nullptr && + Thread::current()->is_Compiler_thread(); +#endif // COMPILER1 || COMPILER2 + return false; +} + +Chunk* ChunkPool::allocate_chunk(Arena* arena, size_t length, AllocFailType alloc_failmode) { // - requested_size = sizeof(Chunk) // - length = payload size // We must ensure that the boundaries of the payload (C and D) are aligned to 64-bit: @@ -164,10 +172,27 @@ Chunk* ChunkPool::allocate_chunk(size_t length, AllocFailType alloc_failmode) { ::new(chunk) Chunk(length); // We rely on arena alignment <= malloc alignment. assert(is_aligned(chunk, ARENA_AMALLOC_ALIGNMENT), "Chunk start address misaligned."); + + if (CompilationMemoryStatistic::enabled() && on_compiler_thread()) { + uint64_t stamp = 0; + CompilationMemoryStatistic::on_arena_chunk_allocation(chunk->length(), (int)arena->get_tag(), &stamp); + chunk->set_stamp(stamp); + } else { + chunk->set_stamp(0); + } + return chunk; } void ChunkPool::deallocate_chunk(Chunk* c) { + + // Inform compilation memstat + if (CompilationMemoryStatistic::enabled() && c->stamp() != 0) { + assert(on_compiler_thread(), "we stamped this chunk"); + CompilationMemoryStatistic::on_arena_chunk_deallocation(c->length(), c->stamp()); + c->set_stamp(0); + } + // If this is a standard-sized chunk, return it to its pool; otherwise free it. ChunkPool* pool = ChunkPool::get_pool_for_size(c->length()); if (pool != nullptr) { @@ -200,8 +225,8 @@ void Arena::start_chunk_pool_cleaner_task() { cleaner->enroll(); } -Chunk::Chunk(size_t length) : _len(length) { - _next = nullptr; // Chain on the linked list +Chunk::Chunk(size_t length) : + _next(nullptr), _len(length), _stamp(0) { } void Chunk::chop(Chunk* k) { @@ -227,7 +252,7 @@ Arena::Arena(MemTag mem_tag, Tag tag, size_t init_size) : _hwm(nullptr), _max(nullptr) { init_size = ARENA_ALIGN(init_size); - _chunk = ChunkPool::allocate_chunk(init_size, AllocFailStrategy::EXIT_OOM); + _chunk = ChunkPool::allocate_chunk(this, init_size, AllocFailStrategy::EXIT_OOM); _first = _chunk; _hwm = _chunk->bottom(); // Save the cached hwm, max _max = _chunk->top(); @@ -258,12 +283,6 @@ void Arena::set_size_in_bytes(size_t size) { ssize_t delta = size - size_in_bytes(); _size_in_bytes = size; MemTracker::record_arena_size_change(delta, _mem_tag); - if (CompilationMemoryStatistic::enabled() && _mem_tag == mtCompiler) { - Thread* const t = Thread::current(); - if (t != nullptr && t->is_Compiler_thread()) { - CompilationMemoryStatistic::on_arena_change(delta, this); - } - } } } @@ -289,7 +308,7 @@ void* Arena::grow(size_t x, AllocFailType alloc_failmode) { } Chunk* k = _chunk; // Get filled-up chunk address - _chunk = ChunkPool::allocate_chunk(len, alloc_failmode); + _chunk = ChunkPool::allocate_chunk(this, len, alloc_failmode); if (_chunk == nullptr) { _chunk = k; // restore the previous value of _chunk diff --git a/src/hotspot/share/memory/arena.hpp b/src/hotspot/share/memory/arena.hpp index 5f0def2a655..01b1ae382db 100644 --- a/src/hotspot/share/memory/arena.hpp +++ b/src/hotspot/share/memory/arena.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,9 @@ class Chunk { private: Chunk* _next; // Next Chunk in list const size_t _len; // Size of this Chunk + // Used for Compilation Memory Statistic + uint64_t _stamp; + public: NONCOPYABLE(Chunk); @@ -66,7 +69,8 @@ class Chunk { tiny_size = 256 - slack, // Size of first chunk (tiny) init_size = 1*K - slack, // Size of first chunk (normal aka small) medium_size= 10*K - slack, // Size of medium-sized chunk - size = 32*K - slack // Default size of an Arena chunk (following the first) + size = 32*K - slack, // Default size of an Arena chunk (following the first) + max_default_size = size // Largest default size }; static void chop(Chunk* chunk); // Chop this chunk @@ -81,19 +85,30 @@ class Chunk { char* bottom() const { return ((char*) this) + aligned_overhead_size(); } char* top() const { return bottom() + _len; } bool contains(char* p) const { return bottom() <= p && p <= top(); } + + void set_stamp(uint64_t v) { _stamp = v; } + uint64_t stamp() const { return _stamp; } }; +// Arena types (for Compilation Memory Statistic) #define DO_ARENA_TAG(FN) \ - FN(other, Others, Other arenas) \ - FN(ra, RA, Resource areas) \ - FN(ha, HA, Handle area) \ - FN(node, NA, Node arena) \ + FN(ra, Resource areas) \ + FN(node, C2 Node arena) \ + FN(comp, C2 Compile arena) \ + FN(type, C2 Type arena) \ + FN(states, C2 Matcher States Arena) \ + FN(reglive, C2 Register Allocation Live Arenas) \ + FN(regsplit, C2 Register Allocation Split Arena) \ + FN(superword, C2 SuperWord Arenas) \ + FN(cienv, CI Env Arena) \ + FN(ha, Handle area) \ + FN(other, Other arenas) \ // Fast allocation of memory class Arena : public CHeapObjBase { public: enum class Tag: uint8_t { -#define ARENA_TAG_ENUM(name, str, desc) tag_##name, +#define ARENA_TAG_ENUM(name, desc) tag_##name, DO_ARENA_TAG(ARENA_TAG_ENUM) #undef ARENA_TAG_ENUM tag_count @@ -114,7 +129,6 @@ class Arena : public CHeapObjBase { protected: friend class HandleMark; friend class NoHandleMark; - friend class VMStructs; Chunk* _first; // First chunk Chunk* _chunk; // current chunk @@ -192,6 +206,7 @@ class Arena : public CHeapObjBase { size_t size_in_bytes() const { return _size_in_bytes; }; void set_size_in_bytes(size_t size); + MemTag get_mem_tag() const { return _mem_tag; } Tag get_tag() const { return _tag; } private: diff --git a/src/hotspot/share/memory/resourceArea.hpp b/src/hotspot/share/memory/resourceArea.hpp index 29dea9ad2f4..557a3c0a24e 100644 --- a/src/hotspot/share/memory/resourceArea.hpp +++ b/src/hotspot/share/memory/resourceArea.hpp @@ -43,8 +43,6 @@ //------------------------------ResourceArea----------------------------------- // A ResourceArea is an Arena that supports safe usage of ResourceMark. class ResourceArea: public Arena { - friend class VMStructs; - #ifdef ASSERT int _nesting; // current # of nested ResourceMarks void verify_has_resource_mark(); @@ -54,8 +52,12 @@ class ResourceArea: public Arena { ResourceArea(MemTag mem_tag = mtThread) : Arena(mem_tag, Arena::Tag::tag_ra) DEBUG_ONLY(COMMA _nesting(0)) {} - ResourceArea(size_t init_size, MemTag mem_tag = mtThread) : - Arena(mem_tag, Arena::Tag::tag_ra, init_size) DEBUG_ONLY(COMMA _nesting(0)) { + ResourceArea(size_t init_size, MemTag mem_tag = mtThread, Arena::Tag arena_tag = Arena::Tag::tag_ra) : + Arena(mem_tag, arena_tag, init_size) DEBUG_ONLY(COMMA _nesting(0)) { + } + + ResourceArea(MemTag mem_tag, Arena::Tag arena_tag) : + Arena(mem_tag, arena_tag) DEBUG_ONLY(COMMA _nesting(0)) { } char* allocate_bytes(size_t size, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM); diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index 76a9fe0a8e1..888e4e117c6 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -575,7 +575,7 @@ void Universe::initialize_basic_type_mirrors(TRAPS) { } } if (CDSConfig::is_dumping_heap()) { - HeapShared::init_scratch_objects(CHECK); + HeapShared::init_scratch_objects_for_basic_type_mirrors(CHECK); } } diff --git a/src/hotspot/share/nmt/vmatree.cpp b/src/hotspot/share/nmt/vmatree.cpp index 21aee26ca87..3352a6e5cd4 100644 --- a/src/hotspot/share/nmt/vmatree.cpp +++ b/src/hotspot/share/nmt/vmatree.cpp @@ -206,7 +206,7 @@ VMATree::SummaryDiff VMATree::register_mapping(position A, position B, StateType } // Finally, we can register the new region [A, B)'s summary data. - SingleDiff& rescom = diff.tag[NMTUtil::tag_to_index(metadata.mem_tag)]; + SingleDiff& rescom = diff.tag[NMTUtil::tag_to_index(stA.out.mem_tag())]; if (state == StateType::Reserved) { rescom.reserve += B - A; } else if (state == StateType::Committed) { diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index 6776f8a0b74..4193e6167a0 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -289,7 +289,7 @@ void ConstantPool::klass_at_put(int class_index, Klass* k) { template <typename Function> void ConstantPool::iterate_archivable_resolved_references(Function function) { objArrayOop rr = resolved_references(); - if (rr != nullptr && cache() != nullptr && CDSConfig::is_dumping_invokedynamic()) { + if (rr != nullptr && cache() != nullptr && CDSConfig::is_dumping_method_handles()) { Array<ResolvedIndyEntry>* indy_entries = cache()->resolved_indy_entries(); if (indy_entries != nullptr) { for (int i = 0; i < indy_entries->length(); i++) { diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp index 136a8175157..d83966c4d72 100644 --- a/src/hotspot/share/oops/cpCache.cpp +++ b/src/hotspot/share/oops/cpCache.cpp @@ -573,7 +573,7 @@ bool ConstantPoolCache::can_archive_resolved_method(ConstantPool* src_cp, Resolv method_entry->is_resolved(Bytecodes::_invokespecial)) { return true; } else if (method_entry->is_resolved(Bytecodes::_invokehandle)) { - if (CDSConfig::is_dumping_invokedynamic()) { + if (CDSConfig::is_dumping_method_handles()) { // invokehandle depends on archived MethodType and LambdaForms. return true; } else { diff --git a/src/hotspot/share/opto/block.hpp b/src/hotspot/share/opto/block.hpp index 231c0994903..4ac6399d3a0 100644 --- a/src/hotspot/share/opto/block.hpp +++ b/src/hotspot/share/opto/block.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, 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 @@ struct Tarjan; // Note that the constructor just zeros things, and since I use Arena // allocation I do not need a destructor to reclaim storage. class Block_Array : public ArenaObj { - friend class VMStructs; uint _size; // allocated size, as opposed to formal limit debug_only(uint _limit;) // limit to formal domain Arena *_arena; // Arena to allocate in @@ -75,7 +74,6 @@ class Block_Array : public ArenaObj { class Block_List : public Block_Array { - friend class VMStructs; public: uint _cnt; Block_List() : Block_List(Thread::current()->resource_area()) { } @@ -93,7 +91,6 @@ class Block_List : public Block_Array { class CFGElement : public AnyObj { - friend class VMStructs; public: double _freq; // Execution frequency (estimate) @@ -109,7 +106,6 @@ class CFGElement : public AnyObj { // Basic blocks are used during the output routines, and are not used during // any optimization pass. They are created late in the game. class Block : public CFGElement { - friend class VMStructs; private: // Nodes in this block, in order @@ -372,7 +368,6 @@ class Block : public CFGElement { //------------------------------PhaseCFG--------------------------------------- // Build an array of Basic Block pointers, one per Node. class PhaseCFG : public Phase { - friend class VMStructs; private: // Root of whole program RootNode* _root; @@ -703,7 +698,6 @@ class BlockProbPair { //------------------------------CFGLoop------------------------------------------- class CFGLoop : public CFGElement { - friend class VMStructs; int _id; int _depth; CFGLoop *_parent; // root of loop tree is the method level "pseudo" loop, it's parent is null @@ -756,7 +750,6 @@ class CFGLoop : public CFGElement { // A edge between two basic blocks that will be embodied by a branch or a // fall-through. class CFGEdge : public ResourceObj { - friend class VMStructs; private: Block * _from; // Source basic block Block * _to; // Destination basic block @@ -892,7 +885,6 @@ class Trace : public ResourceObj { //------------------------------PhaseBlockLayout------------------------------- // Rearrange blocks into some canonical order, based on edges and their frequencies class PhaseBlockLayout : public Phase { - friend class VMStructs; PhaseCFG &_cfg; // Control flow graph GrowableArray<CFGEdge *> *edges; diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index 8804a4f3e2a..468f929fb42 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -346,6 +346,12 @@ develop(bool, TraceLoopUnswitching, false, \ "Trace loop unswitching") \ \ + product(bool, LoopMultiversioning, true, DIAGNOSTIC, \ + "Enable loop multiversioning (for speculative compilation)") \ + \ + develop(bool, TraceLoopMultiversioning, false, \ + "Trace loop multiversioning") \ + \ product(bool, AllowVectorizeOnDemand, true, \ "Globally suppress vectorization set in VectorizeMethod") \ \ diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp index 1f7be6c9f3f..0377b7f22dd 100644 --- a/src/hotspot/share/opto/c2compiler.cpp +++ b/src/hotspot/share/opto/c2compiler.cpp @@ -787,6 +787,7 @@ bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { case vmIntrinsics::_sha2_implCompress: case vmIntrinsics::_sha5_implCompress: case vmIntrinsics::_sha3_implCompress: + case vmIntrinsics::_double_keccak: case vmIntrinsics::_digestBase_implCompressMB: case vmIntrinsics::_multiplyToLen: case vmIntrinsics::_squareToLen: @@ -796,6 +797,11 @@ bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { case vmIntrinsics::_vectorizedMismatch: case vmIntrinsics::_ghash_processBlocks: case vmIntrinsics::_chacha20Block: + case vmIntrinsics::_dilithiumAlmostNtt: + case vmIntrinsics::_dilithiumAlmostInverseNtt: + case vmIntrinsics::_dilithiumNttMult: + case vmIntrinsics::_dilithiumMontMulByConstant: + case vmIntrinsics::_dilithiumDecomposePoly: case vmIntrinsics::_base64_encodeBlock: case vmIntrinsics::_base64_decodeBlock: case vmIntrinsics::_poly1305_processBlocks: diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index 79e1fcbb27a..dd4892638e8 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -197,7 +197,6 @@ class TailJumpNode : public ReturnNode { // This provides a way to map the optimized program back into the interpreter, // or to let the GC mark the stack. class JVMState : public ResourceObj { - friend class VMStructs; public: typedef enum { Reexecute_Undefined = -1, // not defined -- will be translated into false later @@ -330,7 +329,6 @@ class JVMState : public ResourceObj { class SafePointNode : public MultiNode { friend JVMState; friend class GraphKit; - friend class VMStructs; virtual bool cmp( const Node &n ) const; virtual uint size_of() const; // Size is bigger @@ -689,7 +687,6 @@ class CallGenerator; // Call nodes now subsume the function of debug nodes at callsites, so they // contain the functionality of a full scope chain of debug nodes. class CallNode : public SafePointNode { - friend class VMStructs; protected: bool may_modify_arraycopy_helper(const TypeOopPtr* dest_t, const TypeOopPtr* t_oop, PhaseValues* phase); @@ -779,7 +776,6 @@ class CallNode : public SafePointNode { // convention. (The "Java" calling convention is the compiler's calling // convention, as opposed to the interpreter's or that of native C.) class CallJavaNode : public CallNode { - friend class VMStructs; protected: virtual bool cmp( const Node &n ) const; virtual uint size_of() const; // Size is bigger diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index 889b1a011f5..b54ca64530f 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -438,7 +438,7 @@ class IfNode : public MultiBranchNode { IfNode(Node* control, Node* bol, float p, float fcnt); IfNode(Node* control, Node* bol, float p, float fcnt, AssertionPredicateType assertion_predicate_type); - static IfNode* make_with_same_profile(IfNode* if_node_profile, Node* ctrl, BoolNode* bol); + static IfNode* make_with_same_profile(IfNode* if_node_profile, Node* ctrl, Node* bol); virtual int Opcode() const; virtual bool pinned() const { return true; } diff --git a/src/hotspot/share/opto/chaitin.cpp b/src/hotspot/share/opto/chaitin.cpp index da676c9d5ee..4b322d0b3ae 100644 --- a/src/hotspot/share/opto/chaitin.cpp +++ b/src/hotspot/share/opto/chaitin.cpp @@ -366,8 +366,8 @@ void PhaseChaitin::Register_Allocate() { _alternate = 0; _matcher._allocation_started = true; - ResourceArea split_arena(mtCompiler); // Arena for Split local resources - ResourceArea live_arena(mtCompiler); // Arena for liveness & IFG info + ResourceArea split_arena(mtCompiler, Arena::Tag::tag_regsplit); // Arena for Split local resources + ResourceArea live_arena(mtCompiler, Arena::Tag::tag_reglive); // Arena for liveness & IFG info ResourceMark rm(&live_arena); // Need live-ness for the IFG; need the IFG for coalescing. If the diff --git a/src/hotspot/share/opto/chaitin.hpp b/src/hotspot/share/opto/chaitin.hpp index cf02deb6019..4b74420f996 100644 --- a/src/hotspot/share/opto/chaitin.hpp +++ b/src/hotspot/share/opto/chaitin.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, 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 @@ class PhaseChaitin; //------------------------------LRG-------------------------------------------- // Live-RanGe structure. class LRG : public ResourceObj { - friend class VMStructs; public: static const uint AllStack_size = 0xFFFFF; // This mask size is used to tell that the mask of this LRG supports stack positions enum { SPILL_REG=29999 }; // Register number of a spilled LRG @@ -236,7 +235,6 @@ class LRG : public ResourceObj { // abstract! It needs abstraction so I can fiddle with the implementation to // get even more speed. class PhaseIFG : public Phase { - friend class VMStructs; // Current implementation: a triangular adjacency list. // Array of adjacency-lists, indexed by live-range number @@ -417,7 +415,6 @@ class LiveRangeMap { //------------------------------Chaitin---------------------------------------- // Briggs-Chaitin style allocation, mostly. class PhaseChaitin : public PhaseRegAlloc { - friend class VMStructs; int _trip_cnt; int _alternate; diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp index a8fe902e4a6..95876174f0f 100644 --- a/src/hotspot/share/opto/classes.hpp +++ b/src/hotspot/share/opto/classes.hpp @@ -279,6 +279,7 @@ macro(OnSpinWait) macro(Opaque1) macro(OpaqueLoopInit) macro(OpaqueLoopStride) +macro(OpaqueMultiversioning) macro(OpaqueZeroTripGuard) macro(OpaqueNotNull) macro(OpaqueInitializedAssertionPredicate) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 7aaf540bae1..914c478a080 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -41,6 +41,7 @@ #include "jfr/jfrEvents.hpp" #include "jvm_io.h" #include "memory/allocation.hpp" +#include "memory/arena.hpp" #include "memory/resourceArea.hpp" #include "opto/addnode.hpp" #include "opto/block.hpp" @@ -441,6 +442,9 @@ void Compile::disconnect_useless_nodes(Unique_Node_List& useful, Unique_Node_Lis n->raw_del_out(j); --j; --max; + if (child->is_data_proj_of_pure_function(n)) { + worklist.push(n); + } } } if (n->outcnt() == 1 && n->has_special_unique_user()) { @@ -650,7 +654,7 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci, _has_method_handle_invokes(false), _clinit_barrier_on_entry(false), _stress_seed(0), - _comp_arena(mtCompiler), + _comp_arena(mtCompiler, Arena::Tag::tag_comp), _barrier_set_state(BarrierSet::barrier_set()->barrier_set_c2()->create_barrier_state(comp_arena())), _env(ci_env), _directive(directive), @@ -674,7 +678,7 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci, _node_arena_two(mtCompiler, Arena::Tag::tag_node), _node_arena(&_node_arena_one), _mach_constant_base_node(nullptr), - _Compile_types(mtCompiler), + _Compile_types(mtCompiler, Arena::Tag::tag_type), _initial_gvn(nullptr), _igvn_worklist(nullptr), _types(nullptr), @@ -937,7 +941,7 @@ Compile::Compile(ciEnv* ci_env, _has_method_handle_invokes(false), _clinit_barrier_on_entry(false), _stress_seed(0), - _comp_arena(mtCompiler), + _comp_arena(mtCompiler, Arena::Tag::tag_comp), _barrier_set_state(BarrierSet::barrier_set()->barrier_set_c2()->create_barrier_state(comp_arena())), _env(ci_env), _directive(directive), @@ -949,11 +953,11 @@ Compile::Compile(ciEnv* ci_env, _unique(0), _dead_node_count(0), _dead_node_list(comp_arena()), - _node_arena_one(mtCompiler), - _node_arena_two(mtCompiler), + _node_arena_one(mtCompiler, Arena::Tag::tag_node), + _node_arena_two(mtCompiler, Arena::Tag::tag_node), _node_arena(&_node_arena_one), _mach_constant_base_node(nullptr), - _Compile_types(mtCompiler), + _Compile_types(mtCompiler, Arena::Tag::tag_type), _initial_gvn(nullptr), _igvn_worklist(nullptr), _types(nullptr), @@ -3492,6 +3496,13 @@ void Compile::Code_Gen() { print_method(PHASE_POSTALLOC_EXPAND, 3); } +#ifdef ASSERT + { + CompilationMemoryStatistic::do_test_allocations(); + if (failing()) return; + } +#endif + // Convert Nodes to instruction bits in a buffer { TracePhase tp(_t_output); @@ -4799,6 +4810,7 @@ Compile::TracePhase::TracePhase(const char* name, PhaseTraceId id) _dolog(CITimeVerbose) { assert(_compile != nullptr, "sanity check"); + assert(id != PhaseTraceId::_t_none, "Don't use none"); if (_dolog) { _log = _compile->log(); } @@ -4807,12 +4819,23 @@ Compile::TracePhase::TracePhase(const char* name, PhaseTraceId id) _log->stamp(); _log->end_head(); } + + // Inform memory statistic, if enabled + if (CompilationMemoryStatistic::enabled()) { + CompilationMemoryStatistic::on_phase_start((int)id, name); + } } Compile::TracePhase::TracePhase(PhaseTraceId id) : TracePhase(Phase::get_phase_trace_id_text(id), id) {} Compile::TracePhase::~TracePhase() { + + // Inform memory statistic, if enabled + if (CompilationMemoryStatistic::enabled()) { + CompilationMemoryStatistic::on_phase_end(); + } + if (_compile->failing_internal()) { if (_log != nullptr) { _log->done("phase"); diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 5d28b524ea5..f913c621e1f 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -177,7 +177,6 @@ class CloneMap { class Options { friend class Compile; - friend class VMStructs; private: const bool _subsume_loads; // Load can be matched as part of a larger op. const bool _do_escape_analysis; // Do escape analysis. @@ -224,7 +223,6 @@ class Options { // This class defines a top-level Compiler invocation. class Compile : public Phase { - friend class VMStructs; public: // Fixed alias indexes. (See also MergeMemNode.) @@ -240,9 +238,9 @@ class Compile : public Phase { // (The time collection itself is always conditionalized on CITime.) class TracePhase : public TraceTime { private: - Compile* _compile; + Compile* const _compile; CompileLog* _log; - bool _dolog; + const bool _dolog; public: TracePhase(PhaseTraceId phaseTraceId); TracePhase(const char* name, PhaseTraceId phaseTraceId); diff --git a/src/hotspot/share/opto/divnode.cpp b/src/hotspot/share/opto/divnode.cpp index b406b8ff38e..fad86755cf6 100644 --- a/src/hotspot/share/opto/divnode.cpp +++ b/src/hotspot/share/opto/divnode.cpp @@ -1515,6 +1515,12 @@ Node* ModFNode::Ideal(PhaseGVN* phase, bool can_reshape) { if (!can_reshape) { return nullptr; } + PhaseIterGVN* igvn = phase->is_IterGVN(); + + bool result_is_unused = proj_out_or_null(TypeFunc::Parms) == nullptr; + if (result_is_unused) { + return replace_with_con(igvn, TypeF::make(0.)); + } // Either input is TOP ==> the result is TOP const Type* t1 = phase->type(dividend()); @@ -1535,10 +1541,10 @@ Node* ModFNode::Ideal(PhaseGVN* phase, bool can_reshape) { // If either is a NaN, return an input NaN if (g_isnan(f1)) { - return replace_with_con(phase, t1); + return replace_with_con(igvn, t1); } if (g_isnan(f2)) { - return replace_with_con(phase, t2); + return replace_with_con(igvn, t2); } // If an operand is infinity or the divisor is +/- zero, punt. @@ -1553,13 +1559,19 @@ Node* ModFNode::Ideal(PhaseGVN* phase, bool can_reshape) { xr ^= min_jint; } - return replace_with_con(phase, TypeF::make(jfloat_cast(xr))); + return replace_with_con(igvn, TypeF::make(jfloat_cast(xr))); } Node* ModDNode::Ideal(PhaseGVN* phase, bool can_reshape) { if (!can_reshape) { return nullptr; } + PhaseIterGVN* igvn = phase->is_IterGVN(); + + bool result_is_unused = proj_out_or_null(TypeFunc::Parms) == nullptr; + if (result_is_unused) { + return replace_with_con(igvn, TypeD::make(0.)); + } // Either input is TOP ==> the result is TOP const Type* t1 = phase->type(dividend()); @@ -1580,10 +1592,10 @@ Node* ModDNode::Ideal(PhaseGVN* phase, bool can_reshape) { // If either is a NaN, return an input NaN if (g_isnan(f1)) { - return replace_with_con(phase, t1); + return replace_with_con(igvn, t1); } if (g_isnan(f2)) { - return replace_with_con(phase, t2); + return replace_with_con(igvn, t2); } // If an operand is infinity or the divisor is +/- zero, punt. @@ -1598,32 +1610,32 @@ Node* ModDNode::Ideal(PhaseGVN* phase, bool can_reshape) { xr ^= min_jlong; } - return replace_with_con(phase, TypeD::make(jdouble_cast(xr))); + return replace_with_con(igvn, TypeD::make(jdouble_cast(xr))); } -Node* ModFloatingNode::replace_with_con(PhaseGVN* phase, const Type* con) { +Node* ModFloatingNode::replace_with_con(PhaseIterGVN* phase, const Type* con) { Compile* C = phase->C; Node* con_node = phase->makecon(con); CallProjections* projs = extract_projections(false, false); - C->gvn_replace_by(projs->fallthrough_proj, in(TypeFunc::Control)); + phase->replace_node(projs->fallthrough_proj, in(TypeFunc::Control)); if (projs->fallthrough_catchproj != nullptr) { - C->gvn_replace_by(projs->fallthrough_catchproj, in(TypeFunc::Control)); + phase->replace_node(projs->fallthrough_catchproj, in(TypeFunc::Control)); } if (projs->fallthrough_memproj != nullptr) { - C->gvn_replace_by(projs->fallthrough_memproj, in(TypeFunc::Memory)); + phase->replace_node(projs->fallthrough_memproj, in(TypeFunc::Memory)); } if (projs->catchall_memproj != nullptr) { - C->gvn_replace_by(projs->catchall_memproj, C->top()); + phase->replace_node(projs->catchall_memproj, C->top()); } if (projs->fallthrough_ioproj != nullptr) { - C->gvn_replace_by(projs->fallthrough_ioproj, in(TypeFunc::I_O)); + phase->replace_node(projs->fallthrough_ioproj, in(TypeFunc::I_O)); } assert(projs->catchall_ioproj == nullptr, "no exceptions from floating mod"); assert(projs->catchall_catchproj == nullptr, "no exceptions from floating mod"); if (projs->resproj[0] != nullptr) { - C->gvn_replace_by(projs->resproj[0], con_node); + phase->replace_node(projs->resproj[0], con_node); } - C->gvn_replace_by(this, C->top()); + phase->replace_node(this, C->top()); C->remove_macro_node(this); disconnect_inputs(C); return nullptr; diff --git a/src/hotspot/share/opto/divnode.hpp b/src/hotspot/share/opto/divnode.hpp index b48bb9b5acc..f8f07a4074f 100644 --- a/src/hotspot/share/opto/divnode.hpp +++ b/src/hotspot/share/opto/divnode.hpp @@ -158,7 +158,7 @@ class ModLNode : public Node { // Base class for float and double modulus class ModFloatingNode : public CallLeafNode { protected: - Node* replace_with_con(PhaseGVN* phase, const Type* con); + Node* replace_with_con(PhaseIterGVN* phase, const Type* con); public: ModFloatingNode(Compile* C, const TypeFunc* tf, const char *name); diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index ec708357440..75301e143dd 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -2242,6 +2242,11 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { strcmp(call->as_CallLeaf()->_name, "intpoly_assign") == 0 || strcmp(call->as_CallLeaf()->_name, "ghash_processBlocks") == 0 || strcmp(call->as_CallLeaf()->_name, "chacha20Block") == 0 || + strcmp(call->as_CallLeaf()->_name, "dilithiumAlmostNtt") == 0 || + strcmp(call->as_CallLeaf()->_name, "dilithiumAlmostInverseNtt") == 0 || + strcmp(call->as_CallLeaf()->_name, "dilithiumNttMult") == 0 || + strcmp(call->as_CallLeaf()->_name, "dilithiumMontMulByConstant") == 0 || + strcmp(call->as_CallLeaf()->_name, "dilithiumDecomposePoly") == 0 || strcmp(call->as_CallLeaf()->_name, "encodeBlock") == 0 || strcmp(call->as_CallLeaf()->_name, "decodeBlock") == 0 || strcmp(call->as_CallLeaf()->_name, "md5_implCompress") == 0 || @@ -2253,6 +2258,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { strcmp(call->as_CallLeaf()->_name, "sha512_implCompress") == 0 || strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0 || strcmp(call->as_CallLeaf()->_name, "sha3_implCompress") == 0 || + strcmp(call->as_CallLeaf()->_name, "double_keccak") == 0 || strcmp(call->as_CallLeaf()->_name, "sha3_implCompressMB") == 0 || strcmp(call->as_CallLeaf()->_name, "multiplyToLen") == 0 || strcmp(call->as_CallLeaf()->_name, "squareToLen") == 0 || @@ -4564,7 +4570,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist, } } else if (n->is_AddP()) { if (has_reducible_merge_base(n->as_AddP(), reducible_merges)) { - // This AddP will go away when we reduce the the Phi + // This AddP will go away when we reduce the Phi continue; } Node* addp_base = get_addp_base(n); diff --git a/src/hotspot/share/opto/gcm.cpp b/src/hotspot/share/opto/gcm.cpp index 7d6d82de4ff..5d2089c5e23 100644 --- a/src/hotspot/share/opto/gcm.cpp +++ b/src/hotspot/share/opto/gcm.cpp @@ -1698,7 +1698,7 @@ void PhaseCFG::global_code_motion() { // Enabling the scheduler for register pressure plus finding blocks of size to schedule for it // is key to enabling this feature. PhaseChaitin regalloc(C->unique(), *this, _matcher, true); - ResourceArea live_arena(mtCompiler); // Arena for liveness + ResourceArea live_arena(mtCompiler, Arena::Tag::tag_reglive); // Arena for liveness ResourceMark rm_live(&live_arena); PhaseLive live(*this, regalloc._lrg_map.names(), &live_arena, true); PhaseIFG ifg(&live_arena); diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 502607ba031..925f51d6016 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -4571,6 +4571,7 @@ void GraphKit::add_parse_predicates(int nargs) { if (UseProfiledLoopPredicate) { add_parse_predicate(Deoptimization::Reason_profile_predicate, nargs); } + add_parse_predicate(Deoptimization::Reason_auto_vectorization_check, nargs); // Loop Limit Check Predicate should be near the loop. add_parse_predicate(Deoptimization::Reason_loop_limit_check, nargs); } diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp index 0c5954dd898..69736c0f95e 100644 --- a/src/hotspot/share/opto/ifnode.cpp +++ b/src/hotspot/share/opto/ifnode.cpp @@ -469,7 +469,7 @@ static Node* split_if(IfNode *iff, PhaseIterGVN *igvn) { return new ConINode(TypeInt::ZERO); } -IfNode* IfNode::make_with_same_profile(IfNode* if_node_profile, Node* ctrl, BoolNode* bol) { +IfNode* IfNode::make_with_same_profile(IfNode* if_node_profile, Node* ctrl, Node* bol) { // Assert here that we only try to create a clone from an If node with the same profiling if that actually makes sense. // Some If node subtypes should not be cloned in this way. In theory, we should not clone BaseCountedLoopEndNodes. // But they can end up being used as normal If nodes when peeling a loop - they serve as zero-trip guard. @@ -2194,6 +2194,7 @@ ParsePredicateNode::ParsePredicateNode(Node* control, Deoptimization::DeoptReaso switch (deopt_reason) { case Deoptimization::Reason_predicate: case Deoptimization::Reason_profile_predicate: + case Deoptimization::Reason_auto_vectorization_check: case Deoptimization::Reason_loop_limit_check: break; default: @@ -2231,6 +2232,9 @@ void ParsePredicateNode::dump_spec(outputStream* st) const { case Deoptimization::DeoptReason::Reason_profile_predicate: st->print("Profiled Loop "); break; + case Deoptimization::DeoptReason::Reason_auto_vectorization_check: + st->print("Auto_Vectorization_Check "); + break; case Deoptimization::DeoptReason::Reason_loop_limit_check: st->print("Loop Limit Check "); break; diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 592ff2d82e3..4c76230e040 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -601,6 +601,8 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_sha5_implCompress: case vmIntrinsics::_sha3_implCompress: return inline_digestBase_implCompress(intrinsic_id()); + case vmIntrinsics::_double_keccak: + return inline_double_keccak(); case vmIntrinsics::_digestBase_implCompressMB: return inline_digestBase_implCompressMB(predicate); @@ -631,6 +633,16 @@ bool LibraryCallKit::try_to_inline(int predicate) { return inline_ghash_processBlocks(); case vmIntrinsics::_chacha20Block: return inline_chacha20Block(); + case vmIntrinsics::_dilithiumAlmostNtt: + return inline_dilithiumAlmostNtt(); + case vmIntrinsics::_dilithiumAlmostInverseNtt: + return inline_dilithiumAlmostInverseNtt(); + case vmIntrinsics::_dilithiumNttMult: + return inline_dilithiumNttMult(); + case vmIntrinsics::_dilithiumMontMulByConstant: + return inline_dilithiumMontMulByConstant(); + case vmIntrinsics::_dilithiumDecomposePoly: + return inline_dilithiumDecomposePoly(); case vmIntrinsics::_base64_encodeBlock: return inline_base64_encodeBlock(); case vmIntrinsics::_base64_decodeBlock: @@ -7976,6 +7988,176 @@ bool LibraryCallKit::inline_chacha20Block() { return true; } +//------------------------------inline_dilithiumAlmostNtt +bool LibraryCallKit::inline_dilithiumAlmostNtt() { + address stubAddr; + const char *stubName; + assert(UseDilithiumIntrinsics, "need Dilithium intrinsics support"); + assert(callee()->signature()->size() == 2, "dilithiumAlmostNtt has 2 parameters"); + + stubAddr = StubRoutines::dilithiumAlmostNtt(); + stubName = "dilithiumAlmostNtt"; + if (!stubAddr) return false; + + Node* coeffs = argument(0); + Node* ntt_zetas = argument(1); + + coeffs = must_be_not_null(coeffs, true); + ntt_zetas = must_be_not_null(ntt_zetas, true); + + Node* coeffs_start = array_element_address(coeffs, intcon(0), T_INT); + assert(coeffs_start, "coeffs is null"); + Node* ntt_zetas_start = array_element_address(ntt_zetas, intcon(0), T_INT); + assert(ntt_zetas_start, "ntt_zetas is null"); + Node* dilithiumAlmostNtt = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::dilithiumAlmostNtt_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + coeffs_start, ntt_zetas_start); + // return an int + Node* retvalue = _gvn.transform(new ProjNode(dilithiumAlmostNtt, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + +//------------------------------inline_dilithiumAlmostInverseNtt +bool LibraryCallKit::inline_dilithiumAlmostInverseNtt() { + address stubAddr; + const char *stubName; + assert(UseDilithiumIntrinsics, "need Dilithium intrinsics support"); + assert(callee()->signature()->size() == 2, "dilithiumAlmostInverseNtt has 2 parameters"); + + stubAddr = StubRoutines::dilithiumAlmostInverseNtt(); + stubName = "dilithiumAlmostInverseNtt"; + if (!stubAddr) return false; + + Node* coeffs = argument(0); + Node* zetas = argument(1); + + coeffs = must_be_not_null(coeffs, true); + zetas = must_be_not_null(zetas, true); + + Node* coeffs_start = array_element_address(coeffs, intcon(0), T_INT); + assert(coeffs_start, "coeffs is null"); + Node* zetas_start = array_element_address(zetas, intcon(0), T_INT); + assert(zetas_start, "inverseNtt_zetas is null"); + Node* dilithiumAlmostInverseNtt = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::dilithiumAlmostInverseNtt_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + coeffs_start, zetas_start); + + // return an int + Node* retvalue = _gvn.transform(new ProjNode(dilithiumAlmostInverseNtt, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + +//------------------------------inline_dilithiumNttMult +bool LibraryCallKit::inline_dilithiumNttMult() { + address stubAddr; + const char *stubName; + assert(UseDilithiumIntrinsics, "need Dilithium intrinsics support"); + assert(callee()->signature()->size() == 3, "dilithiumNttMult has 3 parameters"); + + stubAddr = StubRoutines::dilithiumNttMult(); + stubName = "dilithiumNttMult"; + if (!stubAddr) return false; + + Node* result = argument(0); + Node* ntta = argument(1); + Node* nttb = argument(2); + + result = must_be_not_null(result, true); + ntta = must_be_not_null(ntta, true); + nttb = must_be_not_null(nttb, true); + + Node* result_start = array_element_address(result, intcon(0), T_INT); + assert(result_start, "result is null"); + Node* ntta_start = array_element_address(ntta, intcon(0), T_INT); + assert(ntta_start, "ntta is null"); + Node* nttb_start = array_element_address(nttb, intcon(0), T_INT); + assert(nttb_start, "nttb is null"); + Node* dilithiumNttMult = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::dilithiumNttMult_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + result_start, ntta_start, nttb_start); + + // return an int + Node* retvalue = _gvn.transform(new ProjNode(dilithiumNttMult, TypeFunc::Parms)); + set_result(retvalue); + + return true; +} + +//------------------------------inline_dilithiumMontMulByConstant +bool LibraryCallKit::inline_dilithiumMontMulByConstant() { + address stubAddr; + const char *stubName; + assert(UseDilithiumIntrinsics, "need Dilithium intrinsics support"); + assert(callee()->signature()->size() == 2, "dilithiumMontMulByConstant has 2 parameters"); + + stubAddr = StubRoutines::dilithiumMontMulByConstant(); + stubName = "dilithiumMontMulByConstant"; + if (!stubAddr) return false; + + Node* coeffs = argument(0); + Node* constant = argument(1); + + coeffs = must_be_not_null(coeffs, true); + + Node* coeffs_start = array_element_address(coeffs, intcon(0), T_INT); + assert(coeffs_start, "coeffs is null"); + Node* dilithiumMontMulByConstant = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::dilithiumMontMulByConstant_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + coeffs_start, constant); + + // return an int + Node* retvalue = _gvn.transform(new ProjNode(dilithiumMontMulByConstant, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + + +//------------------------------inline_dilithiumDecomposePoly +bool LibraryCallKit::inline_dilithiumDecomposePoly() { + address stubAddr; + const char *stubName; + assert(UseDilithiumIntrinsics, "need Dilithium intrinsics support"); + assert(callee()->signature()->size() == 5, "dilithiumDecomposePoly has 5 parameters"); + + stubAddr = StubRoutines::dilithiumDecomposePoly(); + stubName = "dilithiumDecomposePoly"; + if (!stubAddr) return false; + + Node* input = argument(0); + Node* lowPart = argument(1); + Node* highPart = argument(2); + Node* twoGamma2 = argument(3); + Node* multiplier = argument(4); + + input = must_be_not_null(input, true); + lowPart = must_be_not_null(lowPart, true); + highPart = must_be_not_null(highPart, true); + + Node* input_start = array_element_address(input, intcon(0), T_INT); + assert(input_start, "input is null"); + Node* lowPart_start = array_element_address(lowPart, intcon(0), T_INT); + assert(lowPart_start, "lowPart is null"); + Node* highPart_start = array_element_address(highPart, intcon(0), T_INT); + assert(highPart_start, "highPart is null"); + + Node* dilithiumDecomposePoly = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::dilithiumDecomposePoly_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + input_start, lowPart_start, highPart_start, + twoGamma2, multiplier); + + // return an int + Node* retvalue = _gvn.transform(new ProjNode(dilithiumDecomposePoly, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + bool LibraryCallKit::inline_base64_encodeBlock() { address stubAddr; const char *stubName; @@ -8239,6 +8421,38 @@ bool LibraryCallKit::inline_digestBase_implCompress(vmIntrinsics::ID id) { return true; } +//------------------------------inline_double_keccak +bool LibraryCallKit::inline_double_keccak() { + address stubAddr; + const char *stubName; + assert(UseSHA3Intrinsics, "need SHA3 intrinsics support"); + assert(callee()->signature()->size() == 2, "double_keccak has 2 parameters"); + + stubAddr = StubRoutines::double_keccak(); + stubName = "double_keccak"; + if (!stubAddr) return false; + + Node* status0 = argument(0); + Node* status1 = argument(1); + + status0 = must_be_not_null(status0, true); + status1 = must_be_not_null(status1, true); + + Node* status0_start = array_element_address(status0, intcon(0), T_LONG); + assert(status0_start, "status0 is null"); + Node* status1_start = array_element_address(status1, intcon(0), T_LONG); + assert(status1_start, "status1 is null"); + Node* double_keccak = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::double_keccak_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + status0_start, status1_start); + // return an int + Node* retvalue = _gvn.transform(new ProjNode(double_keccak, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + + //------------------------------inline_digestBase_implCompressMB----------------------- // // Calculate MD5/SHA/SHA2/SHA5/SHA3 for multi-block byte[] array. diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index b58d59a9e81..63200aae851 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -341,12 +341,18 @@ class LibraryCallKit : public GraphKit { Node* get_key_start_from_aescrypt_object(Node* aescrypt_object); bool inline_ghash_processBlocks(); bool inline_chacha20Block(); + bool inline_dilithiumAlmostNtt(); + bool inline_dilithiumAlmostInverseNtt(); + bool inline_dilithiumNttMult(); + bool inline_dilithiumMontMulByConstant(); + bool inline_dilithiumDecomposePoly(); bool inline_base64_encodeBlock(); bool inline_base64_decodeBlock(); bool inline_poly1305_processBlocks(); bool inline_intpoly_montgomeryMult_P256(); bool inline_intpoly_assign(); bool inline_digestBase_implCompress(vmIntrinsics::ID id); + bool inline_double_keccak(); bool inline_digestBase_implCompressMB(int predicate); bool inline_digestBase_implCompressMB(Node* digestBaseObj, ciInstanceKlass* instklass, BasicType elem_type, address stubAddr, const char *stubName, diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 03a7bf50e70..436d8758df3 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -745,6 +745,11 @@ void PhaseIdealLoop::do_peeling(IdealLoopTree *loop, Node_List &old_new) { cl->set_trip_count(cl->trip_count() - 1); if (cl->is_main_loop()) { cl->set_normal_loop(); + if (cl->is_multiversion()) { + // Peeling also destroys the connection of the main loop + // to the multiversion_if. + cl->set_no_multiversion(); + } #ifndef PRODUCT if (PrintOpto && VerifyLoopOptimizations) { tty->print("Peeling a 'main' loop; resetting to 'normal' "); @@ -1174,8 +1179,9 @@ bool IdealLoopTree::policy_range_check(PhaseIdealLoop* phase, bool provisional, if (!bol->is_Bool()) { assert(bol->is_OpaqueNotNull() || bol->is_OpaqueTemplateAssertionPredicate() || - bol->is_OpaqueInitializedAssertionPredicate(), - "Opaque node of a non-null-check or an Assertion Predicate"); + bol->is_OpaqueInitializedAssertionPredicate() || + bol->is_OpaqueMultiversioning(), + "Opaque node of a non-null-check or an Assertion Predicate or Multiversioning"); continue; } if (bol->as_Bool()->_test._test == BoolTest::ne) { @@ -3354,6 +3360,23 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n // Do nothing special to pre- and post- loops if (cl->is_pre_loop() || cl->is_post_loop()) return true; + // With multiversioning, we create a fast_loop and a slow_loop, and a multiversion_if that + // decides which loop is taken at runtime. At first, the multiversion_if always takes the + // fast_loop, and we only optimize the fast_loop. Since we are not sure if we will ever use + // the slow_loop, we delay optimizations for it, so we do not waste compile time and code + // size. If we never change the condition of the multiversion_if, the slow_loop is eventually + // folded away after loop-opts. While optimizing the fast_loop, we may want to perform some + // speculative optimization, for which we need a runtime-check. We add this runtime-check + // condition to the multiversion_if. Now, it becomes possible to execute the slow_loop at + // runtime, and we resume optimizations for slow_loop ("un-delay" it). + // TLDR: If the slow_loop is still in "delay" mode, check if the multiversion_if was changed + // and we should now resume optimizations for it. + if (cl->is_multiversion_delayed_slow_loop() && + !phase->try_resume_optimizations_for_delayed_slow_loop(this)) { + // We are still delayed, so wait with further loop-opts. + return true; + } + // Compute loop trip count from profile data compute_profile_trip_cnt(phase); @@ -3413,6 +3436,12 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n if (!phase->may_require_nodes(estimate)) { return false; } + + // We are going to add pre-loop and post-loop. + // But should we also multi-version for auto-vectorization speculative + // checks, i.e. fast and slow-paths? + phase->maybe_multiversion_for_auto_vectorization_runtime_checks(this, old_new); + phase->insert_pre_post_loops(this, old_new, peel_only); } // Adjust the pre- and main-loop limits to let the pre and post loops run diff --git a/src/hotspot/share/opto/loopUnswitch.cpp b/src/hotspot/share/opto/loopUnswitch.cpp index 3edad047429..41850f448d1 100644 --- a/src/hotspot/share/opto/loopUnswitch.cpp +++ b/src/hotspot/share/opto/loopUnswitch.cpp @@ -32,6 +32,23 @@ #include "opto/predicates.hpp" #include "opto/rootnode.hpp" +// Multiversioning: +// A loop is cloned, and a selector If decides which loop is taken at run-time: the true-path-loop (original) or the +// false-path-loop (cloned). +// +// Use-cases: +// - Speculative compilation: +// The selector If checks some assumptions which allow stronger optimization in the true-path-loop. If the assumptions +// do not hold, we can still execute in the false-path-loop, although with fewer optimizations. +// See: PhaseIdealLoop::maybe_multiversion_for_auto_vectorization_runtime_checks +// PhaseIdealLoop::create_new_if_for_multiversion +// +// - Unswitching: +// The selector If has the same (loop invariant) condition as some unswitching candidate If inside the loop. This +// allows us to constant-fold the unswitching candidate If to true in the true-path-loop and to false in the +// false-path-loop, thus eliminating the unswitching candidate If from the loop. +// +// // Loop Unswitching is a loop optimization to move an invariant, non-loop-exiting test in the loop body before the loop. // Such a test is either always true or always false in all loop iterations and could therefore only be executed once. // To achieve that, we duplicate the loop and change the original and cloned loop as follows: @@ -338,14 +355,16 @@ class UnswitchCandidate : public StackObj { #endif // NOT PRODUCT }; -// This class creates an If node (i.e. loop selector) that selects if the true-path-loop or the false-path-loop should be -// executed at runtime. This is done by finding an invariant and non-loop-exiting unswitch candidate If node (guaranteed -// to exist at this point) to perform Loop Unswitching on. -class UnswitchedLoopSelector : public StackObj { +// LoopSelector is used for loop multiversioning and unswitching. This class creates an If node (i.e. loop selector) +// that selects if the true-path-loop or the false-path-loop should be executed at runtime. +class LoopSelector : public StackObj { + // Cached fields for construction. PhaseIdealLoop* const _phase; IdealLoopTree* const _outer_loop; Node* const _original_loop_entry; - const UnswitchCandidate& _unswitch_candidate; + const uint _dom_depth; // of original_loop_entry + + // Constructed selector if with its projections. IfNode* const _selector; IfTrueNode* const _true_path_loop_proj; IfFalseNode* const _false_path_loop_proj; @@ -355,25 +374,45 @@ class UnswitchedLoopSelector : public StackObj { }; public: - UnswitchedLoopSelector(IdealLoopTree* loop, const UnswitchCandidate& unswitch_candidate) + // For multiversioning: create a new selector (multiversion_if) from a bol condition. + LoopSelector(IdealLoopTree* loop, Node* bol, float prob, float fcnt) : _phase(loop->_phase), _outer_loop(loop->skip_strip_mined()->_parent), _original_loop_entry(loop->_head->as_Loop()->skip_strip_mined()->in(LoopNode::EntryControl)), - _unswitch_candidate(unswitch_candidate), - _selector(create_selector_if()), + _dom_depth(_phase->dom_depth(_original_loop_entry)), + _selector(create_multiversioning_if(bol, prob, fcnt)), // multiversioning _true_path_loop_proj(create_proj_to_loop(TRUE_PATH)->as_IfTrue()), _false_path_loop_proj(create_proj_to_loop(FALSE_PATH)->as_IfFalse()) { } - NONCOPYABLE(UnswitchedLoopSelector); + + // For unswitching: create an unswitching if before the loop, from a pre-existing + // unswitching_candidate inside the loop. + LoopSelector(IdealLoopTree* loop, const UnswitchCandidate& unswitch_candidate) + : _phase(loop->_phase), + _outer_loop(loop->skip_strip_mined()->_parent), + _original_loop_entry(loop->_head->as_Loop()->skip_strip_mined()->in(LoopNode::EntryControl)), + _dom_depth(_phase->dom_depth(_original_loop_entry)), + _selector(create_unswitching_if(unswitch_candidate)), // unswitching + _true_path_loop_proj(create_proj_to_loop(TRUE_PATH)->as_IfTrue()), + _false_path_loop_proj(create_proj_to_loop(FALSE_PATH)->as_IfFalse()) { + } + NONCOPYABLE(LoopSelector); private: - IfNode* create_selector_if() const { + IfNode* create_multiversioning_if(Node* bol, float prob, float fcnt) { + _phase->igvn().rehash_node_delayed(_original_loop_entry); + IfNode* selector_if = new IfNode(_original_loop_entry, bol, prob, fcnt); + _phase->register_node(selector_if, _outer_loop, _original_loop_entry, _dom_depth); + return selector_if; + } + + IfNode* create_unswitching_if(const UnswitchCandidate& unswitch_candidate) { const uint dom_depth = _phase->dom_depth(_original_loop_entry); _phase->igvn().rehash_node_delayed(_original_loop_entry); - IfNode* unswitch_candidate_if = _unswitch_candidate.candidate(); + IfNode* unswitch_candidate_if = unswitch_candidate.candidate(); BoolNode* selector_bool; - if (_unswitch_candidate.has_multiple_flat_array_check_candidates()) { - selector_bool = _unswitch_candidate.merge_flat_array_checks(); + if (unswitch_candidate.has_multiple_flat_array_check_candidates()) { + selector_bool = unswitch_candidate.merge_flat_array_checks(); } else { selector_bool = unswitch_candidate_if->in(1)->as_Bool(); } @@ -383,14 +422,13 @@ class UnswitchedLoopSelector : public StackObj { } IfProjNode* create_proj_to_loop(const PathToLoop path_to_loop) { - const uint dom_depth = _phase->dom_depth(_original_loop_entry); IfProjNode* proj_to_loop; if (path_to_loop == TRUE_PATH) { proj_to_loop = new IfTrueNode(_selector); } else { proj_to_loop = new IfFalseNode(_selector); } - _phase->register_node(proj_to_loop, _outer_loop, _selector, dom_depth); + _phase->register_node(proj_to_loop, _outer_loop, _selector, _dom_depth); return proj_to_loop; } @@ -408,6 +446,28 @@ class UnswitchedLoopSelector : public StackObj { } }; +// This class creates an If node (i.e. loop selector) that selects if the true-path-loop or the false-path-loop should be +// executed at runtime. This is done by finding an invariant and non-loop-exiting unswitch candidate If node (guaranteed +// to exist at this point) to perform Loop Unswitching on. +class UnswitchedLoopSelector : public StackObj { + const UnswitchCandidate& _unswitch_candidate; + const LoopSelector _loop_selector; + + public: + UnswitchedLoopSelector(IdealLoopTree* loop, const UnswitchCandidate& unswitch_candidate) + : _unswitch_candidate(unswitch_candidate), + _loop_selector(loop, _unswitch_candidate) {} + NONCOPYABLE(UnswitchedLoopSelector); + + IfNode* selector_if() const { + return _loop_selector.selector(); + } + + const LoopSelector& loop_selector() const { + return _loop_selector; + } +}; + // Class to unswitch the original loop and create Predicates at the new unswitched loop versions. The newly cloned loop // becomes the false-path-loop while original loop becomes the true-path-loop. class OriginalLoop : public StackObj { @@ -427,54 +487,61 @@ class OriginalLoop : public StackObj { // Unswitch the original loop on the invariant loop selector by creating a true-path-loop and a false-path-loop. // Remove the unswitch candidate If from both unswitched loop versions which are now covered by the loop selector If. void unswitch(const UnswitchedLoopSelector& unswitched_loop_selector) { + multiversion(unswitched_loop_selector.loop_selector()); + } + + // Multiversion the original loop. The loop selector if selects between the original loop (true-path-loop), and + // a copy of it (false-path-loop). + void multiversion(const LoopSelector& loop_selector) { const uint first_false_path_loop_node_index = _phase->C->unique(); - clone_loop(unswitched_loop_selector); + clone_loop(loop_selector); - move_parse_and_template_assertion_predicates_to_unswitched_loops(unswitched_loop_selector, + move_parse_and_template_assertion_predicates_to_unswitched_loops(loop_selector, first_false_path_loop_node_index); - DEBUG_ONLY(verify_unswitched_loop_versions(_loop->_head->as_Loop(), unswitched_loop_selector);) + DEBUG_ONLY(verify_loop_versions(_loop->_head->as_Loop(), loop_selector);) _phase->recompute_dom_depth(); } private: - void clone_loop(const UnswitchedLoopSelector& unswitched_loop_selector) { + void clone_loop(const LoopSelector& loop_selector) { _phase->clone_loop(_loop, _old_new, _phase->dom_depth(_loop_head), - PhaseIdealLoop::CloneIncludesStripMined, unswitched_loop_selector.selector()); - fix_loop_entries(unswitched_loop_selector); + PhaseIdealLoop::CloneIncludesStripMined, loop_selector.selector()); + fix_loop_entries(loop_selector); } - void fix_loop_entries(const UnswitchedLoopSelector& unswitched_loop_selector) { - _phase->replace_loop_entry(_loop_head, unswitched_loop_selector.true_path_loop_proj()); + void fix_loop_entries(const LoopSelector& loop_selector) { + _phase->replace_loop_entry(_loop_head, loop_selector.true_path_loop_proj()); LoopNode* false_path_loop_strip_mined_head = old_to_new(_loop_head)->as_Loop(); _phase->replace_loop_entry(false_path_loop_strip_mined_head, - unswitched_loop_selector.false_path_loop_proj()); + loop_selector.false_path_loop_proj()); } // Moves the Parse And Template Assertion Predicates to the true and false path loop. They are inserted between the // loop heads and the loop selector If projections. The old Parse and Template Assertion Predicates before // the unswitched loop selector are killed. void move_parse_and_template_assertion_predicates_to_unswitched_loops( - const UnswitchedLoopSelector& unswitched_loop_selector, const uint first_false_path_loop_node_index) const { + const LoopSelector& loop_selector, const uint first_false_path_loop_node_index) const { const NodeInOriginalLoopBody node_in_true_path_loop_body(first_false_path_loop_node_index, _old_new); const NodeInClonedLoopBody node_in_false_path_loop_body(first_false_path_loop_node_index); CloneUnswitchedLoopPredicatesVisitor clone_unswitched_loop_predicates_visitor(_loop_head, old_to_new(_loop_head)->as_Loop(), node_in_true_path_loop_body, node_in_false_path_loop_body, _phase); - Node* source_loop_entry = unswitched_loop_selector.selector()->in(0); + Node* source_loop_entry = loop_selector.selector()->in(0); PredicateIterator predicate_iterator(source_loop_entry); predicate_iterator.for_each(clone_unswitched_loop_predicates_visitor); } #ifdef ASSERT - void verify_unswitched_loop_versions(LoopNode* true_path_loop_head, - const UnswitchedLoopSelector& unswitched_loop_selector) const { - verify_unswitched_loop_version(true_path_loop_head, unswitched_loop_selector.true_path_loop_proj()); - verify_unswitched_loop_version(old_to_new(true_path_loop_head)->as_Loop(), - unswitched_loop_selector.false_path_loop_proj()); + void verify_loop_versions(LoopNode* true_path_loop_head, + const LoopSelector& loop_selector) const { + verify_loop_version(true_path_loop_head, + loop_selector.true_path_loop_proj()); + verify_loop_version(old_to_new(true_path_loop_head)->as_Loop(), + loop_selector.false_path_loop_proj()); } - static void verify_unswitched_loop_version(LoopNode* loop_head, IfProjNode* loop_selector_if_proj) { + static void verify_loop_version(LoopNode* loop_head, IfProjNode* loop_selector_if_proj) { Node* entry = loop_head->skip_strip_mined()->in(LoopNode::EntryControl); const Predicates predicates(entry); // When skipping all predicates, we should end up at 'loop_selector_if_proj'. @@ -485,7 +552,6 @@ class OriginalLoop : public StackObj { Node* old_to_new(const Node* old) const { return _old_new[old->_idx]; } - }; // See comments below file header for more information about Loop Unswitching. @@ -508,10 +574,10 @@ void PhaseIdealLoop::do_unswitching(IdealLoopTree* loop, Node_List& old_new) { OriginalLoop original_loop(loop, old_new); original_loop.unswitch(unswitched_loop_selector); - unswitch_candidate.update_in_true_path_loop(unswitched_loop_selector.true_path_loop_proj()); - unswitch_candidate.update_in_false_path_loop(unswitched_loop_selector.false_path_loop_proj(), + unswitch_candidate.update_in_true_path_loop(unswitched_loop_selector.loop_selector().true_path_loop_proj()); + unswitch_candidate.update_in_false_path_loop(unswitched_loop_selector.loop_selector().false_path_loop_proj(), old_new[original_head->_idx]->as_Loop()); - hoist_invariant_check_casts(loop, old_new, unswitch_candidate, unswitched_loop_selector.selector()); + hoist_invariant_check_casts(loop, old_new, unswitch_candidate, unswitched_loop_selector.selector_if()); add_unswitched_loop_version_bodies_to_igvn(loop, old_new); LoopNode* new_head = old_new[original_head->_idx]->as_Loop(); @@ -522,6 +588,172 @@ void PhaseIdealLoop::do_unswitching(IdealLoopTree* loop, Node_List& old_new) { C->set_major_progress(); } +void PhaseIdealLoop::do_multiversioning(IdealLoopTree* lpt, Node_List& old_new) { +#ifndef PRODUCT + if (TraceLoopOpts || TraceLoopMultiversioning) { + tty->print("Multiversion "); + lpt->dump_head(); + } +#endif + assert(LoopMultiversioning, "LoopMultiversioning must be enabled"); + + CountedLoopNode* original_head = lpt->_head->as_CountedLoop(); + C->print_method(PHASE_BEFORE_LOOP_MULTIVERSIONING, 4, original_head); + + Node* one = _igvn.intcon(1); + set_ctrl(one, C->root()); + Node* opaque = new OpaqueMultiversioningNode(C, one); + set_ctrl(opaque, C->root()); + _igvn.register_new_node_with_optimizer(opaque); + _igvn.set_type(opaque, TypeInt::BOOL); + + const LoopSelector loop_selector(lpt, opaque, PROB_LIKELY_MAG(3), COUNT_UNKNOWN); + OriginalLoop original_loop(lpt, old_new); + original_loop.multiversion(loop_selector); + + add_unswitched_loop_version_bodies_to_igvn(lpt, old_new); + + CountedLoopNode* new_head = old_new[original_head->_idx]->as_CountedLoop(); + original_head->set_multiversion_fast_loop(); + new_head->set_multiversion_delayed_slow_loop(); + + NOT_PRODUCT(trace_loop_multiversioning_result(loop_selector, original_head, new_head);) + C->print_method(PHASE_AFTER_LOOP_MULTIVERSIONING, 4, new_head); + C->set_major_progress(); +} + +// Create a new if in the multiversioning pattern, adding an additional condition for the +// multiversioning fast-loop. +// +// Before: +// entry opaque +// | | +// multiversion_if +// | | +// +----------------+ +---------------+ +// | | +// multiversion_fast_proj multiversion_slow_proj +// | +// +--------+ +// | +// slow_path +// +// +// After: +// entry opaque <-- to be replaced by caller +// | | +// new_if +// | | +// | +-----------------------------+ +// | | +// new_if_true opaque new_if_false +// | | | +// multiversion_if | +// | | | +// +----------------+ +---------------+ | +// | | | +// multiversion_fast_proj new_multiversion_slow_proj | +// | | +// +------+ | +// | | +// region +// | +// slow_path +// +IfTrueNode* PhaseIdealLoop::create_new_if_for_multiversion(IfTrueNode* multiversioning_fast_proj) { + // Give all nodes in the old sub-graph a name. + IfNode* multiversion_if = multiversioning_fast_proj->in(0)->as_If(); + Node* entry = multiversion_if->in(0); + OpaqueMultiversioningNode* opaque = multiversion_if->in(1)->as_OpaqueMultiversioning(); + IfFalseNode* multiversion_slow_proj = multiversion_if->proj_out(0)->as_IfFalse(); + Node* slow_path = multiversion_slow_proj->unique_ctrl_out(); + + // The slow_loop may still be delayed, and waiting for runtime-checks to be added to the + // multiversion_if. Now that we have at least one condition for the multiversioning, + // we should resume optimizations for the slow loop. + opaque->notify_slow_loop_that_it_can_resume_optimizations(); + + // Create new_if with its projections. + IfNode* new_if = IfNode::make_with_same_profile(multiversion_if, entry, opaque); + IdealLoopTree* lp = get_loop(entry); + register_control(new_if, lp, entry); + + IfTrueNode* new_if_true = new IfTrueNode(new_if); + IfFalseNode* new_if_false = new IfFalseNode(new_if); + register_control(new_if_true, lp, new_if); + register_control(new_if_false, lp, new_if); + + // Hook new_if_true into multiversion_if. + _igvn.replace_input_of(multiversion_if, 0, new_if_true); + + // Clone multiversion_slow_path - this allows us to easily carry the dependencies to + // the new region below. + IfFalseNode* new_multiversion_slow_proj = multiversion_slow_proj->clone()->as_IfFalse(); + register_control(new_multiversion_slow_proj, lp, multiversion_if); + + // Create new Region. + RegionNode* region = new RegionNode(1); + region->add_req(new_multiversion_slow_proj); + region->add_req(new_if_false); + register_control(region, lp, new_multiversion_slow_proj); + + // Hook region into slow_path, in stead of the multiversion_slow_proj. + // This also moves all other dependencies of the multiversion_slow_proj to the region. + _igvn.replace_node(multiversion_slow_proj, region); + + return new_if_true; +} + +OpaqueMultiversioningNode* find_multiversion_opaque_from_multiversion_if_false(Node* maybe_multiversion_if_false) { + IfFalseNode* multiversion_if_false = maybe_multiversion_if_false->isa_IfFalse(); + if (multiversion_if_false == nullptr) { return nullptr; } + IfNode* multiversion_if = multiversion_if_false->in(0)->isa_If(); + if (multiversion_if == nullptr) { return nullptr; } + return multiversion_if->in(1)->isa_OpaqueMultiversioning(); +} + +bool PhaseIdealLoop::try_resume_optimizations_for_delayed_slow_loop(IdealLoopTree* lpt) { + CountedLoopNode* cl = lpt->_head->as_CountedLoop(); + assert(cl->is_multiversion_delayed_slow_loop(), "must currently be delayed"); + + // Find multiversion_if. + Node* entry = cl->skip_strip_mined()->in(LoopNode::EntryControl); + const Predicates predicates(entry); + + Node* slow_path = predicates.entry(); + + // Find opaque. + OpaqueMultiversioningNode* opaque = nullptr; + if (slow_path->is_Region()) { + for (uint i = 1; i < slow_path->req(); i++) { + Node* n = slow_path->in(i); + opaque = find_multiversion_opaque_from_multiversion_if_false(n); + if (opaque != nullptr) { break; } + } + } else { + opaque = find_multiversion_opaque_from_multiversion_if_false(slow_path); + } + assert(opaque != nullptr, "must have found multiversion opaque node"); + if (opaque == nullptr) { return false; } + + // We may still be delayed, if there were not yet any runtime-checks added + // for the multiversioning. We may never add any, and then this loop would + // fold away. So we wait until some runtime-checks are added, then we know + // that this loop will be reachable and it is worth optimizing further. + if (opaque->is_delayed_slow_loop()) { return false; } + + // Clear away the "delayed" status, i.e. resume optimizations. + cl->set_no_multiversion(); + cl->set_multiversion_slow_loop(); +#ifndef PRODUCT + if (TraceLoopOpts) { + tty->print("Resume Optimizations "); + lpt->dump_head(); + } +#endif + return true; +} + bool PhaseIdealLoop::has_control_dependencies_from_predicates(LoopNode* head) { Node* entry = head->skip_strip_mined()->in(LoopNode::EntryControl); const Predicates predicates(entry); @@ -557,7 +789,7 @@ void PhaseIdealLoop::trace_loop_unswitching_result(const UnswitchedLoopSelector& const LoopNode* original_head, const LoopNode* new_head) { if (TraceLoopUnswitching) { IfNode* unswitch_candidate_if = unswitch_candidate.candidate(); - IfNode* loop_selector = unswitched_loop_selector.selector(); + IfNode* loop_selector = unswitched_loop_selector.selector_if(); tty->print_cr("Loop Unswitching:"); tty->print_cr("- Unswitch-Candidate-If: %d %s", unswitch_candidate_if->_idx, unswitch_candidate_if->Name()); tty->print_cr("- Loop-Selector-If: %d %s", loop_selector->_idx, loop_selector->Name()); @@ -566,15 +798,26 @@ void PhaseIdealLoop::trace_loop_unswitching_result(const UnswitchedLoopSelector& unswitch_candidate.trace_flat_array_checks(); } } + +void PhaseIdealLoop::trace_loop_multiversioning_result(const LoopSelector& loop_selector, + const LoopNode* original_head, const LoopNode* new_head) { + if (TraceLoopMultiversioning) { + IfNode* selector_if = loop_selector.selector(); + tty->print_cr("Loop Multiversioning:"); + tty->print_cr("- Loop-Selector-If: %d %s", selector_if->_idx, selector_if->Name()); + tty->print_cr("- True-Path-Loop (=Orig / Fast): %d %s", original_head->_idx, original_head->Name()); + tty->print_cr("- False-Path-Loop (=Clone / Slow): %d %s", new_head->_idx, new_head->Name()); + } +} #endif // When unswitching a counted loop, we need to convert it back to a normal loop since it's not a proper pre, main or, -// post loop anymore after loop unswitching. +// post loop anymore after loop unswitching. We also lose the multiversion structure, with access to the multiversion_if. void PhaseIdealLoop::revert_to_normal_loop(const LoopNode* loop_head) { CountedLoopNode* cl = loop_head->isa_CountedLoop(); - if (cl != nullptr && !cl->is_normal_loop()) { - cl->set_normal_loop(); - } + if (cl == nullptr) { return; } + if (!cl->is_normal_loop()) { cl->set_normal_loop(); } + if (cl->is_multiversion()) { cl->set_no_multiversion(); } } // Hoist invariant CheckCastPPNodes out of each unswitched loop version to the appropriate loop selector If projection. diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index ed2db13421f..8be412412ea 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -1090,6 +1090,14 @@ bool PhaseIdealLoop::create_loop_nest(IdealLoopTree* loop, Node_List &old_new) { if (UseProfiledLoopPredicate) { add_parse_predicate(Deoptimization::Reason_profile_predicate, inner_head, outer_ilt, cloned_sfpt); } + + // We only want to use the auto-vectorization check as a trap once per bci. And + // PhaseIdealLoop::add_parse_predicate only checks trap limits per method, so + // we do a custom check here. + if (!C->too_many_traps(cloned_sfpt->jvms()->method(), cloned_sfpt->jvms()->bci(), Deoptimization::Reason_auto_vectorization_check)) { + add_parse_predicate(Deoptimization::Reason_auto_vectorization_check, inner_head, outer_ilt, cloned_sfpt); + } + add_parse_predicate(Deoptimization::Reason_loop_limit_check, inner_head, outer_ilt, cloned_sfpt); } @@ -2511,6 +2519,9 @@ void CountedLoopNode::dump_spec(outputStream *st) const { if (is_main_loop()) st->print("main of N%d", _idx); if (is_post_loop()) st->print("post of N%d", _main_idx); if (is_strip_mined()) st->print(" strip mined"); + if (is_multiversion_fast_loop()) { st->print(" multiversion_fast"); } + if (is_multiversion_slow_loop()) { st->print(" multiversion_slow"); } + if (is_multiversion_delayed_slow_loop()) { st->print(" multiversion_delayed_slow"); } } #endif @@ -3183,10 +3194,10 @@ void OuterStripMinedLoopNode::transform_to_counted_loop(PhaseIterGVN* igvn, Phas if (iloop->get_loop(iloop->get_ctrl(in)) != outer_loop_ilt) { continue; } - assert(!loop->_body.contains(in), ""); - loop->_body.push(in); wq.push(in); } + assert(!loop->_body.contains(n), "Shouldn't append node to body twice"); + loop->_body.push(n); } iloop->set_loop(safepoint, loop); loop->_body.push(safepoint); @@ -4303,6 +4314,9 @@ void IdealLoopTree::dump_head() { if (cl->is_post_loop()) tty->print(" post"); if (cl->is_vectorized_loop()) tty->print(" vector"); if (range_checks_present()) tty->print(" rc "); + if (cl->is_multiversion_fast_loop()) { tty->print(" multiversion_fast"); } + if (cl->is_multiversion_slow_loop()) { tty->print(" multiversion_slow"); } + if (cl->is_multiversion_delayed_slow_loop()) { tty->print(" multiversion_delayed_slow"); } } if (_has_call) tty->print(" has_call"); if (_has_sfpt) tty->print(" has_sfpt"); @@ -4948,18 +4962,6 @@ void PhaseIdealLoop::build_and_optimize() { C->set_major_progress(); } - // Keep loop predicates and perform optimizations with them - // until no more loop optimizations could be done. - // After that switch predicates off and do more loop optimizations. - if (!C->major_progress() && (C->parse_predicate_count() > 0)) { - C->mark_parse_predicate_nodes_useless(_igvn); - assert(C->parse_predicate_count() == 0, "should be zero now"); - if (TraceLoopOpts) { - tty->print_cr("PredicatesOff"); - } - C->set_major_progress(); - } - // Auto-vectorize main-loop if (C->do_superword() && C->has_loops() && !C->major_progress()) { Compile::TracePhase tp(_t_autoVectorize); @@ -4992,6 +4994,18 @@ void PhaseIdealLoop::build_and_optimize() { } } } + + // Keep loop predicates and perform optimizations with them + // until no more loop optimizations could be done. + // After that switch predicates off and do more loop optimizations. + if (!C->major_progress() && (C->parse_predicate_count() > 0)) { + C->mark_parse_predicate_nodes_useless(_igvn); + assert(C->parse_predicate_count() == 0, "should be zero now"); + if (TraceLoopOpts) { + tty->print_cr("PredicatesOff"); + } + C->set_major_progress(); + } } #ifndef PRODUCT diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 827e5b047ac..32942b01a64 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -44,6 +44,7 @@ class PredicateBlock; class PathFrequency; class PhaseIdealLoop; class UnswitchCandidate; +class LoopSelector; class UnswitchedLoopSelector; class VectorSet; class VSharedData; @@ -81,7 +82,11 @@ class LoopNode : public RegionNode { ProfileTripFailed = 1<<14, LoopNestInnerLoop = 1<<15, LoopNestLongOuterLoop = 1<<16, - FlatArrays = 1<<17}; + MultiversionFastLoop = 1<<17, + MultiversionSlowLoop = 2<<17, + MultiversionDelayedSlowLoop = 3<<17, + MultiversionFlagsMask = 3<<17, + FlatArrays = 1<<18}; char _unswitch_count; enum { _unswitch_max=3 }; @@ -319,6 +324,32 @@ class CountedLoopNode : public BaseCountedLoopNode { void set_slp_max_unroll(int unroll_factor) { _slp_maximum_unroll_factor = unroll_factor; } int slp_max_unroll() const { return _slp_maximum_unroll_factor; } + // Multiversioning allows us to duplicate a CountedLoop, and have two versions, and the multiversion_if + // decides which one is taken: + // (1) fast_loop: We enter this loop by default, by default the multiversion_if has its condition set to + // "true", guarded by a OpaqueMultiversioning. If we want to make a speculative assumption + // for an optimization, we can add the runtime-check to the multiversion_if, and if the + // assumption fails we take the slow_loop instead, where we do not make the same speculative + // assumption. + // We call it the "fast_loop" because it has more optimizations, enabled by the speculative + // runtime-checks at the multiversion_if, and we expect the fast_loop to execute faster. + // (2) slow_loop: By default, it is not taken, until a runtime-check is added to the multiversion_if while + // optimizing the fast_looop. If such a runtime-check is never added, then after loop-opts + // the multiversion_if constant folds to true, and the slow_loop is folded away. To save + // compile time, we delay the optimization of the slow_loop until a runtime-check is added + // to the multiversion_if, at which point we resume optimizations for the slow_loop. + // We call it the "slow_loop" because it has fewer optimizations, since this is the fall-back + // loop where we do not make any of the speculative assumptions we make for the fast_loop. + // Hence, we expect the slow_loop to execute slower. + bool is_multiversion() const { return (_loop_flags & MultiversionFlagsMask) != Normal; } + bool is_multiversion_fast_loop() const { return (_loop_flags & MultiversionFlagsMask) == MultiversionFastLoop; } + bool is_multiversion_slow_loop() const { return (_loop_flags & MultiversionFlagsMask) == MultiversionSlowLoop; } + bool is_multiversion_delayed_slow_loop() const { return (_loop_flags & MultiversionFlagsMask) == MultiversionDelayedSlowLoop; } + void set_multiversion_fast_loop() { assert(!is_multiversion(), ""); _loop_flags |= MultiversionFastLoop; } + void set_multiversion_slow_loop() { assert(!is_multiversion(), ""); _loop_flags |= MultiversionSlowLoop; } + void set_multiversion_delayed_slow_loop() { assert(!is_multiversion(), ""); _loop_flags |= MultiversionDelayedSlowLoop; } + void set_no_multiversion() { assert( is_multiversion(), ""); _loop_flags &= ~MultiversionFlagsMask; } + virtual LoopNode* skip_strip_mined(int expect_skeleton = 1); OuterStripMinedLoopNode* outer_loop() const; virtual IfTrueNode* outer_loop_tail() const; @@ -1464,6 +1495,8 @@ class PhaseIdealLoop : public PhaseTransform { static void trace_loop_unswitching_result(const UnswitchedLoopSelector& unswitched_loop_selector, const UnswitchCandidate& unswitch_candidate, const LoopNode* original_head, const LoopNode* new_head); + static void trace_loop_multiversioning_result(const LoopSelector& loop_selector, + const LoopNode* original_head, const LoopNode* new_head); #endif public: @@ -1490,6 +1523,11 @@ class PhaseIdealLoop : public PhaseTransform { }; AutoVectorizeStatus auto_vectorize(IdealLoopTree* lpt, VSharedData &vshared); + void maybe_multiversion_for_auto_vectorization_runtime_checks(IdealLoopTree* lpt, Node_List& old_new); + void do_multiversioning(IdealLoopTree* lpt, Node_List& old_new); + IfTrueNode* create_new_if_for_multiversion(IfTrueNode* multiversioning_fast_proj); + bool try_resume_optimizations_for_delayed_slow_loop(IdealLoopTree* lpt); + // Move an unordered Reduction out of loop if possible void move_unordered_reduction_out_of_loop(IdealLoopTree* loop); diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index 285302b6595..df4eb0356b2 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -4662,6 +4662,66 @@ PhaseIdealLoop::auto_vectorize(IdealLoopTree* lpt, VSharedData &vshared) { return AutoVectorizeStatus::Success; } +// Just before insert_pre_post_loops, we can multi-version the loop: +// +// multiversion_if +// | | +// fast_loop slow_loop +// +// In the fast_loop we can make speculative assumptions, and put the +// conditions into the multiversion_if. If the conditions hold at runtime, +// we enter the fast_loop, if the conditions fail, we take the slow_loop +// instead which does not make any of the speculative assumptions. +// +// Note: we only multiversion the loop if the loop does not have any +// auto vectorization check Predicate. If we have that predicate, +// then we can simply add the speculative assumption checks to +// that Predicate. This means we do not need to duplicate the +// loop - we have a smaller graph and save compile time. Should +// the conditions ever fail, then we deopt / trap at the Predicate +// and recompile without that Predicate. At that point we will +// multiversion the loop, so that we can still have speculative +// runtime checks. +// +// We perform the multiversioning when the loop is still in its single +// iteration form, even before we insert pre and post loops. This makes +// the cloning much simpler. However, this means that both the fast +// and the slow loop have to be optimized independently (adding pre +// and post loops, unrolling the main loop, auto-vectorize etc.). And +// we may end up not needing any speculative assumptions in the fast_loop +// and then rejecting the slow_loop by constant folding the multiversion_if. +// +// Therefore, we "delay" the optimization of the slow_loop until we add +// at least one speculative assumption for the fast_loop. If we never +// add such a speculative runtime check, the OpaqueMultiversioningNode +// of the multiversion_if constant folds to true after loop opts, and the +// multiversion_if folds away the "delayed" slow_loop. If we add any +// speculative assumption, then we notify the OpaqueMultiversioningNode +// with "notify_slow_loop_that_it_can_resume_optimizations". +// +// Note: new runtime checks can be added to the multiversion_if with +// PhaseIdealLoop::create_new_if_for_multiversion +void PhaseIdealLoop::maybe_multiversion_for_auto_vectorization_runtime_checks(IdealLoopTree* lpt, Node_List& old_new) { + CountedLoopNode* cl = lpt->_head->as_CountedLoop(); + LoopNode* outer_loop = cl->skip_strip_mined(); + Node* entry = outer_loop->in(LoopNode::EntryControl); + + // Check we have multiversioning enabled, and are not already multiversioned. + if (!LoopMultiversioning || cl->is_multiversion()) { return; } + + // Check that we do not have a parse-predicate where we can add the runtime checks + // during auto-vectorization. + const Predicates predicates(entry); + const PredicateBlock* predicate_block = predicates.auto_vectorization_check_block(); + if (predicate_block->has_parse_predicate()) { return; } + + // Check node budget. + uint estimate = lpt->est_loop_clone_sz(2); + if (!may_require_nodes(estimate)) { return; } + + do_multiversioning(lpt, old_new); +} + // Returns true if the Reduction node is unordered. static bool is_unordered_reduction(Node* n) { return n->is_Reduction() && !n->as_Reduction()->requires_strict_order(); diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index 66056093615..4f6bdf65242 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -60,7 +60,7 @@ const uint Matcher::_end_rematerialize = _END_REMATERIALIZE; //---------------------------Matcher------------------------------------------- Matcher::Matcher() : PhaseTransform( Phase::Ins_Select ), - _states_arena(Chunk::medium_size, mtCompiler), + _states_arena(Chunk::medium_size, mtCompiler, Arena::Tag::tag_states), _new_nodes(C->comp_arena()), _visited(&_states_arena), _shared(&_states_arena), diff --git a/src/hotspot/share/opto/mempointer.hpp b/src/hotspot/share/opto/mempointer.hpp index f1d29f2453f..90216a5e2d3 100644 --- a/src/hotspot/share/opto/mempointer.hpp +++ b/src/hotspot/share/opto/mempointer.hpp @@ -229,9 +229,12 @@ // Even if we could know that there is some base address to which we add index offsets, we cannot know // if this reference address points to the beginning of a native memory allocation or into the middle, // or outside it. We also have no guarantee for alignment with such a base address. +// // Still: we would like to find such a base if possible, and if two pointers are similar (i.e. have the // same summands), we would like to find the same base. Further, it is reasonable to speculatively -// assume that such base addresses are aligned (TODO: need to add this speculative check in JDK-8323582). +// assume that such base addresses are aligned. We performs such a speculative alignment runtime check +// in VTransform::add_speculative_alignment_check. +// // A base pointer must have scale = 1, and be accepted byMemPointer::is_native_memory_base_candidate. // It can thus be one of these: // (1) CastX2P diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp index 6795d289f59..9bd9c9536c1 100644 --- a/src/hotspot/share/opto/node.cpp +++ b/src/hotspot/share/opto/node.cpp @@ -1459,6 +1459,8 @@ static void kill_dead_code( Node *dead, PhaseIterGVN *igvn ) { // The restriction (outcnt() <= 2) is the same as in set_req_X() // and remove_globally_dead_node(). igvn->add_users_to_worklist( n ); + } else if (dead->is_data_proj_of_pure_function(n)) { + igvn->_worklist.push(n); } else { BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(igvn, n); } @@ -2938,6 +2940,25 @@ bool Node::is_dead_loop_safe() const { bool Node::is_div_or_mod(BasicType bt) const { return Opcode() == Op_Div(bt) || Opcode() == Op_Mod(bt) || Opcode() == Op_UDiv(bt) || Opcode() == Op_UMod(bt); } +bool Node::is_pure_function() const { + switch (Opcode()) { + case Op_ModD: + case Op_ModF: + return true; + default: + return false; + } +} + +// `maybe_pure_function` is assumed to be the input of `this`. This is a bit redundant, +// but we already have and need maybe_pure_function in all the call sites, so +// it makes it obvious that the `maybe_pure_function` is the same node as in the caller, +// while it takes more thinking to realize that a locally computed in(0) must be equal to +// the local in the caller. +bool Node::is_data_proj_of_pure_function(const Node* maybe_pure_function) const { + return Opcode() == Op_Proj && as_Proj()->_con == TypeFunc::Parms && maybe_pure_function->is_pure_function(); +} + //============================================================================= //------------------------------yank------------------------------------------- // Find and remove diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index adcacb574ad..4df8899239d 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -142,6 +142,7 @@ class NeverBranchNode; class Opaque1Node; class OpaqueLoopInitNode; class OpaqueLoopStrideNode; +class OpaqueMultiversioningNode; class OpaqueNotNullNode; class OpaqueInitializedAssertionPredicateNode; class OpaqueTemplateAssertionPredicateNode; @@ -244,7 +245,6 @@ typedef ResizeableResourceHashtable<Node*, Node*, AnyObj::RESOURCE_AREA, mtCompi // whenever I have phase-specific information. class Node { - friend class VMStructs; // Lots of restrictions on cloning Nodes NONCOPYABLE(Node); @@ -809,6 +809,7 @@ class Node { DEFINE_CLASS_ID(Opaque1, Node, 16) DEFINE_CLASS_ID(OpaqueLoopInit, Opaque1, 0) DEFINE_CLASS_ID(OpaqueLoopStride, Opaque1, 1) + DEFINE_CLASS_ID(OpaqueMultiversioning, Opaque1, 2) DEFINE_CLASS_ID(OpaqueNotNull, Node, 17) DEFINE_CLASS_ID(OpaqueInitializedAssertionPredicate, Node, 18) DEFINE_CLASS_ID(OpaqueTemplateAssertionPredicate, Node, 19) @@ -995,6 +996,7 @@ class Node { DEFINE_CLASS_QUERY(OpaqueTemplateAssertionPredicate) DEFINE_CLASS_QUERY(OpaqueLoopInit) DEFINE_CLASS_QUERY(OpaqueLoopStride) + DEFINE_CLASS_QUERY(OpaqueMultiversioning) DEFINE_CLASS_QUERY(OuterStripMinedLoop) DEFINE_CLASS_QUERY(OuterStripMinedLoopEnd) DEFINE_CLASS_QUERY(Parm) @@ -1295,6 +1297,10 @@ class Node { bool is_div_or_mod(BasicType bt) const; + bool is_pure_function() const; + + bool is_data_proj_of_pure_function(const Node* maybe_pure_function) const; + //----------------- Printing, etc #ifndef PRODUCT public: @@ -1626,7 +1632,6 @@ class SimpleDUIterator : public StackObj { // Note that the constructor just zeros things, and since I use Arena // allocation I do not need a destructor to reclaim storage. class Node_Array : public AnyObj { - friend class VMStructs; protected: Arena* _a; // Arena to allocate in uint _max; @@ -1671,7 +1676,6 @@ class Node_Array : public AnyObj { }; class Node_List : public Node_Array { - friend class VMStructs; uint _cnt; public: Node_List(uint max = OptoNodeListSize) : Node_Array(Thread::current()->resource_area(), max), _cnt(0) {} @@ -1738,7 +1742,6 @@ void Node::visit_uses(Callback callback, Check is_boundary) const { //------------------------------Unique_Node_List------------------------------- class Unique_Node_List : public Node_List { - friend class VMStructs; VectorSet _in_worklist; uint _clock_index; // Index in list where to pop from next public: @@ -1878,7 +1881,6 @@ inline void Compile::remove_for_igvn(Node* n) { //------------------------------Node_Stack------------------------------------- class Node_Stack { - friend class VMStructs; protected: struct INode { Node *node; // Processed node @@ -1954,7 +1956,6 @@ class Node_Stack { // Debugging or profiling annotations loosely and sparsely associated // with some nodes. See Compile::node_notes_at for the accessor. class Node_Notes { - friend class VMStructs; JVMState* _jvms; public: diff --git a/src/hotspot/share/opto/opaquenode.hpp b/src/hotspot/share/opto/opaquenode.hpp index c1686d846f9..0e8a53efd34 100644 --- a/src/hotspot/share/opto/opaquenode.hpp +++ b/src/hotspot/share/opto/opaquenode.hpp @@ -91,6 +91,29 @@ class OpaqueZeroTripGuardNode : public Opaque1Node { IfNode* if_node() const; }; +// This node is used to mark the auto vectorization Predicate. +// At first, the multiversion_if has its condition set to "true" and we always +// take the fast_loop. Since we do not know if the slow_loop is ever going to +// be used, we delay optimizations for it. Once the fast_loop decides to use +// speculative runtime-checks and adds them to the multiversion_if, the slow_loop +// can now resume optimizations, as it is reachable at runtime. +// See PhaseIdealLoop::maybe_multiversion_for_auto_vectorization_runtime_checks +class OpaqueMultiversioningNode : public Opaque1Node { +private: + bool _is_delayed_slow_loop; + +public: + OpaqueMultiversioningNode(Compile* C, Node* n) : + Opaque1Node(C, n), _is_delayed_slow_loop(true) + { + init_class_id(Class_OpaqueMultiversioning); + } + virtual int Opcode() const; + virtual const Type* bottom_type() const { return TypeInt::BOOL; } + bool is_delayed_slow_loop() const { return _is_delayed_slow_loop; } + void notify_slow_loop_that_it_can_resume_optimizations() { _is_delayed_slow_loop = false; } +}; + // This node is used in the context of intrinsics. We sometimes implicitly know that an object is non-null even though // the compiler cannot prove it. We therefore add a corresponding cast to propagate this implicit knowledge. However, // this cast could become top during optimizations (input to cast becomes null) and the data path is folded. To ensure diff --git a/src/hotspot/share/opto/optoreg.hpp b/src/hotspot/share/opto/optoreg.hpp index b079f3473ad..6298eeea39c 100644 --- a/src/hotspot/share/opto/optoreg.hpp +++ b/src/hotspot/share/opto/optoreg.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, 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 @@ -182,7 +182,6 @@ class OptoReg { // and converting that will return OptoReg::Bad losing the identity of the OptoReg. class OptoRegPair { - friend class VMStructs; private: short _second; short _first; diff --git a/src/hotspot/share/opto/phase.hpp b/src/hotspot/share/opto/phase.hpp index ff166c8de8e..6700df6ec17 100644 --- a/src/hotspot/share/opto/phase.hpp +++ b/src/hotspot/share/opto/phase.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, 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 @@ class IfNode; class MergeMemNode; class Node; class PhaseGVN; +class Compile; +class ciMethod; //------------------------------Phase------------------------------------------ // Most optimizations are done in Phases. Creating a phase does any long @@ -65,6 +67,7 @@ class Phase : public StackObj { }; #define ALL_PHASE_TRACE_IDS(f) \ + f( _t_none, "none") \ f( _t_parser, "parse") \ f( _t_optimizer, "optimizer") \ f( _t_escapeAnalysis, "escapeAnalysis") \ @@ -118,7 +121,9 @@ class Phase : public StackObj { f( _t_fillBuffer, "fill buffer") \ f( _t_registerMethod, "install_code") \ f( _t_temporaryTimer1, "tempTimer1") \ - f( _t_temporaryTimer2, "tempTimer2") + f( _t_temporaryTimer2, "tempTimer2") \ + f( _t_testPhase1, "testPhase1") \ + f( _t_testPhase2, "testPhase2") enum PhaseTraceId { #define DEFID(name, text) name, diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 6249732c72e..7427f881dee 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -1342,6 +1342,8 @@ void PhaseIterGVN::remove_globally_dead_node( Node *dead ) { } assert(!(i < imax), "sanity"); } + } else if (dead->is_data_proj_of_pure_function(in)) { + _worklist.push(in); } else { BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(this, in); } diff --git a/src/hotspot/share/opto/phasetype.hpp b/src/hotspot/share/opto/phasetype.hpp index 851e40e428e..95926129b10 100644 --- a/src/hotspot/share/opto/phasetype.hpp +++ b/src/hotspot/share/opto/phasetype.hpp @@ -64,14 +64,17 @@ flags(AFTER_LOOP_PEELING, "After Loop Peeling") \ flags(BEFORE_LOOP_UNSWITCHING, "Before Loop Unswitching") \ flags(AFTER_LOOP_UNSWITCHING, "After Loop Unswitching") \ + flags(BEFORE_LOOP_MULTIVERSIONING, "Before Loop Multiversioning") \ + flags(AFTER_LOOP_MULTIVERSIONING, "After Loop Multiversioning") \ flags(BEFORE_RANGE_CHECK_ELIMINATION, "Before Range Check Elimination") \ flags(AFTER_RANGE_CHECK_ELIMINATION, "After Range Check Elimination") \ flags(BEFORE_PRE_MAIN_POST, "Before Pre/Main/Post Loops") \ flags(AFTER_PRE_MAIN_POST, "After Pre/Main/Post Loops") \ - flags(AUTO_VECTORIZATION1_BEFORE_APPLY, "AutoVectorization 1, Before Apply") \ - flags(AUTO_VECTORIZATION2_AFTER_REORDER, "AutoVectorization 2, After Apply Memop Reordering") \ - flags(AUTO_VECTORIZATION3_AFTER_ADJUST_LIMIT, "AutoVectorization 3, After Adjusting Pre-Loop Limit") \ - flags(AUTO_VECTORIZATION4_AFTER_APPLY, "AutoVectorization 4, After Apply") \ + flags(AUTO_VECTORIZATION1_BEFORE_APPLY, "AutoVectorization 1, Before Apply") \ + flags(AUTO_VECTORIZATION2_AFTER_REORDER, "AutoVectorization 2, After Apply Memop Reordering") \ + flags(AUTO_VECTORIZATION3_AFTER_ADJUST_LIMIT, "AutoVectorization 3, After Adjusting Pre-Loop Limit") \ + flags(AUTO_VECTORIZATION4_AFTER_SPECULATIVE_RUNTIME_CHECKS, "AutoVectorization 4, After Adding Speculative Runtime Checks") \ + flags(AUTO_VECTORIZATION5_AFTER_APPLY, "AutoVectorization 5, After Apply") \ flags(BEFORE_CLOOPS, "Before CountedLoop") \ flags(AFTER_CLOOPS, "After CountedLoop") \ flags(PHASEIDEAL_BEFORE_EA, "PhaseIdealLoop before EA") \ diff --git a/src/hotspot/share/opto/predicates.cpp b/src/hotspot/share/opto/predicates.cpp index 6badaa65487..be4e0067c10 100644 --- a/src/hotspot/share/opto/predicates.cpp +++ b/src/hotspot/share/opto/predicates.cpp @@ -120,6 +120,7 @@ bool RuntimePredicate::has_valid_uncommon_trap(const Node* success_proj) { assert(RegularPredicate::may_be_predicate_if(success_proj), "must have been checked before"); const Deoptimization::DeoptReason deopt_reason = uncommon_trap_reason(success_proj->as_IfProj()); return (deopt_reason == Deoptimization::Reason_loop_limit_check || + deopt_reason == Deoptimization::Reason_auto_vectorization_check || deopt_reason == Deoptimization::Reason_predicate || deopt_reason == Deoptimization::Reason_profile_predicate); } @@ -893,6 +894,8 @@ void Predicates::dump() const { tty->print_cr("%d %s:", loop_head->_idx, loop_head->Name()); tty->print_cr("- Loop Limit Check Predicate Block:"); _loop_limit_check_predicate_block.dump(" "); + tty->print_cr("- Auto Vectorization Check Block:"); + _auto_vectorization_check_block.dump(" "); tty->print_cr("- Profiled Loop Predicate Block:"); _profiled_loop_predicate_block.dump(" "); tty->print_cr("- Loop Predicate Block:"); diff --git a/src/hotspot/share/opto/predicates.hpp b/src/hotspot/share/opto/predicates.hpp index bfc1b23115e..ceb8fe7e317 100644 --- a/src/hotspot/share/opto/predicates.hpp +++ b/src/hotspot/share/opto/predicates.hpp @@ -734,6 +734,8 @@ class PredicateIterator : public StackObj { Node* current = _start_node; PredicateBlockIterator loop_limit_check_predicate_iterator(current, Deoptimization::Reason_loop_limit_check); current = loop_limit_check_predicate_iterator.for_each(predicate_visitor); + PredicateBlockIterator auto_vectorization_check_iterator(current, Deoptimization::Reason_auto_vectorization_check); + current = auto_vectorization_check_iterator.for_each(predicate_visitor); if (UseLoopPredicate) { if (UseProfiledLoopPredicate) { PredicateBlockIterator profiled_loop_predicate_iterator(current, Deoptimization::Reason_profile_predicate); @@ -906,6 +908,7 @@ class PredicateBlock : public StackObj { class Predicates : public StackObj { Node* const _tail; const PredicateBlock _loop_limit_check_predicate_block; + const PredicateBlock _auto_vectorization_check_block; const PredicateBlock _profiled_loop_predicate_block; const PredicateBlock _loop_predicate_block; Node* const _entry; @@ -914,7 +917,9 @@ class Predicates : public StackObj { explicit Predicates(Node* loop_entry) : _tail(loop_entry), _loop_limit_check_predicate_block(loop_entry, Deoptimization::Reason_loop_limit_check), - _profiled_loop_predicate_block(_loop_limit_check_predicate_block.entry(), + _auto_vectorization_check_block(_loop_limit_check_predicate_block.entry(), + Deoptimization::Reason_auto_vectorization_check), + _profiled_loop_predicate_block(_auto_vectorization_check_block.entry(), Deoptimization::Reason_profile_predicate), _loop_predicate_block(_profiled_loop_predicate_block.entry(), Deoptimization::Reason_predicate), @@ -935,6 +940,10 @@ class Predicates : public StackObj { return &_profiled_loop_predicate_block; } + const PredicateBlock* auto_vectorization_check_block() const { + return &_auto_vectorization_check_block; + } + const PredicateBlock* loop_limit_check_predicate_block() const { return &_loop_limit_check_predicate_block; } diff --git a/src/hotspot/share/opto/regalloc.hpp b/src/hotspot/share/opto/regalloc.hpp index ecdf2e2bee8..86877e18325 100644 --- a/src/hotspot/share/opto/regalloc.hpp +++ b/src/hotspot/share/opto/regalloc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,6 @@ class PhaseCFG; //------------------------------PhaseRegAlloc------------------------------------ // Abstract register allocator class PhaseRegAlloc : public Phase { - friend class VMStructs; static void (*_alloc_statistics[MAX_REG_ALLOCATORS])(); static int _num_allocators; diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index 96050f5778a..b9d5c1fc9bf 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -30,6 +30,7 @@ #include "code/pcDesc.hpp" #include "code/scopeDesc.hpp" #include "code/vtableStubs.hpp" +#include "compiler/compilationMemoryStatistic.hpp" #include "compiler/compileBroker.hpp" #include "compiler/oopMap.hpp" #include "gc/g1/g1HeapRegion.hpp" @@ -231,6 +232,7 @@ const TypeFunc* OptoRuntime::_digestBase_implCompress_with_sha3_Type = null const TypeFunc* OptoRuntime::_digestBase_implCompress_without_sha3_Type = nullptr; const TypeFunc* OptoRuntime::_digestBase_implCompressMB_with_sha3_Type = nullptr; const TypeFunc* OptoRuntime::_digestBase_implCompressMB_without_sha3_Type = nullptr; +const TypeFunc* OptoRuntime::_double_keccak_Type = nullptr; const TypeFunc* OptoRuntime::_multiplyToLen_Type = nullptr; const TypeFunc* OptoRuntime::_montgomeryMultiply_Type = nullptr; const TypeFunc* OptoRuntime::_montgomerySquare_Type = nullptr; @@ -240,6 +242,13 @@ const TypeFunc* OptoRuntime::_bigIntegerShift_Type = nullptr; const TypeFunc* OptoRuntime::_vectorizedMismatch_Type = nullptr; const TypeFunc* OptoRuntime::_ghash_processBlocks_Type = nullptr; const TypeFunc* OptoRuntime::_chacha20Block_Type = nullptr; + +const TypeFunc* OptoRuntime::_dilithiumAlmostNtt_Type = nullptr; +const TypeFunc* OptoRuntime::_dilithiumAlmostInverseNtt_Type = nullptr; +const TypeFunc* OptoRuntime::_dilithiumNttMult_Type = nullptr; +const TypeFunc* OptoRuntime::_dilithiumMontMulByConstant_Type = nullptr; +const TypeFunc* OptoRuntime::_dilithiumDecomposePoly_Type = nullptr; + const TypeFunc* OptoRuntime::_base64_encodeBlock_Type = nullptr; const TypeFunc* OptoRuntime::_base64_decodeBlock_Type = nullptr; const TypeFunc* OptoRuntime::_string_IndexOf_Type = nullptr; @@ -269,6 +278,7 @@ address OptoRuntime::generate_stub(ciEnv* env, // Matching the default directive, we currently have no method to match. DirectiveSet* directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler(CompLevel_full_optimization)); + CompilationMemoryStatisticMark cmsm(directive); ResourceMark rm; Compile C(env, gen, C_function, name, is_fancy_jump, pass_tls, return_pc, directive); DirectivesStack::release(directive); @@ -1177,6 +1187,9 @@ static const TypeFunc* make_digestBase_implCompress_Type(bool is_sha3) { return TypeFunc::make(domain, range); } +/* + * int implCompressMultiBlock(byte[] b, int ofs, int limit) + */ static const TypeFunc* make_digestBase_implCompressMB_Type(bool is_sha3) { // create input type (domain) int num_args = is_sha3 ? 5 : 4; @@ -1198,6 +1211,25 @@ static const TypeFunc* make_digestBase_implCompressMB_Type(bool is_sha3) { return TypeFunc::make(domain, range); } +// SHAKE128Parallel doubleKeccak function +static const TypeFunc* make_double_keccak_Type() { + int argcnt = 2; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // status0 + fields[argp++] = TypePtr::NOTNULL; // status1 + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + static const TypeFunc* make_multiplyToLen_Type() { // create input type (domain) int num_args = 5; @@ -1383,6 +1415,105 @@ static const TypeFunc* make_chacha20Block_Type() { return TypeFunc::make(domain, range); } +// Dilithium NTT function except for the final "normalization" to |coeff| < Q +static const TypeFunc* make_dilithiumAlmostNtt_Type() { + int argcnt = 2; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // coeffs + fields[argp++] = TypePtr::NOTNULL; // NTT zetas + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + +// Dilithium inverse NTT function except the final mod Q division by 2^256 +static const TypeFunc* make_dilithiumAlmostInverseNtt_Type() { + int argcnt = 2; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // coeffs + fields[argp++] = TypePtr::NOTNULL; // inverse NTT zetas + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + +// Dilithium NTT multiply function +static const TypeFunc* make_dilithiumNttMult_Type() { + int argcnt = 3; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // result + fields[argp++] = TypePtr::NOTNULL; // ntta + fields[argp++] = TypePtr::NOTNULL; // nttb + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + +// Dilithium Montgomery multiply a polynome coefficient array by a constant +static const TypeFunc* make_dilithiumMontMulByConstant_Type() { + int argcnt = 2; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // coeffs + fields[argp++] = TypeInt::INT; // constant multiplier + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + +// Dilithium decompose polynomial +static const TypeFunc* make_dilithiumDecomposePoly_Type() { + int argcnt = 5; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // input + fields[argp++] = TypePtr::NOTNULL; // lowPart + fields[argp++] = TypePtr::NOTNULL; // highPart + fields[argp++] = TypeInt::INT; // 2 * gamma2 + fields[argp++] = TypeInt::INT; // multiplier + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + static const TypeFunc* make_base64_encodeBlock_Type() { int argcnt = 6; @@ -1986,6 +2117,7 @@ void OptoRuntime::initialize_types() { _digestBase_implCompress_without_sha3_Type = make_digestBase_implCompress_Type( /* is_sha3= */ false);; _digestBase_implCompressMB_with_sha3_Type = make_digestBase_implCompressMB_Type(/* is_sha3= */ true); _digestBase_implCompressMB_without_sha3_Type = make_digestBase_implCompressMB_Type(/* is_sha3= */ false); + _double_keccak_Type = make_double_keccak_Type(); _multiplyToLen_Type = make_multiplyToLen_Type(); _montgomeryMultiply_Type = make_montgomeryMultiply_Type(); _montgomerySquare_Type = make_montgomerySquare_Type(); @@ -1995,6 +2127,13 @@ void OptoRuntime::initialize_types() { _vectorizedMismatch_Type = make_vectorizedMismatch_Type(); _ghash_processBlocks_Type = make_ghash_processBlocks_Type(); _chacha20Block_Type = make_chacha20Block_Type(); + + _dilithiumAlmostNtt_Type = make_dilithiumAlmostNtt_Type(); + _dilithiumAlmostInverseNtt_Type = make_dilithiumAlmostInverseNtt_Type(); + _dilithiumNttMult_Type = make_dilithiumNttMult_Type(); + _dilithiumMontMulByConstant_Type = make_dilithiumMontMulByConstant_Type(); + _dilithiumDecomposePoly_Type = make_dilithiumDecomposePoly_Type(); + _base64_encodeBlock_Type = make_base64_encodeBlock_Type(); _base64_decodeBlock_Type = make_base64_decodeBlock_Type(); _string_IndexOf_Type = make_string_IndexOf_Type(); diff --git a/src/hotspot/share/opto/runtime.hpp b/src/hotspot/share/opto/runtime.hpp index cf67ae176cd..8823f834084 100644 --- a/src/hotspot/share/opto/runtime.hpp +++ b/src/hotspot/share/opto/runtime.hpp @@ -170,6 +170,7 @@ class OptoRuntime : public AllStatic { static const TypeFunc* _digestBase_implCompress_without_sha3_Type; static const TypeFunc* _digestBase_implCompressMB_with_sha3_Type; static const TypeFunc* _digestBase_implCompressMB_without_sha3_Type; + static const TypeFunc* _double_keccak_Type; static const TypeFunc* _multiplyToLen_Type; static const TypeFunc* _montgomeryMultiply_Type; static const TypeFunc* _montgomerySquare_Type; @@ -179,6 +180,11 @@ class OptoRuntime : public AllStatic { static const TypeFunc* _vectorizedMismatch_Type; static const TypeFunc* _ghash_processBlocks_Type; static const TypeFunc* _chacha20Block_Type; + static const TypeFunc* _dilithiumAlmostNtt_Type; + static const TypeFunc* _dilithiumAlmostInverseNtt_Type; + static const TypeFunc* _dilithiumNttMult_Type; + static const TypeFunc* _dilithiumMontMulByConstant_Type; + static const TypeFunc* _dilithiumDecomposePoly_Type; static const TypeFunc* _base64_encodeBlock_Type; static const TypeFunc* _base64_decodeBlock_Type; static const TypeFunc* _string_IndexOf_Type; @@ -529,6 +535,11 @@ class OptoRuntime : public AllStatic { return is_sha3 ? _digestBase_implCompressMB_with_sha3_Type : _digestBase_implCompressMB_without_sha3_Type; } + static inline const TypeFunc* double_keccak_Type() { + assert(_double_keccak_Type != nullptr, "should be initialized"); + return _double_keccak_Type; + } + static inline const TypeFunc* multiplyToLen_Type() { assert(_multiplyToLen_Type != nullptr, "should be initialized"); return _multiplyToLen_Type; @@ -577,6 +588,31 @@ class OptoRuntime : public AllStatic { return _chacha20Block_Type; } + static inline const TypeFunc* dilithiumAlmostNtt_Type() { + assert(_dilithiumAlmostNtt_Type != nullptr, "should be initialized"); + return _dilithiumAlmostNtt_Type; + } + + static inline const TypeFunc* dilithiumAlmostInverseNtt_Type() { + assert(_dilithiumAlmostInverseNtt_Type != nullptr, "should be initialized"); + return _dilithiumAlmostInverseNtt_Type; + } + + static inline const TypeFunc* dilithiumNttMult_Type() { + assert(_dilithiumNttMult_Type != nullptr, "should be initialized"); + return _dilithiumNttMult_Type; + } + + static inline const TypeFunc* dilithiumMontMulByConstant_Type() { + assert(_dilithiumMontMulByConstant_Type != nullptr, "should be initialized"); + return _dilithiumMontMulByConstant_Type; + } + + static inline const TypeFunc* dilithiumDecomposePoly_Type() { + assert(_dilithiumDecomposePoly_Type != nullptr, "should be initialized"); + return _dilithiumDecomposePoly_Type; + } + // Base64 encode function static inline const TypeFunc* base64_encodeBlock_Type() { assert(_base64_encodeBlock_Type != nullptr, "should be initialized"); diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 31aa1507d23..092fa07e184 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -33,7 +33,7 @@ SuperWord::SuperWord(const VLoopAnalyzer &vloop_analyzer) : _vloop_analyzer(vloop_analyzer), _vloop(vloop_analyzer.vloop()), - _arena(mtCompiler), + _arena(mtCompiler, Arena::Tag::tag_superword), _clone_map(phase()->C->clone_map()), // map of nodes created in cloning _pairset(&_arena, _vloop_analyzer), _packset(&_arena, _vloop_analyzer @@ -1484,7 +1484,8 @@ const AlignmentSolution* SuperWord::pack_alignment_solution(const Node_List* pac pack->size(), pre_end->init_trip(), pre_end->stride_con(), - iv_stride() + iv_stride(), + _vloop.are_speculative_checks_possible() DEBUG_ONLY(COMMA is_trace_align_vector())); return solver.solve(); } @@ -1896,6 +1897,7 @@ bool SuperWord::schedule_and_apply() const { VTransformTrace trace(_vloop.vtrace(), is_trace_superword_rejections(), is_trace_align_vector(), + _vloop.is_trace_speculative_runtime_checks(), is_trace_superword_info()); #endif VTransform vtransform(_vloop_analyzer, @@ -1938,8 +1940,11 @@ void VTransform::apply() { adjust_pre_loop_limit_to_align_main_loop_vectors(); C->print_method(PHASE_AUTO_VECTORIZATION3_AFTER_ADJUST_LIMIT, 4, cl()); + apply_speculative_runtime_checks(); + C->print_method(PHASE_AUTO_VECTORIZATION4_AFTER_SPECULATIVE_RUNTIME_CHECKS, 4, cl()); + apply_vectorization(); - C->print_method(PHASE_AUTO_VECTORIZATION4_AFTER_APPLY, 4, cl()); + C->print_method(PHASE_AUTO_VECTORIZATION5_AFTER_APPLY, 4, cl()); } // We prepare the memory graph for the replacement of scalar memops with vector memops. diff --git a/src/hotspot/share/opto/traceAutoVectorizationTag.hpp b/src/hotspot/share/opto/traceAutoVectorizationTag.hpp index 0c08777c90c..0e14964263d 100644 --- a/src/hotspot/share/opto/traceAutoVectorizationTag.hpp +++ b/src/hotspot/share/opto/traceAutoVectorizationTag.hpp @@ -29,25 +29,26 @@ #include "utilities/stringUtils.hpp" #define COMPILER_TRACE_AUTO_VECTORIZATION_TAG(flags) \ - flags(POINTER_PARSING, "Trace VPointer/MemPointer parsing") \ - flags(POINTER_ALIASING, "Trace VPointer/MemPointer aliasing") \ - flags(POINTER_ADJACENCY, "Trace VPointer/MemPointer adjacency") \ - flags(POINTER_OVERLAP, "Trace VPointer/MemPointer overlap") \ - flags(PRECONDITIONS, "Trace VLoop::check_preconditions") \ - flags(LOOP_ANALYZER, "Trace VLoopAnalyzer::setup_submodules") \ - flags(MEMORY_SLICES, "Trace VLoopMemorySlices") \ - flags(BODY, "Trace VLoopBody") \ - flags(TYPES, "Trace VLoopTypes") \ - flags(POINTERS, "Trace VLoopPointers") \ - flags(DEPENDENCY_GRAPH, "Trace VLoopDependencyGraph") \ - flags(SW_ADJACENT_MEMOPS, "Trace SuperWord::find_adjacent_memop_pairs") \ - flags(SW_REJECTIONS, "Trace SuperWord rejections (non vectorizations)") \ - flags(SW_PACKSET, "Trace SuperWord packset at different stages") \ - flags(SW_INFO, "Trace SuperWord info (equivalent to TraceSuperWord)") \ - flags(SW_VERBOSE, "Trace SuperWord verbose (all SW tags enabled)") \ - flags(ALIGN_VECTOR, "Trace AlignVector") \ - flags(VTRANSFORM, "Trace VTransform Graph") \ - flags(ALL, "Trace everything (very verbose)") + flags(POINTER_PARSING, "Trace VPointer/MemPointer parsing") \ + flags(POINTER_ALIASING, "Trace VPointer/MemPointer aliasing") \ + flags(POINTER_ADJACENCY, "Trace VPointer/MemPointer adjacency") \ + flags(POINTER_OVERLAP, "Trace VPointer/MemPointer overlap") \ + flags(PRECONDITIONS, "Trace VLoop::check_preconditions") \ + flags(LOOP_ANALYZER, "Trace VLoopAnalyzer::setup_submodules") \ + flags(MEMORY_SLICES, "Trace VLoopMemorySlices") \ + flags(BODY, "Trace VLoopBody") \ + flags(TYPES, "Trace VLoopTypes") \ + flags(POINTERS, "Trace VLoopPointers") \ + flags(DEPENDENCY_GRAPH, "Trace VLoopDependencyGraph") \ + flags(SW_ADJACENT_MEMOPS, "Trace SuperWord::find_adjacent_memop_pairs") \ + flags(SW_REJECTIONS, "Trace SuperWord rejections (non vectorizations)") \ + flags(SW_PACKSET, "Trace SuperWord packset at different stages") \ + flags(SW_INFO, "Trace SuperWord info (equivalent to TraceSuperWord)") \ + flags(SW_VERBOSE, "Trace SuperWord verbose (all SW tags enabled)") \ + flags(ALIGN_VECTOR, "Trace AlignVector") \ + flags(SPECULATIVE_RUNTIME_CHECKS, "Trace VTransform::apply_speculative_runtime_checks") \ + flags(VTRANSFORM, "Trace VTransform Graph") \ + flags(ALL, "Trace everything (very verbose)") #define table_entry(name, description) name, enum TraceAutoVectorizationTag { diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 333e936d56f..de66168f4bc 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -491,7 +491,7 @@ void Type::Initialize_shared(Compile* current) { // locking. Arena* save = current->type_arena(); - Arena* shared_type_arena = new (mtCompiler)Arena(mtCompiler); + Arena* shared_type_arena = new (mtCompiler)Arena(mtCompiler, Arena::Tag::tag_type); current->set_type_arena(shared_type_arena); diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index 49968283a58..61e53ec1c07 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -81,7 +81,6 @@ class VerifyMeet; // different kind of Type exists. Types are never modified after creation, so // all their interesting fields are constant. class Type { - friend class VMStructs; public: enum TYPES { diff --git a/src/hotspot/share/opto/vectorization.cpp b/src/hotspot/share/opto/vectorization.cpp index ffc2314a59b..e607a1065dd 100644 --- a/src/hotspot/share/opto/vectorization.cpp +++ b/src/hotspot/share/opto/vectorization.cpp @@ -93,9 +93,9 @@ VStatus VLoop::check_preconditions_helper() { return VStatus::make_failure(VLoop::FAILURE_BACKEDGE); } - // To align vector memory accesses in the main-loop, we will have to adjust - // the pre-loop limit. if (_cl->is_main_loop()) { + // To align vector memory accesses in the main-loop, we will have to adjust + // the pre-loop limit. CountedLoopEndNode* pre_end = _cl->find_pre_loop_end(); if (pre_end == nullptr) { return VStatus::make_failure(VLoop::FAILURE_PRE_LOOP_LIMIT); @@ -105,6 +105,41 @@ VStatus VLoop::check_preconditions_helper() { return VStatus::make_failure(VLoop::FAILURE_PRE_LOOP_LIMIT); } _pre_loop_end = pre_end; + + // See if we find the infrastructure for speculative runtime-checks. + // (1) Auto Vectorization Parse Predicate + Node* pre_ctrl = pre_loop_head()->in(LoopNode::EntryControl); + const Predicates predicates(pre_ctrl); + const PredicateBlock* predicate_block = predicates.auto_vectorization_check_block(); + if (predicate_block->has_parse_predicate()) { + _auto_vectorization_parse_predicate_proj = predicate_block->parse_predicate_success_proj(); + } + + // (2) Multiversioning fast-loop projection + IfTrueNode* before_predicates = predicates.entry()->isa_IfTrue(); + if (before_predicates != nullptr && + before_predicates->in(0)->is_If() && + before_predicates->in(0)->in(1)->is_OpaqueMultiversioning()) { + _multiversioning_fast_proj = before_predicates; + } +#ifndef PRODUCT + if (is_trace_preconditions() || is_trace_speculative_runtime_checks()) { + tty->print_cr(" Infrastructure for speculative runtime-checks:"); + if (_auto_vectorization_parse_predicate_proj != nullptr) { + tty->print_cr(" auto_vectorization_parse_predicate_proj: speculate and trap"); + _auto_vectorization_parse_predicate_proj->dump_bfs(5,0,""); + } else if (_multiversioning_fast_proj != nullptr) { + tty->print_cr(" multiversioning_fast_proj: speculate and multiversion"); + _multiversioning_fast_proj->dump_bfs(5,0,""); + } else { + tty->print_cr(" Not found."); + } + } +#endif + assert(_auto_vectorization_parse_predicate_proj == nullptr || + _multiversioning_fast_proj == nullptr, "we should only have at most one of these"); + assert(_cl->is_multiversion_fast_loop() == (_multiversioning_fast_proj != nullptr), + "must find the multiversion selector IFF loop is a multiversion fast loop"); } return VStatus::make_success(); @@ -472,15 +507,28 @@ AlignmentSolution* AlignmentSolver::solve() const { // + con + con + C_const (sum of constant terms) // // We describe the 6 terms: - // 1) The "base" of the address is the address of a Java object (e.g. array), - // and as such ObjectAlignmentInBytes (a power of 2) aligned. We have - // defined aw = MIN(vector_width, ObjectAlignmentInBytes), which is also + // 1) The "base" of the address: + // - For heap objects, this is the base of the object, and as such + // ObjectAlignmentInBytes (a power of 2) aligned. + // - For off-heap / native memory, the "base" has no alignment + // gurantees. To ensure alignment we can do either of these: + // - Add a runtime check to verify ObjectAlignmentInBytes alignment, + // i.e. we can speculatively compile with an alignment assumption. + // If we pass the check, we can go into the loop with the alignment + // assumption, if we fail we have to trap/deopt or take the other + // loop version without alignment assumptions. + // - If runtime checks are not possible, then we return an empty + // solution, i.e. we do not vectorize the corresponding pack. + // + // Let us assume we have an object "base", or passed the alignment + // runtime check for native "bases", hence we know: + // + // base % ObjectAlignmentInBytes = 0 + // + // We defined aw = MIN(vector_width, ObjectAlignmentInBytes), which is // a power of 2. And hence we know that "base" is thus also aw-aligned: // - // base % ObjectAlignmentInBytes = 0 ==> base % aw = 0 - // - // TODO: Note: we have been assuming that this also holds for native memory base - // addresses. This is incorrect, see JDK-8323582. + // base % ObjectAlignmentInBytes = 0 ==> base % aw = 0 (BASE_ALIGNED) // // 2) The "C_const" term is the sum of all constant terms. This is "con", // plus "iv_scale * init" if it is constant. @@ -505,6 +553,13 @@ AlignmentSolution* AlignmentSolver::solve() const { // 6) The "C_main * main_iter" term represents how much the iv is increased // during "main_iter" main-loop iterations. + // For native memory, we must add a runtime-check that "base % ObjectAlignmentInBytes = ", + // to ensure (BASE_ALIGNED). If we cannot add this runtime-check, we have no guarantee on + // its alignment. + if (!_vpointer.mem_pointer().base().is_object() && !_are_speculative_checks_possible) { + return new EmptyAlignmentSolution("Cannot add speculative check for native memory alignment."); + } + // Attribute init (i.e. _init_node) either to C_const or to C_init term. const int C_const_init = _init_node->is_ConI() ? _init_node->as_ConI()->get_int() : 0; const int C_const = _vpointer.con() + C_const_init * iv_scale(); @@ -521,8 +576,7 @@ AlignmentSolution* AlignmentSolver::solve() const { // We must find a pre_iter, such that adr is aw aligned: adr % aw = 0. Note, that we are defining the // modulo operator "%" such that the remainder is always positive, see AlignmentSolution::mod(i, q). // - // TODO: Note: the following assumption is incorrect for native memory bases, see JDK-8323582. - // Since "base % aw = 0", we only need to ensure alignment of the other 5 terms: + // Since "base % aw = 0" (BASE_ALIGNED), we only need to ensure alignment of the other 5 terms: // // (C_const + C_invar * var_invar + C_init * var_init + C_pre * pre_iter + C_main * main_iter) % aw = 0 (1) // @@ -878,8 +932,7 @@ AlignmentSolution* AlignmentSolver::solve() const { // + iv_scale * pre_stride * pre_iter // + iv_scale * main_stride * main_iter)) % aw = // - // -> base aligned: base % aw = 0 - // TODO: Note: this assumption is incorrect for native memory bases, see JDK-8323582. + // -> apply (BASE_ALIGNED): base % aw = 0 // -> main-loop iterations aligned (2): C_main % aw = (iv_scale * main_stride) % aw = 0 // (con + invar + iv_scale * init + iv_scale * pre_stride * pre_iter) % aw = // @@ -958,7 +1011,7 @@ void AlignmentSolver::trace_start_solve() const { _pre_stride, _main_stride); // adr = base + con + invar + iv_scale * iv tty->print(" adr = base[%d]", base().object_or_native()->_idx); - tty->print(" + invar + iv_scale(%d) * iv + con(%d)", iv_scale(), _vpointer.con()); + tty->print_cr(" + invar + iv_scale(%d) * iv + con(%d)", iv_scale(), _vpointer.con()); } } diff --git a/src/hotspot/share/opto/vectorization.hpp b/src/hotspot/share/opto/vectorization.hpp index cb1e8c45856..d4b78515312 100644 --- a/src/hotspot/share/opto/vectorization.hpp +++ b/src/hotspot/share/opto/vectorization.hpp @@ -85,6 +85,14 @@ class VLoop : public StackObj { PhiNode* _iv; CountedLoopEndNode* _pre_loop_end; // cache access to pre-loop for main loops only + // We can add speculative runtime-checks if we have one of these: + // - Auto Vectorization Parse Predicate: + // pass all checks or trap -> recompile without this predicate. + // - Multiversioning fast-loop projection: + // pass all checks or go to slow-path-loop, where we have no speculative assumptions. + ParsePredicateSuccessProj* _auto_vectorization_parse_predicate_proj; + IfTrueNode* _multiversioning_fast_proj; + NOT_PRODUCT(VTrace _vtrace;) NOT_PRODUCT(TraceMemPointer _mptrace;) @@ -104,7 +112,9 @@ class VLoop : public StackObj { _cl (nullptr), _cl_exit (nullptr), _iv (nullptr), - _pre_loop_end (nullptr) + _pre_loop_end (nullptr), + _auto_vectorization_parse_predicate_proj(nullptr), + _multiversioning_fast_proj(nullptr) #ifndef PRODUCT COMMA _mptrace(TraceMemPointer( @@ -138,6 +148,19 @@ class VLoop : public StackObj { return head; }; + ParsePredicateSuccessProj* auto_vectorization_parse_predicate_proj() const { + return _auto_vectorization_parse_predicate_proj; + } + + IfTrueNode* multiversioning_fast_proj() const { + return _multiversioning_fast_proj; + } + + bool are_speculative_checks_possible() const { + return _auto_vectorization_parse_predicate_proj != nullptr || + _multiversioning_fast_proj != nullptr; + } + // Estimate maximum size for data structures, to avoid repeated reallocation int estimated_body_length() const { return lpt()->_body.size(); }; int estimated_node_count() const { return (int)(1.10 * phase()->C->unique()); }; @@ -176,6 +199,10 @@ class VLoop : public StackObj { bool is_trace_vpointers() const { return _vtrace.is_trace(TraceAutoVectorizationTag::POINTERS); } + + bool is_trace_speculative_runtime_checks() const { + return _vtrace.is_trace(TraceAutoVectorizationTag::SPECULATIVE_RUNTIME_CHECKS); + } #endif // Is the node in the basic block of the loop? @@ -229,7 +256,7 @@ class VSharedData : public StackObj { public: VSharedData() : - _arena(mtCompiler), + _arena(mtCompiler, Arena::Tag::tag_superword), _node_idx_to_loop_body_idx(&_arena, estimated_node_count(), 0, 0) { } @@ -418,7 +445,7 @@ class VLoopBody : public StackObj { // types (byte, char, short). In the C2 IR, their operations are // done with full int type with 4 byte precision (e.g. AddI, MulI). // Example: char a,b,c; a = (char)(b + c); -// However, if we can prove the the upper bits are only truncated, +// However, if we can prove the upper bits are only truncated, // and the lower bits for the narrower type computed correctly, we // can compute the operations in the narrower type directly (e.g we // perform the AddI or MulI with 1 or 2 bytes). This allows us to @@ -669,7 +696,7 @@ class VLoopAnalyzer : StackObj { public: VLoopAnalyzer(const VLoop& vloop, VSharedData& vshared) : _vloop(vloop), - _arena(mtCompiler), + _arena(mtCompiler, Arena::Tag::tag_superword), _success(false), _reductions (&_arena, vloop), _memory_slices (&_arena, vloop), @@ -1296,6 +1323,14 @@ class AlignmentSolver { const int _pre_stride; // address increment per pre-loop iteration const int _main_stride; // address increment per main-loop iteration + // For native bases, we have no alignment guarantee. This means we cannot in + // general guarantee alignment statically. But we can check alignment with a + // speculative runtime check, see VTransform::apply_speculative_runtime_checks. + // For this, we need find the Predicate for auto vectorization checks, or else + // we need to find the multiversion_if. If we cannot find either, then we + // cannot make any speculative runtime checks. + const bool _are_speculative_checks_possible; + DEBUG_ONLY( const bool _is_trace; ); static const MemNode* mem_ref_not_null(const MemNode* mem_ref) { @@ -1309,7 +1344,8 @@ class AlignmentSolver { const uint vector_length, const Node* init_node, const int pre_stride, - const int main_stride + const int main_stride, + const bool are_speculative_checks_possible DEBUG_ONLY( COMMA const bool is_trace) ) : _vpointer( vpointer), @@ -1318,7 +1354,8 @@ class AlignmentSolver { _aw( MIN2(_vector_width, ObjectAlignmentInBytes)), _init_node( init_node), _pre_stride( pre_stride), - _main_stride( main_stride) + _main_stride( main_stride), + _are_speculative_checks_possible(are_speculative_checks_possible) DEBUG_ONLY( COMMA _is_trace(is_trace) ) { assert(_mem_ref != nullptr && diff --git a/src/hotspot/share/opto/vtransform.cpp b/src/hotspot/share/opto/vtransform.cpp index 4730f3ac134..18b5c09acb8 100644 --- a/src/hotspot/share/opto/vtransform.cpp +++ b/src/hotspot/share/opto/vtransform.cpp @@ -23,6 +23,7 @@ #include "opto/vtransform.hpp" #include "opto/vectornode.hpp" +#include "opto/castnode.hpp" #include "opto/convertnode.hpp" void VTransformGraph::add_vtnode(VTransformNode* vtnode) { @@ -143,6 +144,94 @@ void VTransformApplyResult::trace(VTransformNode* vtnode) const { } #endif +void VTransform::apply_speculative_runtime_checks() { + if (VLoop::vectors_should_be_aligned()) { +#ifdef ASSERT + if (_trace._align_vector || _trace._speculative_runtime_checks) { + tty->print_cr("\nVTransform::apply_speculative_runtime_checks: native memory alignment"); + } +#endif + + const GrowableArray<VTransformNode*>& vtnodes = _graph.vtnodes(); + for (int i = 0; i < vtnodes.length(); i++) { + VTransformVectorNode* vtn = vtnodes.at(i)->isa_Vector(); + if (vtn == nullptr) { continue; } + MemNode* p0 = vtn->nodes().at(0)->isa_Mem(); + if (p0 == nullptr) { continue; } + const VPointer& vp = vpointer(p0); + if (vp.mem_pointer().base().is_object()) { continue; } + assert(vp.mem_pointer().base().is_native(), "VPointer base must be object or native"); + + // We have a native memory reference. Build a runtime check for it. + // See: AlignmentSolver::solve + // In a future RFE we may be able to speculate on invar alignment as + // well, and allow vectorization of more cases. + add_speculative_alignment_check(vp.mem_pointer().base().native(), ObjectAlignmentInBytes); + } + } +} + +#define TRACE_SPECULATIVE_ALIGNMENT_CHECK(node) { \ + DEBUG_ONLY( \ + if (_trace._align_vector || _trace._speculative_runtime_checks) { \ + tty->print(" " #node ": "); \ + node->dump(); \ + } \ + ) \ +} \ + +// Check: (node % alignment) == 0. +void VTransform::add_speculative_alignment_check(Node* node, juint alignment) { + TRACE_SPECULATIVE_ALIGNMENT_CHECK(node); + Node* ctrl = phase()->get_ctrl(node); + + // Cast adr/long -> int + if (node->bottom_type()->basic_type() == T_ADDRESS) { + // adr -> int/long + node = new CastP2XNode(nullptr, node); + phase()->register_new_node(node, ctrl); + TRACE_SPECULATIVE_ALIGNMENT_CHECK(node); + } + if (node->bottom_type()->basic_type() == T_LONG) { + // long -> int + node = new ConvL2INode(node); + phase()->register_new_node(node, ctrl); + TRACE_SPECULATIVE_ALIGNMENT_CHECK(node); + } + + Node* mask_alignment = igvn().intcon(alignment-1); + Node* base_alignment = new AndINode(node, mask_alignment); + phase()->register_new_node(base_alignment, ctrl); + TRACE_SPECULATIVE_ALIGNMENT_CHECK(mask_alignment); + TRACE_SPECULATIVE_ALIGNMENT_CHECK(base_alignment); + + Node* zero = igvn().intcon(0); + Node* cmp_alignment = CmpNode::make(base_alignment, zero, T_INT, false); + BoolNode* bol_alignment = new BoolNode(cmp_alignment, BoolTest::eq); + phase()->register_new_node(cmp_alignment, ctrl); + phase()->register_new_node(bol_alignment, ctrl); + TRACE_SPECULATIVE_ALIGNMENT_CHECK(cmp_alignment); + TRACE_SPECULATIVE_ALIGNMENT_CHECK(bol_alignment); + + add_speculative_check(bol_alignment); +} + +void VTransform::add_speculative_check(BoolNode* bol) { + assert(_vloop.are_speculative_checks_possible(), "otherwise we cannot make speculative assumptions"); + ParsePredicateSuccessProj* parse_predicate_proj = _vloop.auto_vectorization_parse_predicate_proj(); + IfTrueNode* new_check_proj = nullptr; + if (parse_predicate_proj != nullptr) { + new_check_proj = phase()->create_new_if_for_predicate(parse_predicate_proj, nullptr, + Deoptimization::Reason_auto_vectorization_check, + Op_If); + } else { + new_check_proj = phase()->create_new_if_for_multiversion(_vloop.multiversioning_fast_proj()); + } + Node* iff_speculate = new_check_proj->in(0); + igvn().replace_input_of(iff_speculate, 1, bol); + TRACE_SPECULATIVE_ALIGNMENT_CHECK(iff_speculate); +} + // Helper-class for VTransformGraph::has_store_to_load_forwarding_failure. // It wraps a VPointer. The VPointer has an iv_offset applied, which // simulates a virtual unrolling. They represent the memory region: diff --git a/src/hotspot/share/opto/vtransform.hpp b/src/hotspot/share/opto/vtransform.hpp index 4fc68c7b4df..588da3cd56e 100644 --- a/src/hotspot/share/opto/vtransform.hpp +++ b/src/hotspot/share/opto/vtransform.hpp @@ -109,16 +109,19 @@ class VTransformTrace { const bool _verbose; const bool _rejections; const bool _align_vector; + const bool _speculative_runtime_checks; const bool _info; VTransformTrace(const VTrace& vtrace, const bool is_trace_rejections, const bool is_trace_align_vector, + const bool is_trace_speculative_runtime_checks, const bool is_trace_info) : - _verbose (vtrace.is_trace(TraceAutoVectorizationTag::ALL)), - _rejections (_verbose | is_trace_vtransform(vtrace) | is_trace_rejections), - _align_vector(_verbose | is_trace_vtransform(vtrace) | is_trace_align_vector), - _info (_verbose | is_trace_vtransform(vtrace) | is_trace_info) {} + _verbose (vtrace.is_trace(TraceAutoVectorizationTag::ALL)), + _rejections (_verbose | is_trace_vtransform(vtrace) | is_trace_rejections), + _align_vector (_verbose | is_trace_vtransform(vtrace) | is_trace_align_vector), + _speculative_runtime_checks(_verbose | is_trace_vtransform(vtrace) | is_trace_speculative_runtime_checks), + _info (_verbose | is_trace_vtransform(vtrace) | is_trace_info) {} static bool is_trace_vtransform(const VTrace& vtrace) { return vtrace.is_trace(TraceAutoVectorizationTag::VTRANSFORM); @@ -214,7 +217,7 @@ class VTransform : public StackObj { _vloop_analyzer(vloop_analyzer), _vloop(vloop_analyzer.vloop()), NOT_PRODUCT(_trace(trace) COMMA) - _arena(mtCompiler), + _arena(mtCompiler, Arena::Tag::tag_superword), _graph(_vloop_analyzer, _arena NOT_PRODUCT(COMMA _trace)), _mem_ref_for_main_loop_alignment(mem_ref_for_main_loop_alignment), _aw_for_main_loop_alignment(aw_for_main_loop_alignment) {} @@ -245,6 +248,10 @@ class VTransform : public StackObj { void determine_mem_ref_and_aw_for_main_loop_alignment(); void adjust_pre_loop_limit_to_align_main_loop_vectors(); + void apply_speculative_runtime_checks(); + void add_speculative_alignment_check(Node* node, juint alignment); + void add_speculative_check(BoolNode* bol); + void apply_vectorization() const; }; diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 0776d501339..05cccd4fe45 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -81,6 +81,10 @@ VirtualizationType Abstract_VM_Version::_detected_virtualization = NoDetectedVir #error HOTSPOT_BUILD_TIME must be defined #endif +#ifndef JVM_VARIANT + #error JVM_VARIANT must be defined +#endif + #define VM_RELEASE HOTSPOT_VERSION_STRING // HOTSPOT_VERSION_STRING equals the JDK VERSION_STRING (unless overridden @@ -195,6 +199,10 @@ const char *Abstract_VM_Version::vm_platform_string() { return OS "-" CPU; } +const char* Abstract_VM_Version::vm_variant() { + return JVM_VARIANT; +} + const char* Abstract_VM_Version::internal_vm_info_string() { #ifndef HOTSPOT_BUILD_COMPILER #ifdef _MSC_VER diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp index 491d8a49dae..8cfc7031f97 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.hpp +++ b/src/hotspot/share/runtime/abstract_vm_version.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, 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 @@ -110,6 +110,7 @@ class Abstract_VM_Version: AllStatic { static const char* vm_info_string(); static const char* vm_release(); static const char* vm_platform_string(); + static const char* vm_variant(); static int vm_major_version() { return _vm_major_version; } static int vm_minor_version() { return _vm_minor_version; } diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 075b62d67bf..ed26dd535a3 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -36,6 +36,7 @@ #include "gc/shared/collectedHeap.hpp" #include "gc/shared/memAllocator.hpp" #include "interpreter/bytecode.hpp" +#include "interpreter/bytecode.inline.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/oopMapCache.hpp" @@ -668,11 +669,12 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread bool caller_was_method_handle = false; if (deopt_sender.is_interpreted_frame()) { methodHandle method(current, deopt_sender.interpreter_frame_method()); - Bytecode_invoke cur = Bytecode_invoke_check(method, deopt_sender.interpreter_frame_bci()); - if (cur.is_invokedynamic() || cur.is_invokehandle()) { - // Method handle invokes may involve fairly arbitrary chains of - // calls so it's impossible to know how much actual space the - // caller has for locals. + Bytecode_invoke cur(method, deopt_sender.interpreter_frame_bci()); + if (cur.has_member_arg()) { + // This should cover all real-world cases. One exception is a pathological chain of + // MH.linkToXXX() linker calls, which only trusted code could do anyway. To handle that case, we + // would need to get the size from the resolved method entry. Another exception would + // be an invokedynamic with an adapter that is really a MethodHandle linker. caller_was_method_handle = true; } } @@ -775,9 +777,14 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread } #endif + int caller_actual_parameters = -1; // value not used except for interpreted frames, see below + if (deopt_sender.is_interpreted_frame()) { + caller_actual_parameters = callee_parameters + (caller_was_method_handle ? 1 : 0); + } + UnrollBlock* info = new UnrollBlock(array->frame_size() * BytesPerWord, caller_adjustment * BytesPerWord, - caller_was_method_handle ? 0 : callee_parameters, + caller_actual_parameters, number_of_frames, frame_sizes, frame_pcs, @@ -966,7 +973,7 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m if (Bytecodes::is_invoke(cur_code)) { Bytecode_invoke invoke(mh, iframe->interpreter_frame_bci()); cur_invoke_parameter_size = invoke.size_of_parameters(); - if (i != 0 && !invoke.is_invokedynamic() && MethodHandles::has_member_arg(invoke.klass(), invoke.name())) { + if (i != 0 && invoke.has_member_arg()) { callee_size_of_parameters++; } } @@ -2823,6 +2830,7 @@ const char* Deoptimization::_trap_reason_name[] = { "intrinsic" JVMCI_ONLY("_or_type_checked_inlining"), "bimorphic" JVMCI_ONLY("_or_optimized_type_check"), "profile_predicate", + "auto_vectorization_check", "unloaded", "uninitialized", "initialized", diff --git a/src/hotspot/share/runtime/deoptimization.hpp b/src/hotspot/share/runtime/deoptimization.hpp index dff93052cfd..a7b6632d62a 100644 --- a/src/hotspot/share/runtime/deoptimization.hpp +++ b/src/hotspot/share/runtime/deoptimization.hpp @@ -98,6 +98,7 @@ class Deoptimization : AllStatic { #endif Reason_profile_predicate, // compiler generated predicate moved from frequent branch in a loop failed + Reason_auto_vectorization_check, // compiler generated (speculative) auto vectorization checks failed // recorded per method Reason_unloaded, // unloaded class or constant pool entry diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index ea636e1d88f..4933d445e7a 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -325,6 +325,9 @@ const int ObjectAlignmentInBytes = 8; product(bool, UseChaCha20Intrinsics, false, DIAGNOSTIC, \ "Use intrinsics for the vectorized version of ChaCha20") \ \ + product(bool, UseDilithiumIntrinsics, false, DIAGNOSTIC, \ + "Use intrinsics for the vectorized version of Dilithium") \ + \ product(bool, UseMD5Intrinsics, false, DIAGNOSTIC, \ "Use intrinsics for MD5 crypto hash function") \ \ @@ -1427,6 +1430,9 @@ const int ObjectAlignmentInBytes = 8; product(bool, PrintMetaspaceStatisticsAtExit, false, DIAGNOSTIC, \ "Print metaspace statistics upon VM exit.") \ \ + product(bool, PrintCompilerMemoryStatisticsAtExit, false, DIAGNOSTIC, \ + "Print compiler memory statistics upon VM exit.") \ + \ product(uintx, MinHeapFreeRatio, 40, MANAGEABLE, \ "The minimum percentage of heap free after GC to avoid expansion."\ " For most GCs this applies to the old generation. In G1 and" \ diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index b2c24169505..45e63e90ffb 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -353,8 +353,8 @@ void print_statistics() { MetaspaceUtils::print_basic_report(tty, 0); } - if (CompilerOracle::should_print_final_memstat_report()) { - CompilationMemoryStatistic::print_all_by_size(tty, false, 0); + if (PrintCompilerMemoryStatisticsAtExit) { + CompilationMemoryStatistic::print_final_report(tty); } ThreadsSMRSupport::log_statistics(); diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index 94c4c242f82..29971d7b4f8 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -144,7 +144,7 @@ class ObjectMonitor : public CHeapObj<mtObjectMonitor> { // ParkEvent of unblocker thread. static ParkEvent* _vthread_unparker_ParkEvent; - // Because of frequent access, the the metadata field is at offset zero (0). + // Because of frequent access, the metadata field is at offset zero (0). // Enforced by the assert() in metadata_addr(). // * LM_LIGHTWEIGHT with UseObjectMonitorTable: // Contains the _object's hashCode. diff --git a/src/hotspot/share/runtime/safepoint.cpp b/src/hotspot/share/runtime/safepoint.cpp index c8427b2a55f..00a5ed6802b 100644 --- a/src/hotspot/share/runtime/safepoint.cpp +++ b/src/hotspot/share/runtime/safepoint.cpp @@ -1010,13 +1010,16 @@ void SafepointTracing::end() { "Reaching safepoint: " JLONG_FORMAT " ns, " "At safepoint: " JLONG_FORMAT " ns, " "Leaving safepoint: " JLONG_FORMAT " ns, " - "Total: " JLONG_FORMAT " ns", + "Total: " JLONG_FORMAT " ns, " + "Threads: %d runnable, %d total", VM_Operation::name(_current_type), _last_app_time_ns, _last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns, _last_safepoint_leave_time_ns - _last_safepoint_sync_time_ns, _last_safepoint_end_time_ns - _last_safepoint_leave_time_ns, - _last_safepoint_end_time_ns - _last_safepoint_begin_time_ns + _last_safepoint_end_time_ns - _last_safepoint_begin_time_ns, + _nof_running, + _nof_threads ); RuntimeService::record_safepoint_end(_last_safepoint_end_time_ns - _last_safepoint_sync_time_ns); diff --git a/src/hotspot/share/runtime/sharedRuntime.hpp b/src/hotspot/share/runtime/sharedRuntime.hpp index 8083a159679..7a116d038e8 100644 --- a/src/hotspot/share/runtime/sharedRuntime.hpp +++ b/src/hotspot/share/runtime/sharedRuntime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,8 +57,6 @@ enum class SharedStubId :int { #undef SHARED_STUB_ID_ENUM_DECLARE class SharedRuntime: AllStatic { - friend class VMStructs; - private: // Declare shared stub fields #define SHARED_STUB_FIELD_DECLARE(name, type) \ diff --git a/src/hotspot/share/runtime/stubDeclarations.hpp b/src/hotspot/share/runtime/stubDeclarations.hpp index 6246ae4e7bb..bbad16276ce 100644 --- a/src/hotspot/share/runtime/stubDeclarations.hpp +++ b/src/hotspot/share/runtime/stubDeclarations.hpp @@ -507,7 +507,7 @@ // Currently there is no support for a do_arch_array_entry template. // Include arch-specific stub and entry declarations and make sure the -// relevant template macros ahve been defined +// relevant template macros have been defined #include CPU_HEADER(stubDeclarations) @@ -688,6 +688,21 @@ ghash_processBlocks) \ do_stub(compiler, chacha20Block) \ do_entry(compiler, chacha20Block, chacha20Block, chacha20Block) \ + do_stub(compiler, dilithiumAlmostNtt) \ + do_entry(compiler, dilithiumAlmostNtt, \ + dilithiumAlmostNtt, dilithiumAlmostNtt) \ + do_stub(compiler, dilithiumAlmostInverseNtt) \ + do_entry(compiler, dilithiumAlmostInverseNtt, \ + dilithiumAlmostInverseNtt, dilithiumAlmostInverseNtt) \ + do_stub(compiler, dilithiumNttMult) \ + do_entry(compiler, dilithiumNttMult, \ + dilithiumNttMult, dilithiumNttMult) \ + do_stub(compiler, dilithiumMontMulByConstant) \ + do_entry(compiler, dilithiumMontMulByConstant, \ + dilithiumMontMulByConstant, dilithiumMontMulByConstant) \ + do_stub(compiler, dilithiumDecomposePoly) \ + do_entry(compiler, dilithiumDecomposePoly, \ + dilithiumDecomposePoly, dilithiumDecomposePoly) \ do_stub(compiler, data_cache_writeback) \ do_entry(compiler, data_cache_writeback, data_cache_writeback, \ data_cache_writeback) \ @@ -738,6 +753,8 @@ do_stub(compiler, sha3_implCompressMB) \ do_entry(compiler, sha3_implCompressMB, sha3_implCompressMB, \ sha3_implCompressMB) \ + do_stub(compiler, double_keccak) \ + do_entry(compiler, double_keccak, double_keccak, double_keccak) \ do_stub(compiler, updateBytesAdler32) \ do_entry(compiler, updateBytesAdler32, updateBytesAdler32, \ updateBytesAdler32) \ @@ -1053,7 +1070,6 @@ DO_ARCH_BLOB_EMPTY2, \ DO_ARCH_ENTRY_EMPTY5, DO_ARCH_ENTRY_EMPTY6) \ - // client macro to operate only on StubGenerator arch blobs #define STUBGEN_ARCH_BLOBS_DO(do_arch_blob) \ @@ -1075,4 +1091,3 @@ do_arch_entry, do_arch_entry_init) \ #endif // SHARE_RUNTIME_STUBDECLARATIONS_HPP - diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp index c3013204904..966cb3e03e5 100644 --- a/src/hotspot/share/runtime/stubRoutines.cpp +++ b/src/hotspot/share/runtime/stubRoutines.cpp @@ -99,6 +99,7 @@ STUBGEN_ENTRIES_DO(DEFINE_ENTRY_FIELD, DEFINE_ENTRY_FIELD_INIT, DEFINE_ENTRY_FIE jint StubRoutines::_verify_oop_count = 0; + address StubRoutines::_string_indexof_array[4] = { nullptr }; address StubRoutines::_vector_f_math[VectorSupport::NUM_VEC_SIZES][VectorSupport::NUM_VECTOR_OP_MATH] = {{nullptr}, {nullptr}}; address StubRoutines::_vector_d_math[VectorSupport::NUM_VEC_SIZES][VectorSupport::NUM_VECTOR_OP_MATH] = {{nullptr}, {nullptr}}; diff --git a/src/hotspot/share/runtime/vframeArray.cpp b/src/hotspot/share/runtime/vframeArray.cpp index 1640b08c479..e17961fc424 100644 --- a/src/hotspot/share/runtime/vframeArray.cpp +++ b/src/hotspot/share/runtime/vframeArray.cpp @@ -25,6 +25,7 @@ #include "classfile/vmSymbols.hpp" #include "code/vmreg.inline.hpp" #include "interpreter/bytecode.hpp" +#include "interpreter/bytecode.inline.hpp" #include "interpreter/interpreter.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" @@ -610,10 +611,7 @@ void vframeArray::unpack_to_stack(frame &unpack_frame, int exec_mode, int caller methodHandle caller(current, elem->method()); methodHandle callee(current, element(index - 1)->method()); Bytecode_invoke inv(caller, elem->bci()); - // invokedynamic instructions don't have a class but obviously don't have a MemberName appendix. - // NOTE: Use machinery here that avoids resolving of any kind. - const bool has_member_arg = - !inv.is_invokedynamic() && MethodHandles::has_member_arg(inv.klass(), inv.name()); + const bool has_member_arg = inv.has_member_arg(); callee_parameters = callee->size_of_parameters() + (has_member_arg ? 1 : 0); callee_locals = callee->max_locals(); } diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index a055e944f56..5e51e80ecd6 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -23,18 +23,9 @@ */ #include "cds/filemap.hpp" -#include "ci/ciField.hpp" -#include "ci/ciInstance.hpp" -#include "ci/ciMethodData.hpp" -#include "ci/ciObjArrayKlass.hpp" -#include "ci/ciSymbol.hpp" #include "classfile/classLoaderDataGraph.hpp" -#include "classfile/dictionary.hpp" #include "classfile/javaClasses.hpp" #include "classfile/javaThreadStatus.hpp" -#include "classfile/stringTable.hpp" -#include "classfile/symbolTable.hpp" -#include "classfile/systemDictionary.hpp" #include "classfile/vmClasses.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeBlob.hpp" @@ -105,10 +96,8 @@ #include "runtime/osThread.hpp" #include "runtime/perfMemory.hpp" #include "runtime/serviceThread.hpp" -#include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" -#include "runtime/threadSMR.hpp" #include "runtime/vframeArray.hpp" #include "runtime/vmStructs.hpp" #include "runtime/vm_version.hpp" @@ -117,36 +106,11 @@ #include "utilities/macros.hpp" #include "utilities/vmError.hpp" #ifdef COMPILER2 -#include "opto/addnode.hpp" -#include "opto/block.hpp" -#include "opto/callnode.hpp" -#include "opto/castnode.hpp" -#include "opto/cfgnode.hpp" -#include "opto/chaitin.hpp" -#include "opto/convertnode.hpp" -#include "opto/divnode.hpp" -#include "opto/intrinsicnode.hpp" -#include "opto/locknode.hpp" -#include "opto/loopnode.hpp" -#include "opto/machnode.hpp" -#include "opto/matcher.hpp" -#include "opto/mathexactnode.hpp" -#include "opto/movenode.hpp" -#include "opto/mulnode.hpp" -#include "opto/narrowptrnode.hpp" -#include "opto/opaquenode.hpp" #include "opto/optoreg.hpp" -#include "opto/parse.hpp" -#include "opto/phaseX.hpp" -#include "opto/regalloc.hpp" -#include "opto/rootnode.hpp" -#include "opto/subnode.hpp" -#include "opto/vectornode.hpp" #endif // COMPILER2 #include CPU_HEADER(vmStructs) #include OS_HEADER(vmStructs) -#include OS_CPU_HEADER(vmStructs) // Note: the cross-product of (c1, c2, product, nonproduct, ...), // (nonstatic, static), and (unchecked, checked) has not been taken. @@ -185,11 +149,7 @@ volatile_static_field, \ unchecked_nonstatic_field, \ volatile_nonstatic_field, \ - nonproduct_nonstatic_field, \ - c1_nonstatic_field, \ - c2_nonstatic_field, \ - unchecked_c1_static_field, \ - unchecked_c2_static_field) \ + nonproduct_nonstatic_field) \ \ /*************/ \ /* GC fields */ \ @@ -442,7 +402,7 @@ volatile_static_field(PerfMemory, _initialized, int) \ \ /********************/ \ - /* SystemDictionary */ \ + /* VM Classes */ \ /********************/ \ \ static_field(vmClasses, VM_CLASS_AT(Object_klass), InstanceKlass*) \ @@ -597,8 +557,6 @@ nonstatic_field(nmethod, _comp_level, CompLevel) \ volatile_nonstatic_field(nmethod, _exception_cache, ExceptionCache*) \ \ - unchecked_c2_static_field(Deoptimization, _trap_reason_name, void*) \ - \ nonstatic_field(Deoptimization::UnrollBlock, _size_of_deoptimized_frame, int) \ nonstatic_field(Deoptimization::UnrollBlock, _caller_adjustment, int) \ nonstatic_field(Deoptimization::UnrollBlock, _number_of_frames, int) \ @@ -668,8 +626,6 @@ nonstatic_field(JavaThread, _monitor_owner_id, int64_t) \ volatile_nonstatic_field(JavaThread, _terminated, JavaThread::TerminatedTypes) \ nonstatic_field(Thread, _osthread, OSThread*) \ - nonstatic_field(Thread, _resource_area, ResourceArea*) \ - nonstatic_field(CompilerThread, _env, ciEnv*) \ \ /************/ \ /* OSThread */ \ @@ -712,75 +668,6 @@ static_field(VMRegImpl, regName[0], const char*) \ static_field(VMRegImpl, stack0, VMReg) \ \ - /*******************************/ \ - /* Runtime1 (NOTE: incomplete) */ \ - /*******************************/ \ - \ - unchecked_c1_static_field(Runtime1, _blobs, sizeof(Runtime1::_blobs)) /* NOTE: no type */ \ - \ - /**************/ \ - /* CI */ \ - /************/ \ - \ - nonstatic_field(ciEnv, _compiler_data, void*) \ - nonstatic_field(ciEnv, _factory, ciObjectFactory*) \ - nonstatic_field(ciEnv, _dependencies, Dependencies*) \ - nonstatic_field(ciEnv, _task, CompileTask*) \ - nonstatic_field(ciEnv, _arena, Arena*) \ - \ - nonstatic_field(ciBaseObject, _ident, uint) \ - \ - nonstatic_field(ciObject, _handle, jobject) \ - nonstatic_field(ciObject, _klass, ciKlass*) \ - \ - nonstatic_field(ciMetadata, _metadata, Metadata*) \ - \ - nonstatic_field(ciSymbol, _symbol, Symbol*) \ - \ - nonstatic_field(ciType, _basic_type, BasicType) \ - \ - nonstatic_field(ciKlass, _name, ciSymbol*) \ - \ - nonstatic_field(ciArrayKlass, _dimension, jint) \ - \ - nonstatic_field(ciObjArrayKlass, _element_klass, ciKlass*) \ - nonstatic_field(ciObjArrayKlass, _base_element_klass, ciKlass*) \ - \ - nonstatic_field(ciInstanceKlass, _init_state, InstanceKlass::ClassState) \ - nonstatic_field(ciInstanceKlass, _is_shared, bool) \ - \ - nonstatic_field(ciMethod, _interpreter_invocation_count, int) \ - nonstatic_field(ciMethod, _interpreter_throwout_count, int) \ - nonstatic_field(ciMethod, _inline_instructions_size, int) \ - \ - nonstatic_field(ciMethodData, _data_size, int) \ - nonstatic_field(ciMethodData, _state, u_char) \ - nonstatic_field(ciMethodData, _extra_data_size, int) \ - nonstatic_field(ciMethodData, _data, intptr_t*) \ - nonstatic_field(ciMethodData, _hint_di, int) \ - nonstatic_field(ciMethodData, _eflags, intx) \ - nonstatic_field(ciMethodData, _arg_local, intx) \ - nonstatic_field(ciMethodData, _arg_stack, intx) \ - nonstatic_field(ciMethodData, _arg_returned, intx) \ - nonstatic_field(ciMethodData, _orig, MethodData::CompilerCounters) \ - \ - nonstatic_field(ciField, _holder, ciInstanceKlass*) \ - nonstatic_field(ciField, _name, ciSymbol*) \ - nonstatic_field(ciField, _signature, ciSymbol*) \ - nonstatic_field(ciField, _offset, int) \ - nonstatic_field(ciField, _is_constant, bool) \ - nonstatic_field(ciField, _constant_value, ciConstant) \ - \ - nonstatic_field(ciObjectFactory, _ci_metadata, GrowableArray<ciMetadata*>) \ - nonstatic_field(ciObjectFactory, _symbols, GrowableArray<ciSymbol*>) \ - \ - nonstatic_field(ciConstant, _type, BasicType) \ - nonstatic_field(ciConstant, _value._int, jint) \ - nonstatic_field(ciConstant, _value._long, jlong) \ - nonstatic_field(ciConstant, _value._float, jfloat) \ - nonstatic_field(ciConstant, _value._double, jdouble) \ - nonstatic_field(ciConstant, _value._object, ciObject*) \ - \ /************/ \ /* Monitors */ \ /************/ \ @@ -800,123 +687,6 @@ volatile_nonstatic_field(MonitorList, _head, ObjectMonitor*) \ \ /*********************/ \ - /* Matcher (C2 only) */ \ - /*********************/ \ - \ - unchecked_c2_static_field(Matcher, _regEncode, sizeof(Matcher::_regEncode)) /* NOTE: no type */ \ - \ - c2_nonstatic_field(Node, _in, Node**) \ - c2_nonstatic_field(Node, _out, Node**) \ - c2_nonstatic_field(Node, _cnt, node_idx_t) \ - c2_nonstatic_field(Node, _max, node_idx_t) \ - c2_nonstatic_field(Node, _outcnt, node_idx_t) \ - c2_nonstatic_field(Node, _outmax, node_idx_t) \ - c2_nonstatic_field(Node, _idx, const node_idx_t) \ - c2_nonstatic_field(Node, _class_id, juint) \ - c2_nonstatic_field(Node, _flags, juint) \ - \ - c2_nonstatic_field(Compile, _root, RootNode*) \ - c2_nonstatic_field(Compile, _unique, uint) \ - c2_nonstatic_field(Compile, _entry_bci, int) \ - c2_nonstatic_field(Compile, _top, Node*) \ - c2_nonstatic_field(Compile, _cfg, PhaseCFG*) \ - c2_nonstatic_field(Compile, _regalloc, PhaseRegAlloc*) \ - c2_nonstatic_field(Compile, _method, ciMethod*) \ - c2_nonstatic_field(Compile, _compile_id, const int) \ - c2_nonstatic_field(Compile, _options, const Options) \ - c2_nonstatic_field(Compile, _ilt, InlineTree*) \ - \ - c2_nonstatic_field(Options, _subsume_loads, const bool) \ - c2_nonstatic_field(Options, _do_escape_analysis, const bool) \ - c2_nonstatic_field(Options, _eliminate_boxing, const bool) \ - c2_nonstatic_field(Options, _do_locks_coarsening, const bool) \ - c2_nonstatic_field(Options, _install_code, const bool) \ - \ - c2_nonstatic_field(InlineTree, _caller_jvms, JVMState*) \ - c2_nonstatic_field(InlineTree, _method, ciMethod*) \ - c2_nonstatic_field(InlineTree, _caller_tree, InlineTree*) \ - c2_nonstatic_field(InlineTree, _subtrees, GrowableArray<InlineTree*>) \ - \ - c2_nonstatic_field(OptoRegPair, _first, short) \ - c2_nonstatic_field(OptoRegPair, _second, short) \ - \ - c2_nonstatic_field(JVMState, _caller, JVMState*) \ - c2_nonstatic_field(JVMState, _depth, uint) \ - c2_nonstatic_field(JVMState, _locoff, uint) \ - c2_nonstatic_field(JVMState, _stkoff, uint) \ - c2_nonstatic_field(JVMState, _monoff, uint) \ - c2_nonstatic_field(JVMState, _scloff, uint) \ - c2_nonstatic_field(JVMState, _endoff, uint) \ - c2_nonstatic_field(JVMState, _sp, uint) \ - c2_nonstatic_field(JVMState, _bci, int) \ - c2_nonstatic_field(JVMState, _method, ciMethod*) \ - c2_nonstatic_field(JVMState, _map, SafePointNode*) \ - \ - c2_nonstatic_field(SafePointNode, _jvms, JVMState* const) \ - \ - c2_nonstatic_field(MachSafePointNode, _jvms, JVMState*) \ - c2_nonstatic_field(MachSafePointNode, _jvmadj, uint) \ - \ - c2_nonstatic_field(MachIfNode, _prob, jfloat) \ - c2_nonstatic_field(MachIfNode, _fcnt, jfloat) \ - \ - c2_nonstatic_field(MachJumpNode, _probs, jfloat*) \ - \ - c2_nonstatic_field(CallNode, _entry_point, address) \ - \ - c2_nonstatic_field(CallJavaNode, _method, ciMethod*) \ - \ - c2_nonstatic_field(CallRuntimeNode, _name, const char*) \ - \ - c2_nonstatic_field(CallStaticJavaNode, _name, const char*) \ - \ - c2_nonstatic_field(MachCallJavaNode, _method, ciMethod*) \ - \ - c2_nonstatic_field(MachCallStaticJavaNode, _name, const char*) \ - \ - c2_nonstatic_field(MachCallRuntimeNode, _name, const char*) \ - \ - c2_nonstatic_field(PhaseCFG, _number_of_blocks, uint) \ - c2_nonstatic_field(PhaseCFG, _blocks, Block_List) \ - c2_nonstatic_field(PhaseCFG, _node_to_block_mapping, Block_Array) \ - c2_nonstatic_field(PhaseCFG, _root_block, Block*) \ - \ - c2_nonstatic_field(PhaseRegAlloc, _node_regs, OptoRegPair*) \ - c2_nonstatic_field(PhaseRegAlloc, _node_regs_max_index, uint) \ - c2_nonstatic_field(PhaseRegAlloc, _framesize, uint) \ - c2_nonstatic_field(PhaseRegAlloc, _max_reg, OptoReg::Name) \ - \ - c2_nonstatic_field(PhaseChaitin, _trip_cnt, int) \ - c2_nonstatic_field(PhaseChaitin, _alternate, int) \ - c2_nonstatic_field(PhaseChaitin, _lo_degree, uint) \ - c2_nonstatic_field(PhaseChaitin, _lo_stk_degree, uint) \ - c2_nonstatic_field(PhaseChaitin, _hi_degree, uint) \ - c2_nonstatic_field(PhaseChaitin, _simplified, uint) \ - \ - c2_nonstatic_field(Block, _nodes, Node_List) \ - c2_nonstatic_field(Block, _succs, Block_Array) \ - c2_nonstatic_field(Block, _num_succs, uint) \ - c2_nonstatic_field(Block, _pre_order, uint) \ - c2_nonstatic_field(Block, _dom_depth, uint) \ - c2_nonstatic_field(Block, _idom, Block*) \ - c2_nonstatic_field(Block, _freq, jdouble) \ - \ - c2_nonstatic_field(CFGElement, _freq, jdouble) \ - \ - c2_nonstatic_field(Block_List, _cnt, uint) \ - \ - c2_nonstatic_field(Block_Array, _size, uint) \ - c2_nonstatic_field(Block_Array, _blocks, Block**) \ - c2_nonstatic_field(Block_Array, _arena, Arena*) \ - \ - c2_nonstatic_field(Node_List, _cnt, uint) \ - \ - c2_nonstatic_field(Node_Array, _max, uint) \ - c2_nonstatic_field(Node_Array, _nodes, Node**) \ - c2_nonstatic_field(Node_Array, _a, Arena*) \ - \ - \ - /*********************/ \ /* -XX flags */ \ /*********************/ \ \ @@ -1065,10 +835,7 @@ declare_toplevel_type, \ declare_oop_type, \ declare_integer_type, \ - declare_unsigned_integer_type, \ - declare_c1_toplevel_type, \ - declare_c2_type, \ - declare_c2_toplevel_type) \ + declare_unsigned_integer_type) \ \ /*************************************************************/ \ /* Java primitive types -- required by the SA implementation */ \ @@ -1234,17 +1001,14 @@ declare_type(PerfData, CHeapObj<mtInternal>) \ \ /********************/ \ - /* SystemDictionary */ \ + /* VM Classes */ \ /********************/ \ \ - declare_toplevel_type(SystemDictionary) \ declare_toplevel_type(vmClasses) \ declare_toplevel_type(vmSymbols) \ \ declare_toplevel_type(GrowableArrayBase) \ declare_toplevel_type(GrowableArray<int>) \ - declare_toplevel_type(Arena) \ - declare_type(ResourceArea, Arena) \ \ /***********************************************************/ \ /* Thread hierarchy (needed for run-time type information) */ \ @@ -1315,8 +1079,6 @@ /* CodeBlob hierarchy (needed for run-time type information) */ \ /*************************************************************/ \ \ - declare_toplevel_type(SharedRuntime) \ - \ declare_toplevel_type(CodeBlob) \ declare_type(RuntimeBlob, CodeBlob) \ declare_type(BufferBlob, RuntimeBlob) \ @@ -1329,8 +1091,8 @@ declare_type(UpcallStub, RuntimeBlob) \ declare_type(SafepointBlob, SingletonBlob) \ declare_type(DeoptimizationBlob, SingletonBlob) \ - declare_c2_type(ExceptionBlob, SingletonBlob) \ - declare_c2_type(UncommonTrapBlob, RuntimeBlob) \ + COMPILER2_PRESENT(declare_type(ExceptionBlob, SingletonBlob)) \ + COMPILER2_PRESENT(declare_type(UncommonTrapBlob, RuntimeBlob)) \ \ /***************************************/ \ /* PcDesc and other compiled code info */ \ @@ -1378,12 +1140,6 @@ \ declare_toplevel_type(OopStorage) \ \ - /**********************/ \ - /* Runtime1 (C1 only) */ \ - /**********************/ \ - \ - declare_c1_toplevel_type(Runtime1) \ - \ /************/ \ /* Monitors */ \ /************/ \ @@ -1394,467 +1150,6 @@ declare_toplevel_type(BasicLock) \ declare_toplevel_type(BasicObjectLock) \ \ - /*********************/ \ - /* Matcher (C2 only) */ \ - /*********************/ \ - \ - declare_c2_toplevel_type(Matcher) \ - declare_c2_toplevel_type(Compile) \ - declare_c2_toplevel_type(Options) \ - declare_c2_toplevel_type(InlineTree) \ - declare_c2_toplevel_type(OptoRegPair) \ - declare_c2_toplevel_type(JVMState) \ - declare_c2_toplevel_type(Phase) \ - declare_c2_type(PhaseCFG, Phase) \ - declare_c2_type(PhaseRegAlloc, Phase) \ - declare_c2_type(PhaseChaitin, PhaseRegAlloc) \ - declare_c2_toplevel_type(CFGElement) \ - declare_c2_type(Block, CFGElement) \ - declare_c2_toplevel_type(Block_Array) \ - declare_c2_type(Block_List, Block_Array) \ - declare_c2_toplevel_type(Node_Array) \ - declare_c2_type(Node_List, Node_Array) \ - declare_c2_type(Unique_Node_List, Node_List) \ - declare_c2_toplevel_type(Node) \ - declare_c2_type(AddNode, Node) \ - declare_c2_type(AddINode, AddNode) \ - declare_c2_type(AddLNode, AddNode) \ - declare_c2_type(AddFNode, AddNode) \ - declare_c2_type(AddDNode, AddNode) \ - declare_c2_type(AddPNode, Node) \ - declare_c2_type(OrINode, AddNode) \ - declare_c2_type(OrLNode, AddNode) \ - declare_c2_type(XorINode, AddNode) \ - declare_c2_type(XorLNode, AddNode) \ - declare_c2_type(MaxNode, AddNode) \ - declare_c2_type(MaxINode, MaxNode) \ - declare_c2_type(MinINode, MaxNode) \ - declare_c2_type(MaxLNode, MaxNode) \ - declare_c2_type(MinLNode, MaxNode) \ - declare_c2_type(MaxFNode, MaxNode) \ - declare_c2_type(MinFNode, MaxNode) \ - declare_c2_type(MaxDNode, MaxNode) \ - declare_c2_type(MinDNode, MaxNode) \ - declare_c2_type(StartNode, MultiNode) \ - declare_c2_type(StartOSRNode, StartNode) \ - declare_c2_type(ParmNode, ProjNode) \ - declare_c2_type(ReturnNode, Node) \ - declare_c2_type(RethrowNode, Node) \ - declare_c2_type(TailCallNode, ReturnNode) \ - declare_c2_type(TailJumpNode, ReturnNode) \ - declare_c2_type(ForwardExceptionNode, ReturnNode) \ - declare_c2_type(SafePointNode, MultiNode) \ - declare_c2_type(CallNode, SafePointNode) \ - declare_c2_type(CallJavaNode, CallNode) \ - declare_c2_type(CallStaticJavaNode, CallJavaNode) \ - declare_c2_type(CallDynamicJavaNode, CallJavaNode) \ - declare_c2_type(CallRuntimeNode, CallNode) \ - declare_c2_type(CallLeafNode, CallRuntimeNode) \ - declare_c2_type(CallLeafNoFPNode, CallLeafNode) \ - declare_c2_type(CallLeafVectorNode, CallLeafNode) \ - declare_c2_type(AllocateNode, CallNode) \ - declare_c2_type(AllocateArrayNode, AllocateNode) \ - declare_c2_type(LockNode, AbstractLockNode) \ - declare_c2_type(UnlockNode, AbstractLockNode) \ - declare_c2_type(FastLockNode, CmpNode) \ - declare_c2_type(FastUnlockNode, CmpNode) \ - declare_c2_type(RegionNode, Node) \ - declare_c2_type(JProjNode, ProjNode) \ - declare_c2_type(PhiNode, TypeNode) \ - declare_c2_type(GotoNode, Node) \ - declare_c2_type(CProjNode, ProjNode) \ - declare_c2_type(MultiBranchNode, MultiNode) \ - declare_c2_type(IfNode, MultiBranchNode) \ - declare_c2_type(IfTrueNode, CProjNode) \ - declare_c2_type(IfFalseNode, CProjNode) \ - declare_c2_type(PCTableNode, MultiBranchNode) \ - declare_c2_type(JumpNode, PCTableNode) \ - declare_c2_type(JumpProjNode, JProjNode) \ - declare_c2_type(CatchNode, PCTableNode) \ - declare_c2_type(CatchProjNode, CProjNode) \ - declare_c2_type(CreateExNode, TypeNode) \ - declare_c2_type(ClearArrayNode, Node) \ - declare_c2_type(NeverBranchNode, MultiBranchNode) \ - declare_c2_type(ConNode, TypeNode) \ - declare_c2_type(ConINode, ConNode) \ - declare_c2_type(ConPNode, ConNode) \ - declare_c2_type(ConNNode, ConNode) \ - declare_c2_type(ConLNode, ConNode) \ - declare_c2_type(ConFNode, ConNode) \ - declare_c2_type(ConDNode, ConNode) \ - declare_c2_type(BinaryNode, Node) \ - declare_c2_type(CMoveNode, TypeNode) \ - declare_c2_type(CMoveDNode, CMoveNode) \ - declare_c2_type(CMoveFNode, CMoveNode) \ - declare_c2_type(CMoveINode, CMoveNode) \ - declare_c2_type(CMoveLNode, CMoveNode) \ - declare_c2_type(CMovePNode, CMoveNode) \ - declare_c2_type(CMoveNNode, CMoveNode) \ - declare_c2_type(EncodePNode, TypeNode) \ - declare_c2_type(DecodeNNode, TypeNode) \ - declare_c2_type(EncodePKlassNode, TypeNode) \ - declare_c2_type(DecodeNKlassNode, TypeNode) \ - declare_c2_type(ConstraintCastNode, TypeNode) \ - declare_c2_type(CastIINode, ConstraintCastNode) \ - declare_c2_type(CastPPNode, ConstraintCastNode) \ - declare_c2_type(CheckCastPPNode, TypeNode) \ - declare_c2_type(Conv2BNode, Node) \ - declare_c2_type(ConvertNode, TypeNode) \ - declare_c2_type(ConvD2FNode, Node) \ - declare_c2_type(ConvD2INode, Node) \ - declare_c2_type(ConvD2LNode, Node) \ - declare_c2_type(ConvF2DNode, Node) \ - declare_c2_type(ConvF2INode, Node) \ - declare_c2_type(ConvF2LNode, Node) \ - declare_c2_type(ConvI2DNode, Node) \ - declare_c2_type(ConvI2FNode, Node) \ - declare_c2_type(ConvI2LNode, TypeNode) \ - declare_c2_type(ConvL2DNode, Node) \ - declare_c2_type(ConvL2FNode, Node) \ - declare_c2_type(ConvL2INode, Node) \ - declare_c2_type(CastX2PNode, Node) \ - declare_c2_type(CastP2XNode, Node) \ - declare_c2_type(MemBarNode, MultiNode) \ - declare_c2_type(MemBarAcquireNode, MemBarNode) \ - declare_c2_type(MemBarReleaseNode, MemBarNode) \ - declare_c2_type(LoadFenceNode, MemBarNode) \ - declare_c2_type(StoreFenceNode, MemBarNode) \ - declare_c2_type(MemBarVolatileNode, MemBarNode) \ - declare_c2_type(MemBarCPUOrderNode, MemBarNode) \ - declare_c2_type(OnSpinWaitNode, MemBarNode) \ - declare_c2_type(BlackholeNode, MultiNode) \ - declare_c2_type(InitializeNode, MemBarNode) \ - declare_c2_type(ThreadLocalNode, Node) \ - declare_c2_type(Opaque1Node, Node) \ - declare_c2_type(PartialSubtypeCheckNode, Node) \ - declare_c2_type(MoveI2FNode, Node) \ - declare_c2_type(MoveL2DNode, Node) \ - declare_c2_type(MoveF2INode, Node) \ - declare_c2_type(MoveD2LNode, Node) \ - declare_c2_type(DivINode, Node) \ - declare_c2_type(DivLNode, Node) \ - declare_c2_type(DivFNode, Node) \ - declare_c2_type(DivDNode, Node) \ - declare_c2_type(UDivINode, Node) \ - declare_c2_type(UDivLNode, Node) \ - declare_c2_type(ModINode, Node) \ - declare_c2_type(ModLNode, Node) \ - declare_c2_type(ModFNode, Node) \ - declare_c2_type(ModDNode, Node) \ - declare_c2_type(UModINode, Node) \ - declare_c2_type(UModLNode, Node) \ - declare_c2_type(DivModNode, MultiNode) \ - declare_c2_type(DivModINode, DivModNode) \ - declare_c2_type(DivModLNode, DivModNode) \ - declare_c2_type(UDivModINode, DivModNode) \ - declare_c2_type(UDivModLNode, DivModNode) \ - declare_c2_type(BoxLockNode, Node) \ - declare_c2_type(LoopNode, RegionNode) \ - declare_c2_type(CountedLoopNode, LoopNode) \ - declare_c2_type(CountedLoopEndNode, IfNode) \ - declare_c2_type(MachNode, Node) \ - declare_c2_type(MachIdealNode, MachNode) \ - declare_c2_type(MachTypeNode, MachNode) \ - declare_c2_type(MachBreakpointNode, MachIdealNode) \ - declare_c2_type(MachUEPNode, MachIdealNode) \ - declare_c2_type(MachVEPNode, MachIdealNode) \ - declare_c2_type(MachPrologNode, MachIdealNode) \ - declare_c2_type(MachEpilogNode, MachIdealNode) \ - declare_c2_type(MachNopNode, MachIdealNode) \ - declare_c2_type(MachSpillCopyNode, MachIdealNode) \ - declare_c2_type(MachNullCheckNode, MachIdealNode) \ - declare_c2_type(MachProjNode, ProjNode) \ - declare_c2_type(MachIfNode, MachNode) \ - declare_c2_type(MachJumpNode, MachNode) \ - declare_c2_type(MachFastLockNode, MachNode) \ - declare_c2_type(MachReturnNode, MachNode) \ - declare_c2_type(MachSafePointNode, MachReturnNode) \ - declare_c2_type(MachCallNode, MachSafePointNode) \ - declare_c2_type(MachCallJavaNode, MachCallNode) \ - declare_c2_type(MachCallStaticJavaNode, MachCallJavaNode) \ - declare_c2_type(MachCallDynamicJavaNode, MachCallJavaNode) \ - declare_c2_type(MachCallRuntimeNode, MachCallNode) \ - declare_c2_type(MachHaltNode, MachReturnNode) \ - declare_c2_type(MachTempNode, MachNode) \ - declare_c2_type(MemNode, Node) \ - declare_c2_type(MergeMemNode, Node) \ - declare_c2_type(LoadNode, MemNode) \ - declare_c2_type(LoadBNode, LoadNode) \ - declare_c2_type(LoadUSNode, LoadNode) \ - declare_c2_type(LoadINode, LoadNode) \ - declare_c2_type(LoadRangeNode, LoadINode) \ - declare_c2_type(LoadLNode, LoadNode) \ - declare_c2_type(LoadL_unalignedNode, LoadLNode) \ - declare_c2_type(LoadFNode, LoadNode) \ - declare_c2_type(LoadDNode, LoadNode) \ - declare_c2_type(LoadD_unalignedNode, LoadDNode) \ - declare_c2_type(LoadPNode, LoadNode) \ - declare_c2_type(LoadNNode, LoadNode) \ - declare_c2_type(LoadKlassNode, LoadPNode) \ - declare_c2_type(LoadNKlassNode, LoadNNode) \ - declare_c2_type(LoadSNode, LoadNode) \ - declare_c2_type(StoreNode, MemNode) \ - declare_c2_type(StoreBNode, StoreNode) \ - declare_c2_type(StoreCNode, StoreNode) \ - declare_c2_type(StoreINode, StoreNode) \ - declare_c2_type(StoreLNode, StoreNode) \ - declare_c2_type(StoreFNode, StoreNode) \ - declare_c2_type(StoreDNode, StoreNode) \ - declare_c2_type(StorePNode, StoreNode) \ - declare_c2_type(StoreNNode, StoreNode) \ - declare_c2_type(StoreNKlassNode, StoreNode) \ - declare_c2_type(SCMemProjNode, ProjNode) \ - declare_c2_type(LoadStoreNode, Node) \ - declare_c2_type(CompareAndSwapNode, LoadStoreConditionalNode) \ - declare_c2_type(CompareAndSwapBNode, CompareAndSwapNode) \ - declare_c2_type(CompareAndSwapSNode, CompareAndSwapNode) \ - declare_c2_type(CompareAndSwapLNode, CompareAndSwapNode) \ - declare_c2_type(CompareAndSwapINode, CompareAndSwapNode) \ - declare_c2_type(CompareAndSwapPNode, CompareAndSwapNode) \ - declare_c2_type(CompareAndSwapNNode, CompareAndSwapNode) \ - declare_c2_type(WeakCompareAndSwapBNode, CompareAndSwapNode) \ - declare_c2_type(WeakCompareAndSwapSNode, CompareAndSwapNode) \ - declare_c2_type(WeakCompareAndSwapLNode, CompareAndSwapNode) \ - declare_c2_type(WeakCompareAndSwapINode, CompareAndSwapNode) \ - declare_c2_type(WeakCompareAndSwapPNode, CompareAndSwapNode) \ - declare_c2_type(WeakCompareAndSwapNNode, CompareAndSwapNode) \ - declare_c2_type(CompareAndExchangeNode, LoadStoreNode) \ - declare_c2_type(CompareAndExchangeBNode, CompareAndExchangeNode) \ - declare_c2_type(CompareAndExchangeSNode, CompareAndExchangeNode) \ - declare_c2_type(CompareAndExchangeLNode, CompareAndExchangeNode) \ - declare_c2_type(CompareAndExchangeINode, CompareAndExchangeNode) \ - declare_c2_type(CompareAndExchangePNode, CompareAndExchangeNode) \ - declare_c2_type(CompareAndExchangeNNode, CompareAndExchangeNode) \ - declare_c2_type(MulNode, Node) \ - declare_c2_type(MulINode, MulNode) \ - declare_c2_type(MulLNode, MulNode) \ - declare_c2_type(MulFNode, MulNode) \ - declare_c2_type(MulDNode, MulNode) \ - declare_c2_type(MulHiLNode, Node) \ - declare_c2_type(UMulHiLNode, Node) \ - declare_c2_type(AndINode, MulINode) \ - declare_c2_type(AndLNode, MulLNode) \ - declare_c2_type(LShiftINode, Node) \ - declare_c2_type(LShiftLNode, Node) \ - declare_c2_type(RShiftINode, Node) \ - declare_c2_type(RShiftLNode, Node) \ - declare_c2_type(URShiftINode, Node) \ - declare_c2_type(URShiftLNode, Node) \ - declare_c2_type(MultiNode, Node) \ - declare_c2_type(ProjNode, Node) \ - declare_c2_type(TypeNode, Node) \ - declare_c2_type(RootNode, LoopNode) \ - declare_c2_type(HaltNode, Node) \ - declare_c2_type(SubNode, Node) \ - declare_c2_type(SubINode, SubNode) \ - declare_c2_type(SubLNode, SubNode) \ - declare_c2_type(SubFPNode, SubNode) \ - declare_c2_type(SubFNode, SubFPNode) \ - declare_c2_type(SubDNode, SubFPNode) \ - declare_c2_type(CmpNode, SubNode) \ - declare_c2_type(CmpINode, CmpNode) \ - declare_c2_type(CmpUNode, CmpNode) \ - declare_c2_type(CmpU3Node, CmpUNode) \ - declare_c2_type(CmpPNode, CmpNode) \ - declare_c2_type(CmpNNode, CmpNode) \ - declare_c2_type(CmpLNode, CmpNode) \ - declare_c2_type(CmpULNode, CmpNode) \ - declare_c2_type(CmpL3Node, CmpLNode) \ - declare_c2_type(CmpUL3Node, CmpULNode) \ - declare_c2_type(CmpFNode, CmpNode) \ - declare_c2_type(CmpF3Node, CmpFNode) \ - declare_c2_type(CmpDNode, CmpNode) \ - declare_c2_type(CmpD3Node, CmpDNode) \ - declare_c2_type(BoolNode, Node) \ - declare_c2_type(AbsNode, Node) \ - declare_c2_type(AbsINode, AbsNode) \ - declare_c2_type(AbsFNode, AbsNode) \ - declare_c2_type(AbsDNode, AbsNode) \ - declare_c2_type(CmpLTMaskNode, Node) \ - declare_c2_type(NegNode, Node) \ - declare_c2_type(NegINode, NegNode) \ - declare_c2_type(NegLNode, NegNode) \ - declare_c2_type(NegFNode, NegNode) \ - declare_c2_type(NegDNode, NegNode) \ - declare_c2_type(AtanDNode, Node) \ - declare_c2_type(SqrtFNode, Node) \ - declare_c2_type(SqrtDNode, Node) \ - declare_c2_type(ReverseBytesINode, Node) \ - declare_c2_type(ReverseBytesLNode, Node) \ - declare_c2_type(ReductionNode, Node) \ - declare_c2_type(VectorNode, Node) \ - declare_c2_type(AbsVFNode, VectorNode) \ - declare_c2_type(AbsVDNode, VectorNode) \ - declare_c2_type(AbsVBNode, VectorNode) \ - declare_c2_type(AbsVSNode, VectorNode) \ - declare_c2_type(AbsVINode, VectorNode) \ - declare_c2_type(AbsVLNode, VectorNode) \ - declare_c2_type(AddVBNode, VectorNode) \ - declare_c2_type(AddVSNode, VectorNode) \ - declare_c2_type(AddVINode, VectorNode) \ - declare_c2_type(AddReductionVINode, ReductionNode) \ - declare_c2_type(AddVLNode, VectorNode) \ - declare_c2_type(AddReductionVLNode, ReductionNode) \ - declare_c2_type(AddVFNode, VectorNode) \ - declare_c2_type(AddReductionVFNode, ReductionNode) \ - declare_c2_type(AddVDNode, VectorNode) \ - declare_c2_type(AddReductionVDNode, ReductionNode) \ - declare_c2_type(SubVBNode, VectorNode) \ - declare_c2_type(SubVSNode, VectorNode) \ - declare_c2_type(SubVINode, VectorNode) \ - declare_c2_type(SubVLNode, VectorNode) \ - declare_c2_type(SubVFNode, VectorNode) \ - declare_c2_type(SubVDNode, VectorNode) \ - declare_c2_type(MulVBNode, VectorNode) \ - declare_c2_type(MulVSNode, VectorNode) \ - declare_c2_type(MulVLNode, VectorNode) \ - declare_c2_type(MulReductionVLNode, ReductionNode) \ - declare_c2_type(MulVINode, VectorNode) \ - declare_c2_type(MulReductionVINode, ReductionNode) \ - declare_c2_type(MulVFNode, VectorNode) \ - declare_c2_type(MulReductionVFNode, ReductionNode) \ - declare_c2_type(MulVDNode, VectorNode) \ - declare_c2_type(NegVNode, VectorNode) \ - declare_c2_type(NegVINode, NegVNode) \ - declare_c2_type(NegVLNode, NegVNode) \ - declare_c2_type(NegVFNode, NegVNode) \ - declare_c2_type(NegVDNode, NegVNode) \ - declare_c2_type(FmaVDNode, VectorNode) \ - declare_c2_type(FmaVFNode, VectorNode) \ - declare_c2_type(CompressVNode, VectorNode) \ - declare_c2_type(CompressMNode, VectorNode) \ - declare_c2_type(ExpandVNode, VectorNode) \ - declare_c2_type(CompressBitsVNode, VectorNode) \ - declare_c2_type(ExpandBitsVNode, VectorNode) \ - declare_c2_type(MulReductionVDNode, ReductionNode) \ - declare_c2_type(DivVFNode, VectorNode) \ - declare_c2_type(DivVDNode, VectorNode) \ - declare_c2_type(PopCountVINode, VectorNode) \ - declare_c2_type(PopCountVLNode, VectorNode) \ - declare_c2_type(LShiftVBNode, VectorNode) \ - declare_c2_type(LShiftVSNode, VectorNode) \ - declare_c2_type(LShiftVINode, VectorNode) \ - declare_c2_type(LShiftVLNode, VectorNode) \ - declare_c2_type(RShiftVBNode, VectorNode) \ - declare_c2_type(RShiftVSNode, VectorNode) \ - declare_c2_type(RShiftVINode, VectorNode) \ - declare_c2_type(RShiftVLNode, VectorNode) \ - declare_c2_type(URShiftVBNode, VectorNode) \ - declare_c2_type(URShiftVSNode, VectorNode) \ - declare_c2_type(URShiftVINode, VectorNode) \ - declare_c2_type(URShiftVLNode, VectorNode) \ - declare_c2_type(MinReductionVNode, ReductionNode) \ - declare_c2_type(MaxReductionVNode, ReductionNode) \ - declare_c2_type(AndVNode, VectorNode) \ - declare_c2_type(AndReductionVNode, ReductionNode) \ - declare_c2_type(OrVNode, VectorNode) \ - declare_c2_type(OrReductionVNode, ReductionNode) \ - declare_c2_type(XorVNode, VectorNode) \ - declare_c2_type(XorReductionVNode, ReductionNode) \ - declare_c2_type(MaxVNode, VectorNode) \ - declare_c2_type(MinVNode, VectorNode) \ - declare_c2_type(LoadVectorNode, LoadNode) \ - declare_c2_type(StoreVectorNode, StoreNode) \ - declare_c2_type(ReplicateNode, VectorNode) \ - declare_c2_type(PopulateIndexNode, VectorNode) \ - declare_c2_type(PackNode, VectorNode) \ - declare_c2_type(PackBNode, PackNode) \ - declare_c2_type(PackSNode, PackNode) \ - declare_c2_type(PackINode, PackNode) \ - declare_c2_type(PackLNode, PackNode) \ - declare_c2_type(PackFNode, PackNode) \ - declare_c2_type(PackDNode, PackNode) \ - declare_c2_type(Pack2LNode, PackNode) \ - declare_c2_type(Pack2DNode, PackNode) \ - declare_c2_type(ExtractNode, Node) \ - declare_c2_type(ExtractBNode, ExtractNode) \ - declare_c2_type(ExtractUBNode, ExtractNode) \ - declare_c2_type(ExtractCNode, ExtractNode) \ - declare_c2_type(ExtractSNode, ExtractNode) \ - declare_c2_type(ExtractINode, ExtractNode) \ - declare_c2_type(ExtractLNode, ExtractNode) \ - declare_c2_type(ExtractFNode, ExtractNode) \ - declare_c2_type(ExtractDNode, ExtractNode) \ - declare_c2_type(OverflowNode, CmpNode) \ - declare_c2_type(OverflowINode, OverflowNode) \ - declare_c2_type(OverflowAddINode, OverflowINode) \ - declare_c2_type(OverflowSubINode, OverflowINode) \ - declare_c2_type(OverflowMulINode, OverflowINode) \ - declare_c2_type(OverflowLNode, OverflowNode) \ - declare_c2_type(OverflowAddLNode, OverflowLNode) \ - declare_c2_type(OverflowSubLNode, OverflowLNode) \ - declare_c2_type(OverflowMulLNode, OverflowLNode) \ - declare_c2_type(FmaDNode, Node) \ - declare_c2_type(FmaFNode, Node) \ - declare_c2_type(CopySignDNode, Node) \ - declare_c2_type(CopySignFNode, Node) \ - declare_c2_type(SignumDNode, Node) \ - declare_c2_type(SignumFNode, Node) \ - declare_c2_type(IsInfiniteFNode, Node) \ - declare_c2_type(IsInfiniteDNode, Node) \ - declare_c2_type(IsFiniteFNode, Node) \ - declare_c2_type(IsFiniteDNode, Node) \ - declare_c2_type(LoadVectorGatherNode, LoadVectorNode) \ - declare_c2_type(StoreVectorScatterNode, StoreVectorNode) \ - declare_c2_type(VectorLoadMaskNode, VectorNode) \ - declare_c2_type(VectorLoadShuffleNode, VectorNode) \ - declare_c2_type(VectorStoreMaskNode, VectorNode) \ - declare_c2_type(VectorBlendNode, VectorNode) \ - declare_c2_type(VectorRearrangeNode, VectorNode) \ - declare_c2_type(VectorMaskWrapperNode, VectorNode) \ - declare_c2_type(VectorMaskCmpNode, VectorNode) \ - declare_c2_type(VectorCastB2XNode, VectorNode) \ - declare_c2_type(VectorCastS2XNode, VectorNode) \ - declare_c2_type(VectorCastI2XNode, VectorNode) \ - declare_c2_type(VectorCastL2XNode, VectorNode) \ - declare_c2_type(VectorCastF2XNode, VectorNode) \ - declare_c2_type(VectorCastD2XNode, VectorNode) \ - declare_c2_type(VectorUCastB2XNode, VectorNode) \ - declare_c2_type(VectorUCastS2XNode, VectorNode) \ - declare_c2_type(VectorUCastI2XNode, VectorNode) \ - declare_c2_type(VectorInsertNode, VectorNode) \ - declare_c2_type(VectorUnboxNode, VectorNode) \ - declare_c2_type(VectorReinterpretNode, VectorNode) \ - declare_c2_type(VectorMaskCastNode, VectorNode) \ - declare_c2_type(CountLeadingZerosVNode, VectorNode) \ - declare_c2_type(CountTrailingZerosVNode, VectorNode) \ - declare_c2_type(ReverseBytesVNode, VectorNode) \ - declare_c2_type(ReverseVNode, VectorNode) \ - declare_c2_type(MaskAllNode, VectorNode) \ - declare_c2_type(AndVMaskNode, VectorNode) \ - declare_c2_type(OrVMaskNode, VectorNode) \ - declare_c2_type(XorVMaskNode, VectorNode) \ - declare_c2_type(VectorBoxNode, Node) \ - declare_c2_type(VectorBoxAllocateNode, CallStaticJavaNode) \ - declare_c2_type(VectorTestNode, CmpNode) \ - \ - /*********************/ \ - /* Adapter Blob Entries */ \ - /*********************/ \ - declare_toplevel_type(AdapterHandlerEntry) \ - declare_toplevel_type(AdapterHandlerEntry*) \ - \ - /*********************/ \ - /* CI */ \ - /*********************/ \ - declare_toplevel_type(ciEnv) \ - declare_toplevel_type(ciObjectFactory) \ - declare_toplevel_type(ciConstant) \ - declare_toplevel_type(ciField) \ - declare_toplevel_type(ciSymbol) \ - declare_toplevel_type(ciBaseObject) \ - declare_type(ciObject, ciBaseObject) \ - declare_type(ciInstance, ciObject) \ - declare_type(ciMetadata, ciBaseObject) \ - declare_type(ciMethod, ciMetadata) \ - declare_type(ciMethodData, ciMetadata) \ - declare_type(ciType, ciMetadata) \ - declare_type(ciKlass, ciType) \ - declare_type(ciInstanceKlass, ciKlass) \ - declare_type(ciArrayKlass, ciKlass) \ - declare_type(ciTypeArrayKlass, ciArrayKlass) \ - declare_type(ciObjArrayKlass, ciArrayKlass) \ - \ /********************/ \ /* -XX flags */ \ /********************/ \ @@ -1899,7 +1194,6 @@ declare_integer_type(Location::Type) \ declare_integer_type(Location::Where) \ declare_integer_type(JVMFlag::Flags) \ - COMPILER2_PRESENT(declare_integer_type(OptoReg::Name)) \ \ declare_toplevel_type(CHeapObj<mtInternal>) \ declare_type(Array<int>, MetaspaceObj) \ @@ -1951,7 +1245,6 @@ declare_toplevel_type(Mutex) \ declare_toplevel_type(Mutex*) \ declare_toplevel_type(nmethod*) \ - COMPILER2_PRESENT(declare_unsigned_integer_type(node_idx_t)) \ declare_toplevel_type(ObjectMonitor*) \ declare_toplevel_type(oop*) \ declare_toplevel_type(OopMapCache*) \ @@ -1991,10 +1284,7 @@ #define VM_INT_CONSTANTS(declare_constant, \ declare_constant_with_value, \ - declare_preprocessor_constant, \ - declare_c1_constant, \ - declare_c2_constant, \ - declare_c2_preprocessor_constant) \ + declare_preprocessor_constant) \ \ /****************/ \ /* GC constants */ \ @@ -2008,6 +1298,7 @@ /******************/ \ \ declare_preprocessor_constant("ASSERT", DEBUG_ONLY(1) NOT_DEBUG(0)) \ + declare_preprocessor_constant("COMPILER2", COMPILER2_PRESENT(1) NOT_COMPILER2(0)) \ \ /****************/ \ /* Object sizes */ \ @@ -2274,6 +1565,7 @@ declare_constant(Deoptimization::Reason_age) \ declare_constant(Deoptimization::Reason_predicate) \ declare_constant(Deoptimization::Reason_loop_limit_check) \ + declare_constant(Deoptimization::Reason_auto_vectorization_check) \ declare_constant(Deoptimization::Reason_speculate_class_check) \ declare_constant(Deoptimization::Reason_speculate_null_check) \ declare_constant(Deoptimization::Reason_speculate_null_assert) \ @@ -2356,12 +1648,6 @@ declare_constant(LM_LEGACY) \ declare_constant(LM_LIGHTWEIGHT) \ \ - /*********************/ \ - /* Matcher (C2 only) */ \ - /*********************/ \ - \ - declare_c2_preprocessor_constant("Matcher::interpreter_frame_pointer_reg", Matcher::interpreter_frame_pointer_reg()) \ - \ /*********************************************/ \ /* MethodCompilation (globalDefinitions.hpp) */ \ /*********************************************/ \ @@ -2461,8 +1747,8 @@ \ declare_constant(ConcreteRegisterImpl::number_of_registers) \ declare_preprocessor_constant("REG_COUNT", REG_COUNT) \ - declare_c2_preprocessor_constant("SAVED_ON_ENTRY_REG_COUNT", SAVED_ON_ENTRY_REG_COUNT) \ - declare_c2_preprocessor_constant("C_SAVED_ON_ENTRY_REG_COUNT", C_SAVED_ON_ENTRY_REG_COUNT) \ + COMPILER2_PRESENT(declare_preprocessor_constant("SAVED_ON_ENTRY_REG_COUNT", SAVED_ON_ENTRY_REG_COUNT)) \ + COMPILER2_PRESENT(declare_preprocessor_constant("C_SAVED_ON_ENTRY_REG_COUNT", C_SAVED_ON_ENTRY_REG_COUNT)) \ \ /************/ \ /* PerfData */ \ @@ -2513,7 +1799,7 @@ // enums, etc., while "declare_preprocessor_constant" must be used for // all #defined constants. -#define VM_LONG_CONSTANTS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ +#define VM_LONG_CONSTANTS(declare_constant, declare_preprocessor_constant) \ \ /****************/ \ /* GC constants */ \ @@ -2579,108 +1865,6 @@ # define ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT(a, b, c) #endif /* PRODUCT */ -// Generate and check a nonstatic field in C1 builds -#ifdef COMPILER1 -# define GENERATE_C1_NONSTATIC_VM_STRUCT_ENTRY(a, b, c) GENERATE_NONSTATIC_VM_STRUCT_ENTRY(a, b, c) -# define CHECK_C1_NONSTATIC_VM_STRUCT_ENTRY(a, b, c) CHECK_NONSTATIC_VM_STRUCT_ENTRY(a, b, c) -# define ENSURE_C1_FIELD_TYPE_PRESENT(a, b, c) ENSURE_FIELD_TYPE_PRESENT(a, b, c) -#else -# define GENERATE_C1_NONSTATIC_VM_STRUCT_ENTRY(a, b, c) -# define CHECK_C1_NONSTATIC_VM_STRUCT_ENTRY(a, b, c) -# define ENSURE_C1_FIELD_TYPE_PRESENT(a, b, c) -#endif /* COMPILER1 */ -// Generate and check a nonstatic field in C2 builds -#ifdef COMPILER2 -# define GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY(a, b, c) GENERATE_NONSTATIC_VM_STRUCT_ENTRY(a, b, c) -# define CHECK_C2_NONSTATIC_VM_STRUCT_ENTRY(a, b, c) CHECK_NONSTATIC_VM_STRUCT_ENTRY(a, b, c) -# define ENSURE_C2_FIELD_TYPE_PRESENT(a, b, c) ENSURE_FIELD_TYPE_PRESENT(a, b, c) -#else -# define GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY(a, b, c) -# define CHECK_C2_NONSTATIC_VM_STRUCT_ENTRY(a, b, c) -# define ENSURE_C2_FIELD_TYPE_PRESENT(a, b, c) -#endif /* COMPILER2 */ - -// Generate but do not check a static field in C1 builds -#ifdef COMPILER1 -# define GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY(a, b, c) GENERATE_UNCHECKED_STATIC_VM_STRUCT_ENTRY(a, b, c) -#else -# define GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY(a, b, c) -#endif /* COMPILER1 */ - -// Generate but do not check a static field in C2 builds -#ifdef COMPILER2 -# define GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY(a, b, c) GENERATE_UNCHECKED_STATIC_VM_STRUCT_ENTRY(a, b, c) -#else -# define GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY(a, b, c) -#endif /* COMPILER2 */ - -//-------------------------------------------------------------------------------- -// VMTypeEntry build-specific macros -// - -#ifdef COMPILER1 -# define GENERATE_C1_TOPLEVEL_VM_TYPE_ENTRY(a) GENERATE_TOPLEVEL_VM_TYPE_ENTRY(a) -# define CHECK_C1_TOPLEVEL_VM_TYPE_ENTRY(a) -#else -# define GENERATE_C1_TOPLEVEL_VM_TYPE_ENTRY(a) -# define CHECK_C1_TOPLEVEL_VM_TYPE_ENTRY(a) -#endif /* COMPILER1 */ - -#ifdef COMPILER2 -# define GENERATE_C2_VM_TYPE_ENTRY(a, b) GENERATE_VM_TYPE_ENTRY(a, b) -# define CHECK_C2_VM_TYPE_ENTRY(a, b) CHECK_VM_TYPE_ENTRY(a, b) -# define GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY(a) GENERATE_TOPLEVEL_VM_TYPE_ENTRY(a) -# define CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY(a) -#else -# define GENERATE_C2_VM_TYPE_ENTRY(a, b) -# define CHECK_C2_VM_TYPE_ENTRY(a, b) -# define GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY(a) -# define CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY(a) -#endif /* COMPILER2 */ - - -//-------------------------------------------------------------------------------- -// VMIntConstantEntry build-specific macros -// - -// Generate an int constant for a C1 build -#ifdef COMPILER1 -# define GENERATE_C1_VM_INT_CONSTANT_ENTRY(name) GENERATE_VM_INT_CONSTANT_ENTRY(name) -#else -# define GENERATE_C1_VM_INT_CONSTANT_ENTRY(name) -#endif /* COMPILER1 */ - -// Generate an int constant for a C2 build -#ifdef COMPILER2 -# define GENERATE_C2_VM_INT_CONSTANT_ENTRY(name) GENERATE_VM_INT_CONSTANT_ENTRY(name) -# define GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY(name, value) GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY(name, value) -#else -# define GENERATE_C2_VM_INT_CONSTANT_ENTRY(name) -# define GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY(name, value) -#endif /* COMPILER1 */ - - -//-------------------------------------------------------------------------------- -// VMLongConstantEntry build-specific macros -// - -// Generate a long constant for a C1 build -#ifdef COMPILER1 -# define GENERATE_C1_VM_LONG_CONSTANT_ENTRY(name) GENERATE_VM_LONG_CONSTANT_ENTRY(name) -#else -# define GENERATE_C1_VM_LONG_CONSTANT_ENTRY(name) -#endif /* COMPILER1 */ - -// Generate a long constant for a C2 build -#ifdef COMPILER2 -# define GENERATE_C2_VM_LONG_CONSTANT_ENTRY(name) GENERATE_VM_LONG_CONSTANT_ENTRY(name) -# define GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY(name, value) GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY(name, value) -#else -# define GENERATE_C2_VM_LONG_CONSTANT_ENTRY(name) -# define GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY(name, value) -#endif /* COMPILER1 */ - - // // Instantiation of VMStructEntries, VMTypeEntries and VMIntConstantEntries // @@ -2694,39 +1878,20 @@ VMStructEntry VMStructs::localHotSpotVMStructs[] = { GENERATE_VOLATILE_STATIC_VM_STRUCT_ENTRY, GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_C1_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, - GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY) + GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY) VM_STRUCTS_OS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY, GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, - GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY) + GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY) VM_STRUCTS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY, GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, - GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY) - - VM_STRUCTS_OS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_STATIC_VM_STRUCT_ENTRY, - GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, - GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY) + GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY) GENERATE_VM_STRUCT_LAST_ENTRY() }; @@ -2741,38 +1906,19 @@ VMTypeEntry VMStructs::localHotSpotVMTypes[] = { GENERATE_TOPLEVEL_VM_TYPE_ENTRY, GENERATE_OOP_VM_TYPE_ENTRY, GENERATE_INTEGER_VM_TYPE_ENTRY, - GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY, - GENERATE_C1_TOPLEVEL_VM_TYPE_ENTRY, - GENERATE_C2_VM_TYPE_ENTRY, - GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY) - + GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY) VM_TYPES_OS(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY, GENERATE_OOP_VM_TYPE_ENTRY, GENERATE_INTEGER_VM_TYPE_ENTRY, - GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY, - GENERATE_C1_TOPLEVEL_VM_TYPE_ENTRY, - GENERATE_C2_VM_TYPE_ENTRY, - GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY) + GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY) VM_TYPES_CPU(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY, GENERATE_OOP_VM_TYPE_ENTRY, GENERATE_INTEGER_VM_TYPE_ENTRY, - GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY, - GENERATE_C1_TOPLEVEL_VM_TYPE_ENTRY, - GENERATE_C2_VM_TYPE_ENTRY, - GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY) - - VM_TYPES_OS_CPU(GENERATE_VM_TYPE_ENTRY, - GENERATE_TOPLEVEL_VM_TYPE_ENTRY, - GENERATE_OOP_VM_TYPE_ENTRY, - GENERATE_INTEGER_VM_TYPE_ENTRY, - GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY, - GENERATE_C1_TOPLEVEL_VM_TYPE_ENTRY, - GENERATE_C2_VM_TYPE_ENTRY, - GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY) + GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY) GENERATE_VM_TYPE_LAST_ENTRY() }; @@ -2785,28 +1931,14 @@ VMIntConstantEntry VMStructs::localHotSpotVMIntConstants[] = { VM_INT_CONSTANTS(GENERATE_VM_INT_CONSTANT_ENTRY, GENERATE_VM_INT_CONSTANT_WITH_VALUE_ENTRY, - GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, - GENERATE_C1_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) + GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) VM_INT_CONSTANTS_OS(GENERATE_VM_INT_CONSTANT_ENTRY, - GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, - GENERATE_C1_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) + GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) VM_INT_CONSTANTS_CPU(GENERATE_VM_INT_CONSTANT_ENTRY, - GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, - GENERATE_C1_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) + GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) - VM_INT_CONSTANTS_OS_CPU(GENERATE_VM_INT_CONSTANT_ENTRY, - GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, - GENERATE_C1_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) #ifdef VM_INT_CPU_FEATURE_CONSTANTS VM_INT_CPU_FEATURE_CONSTANTS #endif @@ -2821,28 +1953,14 @@ size_t VMStructs::localHotSpotVMIntConstantsLength() { VMLongConstantEntry VMStructs::localHotSpotVMLongConstants[] = { VM_LONG_CONSTANTS(GENERATE_VM_LONG_CONSTANT_ENTRY, - GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, - GENERATE_C1_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) + GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) VM_LONG_CONSTANTS_OS(GENERATE_VM_LONG_CONSTANT_ENTRY, - GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, - GENERATE_C1_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) + GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) VM_LONG_CONSTANTS_CPU(GENERATE_VM_LONG_CONSTANT_ENTRY, - GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, - GENERATE_C1_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) + GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) - VM_LONG_CONSTANTS_OS_CPU(GENERATE_VM_LONG_CONSTANT_ENTRY, - GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, - GENERATE_C1_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) #ifdef VM_LONG_CPU_FEATURE_CONSTANTS VM_LONG_CPU_FEATURE_CONSTANTS #endif @@ -2896,58 +2014,26 @@ void VMStructs::init() { CHECK_VOLATILE_STATIC_VM_STRUCT_ENTRY, CHECK_NO_OP, CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_C1_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_C2_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_NO_OP, - CHECK_NO_OP); - + CHECK_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY) VM_STRUCTS_CPU(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY, CHECK_NO_OP, CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_C2_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_NO_OP, - CHECK_NO_OP); - - VM_STRUCTS_OS_CPU(CHECK_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_STATIC_VM_STRUCT_ENTRY, - CHECK_NO_OP, - CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_C2_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_NO_OP, - CHECK_NO_OP); + CHECK_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY) VM_TYPES(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, - CHECK_SINGLE_ARG_VM_TYPE_NO_OP, - CHECK_C1_TOPLEVEL_VM_TYPE_ENTRY, - CHECK_C2_VM_TYPE_ENTRY, - CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY); + CHECK_SINGLE_ARG_VM_TYPE_NO_OP) VM_TYPES_CPU(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, - CHECK_SINGLE_ARG_VM_TYPE_NO_OP, - CHECK_C1_TOPLEVEL_VM_TYPE_ENTRY, - CHECK_C2_VM_TYPE_ENTRY, - CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY); - - VM_TYPES_OS_CPU(CHECK_VM_TYPE_ENTRY, - CHECK_SINGLE_ARG_VM_TYPE_NO_OP, - CHECK_SINGLE_ARG_VM_TYPE_NO_OP, - CHECK_SINGLE_ARG_VM_TYPE_NO_OP, - CHECK_SINGLE_ARG_VM_TYPE_NO_OP, - CHECK_C1_TOPLEVEL_VM_TYPE_ENTRY, - CHECK_C2_VM_TYPE_ENTRY, - CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY); + CHECK_SINGLE_ARG_VM_TYPE_NO_OP) // // Split VM_STRUCTS() invocation into two parts to allow MS VC++ 6.0 @@ -2971,39 +2057,20 @@ void VMStructs::init() { CHECK_NO_OP, CHECK_NO_OP, CHECK_NO_OP, - CHECK_NO_OP, - CHECK_NO_OP, - CHECK_NO_OP, - CHECK_NO_OP, - CHECK_NO_OP); + CHECK_NO_OP) VM_STRUCTS(CHECK_NO_OP, ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT, CHECK_NO_OP, ENSURE_FIELD_TYPE_PRESENT, - ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, - ENSURE_C1_FIELD_TYPE_PRESENT, - ENSURE_C2_FIELD_TYPE_PRESENT, - CHECK_NO_OP, - CHECK_NO_OP); + ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT) VM_STRUCTS_CPU(ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT, CHECK_NO_OP, ENSURE_FIELD_TYPE_PRESENT, - ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, - ENSURE_C2_FIELD_TYPE_PRESENT, - CHECK_NO_OP, - CHECK_NO_OP); - VM_STRUCTS_OS_CPU(ENSURE_FIELD_TYPE_PRESENT, - ENSURE_FIELD_TYPE_PRESENT, - CHECK_NO_OP, - ENSURE_FIELD_TYPE_PRESENT, - ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, - ENSURE_C2_FIELD_TYPE_PRESENT, - CHECK_NO_OP, - CHECK_NO_OP); + ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT) #endif // !_WINDOWS } diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index 4b7cdddc618..6e20e515235 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -1170,16 +1170,17 @@ void VThreadPollersDCmd::execute(DCmdSource source, TRAPS) { CompilationMemoryStatisticDCmd::CompilationMemoryStatisticDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), - _human_readable("-H", "Human readable format", "BOOLEAN", false, "false"), - _minsize("-s", "Minimum memory size", "MEMORY SIZE", false, "0") { - _dcmdparser.add_dcmd_option(&_human_readable); + _verbose("verbose", "Print detailed information", "BOOLEAN", false, "false"), + _legend("legend", "Table mode: print legend", "BOOLEAN", false, "false"), + _minsize("minsize", "Minimum memory size", "MEMORY SIZE", false, "0") { + _dcmdparser.add_dcmd_option(&_verbose); _dcmdparser.add_dcmd_option(&_minsize); + _dcmdparser.add_dcmd_option(&_legend); } void CompilationMemoryStatisticDCmd::execute(DCmdSource source, TRAPS) { - const bool human_readable = _human_readable.value(); const size_t minsize = _minsize.has_value() ? _minsize.value()._size : 0; - CompilationMemoryStatistic::print_all_by_size(output(), human_readable, minsize); + CompilationMemoryStatistic::print_jcmd_report(output(), _verbose.value(), _legend.value(), minsize); } #if defined(LINUX) || defined(_WIN64) || defined(__APPLE__) diff --git a/src/hotspot/share/services/diagnosticCommand.hpp b/src/hotspot/share/services/diagnosticCommand.hpp index 0799da08791..5c199eecef9 100644 --- a/src/hotspot/share/services/diagnosticCommand.hpp +++ b/src/hotspot/share/services/diagnosticCommand.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, 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 @@ -825,10 +825,11 @@ class VThreadPollersDCmd : public DCmd { class CompilationMemoryStatisticDCmd: public DCmdWithParser { protected: - DCmdArgument<bool> _human_readable; + DCmdArgument<bool> _verbose; + DCmdArgument<bool> _legend; DCmdArgument<MemorySizeArgument> _minsize; public: - static int num_arguments() { return 2; } + static int num_arguments() { return 3; } CompilationMemoryStatisticDCmd(outputStream* output, bool heap); static const char* name() { return "Compiler.memory"; diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index 2d57df4ffe6..9413f1f72d7 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -625,6 +625,7 @@ void help() { tty->print_cr(" pns($sp, $fp, $pc) on Linux/AArch64 or"); tty->print_cr(" pns($sp, 0, $pc) on Linux/ppc64 or"); tty->print_cr(" pns($sp, $s8, $pc) on Linux/mips or"); + tty->print_cr(" pns($sp, $fp, $pc) on Linux/RISC-V"); tty->print_cr(" - in gdb do 'set overload-resolution off' before calling pns()"); tty->print_cr(" - in dbx do 'frame 1' before calling pns()"); tty->print_cr("class metadata."); diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index 9e06614bc7e..bbf1fcf9d6f 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -27,6 +27,7 @@ #include "cds/metaspaceShared.hpp" #include "code/codeCache.hpp" #include "compiler/compilationFailureInfo.hpp" +#include "compiler/compilationMemoryStatistic.hpp" #include "compiler/compileBroker.hpp" #include "compiler/disassembler.hpp" #include "gc/shared/gcConfig.hpp" @@ -1000,6 +1001,11 @@ void VMError::report(outputStream* st, bool _verbose) { STEP_IF("printing pending compilation failure", _verbose && _thread != nullptr && _thread->is_Compiler_thread()) CompilationFailureInfo::print_pending_compilation_failure(st); + if (CompilationMemoryStatistic::enabled() && CompilationMemoryStatistic::in_oom_crash()) { + st->cr(); + st->print_cr(">> Please see below for a detailed breakdown of compiler memory usage."); + st->cr(); + } #endif STEP_IF("printing registers", _verbose && _context != nullptr) @@ -1260,6 +1266,10 @@ void VMError::report(outputStream* st, bool _verbose) { MemTracker::error_report(st); st->cr(); + STEP_IF("printing compiler memory info, if any", _verbose) + CompilationMemoryStatistic::print_error_report(st); + st->cr(); + STEP_IF("printing periodic trim state", _verbose) NativeHeapTrimmer::print_state(st); st->cr(); @@ -1436,10 +1446,12 @@ void VMError::print_vm_info(outputStream* st) { st->cr(); // STEP("Native Memory Tracking") - MemTracker::error_report(st); st->cr(); + // STEP("Compiler Memory Statistic") + CompilationMemoryStatistic::print_final_report(st); + // STEP("printing periodic trim state") NativeHeapTrimmer::print_state(st); st->cr(); diff --git a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1SubsystemController.java b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1SubsystemController.java index 051b4da5f78..fd325a8f8b4 100644 --- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1SubsystemController.java +++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1SubsystemController.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package jdk.internal.platform.cgroupv1; +import java.lang.System.Logger.Level; +import java.nio.file.Path; +import java.nio.file.Files; import jdk.internal.platform.CgroupSubsystem; import jdk.internal.platform.CgroupSubsystemController; @@ -44,27 +47,36 @@ public CgroupV1SubsystemController(String root, String mountPoint) { public void setPath(String cgroupPath) { if (root != null && cgroupPath != null) { + String path = mountPoint; if (root.equals("/")) { + // host processes and containers with cgroupns=private if (!cgroupPath.equals("/")) { - path = mountPoint + cgroupPath; + path += cgroupPath; } - else { - path = mountPoint; - } - } - else { - if (root.equals(cgroupPath)) { - path = mountPoint; - } - else { - if (cgroupPath.startsWith(root)) { - if (cgroupPath.length() > root.length()) { - String cgroupSubstr = cgroupPath.substring(root.length()); - path = mountPoint + cgroupSubstr; + } else { + // containers with cgroupns=host, default setting is _root==cgroup_path + if (!cgroupPath.equals(root)) { + if (!cgroupPath.equals("") && !cgroupPath.equals("/")) { + // When moved to a subgroup, between subgroups, the path suffix will change. + Path cgp = Path.of(cgroupPath); + int nameCount = cgp.getNameCount(); + for (int i=0; i < nameCount; i++) { + Path dir = Path.of(mountPoint, cgp.toString()); + if (Files.isDirectory(dir)) { + path = dir.toString(); + if (i > 0) { + System.getLogger("jdk.internal.platform").log(Level.DEBUG, String.format( + "Cgroup v1 path reduced to: %s.", cgp)); + } + break; + } + int currentNameCount = cgp.getNameCount(); + cgp = (currentNameCount > 1) ? cgp.subpath(1, currentNameCount) : Path.of(""); } } } } + this.path = path; } } diff --git a/src/java.base/share/classes/java/io/File.java b/src/java.base/share/classes/java/io/File.java index 15e687ebf06..9c9fbc837db 100644 --- a/src/java.base/share/classes/java/io/File.java +++ b/src/java.base/share/classes/java/io/File.java @@ -681,7 +681,6 @@ public URL toURL() throws MalformedURLException { if (isInvalid()) { throw new MalformedURLException("Invalid file path"); } - @SuppressWarnings("deprecation") var result = new URL("file", "", slashify(getAbsolutePath(), isDirectory())); return result; } diff --git a/src/java.base/share/classes/java/io/FileDescriptor.java b/src/java.base/share/classes/java/io/FileDescriptor.java index bdab57c0996..f6466f56eab 100644 --- a/src/java.base/share/classes/java/io/FileDescriptor.java +++ b/src/java.base/share/classes/java/io/FileDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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 @@ -340,7 +340,6 @@ synchronized void attach(Closeable c) { * * The caller closeable gets to call close0(). */ - @SuppressWarnings("try") synchronized void closeAll(Closeable releaser) throws IOException { if (!closed) { closed = true; diff --git a/src/java.base/share/classes/java/lang/Package.java b/src/java.base/share/classes/java/lang/Package.java index 82f40ce373b..14f5682ab0b 100644 --- a/src/java.base/share/classes/java/lang/Package.java +++ b/src/java.base/share/classes/java/lang/Package.java @@ -353,7 +353,6 @@ public boolean isCompatibleWith(String desired) */ @CallerSensitive @Deprecated(since="9") - @SuppressWarnings("deprecation") public static Package getPackage(String name) { ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass()); return l != null ? l.getPackage(name) : BootLoader.getDefinedPackage(name); diff --git a/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java b/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java index 8d84c5f8096..0994071a79e 100644 --- a/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java +++ b/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -142,7 +142,7 @@ public String toString() { return buf.toString(); } - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings("unchecked") public LambdaForm get() { if (cache instanceof LambdaForm lf) { return lf; diff --git a/src/java.base/share/classes/java/lang/invoke/MemberName.java b/src/java.base/share/classes/java/lang/invoke/MemberName.java index 717a1562a1a..5a66e130b13 100644 --- a/src/java.base/share/classes/java/lang/invoke/MemberName.java +++ b/src/java.base/share/classes/java/lang/invoke/MemberName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, 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 @@ -734,7 +734,7 @@ public MemberName getDefinition() { } @Override - @SuppressWarnings({"deprecation", "removal"}) + @SuppressWarnings("removal") public int hashCode() { // Avoid autoboxing getReferenceKind(), since this is used early and will force // early initialization of Byte$ByteCache diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index c6c9d05ec31..3618e6ad572 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,7 @@ import java.lang.classfile.ClassFile; import java.lang.constant.ClassDesc; +import java.lang.foreign.MemoryLayout; import java.lang.invoke.MethodHandles.Lookup; import java.lang.reflect.Array; import java.lang.reflect.Constructor; @@ -1558,8 +1559,8 @@ public Map<String, byte[]> generateHolderClasses(Stream<String> traces) { } @Override - public VarHandle memorySegmentViewHandle(Class<?> carrier, long alignmentMask, ByteOrder order) { - return VarHandles.memorySegmentViewHandle(carrier, alignmentMask, order); + public VarHandle memorySegmentViewHandle(Class<?> carrier, MemoryLayout enclosing, long alignmentMask, ByteOrder order, boolean constantOffset, long offset) { + return VarHandles.memorySegmentViewHandle(carrier, enclosing, alignmentMask, constantOffset, offset, order); } @Override diff --git a/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java b/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java index 69545478ec4..c344cd034c7 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, 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 @@ -110,7 +110,7 @@ public MethodType basicType() { return basicType; } - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings("unchecked") public MethodHandle cachedMethodHandle(int which) { Object entry = methodHandles[which]; if (entry == null) { @@ -136,7 +136,7 @@ public synchronized MethodHandle setCachedMethodHandle(int which, MethodHandle m return mh; } - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings("unchecked") public LambdaForm cachedLambdaForm(int which) { Object entry = lambdaForms[which]; if (entry == null) { @@ -167,7 +167,6 @@ public synchronized LambdaForm setCachedLambdaForm(int which, LambdaForm form) { * This MTF will stand for that type and all un-erased variations. * Eagerly compute some basic properties of the type, common to all variations. */ - @SuppressWarnings({"rawtypes", "unchecked"}) protected MethodTypeForm(MethodType erasedType) { this.erasedType = erasedType; diff --git a/src/java.base/share/classes/java/lang/invoke/SegmentVarHandle.java b/src/java.base/share/classes/java/lang/invoke/SegmentVarHandle.java new file mode 100644 index 00000000000..99fb35379e0 --- /dev/null +++ b/src/java.base/share/classes/java/lang/invoke/SegmentVarHandle.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2019, 2025, 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 java.lang.invoke; + +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.util.Objects; + +import jdk.internal.foreign.AbstractMemorySegmentImpl; +import jdk.internal.misc.ScopedMemoryAccess; +import jdk.internal.vm.annotation.ForceInline; + +/** + * A var handle that accesses primitive values in a memory segment. + */ +final class SegmentVarHandle extends VarHandle { + + // Common implementation fields for the VarForms + static final boolean BE = MethodHandleStatics.UNSAFE.isBigEndian(); + static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); + + /** endianness **/ + final boolean be; + /** The layout the accessed segment must be compatible with. */ + final MemoryLayout enclosing; + /** The offset value, if is constant. vform decides if offset is constant or variable. */ + final long offset; + + SegmentVarHandle(VarForm form, boolean be, MemoryLayout enclosing, long offset, boolean exact) { + super(form, exact); + this.be = be; + this.enclosing = enclosing; + this.offset = offset; + } + + @Override + final MethodType accessModeTypeUncached(VarHandle.AccessType accessType) { + var getType = vform.methodType_table[0]; // erased, but our value type is erase-compatible + return getType.parameterCount() == 2 + ? accessType.accessModeType(MemorySegment.class, getType.returnType(), long.class) + : accessType.accessModeType(MemorySegment.class, getType.returnType(), long.class, long.class); + } + + @Override + public SegmentVarHandle withInvokeExactBehavior() { + return hasInvokeExactBehavior() ? + this : + new SegmentVarHandle(vform, be, enclosing, offset, true); + } + + @Override + public SegmentVarHandle withInvokeBehavior() { + return !hasInvokeExactBehavior() ? + this : + new SegmentVarHandle(vform, be, enclosing, offset, false); + } + + // Common implementation methods for the VarForms + + @ForceInline + static long offset(AbstractMemorySegmentImpl bb, long base, long offset) { + long segment_base = bb.unsafeGetOffset(); + return segment_base + base + offset; + } + + @ForceInline + AbstractMemorySegmentImpl checkSegment(Object obb, long base, boolean ro) { + AbstractMemorySegmentImpl oo = (AbstractMemorySegmentImpl) Objects.requireNonNull(obb); + oo.checkEnclosingLayout(base, this.enclosing, ro); + return oo; + } +} diff --git a/src/java.base/share/classes/java/lang/invoke/VarForm.java b/src/java.base/share/classes/java/lang/invoke/VarForm.java index 0856bf126f9..f1f94a1c26b 100644 --- a/src/java.base/share/classes/java/lang/invoke/VarForm.java +++ b/src/java.base/share/classes/java/lang/invoke/VarForm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import java.util.List; import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic; +import static java.lang.invoke.MethodHandleStatics.UNSAFE; /** * A var handle form containing a set of member name, one for each operation. @@ -43,6 +44,7 @@ */ final class VarForm { + // implClass must be initialized when the member names are accessed! final Class<?> implClass; final @Stable MethodType[] methodType_table; @@ -63,6 +65,15 @@ final class VarForm { } } + VarForm(Class<?> implClass, VarForm methodTypeSource) { + this.implClass = implClass; + // reuse initMethodTypes result from methodTypeSource + this.methodType_table = methodTypeSource.methodType_table; + this.methodType_V_table = methodTypeSource.methodType_V_table; + this.memberName_table = new MemberName[VarHandle.AccessMode.COUNT]; + assert assertMethodTypeTableInitialized() : implClass; + } + // Used by IndirectVarHandle VarForm(Class<?> value, Class<?>[] coordinates) { this.methodType_table = new MethodType[VarHandle.AccessType.COUNT]; @@ -103,6 +114,15 @@ void initMethodTypes(Class<?> value, Class<?>... coordinates) { type.changeReturnType(boolean.class); } + private boolean assertMethodTypeTableInitialized() { + if (methodType_table == null) + return false; + for (int i = 0; i < VarHandle.AccessType.COUNT; i++) { + assert methodType_table[i] != null : implClass + " " + VarHandle.AccessType.values()[i]; + } + return true; + } + @ForceInline final MethodType getMethodType(int type) { return methodType_table[type]; @@ -137,6 +157,7 @@ MemberName resolveMemberName(int mode) { AccessMode value = AccessMode.valueFromOrdinal(mode); String methodName = value.methodName(); MethodType type = methodType_table[value.at.ordinal()].insertParameterTypes(0, VarHandle.class); + assert !UNSAFE.shouldBeInitialized(implClass) : implClass; return memberName_table[mode] = MethodHandles.Lookup.IMPL_LOOKUP .resolveOrNull(REF_invokeStatic, implClass, methodName, type); } diff --git a/src/java.base/share/classes/java/lang/invoke/VarHandle.java b/src/java.base/share/classes/java/lang/invoke/VarHandle.java index 7c849d8686b..4082351010b 100644 --- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java @@ -472,8 +472,7 @@ * @since 9 */ public abstract sealed class VarHandle implements Constable - permits IndirectVarHandle, LazyInitializingVarHandle, - VarHandleSegmentViewBase, + permits IndirectVarHandle, LazyInitializingVarHandle, SegmentVarHandle, VarHandleByteArrayAsChars.ByteArrayViewVarHandle, VarHandleByteArrayAsDoubles.ByteArrayViewVarHandle, VarHandleByteArrayAsFloats.ByteArrayViewVarHandle, diff --git a/src/java.base/share/classes/java/lang/invoke/VarHandleGuards.java b/src/java.base/share/classes/java/lang/invoke/VarHandleGuards.java index 8b73587eca5..1590053a6d0 100644 --- a/src/java.base/share/classes/java/lang/invoke/VarHandleGuards.java +++ b/src/java.base/share/classes/java/lang/invoke/VarHandleGuards.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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,110 +47,132 @@ static final Object guard_L_L(VarHandle handle, Object arg0, VarHandle.AccessDes @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_LL_V(VarHandle handle, Object arg0, Object arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final int guard_L_I(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); - } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + return (int) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); } } @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_LLL_Z(VarHandle handle, Object arg0, Object arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final long guard_L_J(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return (long) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); } } @ForceInline @LambdaForm.Compiled @Hidden - static final Object guard_LLL_L(VarHandle handle, Object arg0, Object arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final float guard_L_F(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); - return ad.returnType.cast(r); + return (float) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); } } @ForceInline @LambdaForm.Compiled @Hidden - static final Object guard_LL_L(VarHandle handle, Object arg0, Object arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final double guard_L_D(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - Object r = MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + return (double) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final Object guard__L(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + Object r = MethodHandle.linkToStatic(handle, handle.vform.getMemberName(ad.mode)); return ad.returnType.cast(r); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect()); } } @ForceInline @LambdaForm.Compiled @Hidden - static final int guard_L_I(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable { + static final int guard__I(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (int) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + return (int) MethodHandle.linkToStatic(handle, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); + return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect()); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_LI_V(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final long guard__J(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); - } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + return (long) MethodHandle.linkToStatic(handle, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect()); } } @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_LII_Z(VarHandle handle, Object arg0, int arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final float guard__F(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return (float) MethodHandle.linkToStatic(handle, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect()); } } @ForceInline @LambdaForm.Compiled @Hidden - static final int guard_LII_I(VarHandle handle, Object arg0, int arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final double guard__D(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return (double) MethodHandle.linkToStatic(handle, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect()); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final Object guard_LI_L(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + Object r = MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + return ad.returnType.cast(r); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @@ -170,54 +192,66 @@ static final int guard_LI_I(VarHandle handle, Object arg0, int arg1, VarHandle.A @ForceInline @LambdaForm.Compiled @Hidden - static final long guard_L_J(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable { + static final long guard_LI_J(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (long) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + return (long) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); + return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_LJ_V(VarHandle handle, Object arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final float guard_LI_F(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); - } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + return (float) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_LJJ_Z(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final double guard_LI_D(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return (double) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final long guard_LJJ_J(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final Object guard_LJ_L(VarHandle handle, Object arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + Object r = MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + return ad.returnType.cast(r); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final int guard_LJ_I(VarHandle handle, Object arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (int) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @@ -237,48 +271,73 @@ static final long guard_LJ_J(VarHandle handle, Object arg0, long arg1, VarHandle @ForceInline @LambdaForm.Compiled @Hidden - static final float guard_L_F(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable { + static final float guard_LJ_F(VarHandle handle, Object arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (float) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + return (float) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); + return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_LF_V(VarHandle handle, Object arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final double guard_LJ_D(VarHandle handle, Object arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); - } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + return (double) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_LFF_Z(VarHandle handle, Object arg0, float arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final Object guard_LJJ_L(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return ad.returnType.cast(r); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @ForceInline @LambdaForm.Compiled @Hidden - static final float guard_LFF_F(VarHandle handle, Object arg0, float arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final int guard_LJJ_I(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final long guard_LJJ_J(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final float guard_LJJ_F(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); @@ -291,33 +350,35 @@ static final float guard_LFF_F(VarHandle handle, Object arg0, float arg1, float @ForceInline @LambdaForm.Compiled @Hidden - static final float guard_LF_F(VarHandle handle, Object arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final double guard_LJJ_D(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (float) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @ForceInline @LambdaForm.Compiled @Hidden - static final double guard_L_D(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable { + static final void guard_LL_V(VarHandle handle, Object arg0, Object arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (double) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_LD_V(VarHandle handle, Object arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final void guard_LI_V(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); @@ -332,60 +393,67 @@ static final void guard_LD_V(VarHandle handle, Object arg0, double arg1, VarHand @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_LDD_Z(VarHandle handle, Object arg0, double arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final void guard_LJ_V(VarHandle handle, Object arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final double guard_LDD_D(VarHandle handle, Object arg0, double arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final void guard_LF_V(VarHandle handle, Object arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final double guard_LD_D(VarHandle handle, Object arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final void guard_LD_V(VarHandle handle, Object arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (double) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final Object guard__L(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable { + static final void guard_L_V(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - Object r = MethodHandle.linkToStatic(handle, handle.vform.getMemberName(ad.mode)); - return ad.returnType.cast(r); + MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect()); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_L_V(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable { + static final void guard_I_V(VarHandle handle, int arg0, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); @@ -400,33 +468,37 @@ static final void guard_L_V(VarHandle handle, Object arg0, VarHandle.AccessDescr @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_LL_Z(VarHandle handle, Object arg0, Object arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final void guard_J_V(VarHandle handle, long arg0, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); } } @ForceInline @LambdaForm.Compiled @Hidden - static final int guard__I(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable { + static final void guard_F_V(VarHandle handle, float arg0, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (int) MethodHandle.linkToStatic(handle, handle.vform.getMemberName(ad.mode)); + MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect()); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_I_V(VarHandle handle, int arg0, VarHandle.AccessDescriptor ad) throws Throwable { + static final void guard_D_V(VarHandle handle, double arg0, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); @@ -441,289 +513,742 @@ static final void guard_I_V(VarHandle handle, int arg0, VarHandle.AccessDescript @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_II_Z(VarHandle handle, int arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final void guard_LIL_V(VarHandle handle, Object arg0, int arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @ForceInline @LambdaForm.Compiled @Hidden - static final int guard_II_I(VarHandle handle, int arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final void guard_LII_V(VarHandle handle, Object arg0, int arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (int) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @ForceInline @LambdaForm.Compiled @Hidden - static final int guard_I_I(VarHandle handle, int arg0, VarHandle.AccessDescriptor ad) throws Throwable { + static final void guard_LIJ_V(VarHandle handle, Object arg0, int arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final void guard_LIF_V(VarHandle handle, Object arg0, int arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final void guard_LID_V(VarHandle handle, Object arg0, int arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final void guard_LJL_V(VarHandle handle, Object arg0, long arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final void guard_LJI_V(VarHandle handle, Object arg0, long arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final void guard_LJJ_V(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final void guard_LJF_V(VarHandle handle, Object arg0, long arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final void guard_LJD_V(VarHandle handle, Object arg0, long arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final void guard_LJJL_V(VarHandle handle, Object arg0, long arg1, long arg2, Object arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final void guard_LJJI_V(VarHandle handle, Object arg0, long arg1, long arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final void guard_LJJJ_V(VarHandle handle, Object arg0, long arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final void guard_LJJF_V(VarHandle handle, Object arg0, long arg1, long arg2, float arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final void guard_LJJD_V(VarHandle handle, Object arg0, long arg1, long arg2, double arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { + MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LLL_Z(VarHandle handle, Object arg0, Object arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LII_Z(VarHandle handle, Object arg0, int arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LJJ_Z(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LFF_Z(VarHandle handle, Object arg0, float arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LDD_Z(VarHandle handle, Object arg0, double arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LL_Z(VarHandle handle, Object arg0, Object arg1, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_II_Z(VarHandle handle, int arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_JJ_Z(VarHandle handle, long arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_FF_Z(VarHandle handle, float arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_DD_Z(VarHandle handle, double arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LILL_Z(VarHandle handle, Object arg0, int arg1, Object arg2, Object arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LIII_Z(VarHandle handle, Object arg0, int arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LIJJ_Z(VarHandle handle, Object arg0, int arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LIFF_Z(VarHandle handle, Object arg0, int arg1, float arg2, float arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LIDD_Z(VarHandle handle, Object arg0, int arg1, double arg2, double arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LJLL_Z(VarHandle handle, Object arg0, long arg1, Object arg2, Object arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LJII_Z(VarHandle handle, Object arg0, long arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LJJJ_Z(VarHandle handle, Object arg0, long arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LJFF_Z(VarHandle handle, Object arg0, long arg1, float arg2, float arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LJDD_Z(VarHandle handle, Object arg0, long arg1, double arg2, double arg3, VarHandle.AccessDescriptor ad) throws Throwable { + boolean direct = handle.checkAccessModeThenIsDirect(ad); + if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + } else { + MethodHandle mh = handle.getMethodHandle(ad.mode); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + } + } + + @ForceInline + @LambdaForm.Compiled + @Hidden + static final boolean guard_LJJLL_Z(VarHandle handle, Object arg0, long arg1, long arg2, Object arg3, Object arg4, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (int) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, arg4, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3, arg4); } } @ForceInline @LambdaForm.Compiled @Hidden - static final long guard__J(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable { + static final boolean guard_LJJII_Z(VarHandle handle, Object arg0, long arg1, long arg2, int arg3, int arg4, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (long) MethodHandle.linkToStatic(handle, handle.vform.getMemberName(ad.mode)); + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, arg4, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect()); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3, arg4); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_J_V(VarHandle handle, long arg0, VarHandle.AccessDescriptor ad) throws Throwable { + static final boolean guard_LJJJJ_Z(VarHandle handle, Object arg0, long arg1, long arg2, long arg3, long arg4, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); - } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, arg4, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3, arg4); } } @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_JJ_Z(VarHandle handle, long arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final boolean guard_LJJFF_Z(VarHandle handle, Object arg0, long arg1, long arg2, float arg3, float arg4, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, arg4, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3, arg4); } } @ForceInline @LambdaForm.Compiled @Hidden - static final long guard_JJ_J(VarHandle handle, long arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final boolean guard_LJJDD_Z(VarHandle handle, Object arg0, long arg1, long arg2, double arg3, double arg4, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (long) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, arg4, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3, arg4); } } @ForceInline @LambdaForm.Compiled @Hidden - static final long guard_J_J(VarHandle handle, long arg0, VarHandle.AccessDescriptor ad) throws Throwable { + static final Object guard_LLL_L(VarHandle handle, Object arg0, Object arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (long) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return ad.returnType.cast(r); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); + return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @ForceInline @LambdaForm.Compiled @Hidden - static final float guard__F(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable { + static final int guard_LII_I(VarHandle handle, Object arg0, int arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (float) MethodHandle.linkToStatic(handle, handle.vform.getMemberName(ad.mode)); + return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect()); + return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_F_V(VarHandle handle, float arg0, VarHandle.AccessDescriptor ad) throws Throwable { + static final float guard_LFF_F(VarHandle handle, Object arg0, float arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); - } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); + return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_FF_Z(VarHandle handle, float arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final double guard_LDD_D(VarHandle handle, Object arg0, double arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @ForceInline @LambdaForm.Compiled @Hidden - static final float guard_FF_F(VarHandle handle, float arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final Object guard_LL_L(VarHandle handle, Object arg0, Object arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (float) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + Object r = MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + return ad.returnType.cast(r); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final float guard_F_F(VarHandle handle, float arg0, VarHandle.AccessDescriptor ad) throws Throwable { + static final int guard_II_I(VarHandle handle, int arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (float) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + return (int) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); + return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final double guard__D(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable { + static final long guard_JJ_J(VarHandle handle, long arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (double) MethodHandle.linkToStatic(handle, handle.vform.getMemberName(ad.mode)); + return (long) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect()); + return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_D_V(VarHandle handle, double arg0, VarHandle.AccessDescriptor ad) throws Throwable { + static final float guard_FF_F(VarHandle handle, float arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); - } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + return (float) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); + return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_DD_Z(VarHandle handle, double arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final double guard_DD_D(VarHandle handle, double arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + return (double) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final double guard_DD_D(VarHandle handle, double arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final Object guard_LILL_L(VarHandle handle, Object arg0, int arg1, Object arg2, Object arg3, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (double) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return ad.returnType.cast(r); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); } } @ForceInline @LambdaForm.Compiled @Hidden - static final double guard_D_D(VarHandle handle, double arg0, VarHandle.AccessDescriptor ad) throws Throwable { + static final int guard_LIII_I(VarHandle handle, Object arg0, int arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (double) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); + return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); + return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); } } @ForceInline @LambdaForm.Compiled @Hidden - static final Object guard_LI_L(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final long guard_LIJJ_J(VarHandle handle, Object arg0, int arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - Object r = MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); - return ad.returnType.cast(r); + return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_LIL_V(VarHandle handle, Object arg0, int arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final float guard_LIFF_F(VarHandle handle, Object arg0, int arg1, float arg2, float arg3, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); - } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); } } @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_LILL_Z(VarHandle handle, Object arg0, int arg1, Object arg2, Object arg3, VarHandle.AccessDescriptor ad) throws Throwable { + static final double guard_LIDD_D(VarHandle handle, Object arg0, int arg1, double arg2, double arg3, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); } } @ForceInline @LambdaForm.Compiled @Hidden - static final Object guard_LILL_L(VarHandle handle, Object arg0, int arg1, Object arg2, Object arg3, VarHandle.AccessDescriptor ad) throws Throwable { + static final Object guard_LJLL_L(VarHandle handle, Object arg0, long arg1, Object arg2, Object arg3, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); @@ -737,129 +1262,125 @@ static final Object guard_LILL_L(VarHandle handle, Object arg0, int arg1, Object @ForceInline @LambdaForm.Compiled @Hidden - static final Object guard_LIL_L(VarHandle handle, Object arg0, int arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final int guard_LJII_I(VarHandle handle, Object arg0, long arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); - return ad.returnType.cast(r); + return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_LII_V(VarHandle handle, Object arg0, int arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final long guard_LJJJ_J(VarHandle handle, Object arg0, long arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); - } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); } } @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_LIII_Z(VarHandle handle, Object arg0, int arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable { + static final float guard_LJFF_F(VarHandle handle, Object arg0, long arg1, float arg2, float arg3, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); } } @ForceInline @LambdaForm.Compiled @Hidden - static final int guard_LIII_I(VarHandle handle, Object arg0, int arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable { + static final double guard_LJDD_D(VarHandle handle, Object arg0, long arg1, double arg2, double arg3, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); } } @ForceInline @LambdaForm.Compiled @Hidden - static final long guard_LI_J(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final Object guard_LJJLL_L(VarHandle handle, Object arg0, long arg1, long arg2, Object arg3, Object arg4, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (long) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, arg4, handle.vform.getMemberName(ad.mode)); + return ad.returnType.cast(r); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3, arg4); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_LIJ_V(VarHandle handle, Object arg0, int arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final int guard_LJJII_I(VarHandle handle, Object arg0, long arg1, long arg2, int arg3, int arg4, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); - } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, arg4, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3, arg4); } } @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_LIJJ_Z(VarHandle handle, Object arg0, int arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable { + static final long guard_LJJJJ_J(VarHandle handle, Object arg0, long arg1, long arg2, long arg3, long arg4, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, arg4, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3, arg4); } } @ForceInline @LambdaForm.Compiled @Hidden - static final long guard_LIJJ_J(VarHandle handle, Object arg0, int arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable { + static final float guard_LJJFF_F(VarHandle handle, Object arg0, long arg1, long arg2, float arg3, float arg4, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, arg4, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3, arg4); } } @ForceInline @LambdaForm.Compiled @Hidden - static final long guard_LIJ_J(VarHandle handle, Object arg0, int arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final double guard_LJJDD_D(VarHandle handle, Object arg0, long arg1, long arg2, double arg3, double arg4, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, arg4, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3, arg4); } } @ForceInline @LambdaForm.Compiled @Hidden - static final float guard_LI_F(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final float guard_LF_F(VarHandle handle, Object arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { return (float) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); @@ -872,108 +1393,105 @@ static final float guard_LI_F(VarHandle handle, Object arg0, int arg1, VarHandle @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_LIF_V(VarHandle handle, Object arg0, int arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final double guard_LD_D(VarHandle handle, Object arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); - } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return (double) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); } } @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_LIFF_Z(VarHandle handle, Object arg0, int arg1, float arg2, float arg3, VarHandle.AccessDescriptor ad) throws Throwable { + static final int guard_I_I(VarHandle handle, int arg0, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return (int) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); } } @ForceInline @LambdaForm.Compiled @Hidden - static final float guard_LIFF_F(VarHandle handle, Object arg0, int arg1, float arg2, float arg3, VarHandle.AccessDescriptor ad) throws Throwable { + static final long guard_J_J(VarHandle handle, long arg0, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return (long) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); } } @ForceInline @LambdaForm.Compiled @Hidden - static final float guard_LIF_F(VarHandle handle, Object arg0, int arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final float guard_F_F(VarHandle handle, float arg0, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return (float) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); } } @ForceInline @LambdaForm.Compiled @Hidden - static final double guard_LI_D(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final double guard_D_D(VarHandle handle, double arg0, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (double) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + return (double) MethodHandle.linkToStatic(handle, arg0, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_LID_V(VarHandle handle, Object arg0, int arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final Object guard_LIL_L(VarHandle handle, Object arg0, int arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); - } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return ad.returnType.cast(r); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_LIDD_Z(VarHandle handle, Object arg0, int arg1, double arg2, double arg3, VarHandle.AccessDescriptor ad) throws Throwable { + static final long guard_LIJ_J(VarHandle handle, Object arg0, int arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @ForceInline @LambdaForm.Compiled @Hidden - static final double guard_LIDD_D(VarHandle handle, Object arg0, int arg1, double arg2, double arg3, VarHandle.AccessDescriptor ad) throws Throwable { + static final float guard_LIF_F(VarHandle handle, Object arg0, int arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @@ -993,108 +1511,106 @@ static final double guard_LID_D(VarHandle handle, Object arg0, int arg1, double @ForceInline @LambdaForm.Compiled @Hidden - static final int guard_LJ_I(VarHandle handle, Object arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable { + static final Object guard_LJL_L(VarHandle handle, Object arg0, long arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (int) MethodHandle.linkToStatic(handle, arg0, arg1, handle.vform.getMemberName(ad.mode)); + Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return ad.returnType.cast(r); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1); + return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_LJI_V(VarHandle handle, Object arg0, long arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final int guard_LJI_I(VarHandle handle, Object arg0, long arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); - } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_LJII_Z(VarHandle handle, Object arg0, long arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable { + static final float guard_LJF_F(VarHandle handle, Object arg0, long arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @ForceInline @LambdaForm.Compiled @Hidden - static final int guard_LJII_I(VarHandle handle, Object arg0, long arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable { + static final double guard_LJD_D(VarHandle handle, Object arg0, long arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); } } @ForceInline @LambdaForm.Compiled @Hidden - static final int guard_LJI_I(VarHandle handle, Object arg0, long arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final Object guard_LJJL_L(VarHandle handle, Object arg0, long arg1, long arg2, Object arg3, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return ad.returnType.cast(r); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); } } @ForceInline @LambdaForm.Compiled @Hidden - static final void guard_LJJ_V(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable { + static final int guard_LJJI_I(VarHandle handle, Object arg0, long arg1, long arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); - } else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) { - MethodHandle.linkToStatic(handle, arg0, arg1, arg2, handle.vform.getMemberName(ad.mode)); + return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2); + return (int) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); } } @ForceInline @LambdaForm.Compiled @Hidden - static final boolean guard_LJJJ_Z(VarHandle handle, Object arg0, long arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable { + static final float guard_LJJF_F(VarHandle handle, Object arg0, long arg1, long arg2, float arg3, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (boolean) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + return (float) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); } } @ForceInline @LambdaForm.Compiled @Hidden - static final long guard_LJJJ_J(VarHandle handle, Object arg0, long arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable { + static final double guard_LJJD_D(VarHandle handle, Object arg0, long arg1, long arg2, double arg3, VarHandle.AccessDescriptor ad) throws Throwable { boolean direct = handle.checkAccessModeThenIsDirect(ad); if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) { - return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); + return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, handle.vform.getMemberName(ad.mode)); } else { MethodHandle mh = handle.getMethodHandle(ad.mode); - return (long) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); + return (double) mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(handle.asDirect(), arg0, arg1, arg2, arg3); } } diff --git a/src/java.base/share/classes/java/lang/invoke/VarHandleSegmentViewBase.java b/src/java.base/share/classes/java/lang/invoke/VarHandleSegmentViewBase.java deleted file mode 100644 index 31ec02c3d7c..00000000000 --- a/src/java.base/share/classes/java/lang/invoke/VarHandleSegmentViewBase.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -package java.lang.invoke; - -/** - * Base class for memory segment var handle view implementations. - */ -abstract sealed class VarHandleSegmentViewBase extends VarHandle permits - VarHandleSegmentAsBytes, - VarHandleSegmentAsChars, - VarHandleSegmentAsDoubles, - VarHandleSegmentAsFloats, - VarHandleSegmentAsInts, - VarHandleSegmentAsLongs, - VarHandleSegmentAsShorts { - - /** endianness **/ - final boolean be; - - /** alignment constraint (in bytes, expressed as a bit mask) **/ - final long alignmentMask; - - VarHandleSegmentViewBase(VarForm form, boolean be, long alignmentMask, boolean exact) { - super(form, exact); - this.be = be; - this.alignmentMask = alignmentMask; - } - - static UnsupportedOperationException newUnsupportedAccessModeForAlignment(long alignment) { - return new UnsupportedOperationException("Unsupported access mode for alignment: " + alignment); - } -} diff --git a/src/java.base/share/classes/java/lang/invoke/VarHandles.java b/src/java.base/share/classes/java/lang/invoke/VarHandles.java index 47f95fe17e9..0881ab68024 100644 --- a/src/java.base/share/classes/java/lang/invoke/VarHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/VarHandles.java @@ -27,6 +27,7 @@ import sun.invoke.util.Wrapper; +import java.lang.foreign.MemoryLayout; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -313,44 +314,55 @@ else if (viewComponentType == float.class) { } /** - * Creates a memory segment view var handle. - * + * Creates a memory segment view var handle accessing a {@code carrier} element. It has access coordinates + * {@code (MS, long)} if {@code constantOffset}, {@code (MS, long, (validated) long)} otherwise. + * <p> * The resulting var handle will take a memory segment as first argument (the segment to be dereferenced), - * and a {@code long} as second argument (the offset into the segment). - * - * Note: the returned var handle does not perform any size or alignment check. It is up to clients - * to adapt the returned var handle and insert the appropriate checks. + * and a {@code long} as second argument (the offset into the segment). Both arguments are checked. + * <p> + * If {@code constantOffset == false}, the resulting var handle will take a third pre-validated additional + * offset instead of the given fixed {@code offset}, and caller must ensure that passed additional offset, + * either to the handle (such as computing through method handles) or as fixed {@code offset} here, is valid. * - * @param carrier the Java carrier type. - * @param alignmentMask alignment requirement to be checked upon access. In bytes. Expressed as a mask. - * @param byteOrder the byte order. - * @return the created VarHandle. + * @param carrier the Java carrier type of the element + * @param enclosing the enclosing layout to perform bound and alignment checks against + * @param alignmentMask alignment of this accessed element in the enclosing layout + * @param constantOffset if access path has a constant offset value, i.e. it has no strides + * @param offset the offset value, if the offset is constant + * @param byteOrder the byte order + * @return the created var handle */ - static VarHandle memorySegmentViewHandle(Class<?> carrier, long alignmentMask, - ByteOrder byteOrder) { - if (!carrier.isPrimitive() || carrier == void.class || carrier == boolean.class) { + static VarHandle memorySegmentViewHandle(Class<?> carrier, MemoryLayout enclosing, long alignmentMask, + boolean constantOffset, long offset, ByteOrder byteOrder) { + if (!carrier.isPrimitive() || carrier == void.class) { throw new IllegalArgumentException("Invalid carrier: " + carrier.getName()); } boolean be = byteOrder == ByteOrder.BIG_ENDIAN; boolean exact = VAR_HANDLE_SEGMENT_FORCE_EXACT; + // All carrier types must persist across MethodType erasure + VarForm form; if (carrier == byte.class) { - return maybeAdapt(new VarHandleSegmentAsBytes(be, alignmentMask, exact)); + form = VarHandleSegmentAsBytes.selectForm(alignmentMask, constantOffset); } else if (carrier == char.class) { - return maybeAdapt(new VarHandleSegmentAsChars(be, alignmentMask, exact)); + form = VarHandleSegmentAsChars.selectForm(alignmentMask, constantOffset); } else if (carrier == short.class) { - return maybeAdapt(new VarHandleSegmentAsShorts(be, alignmentMask, exact)); + form = VarHandleSegmentAsShorts.selectForm(alignmentMask, constantOffset); } else if (carrier == int.class) { - return maybeAdapt(new VarHandleSegmentAsInts(be, alignmentMask, exact)); + form = VarHandleSegmentAsInts.selectForm(alignmentMask, constantOffset); } else if (carrier == float.class) { - return maybeAdapt(new VarHandleSegmentAsFloats(be, alignmentMask, exact)); + form = VarHandleSegmentAsFloats.selectForm(alignmentMask, constantOffset); } else if (carrier == long.class) { - return maybeAdapt(new VarHandleSegmentAsLongs(be, alignmentMask, exact)); + form = VarHandleSegmentAsLongs.selectForm(alignmentMask, constantOffset); } else if (carrier == double.class) { - return maybeAdapt(new VarHandleSegmentAsDoubles(be, alignmentMask, exact)); + form = VarHandleSegmentAsDoubles.selectForm(alignmentMask, constantOffset); + } else if (carrier == boolean.class) { + form = VarHandleSegmentAsBooleans.selectForm(alignmentMask, constantOffset); } else { throw new IllegalStateException("Cannot get here"); } + + return maybeAdapt(new SegmentVarHandle(form, be, enclosing, offset, exact)); } private static VarHandle maybeAdapt(VarHandle target) { @@ -746,7 +758,7 @@ private static boolean isCheckedException(Class<?> clazz) { // Object getAndUpdate(Object value); // } // -// record HandleType(Class<?> receiver, Class<?> value, Class<?>... intermediates) { +// record HandleType(Class<?> receiver, Class<?>... intermediates) { // } // // /** @@ -766,48 +778,31 @@ private static boolean isCheckedException(Class<?> clazz) { // System.out.println(); // // // Declare the stream of shapes -// Stream<HandleType> hts = Stream.of( -// // Object->Object -// new HandleType(Object.class, Object.class), -// // Object->int +// List<HandleType> hts = List.of( +// // Object->T +// new HandleType(Object.class), +// +// // <static>->T +// new HandleType(null), +// +// // Array[index]->T // new HandleType(Object.class, int.class), -// // Object->long +// +// // MS[base]->T // new HandleType(Object.class, long.class), -// // Object->float -// new HandleType(Object.class, float.class), -// // Object->double -// new HandleType(Object.class, double.class), -// -// // <static>->Object -// new HandleType(null, Object.class), -// // <static>->int -// new HandleType(null, int.class), -// // <static>->long -// new HandleType(null, long.class), -// // <static>->float -// new HandleType(null, float.class), -// // <static>->double -// new HandleType(null, double.class), -// -// // Array[int]->Object -// new HandleType(Object.class, Object.class, int.class), -// // Array[int]->int -// new HandleType(Object.class, int.class, int.class), -// // Array[int]->long -// new HandleType(Object.class, long.class, int.class), -// // Array[int]->float -// new HandleType(Object.class, float.class, int.class), -// // Array[int]->double -// new HandleType(Object.class, double.class, int.class), -// -// // Array[long]->int -// new HandleType(Object.class, int.class, long.class), -// // Array[long]->long +// +// // MS[base][offset]->T // new HandleType(Object.class, long.class, long.class) // ); // -// hts.flatMap(ht -> Stream.of(VarHandleTemplate.class.getMethods()). -// map(m -> generateMethodType(m, ht.receiver, ht.value, ht.intermediates))). +// Stream.of(VarHandleTemplate.class.getMethods()).<MethodType> +// mapMulti((m, sink) -> { +// for (var ht : hts) { +// for (var bt : LambdaForm.BasicType.ARG_TYPES) { +// sink.accept(generateMethodType(m, ht.receiver, bt.btClass, ht.intermediates)); +// } +// } +// }). // distinct(). // map(GuardMethodGenerator::generateMethod). // forEach(System.out::println); diff --git a/src/java.base/share/classes/java/lang/invoke/X-VarHandleSegmentView.java.template b/src/java.base/share/classes/java/lang/invoke/X-VarHandleSegmentView.java.template index c5942e93c46..aa8c7b28617 100644 --- a/src/java.base/share/classes/java/lang/invoke/X-VarHandleSegmentView.java.template +++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandleSegmentView.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,370 +25,465 @@ package java.lang.invoke; import jdk.internal.foreign.AbstractMemorySegmentImpl; -import jdk.internal.foreign.Utils; -import jdk.internal.misc.ScopedMemoryAccess; import jdk.internal.vm.annotation.ForceInline; -import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.ref.Reference; -import java.util.Objects; - -import static java.lang.invoke.MethodHandleStatics.UNSAFE; +import static java.lang.invoke.SegmentVarHandle.*; #warn -final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { - - static final boolean BE = UNSAFE.isBigEndian(); - - static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); +{#if[byte]?final:sealed} class VarHandleSegmentAs$Type$s { +#if[!byte] static final int NON_PLAIN_ACCESS_MIN_ALIGN_MASK = $BoxType$.BYTES - 1; - static final VarForm FORM = new VarForm(VarHandleSegmentAs$Type$s.class, MemorySegment.class, $type$.class, MemoryLayout.class, long.class, long.class); - - VarHandleSegmentAs$Type$s(boolean be, long alignmentMask, boolean exact) { - super(FORM, be, alignmentMask, exact); - } - - @Override - final MethodType accessModeTypeUncached(VarHandle.AccessType accessType) { - return accessType.accessModeType(MemorySegment.class, $type$.class, MemoryLayout.class, long.class, long.class); - } - - @Override - public VarHandleSegmentAs$Type$s withInvokeExactBehavior() { - return hasInvokeExactBehavior() ? - this : - new VarHandleSegmentAs$Type$s(be, alignmentMask, true); - } - - @Override - public VarHandleSegmentAs$Type$s withInvokeBehavior() { - return !hasInvokeExactBehavior() ? - this : - new VarHandleSegmentAs$Type$s(be, alignmentMask, false); - } - -#if[floatingPoint] - @ForceInline - static $rawType$ convEndian(boolean big, $type$ v) { - $rawType$ rv = $Type$.$type$ToRaw$RawType$Bits(v); - return big == BE ? rv : $RawBoxType$.reverseBytes(rv); - } - - @ForceInline - static $type$ convEndian(boolean big, $rawType$ rv) { - rv = big == BE ? rv : $RawBoxType$.reverseBytes(rv); - return $Type$.$rawType$BitsTo$Type$(rv); - } -#else[floatingPoint] +#end[byte] + static VarForm selectForm(long alignmentMask, boolean constantOffset) { #if[byte] - @ForceInline - static $type$ convEndian(boolean big, $type$ n) { - return n; - } + return constantOffset ? CONSTANT_OFFSET_FORM : VARIABLE_OFFSET_FORM; #else[byte] - @ForceInline - static $type$ convEndian(boolean big, $type$ n) { - return big == BE ? n : $BoxType$.reverseBytes(n); - } + return (alignmentMask & NON_PLAIN_ACCESS_MIN_ALIGN_MASK) != NON_PLAIN_ACCESS_MIN_ALIGN_MASK ? + (constantOffset ? CONSTANT_OFFSET_FORM : VARIABLE_OFFSET_FORM) : + (constantOffset ? VarHandleSegmentAs$Type$sAligned.CONSTANT_OFFSET_FORM : VarHandleSegmentAs$Type$sAligned.VARIABLE_OFFSET_FORM); #end[byte] -#end[floatingPoint] - - @ForceInline - static AbstractMemorySegmentImpl checkSegment(Object obb, Object encl, long base, boolean ro) { - AbstractMemorySegmentImpl oo = (AbstractMemorySegmentImpl)Objects.requireNonNull(obb); - oo.checkEnclosingLayout(base, (MemoryLayout)encl, ro); - return oo; } - @ForceInline - static long offsetNonPlain(AbstractMemorySegmentImpl bb, long base, long offset, long alignmentMask) { - if ((alignmentMask & NON_PLAIN_ACCESS_MIN_ALIGN_MASK) != NON_PLAIN_ACCESS_MIN_ALIGN_MASK) { - throw VarHandleSegmentViewBase.newUnsupportedAccessModeForAlignment(alignmentMask + 1); - } - return offsetPlain(bb, base, offset); - } + static final VarForm CONSTANT_OFFSET_FORM = new VarForm(VarHandleSegmentAs$Type$s.class, MemorySegment.class, $type$.class, long.class); + static final VarForm VARIABLE_OFFSET_FORM = new VarForm(VarHandleSegmentAs$Type$s.class, MemorySegment.class, $type$.class, long.class, long.class); + + VarHandleSegmentAs$Type$s() { throw new AssertionError(); } @ForceInline - static long offsetPlain(AbstractMemorySegmentImpl bb, long base, long offset) { - long segment_base = bb.unsafeGetOffset(); - return segment_base + base + offset; + static $type$ get(VarHandle ob, Object obb, long base) { + return get(ob, obb, base, ((SegmentVarHandle) ob).offset); } @ForceInline - static $type$ get(VarHandle ob, Object obb, Object encl, long base, long offset) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, true); + static $type$ get(VarHandle ob, Object obb, long base, long offset) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, true); #if[floatingPoint] $rawType$ rawValue = SCOPED_MEMORY_ACCESS.get$RawType$Unaligned(bb.sessionImpl(), bb.unsafeGetBase(), - offsetPlain(bb, base, offset), + offset(bb, base, offset), handle.be); return $Type$.$rawType$BitsTo$Type$(rawValue); #else[floatingPoint] #if[byte] return SCOPED_MEMORY_ACCESS.get$Type$(bb.sessionImpl(), bb.unsafeGetBase(), - offsetPlain(bb, base, offset)); + offset(bb, base, offset)); #else[byte] return SCOPED_MEMORY_ACCESS.get$Type$Unaligned(bb.sessionImpl(), bb.unsafeGetBase(), - offsetPlain(bb, base, offset), + offset(bb, base, offset), handle.be); #end[byte] #end[floatingPoint] } @ForceInline - static void set(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static void set(VarHandle ob, Object obb, long base, $type$ value) { + set(ob, obb, base, ((SegmentVarHandle) ob).offset, value); + } + + @ForceInline + static void set(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); #if[floatingPoint] SCOPED_MEMORY_ACCESS.put$RawType$Unaligned(bb.sessionImpl(), bb.unsafeGetBase(), - offsetPlain(bb, base, offset), + offset(bb, base, offset), $Type$.$type$ToRaw$RawType$Bits(value), handle.be); #else[floatingPoint] #if[byte] SCOPED_MEMORY_ACCESS.put$Type$(bb.sessionImpl(), bb.unsafeGetBase(), - offsetPlain(bb, base, offset), + offset(bb, base, offset), value); #else[byte] SCOPED_MEMORY_ACCESS.put$Type$Unaligned(bb.sessionImpl(), bb.unsafeGetBase(), - offsetPlain(bb, base, offset), + offset(bb, base, offset), value, handle.be); #end[byte] #end[floatingPoint] } +#if[!byte] +} +// This class must be accessed through non-aligned VarHandleSegmentAs$Type$s +final class VarHandleSegmentAs$Type$sAligned extends VarHandleSegmentAs$Type$s { + + static final VarForm CONSTANT_OFFSET_FORM = new VarForm(VarHandleSegmentAs$Type$sAligned.class, VarHandleSegmentAs$Type$s.CONSTANT_OFFSET_FORM); + static final VarForm VARIABLE_OFFSET_FORM = new VarForm(VarHandleSegmentAs$Type$sAligned.class, VarHandleSegmentAs$Type$s.VARIABLE_OFFSET_FORM); + + VarHandleSegmentAs$Type$sAligned() { throw new AssertionError(); } +#end[byte] + +#if[floatingPoint] + @ForceInline + static $rawType$ convEndian(boolean big, $type$ v) { + $rawType$ rv = $Type$.$type$ToRaw$RawType$Bits(v); + return big == BE ? rv : $RawBoxType$.reverseBytes(rv); + } + + @ForceInline + static $type$ convEndian(boolean big, $rawType$ rv) { + rv = big == BE ? rv : $RawBoxType$.reverseBytes(rv); + return $Type$.$rawType$BitsTo$Type$(rv); + } +#else[floatingPoint] +#if[byte] + @ForceInline + static $type$ convEndian(boolean big, $type$ n) { + return n; + } +#else[byte] @ForceInline - static $type$ getVolatile(VarHandle ob, Object obb, Object encl, long base, long offset) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, true); + static $type$ convEndian(boolean big, $type$ n) { + return big == BE ? n : $BoxType$.reverseBytes(n); + } +#end[byte] +#end[floatingPoint] + + @ForceInline + static $type$ getVolatile(VarHandle ob, Object obb, long base) { + return getVolatile(ob, obb, base, ((SegmentVarHandle) ob).offset); + } + + @ForceInline + static $type$ getVolatile(VarHandle ob, Object obb, long base, long offset) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, true); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask))); + offset(bb, base, offset))); } @ForceInline - static void setVolatile(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static void setVolatile(VarHandle ob, Object obb, long base, $type$ value) { + setVolatile(ob, obb, base, ((SegmentVarHandle) ob).offset, value); + } + + @ForceInline + static void setVolatile(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); SCOPED_MEMORY_ACCESS.put$RawType$Volatile(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), convEndian(handle.be, value)); } @ForceInline - static $type$ getAcquire(VarHandle ob, Object obb, Object encl, long base, long offset) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, true); + static $type$ getAcquire(VarHandle ob, Object obb, long base) { + return getAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset); + } + + @ForceInline + static $type$ getAcquire(VarHandle ob, Object obb, long base, long offset) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, true); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.get$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask))); + offset(bb, base, offset))); } @ForceInline - static void setRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static void setRelease(VarHandle ob, Object obb, long base, $type$ value) { + setRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value); + } + + @ForceInline + static void setRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); SCOPED_MEMORY_ACCESS.put$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), convEndian(handle.be, value)); } @ForceInline - static $type$ getOpaque(VarHandle ob, Object obb, Object encl, long base, long offset) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, true); + static $type$ getOpaque(VarHandle ob, Object obb, long base) { + return getOpaque(ob, obb, base, ((SegmentVarHandle) ob).offset); + } + + @ForceInline + static $type$ getOpaque(VarHandle ob, Object obb, long base, long offset) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, true); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.get$RawType$Opaque(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask))); + offset(bb, base, offset))); } @ForceInline - static void setOpaque(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static void setOpaque(VarHandle ob, Object obb, long base, $type$ value) { + setOpaque(ob, obb, base, ((SegmentVarHandle) ob).offset, value); + } + + @ForceInline + static void setOpaque(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); SCOPED_MEMORY_ACCESS.put$RawType$Opaque(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), convEndian(handle.be, value)); } #if[CAS] @ForceInline - static boolean compareAndSet(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static boolean compareAndSet(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) { + return compareAndSet(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value); + } + + @ForceInline + static boolean compareAndSet(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); return SCOPED_MEMORY_ACCESS.compareAndSet$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), convEndian(handle.be, expected), convEndian(handle.be, value)); } @ForceInline - static $type$ compareAndExchange(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ compareAndExchange(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) { + return compareAndExchange(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value); + } + + @ForceInline + static $type$ compareAndExchange(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), convEndian(handle.be, expected), convEndian(handle.be, value))); } @ForceInline - static $type$ compareAndExchangeAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ compareAndExchangeAcquire(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) { + return compareAndExchangeAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value); + } + + @ForceInline + static $type$ compareAndExchangeAcquire(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), convEndian(handle.be, expected), convEndian(handle.be, value))); } @ForceInline - static $type$ compareAndExchangeRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ compareAndExchangeRelease(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) { + return compareAndExchangeRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value); + } + + @ForceInline + static $type$ compareAndExchangeRelease(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), convEndian(handle.be, expected), convEndian(handle.be, value))); } @ForceInline - static boolean weakCompareAndSetPlain(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static boolean weakCompareAndSetPlain(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) { + return weakCompareAndSetPlain(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value); + } + + @ForceInline + static boolean weakCompareAndSetPlain(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Plain(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), convEndian(handle.be, expected), convEndian(handle.be, value)); } @ForceInline - static boolean weakCompareAndSet(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static boolean weakCompareAndSet(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) { + return weakCompareAndSet(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value); + } + + @ForceInline + static boolean weakCompareAndSet(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), convEndian(handle.be, expected), convEndian(handle.be, value)); } @ForceInline - static boolean weakCompareAndSetAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static boolean weakCompareAndSetAcquire(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) { + return weakCompareAndSetAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value); + } + + @ForceInline + static boolean weakCompareAndSetAcquire(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), convEndian(handle.be, expected), convEndian(handle.be, value)); } @ForceInline - static boolean weakCompareAndSetRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static boolean weakCompareAndSetRelease(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) { + return weakCompareAndSetRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value); + } + + @ForceInline + static boolean weakCompareAndSetRelease(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), convEndian(handle.be, expected), convEndian(handle.be, value)); } @ForceInline - static $type$ getAndSet(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndSet(VarHandle ob, Object obb, long base, $type$ value) { + return getAndSet(ob, obb, base, ((SegmentVarHandle) ob).offset, value); + } + + @ForceInline + static $type$ getAndSet(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.getAndSet$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), convEndian(handle.be, value))); } @ForceInline - static $type$ getAndSetAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndSetAcquire(VarHandle ob, Object obb, long base, $type$ value) { + return getAndSetAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value); + } + + @ForceInline + static $type$ getAndSetAcquire(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.getAndSet$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), convEndian(handle.be, value))); } @ForceInline - static $type$ getAndSetRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndSetRelease(VarHandle ob, Object obb, long base, $type$ value) { + return getAndSetRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value); + } + + @ForceInline + static $type$ getAndSetRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); return convEndian(handle.be, SCOPED_MEMORY_ACCESS.getAndSet$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), convEndian(handle.be, value))); } #end[CAS] #if[AtomicAdd] @ForceInline - static $type$ getAndAdd(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ delta) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndAdd(VarHandle ob, Object obb, long base, $type$ value) { + return getAndAdd(ob, obb, base, ((SegmentVarHandle) ob).offset, value); + } + + @ForceInline + static $type$ getAndAdd(VarHandle ob, Object obb, long base, long offset, $type$ delta) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); +#if[!byte] if (handle.be == BE) { +#end[byte] return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), delta); +#if[!byte] } else { - return getAndAddConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), delta); + return getAndAddConvEndianWithCAS(bb, offset(bb, base, offset), delta); } +#end[byte] } @ForceInline - static $type$ getAndAddAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ delta) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndAddAcquire(VarHandle ob, Object obb, long base, $type$ value) { + return getAndAddAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value); + } + + @ForceInline + static $type$ getAndAddAcquire(VarHandle ob, Object obb, long base, long offset, $type$ delta) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); +#if[!byte] if (handle.be == BE) { +#end[byte] return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), delta); +#if[!byte] } else { - return getAndAddConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), delta); + return getAndAddConvEndianWithCAS(bb, offset(bb, base, offset), delta); } +#end[byte] + } + + @ForceInline + static $type$ getAndAddRelease(VarHandle ob, Object obb, long base, $type$ value) { + return getAndAddRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value); } @ForceInline - static $type$ getAndAddRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ delta) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndAddRelease(VarHandle ob, Object obb, long base, long offset, $type$ delta) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); +#if[!byte] if (handle.be == BE) { +#end[byte] return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), delta); +#if[!byte] } else { - return getAndAddConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), delta); + return getAndAddConvEndianWithCAS(bb, offset(bb, base, offset), delta); } +#end[byte] } +#if[!byte] @ForceInline static $type$ getAndAddConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ delta) { @@ -398,53 +493,82 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset); expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue); } while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset, - nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta))); + nativeExpectedValue, $RawBoxType$.reverseBytes({#if[ShorterThanInt]?($type$) }(expectedValue + delta)))); return expectedValue; } +#end[byte] #end[AtomicAdd] #if[Bitwise] @ForceInline - static $type$ getAndBitwiseOr(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndBitwiseOr(VarHandle ob, Object obb, long base, $type$ value) { + return getAndBitwiseOr(ob, obb, base, ((SegmentVarHandle) ob).offset, value); + } + + @ForceInline + static $type$ getAndBitwiseOr(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); +#if[!byte] if (handle.be == BE) { +#end[byte] return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), value); +#if[!byte] } else { - return getAndBitwiseOrConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value); + return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, offset), value); } +#end[byte] + } + + @ForceInline + static $type$ getAndBitwiseOrRelease(VarHandle ob, Object obb, long base, $type$ value) { + return getAndBitwiseOrRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value); } @ForceInline - static $type$ getAndBitwiseOrRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndBitwiseOrRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); +#if[!byte] if (handle.be == BE) { +#end[byte] return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), value); +#if[!byte] } else { - return getAndBitwiseOrConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value); + return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, offset), value); } +#end[byte] + } + + @ForceInline + static $type$ getAndBitwiseOrAcquire(VarHandle ob, Object obb, long base, $type$ value) { + return getAndBitwiseOrAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value); } @ForceInline - static $type$ getAndBitwiseOrAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndBitwiseOrAcquire(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); +#if[!byte] if (handle.be == BE) { +#end[byte] return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), value); +#if[!byte] } else { - return getAndBitwiseOrConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value); + return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, offset), value); } +#end[byte] } +#if[!byte] @ForceInline static $type$ getAndBitwiseOrConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ value) { @@ -454,51 +578,81 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset); expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue); } while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset, - nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue | value))); + nativeExpectedValue, $RawBoxType$.reverseBytes({#if[ShorterThanInt]?($type$) }(expectedValue | value)))); return expectedValue; } +#end[byte] + + @ForceInline + static $type$ getAndBitwiseAnd(VarHandle ob, Object obb, long base, $type$ value) { + return getAndBitwiseAnd(ob, obb, base, ((SegmentVarHandle) ob).offset, value); + } @ForceInline - static $type$ getAndBitwiseAnd(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndBitwiseAnd(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); +#if[!byte] if (handle.be == BE) { +#end[byte] return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), value); +#if[!byte] } else { - return getAndBitwiseAndConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value); + return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, offset), value); } +#end[byte] + } + + @ForceInline + static $type$ getAndBitwiseAndRelease(VarHandle ob, Object obb, long base, $type$ value) { + return getAndBitwiseAndRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value); } @ForceInline - static $type$ getAndBitwiseAndRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndBitwiseAndRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); +#if[!byte] if (handle.be == BE) { +#end[byte] return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), value); +#if[!byte] } else { - return getAndBitwiseAndConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value); + return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, offset), value); } +#end[byte] + } + + @ForceInline + static $type$ getAndBitwiseAndAcquire(VarHandle ob, Object obb, long base, $type$ value) { + return getAndBitwiseAndAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value); } + @ForceInline - static $type$ getAndBitwiseAndAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndBitwiseAndAcquire(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); +#if[!byte] if (handle.be == BE) { +#end[byte] return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), value); +#if[!byte] } else { - return getAndBitwiseAndConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value); + return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, offset), value); } +#end[byte] } +#if[!byte] @ForceInline static $type$ getAndBitwiseAndConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ value) { @@ -508,52 +662,80 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset); expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue); } while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset, - nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue & value))); + nativeExpectedValue, $RawBoxType$.reverseBytes({#if[ShorterThanInt]?($type$) }(expectedValue & value)))); return expectedValue; } +#end[byte] + @ForceInline + static $type$ getAndBitwiseXor(VarHandle ob, Object obb, long base, $type$ value) { + return getAndBitwiseXor(ob, obb, base, ((SegmentVarHandle) ob).offset, value); + } @ForceInline - static $type$ getAndBitwiseXor(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndBitwiseXor(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); +#if[!byte] if (handle.be == BE) { +#end[byte] return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), value); +#if[!byte] } else { - return getAndBitwiseXorConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value); + return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, offset), value); } +#end[byte] } @ForceInline - static $type$ getAndBitwiseXorRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndBitwiseXorRelease(VarHandle ob, Object obb, long base, $type$ value) { + return getAndBitwiseXorRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value); + } + + @ForceInline + static $type$ getAndBitwiseXorRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); +#if[!byte] if (handle.be == BE) { +#end[byte] return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), value); +#if[!byte] } else { - return getAndBitwiseXorConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value); + return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, offset), value); } +#end[byte] } @ForceInline - static $type$ getAndBitwiseXorAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) { - VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob; - AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false); + static $type$ getAndBitwiseXorAcquire(VarHandle ob, Object obb, long base, $type$ value) { + return getAndBitwiseXorAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value); + } + + @ForceInline + static $type$ getAndBitwiseXorAcquire(VarHandle ob, Object obb, long base, long offset, $type$ value) { + SegmentVarHandle handle = (SegmentVarHandle)ob; + AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false); +#if[!byte] if (handle.be == BE) { +#end[byte] return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNonPlain(bb, base, offset, handle.alignmentMask), + offset(bb, base, offset), value); +#if[!byte] } else { - return getAndBitwiseXorConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value); + return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, offset), value); } +#end[byte] } +#if[!byte] @ForceInline static $type$ getAndBitwiseXorConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ value) { @@ -563,8 +745,9 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset); expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue); } while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset, - nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue ^ value))); + nativeExpectedValue, $RawBoxType$.reverseBytes({#if[ShorterThanInt]?($type$) }(expectedValue ^ value)))); return expectedValue; } +#end[byte] #end[Bitwise] } diff --git a/src/java.base/share/classes/java/lang/reflect/Constructor.java b/src/java.base/share/classes/java/lang/reflect/Constructor.java index 30445307369..d072971307c 100644 --- a/src/java.base/share/classes/java/lang/reflect/Constructor.java +++ b/src/java.base/share/classes/java/lang/reflect/Constructor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, 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 @@ -240,7 +240,7 @@ public int getModifiers() { * @since 1.5 */ @Override - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings("unchecked") public TypeVariable<Constructor<T>>[] getTypeParameters() { if (getSignature() != null) { return (TypeVariable<Constructor<T>>[])getGenericInfo().getTypeParameters(); diff --git a/src/java.base/share/classes/java/lang/reflect/Method.java b/src/java.base/share/classes/java/lang/reflect/Method.java index f1d5ee63919..07616206075 100644 --- a/src/java.base/share/classes/java/lang/reflect/Method.java +++ b/src/java.base/share/classes/java/lang/reflect/Method.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, 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 @@ -231,7 +231,7 @@ public int getModifiers() { * @jls 8.4.4 Generic Methods */ @Override - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings("unchecked") public TypeVariable<Method>[] getTypeParameters() { if (getGenericSignature() != null) return (TypeVariable<Method>[])getGenericInfo().getTypeParameters(); diff --git a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java index d7d4258cc82..08bb6781896 100644 --- a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java +++ b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, 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 @@ -202,7 +202,6 @@ private ProxyGenerator(String className, List<Class<?>> interfaces, * @param interfaces proxy interfaces * @param accessFlags access flags of the proxy class */ - @SuppressWarnings("removal") static byte[] generateProxyClass(ClassLoader loader, final String name, List<Class<?>> interfaces, diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index 17d6eebbcb8..44a0a8e164c 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, 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 @@ -860,7 +860,10 @@ public static Path createTempFile(String prefix, * file-attributes} to set atomically when creating the directory. Each * attribute is identified by its {@link FileAttribute#name name}. If more * than one attribute of the same name is included in the array then all but - * the last occurrence is ignored. + * the last occurrence is ignored. When no file attributes are specified, + * then the resulting directory may have more restrictive access + * permissions to directories created by the + * {@linkplain Files#createDirectory(Path, FileAttribute<?>...)} method. * * @param dir * the path to directory in which to create the directory diff --git a/src/java.base/share/classes/java/text/DecimalFormat.java b/src/java.base/share/classes/java/text/DecimalFormat.java index b23c5f360bf..ce2ecfb23a2 100644 --- a/src/java.base/share/classes/java/text/DecimalFormat.java +++ b/src/java.base/share/classes/java/text/DecimalFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, 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,7 @@ import java.util.ArrayList; import java.util.Currency; import java.util.Locale; +import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -2811,9 +2812,11 @@ public String getPositivePrefix () { * Set the positive prefix. * <P>Examples: +123, $123, sFr123 * - * @param newValue the new positive prefix + * @param newValue the new positive prefix. Non-null. + * @throws NullPointerException if {@code newValue} is {@code null} */ public void setPositivePrefix (String newValue) { + Objects.requireNonNull(newValue, "prefix must not be null"); positivePrefix = newValue; posPrefixPattern = null; positivePrefixFieldPositions = null; @@ -2853,9 +2856,11 @@ public String getNegativePrefix () { * Set the negative prefix. * <P>Examples: -123, ($123) (with negative suffix), sFr-123 * - * @param newValue the new negative prefix + * @param newValue the new negative prefix. Non-null. + * @throws NullPointerException if {@code newValue} is {@code null} */ public void setNegativePrefix (String newValue) { + Objects.requireNonNull(newValue, "prefix must not be null"); negativePrefix = newValue; negPrefixPattern = null; fastPathCheckNeeded = true; @@ -2894,9 +2899,11 @@ public String getPositiveSuffix () { * Set the positive suffix. * <P>Example: 123% * - * @param newValue the new positive suffix + * @param newValue the new positive suffix. Non-null. + * @throws NullPointerException if {@code newValue} is {@code null} */ public void setPositiveSuffix (String newValue) { + Objects.requireNonNull(newValue, "suffix must not be null"); positiveSuffix = newValue; posSuffixPattern = null; fastPathCheckNeeded = true; @@ -2935,9 +2942,11 @@ public String getNegativeSuffix () { * Set the negative suffix. * <P>Examples: 123% * - * @param newValue the new negative suffix + * @param newValue the new negative suffix. Non-null. + * @throws NullPointerException if {@code newValue} is {@code null} */ public void setNegativeSuffix (String newValue) { + Objects.requireNonNull(newValue, "suffix must not be null"); negativeSuffix = newValue; negSuffixPattern = null; fastPathCheckNeeded = true; diff --git a/src/java.base/share/classes/java/text/NumberFormat.java b/src/java.base/share/classes/java/text/NumberFormat.java index e397d4ba15d..710c4e771ff 100644 --- a/src/java.base/share/classes/java/text/NumberFormat.java +++ b/src/java.base/share/classes/java/text/NumberFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, 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 @@ -883,14 +883,22 @@ public Object clone() { } /** - * Returns true if grouping is used in this format. For example, in the - * English locale, with grouping on, the number 1234567 might be formatted - * as "1,234,567". The grouping separator as well as the size of each group - * is locale dependent and is determined by sub-classes of NumberFormat. + * Returns true if grouping is used in this format. This applies to both + * formatting and parsing. The grouping separator as well as the size of each + * group is locale dependent and is determined by sub-classes of NumberFormat. + * For example, consider a {@code NumberFormat} that expects a "{@code ,}" + * grouping separator symbol with a grouping size of 3. + * <ul> + * <li> Formatting {@code 1234567} with grouping on returns {@code "1,234,567"} + * <li> Parsing {@code "1,234,567"} with grouping off returns {@code 1} + * <li> Parsing {@code "1,234,567"} with grouping off when {@link #isStrict()} + * returns {@code true} throws {@code ParseException} + * </ul> * * @return {@code true} if grouping is used; * {@code false} otherwise * @see #setGroupingUsed + * @see ##leniency Leniency Section */ public boolean isGroupingUsed() { return groupingUsed; @@ -898,6 +906,7 @@ public boolean isGroupingUsed() { /** * Set whether or not grouping will be used in this format. + * This applies to both formatting and parsing. * * @param newValue {@code true} if grouping is used; * {@code false} otherwise diff --git a/src/java.base/share/classes/java/time/chrono/ChronoLocalDate.java b/src/java.base/share/classes/java/time/chrono/ChronoLocalDate.java index 5543c8a73bc..3aae065715a 100644 --- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDate.java +++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -652,7 +652,6 @@ default String format(DateTimeFormatter formatter) { * @param localTime the local time to use, not null * @return the local date-time formed from this date and the specified time, not null */ - @SuppressWarnings("unchecked") default ChronoLocalDateTime<?> atTime(LocalTime localTime) { return ChronoLocalDateTimeImpl.of(this, localTime); } diff --git a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java index 412d4845456..5fcde7b2aad 100644 --- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java +++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -269,7 +269,6 @@ public long getLong(TemporalField field) { } //----------------------------------------------------------------------- - @SuppressWarnings("unchecked") @Override public ChronoLocalDateTimeImpl<D> with(TemporalAdjuster adjuster) { if (adjuster instanceof ChronoLocalDate) { diff --git a/src/java.base/share/classes/java/util/Arrays.java b/src/java.base/share/classes/java/util/Arrays.java index c59b8f04b0d..7d420a6e917 100644 --- a/src/java.base/share/classes/java/util/Arrays.java +++ b/src/java.base/share/classes/java/util/Arrays.java @@ -1127,7 +1127,7 @@ private static void legacyMergeSort(Object[] a, * off is the offset to generate corresponding low, high in src * To be removed in a future release. */ - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings("unchecked") private static void mergeSort(Object[] src, Object[] dest, int low, diff --git a/src/java.base/share/classes/java/util/Collections.java b/src/java.base/share/classes/java/util/Collections.java index ec08168e2a2..4dc7edeb852 100644 --- a/src/java.base/share/classes/java/util/Collections.java +++ b/src/java.base/share/classes/java/util/Collections.java @@ -3363,7 +3363,6 @@ static class CheckedCollection<E> implements Collection<E>, Serializable { @SuppressWarnings("serial") // Conditionally serializable final Collection<E> c; /** @serial */ - @SuppressWarnings("serial") // Conditionally serializable final Class<E> type; @SuppressWarnings("unchecked") @@ -3926,10 +3925,8 @@ private static class CheckedMap<K,V> @SuppressWarnings("serial") // Conditionally serializable private final Map<K, V> m; /** @serial */ - @SuppressWarnings("serial") // Conditionally serializable final Class<K> keyType; /** @serial */ - @SuppressWarnings("serial") // Conditionally serializable final Class<V> valueType; private void typeCheck(Object key, Object value) { diff --git a/src/java.base/share/classes/java/util/ComparableTimSort.java b/src/java.base/share/classes/java/util/ComparableTimSort.java index 7b908077224..ac2b1573152 100644 --- a/src/java.base/share/classes/java/util/ComparableTimSort.java +++ b/src/java.base/share/classes/java/util/ComparableTimSort.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright 2009 Google Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -309,7 +309,7 @@ private static void binarySort(Object[] a, int lo, int hi, int start) { * @return the length of the run beginning at the specified position in * the specified array */ - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings("unchecked") private static int countRunAndMakeAscending(Object[] a, int lo, int hi) { assert lo < hi; int runHi = lo + 1; @@ -648,7 +648,7 @@ private static int gallopRight(Comparable<Object> key, Object[] a, * (must be aBase + aLen) * @param len2 length of second run to be merged (must be > 0) */ - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings("unchecked") private void mergeLo(int base1, int len1, int base2, int len2) { assert len1 > 0 && len2 > 0 && base1 + len1 == base2; @@ -765,7 +765,7 @@ private void mergeLo(int base1, int len1, int base2, int len2) { * (must be aBase + aLen) * @param len2 length of second run to be merged (must be > 0) */ - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings("unchecked") private void mergeHi(int base1, int len1, int base2, int len2) { assert len1 > 0 && len2 > 0 && base1 + len1 == base2; @@ -895,7 +895,7 @@ private Object[] ensureCapacity(int minCapacity) { else newSize = Math.min(newSize, a.length >>> 1); - @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"}) + @SuppressWarnings("UnnecessaryLocalVariable") Object[] newArray = new Object[newSize]; tmp = newArray; tmpLen = newSize; diff --git a/src/java.base/share/classes/java/util/HashMap.java b/src/java.base/share/classes/java/util/HashMap.java index 46c89984be8..3320b394e6c 100644 --- a/src/java.base/share/classes/java/util/HashMap.java +++ b/src/java.base/share/classes/java/util/HashMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, 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 @@ -365,7 +365,7 @@ static Class<?> comparableClassFor(Object x) { * Returns k.compareTo(x) if x matches kc (k's screened comparable * class), else 0. */ - @SuppressWarnings({"rawtypes","unchecked"}) // for cast to Comparable + @SuppressWarnings("unchecked") // for cast to Comparable static int compareComparables(Class<?> kc, Object k, Object x) { return (x == null || x.getClass() != kc ? 0 : ((Comparable)k).compareTo(x)); diff --git a/src/java.base/share/classes/java/util/JapaneseImperialCalendar.java b/src/java.base/share/classes/java/util/JapaneseImperialCalendar.java index d275b09834a..755fe1133f5 100644 --- a/src/java.base/share/classes/java/util/JapaneseImperialCalendar.java +++ b/src/java.base/share/classes/java/util/JapaneseImperialCalendar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -1856,6 +1856,14 @@ protected void computeTime() { if (isSet(ERA)) { era = internalGet(ERA); + // Don't check under, historically we have allowed values under + // BEFORE_MEIJI to be ignored during normalization + // We check against eras.length (not the highest constant ERA value) + // due to future added eras, or additional eras via + // "jdk.calendar.japanese.supplemental.era" + if (era >= eras.length) { + throw new IllegalArgumentException("Invalid era"); + } year = isSet(YEAR) ? internalGet(YEAR) : 1; } else { if (isSet(YEAR)) { diff --git a/src/java.base/share/classes/java/util/LinkedHashSet.java b/src/java.base/share/classes/java/util/LinkedHashSet.java index bec2733dae3..1ec8214208d 100644 --- a/src/java.base/share/classes/java/util/LinkedHashSet.java +++ b/src/java.base/share/classes/java/util/LinkedHashSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, 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 @@ -226,7 +226,6 @@ public static <T> LinkedHashSet<T> newLinkedHashSet(int numElements) { return new LinkedHashSet<>(HashMap.calculateHashMapCapacity(numElements)); } - @SuppressWarnings("unchecked") LinkedHashMap<E, Object> map() { return (LinkedHashMap<E, Object>) map; } diff --git a/src/java.base/share/classes/java/util/List.java b/src/java.base/share/classes/java/util/List.java index 86cf4267312..32430298363 100644 --- a/src/java.base/share/classes/java/util/List.java +++ b/src/java.base/share/classes/java/util/List.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, 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 @@ -501,7 +501,7 @@ default void replaceAll(UnaryOperator<E> operator) { * contract * @since 1.8 */ - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings("unchecked") default void sort(Comparator<? super E> c) { Object[] a = this.toArray(); Arrays.sort(a, (Comparator) c); diff --git a/src/java.base/share/classes/java/util/Map.java b/src/java.base/share/classes/java/util/Map.java index ea2fd4e1807..fbb41be5073 100644 --- a/src/java.base/share/classes/java/util/Map.java +++ b/src/java.base/share/classes/java/util/Map.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, 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 @@ -1658,7 +1658,6 @@ static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, * @since 9 */ @SafeVarargs - @SuppressWarnings("varargs") static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) { if (entries.length == 0) { // implicit null check of entries array @SuppressWarnings("unchecked") diff --git a/src/java.base/share/classes/java/util/PrimitiveIterator.java b/src/java.base/share/classes/java/util/PrimitiveIterator.java index b0e07ef6e5a..db6f1bcf483 100644 --- a/src/java.base/share/classes/java/util/PrimitiveIterator.java +++ b/src/java.base/share/classes/java/util/PrimitiveIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,7 +84,6 @@ public interface PrimitiveIterator<T, T_CONS> extends Iterator<T> { * @param action The action to be performed for each element * @throws NullPointerException if the specified action is null */ - @SuppressWarnings("overloads") void forEachRemaining(T_CONS action); /** diff --git a/src/java.base/share/classes/java/util/PropertyResourceBundle.java b/src/java.base/share/classes/java/util/PropertyResourceBundle.java index aba65cbcd88..d8cc1fac198 100644 --- a/src/java.base/share/classes/java/util/PropertyResourceBundle.java +++ b/src/java.base/share/classes/java/util/PropertyResourceBundle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, 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 @@ -163,7 +163,6 @@ public class PropertyResourceBundle extends ResourceBundle { * {@code java.util.PropertyResourceBundle.encoding} is set to "UTF-8" * and {@code stream} contains an unmappable UTF-8 byte sequence. */ - @SuppressWarnings({"unchecked", "rawtypes"}) public PropertyResourceBundle (InputStream stream) throws IOException { this(new InputStreamReader(stream, "ISO-8859-1".equals(encoding) ? diff --git a/src/java.base/share/classes/java/util/ResourceBundle.java b/src/java.base/share/classes/java/util/ResourceBundle.java index 4206dda6a3a..fb88a38903a 100644 --- a/src/java.base/share/classes/java/util/ResourceBundle.java +++ b/src/java.base/share/classes/java/util/ResourceBundle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, 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 @@ -3511,7 +3511,6 @@ private static class ResourceBundleProviderHelper { */ static ResourceBundle newResourceBundle(Class<? extends ResourceBundle> bundleClass) { try { - @SuppressWarnings("unchecked") Constructor<? extends ResourceBundle> ctor = bundleClass.getConstructor(); if (!Modifier.isPublic(ctor.getModifiers())) { diff --git a/src/java.base/share/classes/java/util/ReverseOrderDequeView.java b/src/java.base/share/classes/java/util/ReverseOrderDequeView.java index 695db6a74dc..35e34c4d80b 100644 --- a/src/java.base/share/classes/java/util/ReverseOrderDequeView.java +++ b/src/java.base/share/classes/java/util/ReverseOrderDequeView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, 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 @@ -161,7 +161,6 @@ public Object[] toArray() { return ArraysSupport.reverse(base.toArray()); } - @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { return ArraysSupport.toArrayReversed(base, a); } diff --git a/src/java.base/share/classes/java/util/ReverseOrderListView.java b/src/java.base/share/classes/java/util/ReverseOrderListView.java index 42b57e2d8b9..f48b41920c9 100644 --- a/src/java.base/share/classes/java/util/ReverseOrderListView.java +++ b/src/java.base/share/classes/java/util/ReverseOrderListView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, 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 @@ -286,7 +286,6 @@ public Object[] toArray() { return ArraysSupport.reverse(base.toArray()); } - @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { return ArraysSupport.toArrayReversed(base, a); } diff --git a/src/java.base/share/classes/java/util/ReverseOrderSortedMapView.java b/src/java.base/share/classes/java/util/ReverseOrderSortedMapView.java index 404950e8fd5..74703f3a866 100644 --- a/src/java.base/share/classes/java/util/ReverseOrderSortedMapView.java +++ b/src/java.base/share/classes/java/util/ReverseOrderSortedMapView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, 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 @@ -314,7 +314,6 @@ class Submap extends AbstractMap<K, V> implements SortedMap<K, V> { final K head; // head key, or negative infinity if null final K tail; // tail key, or positive infinity if null - @SuppressWarnings("unchecked") Submap(K head, K tail) { this.head = head; this.tail = tail; diff --git a/src/java.base/share/classes/java/util/ReverseOrderSortedSetView.java b/src/java.base/share/classes/java/util/ReverseOrderSortedSetView.java index 3719852e2a5..70511c8ae86 100644 --- a/src/java.base/share/classes/java/util/ReverseOrderSortedSetView.java +++ b/src/java.base/share/classes/java/util/ReverseOrderSortedSetView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, 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 @@ -170,7 +170,6 @@ public Object[] toArray() { return ArraysSupport.reverse(base.toArray()); } - @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { return ArraysSupport.toArrayReversed(base, a); } diff --git a/src/java.base/share/classes/java/util/ServiceLoader.java b/src/java.base/share/classes/java/util/ServiceLoader.java index c634d6321c0..5137adc1c08 100644 --- a/src/java.base/share/classes/java/util/ServiceLoader.java +++ b/src/java.base/share/classes/java/util/ServiceLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -726,7 +726,7 @@ public int hashCode() { @Override public boolean equals(Object ob) { - return ob instanceof @SuppressWarnings("unchecked")ProviderImpl<?> that + return ob instanceof ProviderImpl<?> that && this.service == that.service && this.type == that.type; } diff --git a/src/java.base/share/classes/java/util/Spliterator.java b/src/java.base/share/classes/java/util/Spliterator.java index 517d71c191b..6873bca6568 100644 --- a/src/java.base/share/classes/java/util/Spliterator.java +++ b/src/java.base/share/classes/java/util/Spliterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, 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 @@ -628,7 +628,6 @@ public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive * upon entry to this method, else {@code true}. * @throws NullPointerException if the specified action is null */ - @SuppressWarnings("overloads") boolean tryAdvance(T_CONS action); /** @@ -649,7 +648,6 @@ public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive * @param action The action * @throws NullPointerException if the specified action is null */ - @SuppressWarnings("overloads") default void forEachRemaining(T_CONS action) { do { } while (tryAdvance(action)); } diff --git a/src/java.base/share/classes/java/util/TreeMap.java b/src/java.base/share/classes/java/util/TreeMap.java index ab565f371a9..f8eea8c8d8f 100644 --- a/src/java.base/share/classes/java/util/TreeMap.java +++ b/src/java.base/share/classes/java/util/TreeMap.java @@ -2982,7 +2982,7 @@ static <K> Spliterator<K> keySpliteratorFor(NavigableMap<K,?> m) { return t.keySpliterator(); } if (m instanceof DescendingSubMap) { - @SuppressWarnings("unchecked") DescendingSubMap<K,?> dm = + DescendingSubMap<K,?> dm = (DescendingSubMap<K,?>) m; TreeMap<K,?> tm = dm.m; if (dm == tm.descendingMap) { @@ -2991,7 +2991,7 @@ static <K> Spliterator<K> keySpliteratorFor(NavigableMap<K,?> m) { return t.descendingKeySpliterator(); } } - @SuppressWarnings("unchecked") NavigableSubMap<K,?> sm = + NavigableSubMap<K,?> sm = (NavigableSubMap<K,?>) m; return sm.keySpliterator(); } diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java index b0818d3da6e..8734980cf80 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -744,7 +744,7 @@ static Class<?> comparableClassFor(Object x) { * Returns k.compareTo(x) if x matches kc (k's screened comparable * class), else 0. */ - @SuppressWarnings({"rawtypes","unchecked"}) // for cast to Comparable + @SuppressWarnings("unchecked") // for cast to Comparable static int compareComparables(Class<?> kc, Object k, Object x) { return (x == null || x.getClass() != kc ? 0 : ((Comparable)k).compareTo(x)); diff --git a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java index f5069c61d45..2d3bdb429e9 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -1727,7 +1727,6 @@ public void add(E e) { } @Override - @SuppressWarnings("unchecked") public void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); while (hasNext()) { diff --git a/src/java.base/share/classes/java/util/concurrent/Executors.java b/src/java.base/share/classes/java/util/concurrent/Executors.java index 49cf497c20b..ba7c2e1efee 100644 --- a/src/java.base/share/classes/java/util/concurrent/Executors.java +++ b/src/java.base/share/classes/java/util/concurrent/Executors.java @@ -576,10 +576,8 @@ public String toString() { private static final class PrivilegedCallableUsingCurrentClassLoader<T> implements Callable<T> { final Callable<T> task; - @SuppressWarnings("removal") final ClassLoader ccl; - @SuppressWarnings("removal") PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) { this.task = task; this.ccl = Thread.currentThread().getContextClassLoader(); @@ -637,7 +635,6 @@ public Thread newThread(Runnable r) { * Thread factory capturing the current class loader. */ private static class PrivilegedThreadFactory extends DefaultThreadFactory { - @SuppressWarnings("removal") final ClassLoader ccl; PrivilegedThreadFactory() { @@ -647,7 +644,6 @@ private static class PrivilegedThreadFactory extends DefaultThreadFactory { public Thread newThread(final Runnable r) { return super.newThread(new Runnable() { - @SuppressWarnings("removal") public void run() { Thread.currentThread().setContextClassLoader(ccl); r.run(); diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java index 6062a0f6455..ec91e33975d 100644 --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java @@ -787,7 +787,6 @@ public static <T extends ForkJoinTask<?>> Collection<T> invokeAll(Collection<T> invokeAll(tasks.toArray(new ForkJoinTask<?>[0])); return tasks; } - @SuppressWarnings("unchecked") List<? extends ForkJoinTask<?>> ts = (List<? extends ForkJoinTask<?>>) tasks; Throwable ex = null; diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java index b22786a09f6..7c112eb8008 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -910,7 +910,6 @@ public boolean addAll(Collection<? extends E> c) { * * @return an array containing all of the elements in this deque */ - @SuppressWarnings("unchecked") public Object[] toArray() { final ReentrantLock lock = this.lock; lock.lock(); diff --git a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java index a2fc3ac92bd..388241b115d 100644 --- a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java +++ b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java @@ -1048,7 +1048,6 @@ public final void setRawResult(Void v) {} * assignment coding style. Also, all methods and fields have * default visibility to simplify usage by callers. */ - @SuppressWarnings("serial") @jdk.internal.vm.annotation.Contended static final class BufferedSubscription<T> implements Subscription, ForkJoinPool.ManagedBlocker { diff --git a/src/java.base/share/classes/java/util/regex/Pattern.java b/src/java.base/share/classes/java/util/regex/Pattern.java index 654adb5376f..b7f03c1b0af 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, 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 @@ -3369,7 +3369,6 @@ private void addFlag() { * Parses the second part of inlined match flags and turns off * flags appropriately. */ - @SuppressWarnings("fallthrough") private void subFlag() { int ch = peek(); for (;;) { diff --git a/src/java.base/share/classes/java/util/stream/AbstractPipeline.java b/src/java.base/share/classes/java/util/stream/AbstractPipeline.java index 8afe5083cc7..68d127e511a 100644 --- a/src/java.base/share/classes/java/util/stream/AbstractPipeline.java +++ b/src/java.base/share/classes/java/util/stream/AbstractPipeline.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -578,7 +578,7 @@ final <P_IN> void copyInto(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator @Override @SuppressWarnings("unchecked") final <P_IN> boolean copyIntoWithCancel(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) { - @SuppressWarnings({"rawtypes","unchecked"}) + @SuppressWarnings("rawtypes") AbstractPipeline p = AbstractPipeline.this; while (p.depth > 0) { p = p.previousStage; @@ -622,7 +622,6 @@ final <P_IN> Spliterator<E_OUT> wrapSpliterator(Spliterator<P_IN> sourceSplitera } @Override - @SuppressWarnings("unchecked") final <P_IN> Node<E_OUT> evaluate(Spliterator<P_IN> spliterator, boolean flatten, IntFunction<E_OUT[]> generator) { @@ -790,7 +789,6 @@ <P_IN> Node<E_OUT> opEvaluateParallel(PipelineHelper<E_OUT> helper, * @param spliterator the source {@code Spliterator} * @return a {@code Spliterator} describing the result of the evaluation */ - @SuppressWarnings("unchecked") <P_IN> Spliterator<E_OUT> opEvaluateParallelLazy(PipelineHelper<E_OUT> helper, Spliterator<P_IN> spliterator) { return opEvaluateParallel(helper, spliterator, Nodes.castingArray()).spliterator(); diff --git a/src/java.base/share/classes/java/util/stream/DoublePipeline.java b/src/java.base/share/classes/java/util/stream/DoublePipeline.java index 22b3bf67ef4..ea561d8507f 100644 --- a/src/java.base/share/classes/java/util/stream/DoublePipeline.java +++ b/src/java.base/share/classes/java/util/stream/DoublePipeline.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, 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 @@ -324,7 +324,6 @@ public void begin(long size) { } @Override - @SuppressWarnings("unchecked") public void accept(double t) { mapper.accept(t, (DoubleConsumer) downstream); } diff --git a/src/java.base/share/classes/java/util/stream/IntPipeline.java b/src/java.base/share/classes/java/util/stream/IntPipeline.java index e78bc9fecc9..5c624e2fc42 100644 --- a/src/java.base/share/classes/java/util/stream/IntPipeline.java +++ b/src/java.base/share/classes/java/util/stream/IntPipeline.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -356,7 +356,6 @@ public void begin(long size) { } @Override - @SuppressWarnings("unchecked") public void accept(int t) { mapper.accept(t, (IntConsumer) downstream); } diff --git a/src/java.base/share/classes/java/util/stream/LongPipeline.java b/src/java.base/share/classes/java/util/stream/LongPipeline.java index c8c296824ed..05d6d506bea 100644 --- a/src/java.base/share/classes/java/util/stream/LongPipeline.java +++ b/src/java.base/share/classes/java/util/stream/LongPipeline.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, 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 @@ -339,7 +339,6 @@ public void begin(long size) { } @Override - @SuppressWarnings("unchecked") public void accept(long t) { mapper.accept(t, (LongConsumer) downstream); } diff --git a/src/java.base/share/classes/java/util/stream/Node.java b/src/java.base/share/classes/java/util/stream/Node.java index 0f88850cfc5..d8308d778d9 100644 --- a/src/java.base/share/classes/java/util/stream/Node.java +++ b/src/java.base/share/classes/java/util/stream/Node.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -245,7 +245,6 @@ public interface OfPrimitive<T, T_CONS, T_ARR, * @param action a consumer that is to be invoked with each * element in this {@code Node.OfPrimitive} */ - @SuppressWarnings("overloads") void forEach(T_CONS action); @Override diff --git a/src/java.base/share/classes/java/util/stream/Nodes.java b/src/java.base/share/classes/java/util/stream/Nodes.java index 77d70091717..d2627434f36 100644 --- a/src/java.base/share/classes/java/util/stream/Nodes.java +++ b/src/java.base/share/classes/java/util/stream/Nodes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -643,7 +643,6 @@ private static class ArrayNode<T> implements Node<T> { final T[] array; int curSize; - @SuppressWarnings("unchecked") ArrayNode(long size, IntFunction<T[]> generator) { if (size >= MAX_ARRAY_SIZE) throw new IllegalArgumentException(BAD_SIZE); @@ -720,7 +719,6 @@ public void copyInto(T[] array, int offset) { } @Override - @SuppressWarnings("unchecked") public T[] asArray(IntFunction<T[]> generator) { return c.toArray(generator.apply(c.size())); } diff --git a/src/java.base/share/classes/java/util/stream/ReferencePipeline.java b/src/java.base/share/classes/java/util/stream/ReferencePipeline.java index 3133b20b03d..3699990a326 100644 --- a/src/java.base/share/classes/java/util/stream/ReferencePipeline.java +++ b/src/java.base/share/classes/java/util/stream/ReferencePipeline.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -202,7 +202,6 @@ public void accept(P_OUT u) { } @Override - @SuppressWarnings("unchecked") public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) { Objects.requireNonNull(mapper); return new StatelessOp<>(this, StreamShape.REFERENCE, @@ -509,7 +508,6 @@ public void begin(long size) { } @Override - @SuppressWarnings("unchecked") public void accept(P_OUT u) { mapper.accept(u, (IntConsumer)downstream); } @@ -533,7 +531,6 @@ public void begin(long size) { } @Override - @SuppressWarnings("unchecked") public void accept(P_OUT u) { mapper.accept(u, (LongConsumer) downstream); } @@ -558,7 +555,6 @@ public void begin(long size) { } @Override - @SuppressWarnings("unchecked") public void accept(P_OUT u) { mapper.accept(u, (DoubleConsumer) downstream); } diff --git a/src/java.base/share/classes/java/util/stream/SpinedBuffer.java b/src/java.base/share/classes/java/util/stream/SpinedBuffer.java index 98bbc040a7b..cb9eb24d635 100644 --- a/src/java.base/share/classes/java/util/stream/SpinedBuffer.java +++ b/src/java.base/share/classes/java/util/stream/SpinedBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -583,7 +583,6 @@ public void clear() { spineIndex = 0; } - @SuppressWarnings("overloads") public void forEach(T_CONS consumer) { // completed chunks, if any for (int j = 0; j < spineIndex; j++) diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java index 0caf66bbc42..5c5d2e33c7d 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ import jdk.internal.foreign.abi.NativeEntryPoint; +import java.lang.foreign.MemoryLayout; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; import java.lang.reflect.Constructor; @@ -81,7 +81,7 @@ public interface JavaLangInvokeAccess { * Used by {@code jdk.internal.foreign.LayoutPath} and * {@code java.lang.invoke.MethodHandles}. */ - VarHandle memorySegmentViewHandle(Class<?> carrier, long alignmentMask, ByteOrder order); + VarHandle memorySegmentViewHandle(Class<?> carrier, MemoryLayout enclosing, long alignmentMask, ByteOrder order, boolean constantOffset, long offset); /** * Var handle carrier combinator. diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassFileImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassFileImpl.java index 3ab5d24f09c..152569683ba 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassFileImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassFileImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,7 +90,6 @@ private ClassFileImpl(Option stackMapsOption, null // _ -> null ); - @SuppressWarnings("unchecked") @Override public ClassFileImpl withOptions(Option... options) { var smo = stackMapsOption; diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java index 54222764f8d..8bca5415384 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java @@ -272,7 +272,6 @@ private void inflateJumpTargets() { } return; } - @SuppressWarnings("unchecked") int stackMapPos = ((BoundAttribute<StackMapTableAttribute>) a.get()).payloadStart; int bci = -1; //compensate for offsetDelta + 1 diff --git a/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java b/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java index 58552d44ea4..11407de93a9 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java +++ b/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java @@ -59,6 +59,7 @@ public class LayoutPath { private static final long[] EMPTY_STRIDES = new long[0]; private static final long[] EMPTY_BOUNDS = new long[0]; private static final MethodHandle[] EMPTY_DEREF_HANDLES = new MethodHandle[0]; + public static final MemoryLayout.PathElement[] EMPTY_PATH_ELEMENTS = new MemoryLayout.PathElement[0]; private static final MethodHandle MH_ADD_SCALED_OFFSET; private static final MethodHandle MH_SLICE; @@ -205,15 +206,13 @@ public VarHandle dereferenceHandle(boolean adapt) { String.format("Path does not select a value layout: %s", breadcrumbs())); } - VarHandle handle = Utils.makeRawSegmentViewVarHandle(valueLayout); // (MS, ML, long, long) - handle = MethodHandles.insertCoordinates(handle, 1, rootLayout()); // (MS, long, long) - if (strides.length > 0) { - MethodHandle offsetAdapter = offsetHandle(); + boolean constantOffset = strides.length == 0; + // (MS, long, long) if variable offset, (MS, long) if constant offset + VarHandle handle = Utils.makeRawSegmentViewVarHandle(rootLayout(), valueLayout, constantOffset, offset); + if (!constantOffset) { + MethodHandle offsetAdapter = offsetHandle(); // Adapter performs the bound checks offsetAdapter = MethodHandles.insertArguments(offsetAdapter, 0, 0L); handle = MethodHandles.collectCoordinates(handle, 2, offsetAdapter); // (MS, long) - } else { - // simpler adaptation - handle = MethodHandles.insertCoordinates(handle, 2, offset); // (MS, long) } if (adapt) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/Utils.java b/src/java.base/share/classes/jdk/internal/foreign/Utils.java index 391a46c092c..4214b0395b8 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/Utils.java +++ b/src/java.base/share/classes/jdk/internal/foreign/Utils.java @@ -1,27 +1,26 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * Copyright (c) 2019, 2025, 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 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). + * 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. + * 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.foreign; @@ -34,7 +33,6 @@ import java.lang.foreign.AddressLayout; import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemoryLayout.PathElement; import java.lang.foreign.MemorySegment; import java.lang.foreign.StructLayout; import java.lang.foreign.ValueLayout; @@ -46,6 +44,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; import java.util.function.Supplier; /** @@ -56,25 +55,31 @@ public final class Utils { // Suppresses default constructor, ensuring non-instantiability. private Utils() {} - private static final MethodHandle BYTE_TO_BOOL; - private static final MethodHandle BOOL_TO_BYTE; - private static final MethodHandle ADDRESS_TO_LONG; + private static final Class<?> ADDRESS_CARRIER_TYPE; + private static final MethodHandle LONG_TO_CARRIER; private static final MethodHandle LONG_TO_ADDRESS_TARGET; private static final MethodHandle LONG_TO_ADDRESS_NO_TARGET; static { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + String unboxSegmentName; + Class<?> rawAddressType; + if (Unsafe.getUnsafe().addressSize() == 8) { + unboxSegmentName = "unboxSegment"; + rawAddressType = long.class; + } else { + assert Unsafe.getUnsafe().addressSize() == 4 : Unsafe.getUnsafe().addressSize(); + unboxSegmentName = "unboxSegment32"; + rawAddressType = int.class; + } + ADDRESS_CARRIER_TYPE = rawAddressType; try { - MethodHandles.Lookup lookup = MethodHandles.lookup(); - BYTE_TO_BOOL = lookup.findStatic(Utils.class, "byteToBoolean", - MethodType.methodType(boolean.class, byte.class)); - BOOL_TO_BYTE = lookup.findStatic(Utils.class, "booleanToByte", - MethodType.methodType(byte.class, boolean.class)); - ADDRESS_TO_LONG = lookup.findStatic(SharedUtils.class, "unboxSegment", - MethodType.methodType(long.class, MemorySegment.class)); + LONG_TO_CARRIER = lookup.findStatic(SharedUtils.class, unboxSegmentName, + MethodType.methodType(rawAddressType, MemorySegment.class)); LONG_TO_ADDRESS_TARGET = lookup.findStatic(Utils.class, "longToAddress", - MethodType.methodType(MemorySegment.class, long.class, AddressLayout.class)); + MethodType.methodType(MemorySegment.class, rawAddressType, AddressLayout.class)); LONG_TO_ADDRESS_NO_TARGET = lookup.findStatic(Utils.class, "longToAddress", - MethodType.methodType(MemorySegment.class, long.class)); + MethodType.methodType(MemorySegment.class, rawAddressType)); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } @@ -90,48 +95,57 @@ public static MemorySegment alignUp(MemorySegment ms, long alignment) { } /** - * This method returns a <em>raw var handle</em>, that is, a var handle that does not perform any size - * or alignment checks. Such checks are added (using adaptation) by {@link LayoutPath#dereferenceHandle()}. + * This method returns a var handle that accesses a target layout in an enclosing layout, taking the memory offset + * and the base offset of the enclosing layout in the segment. + * <p> + * If the offset of the target layout in the enclosing layout is constant, the coordinates are (MS, long). + * If the offset of the target layout in the enclosing layout is variable, the coordinates are (MS, long, long). + * The trailing long is a pre-validated, variable extra offset, which the var handle does not perform any size or + * alignment checks against. Such checks are added (using adaptation) by {@link LayoutPath#dereferenceHandle()}. * <p> * We provide two level of caching of the generated var handles. First, the var handle associated * with a {@link ValueLayout#varHandle()} call is cached inside a stable field of the value layout implementation. * This optimizes common code idioms like {@code JAVA_INT.varHandle().getInt(...)}. A second layer of caching - * is then provided by this method: after all, var handles constructed by {@link MemoryLayout#varHandle(PathElement...)} - * will be obtained by adapting some raw var handle generated by this method. + * is then provided by this method, so different value layouts with same effects can reuse var handle instances. + * (The 2nd layer may be redundant in the long run) * - * @param layout the value layout for which a raw memory segment var handle is to be created. - * @return a raw memory segment var handle. + * @param enclosing the enclosing context of the value layout + * @param layout the value layout for which a raw memory segment var handle is to be created + * @param constantOffset if the VH carries a constant offset instead of taking a variable offset + * @param offset the offset if it is a constant + * @return a raw memory segment var handle */ - public static VarHandle makeRawSegmentViewVarHandle(ValueLayout layout) { - final class VarHandleCache { - private static final Map<ValueLayout, VarHandle> HANDLE_MAP = new ConcurrentHashMap<>(); + public static VarHandle makeRawSegmentViewVarHandle(MemoryLayout enclosing, ValueLayout layout, boolean constantOffset, long offset) { + if (enclosing instanceof ValueLayout direct) { + assert direct.equals(layout) && constantOffset && offset == 0; + record VarHandleCache() implements Function<ValueLayout, VarHandle> { + private static final Map<ValueLayout, VarHandle> HANDLE_MAP = new ConcurrentHashMap<>(); + private static final VarHandleCache INSTANCE = new VarHandleCache(); + + @Override + public VarHandle apply(ValueLayout valueLayout) { + return Utils.makeRawSegmentViewVarHandleInternal(valueLayout, valueLayout, true, 0); + } + } + return VarHandleCache.HANDLE_MAP.computeIfAbsent(direct.withoutName(), VarHandleCache.INSTANCE); } - return VarHandleCache.HANDLE_MAP - .computeIfAbsent(layout.withoutName(), Utils::makeRawSegmentViewVarHandleInternal); + return makeRawSegmentViewVarHandleInternal(enclosing, layout, constantOffset, offset); } - private static VarHandle makeRawSegmentViewVarHandleInternal(ValueLayout layout) { + private static VarHandle makeRawSegmentViewVarHandleInternal(MemoryLayout enclosing, ValueLayout layout, boolean constantOffset, long offset) { Class<?> baseCarrier = layout.carrier(); if (layout.carrier() == MemorySegment.class) { - baseCarrier = switch ((int) ValueLayout.ADDRESS.byteSize()) { - case Long.BYTES -> long.class; - case Integer.BYTES -> int.class; - default -> throw new UnsupportedOperationException("Unsupported address layout"); - }; - } else if (layout.carrier() == boolean.class) { - baseCarrier = byte.class; + baseCarrier = ADDRESS_CARRIER_TYPE; } VarHandle handle = SharedSecrets.getJavaLangInvokeAccess().memorySegmentViewHandle(baseCarrier, - layout.byteAlignment() - 1, layout.order()); + enclosing, layout.byteAlignment() - 1, layout.order(), constantOffset, offset); - if (layout.carrier() == boolean.class) { - handle = MethodHandles.filterValue(handle, BOOL_TO_BYTE, BYTE_TO_BOOL); - } else if (layout instanceof AddressLayout addressLayout) { + if (layout instanceof AddressLayout addressLayout) { MethodHandle longToAddressAdapter = addressLayout.targetLayout().isPresent() ? MethodHandles.insertArguments(LONG_TO_ADDRESS_TARGET, 1, addressLayout) : LONG_TO_ADDRESS_NO_TARGET; - handle = MethodHandles.filterValue(handle, ADDRESS_TO_LONG, longToAddressAdapter); + handle = MethodHandles.filterValue(handle, LONG_TO_CARRIER, longToAddressAdapter); } return handle; } @@ -149,11 +163,23 @@ public static MemorySegment longToAddress(long addr) { return longToAddress(addr, 0, 1); } + // 32 bit + @ForceInline + public static MemorySegment longToAddress(int addr) { + return longToAddress(addr, 0, 1); + } + @ForceInline public static MemorySegment longToAddress(long addr, AddressLayout layout) { return longToAddress(addr, pointeeByteSize(layout), pointeeByteAlign(layout)); } + // 32 bit + @ForceInline + public static MemorySegment longToAddress(int addr, AddressLayout layout) { + return longToAddress(addr, pointeeByteSize(layout), pointeeByteAlign(layout)); + } + @ForceInline public static MemorySegment longToAddress(long addr, long size, long align) { if (!isAligned(addr, align)) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java index 9078920f677..17324894ac5 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java @@ -321,11 +321,20 @@ public static void checkNative(MemorySegment segment) { } } + @ForceInline public static long unboxSegment(MemorySegment segment) { checkNative(segment); return segment.address(); } + @ForceInline + public static int unboxSegment32(MemorySegment segment) { + // This cast to 'int' is safe, because we only call this method on 32-bit + // platforms, where we know the address of a segment is truncated to 32-bits. + // There's a similar cast for 4-byte addresses in Unsafe.putAddress. + return (int) unboxSegment(segment); + } + public static void checkExceptions(MethodHandle target) { Class<?>[] exceptions = JLIA.exceptionTypes(target); if (exceptions != null && exceptions.length != 0) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java b/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java index e546773c429..685b95691ba 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ */ package jdk.internal.foreign.layout; +import jdk.internal.foreign.LayoutPath; import jdk.internal.foreign.Utils; import jdk.internal.misc.Unsafe; import jdk.internal.reflect.CallerSensitive; @@ -38,10 +39,8 @@ import java.lang.foreign.ValueLayout; import java.lang.invoke.VarHandle; import java.nio.ByteOrder; -import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; /** * A value layout. A value layout is used to model the memory layout associated with values of basic data types, such as <em>integral</em> types @@ -159,19 +158,13 @@ static boolean isValidCarrier(Class<?> carrier) { @ForceInline public final VarHandle varHandle() { - final class VarHandleCache { - private static final Map<ValueLayout, VarHandle> HANDLE_MAP = new ConcurrentHashMap<>(); + var vh = handle; + if (vh == null) { + vh = varHandleInternal(LayoutPath.EMPTY_PATH_ELEMENTS); + // benign race stable field store is safe because VarHandle is thread safe + handle = vh; } - if (handle == null) { - // this store to stable field is safe, because return value of 'makeMemoryAccessVarHandle' has stable identity - handle = VarHandleCache.HANDLE_MAP.computeIfAbsent(self().withoutName(), _ -> varHandleInternal()); - } - return handle; - } - - @SuppressWarnings("unchecked") - final V self() { - return (V) this; + return vh; } } diff --git a/src/java.base/share/classes/jdk/internal/invoke/MhUtil.java b/src/java.base/share/classes/jdk/internal/invoke/MhUtil.java index 16a4e10221c..4a8cb785470 100644 --- a/src/java.base/share/classes/jdk/internal/invoke/MhUtil.java +++ b/src/java.base/share/classes/jdk/internal/invoke/MhUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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,9 @@ /** * Static factories for certain VarHandle/MethodHandle variants. * <p> + * Some methods take no receiver argument. In these cases, the receiver is the + * lookup class. + * <p> * The methods will throw an {@link InternalError} if the lookup fails. * <p> * Here is an example of how one of these methods could be used: @@ -63,6 +66,11 @@ public static VarHandle findVarHandle(MethodHandles.Lookup lookup, } } + public static MethodHandle findVirtual(MethodHandles.Lookup lookup, + String name, + MethodType type) { + return findVirtual(lookup, lookup.lookupClass(), name, type); + } public static MethodHandle findVirtual(MethodHandles.Lookup lookup, Class<?> refc, @@ -75,4 +83,21 @@ public static MethodHandle findVirtual(MethodHandles.Lookup lookup, } } + public static MethodHandle findStatic(MethodHandles.Lookup lookup, + String name, + MethodType type) { + return findStatic(lookup, lookup.lookupClass(), name, type); + } + + public static MethodHandle findStatic(MethodHandles.Lookup lookup, + Class<?> refc, + String name, + MethodType type) { + try { + return lookup.findStatic(refc, name, type); + } catch (ReflectiveOperationException e) { + throw new InternalError(e); + } + } + } diff --git a/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java b/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java index 07879353d90..c06c62488db 100644 --- a/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java +++ b/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -49,7 +49,7 @@ * to the jimage file provided by the shipped JDK by tools running on JDK 8. */ public class BasicImageReader implements AutoCloseable { - @SuppressWarnings("removal") + @SuppressWarnings({ "removal", "suppression" }) private static boolean isSystemProperty(String key, String value, String def) { // No lambdas during bootstrap return AccessController.doPrivileged( @@ -82,7 +82,7 @@ public Boolean run() { private final ImageStringsReader stringsReader; private final Decompressor decompressor; - @SuppressWarnings({ "removal", "this-escape" }) + @SuppressWarnings({ "removal", "this-escape", "suppression" }) protected BasicImageReader(Path path, ByteOrder byteOrder) throws IOException { this.imagePath = Objects.requireNonNull(path); diff --git a/src/java.base/share/classes/jdk/internal/jimage/NativeImageBuffer.java b/src/java.base/share/classes/jdk/internal/jimage/NativeImageBuffer.java index 9ef02364195..b55080eb192 100644 --- a/src/java.base/share/classes/jdk/internal/jimage/NativeImageBuffer.java +++ b/src/java.base/share/classes/jdk/internal/jimage/NativeImageBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ * but also compiled and delivered as part of the jrtfs.jar to support access * to the jimage file provided by the shipped JDK by tools running on JDK 8. */ -@SuppressWarnings("removal") +@SuppressWarnings({ "removal", "suppression"} ) class NativeImageBuffer { static { java.security.AccessController.doPrivileged( diff --git a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileStore.java b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileStore.java index 7d4b0a18822..7846b740544 100644 --- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileStore.java +++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,6 @@ public boolean supportsFileAttributeView(String name) { } @Override - @SuppressWarnings("unchecked") public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> type) { Objects.requireNonNull(type, "type"); return (V) null; diff --git a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java index 4d3e0ed9d2c..c0d3eeab6bd 100644 --- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java +++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -68,7 +68,7 @@ public String getScheme() { * Need RuntimePermission "accessSystemModules" to create or get jrt:/ */ private void checkPermission() { - @SuppressWarnings("removal") + @SuppressWarnings({ "removal", "suppression" }) SecurityManager sm = System.getSecurityManager(); if (sm != null) { RuntimePermission perm = new RuntimePermission("accessSystemModules"); @@ -123,7 +123,7 @@ private FileSystem newFileSystem(String targetHome, URI uri, Map<String, ?> env) ClassLoader cl = newJrtFsLoader(jrtfs); try { Class<?> c = Class.forName(JrtFileSystemProvider.class.getName(), false, cl); - @SuppressWarnings("deprecation") + @SuppressWarnings({ "deprecation", "suppression" }) Object tmp = c.newInstance(); return ((FileSystemProvider)tmp).newFileSystem(uri, newEnv); } catch (ClassNotFoundException | @@ -156,7 +156,7 @@ protected Class<?> loadClass(String cn, boolean resolve) } } - @SuppressWarnings("removal") + @SuppressWarnings({ "removal", "suppression" }) private static URLClassLoader newJrtFsLoader(Path jrtfs) { final URL url; try { @@ -261,7 +261,6 @@ public final void delete(Path path) throws IOException { } @Override - @SuppressWarnings("unchecked") public <V extends FileAttributeView> V getFileAttributeView(Path path, Class<V> type, LinkOption... options) { return JrtFileAttributeView.get(toJrtPath(path), type, options); diff --git a/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java b/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java index e1770d9c55b..88cdf724e7d 100644 --- a/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java +++ b/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ * but also compiled and delivered as part of the jrtfs.jar to support access * to the jimage file provided by the shipped JDK by tools running on JDK 8. */ -@SuppressWarnings("removal") +@SuppressWarnings({ "removal", "suppression"} ) abstract class SystemImage { abstract Node findNode(String path) throws IOException; diff --git a/src/java.base/share/classes/jdk/internal/logger/BootstrapLogger.java b/src/java.base/share/classes/jdk/internal/logger/BootstrapLogger.java index a4c9e4baf63..01d8fedb0aa 100644 --- a/src/java.base/share/classes/jdk/internal/logger/BootstrapLogger.java +++ b/src/java.base/share/classes/jdk/internal/logger/BootstrapLogger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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 @@ -263,7 +263,6 @@ static final class LogEvent { // The next event in the queue LogEvent next; - @SuppressWarnings("removal") private LogEvent(BootstrapLogger bootstrap, Level level, ResourceBundle bundle, String msg, Throwable thrown, Object[] params) { @@ -281,7 +280,6 @@ private LogEvent(BootstrapLogger bootstrap, Level level, this.bootstrap = bootstrap; } - @SuppressWarnings("removal") private LogEvent(BootstrapLogger bootstrap, Level level, Supplier<String> msgSupplier, Throwable thrown, Object[] params) { @@ -299,7 +297,6 @@ private LogEvent(BootstrapLogger bootstrap, Level level, this.bootstrap = bootstrap; } - @SuppressWarnings("removal") private LogEvent(BootstrapLogger bootstrap, PlatformLogger.Level platformLevel, String sourceClass, String sourceMethod, @@ -319,7 +316,6 @@ private LogEvent(BootstrapLogger bootstrap, this.bootstrap = bootstrap; } - @SuppressWarnings("removal") private LogEvent(BootstrapLogger bootstrap, PlatformLogger.Level platformLevel, String sourceClass, String sourceMethod, @@ -860,7 +856,6 @@ private LoggingBackend(boolean useLoggerFinder) { // The purpose of this class is to delay the initialization of // the detectedBackend field until it is actually read. // We do not want this field to get initialized if VM.isBooted() is false. - @SuppressWarnings("removal") private static final class DetectBackend { static final LoggingBackend detectedBackend = detectBackend(); diff --git a/src/java.base/share/classes/jdk/internal/misc/X-ScopedMemoryAccess.java.template b/src/java.base/share/classes/jdk/internal/misc/X-ScopedMemoryAccess.java.template index c2f5f7fabd0..158df7c8bb3 100644 --- a/src/java.base/share/classes/jdk/internal/misc/X-ScopedMemoryAccess.java.template +++ b/src/java.base/share/classes/jdk/internal/misc/X-ScopedMemoryAccess.java.template @@ -75,7 +75,7 @@ import jdk.internal.vm.vector.VectorSupport; * which might be deemed to expensive; in other words, this approach prioritizes the performance of memory access over * that of releasing a shared memory resource. */ -public class ScopedMemoryAccess { +public final class ScopedMemoryAccess { private static final Unsafe UNSAFE = Unsafe.getUnsafe(); diff --git a/src/java.base/share/classes/jdk/internal/util/xml/impl/Parser.java b/src/java.base/share/classes/jdk/internal/util/xml/impl/Parser.java index 8ff4742a59d..4e8f0070a7c 100644 --- a/src/java.base/share/classes/jdk/internal/util/xml/impl/Parser.java +++ b/src/java.base/share/classes/jdk/internal/util/xml/impl/Parser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -2086,7 +2086,6 @@ private String ent(char flag) throws Exception { * @exception Exception is parser specific exception form panic method. * @exception IOException */ - @SuppressWarnings("fallthrough") private void pent(char flag) throws Exception { char ch; int idx = mBuffIdx + 1; diff --git a/src/java.base/share/classes/jdk/internal/vm/VMSupport.java b/src/java.base/share/classes/jdk/internal/vm/VMSupport.java index c31fa4d441f..197da0d456c 100644 --- a/src/java.base/share/classes/jdk/internal/vm/VMSupport.java +++ b/src/java.base/share/classes/jdk/internal/vm/VMSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -459,7 +459,7 @@ public interface AnnotationDecoder<T, A, E, X> { * @param <X> type of the object representing a decoded error * @return an immutable list of {@code A} objects */ - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings("unchecked") public static <T, A, E, X> List<A> decodeAnnotations(byte[] encoded, AnnotationDecoder<T, A, E, X> decoder) { try { ByteArrayInputStream bais = new ByteArrayInputStream(encoded); diff --git a/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/src/java.base/share/classes/sun/launcher/LauncherHelper.java index 3ba0758585e..8fbf76851cc 100644 --- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java +++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, 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 @@ -156,7 +156,6 @@ enum Option { DEFAULT, ALL, LOCALE, PROPERTIES, SECURITY, * this code determine this value, using a suitable method or omit the * line entirely. */ - @SuppressWarnings("fallthrough") static void showSettings(boolean printToStderr, String optionFlag, long initialHeapSize, long maxHeapSize, long stackSize) { @@ -733,7 +732,6 @@ static void abort(Throwable t, String msgKey, Object... args) { * * @return the application's main class */ - @SuppressWarnings("fallthrough") public static Class<?> checkAndLoadMain(boolean printToStderr, int mode, String what) { diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 602f798448c..5d8e6f467aa 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2025, 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 @@ -2069,7 +2069,6 @@ private void setPreemptiveProxyAuthentication(MessageHeader requests) throws IOE * Gets the authentication for an HTTP proxy, and applies it to * the connection. */ - @SuppressWarnings("fallthrough") private AuthenticationInfo getHttpProxyAuthentication(AuthenticationHeader authhdr) throws IOException { diff --git a/src/java.base/share/classes/sun/security/provider/ML_DSA.java b/src/java.base/share/classes/sun/security/provider/ML_DSA.java index f3b72f53a32..969b8fffa39 100644 --- a/src/java.base/share/classes/sun/security/provider/ML_DSA.java +++ b/src/java.base/share/classes/sun/security/provider/ML_DSA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,12 @@ package sun.security.provider; +import jdk.internal.vm.annotation.IntrinsicCandidate; import sun.security.provider.SHA3.SHAKE128; import sun.security.provider.SHA3.SHAKE256; +import sun.security.provider.SHA3Parallel.Shake128Parallel; +import java.security.InvalidAlgorithmParameterException; import java.security.MessageDigest; import java.security.InvalidKeyException; import java.security.SignatureException; @@ -44,7 +47,7 @@ public class ML_DSA { private static final int ML_DSA_Q = 8380417; private static final int ML_DSA_N = 256; private static final int SHAKE256_BLOCK_SIZE = 136; // the block length for SHAKE256 - + private static final int SHAKE128_BLOCK_SIZE = 168; // the block length for SHAKE128 private final int A_SEED_LEN = 32; private final int S1S2_SEED_LEN = 64; private final int K_LEN = 32; @@ -98,39 +101,280 @@ public class ML_DSA { -2235985, -420899, -2286327, 183443, -976891, 1612842, -3545687, -554416, 3919660, -48306, -1362209, 3937738, 1400424, -846154, 1976782 }; - private static final int[] MONT_ZETAS_FOR_INVERSE_NTT = new int[]{ - -1976782, 846154, -1400424, -3937738, 1362209, 48306, -3919660, 554416, - 3545687, -1612842, 976891, -183443, 2286327, 420899, 2235985, 2939036, - 3833893, 260646, 1104333, 1667432, -1910376, 1803090, -1723600, 426683, - -472078, -1717735, 975884, -2213111, -269760, -3866901, -3523897, 3038916, - 1799107, 3694233, -1652634, -810149, -3014001, -1616392, -162844, 3183426, - 1207385, -185531, -3369112, -1957272, 164721, -2454455, -2432395, 2013608, - 3776993, -594136, 3724270, 2584293, 1846953, 1671176, 2831860, 542412, - -3406031, -2235880, -777191, -1500165, 1374803, 2546312, -1917081, 1279661, - 1962642, -3306115, -1312455, 451100, 1430225, 3318210, -1237275, 1333058, - 1050970, -1903435, -1869119, 2994039, 3548272, -2635921, -1250494, 3767016, - -1595974, -2486353, -1247620, -4055324, -1265009, 2590150, -2691481, -2842341, - -203044, -1735879, 3342277, -3437287, -4108315, 2437823, -286988, -342297, - 3595838, 768622, 525098, 3556995, -3207046, -2031748, 3122442, 655327, - 522500, 43260, 1613174, -495491, -819034, -909542, -1859098, -900702, - 3193378, 1197226, 3759364, 3520352, -3513181, 1235728, -2434439, -266997, - 3562462, 2446433, -2244091, 3342478, -3817976, -2316500, -3407706, -2091667, - -3839961, 3628969, 3881060, 3019102, 1439742, 812732, 1584928, -1285669, - -1341330, -1315589, 177440, 2409325, 1851402, -3159746, 3553272, -189548, - 1316856, -759969, 210977, -2389356, 3249728, -1653064, 8578, 3724342, - -3958618, -904516, 1100098, -44288, -3097992, -508951, -264944, 3343383, - 1430430, -1852771, -1349076, 381987, 1308169, 22981, 1228525, 671102, - 2477047, 411027, 3693493, 2967645, -2715295, -2147896, 983419, -3412210, - -126922, 3632928, 3157330, 3190144, 1000202, 4083598, -1939314, 1257611, - 1585221, -2176455, -3475950, 1452451, 3041255, 3677745, 1528703, 3930395, - 2797779, -2071892, 2556880, -3900724, -3881043, -954230, -531354, -811944, - -3699596, 1600420, 2140649, -3507263, 3821735, -3505694, 1643818, 1699267, - 539299, -2348700, 300467, -3539968, 2867647, -3574422, 3043716, 3861115, - -3915439, 2537516, 3592148, 1661693, -3530437, -3077325, -95776, -2706023, - -280005, -4010497, 19422, -1757237, 3277672, 1399561, 3859737, 2118186, - 2108549, -2619752, 1119584, 549488, -3585928, 1079900, -1024112, -2725464, - -2680103, -3111497, 2884855, -3119733, 2091905, 359251, -2353451, -1826347, - -466468, 876248, 777960, -237124, 518909, 2608894, -25847 + private static final int[] MONT_ZETAS_FOR_VECTOR_NTT = new int[]{ + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + + 237124, 237124, 237124, 237124, 237124, 237124, 237124, 237124, + 237124, 237124, 237124, 237124, 237124, 237124, 237124, 237124, + 237124, 237124, 237124, 237124, 237124, 237124, 237124, 237124, + 237124, 237124, 237124, 237124, 237124, 237124, 237124, 237124, + -777960, -777960, -777960, -777960, -777960, -777960, -777960, -777960, + -777960, -777960, -777960, -777960, -777960, -777960, -777960, -777960, + -777960, -777960, -777960, -777960, -777960, -777960, -777960, -777960, + -777960, -777960, -777960, -777960, -777960, -777960, -777960, -777960, + -876248, -876248, -876248, -876248, -876248, -876248, -876248, -876248, + -876248, -876248, -876248, -876248, -876248, -876248, -876248, -876248, + -876248, -876248, -876248, -876248, -876248, -876248, -876248, -876248, + -876248, -876248, -876248, -876248, -876248, -876248, -876248, -876248, + 466468, 466468, 466468, 466468, 466468, 466468, 466468, 466468, + 466468, 466468, 466468, 466468, 466468, 466468, 466468, 466468, + 466468, 466468, 466468, 466468, 466468, 466468, 466468, 466468, + 466468, 466468, 466468, 466468, 466468, 466468, 466468, 466468, + + 1826347, 1826347, 1826347, 1826347, 1826347, 1826347, 1826347, 1826347, + 1826347, 1826347, 1826347, 1826347, 1826347, 1826347, 1826347, 1826347, + 2353451, 2353451, 2353451, 2353451, 2353451, 2353451, 2353451, 2353451, + 2353451, 2353451, 2353451, 2353451, 2353451, 2353451, 2353451, 2353451, + -359251, -359251, -359251, -359251, -359251, -359251, -359251, -359251, + -359251, -359251, -359251, -359251, -359251, -359251, -359251, -359251, + -2091905, -2091905, -2091905, -2091905, -2091905, -2091905, -2091905, -2091905, + -2091905, -2091905, -2091905, -2091905, -2091905, -2091905, -2091905, -2091905, + 3119733, 3119733, 3119733, 3119733, 3119733, 3119733, 3119733, 3119733, + 3119733, 3119733, 3119733, 3119733, 3119733, 3119733, 3119733, 3119733, + -2884855, -2884855, -2884855, -2884855, -2884855, -2884855, -2884855, -2884855, + -2884855, -2884855, -2884855, -2884855, -2884855, -2884855, -2884855, -2884855, + 3111497, 3111497, 3111497, 3111497, 3111497, 3111497, 3111497, 3111497, + 3111497, 3111497, 3111497, 3111497, 3111497, 3111497, 3111497, 3111497, + 2680103, 2680103, 2680103, 2680103, 2680103, 2680103, 2680103, 2680103, + 2680103, 2680103, 2680103, 2680103, 2680103, 2680103, 2680103, 2680103, + + 2725464, 2725464, 2725464, 2725464, 2725464, 2725464, 2725464, 2725464, + 1024112, 1024112, 1024112, 1024112, 1024112, 1024112, 1024112, 1024112, + -1079900, -1079900, -1079900, -1079900, -1079900, -1079900, -1079900, -1079900, + 3585928, 3585928, 3585928, 3585928, 3585928, 3585928, 3585928, 3585928, + -549488, -549488, -549488, -549488, -549488, -549488, -549488, -549488, + -1119584, -1119584, -1119584, -1119584, -1119584, -1119584, -1119584, -1119584, + 2619752, 2619752, 2619752, 2619752, 2619752, 2619752, 2619752, 2619752, + -2108549, -2108549, -2108549, -2108549, -2108549, -2108549, -2108549, -2108549, + -2118186, -2118186, -2118186, -2118186, -2118186, -2118186, -2118186, -2118186, + -3859737, -3859737, -3859737, -3859737, -3859737, -3859737, -3859737, -3859737, + -1399561, -1399561, -1399561, -1399561, -1399561, -1399561, -1399561, -1399561, + -3277672, -3277672, -3277672, -3277672, -3277672, -3277672, -3277672, -3277672, + 1757237, 1757237, 1757237, 1757237, 1757237, 1757237, 1757237, 1757237, + -19422, -19422, -19422, -19422, -19422, -19422, -19422, -19422, + 4010497, 4010497, 4010497, 4010497, 4010497, 4010497, 4010497, 4010497, + 280005, 280005, 280005, 280005, 280005, 280005, 280005, 280005, + + 2706023, 2706023, 2706023, 2706023, 95776, 95776, 95776, 95776, + 3077325, 3077325, 3077325, 3077325, 3530437, 3530437, 3530437, 3530437, + -1661693, -1661693, -1661693, -1661693, -3592148, -3592148, -3592148, -3592148, + -2537516, -2537516, -2537516, -2537516, 3915439, 3915439, 3915439, 3915439, + -3861115, -3861115, -3861115, -3861115, -3043716, -3043716, -3043716, -3043716, + 3574422, 3574422, 3574422, 3574422, -2867647, -2867647, -2867647, -2867647, + 3539968, 3539968, 3539968, 3539968, -300467, -300467, -300467, -300467, + 2348700, 2348700, 2348700, 2348700, -539299, -539299, -539299, -539299, + -1699267, -1699267, -1699267, -1699267, -1643818, -1643818, -1643818, -1643818, + 3505694, 3505694, 3505694, 3505694, -3821735, -3821735, -3821735, -3821735, + 3507263, 3507263, 3507263, 3507263, -2140649, -2140649, -2140649, -2140649, + -1600420, -1600420, -1600420, -1600420, 3699596, 3699596, 3699596, 3699596, + 811944, 811944, 811944, 811944, 531354, 531354, 531354, 531354, + 954230, 954230, 954230, 954230, 3881043, 3881043, 3881043, 3881043, + 3900724, 3900724, 3900724, 3900724, -2556880, -2556880, -2556880, -2556880, + 2071892, 2071892, 2071892, 2071892, -2797779, -2797779, -2797779, -2797779, + + -3930395, -3930395, -1528703, -1528703, -3677745, -3677745, -3041255, -3041255, + -1452451, -1452451, 3475950, 3475950, 2176455, 2176455, -1585221, -1585221, + -1257611, -1257611, 1939314, 1939314, -4083598, -4083598, -1000202, -1000202, + -3190144, -3190144, -3157330, -3157330, -3632928, -3632928, 126922, 126922, + 3412210, 3412210, -983419, -983419, 2147896, 2147896, 2715295, 2715295, + -2967645, -2967645, -3693493, -3693493, -411027, -411027, -2477047, -2477047, + -671102, -671102, -1228525, -1228525, -22981, -22981, -1308169, -1308169, + -381987, -381987, 1349076, 1349076, 1852771, 1852771, -1430430, -1430430, + -3343383, -3343383, 264944, 264944, 508951, 508951, 3097992, 3097992, + 44288, 44288, -1100098, -1100098, 904516, 904516, 3958618, 3958618, + -3724342, -3724342, -8578, -8578, 1653064, 1653064, -3249728, -3249728, + 2389356, 2389356, -210977, -210977, 759969, 759969, -1316856, -1316856, + 189548, 189548, -3553272, -3553272, 3159746, 3159746, -1851402, -1851402, + -2409325, -2409325, -177440, -177440, 1315589, 1315589, 1341330, 1341330, + 1285669, 1285669, -1584928, -1584928, -812732, -812732, -1439742, -1439742, + -3019102, -3019102, -3881060, -3881060, -3628969, -3628969, 3839961, 3839961, + + 2091667, 3407706, 2316500, 3817976, -3342478, 2244091, -2446433, -3562462, + 266997, 2434439, -1235728, 3513181, -3520352, -3759364, -1197226, -3193378, + 900702, 1859098, 909542, 819034, 495491, -1613174, -43260, -522500, + -655327, -3122442, 2031748, 3207046, -3556995, -525098, -768622, -3595838, + 342297, 286988, -2437823, 4108315, 3437287, -3342277, 1735879, 203044, + 2842341, 2691481, -2590150, 1265009, 4055324, 1247620, 2486353, 1595974, + -3767016, 1250494, 2635921, -3548272, -2994039, 1869119, 1903435, -1050970, + -1333058, 1237275, -3318210, -1430225, -451100, 1312455, 3306115, -1962642, + -1279661, 1917081, -2546312, -1374803, 1500165, 777191, 2235880, 3406031, + -542412, -2831860, -1671176, -1846953, -2584293, -3724270, 594136, -3776993, + -2013608, 2432395, 2454455, -164721, 1957272, 3369112, 185531, -1207385, + -3183426, 162844, 1616392, 3014001, 810149, 1652634, -3694233, -1799107, + -3038916, 3523897, 3866901, 269760, 2213111, -975884, 1717735, 472078, + -426683, 1723600, -1803090, 1910376, -1667432, -1104333, -260646, -3833893, + -2939036, -2235985, -420899, -2286327, 183443, -976891, 1612842, -3545687, + -554416, 3919660, -48306, -1362209, 3937738, 1400424, -846154, 1976782 + }; + + private static final int[] MONT_ZETAS_FOR_VECTOR_INVERSE_NTT = new int[]{ + -1976782, 846154, -1400424, -3937738, 1362209, 48306, -3919660, 554416, + 3545687, -1612842, 976891, -183443, 2286327, 420899, 2235985, 2939036, + 3833893, 260646, 1104333, 1667432, -1910376, 1803090, -1723600, 426683, + -472078, -1717735, 975884, -2213111, -269760, -3866901, -3523897, 3038916, + 1799107, 3694233, -1652634, -810149, -3014001, -1616392, -162844, 3183426, + 1207385, -185531, -3369112, -1957272, 164721, -2454455, -2432395, 2013608, + 3776993, -594136, 3724270, 2584293, 1846953, 1671176, 2831860, 542412, + -3406031, -2235880, -777191, -1500165, 1374803, 2546312, -1917081, 1279661, + 1962642, -3306115, -1312455, 451100, 1430225, 3318210, -1237275, 1333058, + 1050970, -1903435, -1869119, 2994039, 3548272, -2635921, -1250494, 3767016, + -1595974, -2486353, -1247620, -4055324, -1265009, 2590150, -2691481, -2842341, + -203044, -1735879, 3342277, -3437287, -4108315, 2437823, -286988, -342297, + 3595838, 768622, 525098, 3556995, -3207046, -2031748, 3122442, 655327, + 522500, 43260, 1613174, -495491, -819034, -909542, -1859098, -900702, + 3193378, 1197226, 3759364, 3520352, -3513181, 1235728, -2434439, -266997, + 3562462, 2446433, -2244091, 3342478, -3817976, -2316500, -3407706, -2091667, + + -3839961, -3839961, 3628969, 3628969, 3881060, 3881060, 3019102, 3019102, + 1439742, 1439742, 812732, 812732, 1584928, 1584928, -1285669, -1285669, + -1341330, - 1341330, -1315589, -1315589, 177440, 177440, 2409325, 2409325, + 1851402, 1851402, -3159746, -3159746, 3553272, 3553272, -189548, -189548, + 1316856, 1316856, -759969, -759969, 210977, 210977, -2389356, -2389356, + 3249728, 3249728, -1653064, -1653064, 8578, 8578, 3724342, 3724342, + -3958618, -3958618, -904516, -904516, 1100098, 1100098, -44288, -44288, + -3097992, -3097992, -508951, -508951, -264944, -264944, 3343383, 3343383, + 1430430, 1430430, -1852771, -1852771, -1349076, -1349076, 381987, 381987, + 1308169, 1308169, 22981, 22981, 1228525, 1228525, 671102, 671102, + 2477047, 2477047, 411027, 411027, 3693493, 3693493, 2967645, 2967645, + -2715295, -2715295, -2147896, -2147896, 983419, 983419, -3412210, -3412210, + -126922, -126922, 3632928, 3632928, 3157330, 3157330, 3190144, 3190144, + 1000202, 1000202, 4083598, 4083598, -1939314, -1939314, 1257611, 1257611, + 1585221, 1585221, -2176455, -2176455, -3475950, -3475950, 1452451, 1452451, + 3041255, 3041255, 3677745, 3677745, 1528703, 1528703, 3930395, 3930395, + + 2797779, 2797779, 2797779, 2797779, -2071892, -2071892, -2071892, -2071892, + 2556880, 2556880, 2556880, 2556880, -3900724, -3900724, -3900724, -3900724, + -3881043, -3881043, -3881043, -3881043, -954230, -954230, -954230, -954230, + -531354, -531354, -531354, -531354, -811944, -811944, -811944, -811944, + -3699596, -3699596, -3699596, -3699596, 1600420, 1600420, 1600420, 1600420, + 2140649, 2140649, 2140649, 2140649, -3507263, -3507263, -3507263, -3507263, + 3821735, 3821735, 3821735, 3821735, -3505694, -3505694, -3505694, -3505694, + 1643818, 1643818, 1643818, 1643818, 1699267, 1699267, 1699267, 1699267, + 539299, 539299, 539299, 539299, -2348700, -2348700, -2348700, -2348700, + 300467, 300467, 300467, 300467, -3539968, -3539968, -3539968, -3539968, + 2867647, 2867647, 2867647, 2867647, -3574422, -3574422, -3574422, -3574422, + 3043716, 3043716, 3043716, 3043716, 3861115, 3861115, 3861115, 3861115, + -3915439, -3915439, -3915439, -3915439, 2537516, 2537516, 2537516, 2537516, + 3592148, 3592148, 3592148, 3592148, 1661693, 1661693, 1661693, 1661693, + -3530437, -3530437, -3530437, -3530437, -3077325, -3077325, -3077325, -3077325, + -95776, -95776, -95776, -95776, -2706023, -2706023, -2706023, -2706023, + + -280005, -280005, -280005, -280005, -280005, -280005, -280005, -280005, + -4010497, -4010497, -4010497, -4010497, -4010497, -4010497, -4010497, -4010497, + 19422, 19422, 19422, 19422, 19422, 19422, 19422, 19422, + -1757237, -1757237, -1757237, -1757237, -1757237, -1757237, -1757237, -1757237, + 3277672, 3277672, 3277672, 3277672, 3277672, 3277672, 3277672, 3277672, + 1399561, 1399561, 1399561, 1399561, 1399561, 1399561, 1399561, 1399561, + 3859737, 3859737, 3859737, 3859737, 3859737, 3859737, 3859737, 3859737, + 2118186, 2118186, 2118186, 2118186, 2118186, 2118186, 2118186, 2118186, + 2108549, 2108549, 2108549, 2108549, 2108549, 2108549, 2108549, 2108549, + -2619752, -2619752, -2619752, -2619752, -2619752, -2619752, -2619752, -2619752, + 1119584, 1119584, 1119584, 1119584, 1119584, 1119584, 1119584, 1119584, + 549488, 549488, 549488, 549488, 549488, 549488, 549488, 549488, + -3585928, -3585928, -3585928, -3585928, -3585928, -3585928, -3585928, -3585928, + 1079900, 1079900, 1079900, 1079900, 1079900, 1079900, 1079900, 1079900, + -1024112, -1024112, -1024112, -1024112, -1024112, -1024112, -1024112, -1024112, + -2725464, -2725464, -2725464, -2725464, -2725464, -2725464, -2725464, -2725464, + + -2680103, -2680103, -2680103, -2680103, -2680103, -2680103, -2680103, -2680103, + -2680103, -2680103, -2680103, -2680103, -2680103, -2680103, -2680103, -2680103, + -3111497, -3111497, -3111497, -3111497, -3111497, -3111497, -3111497, -3111497, + -3111497, -3111497, -3111497, -3111497, -3111497, -3111497, -3111497, -3111497, + 2884855, 2884855, 2884855, 2884855, 2884855, 2884855, 2884855, 2884855, + 2884855, 2884855, 2884855, 2884855, 2884855, 2884855, 2884855, 2884855, + -3119733, -3119733, -3119733, -3119733, -3119733, -3119733, -3119733, -3119733, + -3119733, -3119733, -3119733, -3119733, -3119733, -3119733, -3119733, -3119733, + 2091905, 2091905, 2091905, 2091905, 2091905, 2091905, 2091905, 2091905, + 2091905, 2091905, 2091905, 2091905, 2091905, 2091905, 2091905, 2091905, + 359251, 359251, 359251, 359251, 359251, 359251, 359251, 359251, + 359251, 359251, 359251, 359251, 359251, 359251, 359251, 359251, + -2353451, -2353451, -2353451, -2353451, -2353451, -2353451, -2353451, -2353451, + -2353451, -2353451, -2353451, -2353451, -2353451, -2353451, -2353451, -2353451, + -1826347, -1826347, -1826347, -1826347, -1826347, -1826347, -1826347, -1826347, + -1826347, -1826347, -1826347, -1826347, -1826347, -1826347, -1826347, -1826347, + + -466468, -466468, -466468, -466468, -466468, -466468, -466468, -466468, + -466468, -466468, -466468, -466468, -466468, -466468, -466468, -466468, + -466468, -466468, -466468, -466468, -466468, -466468, -466468, -466468, + -466468, -466468, -466468, -466468, -466468, -466468, -466468, -466468, + 876248, 876248, 876248, 876248, 876248, 876248, 876248, 876248, + 876248, 876248, 876248, 876248, 876248, 876248, 876248, 876248, + 876248, 876248, 876248, 876248, 876248, 876248, 876248, 876248, + 876248, 876248, 876248, 876248, 876248, 876248, 876248, 876248, + 777960, 777960, 777960, 777960, 777960, 777960, 777960, 777960, + 777960, 777960, 777960, 777960, 777960, 777960, 777960, 777960, + 777960, 777960, 777960, 777960, 777960, 777960, 777960, 777960, + 777960, 777960, 777960, 777960, 777960, 777960, 777960, 777960, + -237124, -237124, -237124, -237124, -237124, -237124, -237124, -237124, + -237124, -237124, -237124, -237124, -237124, -237124, -237124, -237124, + -237124, -237124, -237124, -237124, -237124, -237124, -237124, -237124, + -237124, -237124, -237124, -237124, -237124, -237124, -237124, -237124, + + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847 }; // Constants defined for each security level @@ -848,43 +1092,85 @@ private void sampleInBall(int[] c, byte[] rho) { } } - int[][][] generateA(byte[] seed) { - int blockSize = 168; // the size of one block of SHAKE128 output - var xof = new SHAKE128(0); - byte[] xofSeed = new byte[A_SEED_LEN + 2]; - System.arraycopy(seed, 0, xofSeed, 0, A_SEED_LEN); + private int[][][] generateA(byte[] seed) { int[][][] a = new int[mlDsa_k][mlDsa_l][]; - for (int i = 0; i < mlDsa_k; i++) { - for (int j = 0; j < mlDsa_l; j++) { - xofSeed[A_SEED_LEN] = (byte) j; - xofSeed[A_SEED_LEN + 1] = (byte) i; - xof.reset(); - xof.update(xofSeed); - - byte[] rawAij = new byte[blockSize]; - int[] aij = new int[ML_DSA_N]; - int ofs = 0; - int rawOfs = blockSize; - int tmp; - while (ofs < ML_DSA_N) { - if (rawOfs == blockSize) { - // works because 3 divides blockSize (=168) - xof.squeeze(rawAij, 0, blockSize); - rawOfs = 0; - } - tmp = (rawAij[rawOfs] & 0xFF) + - ((rawAij[rawOfs + 1] & 0xFF) << 8) + - ((rawAij[rawOfs + 2] & 0x7F) << 16); - rawOfs += 3; - if (tmp < ML_DSA_Q) { - aij[ofs] = tmp; - ofs++; + int nrPar = 2; + int rhoLen = seed.length; + byte[] seedBuf = new byte[SHAKE128_BLOCK_SIZE]; + System.arraycopy(seed, 0, seedBuf, 0, seed.length); + seedBuf[rhoLen + 2] = 0x1F; + seedBuf[SHAKE128_BLOCK_SIZE - 1] = (byte)0x80; + byte[][] xofBufArr = new byte[nrPar][SHAKE128_BLOCK_SIZE]; + int[] iIndex = new int[nrPar]; + int[] jIndex = new int[nrPar]; + + int[] parsedBuf = new int[SHAKE128_BLOCK_SIZE / 3]; + + int parInd = 0; + boolean allDone; + int[] ofs = new int[nrPar]; + Arrays.fill(ofs, 0); + int[][] aij = new int[nrPar][]; + try { + Shake128Parallel parXof = new Shake128Parallel(xofBufArr); + + for (int i = 0; i < mlDsa_k; i++) { + for (int j = 0; j < mlDsa_l; j++) { + xofBufArr[parInd] = seedBuf.clone(); + xofBufArr[parInd][rhoLen] = (byte) j; + xofBufArr[parInd][rhoLen + 1] = (byte) i; + iIndex[parInd] = i; + jIndex[parInd] = j; + ofs[parInd] = 0; + aij[parInd] = new int[ML_DSA_N]; + parInd++; + + if ((parInd == nrPar) || + ((i == mlDsa_k - 1) && (j == mlDsa_l - 1))) { + parXof.reset(xofBufArr); + + allDone = false; + while (!allDone) { + allDone = true; + parXof.squeezeBlock(); + for (int k = 0; k < parInd; k++) { + int parsedOfs = 0; + int tmp; + if (ofs[k] < ML_DSA_N) { + for (int l = 0; l < SHAKE128_BLOCK_SIZE; l += 3) { + byte[] rawBuf = xofBufArr[k]; + parsedBuf[l / 3] = (rawBuf[l] & 0xFF) + + ((rawBuf[l + 1] & 0xFF) << 8) + + ((rawBuf[l + 2] & 0x7F) << 16); + } + } + while ((ofs[k] < ML_DSA_N) && + (parsedOfs < SHAKE128_BLOCK_SIZE / 3)) { + tmp = parsedBuf[parsedOfs++]; + if (tmp < ML_DSA_Q) { + aij[k][ofs[k]] = tmp; + ofs[k]++; + } + } + if (ofs[k] < ML_DSA_N) { + allDone = false; + } + } + } + + for (int k = 0; k < parInd; k++) { + a[iIndex[k]][jIndex[k]] = aij[k]; + } + parInd = 0; } } - a[i][j] = aij; } + } catch (InvalidAlgorithmParameterException e) { + // This should never happen since xofBufArr is of the correct size + throw new RuntimeException("Internal error."); } + return a; } @@ -979,7 +1265,7 @@ private void power2Round(int[][] input, int[][] lowPart, int[][] highPart) { private void decompose(int[][] input, int[][] lowPart, int[][] highPart) { int multiplier = (gamma2 == 95232 ? 22 : 8); for (int i = 0; i < mlDsa_k; i++) { - ML_DSA.mlDsaDecomposePoly(input[i], lowPart[i], + mlDsaDecomposePoly(input[i], lowPart[i], highPart[i], gamma2 * 2, multiplier); } } @@ -1011,7 +1297,7 @@ private int makeHint(boolean[][] res, int[][] z, int[][] r) { private int[][] useHint(boolean[][] h, int[][] r) { int m = (ML_DSA_Q - 1) / (2*gamma2); - int[][] lowPart = new int[mlDsa_k][ML_DSA_N]; + int[][] lowPart = r; int[][] highPart = new int[mlDsa_k][ML_DSA_N]; decompose(r, lowPart, highPart); @@ -1030,7 +1316,18 @@ private int[][] useHint(boolean[][] h, int[][] r) { NTT functions as specified in Section 7.5 of specification */ - public static int[] mlDsaNtt(int[] coeffs) { + public static void mlDsaNtt(int[] coeffs) { + implDilithiumAlmostNtt(coeffs, MONT_ZETAS_FOR_VECTOR_NTT); + implDilithiumMontMulByConstant(coeffs, MONT_R_MOD_Q); + } + + @IntrinsicCandidate + static int implDilithiumAlmostNtt(int[] coeffs, int[] zetas) { + implDilithiumAlmostNttJava(coeffs); + return 1; + } + + static void implDilithiumAlmostNttJava(int[] coeffs) { int dimension = ML_DSA_N; int m = 0; for (int l = dimension / 2; l > 0; l /= 2) { @@ -1043,26 +1340,33 @@ public static int[] mlDsaNtt(int[] coeffs) { m++; } } - montMulByConstant(coeffs, MONT_R_MOD_Q); - return coeffs; } - public static int[] mlDsaInverseNtt(int[] coeffs) { + public static void mlDsaInverseNtt(int[] coeffs) { + implDilithiumAlmostInverseNtt(coeffs, MONT_ZETAS_FOR_VECTOR_INVERSE_NTT); + implDilithiumMontMulByConstant(coeffs, MONT_DIM_INVERSE); + } + + @IntrinsicCandidate + static int implDilithiumAlmostInverseNtt(int[] coeffs, int[] zetas) { + implDilithiumAlmostInverseNttJava(coeffs); + return 1; + } + + static void implDilithiumAlmostInverseNttJava(int[] coeffs) { int dimension = ML_DSA_N; - int m = 0; + int m = MONT_ZETAS_FOR_NTT.length - 1; for (int l = 1; l < dimension; l *= 2) { for (int s = 0; s < dimension; s += 2 * l) { for (int j = s; j < s + l; j++) { int tmp = coeffs[j]; coeffs[j] = (tmp + coeffs[j + l]); coeffs[j + l] = montMul(tmp - coeffs[j + l], - MONT_ZETAS_FOR_INVERSE_NTT[m]); + -MONT_ZETAS_FOR_NTT[m]); } - m++; + m--; } } - montMulByConstant(coeffs, MONT_DIM_INVERSE); - return coeffs; } void mlDsaVectorNtt(int[][] vector) { @@ -1078,12 +1382,29 @@ void mlDsaVectorInverseNtt(int[][] vector) { } public static void mlDsaNttMultiply(int[] product, int[] coeffs1, int[] coeffs2) { + implDilithiumNttMult(product, coeffs1, coeffs2); + } + + + @IntrinsicCandidate + static int implDilithiumNttMult(int[] product, int[] coeffs1, int[] coeffs2) { + implDilithiumNttMultJava(product, coeffs1, coeffs2); + return 1; + } + + static void implDilithiumNttMultJava(int[] product, int[] coeffs1, int[] coeffs2) { for (int i = 0; i < ML_DSA_N; i++) { product[i] = montMul(coeffs1[i], toMont(coeffs2[i])); } } - public static void montMulByConstant(int[] coeffs, int constant) { + @IntrinsicCandidate + static int implDilithiumMontMulByConstant(int[] coeffs, int constant) { + implDilithiumMontMulByConstantJava(coeffs, constant); + return 1; + } + + static void implDilithiumMontMulByConstantJava(int[] coeffs, int constant) { for (int i = 0; i < ML_DSA_N; i++) { coeffs[i] = montMul((coeffs[i]), constant); } @@ -1091,17 +1412,39 @@ public static void montMulByConstant(int[] coeffs, int constant) { public static void mlDsaDecomposePoly(int[] input, int[] lowPart, int[] highPart, int twoGamma2, int multiplier) { + implDilithiumDecomposePoly(input, lowPart, highPart,twoGamma2, multiplier); + } + + @IntrinsicCandidate + static int implDilithiumDecomposePoly(int[] input, int[] lowPart, int[] highPart, + int twoGamma2, int multiplier) { + decomposePolyJava(input, lowPart, highPart, twoGamma2, multiplier); + return 1; + } + + static void decomposePolyJava(int[] input, int[] lowPart, int[] highPart, + int twoGamma2, int multiplier) { + int dilithiumBarrettAddend = 5373807; for (int m = 0; m < ML_DSA_N; m++) { int rplus = input[m]; - rplus = rplus - ((rplus + 5373807) >> 23) * ML_DSA_Q; - rplus = rplus + ((rplus >> 31) & ML_DSA_Q); - int r0 = rplus - ((rplus * multiplier) >> 22) * twoGamma2; - r0 -= (((twoGamma2 - r0) >> 22) & twoGamma2); - r0 -= (((twoGamma2 / 2 - r0) >> 31) & twoGamma2); + rplus -= ((rplus + dilithiumBarrettAddend) >> 23) * ML_DSA_Q; + rplus += ((rplus >> 31) & ML_DSA_Q); + + int quotient = (rplus * multiplier) >> 22; + int r0 = rplus - quotient * twoGamma2; + int mask = (twoGamma2 - r0) >> 22; + r0 -= (mask & twoGamma2); + quotient += (mask & 1); + mask = (twoGamma2 / 2 - r0) >> 31; + r0 -= (mask & twoGamma2); + quotient += (mask & 1); + int r1 = rplus - r0 - (ML_DSA_Q - 1); - r1 = (r1 | (-r1)) >> 31; + r1 = (r1 | (-r1)) >> 31; // 0 if rplus - r0 == (dilithium_q - 1), -1 otherwise r0 += ~r1; - r1 = r1 & ((rplus - r0) / twoGamma2); + // quotient = (rplus - r0) / twoGamma2; + r1 = r1 & quotient; + lowPart[m] = r0; highPart[m] = r1; } @@ -1207,6 +1550,7 @@ boolean vectorNormBound(int[][] vec, int bound) { // precondition: -2^31 * MONT_Q <= a, b < 2^31, -2^31 < a * b < 2^31 * MONT_Q // computes a * b * 2^-32 mod MONT_Q // the result is greater than -MONT_Q and less than MONT_Q + // see e.g. Algorithm 3 in https://eprint.iacr.org/2018/039.pdf private static int montMul(int b, int c) { long a = (long) b * (long) c; int aHigh = (int) (a >> MONT_R_BITS); diff --git a/src/java.base/share/classes/sun/security/provider/SHA3Parallel.java b/src/java.base/share/classes/sun/security/provider/SHA3Parallel.java index d9abfbe413f..0851d4a9216 100644 --- a/src/java.base/share/classes/sun/security/provider/SHA3Parallel.java +++ b/src/java.base/share/classes/sun/security/provider/SHA3Parallel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,20 @@ import static sun.security.provider.SHA3.keccak; +/* + * This class is for making it possible that NRPAR (= 2) (rather restricted) + * SHAKE computations execute in parallel. + * The restrictions are: + * 1. The messages processed should be such that the absorb phase should + * execute a single keccak() call and the byte arrays passed to the constructor + * (or reset() method) of this class should be the message padded with the + * appropriate padding described in + * https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf. + * 2. The only available way for extracting data is the squeeze() method + * that extracts exactly 1 block of data of each computation, delivering it + * in the arrays that were passed to the class in the constructor (or the + * reset() call). + */ public class SHA3Parallel { private int blockSize = 0; private static final int DM = 5; // dimension of lanesArr diff --git a/src/java.base/share/classes/sun/text/DictionaryBasedBreakIterator.java b/src/java.base/share/classes/sun/text/DictionaryBasedBreakIterator.java index fb072ae402f..7978b83cbde 100644 --- a/src/java.base/share/classes/sun/text/DictionaryBasedBreakIterator.java +++ b/src/java.base/share/classes/sun/text/DictionaryBasedBreakIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, 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 @@ -338,7 +338,6 @@ protected int lookupCategory(int c) { * cachedBreakPositions so that we only have to do this work once * for each time we enter the range. */ - @SuppressWarnings("unchecked") private void divideUpDictionaryRange(int startPos, int endPos) { CharacterIterator text = getText(); diff --git a/src/java.desktop/share/classes/com/sun/beans/finder/MethodFinder.java b/src/java.desktop/share/classes/com/sun/beans/finder/MethodFinder.java index 5283cbfce0d..d05e2f81cf5 100644 --- a/src/java.desktop/share/classes/com/sun/beans/finder/MethodFinder.java +++ b/src/java.desktop/share/classes/com/sun/beans/finder/MethodFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, 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,8 +77,7 @@ public static Method findMethod(Class<?> type, String name, Class<?>...args) thr Signature signature = new Signature(type, name, args); try { - Method method = CACHE.get(signature); - return (method == null) ? method : CACHE.create(signature); + return CACHE.get(signature); } catch (SignatureException exception) { throw exception.toNoSuchMethodException("Method '" + name + "' is not found"); diff --git a/src/java.desktop/share/legal/freetype.md b/src/java.desktop/share/legal/freetype.md index 0ddbe9b1136..5df525e2f67 100644 --- a/src/java.desktop/share/legal/freetype.md +++ b/src/java.desktop/share/legal/freetype.md @@ -1,4 +1,4 @@ -## The FreeType Project: Freetype v2.13.2 +## The FreeType Project: Freetype v2.13.3 ### FreeType Notice @@ -21,23 +21,23 @@ which fits your needs best. ### FreeType License ``` -Copyright (C) 1996-2023 by David Turner, Robert Wilhelm, and Werner Lemberg. -Copyright (C) 2007-2023 by Dereg Clegg and Michael Toftdal. -Copyright (C) 1996-2023 by Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. -Copyright (C) 2022-2023 by David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and -Copyright (C) 2004-2023 by Masatake YAMATO and Redhat K.K. -Copyright (C) 2007-2023 by Derek Clegg and Michael Toftdal. -Copyright (C) 2003-2023 by Masatake YAMATO, Red Hat K.K., -Copyright (C) 1996-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. -Copyright (C) 2007-2023 by David Turner. -Copyright (C) 2022-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. -Copyright (C) 2007-2023 by Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. -Copyright (C) 2008-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. -Copyright (C) 2013-2023 by Google, Inc. -Copyright (C) 2019-2023 by Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. -Copyright (C) 2009-2023 by Oran Agra and Mickey Gabel. -Copyright (C) 2018-2023 by David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. -Copyright (C) 2004-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. +Copyright (C) 1996-2024 by David Turner, Robert Wilhelm, and Werner Lemberg. +Copyright (C) 2007-2024 by Dereg Clegg and Michael Toftdal. +Copyright (C) 1996-2024 by Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. +Copyright (C) 2022-2024 by David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and +Copyright (C) 2004-2024 by Masatake YAMATO and Redhat K.K. +Copyright (C) 2007-2024 by Derek Clegg and Michael Toftdal. +Copyright (C) 2003-2024 by Masatake YAMATO, Red Hat K.K., +Copyright (C) 1996-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. +Copyright (C) 2007-2024 by David Turner. +Copyright (C) 2022-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. +Copyright (C) 2007-2024 by Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. +Copyright (C) 2008-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. +Copyright (C) 2013-2024 by Google, Inc. +Copyright (C) 2019-2024 by Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. +Copyright (C) 2009-2024 by Oran Agra and Mickey Gabel. +Copyright (C) 2018-2024 by David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. +Copyright (C) 2004-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. The FreeType Project LICENSE @@ -559,7 +559,7 @@ Public License instead of this License. ``` --------------------------------- -The below license applies to the following files: +The below applies to the following file(s): libfreetype/src/psaux/psarrst.c libfreetype/src/psaux/psarrst.h libfreetype/src/psaux/psblues.c @@ -582,7 +582,7 @@ libfreetype/src/psaux/psstack.c libfreetype/src/psaux/psstack.h libfreetype/src/psaux/pstypes.h -Copyright 2006-2014 Adobe Systems Incorporated. +Copyright (C) 2006-2014 Adobe Systems Incorporated. This software, and all works of authorship, whether in source or object code form as indicated by the copyright notice(s) included @@ -618,12 +618,12 @@ and you accept them fully. ``` --------------------------------- -The below license applies to the following files: +The below applies to the following file(s): libfreetype/include/freetype/internal/fthash.h libfreetype/src/base/fthash.c -Copyright 2000 Computing Research Labs, New Mexico State University -Copyright 2001-2015 +Copyright (C) 2000 Computing Research Labs, New Mexico State University +Copyright (C) 2001-2015 Francesco Zappa Nardelli diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h index a85151699d0..0667493fec6 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h @@ -4,7 +4,7 @@ * * ANSI-specific configuration file (specification only). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h index e607bce15c5..f6ef2618ded 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h @@ -4,7 +4,7 @@ * * Build macros of the FreeType 2 library. * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h index 4375c7a6ff3..d29a0a7cefb 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h @@ -4,7 +4,7 @@ * * User-selectable configuration macros (specification only). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -757,6 +757,22 @@ FT_BEGIN_HEADER #endif + /************************************************************************** + * + * Option `TT_CONFIG_OPTION_GPOS_KERNING` enables a basic GPOS kerning + * implementation (for TrueType fonts only). With this defined, FreeType + * is able to get kerning pair data from the GPOS 'kern' feature as well as + * legacy 'kern' tables; without this defined, FreeType will only be able + * to use legacy 'kern' tables. + * + * Note that FreeType does not support more advanced GPOS layout features; + * even the 'kern' feature implemented here doesn't handle more + * sophisticated kerning variants. Use a higher-level library like + * HarfBuzz instead for that. + */ +/* #define TT_CONFIG_OPTION_GPOS_KERNING */ + + /*************************************************************************/ /*************************************************************************/ /**** ****/ diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h index f65148a902e..e17aa7b89d5 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h @@ -5,7 +5,7 @@ * ANSI-specific library and header configuration file (specification * only). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h index 7258b508541..c27505ffc4b 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h @@ -4,7 +4,7 @@ * * FreeType integer types definitions. * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h index b77b96d5db8..07b6f915bd8 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h @@ -4,7 +4,7 @@ * * Mac/OS X support configuration header. * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h index 23d0fa6a329..f56581a6ee7 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h @@ -4,7 +4,7 @@ * * Define a set of compiler macros used in public FreeType headers. * - * Copyright (C) 2020-2023 by + * Copyright (C) 2020-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h b/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h index 92acf3794a7..58fc33dfe60 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h @@ -4,7 +4,7 @@ * * FreeType high-level API and common types (specification only). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -1322,9 +1322,13 @@ FT_BEGIN_HEADER * FT_FACE_FLAG_KERNING :: * The face contains kerning information. If set, the kerning distance * can be retrieved using the function @FT_Get_Kerning. Otherwise the - * function always returns the vector (0,0). Note that FreeType - * doesn't handle kerning data from the SFNT 'GPOS' table (as present - * in many OpenType fonts). + * function always returns the vector (0,0). + * + * Note that for TrueType fonts only, FreeType supports both the 'kern' + * table and the basic, pair-wise kerning feature from the 'GPOS' table + * (with `TT_CONFIG_OPTION_GPOS_KERNING` enabled), though FreeType does + * not support the more advanced GPOS layout features; use a library + * like HarfBuzz for those instead. * * FT_FACE_FLAG_FAST_GLYPHS :: * THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT. @@ -3767,87 +3771,18 @@ FT_BEGIN_HEADER * pixels and use the @FT_PIXEL_MODE_LCD_V mode. * * FT_RENDER_MODE_SDF :: - * This mode corresponds to 8-bit, single-channel signed distance field - * (SDF) bitmaps. Each pixel in the SDF grid is the value from the - * pixel's position to the nearest glyph's outline. The distances are - * calculated from the center of the pixel and are positive if they are - * filled by the outline (i.e., inside the outline) and negative - * otherwise. Check the note below on how to convert the output values - * to usable data. + * The positive (unsigned) 8-bit bitmap values can be converted to the + * single-channel signed distance field (SDF) by subtracting 128, with + * the positive and negative results corresponding to the inside and + * the outside of a glyph contour, respectively. The distance units are + * arbitrarily determined by an adjustable @spread property. * * @note: - * The selected render mode only affects vector glyphs of a font. + * The selected render mode only affects scalable vector glyphs of a font. * Embedded bitmaps often have a different pixel mode like * @FT_PIXEL_MODE_MONO. You can use @FT_Bitmap_Convert to transform them * into 8-bit pixmaps. * - * For @FT_RENDER_MODE_SDF the output bitmap buffer contains normalized - * distances that are packed into unsigned 8-bit values. To get pixel - * values in floating point representation use the following pseudo-C - * code for the conversion. - * - * ``` - * // Load glyph and render using FT_RENDER_MODE_SDF, - * // then use the output buffer as follows. - * - * ... - * FT_Byte buffer = glyph->bitmap->buffer; - * - * - * for pixel in buffer - * { - * // `sd` is the signed distance and `spread` is the current spread; - * // the default spread is 2 and can be changed. - * - * float sd = (float)pixel - 128.0f; - * - * - * // Convert to pixel values. - * sd = ( sd / 128.0f ) * spread; - * - * // Store `sd` in a buffer or use as required. - * } - * - * ``` - * - * FreeType has two rasterizers for generating SDF, namely: - * - * 1. `sdf` for generating SDF directly from glyph's outline, and - * - * 2. `bsdf` for generating SDF from rasterized bitmaps. - * - * Depending on the glyph type (i.e., outline or bitmap), one of the two - * rasterizers is chosen at runtime and used for generating SDFs. To - * force the use of `bsdf` you should render the glyph with any of the - * FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and - * then re-render with `FT_RENDER_MODE_SDF`. - * - * There are some issues with stability and possible failures of the SDF - * renderers (specifically `sdf`). - * - * 1. The `sdf` rasterizer is sensitive to really small features (e.g., - * sharp turns that are less than 1~pixel) and imperfections in the - * glyph's outline, causing artifacts in the final output. - * - * 2. The `sdf` rasterizer has limited support for handling intersecting - * contours and *cannot* handle self-intersecting contours whatsoever. - * Self-intersection happens when a single connected contour - * intersects itself at some point; having these in your font - * definitely poses a problem to the rasterizer and cause artifacts, - * too. - * - * 3. Generating SDF for really small glyphs may result in undesirable - * output; the pixel grid (which stores distance information) becomes - * too coarse. - * - * 4. Since the output buffer is normalized, precision at smaller spreads - * is greater than precision at larger spread values because the - * output range of [0..255] gets mapped to a smaller SDF range. A - * spread of~2 should be sufficient in most cases. - * - * Points (1) and (2) can be avoided by using the `bsdf` rasterizer, - * which is more stable than the `sdf` rasterizer in general. - * */ typedef enum FT_Render_Mode_ { @@ -4058,9 +3993,26 @@ FT_BEGIN_HEADER * out of the scope of this API function -- they can be implemented * through format-specific interfaces. * - * Kerning for OpenType fonts implemented in a 'GPOS' table is not - * supported; use @FT_HAS_KERNING to find out whether a font has data - * that can be extracted with `FT_Get_Kerning`. + * Note that, for TrueType fonts only, this can extract data from both + * the 'kern' table and the basic, pair-wise kerning feature from the + * GPOS table (with `TT_CONFIG_OPTION_GPOS_KERNING` enabled), though + * FreeType does not support the more advanced GPOS layout features; use + * a library like HarfBuzz for those instead. If a font has both a + * 'kern' table and kern features of a GPOS table, the 'kern' table will + * be used. + * + * Also note for right-to-left scripts, the functionality may differ for + * fonts with GPOS tables vs. 'kern' tables. For GPOS, right-to-left + * fonts typically use both a placement offset and an advance for pair + * positioning, which this API does not support, so it would output + * kerning values of zero; though if the right-to-left font used only + * advances in GPOS pair positioning, then this API could output kerning + * values for it, but it would use `left_glyph` to mean the first glyph + * for that case. Whereas 'kern' tables are always advance-only and + * always store the left glyph first. + * + * Use @FT_HAS_KERNING to find out whether a font has data that can be + * extracted with `FT_Get_Kerning`. */ FT_EXPORT( FT_Error ) FT_Get_Kerning( FT_Face face, @@ -5222,7 +5174,7 @@ FT_BEGIN_HEADER */ #define FREETYPE_MAJOR 2 #define FREETYPE_MINOR 13 -#define FREETYPE_PATCH 2 +#define FREETYPE_PATCH 3 /************************************************************************** diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h index 4560ded6dcb..85b8ba2554b 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h @@ -4,7 +4,7 @@ * * Quick computation of advance widths (specification only). * - * Copyright (C) 2008-2023 by + * Copyright (C) 2008-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h index fc21740fc2b..12bbfa63a62 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h @@ -4,7 +4,7 @@ * * FreeType exact bbox computation (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h index e8ce6431285..6f63b0b1e78 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h @@ -4,7 +4,7 @@ * * FreeType API for accessing BDF-specific strings (specification). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h index eb6b4b1eebe..df9d462652e 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h @@ -4,7 +4,7 @@ * * FreeType utility functions for bitmaps (specification). * - * Copyright (C) 2004-2023 by + * Copyright (C) 2004-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h index ef229390224..96b2a90fc59 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h @@ -4,7 +4,7 @@ * * FreeType API for accessing CID font information (specification). * - * Copyright (C) 2007-2023 by + * Copyright (C) 2007-2024 by * Dereg Clegg and Michael Toftdal. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h index eae200fdf14..420720ddf22 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h @@ -4,7 +4,7 @@ * * FreeType's glyph color management (specification). * - * Copyright (C) 2018-2023 by + * Copyright (C) 2018-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h index 7af7465bc76..1b7f539f5e2 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h @@ -4,7 +4,7 @@ * * FreeType API for controlling driver modules (specification only). * - * Copyright (C) 2017-2023 by + * Copyright (C) 2017-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -817,6 +817,80 @@ FT_BEGIN_HEADER * 2.5 */ + + /************************************************************************** + * + * @property: + * spread + * + * @description: + * This property of the 'sdf' and 'bsdf' renderers defines how the signed + * distance field (SDF) is represented in the output bitmap. The output + * values are calculated as follows, '128 * ( SDF / spread + 1 )', with + * the result clamped to the 8-bit range [0..255]. Therefore, 'spread' + * is also the maximum euclidean distance from the edge after which the + * values are clamped. The spread is specified in pixels with the + * default value of 8. For accurate SDF texture mapping (interpolation), + * the spread should be large enough to accommodate the target grid unit. + * + * @example: + * The following example code demonstrates how to set the SDF spread + * (omitting the error handling). + * + * ``` + * FT_Library library; + * FT_Int spread = 2; + * + * + * FT_Init_FreeType( &library ); + * + * FT_Property_Set( library, "sdf", "spread", &spread ); + * ``` + * + * @note: + * FreeType has two rasterizers for generating SDF, namely: + * + * 1. `sdf` for generating SDF directly from glyph's outline, and + * + * 2. `bsdf` for generating SDF from rasterized bitmaps. + * + * Depending on the glyph type (i.e., outline or bitmap), one of the two + * rasterizers is chosen at runtime and used for generating SDFs. To + * force the use of `bsdf` you should render the glyph with any of the + * FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and + * then re-render with `FT_RENDER_MODE_SDF`. + * + * There are some issues with stability and possible failures of the SDF + * renderers (specifically `sdf`). + * + * 1. The `sdf` rasterizer is sensitive to really small features (e.g., + * sharp turns that are less than 1~pixel) and imperfections in the + * glyph's outline, causing artifacts in the final output. + * + * 2. The `sdf` rasterizer has limited support for handling intersecting + * contours and *cannot* handle self-intersecting contours whatsoever. + * Self-intersection happens when a single connected contour + * intersects itself at some point; having these in your font + * definitely poses a problem to the rasterizer and cause artifacts, + * too. + * + * 3. Generating SDF for really small glyphs may result in undesirable + * output; the pixel grid (which stores distance information) becomes + * too coarse. + * + * 4. Since the output buffer is normalized, precision at smaller spreads + * is greater than precision at larger spread values because the + * output range of [0..255] gets mapped to a smaller SDF range. A + * spread of~2 should be sufficient in most cases. + * + * Points (1) and (2) can be avoided by using the `bsdf` rasterizer, + * which is more stable than the `sdf` rasterizer in general. + * + * @since: + * 2.11 + */ + + /************************************************************************** * * @property: diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h b/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h index d59b3cc2da2..710ca91bbdd 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h @@ -4,7 +4,7 @@ * * FreeType error codes (specification). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h b/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h index 15ef3f76b59..27c0ece5c1c 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h @@ -4,7 +4,7 @@ * * FreeType error code handling (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h index c0018fc830c..7c8b0874a81 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h @@ -4,7 +4,7 @@ * * Support functions for font formats. * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h index d5f19add8f2..30e5a9bf82b 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h @@ -4,7 +4,7 @@ * * Access of TrueType's 'gasp' table (specification). * - * Copyright (C) 2007-2023 by + * Copyright (C) 2007-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h index 4658895f7a9..dc1eb8873ae 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h @@ -4,7 +4,7 @@ * * FreeType convenience functions to handle glyphs (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h index 443ec29db1b..9516dc030ac 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h @@ -4,7 +4,7 @@ * * Gzip-compressed stream support. * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h index 6baa812560e..2b4b4ac60ae 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h @@ -5,7 +5,7 @@ * FreeType glyph image formats and default raster interface * (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -21,6 +21,11 @@ * Note: A 'raster' is simply a scan-line converter, used to render * `FT_Outline`s into `FT_Bitmap`s. * + * Note: This file can be used for `STANDALONE_` compilation of raster + * (B/W) and smooth (anti-aliased) renderers. Therefore, it must + * rely on standard variable types only instead of aliases in + * `fttypes.h`. + * */ @@ -318,7 +323,7 @@ FT_BEGIN_HEADER * * If bit~2 is set, bits 5-7 contain the drop-out mode (as defined in * the OpenType specification; the value is the same as the argument to - * the 'SCANMODE' instruction). + * the 'SCANTYPE' instruction). * * Bits 3 and~4 are reserved for internal purposes. * @@ -341,14 +346,14 @@ FT_BEGIN_HEADER */ typedef struct FT_Outline_ { - short n_contours; /* number of contours in glyph */ - short n_points; /* number of points in the glyph */ + unsigned short n_contours; /* number of contours in glyph */ + unsigned short n_points; /* number of points in the glyph */ - FT_Vector* points; /* the outline's points */ - char* tags; /* the points flags */ - short* contours; /* the contour end points */ + FT_Vector* points; /* the outline's points */ + unsigned char* tags; /* the points flags */ + unsigned short* contours; /* the contour end points */ - int flags; /* outline masks */ + int flags; /* outline masks */ } FT_Outline; @@ -356,8 +361,8 @@ FT_BEGIN_HEADER /* Following limits must be consistent with */ /* FT_Outline.{n_contours,n_points} */ -#define FT_OUTLINE_CONTOURS_MAX SHRT_MAX -#define FT_OUTLINE_POINTS_MAX SHRT_MAX +#define FT_OUTLINE_CONTOURS_MAX USHRT_MAX +#define FT_OUTLINE_POINTS_MAX USHRT_MAX /************************************************************************** @@ -434,8 +439,8 @@ FT_BEGIN_HEADER * rasterizer; see the `tags` field in @FT_Outline. * * Please refer to the description of the 'SCANTYPE' instruction in the - * OpenType specification (in file `ttinst1.doc`) how simple drop-outs, - * smart drop-outs, and stubs are defined. + * [OpenType specification](https://learn.microsoft.com/en-us/typography/opentype/spec/tt_instructions#scantype) + * how simple drop-outs, smart drop-outs, and stubs are defined. */ #define FT_OUTLINE_NONE 0x0 #define FT_OUTLINE_OWNER 0x1 diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h index 2d4f5def241..816581b78eb 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h @@ -4,7 +4,7 @@ * * FreeType incremental loading (specification). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h index d3723e16f67..25274dc4ac2 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h @@ -5,7 +5,7 @@ * FreeType API for color filtering of subpixel bitmap glyphs * (specification). * - * Copyright (C) 2006-2023 by + * Copyright (C) 2006-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h index b5531313359..972fbfa2fe4 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h @@ -4,7 +4,7 @@ * * Generic list support for FreeType (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h index 53b8b896427..1813cfc2c27 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h @@ -4,7 +4,7 @@ * * Additional debugging APIs. * - * Copyright (C) 2020-2023 by + * Copyright (C) 2020-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h index a91e38f9ea7..e4efde33dd8 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h @@ -4,7 +4,7 @@ * * Additional Mac-specific API. * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h index d145128a9bc..35ed039c89b 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h @@ -4,7 +4,7 @@ * * FreeType Multiple Master font interface (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -19,8 +19,13 @@ #ifndef FTMM_H_ #define FTMM_H_ +#include <freetype/freetype.h> -#include <freetype/t1tables.h> +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif FT_BEGIN_HEADER @@ -53,6 +58,30 @@ FT_BEGIN_HEADER */ + /************************************************************************** + * + * @enum: + * T1_MAX_MM_XXX + * + * @description: + * Multiple Masters limits as defined in their specifications. + * + * @values: + * T1_MAX_MM_AXIS :: + * The maximum number of Multiple Masters axes. + * + * T1_MAX_MM_DESIGNS :: + * The maximum number of Multiple Masters designs. + * + * T1_MAX_MM_MAP_POINTS :: + * The maximum number of elements in a design map. + * + */ +#define T1_MAX_MM_AXIS 4 +#define T1_MAX_MM_DESIGNS 16 +#define T1_MAX_MM_MAP_POINTS 20 + + /************************************************************************** * * @struct: diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h index c8f0c2c2a45..0ee715898f7 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h @@ -4,7 +4,7 @@ * * FreeType modules public interface (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h index c8c892dcce8..6722fbf8b70 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h @@ -4,7 +4,7 @@ * * FreeType module error offsets (specification). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h index f9329ca40c9..44e94b4f5bb 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h @@ -5,7 +5,7 @@ * Support for the FT_Outline type used to store glyph shapes of * most scalable font formats (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -112,7 +112,7 @@ FT_BEGIN_HEADER * Degenerate contours, segments, and Bezier arcs may be reported. In * most cases, it is best to filter these out before using the outline * for stroking or other path modification purposes (which may cause - * degenerate segments to become non-degenrate and visible, like when + * degenerate segments to become non-degenerate and visible, like when * stroke caps are used or the path is otherwise outset). Some glyph * outlines may contain deliberate degenerate single points for mark * attachement. diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h index 6a9f243bc90..43bf69c202f 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h @@ -4,7 +4,7 @@ * * FreeType API for possible FT_Parameter tags (specification only). * - * Copyright (C) 2017-2023 by + * Copyright (C) 2017-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h index 0b6fad32e84..dc5018a1b54 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h @@ -4,7 +4,7 @@ * * FreeType renderer modules public interface (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h index 7bfb1aed4c2..4ef5c7955df 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h @@ -4,7 +4,7 @@ * * FreeType size objects management (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h index 9d5d22bb255..d5d5cd93103 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h @@ -7,7 +7,7 @@ * * This is _not_ used to retrieve glyph names! * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h index b3d90802a56..41626dc9d7b 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h @@ -4,7 +4,7 @@ * * FreeType path stroker (specification). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h index af90967dda0..43081b6c330 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h @@ -5,7 +5,7 @@ * FreeType synthesizing code for emboldening and slanting * (specification). * - * Copyright (C) 2000-2023 by + * Copyright (C) 2000-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h index 3a08f4912c9..1eacb3af398 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h @@ -4,7 +4,7 @@ * * FreeType low-level system interface definition (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h b/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h index 294981a6f31..a5299e938d4 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h @@ -4,7 +4,7 @@ * * FreeType trigonometric functions (specification). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h index 5b109f0c73c..27815143a64 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h @@ -4,7 +4,7 @@ * * FreeType simple types definitions (specification only). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h index bf9c8b7cf2a..8865d53b389 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h @@ -4,7 +4,7 @@ * * High-level 'autohint' module-specific interface (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h index 50d53538498..36b0390a5a5 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h @@ -4,7 +4,7 @@ * * Basic OpenType/CFF object type definitions (specification). * - * Copyright (C) 2017-2023 by + * Copyright (C) 2017-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h index c2521764caa..ef2e8e7569c 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h @@ -5,7 +5,7 @@ * Basic OpenType/CFF type definitions and interface (specification * only). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -248,10 +248,10 @@ FT_BEGIN_HEADER FT_Byte num_family_blues; FT_Byte num_family_other_blues; - FT_Pos blue_values[14]; - FT_Pos other_blues[10]; - FT_Pos family_blues[14]; - FT_Pos family_other_blues[10]; + FT_Fixed blue_values[14]; + FT_Fixed other_blues[10]; + FT_Fixed family_blues[14]; + FT_Fixed family_other_blues[10]; FT_Fixed blue_scale; FT_Pos blue_shift; diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h index 6f67650979e..876f66e2561 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h @@ -4,7 +4,7 @@ * * Compiler-specific macro definitions used internally by FreeType. * - * Copyright (C) 2020-2023 by + * Copyright (C) 2020-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h index d9aea236024..71128a2df90 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h @@ -4,7 +4,7 @@ * * Arithmetic computations (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -415,7 +415,7 @@ FT_BEGIN_HEADER #define FT_MSB( x ) ( 31 - _CountLeadingZeros( x ) ) -#elif defined( _M_ARM64 ) || defined( _M_ARM ) +#elif defined( _M_ARM64 ) || defined( _M_ARM ) || defined( _M_ARM64EC ) #include <intrin.h> #pragma intrinsic( _CountLeadingZeros ) @@ -455,6 +455,12 @@ FT_BEGIN_HEADER #define FT_MSB( x ) FT_MSB_i386( x ) +#elif defined( __SunOS_5_11 ) + +#include <string.h> + +#define FT_MSB( x ) ( fls( x ) - 1 ) + #elif defined( __DECC ) || defined( __DECCXX ) #include <builtins.h> @@ -489,8 +495,6 @@ FT_BEGIN_HEADER FT_Fixed y ); -#if 0 - /************************************************************************** * * @function: @@ -507,12 +511,11 @@ FT_BEGIN_HEADER * The result of 'sqrt(x)'. * * @note: - * This function is not very fast. + * This function is slow and should be avoided. Consider @FT_Hypot or + * @FT_Vector_NormLen instead. */ - FT_BASE( FT_Int32 ) - FT_SqrtFixed( FT_Int32 x ); - -#endif /* 0 */ + FT_BASE( FT_UInt32 ) + FT_SqrtFixed( FT_UInt32 x ); #define INT_TO_F26DOT6( x ) ( (FT_Long)(x) * 64 ) /* << 6 */ diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h index 4e013ba1e26..d7fa8dc93cf 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h @@ -4,7 +4,7 @@ * * Debugging and logging component (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h index 9001c07ad0b..5609b3ef12b 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h @@ -4,7 +4,7 @@ * * FreeType internal font driver interface (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h index 36e5509f9ea..f1c155b162c 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h @@ -4,7 +4,7 @@ * * The FreeType glyph loader (specification). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h index 5eb1d21ff67..4e05a29f13a 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h @@ -4,7 +4,7 @@ * * The FreeType memory management macros (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg * * This file is part of the FreeType project, and may only be used, @@ -371,8 +371,11 @@ extern "C++" #define FT_STRDUP( dst, str ) \ FT_MEM_SET_ERROR( FT_MEM_STRDUP( dst, str ) ) -#define FT_MEM_DUP( dst, address, size ) \ - (dst) = ft_mem_dup( memory, (address), (FT_ULong)(size), &error ) +#define FT_MEM_DUP( dst, address, size ) \ + FT_ASSIGNP_INNER( dst, ft_mem_dup( memory, \ + (address), \ + (FT_ULong)(size), \ + &error ) ) #define FT_DUP( dst, address, size ) \ FT_MEM_SET_ERROR( FT_MEM_DUP( dst, address, size ) ) diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h index c4b21d6144e..8449e7a010d 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h @@ -5,7 +5,7 @@ * OpenType Variations type definitions for internal use * with the multi-masters service (specification). * - * Copyright (C) 2022-2023 by + * Copyright (C) 2022-2024 by * David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and * Dominik Röttsches. * diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h index 28bc9b65f05..a1e93298fdb 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h @@ -4,7 +4,7 @@ * * The FreeType private base classes (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -604,12 +604,6 @@ FT_BEGIN_HEADER #define FT_FACE_MEMORY( x ) FT_FACE( x )->memory #define FT_FACE_STREAM( x ) FT_FACE( x )->stream -#define FT_SIZE_FACE( x ) FT_SIZE( x )->face -#define FT_SLOT_FACE( x ) FT_SLOT( x )->face - -#define FT_FACE_SLOT( x ) FT_FACE( x )->glyph -#define FT_FACE_SIZE( x ) FT_FACE( x )->size - /************************************************************************** * diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h index 1d5b287ad20..4f11aa16ba1 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h @@ -4,7 +4,7 @@ * * Get and set properties of PostScript drivers (specification). * - * Copyright (C) 2017-2023 by + * Copyright (C) 2017-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h index e96459921ef..05c1d6c48b5 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h @@ -4,7 +4,7 @@ * * Embedded resource forks accessor (specification). * - * Copyright (C) 2004-2023 by + * Copyright (C) 2004-2024 by * Masatake YAMATO and Redhat K.K. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h index 1e85d6d3856..8c35dbd7139 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h @@ -4,7 +4,7 @@ * * The FreeType services (specification only). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h index 88e19287c80..fd52f767ef7 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h @@ -4,7 +4,7 @@ * * Stream handling (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h index 319fe56fd2d..42595a29ff3 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h @@ -4,7 +4,7 @@ * * Tracing handling (specification only). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -64,6 +64,7 @@ FT_TRACE_DEF( ttbdf ) /* TrueType embedded BDF (ttbdf.c) */ FT_TRACE_DEF( ttcmap ) /* charmap handler (ttcmap.c) */ FT_TRACE_DEF( ttcolr ) /* glyph layer table (ttcolr.c) */ FT_TRACE_DEF( ttcpal ) /* color palette table (ttcpal.c) */ +FT_TRACE_DEF( ttgpos ) /* GPOS handler (ttgpos.c) */ FT_TRACE_DEF( ttsvg ) /* OpenType SVG table (ttsvg.c) */ FT_TRACE_DEF( ttkern ) /* kerning handler (ttkern.c) */ FT_TRACE_DEF( ttload ) /* basic TrueType tables (ttload.c) */ diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h index e98ee4e4737..a1312f2aba6 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h @@ -4,7 +4,7 @@ * * FreeType validation support (specification). * - * Copyright (C) 2004-2023 by + * Copyright (C) 2004-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h index dfb1987f868..745d2cb56b7 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h @@ -5,7 +5,7 @@ * Auxiliary functions and data structures related to PostScript fonts * (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -225,6 +225,7 @@ FT_BEGIN_HEADER typedef enum T1_FieldLocation_ { + T1_FIELD_LOCATION_NONE = 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_LOCATION_FONT_DICT, T1_FIELD_LOCATION_FONT_EXTRA, @@ -249,6 +250,7 @@ FT_BEGIN_HEADER /* structure type used to model object fields */ typedef struct T1_FieldRec_ { + FT_UInt len; /* field identifier length */ const char* ident; /* field identifier */ T1_FieldLocation location; T1_FieldType type; /* type of field */ @@ -273,8 +275,9 @@ FT_BEGIN_HEADER #define T1_NEW_SIMPLE_FIELD( _ident, _type, _fname, _dict ) \ { \ + sizeof ( _ident ) - 1, \ _ident, T1CODE, _type, \ - 0, \ + NULL, \ FT_FIELD_OFFSET( _fname ), \ FT_FIELD_SIZE( _fname ), \ 0, 0, \ @@ -283,6 +286,7 @@ FT_BEGIN_HEADER #define T1_NEW_CALLBACK_FIELD( _ident, _reader, _dict ) \ { \ + sizeof ( _ident ) - 1, \ _ident, T1CODE, T1_FIELD_TYPE_CALLBACK, \ (T1_Field_ParseFunc)_reader, \ 0, 0, \ @@ -292,8 +296,9 @@ FT_BEGIN_HEADER #define T1_NEW_TABLE_FIELD( _ident, _type, _fname, _max, _dict ) \ { \ + sizeof ( _ident ) - 1, \ _ident, T1CODE, _type, \ - 0, \ + NULL, \ FT_FIELD_OFFSET( _fname ), \ FT_FIELD_SIZE_DELTA( _fname ), \ _max, \ @@ -303,8 +308,9 @@ FT_BEGIN_HEADER #define T1_NEW_TABLE_FIELD2( _ident, _type, _fname, _max, _dict ) \ { \ + sizeof ( _ident ) - 1, \ _ident, T1CODE, _type, \ - 0, \ + NULL, \ FT_FIELD_OFFSET( _fname ), \ FT_FIELD_SIZE_DELTA( _fname ), \ _max, 0, \ @@ -354,6 +360,13 @@ FT_BEGIN_HEADER #define T1_FIELD_CALLBACK( _ident, _name, _dict ) \ T1_NEW_CALLBACK_FIELD( _ident, _name, _dict ) +#define T1_FIELD_ZERO \ + { \ + 0, \ + NULL, T1_FIELD_LOCATION_NONE, T1_FIELD_TYPE_NONE, \ + NULL, 0, 0, 0, 0, 0 \ + } + /*************************************************************************/ /*************************************************************************/ diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h index ededc4c72e7..dba6c7303fd 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h @@ -6,7 +6,7 @@ * recorders (specification only). These are used to support native * T1/T2 hints in the 'type1', 'cid', and 'cff' font drivers. * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h index bf0c1dcc714..89e9c2e5de8 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h @@ -4,7 +4,7 @@ * * The FreeType BDF services (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h index 4a20498ee0c..3cb483c344f 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h @@ -4,7 +4,7 @@ * * The FreeType CFF tables loader service (specification). * - * Copyright (C) 2017-2023 by + * Copyright (C) 2017-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h index 06d0cb8fd62..8362cb8724d 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h @@ -4,7 +4,7 @@ * * The FreeType CID font services (specification). * - * Copyright (C) 2007-2023 by + * Copyright (C) 2007-2024 by * Derek Clegg and Michael Toftdal. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h index bc45e80568f..6b837e79fcd 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h @@ -4,7 +4,7 @@ * * The FreeType font format service (specification only). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h index 6437abfbf2e..6126ec9ada4 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h @@ -4,7 +4,7 @@ * * The FreeType glyph dictionary services (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h index 31016afe0d0..29cf5528189 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h @@ -4,7 +4,7 @@ * * FreeType API for validating TrueTypeGX/AAT tables (specification). * - * Copyright (C) 2004-2023 by + * Copyright (C) 2004-2024 by * Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h index bcabbc3e68f..ac1bc30c412 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h @@ -4,7 +4,7 @@ * * The FreeType Kerning service (specification). * - * Copyright (C) 2006-2023 by + * Copyright (C) 2006-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h index 167617ebb3d..8b3563b25ca 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h @@ -4,7 +4,7 @@ * * The FreeType services for metrics variations (specification). * - * Copyright (C) 2016-2023 by + * Copyright (C) 2016-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h index 7e76ab8324e..5288fadf375 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h @@ -4,7 +4,7 @@ * * The FreeType Multiple Masters and GX var services (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h index a4683cd5fb6..7aea7ec11f0 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h @@ -4,7 +4,7 @@ * * The FreeType OpenType validation service (specification). * - * Copyright (C) 2004-2023 by + * Copyright (C) 2004-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h index fd189c7de77..b2fac6d086b 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h @@ -4,7 +4,7 @@ * * Internal PFR service functions (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h index 2b8f6dfecfb..d19f3adc6d5 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h @@ -4,7 +4,7 @@ * * The FreeType PostScript name services (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h index 932ce32e03d..ba39c0dd4da 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h @@ -4,7 +4,7 @@ * * The FreeType property service (specification). * - * Copyright (C) 2012-2023 by + * Copyright (C) 2012-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h index 6e599f3aabe..d4908ee41aa 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h @@ -4,7 +4,7 @@ * * The FreeType PostScript charmap service (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h index 09c4cdccc53..2aadcdd02a1 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h @@ -4,7 +4,7 @@ * * The FreeType PostScript info service (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h index f98df2ef5fe..9e0f4ff202e 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h @@ -4,7 +4,7 @@ * * The FreeType SFNT table loading service (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h index 5f9eb02d665..250886bcc5d 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h @@ -4,7 +4,7 @@ * * The FreeType TrueType/sfnt cmap extra information service. * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * Masatake YAMATO, Redhat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h index ad577cb2904..14967529a9a 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h @@ -4,7 +4,7 @@ * * The FreeType TrueType engine query service (specification). * - * Copyright (C) 2006-2023 by + * Copyright (C) 2006-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h index ca6fff74444..f190b3985d0 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h @@ -4,7 +4,7 @@ * * The FreeType TrueType glyph service. * - * Copyright (C) 2007-2023 by + * Copyright (C) 2007-2024 by * David Turner. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h index 002923f8c91..49f3fb7f775 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h @@ -4,7 +4,7 @@ * * The FreeType Windows FNT/FONT service (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h index a2d4e15baaf..35e4e73af02 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h @@ -4,7 +4,7 @@ * * High-level 'sfnt' driver interface (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -924,6 +924,7 @@ FT_BEGIN_HEADER /* this field was called `load_kerning' up to version 2.1.10 */ TT_Load_Table_Func load_kern; + TT_Load_Table_Func load_gpos; TT_Load_Table_Func load_gasp; TT_Load_Table_Func load_pclt; @@ -944,6 +945,8 @@ FT_BEGIN_HEADER /* new elements introduced after version 2.1.10 */ + TT_Face_GetKerningFunc get_gpos_kerning; + /* load the font directory, i.e., the offset table and */ /* the table directory */ TT_Load_Table_Func load_font_dir; @@ -1002,6 +1005,7 @@ FT_BEGIN_HEADER load_name_, \ free_name_, \ load_kern_, \ + load_gpos_, \ load_gasp_, \ load_pclt_, \ load_bhed_, \ @@ -1009,6 +1013,7 @@ FT_BEGIN_HEADER get_psname_, \ free_psnames_, \ get_kerning_, \ + get_gpos_kerning_, \ load_font_dir_, \ load_hmtx_, \ load_eblc_, \ @@ -1050,6 +1055,7 @@ FT_BEGIN_HEADER load_name_, \ free_name_, \ load_kern_, \ + load_gpos_, \ load_gasp_, \ load_pclt_, \ load_bhed_, \ @@ -1057,6 +1063,7 @@ FT_BEGIN_HEADER get_psname_, \ free_psnames_, \ get_kerning_, \ + get_gpos_kerning_, \ load_font_dir_, \ load_hmtx_, \ load_eblc_, \ diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h index f464b2c0583..68c99efb10a 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h @@ -4,7 +4,7 @@ * * Interface of ot-svg module (specification only). * - * Copyright (C) 2022-2023 by + * Copyright (C) 2022-2024 by * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h index b9c94398fd1..1821ae5cc83 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h @@ -5,7 +5,7 @@ * Basic Type1/Type2 type definitions and interface (specification * only). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -21,7 +21,7 @@ #define T1TYPES_H_ -#include <freetype/t1tables.h> +#include <freetype/ftmm.h> #include <freetype/internal/pshints.h> #include <freetype/internal/ftserv.h> #include <freetype/internal/fthash.h> @@ -137,6 +137,54 @@ FT_BEGIN_HEADER } CID_SubrsRec, *CID_Subrs; + /* this structure is used to store the BlendDesignMap entry for an axis */ + typedef struct PS_DesignMap_ + { + FT_Byte num_points; + FT_Long* design_points; + FT_Fixed* blend_points; + + } PS_DesignMapRec, *PS_DesignMap; + + /* backward compatible definition */ + typedef PS_DesignMapRec T1_DesignMap; + + + typedef struct PS_BlendRec_ + { + FT_UInt num_designs; + FT_UInt num_axis; + + FT_String* axis_names[T1_MAX_MM_AXIS]; + FT_Fixed* design_pos[T1_MAX_MM_DESIGNS]; + PS_DesignMapRec design_map[T1_MAX_MM_AXIS]; + + FT_Fixed* weight_vector; + FT_Fixed* default_weight_vector; + + PS_FontInfo font_infos[T1_MAX_MM_DESIGNS + 1]; + PS_Private privates [T1_MAX_MM_DESIGNS + 1]; + + FT_ULong blend_bitflags; + + FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1]; + + /* since 2.3.0 */ + + /* undocumented, optional: the default design instance; */ + /* corresponds to default_weight_vector -- */ + /* num_default_design_vector == 0 means it is not present */ + /* in the font and associated metrics files */ + FT_UInt default_design_vector[T1_MAX_MM_DESIGNS]; + FT_UInt num_default_design_vector; + + } PS_BlendRec, *PS_Blend; + + + /* backward compatible definition */ + typedef PS_BlendRec T1_Blend; + + /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h index b9788c7831e..7053e656a7e 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h @@ -5,7 +5,7 @@ * Basic SFNT/TrueType type definitions and interface (specification * only). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -24,6 +24,7 @@ #include <freetype/tttables.h> #include <freetype/internal/ftobjs.h> #include <freetype/ftcolor.h> +#include "freetype/fttypes.h" #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT #include <freetype/ftmm.h> @@ -1581,6 +1582,11 @@ FT_BEGIN_HEADER FT_UInt32 kern_avail_bits; FT_UInt32 kern_order_bits; +#ifdef TT_CONFIG_OPTION_GPOS_KERNING + FT_Byte* gpos_table; + FT_Bool gpos_kerning_available; +#endif + #ifdef TT_CONFIG_OPTION_BDF TT_BDFRec bdf; #endif /* TT_CONFIG_OPTION_BDF */ @@ -1649,9 +1655,9 @@ FT_BEGIN_HEADER { FT_Memory memory; FT_UShort max_points; - FT_Short max_contours; + FT_UShort max_contours; FT_UShort n_points; /* number of points in zone */ - FT_Short n_contours; /* number of contours */ + FT_UShort n_contours; /* number of contours */ FT_Vector* org; /* original point coordinates */ FT_Vector* cur; /* current point coordinates */ diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h index 0c1d8eeaf8c..4a169d12f57 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h @@ -5,7 +5,7 @@ * Basic WOFF/WOFF2 type definitions and interface (specification * only). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h b/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h index bfe9a6ab74e..9d356938cc7 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h @@ -4,7 +4,7 @@ * * Interface for OT-SVG support related things (specification). * - * Copyright (C) 2022-2023 by + * Copyright (C) 2022-2024 by * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h b/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h index 1aecfbbd902..fbd558aa34d 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h @@ -5,7 +5,7 @@ * Basic Type 1/Type 2 tables definitions and interface (specification * only). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -269,64 +269,6 @@ FT_BEGIN_HEADER /* */ - /* maximum number of Multiple Masters designs, as defined in the spec */ -#define T1_MAX_MM_DESIGNS 16 - - /* maximum number of Multiple Masters axes, as defined in the spec */ -#define T1_MAX_MM_AXIS 4 - - /* maximum number of elements in a design map */ -#define T1_MAX_MM_MAP_POINTS 20 - - - /* this structure is used to store the BlendDesignMap entry for an axis */ - typedef struct PS_DesignMap_ - { - FT_Byte num_points; - FT_Long* design_points; - FT_Fixed* blend_points; - - } PS_DesignMapRec, *PS_DesignMap; - - /* backward compatible definition */ - typedef PS_DesignMapRec T1_DesignMap; - - - typedef struct PS_BlendRec_ - { - FT_UInt num_designs; - FT_UInt num_axis; - - FT_String* axis_names[T1_MAX_MM_AXIS]; - FT_Fixed* design_pos[T1_MAX_MM_DESIGNS]; - PS_DesignMapRec design_map[T1_MAX_MM_AXIS]; - - FT_Fixed* weight_vector; - FT_Fixed* default_weight_vector; - - PS_FontInfo font_infos[T1_MAX_MM_DESIGNS + 1]; - PS_Private privates [T1_MAX_MM_DESIGNS + 1]; - - FT_ULong blend_bitflags; - - FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1]; - - /* since 2.3.0 */ - - /* undocumented, optional: the default design instance; */ - /* corresponds to default_weight_vector -- */ - /* num_default_design_vector == 0 means it is not present */ - /* in the font and associated metrics files */ - FT_UInt default_design_vector[T1_MAX_MM_DESIGNS]; - FT_UInt num_default_design_vector; - - } PS_BlendRec, *PS_Blend; - - - /* backward compatible definition */ - typedef PS_BlendRec T1_Blend; - - /************************************************************************** * * @struct: diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h b/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h index e31c68b9baf..d5d470e380f 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h @@ -4,7 +4,7 @@ * * TrueType name ID definitions (specification only). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h b/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h index a9f60e76201..2cf0ff1bc61 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h @@ -5,7 +5,7 @@ * Basic SFNT/TrueType tables definitions and interface * (specification only). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -838,8 +838,9 @@ FT_BEGIN_HEADER * The target charmap. * * @return: - * The format of `charmap`. If `charmap` doesn't belong to an SFNT face, - * return -1. + * The format of `charmap`. If `charmap` doesn't belong to an SFNT face + * (including the synthetic Unicode charmap sometimes created by + * FreeType), return -1. */ FT_EXPORT( FT_Long ) FT_Get_CMap_Format( FT_CharMap charmap ); diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h b/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h index 9bf4fca23fb..da0af5d3f23 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h @@ -4,7 +4,7 @@ * * Tags for TrueType and OpenType tables (specification only). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/ft2build.h b/src/java.desktop/share/native/libfreetype/include/ft2build.h index 58491ceea1f..d3d7685039c 100644 --- a/src/java.desktop/share/native/libfreetype/include/ft2build.h +++ b/src/java.desktop/share/native/libfreetype/include/ft2build.h @@ -4,7 +4,7 @@ * * FreeType 2 build and setup macros. * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c index d7655b9b99e..ea83969cdc9 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c @@ -7,7 +7,7 @@ * * Auto-fitter data for blue strings (body). * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin index d561c5093b7..d2270fac744 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin @@ -4,7 +4,7 @@ * * Auto-fitter data for blue strings (body). * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat index 8299baa2591..88bab2632ab 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat @@ -2,7 +2,7 @@ // // Auto-fitter data for blue strings. // -// Copyright (C) 2013-2023 by +// Copyright (C) 2013-2024 by // David Turner, Robert Wilhelm, and Werner Lemberg. // // This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h index 76f2f47cb00..2aa9d0984ef 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h @@ -7,7 +7,7 @@ * * Auto-fitter data for blue strings (specification). * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin index 6a31298e65f..38031505a85 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin @@ -4,7 +4,7 @@ * * Auto-fitter data for blue strings (specification). * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c index f414289adcd..869b60487c2 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for CJK writing system (body). * - * Copyright (C) 2006-2023 by + * Copyright (C) 2006-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h index f380ef6e032..bc5aaf12e6e 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for CJK writing system (specification). * - * Copyright (C) 2006-2023 by + * Copyright (C) 2006-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -84,7 +84,7 @@ FT_BEGIN_HEADER /* used for horizontal metrics too for CJK */ FT_Bool control_overshoot; FT_UInt blue_count; - AF_CJKBlueRec blues[AF_BLUE_STRINGSET_MAX]; + AF_CJKBlueRec blues[AF_BLUE_STRINGSET_MAX_LEN]; FT_Fixed org_scale; FT_Pos org_delta; diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h b/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h index 102ed427828..7980cf2e979 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h @@ -4,7 +4,7 @@ * * Auto-fitter coverages (specification only). * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c index a4629b528dc..ad667d2edc7 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c @@ -5,7 +5,7 @@ * Auto-fitter dummy routines to be used if no hinting should be * performed (body). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h index a7af3f62c9e..613c2f88a38 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h @@ -5,7 +5,7 @@ * Auto-fitter dummy routines to be used if no hinting should be * performed (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h b/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h index 88faf05c950..ae584ff06db 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h @@ -4,7 +4,7 @@ * * Autofitter error codes (specification only). * - * Copyright (C) 2005-2023 by + * Copyright (C) 2005-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c index b1957570f03..b7403fa65e1 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c @@ -4,7 +4,7 @@ * * Auto-fitter routines to compute global hinting values (body). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h index 66170e419dd..ddb54c89b27 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h @@ -5,7 +5,7 @@ * Auto-fitter routines to compute global hinting values * (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c index e4a378fbf74..96ffe343aa4 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines (body). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -979,8 +979,8 @@ /* compute coordinates & Bezier flags, next and prev */ { FT_Vector* vec = outline->points; - char* tag = outline->tags; - FT_Short endpoint = outline->contours[0]; + FT_Byte* tag = outline->tags; + FT_UShort endpoint = outline->contours[0]; AF_Point end = points + endpoint; AF_Point prev = end; FT_Int contour_index = 0; @@ -1046,16 +1046,16 @@ /* set up the contours array */ { - AF_Point* contour = hints->contours; - AF_Point* contour_limit = contour + hints->num_contours; - short* end = outline->contours; - short idx = 0; + AF_Point* contour = hints->contours; + AF_Point* contour_limit = contour + hints->num_contours; + FT_UShort* end = outline->contours; + FT_Int idx = 0; for ( ; contour < contour_limit; contour++, end++ ) { contour[0] = points + idx; - idx = (short)( end[0] + 1 ); + idx = *end + 1; } } @@ -1292,7 +1292,7 @@ AF_Point point = hints->points; AF_Point limit = point + hints->num_points; FT_Vector* vec = outline->points; - char* tag = outline->tags; + FT_Byte* tag = outline->tags; for ( ; point < limit; point++, vec++, tag++ ) diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h index d1cf9529bf1..76fe83006a5 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c index 7fb12c63d5a..c6d23efd86f 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for Indic writing system (body). * - * Copyright (C) 2007-2023 by + * Copyright (C) 2007-2024 by * Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h index 3eb67f63b00..a7f73f25153 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h @@ -5,7 +5,7 @@ * Auto-fitter hinting routines for Indic writing system * (specification). * - * Copyright (C) 2007-2023 by + * Copyright (C) 2007-2024 by * Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c index b86367aa94d..89287f7ea5a 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for latin writing system (body). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -981,7 +981,7 @@ /* `ref' and `shoot' values of two blue zones must not overlap */ FT_UInt i; - AF_LatinBlue blue_sorted[AF_BLUE_STRINGSET_MAX_LEN + 2]; + AF_LatinBlue blue_sorted[AF_BLUE_STRINGSET_MAX_LEN]; for ( i = 0; i < axis->blue_count; i++ ) @@ -1263,10 +1263,9 @@ max_height = FT_MAX( max_height, -Axis->blues[nn].descender ); } - dist = FT_ABS( FT_MulFix( max_height, new_scale - scale ) ); - dist &= ~127; + dist = FT_MulFix( max_height, new_scale - scale ); - if ( dist == 0 ) + if ( -128 < dist && dist < 128 ) { FT_TRACE5(( "af_latin_metrics_scale_dim:" " x height alignment (style `%s'):\n", diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h index 31aa91d3bdb..54e50615021 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h @@ -5,7 +5,7 @@ * Auto-fitter hinting routines for latin writing system * (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -98,7 +98,7 @@ FT_BEGIN_HEADER /* ignored for horizontal metrics */ FT_UInt blue_count; - AF_LatinBlueRec blues[AF_BLUE_STRINGSET_MAX]; + AF_LatinBlueRec blues[AF_BLUE_STRINGSET_MAX_LEN]; FT_Fixed org_scale; FT_Pos org_delta; diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c index 7c47d562af6..af1d59a6896 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c @@ -4,7 +4,7 @@ * * Auto-fitter glyph loading routines (body). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h index e4e197e374f..99f0e15f92b 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h @@ -4,7 +4,7 @@ * * Auto-fitter glyph loading routines (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c index 20a6b96bc4f..726f6ca2b78 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c @@ -4,7 +4,7 @@ * * Auto-fitter module implementation (body). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -438,7 +438,7 @@ AF_Module module = (AF_Module)module_; FT_Error error = FT_Err_Ok; - FT_Memory memory = module->root.library->memory; + FT_Memory memory = module->root.memory; #ifdef FT_DEBUG_AUTOFIT diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h index 4b8b4562c67..91a1abfef1f 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h @@ -4,7 +4,7 @@ * * Auto-fitter module implementation (specification). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c index cfcaf340a79..007b4328189 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c @@ -4,7 +4,7 @@ * * Auto-fitter Unicode script ranges (body). * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h index 5775738bc0b..813b3ee78ef 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h @@ -4,7 +4,7 @@ * * Auto-fitter Unicode script ranges (specification). * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h b/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h index 3a101937d70..0a83d771501 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h @@ -4,7 +4,7 @@ * * Auto-fitter scripts (specification only). * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c index abc6f1d292d..df0f46ada89 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c @@ -4,7 +4,7 @@ * * HarfBuzz interface for accessing OpenType features (body). * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h index 054a18ffbc2..2eb03bb5d98 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h @@ -4,7 +4,7 @@ * * HarfBuzz interface for accessing OpenType features (specification). * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h b/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h index 73ebef01716..7a33f37a856 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h @@ -4,7 +4,7 @@ * * Auto-fitter styles (specification only). * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h b/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h index 66151944965..27e4185e9f8 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h @@ -4,7 +4,7 @@ * * Auto-fitter types (specification only). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h b/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h index 48c888afed8..b78745af74e 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h @@ -4,7 +4,7 @@ * * Auto-fitter writing system declarations (specification only). * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h b/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h index a0a686f8cee..c86d609a352 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h @@ -4,7 +4,7 @@ * * Auto-fitter writing systems iterator (specification only). * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c b/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c index de25476fe92..717f7d08b35 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c @@ -4,7 +4,7 @@ * * Quick computation of advance widths (body). * - * Copyright (C) 2008-2023 by + * Copyright (C) 2008-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbase.h b/src/java.desktop/share/native/libfreetype/src/base/ftbase.h index 00790d3b226..1d98b26dd51 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftbase.h +++ b/src/java.desktop/share/native/libfreetype/src/base/ftbase.h @@ -4,7 +4,7 @@ * * Private functions used in the `base' module (specification). * - * Copyright (C) 2008-2023 by + * Copyright (C) 2008-2024 by * David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c b/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c index 385fea40401..d6aa5d56df8 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c @@ -4,7 +4,7 @@ * * FreeType bbox computation (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used @@ -489,7 +489,7 @@ return FT_THROW( Invalid_Outline ); /* if outline is empty, return (0,0,0,0) */ - if ( outline->n_points == 0 || outline->n_contours <= 0 ) + if ( outline->n_points == 0 || outline->n_contours == 0 ) { abbox->xMin = abbox->xMax = 0; abbox->yMin = abbox->yMax = 0; diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c b/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c index 1c93648dcbc..4be145679fd 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c @@ -4,7 +4,7 @@ * * FreeType utility functions for bitmaps (body). * - * Copyright (C) 2004-2023 by + * Copyright (C) 2004-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c b/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c index c5bc7e3b14e..92de09ed877 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c @@ -4,7 +4,7 @@ * * Arithmetic computations (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -69,13 +69,15 @@ /* transfer sign, leaving a positive number; */ /* we need an unsigned value to safely negate INT_MIN (or LONG_MIN) */ -#define FT_MOVE_SIGN( x, x_unsigned, s ) \ - FT_BEGIN_STMNT \ - if ( x < 0 ) \ - { \ - x_unsigned = 0U - (x_unsigned); \ - s = -s; \ - } \ +#define FT_MOVE_SIGN( utype, x, x_unsigned, s ) \ + FT_BEGIN_STMNT \ + if ( x < 0 ) \ + { \ + x_unsigned = 0U - (utype)x; \ + s = -s; \ + } \ + else \ + x_unsigned = (utype)x; \ FT_END_STMNT /* The following three functions are available regardless of whether */ @@ -179,13 +181,9 @@ FT_Long d_; - a = (FT_UInt64)a_; - b = (FT_UInt64)b_; - c = (FT_UInt64)c_; - - FT_MOVE_SIGN( a_, a, s ); - FT_MOVE_SIGN( b_, b, s ); - FT_MOVE_SIGN( c_, c, s ); + FT_MOVE_SIGN( FT_UInt64, a_, a, s ); + FT_MOVE_SIGN( FT_UInt64, b_, b, s ); + FT_MOVE_SIGN( FT_UInt64, c_, c, s ); d = c > 0 ? ( a * b + ( c >> 1 ) ) / c : 0x7FFFFFFFUL; @@ -208,13 +206,9 @@ FT_Long d_; - a = (FT_UInt64)a_; - b = (FT_UInt64)b_; - c = (FT_UInt64)c_; - - FT_MOVE_SIGN( a_, a, s ); - FT_MOVE_SIGN( b_, b, s ); - FT_MOVE_SIGN( c_, c, s ); + FT_MOVE_SIGN( FT_UInt64, a_, a, s ); + FT_MOVE_SIGN( FT_UInt64, b_, b, s ); + FT_MOVE_SIGN( FT_UInt64, c_, c, s ); d = c > 0 ? a * b / c : 0x7FFFFFFFUL; @@ -257,11 +251,8 @@ FT_Long q_; - a = (FT_UInt64)a_; - b = (FT_UInt64)b_; - - FT_MOVE_SIGN( a_, a, s ); - FT_MOVE_SIGN( b_, b, s ); + FT_MOVE_SIGN( FT_UInt64, a_, a, s ); + FT_MOVE_SIGN( FT_UInt64, b_, b, s ); q = b > 0 ? ( ( a << 16 ) + ( b >> 1 ) ) / b : 0x7FFFFFFFUL; @@ -422,13 +413,9 @@ /* XXX: this function does not allow 64-bit arguments */ - a = (FT_UInt32)a_; - b = (FT_UInt32)b_; - c = (FT_UInt32)c_; - - FT_MOVE_SIGN( a_, a, s ); - FT_MOVE_SIGN( b_, b, s ); - FT_MOVE_SIGN( c_, c, s ); + FT_MOVE_SIGN( FT_UInt32, a_, a, s ); + FT_MOVE_SIGN( FT_UInt32, b_, b, s ); + FT_MOVE_SIGN( FT_UInt32, c_, c, s ); if ( c == 0 ) a = 0x7FFFFFFFUL; @@ -470,13 +457,9 @@ /* XXX: this function does not allow 64-bit arguments */ - a = (FT_UInt32)a_; - b = (FT_UInt32)b_; - c = (FT_UInt32)c_; - - FT_MOVE_SIGN( a_, a, s ); - FT_MOVE_SIGN( b_, b, s ); - FT_MOVE_SIGN( c_, c, s ); + FT_MOVE_SIGN( FT_UInt32, a_, a, s ); + FT_MOVE_SIGN( FT_UInt32, b_, b, s ); + FT_MOVE_SIGN( FT_UInt32, c_, c, s ); if ( c == 0 ) a = 0x7FFFFFFFUL; @@ -575,11 +558,8 @@ /* XXX: this function does not allow 64-bit arguments */ - a = (FT_UInt32)a_; - b = (FT_UInt32)b_; - - FT_MOVE_SIGN( a_, a, s ); - FT_MOVE_SIGN( b_, b, s ); + FT_MOVE_SIGN( FT_UInt32, a_, a, s ); + FT_MOVE_SIGN( FT_UInt32, b_, b, s ); if ( a + ( b >> 8 ) <= 8190UL ) a = ( a * b + 0x8000UL ) >> 16; @@ -614,11 +594,8 @@ /* XXX: this function does not allow 64-bit arguments */ - a = (FT_UInt32)a_; - b = (FT_UInt32)b_; - - FT_MOVE_SIGN( a_, a, s ); - FT_MOVE_SIGN( b_, b, s ); + FT_MOVE_SIGN( FT_UInt32, a_, a, s ); + FT_MOVE_SIGN( FT_UInt32, b_, b, s ); if ( b == 0 ) { @@ -829,11 +806,8 @@ FT_Int sx = 1, sy = 1, shift; - x = (FT_UInt32)x_; - y = (FT_UInt32)y_; - - FT_MOVE_SIGN( x_, x, sx ); - FT_MOVE_SIGN( y_, y, sy ); + FT_MOVE_SIGN( FT_UInt32, x_, x, sx ); + FT_MOVE_SIGN( FT_UInt32, y_, y, sy ); /* trivial cases */ if ( x == 0 ) @@ -913,43 +887,71 @@ } -#if 0 - /* documentation is in ftcalc.h */ - FT_BASE_DEF( FT_Int32 ) - FT_SqrtFixed( FT_Int32 x ) + FT_BASE_DEF( FT_UInt32 ) + FT_SqrtFixed( FT_UInt32 v ) { - FT_UInt32 root, rem_hi, rem_lo, test_div; - FT_Int count; - + if ( v == 0 ) + return 0; - root = 0; +#ifndef FT_INT64 - if ( x > 0 ) + /* Algorithm by Christophe Meessen (1993) with overflow fixed and */ + /* rounding added. Any unsigned fixed 16.16 argument is acceptable. */ + /* However, this algorithm is slower than the Babylonian method with */ + /* a good initial guess. We only use it for large 32-bit values when */ + /* 64-bit computations are not desirable. */ + else if ( v > 0x10000U ) { - rem_hi = 0; - rem_lo = (FT_UInt32)x; - count = 24; + FT_UInt32 r = v >> 1; + FT_UInt32 q = ( v & 1 ) << 15; + FT_UInt32 b = 0x20000000; + FT_UInt32 t; + + do { - rem_hi = ( rem_hi << 2 ) | ( rem_lo >> 30 ); - rem_lo <<= 2; - root <<= 1; - test_div = ( root << 1 ) + 1; - - if ( rem_hi >= test_div ) + t = q + b; + if ( r >= t ) { - rem_hi -= test_div; - root += 1; + r -= t; + q = t + b; /* equivalent to q += 2*b */ } - } while ( --count ); + r <<= 1; + b >>= 1; + + } while ( b > 0x10 ); /* exactly 25 cycles */ + + return ( q + 0x40 ) >> 7; } + else + { + FT_UInt32 r = ( v << 16 ) - 1; - return (FT_Int32)root; - } +#else /* FT_INT64 */ -#endif /* 0 */ + else + { + FT_UInt64 r = ( (FT_UInt64)v << 16 ) - 1; + +#endif /* FT_INT64 */ + + FT_UInt32 q = 1 << ( ( 17 + FT_MSB( v ) ) >> 1 ); + FT_UInt32 t; + + + /* Babylonian method with rounded-up division */ + do + { + t = q; + q = ( t + (FT_UInt32)( r / t ) + 1 ) >> 1; + + } while ( q != t ); /* less than 6 cycles */ + + return q; + } + } /* documentation is in ftcalc.h */ @@ -1094,11 +1096,8 @@ FT_UInt32 factor; - scalar = (FT_UInt32)s[i]; - factor = (FT_UInt32)f[i]; - - FT_MOVE_SIGN( s[i], scalar, sign ); - FT_MOVE_SIGN( f[i], factor, sign ); + FT_MOVE_SIGN( FT_UInt32, s[i], scalar, sign ); + FT_MOVE_SIGN( FT_UInt32, f[i], factor, sign ); ft_multo64( scalar, factor, &multResult ); diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcid.c b/src/java.desktop/share/native/libfreetype/src/base/ftcid.c index 866cd23e91b..4f2deb19a05 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftcid.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftcid.c @@ -4,7 +4,7 @@ * * FreeType API for accessing CID font information. * - * Copyright (C) 2007-2023 by + * Copyright (C) 2007-2024 by * Derek Clegg and Michael Toftdal. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c b/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c index bcd6e893d4a..c6bf2a3cd1a 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c @@ -4,7 +4,7 @@ * * FreeType's glyph color management (body). * - * Copyright (C) 2018-2023 by + * Copyright (C) 2018-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c b/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c index 8fab50dd017..902a5dc8bbc 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c @@ -4,7 +4,7 @@ * * Memory debugger (body). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c b/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c index 61c4563b0c4..11307eaace4 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c @@ -4,7 +4,7 @@ * * Debugging and logging component (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c b/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c index 0b41f7cc83d..77b4089e7e2 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c @@ -4,7 +4,7 @@ * * FreeType utility file for font formats (body). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c b/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c index ea24e64c6ea..1565c3b7e25 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c @@ -4,7 +4,7 @@ * * FreeType utility file to access FSType data (body). * - * Copyright (C) 2008-2023 by + * Copyright (C) 2008-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c b/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c index 29b7b08b787..c63d30e978c 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c @@ -4,7 +4,7 @@ * * Access of TrueType's `gasp' table (body). * - * Copyright (C) 2007-2023 by + * Copyright (C) 2007-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c b/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c index 9823d09e41a..484d98f1722 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c @@ -4,7 +4,7 @@ * * The FreeType glyph loader (body). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg * * This file is part of the FreeType project, and may only be used, @@ -355,34 +355,25 @@ FT_BASE_DEF( void ) FT_GlyphLoader_Add( FT_GlyphLoader loader ) { - FT_GlyphLoad base; - FT_GlyphLoad current; - - FT_Int n_curr_contours; - FT_Int n_base_points; - FT_Int n; + FT_Outline* base; + FT_Outline* current; + FT_Int n; if ( !loader ) return; - base = &loader->base; - current = &loader->current; - - n_curr_contours = current->outline.n_contours; - n_base_points = base->outline.n_points; + base = &loader->base.outline; + current = &loader->current.outline; - base->outline.n_points = - (short)( base->outline.n_points + current->outline.n_points ); - base->outline.n_contours = - (short)( base->outline.n_contours + current->outline.n_contours ); + /* adjust contours count in newest outline */ + for ( n = 0; n < current->n_contours; n++ ) + current->contours[n] += base->n_points; - base->num_subglyphs += current->num_subglyphs; + base->n_points += current->n_points; + base->n_contours += current->n_contours; - /* adjust contours count in newest outline */ - for ( n = 0; n < n_curr_contours; n++ ) - current->outline.contours[n] = - (short)( current->outline.contours[n] + n_base_points ); + loader->base.num_subglyphs += loader->current.num_subglyphs; /* prepare for another new glyph image */ FT_GlyphLoader_Prepare( loader ); diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c b/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c index 393d4949f84..1b5849f99af 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c @@ -4,7 +4,7 @@ * * FreeType convenience functions to handle glyphs (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftinit.c b/src/java.desktop/share/native/libfreetype/src/base/ftinit.c index c9c71d24bf9..9a6c00e13ef 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftinit.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftinit.c @@ -4,7 +4,7 @@ * * FreeType initialization layer (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c b/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c index 6c3fd66e0bb..1e69d4da70f 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c @@ -4,7 +4,7 @@ * * FreeType API for color filtering of subpixel bitmap glyphs (body). * - * Copyright (C) 2006-2023 by + * Copyright (C) 2006-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftmac.c b/src/java.desktop/share/native/libfreetype/src/base/ftmac.c index 492d0553845..e8e35627b50 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftmac.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftmac.c @@ -8,7 +8,7 @@ * This file is for Mac OS X only; see builds/mac/ftoldmac.c for * classic platforms built by MPW. * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -812,6 +812,7 @@ ResourceIndex res_index; Handle fond; short num_faces_in_res; + FT_Long count; if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) ) @@ -821,8 +822,10 @@ if ( ResError() ) return FT_THROW( Cannot_Open_Resource ); + res_index = 1; num_faces_in_res = 0; - for ( res_index = 1; ; res_index++ ) + count = face_index; + while ( count >= 0 ) { short num_faces_in_fond; @@ -834,15 +837,21 @@ num_faces_in_fond = count_faces( fond, pathname ); num_faces_in_res += num_faces_in_fond; - if ( 0 <= face_index && face_index < num_faces_in_fond && error ) - error = FT_New_Face_From_FOND( library, fond, face_index, aface ); + if ( count < num_faces_in_fond ) + error = FT_New_Face_From_FOND( library, fond, count, aface ); - face_index -= num_faces_in_fond; + res_index++; + count -= num_faces_in_fond; } CloseResFile( res_ref ); + if ( !error && aface && *aface ) - (*aface)->num_faces = num_faces_in_res; + { + (*aface)->num_faces = num_faces_in_res; + (*aface)->face_index = face_index; + } + return error; } diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftmm.c b/src/java.desktop/share/native/libfreetype/src/base/ftmm.c index 9e2dd7ee79d..cc4ca22fba3 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftmm.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftmm.c @@ -4,7 +4,7 @@ * * Multiple Master font support (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c b/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c index 89a25bc732d..9b97820c379 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c @@ -4,7 +4,7 @@ * * The FreeType private base classes (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -2302,7 +2302,10 @@ face_index_internal, aface ); FT_FREE( data_offsets ); if ( !error ) - (*aface)->num_faces = count; + { + (*aface)->num_faces = count; + (*aface)->face_index = face_index_internal; + } } return error; @@ -5791,7 +5794,7 @@ ttface = (TT_Face)face; sfnt = (SFNT_Service)ttface->sfnt; - if ( sfnt->get_colr_layer ) + if ( sfnt->get_colr_glyph_paint ) return sfnt->get_colr_glyph_paint( ttface, base_glyph, root_transform, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c b/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c index 134f39d2b1f..ef699b3c7cd 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c @@ -4,7 +4,7 @@ * * FreeType outline management (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -53,7 +53,7 @@ FT_Vector* point; FT_Vector* limit; - char* tags; + FT_Byte* tags; FT_Error error; @@ -332,8 +332,8 @@ FT_NEW_ARRAY( anoutline->contours, numContours ) ) goto Fail; - anoutline->n_points = (FT_Short)numPoints; - anoutline->n_contours = (FT_Short)numContours; + anoutline->n_points = (FT_UShort)numPoints; + anoutline->n_contours = (FT_UShort)numContours; anoutline->flags |= FT_OUTLINE_OWNER; return FT_Err_Ok; @@ -359,12 +359,14 @@ FT_Int n; + FT_TRACE5(( "FT_Outline_Check: contours = %d, points = %d\n", + n_contours, n_points )); /* empty glyph? */ if ( n_points == 0 && n_contours == 0 ) return FT_Err_Ok; /* check point and contour counts */ - if ( n_points <= 0 || n_contours <= 0 ) + if ( n_points == 0 || n_contours == 0 ) goto Bad; end0 = -1; @@ -576,13 +578,13 @@ /* reverse tags table */ { - char* p = outline->tags + first; - char* q = outline->tags + last; + FT_Byte* p = outline->tags + first; + FT_Byte* q = outline->tags + last; while ( p < q ) { - char swap; + FT_Byte swap; swap = *p; diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c b/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c index cb5efadffb1..2055757e023 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c @@ -5,7 +5,7 @@ * FreeType API for checking patented TrueType bytecode instructions * (body). Obsolete, retained for backward compatibility. * - * Copyright (C) 2007-2023 by + * Copyright (C) 2007-2024 by * David Turner. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c b/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c index cefdf489d7f..37a6cee6cc9 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c @@ -5,7 +5,7 @@ * Get and set properties of PostScript drivers (body). * See `ftdriver.h' for available properties. * - * Copyright (C) 2017-2023 by + * Copyright (C) 2017-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c b/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c index 2ab430195f2..dc9b043d8bb 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c @@ -4,7 +4,7 @@ * * Embedded resource forks accessor (body). * - * Copyright (C) 2004-2023 by + * Copyright (C) 2004-2024 by * Masatake YAMATO and Redhat K.K. * * FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c b/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c index 1917a3f1dff..f7231fd61cc 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c @@ -7,7 +7,7 @@ * * This is _not_ used to retrieve glyph names! * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftstream.c b/src/java.desktop/share/native/libfreetype/src/base/ftstream.c index 64826acebe5..66722246128 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftstream.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftstream.c @@ -4,7 +4,7 @@ * * I/O stream support (body). * - * Copyright (C) 2000-2023 by + * Copyright (C) 2000-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -763,10 +763,10 @@ case ft_frame_bytes: /* read a byte sequence */ case ft_frame_skip: /* skip some bytes */ { - FT_UInt len = fields->size; + FT_Offset len = fields->size; - if ( cursor + len > stream->limit ) + if ( len > (FT_Offset)( stream->limit - cursor ) ) { error = FT_THROW( Invalid_Stream_Operation ); goto Exit; @@ -830,7 +830,7 @@ goto Exit; } - /* now, compute the signed value is necessary */ + /* now, compute the signed value if necessary */ if ( fields->value & FT_FRAME_OP_SIGNED ) value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift ); diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c b/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c index 92f1e43080f..64f46ce43e7 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c @@ -4,7 +4,7 @@ * * FreeType path stroker (body). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -711,7 +711,7 @@ { FT_UInt count = border->num_points; FT_Byte* read = border->tags; - FT_Byte* write = (FT_Byte*)outline->tags + outline->n_points; + FT_Byte* write = outline->tags + outline->n_points; for ( ; count > 0; count--, read++, write++ ) @@ -727,10 +727,10 @@ /* copy contours */ { - FT_UInt count = border->num_points; - FT_Byte* tags = border->tags; - FT_Short* write = outline->contours + outline->n_contours; - FT_Short idx = (FT_Short)outline->n_points; + FT_UInt count = border->num_points; + FT_Byte* tags = border->tags; + FT_UShort* write = outline->contours + outline->n_contours; + FT_UShort idx = outline->n_points; for ( ; count > 0; count--, tags++, idx++ ) @@ -743,7 +743,7 @@ } } - outline->n_points += (short)border->num_points; + outline->n_points += (FT_UShort)border->num_points; FT_ASSERT( FT_Outline_Check( outline ) == 0 ); } @@ -2050,7 +2050,7 @@ FT_Vector* point; FT_Vector* limit; - char* tags; + FT_Byte* tags; FT_Error error; diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c b/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c index f32edd3388b..ec05bce33a9 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c @@ -4,7 +4,7 @@ * * FreeType synthesizing code for emboldening and slanting (body). * - * Copyright (C) 2000-2023 by + * Copyright (C) 2000-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c b/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c index 61c99e36357..eee3642334f 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c @@ -4,7 +4,7 @@ * * ANSI-specific FreeType low-level system interface (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c b/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c index 2dd2c3459e5..4b1aced1cba 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c +++ b/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c @@ -4,7 +4,7 @@ * * FreeType trigonometric functions (body). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/fttype1.c b/src/java.desktop/share/native/libfreetype/src/base/fttype1.c index 637c5cf775e..cedf7c40505 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/fttype1.c +++ b/src/java.desktop/share/native/libfreetype/src/base/fttype1.c @@ -4,7 +4,7 @@ * * FreeType utility file for PS names support (body). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftutil.c b/src/java.desktop/share/native/libfreetype/src/base/ftutil.c index 6120846d2ca..b13512f8704 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftutil.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftutil.c @@ -4,7 +4,7 @@ * * FreeType utility file for memory and list management (body). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c index 10d287bc81f..ea5f8ed2885 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c @@ -4,7 +4,7 @@ * * CFF character mapping table (cmap) support (body). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h index b2afc2fab62..1dd8700cd8b 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h @@ -4,7 +4,7 @@ * * CFF character mapping table (cmap) support (specification). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c index 9898d625ca4..f6ebdb3810a 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c @@ -4,7 +4,7 @@ * * OpenType font driver implementation (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h index ab1f147bb2a..fd5bc37ecd4 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h @@ -4,7 +4,7 @@ * * High-level OpenType driver interface (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h b/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h index bc9a3043fcf..128adc3b716 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h @@ -4,7 +4,7 @@ * * CFF error codes (specification only). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c index c483d1d1a59..cbb071abdfe 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c @@ -4,7 +4,7 @@ * * OpenType Glyph Loader (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h index 3b8cf236ddc..346d4b11c31 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h @@ -4,7 +4,7 @@ * * OpenType Glyph Loader (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffload.c b/src/java.desktop/share/native/libfreetype/src/cff/cffload.c index af79082e98c..979fd45f6ca 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffload.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffload.c @@ -4,7 +4,7 @@ * * OpenType and CFF data/program tables loader (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -1202,17 +1202,21 @@ { CFF_AxisCoords* axis = ®ion->axisList[j]; - FT_Int16 start14, peak14, end14; + FT_Int start, peak, end; - if ( FT_READ_SHORT( start14 ) || - FT_READ_SHORT( peak14 ) || - FT_READ_SHORT( end14 ) ) + if ( FT_READ_SHORT( start ) || + FT_READ_SHORT( peak ) || + FT_READ_SHORT( end ) ) goto Exit; - axis->startCoord = FT_fdot14ToFixed( start14 ); - axis->peakCoord = FT_fdot14ToFixed( peak14 ); - axis->endCoord = FT_fdot14ToFixed( end14 ); + /* immediately tag invalid ranges with special peak = 0 */ + if ( ( start < 0 && end > 0 ) || start > peak || peak > end ) + peak = 0; + + axis->startCoord = FT_fdot14ToFixed( start ); + axis->peakCoord = FT_fdot14ToFixed( peak ); + axis->endCoord = FT_fdot14ToFixed( end ); } } @@ -1379,10 +1383,10 @@ /* opcode in both CFF and CFF2 DICTs. See `cff_parse_num' for */ /* decode of this, which rounds to an integer. */ *subFont->blend_top++ = 255; - *subFont->blend_top++ = (FT_Byte)( sum >> 24 ); - *subFont->blend_top++ = (FT_Byte)( sum >> 16 ); - *subFont->blend_top++ = (FT_Byte)( sum >> 8 ); - *subFont->blend_top++ = (FT_Byte)sum; + *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >> 24 ); + *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >> 16 ); + *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >> 8 ); + *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum ); } /* leave only numBlends results on parser stack */ @@ -1495,44 +1499,31 @@ for ( j = 0; j < lenNDV; j++ ) { CFF_AxisCoords* axis = &varRegion->axisList[j]; - FT_Fixed axisScalar; - - - /* compute the scalar contribution of this axis; */ - /* ignore invalid ranges */ - if ( axis->startCoord > axis->peakCoord || - axis->peakCoord > axis->endCoord ) - axisScalar = FT_FIXED_ONE; - else if ( axis->startCoord < 0 && - axis->endCoord > 0 && - axis->peakCoord != 0 ) - axisScalar = FT_FIXED_ONE; - /* peak of 0 means ignore this axis */ - else if ( axis->peakCoord == 0 ) - axisScalar = FT_FIXED_ONE; + /* compute the scalar contribution of this axis */ + /* with peak of 0 used for invalid axes */ + if ( axis->peakCoord == NDV[j] || + axis->peakCoord == 0 ) + continue; /* ignore this region if coords are out of range */ - else if ( NDV[j] < axis->startCoord || - NDV[j] > axis->endCoord ) - axisScalar = 0; - - /* calculate a proportional factor */ - else + else if ( NDV[j] <= axis->startCoord || + NDV[j] >= axis->endCoord ) { - if ( NDV[j] == axis->peakCoord ) - axisScalar = FT_FIXED_ONE; - else if ( NDV[j] < axis->peakCoord ) - axisScalar = FT_DivFix( NDV[j] - axis->startCoord, - axis->peakCoord - axis->startCoord ); - else - axisScalar = FT_DivFix( axis->endCoord - NDV[j], - axis->endCoord - axis->peakCoord ); + blend->BV[master] = 0; + break; } - /* take product of all the axis scalars */ - blend->BV[master] = FT_MulFix( blend->BV[master], axisScalar ); + /* adjust proportionally */ + else if ( NDV[j] < axis->peakCoord ) + blend->BV[master] = FT_MulDiv( blend->BV[master], + NDV[j] - axis->startCoord, + axis->peakCoord - axis->startCoord ); + else /* NDV[j] > axis->peakCoord ) */ + blend->BV[master] = FT_MulDiv( blend->BV[master], + axis->endCoord - NDV[j], + axis->endCoord - axis->peakCoord ); } FT_TRACE4(( ", %f ", diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffload.h b/src/java.desktop/share/native/libfreetype/src/cff/cffload.h index b5286b0c8cb..02209245421 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffload.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffload.h @@ -4,7 +4,7 @@ * * OpenType & CFF data/program tables loader (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c index 6d08620c487..7c6713739a1 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c @@ -4,7 +4,7 @@ * * OpenType objects manager (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -42,6 +42,8 @@ #include <freetype/internal/psaux.h> #include <freetype/internal/services/svcfftl.h> +#define CFF_fixedToInt( x ) \ + ( (FT_Short)( ( (x) + 0x8000U ) >> 16 ) ) /************************************************************************** * @@ -124,19 +126,20 @@ count = priv->num_blue_values = cpriv->num_blue_values; for ( n = 0; n < count; n++ ) - priv->blue_values[n] = (FT_Short)cpriv->blue_values[n]; + priv->blue_values[n] = CFF_fixedToInt( cpriv->blue_values[n] ); count = priv->num_other_blues = cpriv->num_other_blues; for ( n = 0; n < count; n++ ) - priv->other_blues[n] = (FT_Short)cpriv->other_blues[n]; + priv->other_blues[n] = CFF_fixedToInt( cpriv->other_blues[n] ); count = priv->num_family_blues = cpriv->num_family_blues; for ( n = 0; n < count; n++ ) - priv->family_blues[n] = (FT_Short)cpriv->family_blues[n]; + priv->family_blues[n] = CFF_fixedToInt( cpriv->family_blues[n] ); count = priv->num_family_other_blues = cpriv->num_family_other_blues; for ( n = 0; n < count; n++ ) - priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n]; + priv->family_other_blues[n] = + CFF_fixedToInt( cpriv->family_other_blues[n] ); priv->blue_scale = cpriv->blue_scale; priv->blue_shift = (FT_Int)cpriv->blue_shift; @@ -421,32 +424,23 @@ static void remove_subset_prefix( FT_String* name ) { - FT_Int32 idx = 0; - FT_Int32 length = (FT_Int32)ft_strlen( name ) + 1; - FT_Bool continue_search = 1; + FT_UInt32 i = 0, idx = 0; - while ( continue_search ) + /* six ASCII uppercase letters followed by a plus sign */ + while ( 'A' <= name[i] && name[i++] <= 'Z' && + 'A' <= name[i] && name[i++] <= 'Z' && + 'A' <= name[i] && name[i++] <= 'Z' && + 'A' <= name[i] && name[i++] <= 'Z' && + 'A' <= name[i] && name[i++] <= 'Z' && + 'A' <= name[i] && name[i++] <= 'Z' && + name[i++] == '+' ) { - if ( length >= 7 && name[6] == '+' ) - { - for ( idx = 0; idx < 6; idx++ ) - { - /* ASCII uppercase letters */ - if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) ) - continue_search = 0; - } - - if ( continue_search ) - { - for ( idx = 7; idx < length; idx++ ) - name[idx - 7] = name[idx]; - length -= 7; - } - } - else - continue_search = 0; + idx = i; } + + if ( idx ) + FT_MEM_MOVE( name, name + idx, ft_strlen( name + idx ) + 1 ); } @@ -456,42 +450,20 @@ remove_style( FT_String* family_name, const FT_String* style_name ) { - FT_Int32 family_name_length, style_name_length; + FT_String* f = family_name + ft_strlen( family_name ); + const FT_String* s = style_name + ft_strlen( style_name ); - family_name_length = (FT_Int32)ft_strlen( family_name ); - style_name_length = (FT_Int32)ft_strlen( style_name ); + /* compare strings moving backwards */ + while ( s > style_name ) + if ( f == family_name || *--s != *--f ) + return; - if ( family_name_length > style_name_length ) - { - FT_Int idx; - - - for ( idx = 1; idx <= style_name_length; idx++ ) - { - if ( family_name[family_name_length - idx] != - style_name[style_name_length - idx] ) - break; - } - - if ( idx > style_name_length ) - { - /* family_name ends with style_name; remove it */ - idx = family_name_length - style_name_length - 1; - - /* also remove special characters */ - /* between real family name and style */ - while ( idx > 0 && - ( family_name[idx] == '-' || - family_name[idx] == ' ' || - family_name[idx] == '_' || - family_name[idx] == '+' ) ) - idx--; - - if ( idx > 0 ) - family_name[idx + 1] = '\0'; - } - } + /* terminate and remove special characters */ + do + *f = '\0'; + while ( f-- > family_name && + ( *f == '-' || *f == ' ' || *f == '_' || *f == '+' ) ); } @@ -722,8 +694,7 @@ FT_UInt instance_index = (FT_UInt)face_index >> 16; - if ( FT_HAS_MULTIPLE_MASTERS( cffface ) && - instance_index > 0 ) + if ( FT_HAS_MULTIPLE_MASTERS( cffface ) ) { error = FT_Set_Named_Instance( cffface, instance_index ); if ( error ) diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h index 8f05f6132bc..91ad83b1cd0 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h @@ -4,7 +4,7 @@ * * OpenType objects manager (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c index 3b076704cf7..92a69c3b516 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c @@ -4,7 +4,7 @@ * * CFF token stream parser (body) * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -501,10 +501,10 @@ return cff_parse_real( *d, parser->limit, scaling, NULL ); else if ( **d == 255 ) { - FT_Fixed val = ( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) | - ( (FT_UInt32)*( d[0] + 2 ) << 16 ) | - ( (FT_UInt32)*( d[0] + 3 ) << 8 ) | - (FT_UInt32)*( d[0] + 4 ) ) ); + FT_Fixed val = (FT_Int32)( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) | + ( (FT_UInt32)*( d[0] + 2 ) << 16 ) | + ( (FT_UInt32)*( d[0] + 3 ) << 8 ) | + (FT_UInt32)*( d[0] + 4 ) ) ); if ( scaling ) { @@ -1031,10 +1031,14 @@ CFF_FIELD( code, name, id, cff_kind_string ) #define CFF_FIELD_BOOL( code, name, id ) \ CFF_FIELD( code, name, id, cff_kind_bool ) +#define CFF_FIELD_DELTA( code, name, max, id ) \ + CFF_FIELD_DELTA_KIND( code, name, max, id, cff_kind_delta ) +#define CFF_FIELD_DELTA_FIXED( code, name, max, id ) \ + CFF_FIELD_DELTA_KIND( code, name, max, id, cff_kind_delta_fixed ) #undef CFF_FIELD -#undef CFF_FIELD_DELTA +#undef CFF_FIELD_DELTA_KIND #ifndef FT_DEBUG_LEVEL_TRACE @@ -1064,18 +1068,18 @@ code | CFFCODE, \ FT_FIELD_OFFSET( name ), \ FT_FIELD_SIZE( name ), \ - 0, 0, 0 \ + NULL, 0, 0 \ }, -#define CFF_FIELD_DELTA( code, name, max, id ) \ - { \ - cff_kind_delta, \ - code | CFFCODE, \ - FT_FIELD_OFFSET( name ), \ - FT_FIELD_SIZE_DELTA( name ), \ - 0, \ - max, \ - FT_FIELD_OFFSET( num_ ## name ) \ +#define CFF_FIELD_DELTA_KIND( code, name, max, id, kind ) \ + { \ + kind, \ + code | CFFCODE, \ + FT_FIELD_OFFSET( name ), \ + FT_FIELD_SIZE_DELTA( name ), \ + NULL, \ + max, \ + FT_FIELD_OFFSET( num_ ## name ) \ }, static const CFF_Field_Handler cff_field_handlers[] = @@ -1083,7 +1087,7 @@ #include "cfftoken.h" - { 0, 0, 0, 0, 0, 0, 0 } + { 0, 0, 0, 0, NULL, 0, 0 } }; @@ -1117,20 +1121,20 @@ code | CFFCODE, \ FT_FIELD_OFFSET( name ), \ FT_FIELD_SIZE( name ), \ - 0, 0, 0, \ + NULL, 0, 0, \ id \ }, -#define CFF_FIELD_DELTA( code, name, max, id ) \ - { \ - cff_kind_delta, \ - code | CFFCODE, \ - FT_FIELD_OFFSET( name ), \ - FT_FIELD_SIZE_DELTA( name ), \ - 0, \ - max, \ - FT_FIELD_OFFSET( num_ ## name ), \ - id \ +#define CFF_FIELD_DELTA_KIND( code, name, max, id, kind ) \ + { \ + kind, \ + code | CFFCODE, \ + FT_FIELD_OFFSET( name ), \ + FT_FIELD_SIZE_DELTA( name ), \ + NULL, \ + max, \ + FT_FIELD_OFFSET( num_ ## name ), \ + id \ }, static const CFF_Field_Handler cff_field_handlers[] = @@ -1138,7 +1142,7 @@ #include "cfftoken.h" - { 0, 0, 0, 0, 0, 0, 0, 0 } + { 0, 0, 0, 0, NULL, 0, 0, NULL } }; @@ -1356,7 +1360,8 @@ /* check that we have enough arguments -- except for */ /* delta encoded arrays, which can be empty */ - if ( field->kind != cff_kind_delta && num_args < 1 ) + if ( field->kind != cff_kind_delta && + field->kind != cff_kind_delta_fixed && num_args < 1 ) goto Stack_Underflow; switch ( field->kind ) @@ -1471,6 +1476,38 @@ } break; + case cff_kind_delta_fixed: + { + FT_Byte* qcount = (FT_Byte*)parser->object + + field->count_offset; + + FT_Byte** data = parser->stack; + + + if ( num_args > field->array_max ) + num_args = field->array_max; + + FT_TRACE4(( " [" )); + + /* store count */ + *qcount = (FT_Byte)num_args; + + val = 0; + while ( num_args > 0 ) + { + val = ADD_LONG( val, cff_parse_fixed( parser, data++ ) ); + *(FT_Long*)q = val; + + FT_TRACE4(( " %f\n", (double)val / 65536 )); + + q += field->size; + num_args--; + } + + FT_TRACE4(( "]\n" )); + } + break; + default: /* callback or blend */ error = field->reader( parser ); if ( error ) diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h index 418caacc68c..ca6b18af6aa 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h @@ -4,7 +4,7 @@ * * CFF token stream parser (specification) * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -107,6 +107,7 @@ FT_BEGIN_HEADER cff_kind_string, cff_kind_bool, cff_kind_delta, + cff_kind_delta_fixed, cff_kind_callback, cff_kind_blend, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h b/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h index b61cb0e66e8..da45faa7f4e 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h @@ -4,7 +4,7 @@ * * CFF token definitions (specification only). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -80,26 +80,26 @@ #undef CFFCODE #define CFFCODE CFF_CODE_PRIVATE - CFF_FIELD_DELTA ( 6, blue_values, 14, "BlueValues" ) - CFF_FIELD_DELTA ( 7, other_blues, 10, "OtherBlues" ) - CFF_FIELD_DELTA ( 8, family_blues, 14, "FamilyBlues" ) - CFF_FIELD_DELTA ( 9, family_other_blues, 10, "FamilyOtherBlues" ) - CFF_FIELD_FIXED_1000( 0x109, blue_scale, "BlueScale" ) - CFF_FIELD_NUM ( 0x10A, blue_shift, "BlueShift" ) - CFF_FIELD_NUM ( 0x10B, blue_fuzz, "BlueFuzz" ) - CFF_FIELD_NUM ( 10, standard_width, "StdHW" ) - CFF_FIELD_NUM ( 11, standard_height, "StdVW" ) - CFF_FIELD_DELTA ( 0x10C, snap_widths, 13, "StemSnapH" ) - CFF_FIELD_DELTA ( 0x10D, snap_heights, 13, "StemSnapV" ) - CFF_FIELD_BOOL ( 0x10E, force_bold, "ForceBold" ) - CFF_FIELD_FIXED ( 0x10F, force_bold_threshold, "ForceBoldThreshold" ) - CFF_FIELD_NUM ( 0x110, lenIV, "lenIV" ) - CFF_FIELD_NUM ( 0x111, language_group, "LanguageGroup" ) - CFF_FIELD_FIXED ( 0x112, expansion_factor, "ExpansionFactor" ) - CFF_FIELD_NUM ( 0x113, initial_random_seed, "initialRandomSeed" ) - CFF_FIELD_NUM ( 19, local_subrs_offset, "Subrs" ) - CFF_FIELD_NUM ( 20, default_width, "defaultWidthX" ) - CFF_FIELD_NUM ( 21, nominal_width, "nominalWidthX" ) + CFF_FIELD_DELTA_FIXED( 6, blue_values, 14, "BlueValues" ) + CFF_FIELD_DELTA_FIXED( 7, other_blues, 10, "OtherBlues" ) + CFF_FIELD_DELTA_FIXED( 8, family_blues, 14, "FamilyBlues" ) + CFF_FIELD_DELTA_FIXED( 9, family_other_blues, 10, "FamilyOtherBlues" ) + CFF_FIELD_FIXED_1000 ( 0x109, blue_scale, "BlueScale" ) + CFF_FIELD_NUM ( 0x10A, blue_shift, "BlueShift" ) + CFF_FIELD_NUM ( 0x10B, blue_fuzz, "BlueFuzz" ) + CFF_FIELD_NUM ( 10, standard_width, "StdHW" ) + CFF_FIELD_NUM ( 11, standard_height, "StdVW" ) + CFF_FIELD_DELTA ( 0x10C, snap_widths, 13, "StemSnapH" ) + CFF_FIELD_DELTA ( 0x10D, snap_heights, 13, "StemSnapV" ) + CFF_FIELD_BOOL ( 0x10E, force_bold, "ForceBold" ) + CFF_FIELD_FIXED ( 0x10F, force_bold_threshold, "ForceBoldThreshold" ) + CFF_FIELD_NUM ( 0x110, lenIV, "lenIV" ) + CFF_FIELD_NUM ( 0x111, language_group, "LanguageGroup" ) + CFF_FIELD_FIXED ( 0x112, expansion_factor, "ExpansionFactor" ) + CFF_FIELD_NUM ( 0x113, initial_random_seed, "initialRandomSeed" ) + CFF_FIELD_NUM ( 19, local_subrs_offset, "Subrs" ) + CFF_FIELD_NUM ( 20, default_width, "defaultWidthX" ) + CFF_FIELD_NUM ( 21, nominal_width, "nominalWidthX" ) #undef FT_STRUCTURE @@ -129,22 +129,22 @@ #undef CFFCODE #define CFFCODE CFF2_CODE_PRIVATE - CFF_FIELD_DELTA ( 6, blue_values, 14, "BlueValues" ) - CFF_FIELD_DELTA ( 7, other_blues, 10, "OtherBlues" ) - CFF_FIELD_DELTA ( 8, family_blues, 14, "FamilyBlues" ) - CFF_FIELD_DELTA ( 9, family_other_blues, 10, "FamilyOtherBlues" ) - CFF_FIELD_FIXED_1000( 0x109, blue_scale, "BlueScale" ) - CFF_FIELD_NUM ( 0x10A, blue_shift, "BlueShift" ) - CFF_FIELD_NUM ( 0x10B, blue_fuzz, "BlueFuzz" ) - CFF_FIELD_NUM ( 10, standard_width, "StdHW" ) - CFF_FIELD_NUM ( 11, standard_height, "StdVW" ) - CFF_FIELD_DELTA ( 0x10C, snap_widths, 13, "StemSnapH" ) - CFF_FIELD_DELTA ( 0x10D, snap_heights, 13, "StemSnapV" ) - CFF_FIELD_NUM ( 0x111, language_group, "LanguageGroup" ) - CFF_FIELD_FIXED ( 0x112, expansion_factor, "ExpansionFactor" ) - CFF_FIELD_CALLBACK ( 22, vsindex, "vsindex" ) - CFF_FIELD_BLEND ( 23, "blend" ) - CFF_FIELD_NUM ( 19, local_subrs_offset, "Subrs" ) + CFF_FIELD_DELTA_FIXED( 6, blue_values, 14, "BlueValues" ) + CFF_FIELD_DELTA_FIXED( 7, other_blues, 10, "OtherBlues" ) + CFF_FIELD_DELTA_FIXED( 8, family_blues, 14, "FamilyBlues" ) + CFF_FIELD_DELTA_FIXED( 9, family_other_blues, 10, "FamilyOtherBlues" ) + CFF_FIELD_FIXED_1000 ( 0x109, blue_scale, "BlueScale" ) + CFF_FIELD_NUM ( 0x10A, blue_shift, "BlueShift" ) + CFF_FIELD_NUM ( 0x10B, blue_fuzz, "BlueFuzz" ) + CFF_FIELD_NUM ( 10, standard_width, "StdHW" ) + CFF_FIELD_NUM ( 11, standard_height, "StdVW" ) + CFF_FIELD_DELTA ( 0x10C, snap_widths, 13, "StemSnapH" ) + CFF_FIELD_DELTA ( 0x10D, snap_heights, 13, "StemSnapV" ) + CFF_FIELD_NUM ( 0x111, language_group, "LanguageGroup" ) + CFF_FIELD_FIXED ( 0x112, expansion_factor, "ExpansionFactor" ) + CFF_FIELD_CALLBACK ( 22, vsindex, "vsindex" ) + CFF_FIELD_BLEND ( 23, "blend" ) + CFF_FIELD_NUM ( 19, local_subrs_offset, "Subrs" ) /* END */ diff --git a/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h b/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h index 40a1097d0ac..c439a8c4a0b 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h @@ -4,7 +4,7 @@ * * CID error codes (specification only). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c index eaca765ad06..7b571322d45 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c @@ -4,7 +4,7 @@ * * CID-keyed Type1 Glyph Loader (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h index edd6229234c..9fdc9db5892 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h @@ -4,7 +4,7 @@ * * OpenType Glyph Loader (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidload.c b/src/java.desktop/share/native/libfreetype/src/cid/cidload.c index a7da8ea39d5..722f5a34ddf 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidload.c +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidload.c @@ -4,7 +4,7 @@ * * CID-keyed Type1 font loader (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -388,7 +388,7 @@ T1_FIELD_CALLBACK( "ExpansionFactor", parse_expansion_factor, 0 ) T1_FIELD_CALLBACK( "FontName", parse_font_name, 0 ) - { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 } + T1_FIELD_ZERO }; @@ -469,36 +469,23 @@ T1_Field keyword = (T1_Field)cid_field_records; - for (;;) + while ( keyword->len ) { - FT_Byte* name; + FT_Byte* name = (FT_Byte*)keyword->ident; - name = (FT_Byte*)keyword->ident; - if ( !name ) - break; - - if ( cur[0] == name[0] && - len == ft_strlen( (const char*)name ) ) + if ( keyword->len == len && + ft_memcmp( cur, name, len ) == 0 ) { - FT_UInt n; - - - for ( n = 1; n < len; n++ ) - if ( cur[n] != name[n] ) - break; - - if ( n >= len ) - { - /* we found it - run the parsing callback */ - parser->root.error = cid_load_keyword( face, - loader, - keyword ); - if ( parser->root.error ) - return parser->root.error; - break; - } + /* we found it - run the parsing callback */ + parser->root.error = cid_load_keyword( face, + loader, + keyword ); + if ( parser->root.error ) + return parser->root.error; + break; } + keyword++; } } diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidload.h b/src/java.desktop/share/native/libfreetype/src/cid/cidload.h index d12d2962a68..7f030b32df7 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidload.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidload.h @@ -4,7 +4,7 @@ * * CID-keyed Type1 font loader (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c index f698a419289..8d337c41128 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c @@ -4,7 +4,7 @@ * * CID objects manager (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h index 83c0c61c3ca..d371cbe9954 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h @@ -4,7 +4,7 @@ * * CID objects manager (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c index 171a886215a..73a3ade893b 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c @@ -4,7 +4,7 @@ * * CID-keyed Type1 parser (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -90,10 +90,15 @@ if ( error ) goto Exit; - Again: - /* now, read the rest of the file until we find */ - /* `StartData' or `/sfnts' */ + if ( !stream->read ) { + /* just parse memory-based streams */ + offset = stream->size; + } + else { + /* Find the last `StartData` or `/sfnts`. The parser requires */ + /* contiguous memory; attempt to pin as little as necessary. */ + /* * The algorithm is as follows (omitting the case with less than 256 * bytes to fill for simplicity). @@ -119,7 +124,8 @@ FT_Byte* p = buffer; - for ( offset = FT_STREAM_POS(); ; offset += 256 ) + offset = 0; + while ( 1 ) { FT_ULong stream_len; @@ -127,7 +133,7 @@ stream_len = stream->size - FT_STREAM_POS(); read_len = FT_MIN( read_len, stream_len ); - if ( FT_STREAM_READ( p, read_len ) ) + if ( read_len && FT_STREAM_READ( p, read_len ) ) goto Exit; /* ensure that we do not compare with data beyond the buffer */ @@ -141,20 +147,23 @@ ft_strncmp( (char*)p, STARTDATA, STARTDATA_LEN ) == 0 ) { /* save offset of binary data after `StartData' */ - offset += (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1; - goto Found; + offset = FT_STREAM_POS() - read_len - read_offset + + (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1; } else if ( p[1] == 's' && ft_strncmp( (char*)p, SFNTS, SFNTS_LEN ) == 0 ) { - offset += (FT_ULong)( p - buffer ) + SFNTS_LEN + 1; - goto Found; + offset = FT_STREAM_POS() - read_len - read_offset + + (FT_ULong)( p - buffer ) + SFNTS_LEN + 1; } } - if ( read_offset + read_len < STARTDATA_LEN ) + if ( read_offset + read_len <= STARTDATA_LEN ) { - FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" )); + if ( offset ) + goto Found; + + FT_TRACE2(( "cid_parser_new: no `StartData` keyword found\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } @@ -171,9 +180,9 @@ } Found: - /* We have found the start of the binary data or the `/sfnts' token. */ - /* Now rewind and extract the frame corresponding to this PostScript */ - /* section. */ + /* We have found an efficient range to look for the binary data or */ + /* `/sfnts' token. Now rewind and extract the frame corresponding to */ + /* this PostScript section. */ ps_len = offset - base_offset; if ( FT_STREAM_SEEK( base_offset ) || @@ -187,8 +196,8 @@ parser->root.limit = parser->root.cursor + ps_len; parser->num_dict = FT_UINT_MAX; - /* Finally, we check whether `StartData' or `/sfnts' was real -- */ - /* it could be in a comment or string. We also get the arguments */ + /* Find the first real `StartData' or `/sfnts' -- the last one */ + /* could be in a comment or string. We also get the arguments */ /* of `StartData' to find out whether the data is represented in */ /* binary or hex format. */ @@ -216,6 +225,7 @@ { T1_TokenRec type_token; FT_Long binary_length; + FT_ULong found_offset; parser->root.cursor = arg1; @@ -234,6 +244,24 @@ parser->binary_length = (FT_ULong)binary_length; } + /* set the real values for the parser, if different */ + found_offset = (FT_ULong)( cur - parser->postscript ) + + STARTDATA_LEN + 1; + if ( found_offset != offset ) + { + FT_FRAME_RELEASE( parser->postscript ); + + ps_len = found_offset - base_offset; + if ( FT_STREAM_SEEK( base_offset ) || + FT_FRAME_EXTRACT( ps_len, parser->postscript ) ) + goto Exit; + + parser->data_offset = found_offset; + parser->postscript_len = ps_len; + parser->root.base = parser->postscript; + parser->root.cursor = parser->postscript; + parser->root.limit = parser->root.cursor + ps_len; + } goto Exit; } else if ( cur[1] == 's' && @@ -251,11 +279,8 @@ cur = parser->root.cursor; } - /* we haven't found the correct `StartData'; go back and continue */ - /* searching */ - FT_FRAME_RELEASE( parser->postscript ); - if ( !FT_STREAM_SEEK( offset ) ) - goto Again; + FT_TRACE2(( "cid_parser_new: no `StartData` token found\n" )); + error = FT_THROW( Invalid_File_Format ); Exit: return error; diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h index 2fd4e7a9310..0f5baddcb92 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h @@ -4,7 +4,7 @@ * * CID-keyed Type1 parser (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c index 99e7b118395..4be8a5c00d5 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c @@ -4,7 +4,7 @@ * * CID driver interface (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h index a6249385c81..7ddce431c5b 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h @@ -4,7 +4,7 @@ * * High-level CID driver interface (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h b/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h index 925951acdbd..160897d1447 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h @@ -4,7 +4,7 @@ * * CID token definitions (specification only). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c index db08941def7..e2f6a8e5adb 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c @@ -4,7 +4,7 @@ * * AFM parser (body). * - * Copyright (C) 2006-2023 by + * Copyright (C) 2006-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h index 2d3b6e6e169..b7766372821 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h @@ -4,7 +4,7 @@ * * AFM parser (specification). * - * Copyright (C) 2006-2023 by + * Copyright (C) 2006-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c index 562d17d2216..9556e11a586 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c @@ -4,7 +4,7 @@ * * PostScript CFF (Type 2) decoding routines (body). * - * Copyright (C) 2017-2023 by + * Copyright (C) 2017-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -17,6 +17,7 @@ #include <freetype/freetype.h> +#include <freetype/internal/ftcalc.h> #include <freetype/internal/ftdebug.h> #include <freetype/internal/ftserv.h> #include <freetype/internal/services/svcfftl.h> @@ -1752,22 +1753,9 @@ /* without upper limit the loop below might not finish */ if ( args[0] > 0x7FFFFFFFL ) - args[0] = 46341; + args[0] = 0xB504F4L; /* sqrt( 32768.0044 ) */ else if ( args[0] > 0 ) - { - FT_Fixed root = args[0]; - FT_Fixed new_root; - - - for (;;) - { - new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1; - if ( new_root == root ) - break; - root = new_root; - } - args[0] = new_root; - } + args[0] = (FT_Fixed)FT_SqrtFixed( args[0] ); else args[0] = 0; args++; diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h index e8bb4001cba..038f7235c3d 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h @@ -4,7 +4,7 @@ * * PostScript CFF (Type 2) decoding routines (specification). * - * Copyright (C) 2017-2023 by + * Copyright (C) 2017-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h b/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h index 895ffa48c2c..18428c40d5a 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h @@ -4,7 +4,7 @@ * * PS auxiliary module error codes (specification only). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c index 45e35aa53c4..6826f9d8d3e 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c @@ -4,7 +4,7 @@ * * FreeType auxiliary PostScript module implementation (body). * - * Copyright (C) 2000-2023 by + * Copyright (C) 2000-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h index 94dbf48813c..82d7e348af8 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h @@ -4,7 +4,7 @@ * * FreeType auxiliary PostScript module implementation (specification). * - * Copyright (C) 2000-2023 by + * Copyright (C) 2000-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c b/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c index f9c864fea9a..213b943b465 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c @@ -54,14 +54,6 @@ #define FT_COMPONENT cf2blues - /* - * For blue values, the FreeType parser produces an array of integers, - * while the Adobe CFF engine produces an array of fixed. - * Define a macro to convert FreeType to fixed. - */ -#define cf2_blueToFixed( x ) cf2_intToFixed( x ) - - FT_LOCAL_DEF( void ) cf2_blues_init( CF2_Blues blues, CF2_Font font ) @@ -78,10 +70,10 @@ size_t numFamilyBlues; size_t numFamilyOtherBlues; - FT_Pos* blueValues; - FT_Pos* otherBlues; - FT_Pos* familyBlues; - FT_Pos* familyOtherBlues; + FT_Fixed* blueValues; + FT_Fixed* otherBlues; + FT_Fixed* familyBlues; + FT_Fixed* familyOtherBlues; size_t i; CF2_Fixed emBoxBottom, emBoxTop; @@ -138,13 +130,13 @@ emBoxTop = CF2_ICF_Top; } - if ( cf2_getLanguageGroup( decoder ) == 1 && - ( numBlueValues == 0 || - ( numBlueValues == 4 && - cf2_blueToFixed( blueValues[0] ) < emBoxBottom && - cf2_blueToFixed( blueValues[1] ) < emBoxBottom && - cf2_blueToFixed( blueValues[2] ) > emBoxTop && - cf2_blueToFixed( blueValues[3] ) > emBoxTop ) ) ) + if ( cf2_getLanguageGroup( decoder ) == 1 && + ( numBlueValues == 0 || + ( numBlueValues == 4 && + blueValues[0] < emBoxBottom && + blueValues[1] < emBoxBottom && + blueValues[2] > emBoxTop && + blueValues[3] > emBoxTop ) ) ) { /* * Construct hint edges suitable for synthetic ghost hints at top @@ -189,10 +181,8 @@ /* bottom zones */ for ( i = 0; i < numBlueValues; i += 2 ) { - blues->zone[blues->count].csBottomEdge = - cf2_blueToFixed( blueValues[i] ); - blues->zone[blues->count].csTopEdge = - cf2_blueToFixed( blueValues[i + 1] ); + blues->zone[blues->count].csBottomEdge = blueValues[i]; + blues->zone[blues->count].csTopEdge = blueValues[i + 1]; zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge, blues->zone[blues->count].csBottomEdge ); @@ -238,10 +228,8 @@ for ( i = 0; i < numOtherBlues; i += 2 ) { - blues->zone[blues->count].csBottomEdge = - cf2_blueToFixed( otherBlues[i] ); - blues->zone[blues->count].csTopEdge = - cf2_blueToFixed( otherBlues[i + 1] ); + blues->zone[blues->count].csBottomEdge = otherBlues[i]; + blues->zone[blues->count].csTopEdge = otherBlues[i + 1]; zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge, blues->zone[blues->count].csBottomEdge ); @@ -299,7 +287,7 @@ for ( j = 0; j < numFamilyOtherBlues; j += 2 ) { /* top edge */ - flatFamilyEdge = cf2_blueToFixed( familyOtherBlues[j + 1] ); + flatFamilyEdge = familyOtherBlues[j + 1]; diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) ); @@ -317,7 +305,7 @@ if ( numFamilyBlues >= 2 ) { /* top edge */ - flatFamilyEdge = cf2_blueToFixed( familyBlues[1] ); + flatFamilyEdge = familyBlues[1]; diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) ); @@ -337,7 +325,7 @@ for ( j = 2; j < numFamilyBlues; j += 2 ) { /* bottom edge */ - flatFamilyEdge = cf2_blueToFixed( familyBlues[j] ); + flatFamilyEdge = familyBlues[j]; /* adjust edges of top zone upward by twice darkening amount */ flatFamilyEdge += 2 * font->darkenY; /* bottom edge */ diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c index b9c7138d846..56c0ecd1d7f 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c @@ -4,7 +4,7 @@ * * Some convenience conversions (body). * - * Copyright (C) 2006-2023 by + * Copyright (C) 2006-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h index b7c3ee00be8..91fcd15a1c9 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h @@ -4,7 +4,7 @@ * * Some convenience conversions (specification). * - * Copyright (C) 2006-2023 by + * Copyright (C) 2006-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psft.c b/src/java.desktop/share/native/libfreetype/src/psaux/psft.c index 618864e6e07..fd0abe17154 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psft.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psft.c @@ -566,12 +566,12 @@ FT_LOCAL_DEF( void ) cf2_getBlueValues( PS_Decoder* decoder, size_t* count, - FT_Pos* *data ) + FT_Fixed* *data ) { FT_ASSERT( decoder && decoder->current_subfont ); *count = decoder->current_subfont->private_dict.num_blue_values; - *data = (FT_Pos*) + *data = (FT_Fixed*) &decoder->current_subfont->private_dict.blue_values; } @@ -579,12 +579,12 @@ FT_LOCAL_DEF( void ) cf2_getOtherBlues( PS_Decoder* decoder, size_t* count, - FT_Pos* *data ) + FT_Fixed* *data ) { FT_ASSERT( decoder && decoder->current_subfont ); *count = decoder->current_subfont->private_dict.num_other_blues; - *data = (FT_Pos*) + *data = (FT_Fixed*) &decoder->current_subfont->private_dict.other_blues; } @@ -592,12 +592,12 @@ FT_LOCAL_DEF( void ) cf2_getFamilyBlues( PS_Decoder* decoder, size_t* count, - FT_Pos* *data ) + FT_Fixed* *data ) { FT_ASSERT( decoder && decoder->current_subfont ); *count = decoder->current_subfont->private_dict.num_family_blues; - *data = (FT_Pos*) + *data = (FT_Fixed*) &decoder->current_subfont->private_dict.family_blues; } @@ -605,12 +605,12 @@ FT_LOCAL_DEF( void ) cf2_getFamilyOtherBlues( PS_Decoder* decoder, size_t* count, - FT_Pos* *data ) + FT_Fixed* *data ) { FT_ASSERT( decoder && decoder->current_subfont ); *count = decoder->current_subfont->private_dict.num_family_other_blues; - *data = (FT_Pos*) + *data = (FT_Fixed*) &decoder->current_subfont->private_dict.family_other_blues; } diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psft.h b/src/java.desktop/share/native/libfreetype/src/psaux/psft.h index 3da454e6012..d9082f3a2be 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psft.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psft.h @@ -92,19 +92,19 @@ FT_BEGIN_HEADER FT_LOCAL( void ) cf2_getBlueValues( PS_Decoder* decoder, size_t* count, - FT_Pos* *data ); + FT_Fixed* *data ); FT_LOCAL( void ) cf2_getOtherBlues( PS_Decoder* decoder, size_t* count, - FT_Pos* *data ); + FT_Fixed* *data ); FT_LOCAL( void ) cf2_getFamilyBlues( PS_Decoder* decoder, size_t* count, - FT_Pos* *data ); + FT_Fixed* *data ); FT_LOCAL( void ) cf2_getFamilyOtherBlues( PS_Decoder* decoder, size_t* count, - FT_Pos* *data ); + FT_Fixed* *data ); FT_LOCAL( CF2_Int ) cf2_getLanguageGroup( PS_Decoder* decoder ); diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c b/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c index 6c640eebd5a..7572e225e37 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c @@ -37,6 +37,7 @@ #include "psft.h" +#include <freetype/internal/ftcalc.h> #include <freetype/internal/ftdebug.h> #include <freetype/internal/services/svcfftl.h> @@ -428,6 +429,8 @@ base = cf2_stack_count( opStack ) - numOperands; delta = base + numBlends; + FT_TRACE6(( " (" )); + for ( i = 0; i < numBlends; i++ ) { const CF2_Fixed* weight = &blend->BV[1]; @@ -442,10 +445,14 @@ cf2_stack_getReal( opStack, delta++ ) ) ); + FT_TRACE6(( "%f ", (double)sum / 65536 )); + /* store blended result */ cf2_stack_setReal( opStack, i + base, sum ); } + FT_TRACE6(( "blended)\n" )); + /* leave only `numBlends' results on stack */ cf2_stack_pop( opStack, numOperands - numBlends ); } @@ -734,7 +741,7 @@ FT_UInt numBlends; - FT_TRACE4(( " blend\n" )); + FT_TRACE4(( " blend" )); if ( !font->isCFF2 ) break; /* clear stack & ignore */ @@ -2275,23 +2282,7 @@ arg = cf2_stack_popFixed( opStack ); if ( arg > 0 ) - { - /* use a start value that doesn't make */ - /* the algorithm's addition overflow */ - FT_Fixed root = arg < 10 ? arg : arg >> 1; - FT_Fixed new_root; - - - /* Babylonian method */ - for (;;) - { - new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1; - if ( new_root == root ) - break; - root = new_root; - } - arg = new_root; - } + arg = (CF2_F16Dot16)FT_SqrtFixed( (FT_UInt32)arg ); else arg = 0; diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c index 8da755d0e57..eca465f009e 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c @@ -4,7 +4,7 @@ * * Auxiliary functions for PostScript fonts (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -23,6 +23,7 @@ #include "psobjs.h" #include "psconv.h" +#include "psft.h" #include "psauxerr.h" #include "psauxmod.h" @@ -200,7 +201,9 @@ /* add the object to the base block and adjust offset */ table->elements[idx] = FT_OFFSET( table->block, table->cursor ); table->lengths [idx] = length; - FT_MEM_COPY( table->block + table->cursor, object, length ); + /* length == 0 also implies a NULL destination, so skip the copy call */ + if ( length > 0 ) + FT_MEM_COPY( table->block + table->cursor, object, length ); table->cursor += length; return FT_Err_Ok; @@ -1624,7 +1627,7 @@ if ( builder->load_points ) { FT_Vector* point = outline->points + outline->n_points; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; + FT_Byte* control = outline->tags + outline->n_points; point->x = FIXED_TO_INT( x ); @@ -1677,8 +1680,7 @@ if ( !error ) { if ( outline->n_contours > 0 ) - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); + outline->contours[outline->n_contours - 1] = outline->n_points - 1; outline->n_contours++; } @@ -1740,7 +1742,7 @@ { FT_Vector* p1 = outline->points + first; FT_Vector* p2 = outline->points + outline->n_points - 1; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; + FT_Byte* control = outline->tags + outline->n_points - 1; /* `delete' last point only if it coincides with the first */ @@ -1760,8 +1762,7 @@ outline->n_points--; } else - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); + outline->contours[outline->n_contours - 1] = outline->n_points - 1; } } @@ -1899,7 +1900,7 @@ if ( builder->load_points ) { FT_Vector* point = outline->points + outline->n_points; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; + FT_Byte* control = outline->tags + outline->n_points; #ifdef CFF_CONFIG_OPTION_OLD_ENGINE PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face ); @@ -1959,8 +1960,7 @@ if ( !error ) { if ( outline->n_contours > 0 ) - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); + outline->contours[outline->n_contours - 1] = outline->n_points - 1; outline->n_contours++; } @@ -2019,7 +2019,7 @@ { FT_Vector* p1 = outline->points + first; FT_Vector* p2 = outline->points + outline->n_points - 1; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; + FT_Byte* control = outline->tags + outline->n_points - 1; /* `delete' last point only if it coincides with the first */ @@ -2039,8 +2039,7 @@ outline->n_points--; } else - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); + outline->contours[outline->n_contours - 1] = outline->n_points - 1; } } @@ -2188,7 +2187,7 @@ if ( builder->load_points ) { FT_Vector* point = outline->points + outline->n_points; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; + FT_Byte* control = outline->tags + outline->n_points; #ifdef CFF_CONFIG_OPTION_OLD_ENGINE PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face ); @@ -2267,8 +2266,7 @@ if ( !error ) { if ( outline->n_contours > 0 ) - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); + outline->contours[outline->n_contours - 1] = outline->n_points - 1; outline->n_contours++; } @@ -2327,7 +2325,7 @@ { FT_Vector* p1 = outline->points + first; FT_Vector* p2 = outline->points + outline->n_points - 1; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; + FT_Byte* control = outline->tags + outline->n_points - 1; /* `delete' last point only if it coincides with the first */ @@ -2347,8 +2345,7 @@ outline->n_points--; } else - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); + outline->contours[outline->n_contours - 1] = outline->n_points - 1; } } @@ -2463,19 +2460,20 @@ count = cpriv->num_blue_values = priv->num_blue_values; for ( n = 0; n < count; n++ ) - cpriv->blue_values[n] = (FT_Pos)priv->blue_values[n]; + cpriv->blue_values[n] = cf2_intToFixed( priv->blue_values[n] ); count = cpriv->num_other_blues = priv->num_other_blues; for ( n = 0; n < count; n++ ) - cpriv->other_blues[n] = (FT_Pos)priv->other_blues[n]; + cpriv->other_blues[n] = cf2_intToFixed( priv->other_blues[n] ); count = cpriv->num_family_blues = priv->num_family_blues; for ( n = 0; n < count; n++ ) - cpriv->family_blues[n] = (FT_Pos)priv->family_blues[n]; + cpriv->family_blues[n] = cf2_intToFixed( priv->family_blues[n] ); count = cpriv->num_family_other_blues = priv->num_family_other_blues; for ( n = 0; n < count; n++ ) - cpriv->family_other_blues[n] = (FT_Pos)priv->family_other_blues[n]; + cpriv->family_other_blues[n] = + cf2_intToFixed( priv->family_other_blues[n] ); cpriv->blue_scale = priv->blue_scale; cpriv->blue_shift = (FT_Pos)priv->blue_shift; diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h index d5bce541082..345fc8a7335 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h @@ -4,7 +4,7 @@ * * Auxiliary functions for PostScript fonts (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c index c4bcf599ea3..5681c3bd0fd 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c @@ -4,7 +4,7 @@ * * Type 1 character map support (body). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h index b3702498a55..445e6a2784f 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h @@ -4,7 +4,7 @@ * * Type 1 character map support (specification). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c index 4b6b969bcb9..c74baa8038f 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c @@ -4,7 +4,7 @@ * * PostScript Type 1 decoding routines (body). * - * Copyright (C) 2000-2023 by + * Copyright (C) 2000-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h index 0970def960b..16203b8f734 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h @@ -4,7 +4,7 @@ * * PostScript Type 1 decoding routines (specification). * - * Copyright (C) 2000-2023 by + * Copyright (C) 2000-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c index 4f622e1e440..967767b3485 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c @@ -4,7 +4,7 @@ * * PostScript hinting algorithm (body). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used @@ -1118,7 +1118,7 @@ FT_UInt n; PSH_Point point = glyph->points; FT_Vector* vec = glyph->outline->points; - char* tags = glyph->outline->tags; + FT_Byte* tags = glyph->outline->tags; for ( n = 0; n < glyph->num_points; n++ ) @@ -1171,8 +1171,8 @@ FT_QNEW_ARRAY( glyph->contours, outline->n_contours ) ) goto Exit; - glyph->num_points = (FT_UInt)outline->n_points; - glyph->num_contours = (FT_UInt)outline->n_contours; + glyph->num_points = outline->n_points; + glyph->num_contours = outline->n_contours; { FT_UInt first = 0, next, n; @@ -1186,7 +1186,7 @@ PSH_Point point; - next = (FT_UInt)outline->contours[n] + 1; + next = outline->contours[n] + 1; count = next - first; contour->start = points + first; diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h index 3f0ba28a693..fb362f061b6 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h @@ -4,7 +4,7 @@ * * PostScript hinting algorithm (specification). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c index d4c5eb32b1c..435f45838ff 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c @@ -5,7 +5,7 @@ * PostScript hinter global hinting management (body). * Inspired by the new auto-hinter module. * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h index 579eb2148a5..c5a5c913168 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h @@ -4,7 +4,7 @@ * * PostScript hinter global hinting management. * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c index 974a99e0186..9965d5b16bf 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c @@ -4,7 +4,7 @@ * * FreeType PostScript hinter module implementation (body). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h index 4bd781a35d7..62ac0a60fdc 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h @@ -4,7 +4,7 @@ * * PostScript hinter module interface (specification). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h index 97624952d8c..e9641340e53 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h @@ -4,7 +4,7 @@ * * PS Hinter error codes (specification only). * - * Copyright (C) 2003-2023 by + * Copyright (C) 2003-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c index 680e6d01358..0b2b549fc29 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c @@ -4,7 +4,7 @@ * * FreeType PostScript hints recorder (body). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -806,7 +806,7 @@ ps_hints_stem( PS_Hints hints, FT_UInt dimension, FT_Int count, - FT_Long* stems ) + FT_Pos* stems ) { PS_Dimension dim; diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h index 0b2484af121..7e375af7ba8 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h @@ -4,7 +4,7 @@ * * Postscript (Type1/Type2) hints recorder (specification). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c index 8203a0465d2..35d054d1cfb 100644 --- a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c +++ b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c @@ -4,7 +4,7 @@ * * psnames module implementation (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h index 0904700bfb8..770458316b1 100644 --- a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h +++ b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h @@ -4,7 +4,7 @@ * * High-level psnames module interface (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h b/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h index 0073f822848..e123eb65e39 100644 --- a/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h +++ b/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h @@ -4,7 +4,7 @@ * * PS names module error codes (specification only). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h b/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h index 7f92cce6039..2a941b04609 100644 --- a/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h +++ b/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h @@ -4,7 +4,7 @@ * * PostScript glyph names. * - * Copyright (C) 2005-2023 by + * Copyright (C) 2005-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h b/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h index 33dbfd631e9..943f2aa0a50 100644 --- a/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h @@ -5,7 +5,7 @@ * Miscellaneous macros for stand-alone rasterizer (specification * only). * - * Copyright (C) 2005-2023 by + * Copyright (C) 2005-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used @@ -92,27 +92,6 @@ #endif - static FT_Long - FT_MulDiv( FT_Long a, - FT_Long b, - FT_Long c ) - { - FT_Int s; - FT_Long d; - - - s = 1; - if ( a < 0 ) { a = -a; s = -1; } - if ( b < 0 ) { b = -b; s = -s; } - if ( c < 0 ) { c = -c; s = -s; } - - d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c - : 0x7FFFFFFFL ); - - return ( s > 0 ) ? d : -d; - } - - static FT_Long FT_MulDiv_No_Round( FT_Long a, FT_Long b, diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c index 192ca0701a2..e4b7b937d5a 100644 --- a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -63,8 +63,7 @@ #else /* !STANDALONE_ */ #include "ftraster.h" -#include <freetype/internal/ftcalc.h> /* for FT_MulDiv and FT_MulDiv_No_Round */ -#include <freetype/ftoutln.h> /* for FT_Outline_Get_CBox */ +#include <freetype/internal/ftcalc.h> /* for FT_MulDiv_No_Round */ #endif /* !STANDALONE_ */ @@ -115,12 +114,12 @@ * a change of direction is detected in the outline, a new profile is * generated until the end of the outline. * - * Note that when all profiles have been generated, the function - * Finalize_Profile_Table() is used to record, for each profile, its - * bottom-most scanline as well as the scanline above its upmost - * boundary. These positions are called `y-turns' because they (sort - * of) correspond to local extrema. They are stored in a sorted list - * built from the top of the render pool as a downwards stack: + * Note that, for all generated profiles, the function End_Profile() + * is used to record all their bottom-most scanlines as well as the + * scanline above their upmost boundary. These positions are called + * `y-turns' because they (sort of) correspond to local extrema. + * They are stored in a sorted list built from the top of the render + * pool as a downwards stack: * * _ _ _______________________________________ * | | @@ -136,7 +135,7 @@ * optimize performance (see technical note on the sweep below). * * Of course, the raster detects whether the two stacks collide and - * handles the situation properly. + * handles the situation by bisecting the job and restarting. * */ @@ -252,7 +251,6 @@ /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */ /* for clipping computations. It simply uses the FT_MulDiv() function */ /* defined in `ftcalc.h'. */ -#define SMulDiv FT_MulDiv #define SMulDiv_No_Round FT_MulDiv_No_Round /* The rasterizer is a very general purpose component; please leave */ @@ -305,16 +303,6 @@ typedef unsigned char Byte, *PByte; typedef char Bool; - - typedef union Alignment_ - { - Long l; - void* p; - void (*f)(void); - - } Alignment, *PAlignment; - - typedef struct TPoint_ { Long x; @@ -327,6 +315,7 @@ #define Flow_Up 0x08U #define Overshoot_Top 0x10U #define Overshoot_Bottom 0x20U +#define Dropout 0x40U /* States of each line, arc, and profile */ @@ -345,31 +334,28 @@ struct TProfile_ { - FT_F26Dot6 X; /* current coordinate during sweep */ PProfile link; /* link to next profile (various purposes) */ - PLong offset; /* start of profile's data in render pool */ + PProfile next; /* next profile in same contour, used */ + /* during drop-out control */ + Int offset; /* bottom or currently scanned array index */ + Int height; /* profile's height in scanlines */ + Int start; /* profile's starting scanline, also use */ + /* as activation counter */ UShort flags; /* Bit 0-2: drop-out mode */ /* Bit 3: profile orientation (up/down) */ /* Bit 4: is top profile? */ /* Bit 5: is bottom profile? */ - Long height; /* profile's height in scanlines */ - Long start; /* profile's starting scanline */ + /* Bit 6: dropout detected */ - Int countL; /* number of lines to step before this */ - /* profile becomes drawable */ - - PProfile next; /* next profile in same contour, used */ - /* during drop-out control */ + FT_F26Dot6 X; /* current coordinate during sweep */ + Long x[1]; /* actually variable array of scanline */ + /* intersections with `height` elements */ }; typedef PProfile TProfileList; typedef PProfile* PProfileList; -#define AlignProfileSize \ - ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( Long ) ) - - #undef RAS_ARG #undef RAS_ARGS #undef RAS_VAR @@ -407,15 +393,13 @@ /* prototypes used for sweep function dispatch */ typedef void - Function_Sweep_Init( RAS_ARGS Short min, - Short max ); + Function_Sweep_Init( RAS_ARGS Int min, + Int max ); typedef void - Function_Sweep_Span( RAS_ARGS Short y, + Function_Sweep_Span( RAS_ARGS Int y, FT_F26Dot6 x1, - FT_F26Dot6 x2, - PProfile left, - PProfile right ); + FT_F26Dot6 x2 ); typedef void Function_Sweep_Step( RAS_ARG ); @@ -441,8 +425,7 @@ (Bool)( x - FLOOR( x ) >= ras.precision_half ) /* Smart dropout rounding to find which pixel is closer to span ends. */ - /* To mimick Windows, symmetric cases break down indepenently of the */ - /* precision. */ + /* To mimic Windows, symmetric cases do not depend on the precision. */ #define SMART( p, q ) FLOOR( ( (p) + (q) + ras.precision * 63 / 64 ) >> 1 ) #if FT_RENDER_POOL_SIZE > 2048 @@ -462,7 +445,6 @@ Int precision_half; Int precision_scale; Int precision_step; - Int precision_jitter; PLong buff; /* The profiles buffer */ PLong sizeBuff; /* Render pool size */ @@ -471,24 +453,14 @@ FT_Error error; - Int numTurns; /* number of Y-turns in outline */ - Byte dropOutControl; /* current drop_out control method */ - UShort bWidth; /* target bitmap width */ - PByte bOrigin; /* target bitmap bottom-left origin */ - PByte bLine; /* target bitmap current line */ - Long lastX, lastY; Long minY, maxY; UShort num_Profs; /* current number of profiles */ + Int numTurns; /* number of Y-turns in outline */ - Bool fresh; /* signals a fresh new profile which */ - /* `start' field must be completed */ - Bool joint; /* signals that the last arc ended */ - /* exactly on a scanline. Allows */ - /* removal of doublets */ PProfile cProfile; /* current profile */ PProfile fProfile; /* head of linked list of profiles */ PProfile gProfile; /* contour's first profile in case */ @@ -496,9 +468,14 @@ TStates state; /* rendering state */ - FT_Bitmap target; /* description of target bit/pixmap */ FT_Outline outline; + Int bTop; /* target bitmap max line index */ + Int bRight; /* target bitmap rightmost index */ + Int bPitch; /* target bitmap pitch */ + PByte bOrigin; /* target bitmap bottom-left origin */ + PByte bLine; /* target bitmap current line */ + /* dispatch variables */ Function_Sweep_Init* Proc_Sweep_Init; @@ -563,37 +540,82 @@ * * 256 / (1 << 12) = 0.0625 pixels. * - * `precision_jitter' is an epsilon threshold used in - * `Vertical_Sweep_Span' to deal with small imperfections in the Bezier - * decomposition (after all, we are working with approximations only); - * it avoids switching on additional pixels which would cause artifacts - * otherwise. - * - * The value of `precision_jitter' has been determined heuristically. - * */ if ( High ) { ras.precision_bits = 12; ras.precision_step = 256; - ras.precision_jitter = 30; } else { ras.precision_bits = 6; ras.precision_step = 32; - ras.precision_jitter = 2; } - FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" )); - ras.precision = 1 << ras.precision_bits; ras.precision_half = ras.precision >> 1; ras.precision_scale = ras.precision >> Pixel_Bits; } + /************************************************************************** + * + * @Function: + * Insert_Y_Turn + * + * @Description: + * Insert a salient into the sorted list placed on top of the render + * pool. + * + * @Input: + * New y scanline position. + * + * @Return: + * SUCCESS on success. FAILURE in case of overflow. + */ + static Bool + Insert_Y_Turns( RAS_ARGS Int y, + Int top ) + { + Int n = ras.numTurns; + PLong y_turns = ras.maxBuff; + + + /* update top value */ + if ( n == 0 || top > y_turns[n] ) + y_turns[n] = top; + + /* look for first y value that is <= */ + while ( n-- && y < y_turns[n] ) + ; + + /* if it is <, simply insert it, ignore if == */ + if ( n < 0 || y > y_turns[n] ) + { + ras.maxBuff--; + if ( ras.maxBuff <= ras.top ) + { + ras.error = FT_THROW( Raster_Overflow ); + return FAILURE; + } + + do + { + Int y2 = (Int)y_turns[n]; + + + y_turns[n] = y; + y = y2; + } while ( n-- >= 0 ); + + ras.numTurns++; + } + + return SUCCESS; + } + + /************************************************************************** * * @Function: @@ -606,52 +628,48 @@ * aState :: * The state/orientation of the new profile. * - * overshoot :: - * Whether the profile's unrounded start position - * differs by at least a half pixel. - * * @Return: * SUCCESS on success. FAILURE in case of overflow or of incoherent * profile. */ static Bool - New_Profile( RAS_ARGS TStates aState, - Bool overshoot ) + New_Profile( RAS_ARGS TStates aState ) { - if ( !ras.fProfile ) + Long e; + + + if ( !ras.cProfile || ras.cProfile->height ) { ras.cProfile = (PProfile)ras.top; - ras.fProfile = ras.cProfile; - ras.top += AlignProfileSize; - } + ras.top = ras.cProfile->x; - if ( ras.top >= ras.maxBuff ) - { - ras.error = FT_THROW( Raster_Overflow ); - return FAILURE; + if ( ras.top >= ras.maxBuff ) + { + FT_TRACE1(( "overflow in New_Profile\n" )); + ras.error = FT_THROW( Raster_Overflow ); + return FAILURE; + } + + ras.cProfile->height = 0; } - ras.cProfile->start = 0; - ras.cProfile->height = 0; - ras.cProfile->offset = ras.top; - ras.cProfile->link = (PProfile)0; - ras.cProfile->next = (PProfile)0; ras.cProfile->flags = ras.dropOutControl; switch ( aState ) { case Ascending_State: ras.cProfile->flags |= Flow_Up; - if ( overshoot ) + if ( IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ras.cProfile->flags |= Overshoot_Bottom; - FT_TRACE6(( " new ascending profile = %p\n", (void *)ras.cProfile )); + e = CEILING( ras.lastY ); break; case Descending_State: - if ( overshoot ) + if ( IS_TOP_OVERSHOOT( ras.lastY ) ) ras.cProfile->flags |= Overshoot_Top; - FT_TRACE6(( " new descending profile = %p\n", (void *)ras.cProfile )); + + e = FLOOR( ras.lastY ); break; default: @@ -660,12 +678,20 @@ return FAILURE; } - if ( !ras.gProfile ) - ras.gProfile = ras.cProfile; + if ( e > ras.maxY ) + e = ras.maxY; + if ( e < ras.minY ) + e = ras.minY; + ras.cProfile->start = (Int)TRUNC( e ); + + FT_TRACE7(( " new %s profile = %p, start = %d\n", + aState == Ascending_State ? "ascending" : "descending", + (void *)ras.cProfile, ras.cProfile->start )); + + if ( ras.lastY == e ) + *ras.top++ = ras.lastX; ras.state = aState; - ras.fresh = TRUE; - ras.joint = FALSE; return SUCCESS; } @@ -677,24 +703,19 @@ * End_Profile * * @Description: - * Finalize the current profile. - * - * @Input: - * overshoot :: - * Whether the profile's unrounded end position differs - * by at least a half pixel. + * Finalize the current profile and record y-turns. * * @Return: * SUCCESS on success. FAILURE in case of overflow or incoherency. */ static Bool - End_Profile( RAS_ARGS Bool overshoot ) + End_Profile( RAS_ARG ) { - Long h; + PProfile p = ras.cProfile; + Int h = (Int)( ras.top - p->x ); + Int bottom, top; - h = (Long)( ras.top - ras.cProfile->offset ); - if ( h < 0 ) { FT_ERROR(( "End_Profile: negative height encountered\n" )); @@ -704,98 +725,46 @@ if ( h > 0 ) { - PProfile oldProfile; + FT_TRACE7(( " ending profile %p, start = %2d, height = %+3d\n", + (void *)p, p->start, p->flags & Flow_Up ? h : -h )); + p->height = h; - FT_TRACE6(( " ending profile %p, start = %ld, height = %ld\n", - (void *)ras.cProfile, ras.cProfile->start, h )); + if ( p->flags & Flow_Up ) + { + if ( IS_TOP_OVERSHOOT( ras.lastY ) ) + p->flags |= Overshoot_Top; - ras.cProfile->height = h; - if ( overshoot ) + bottom = p->start; + top = bottom + h; + p->offset = 0; + p->X = p->x[0]; + } + else { - if ( ras.cProfile->flags & Flow_Up ) - ras.cProfile->flags |= Overshoot_Top; - else - ras.cProfile->flags |= Overshoot_Bottom; + if ( IS_BOTTOM_OVERSHOOT( ras.lastY ) ) + p->flags |= Overshoot_Bottom; + + top = p->start + 1; + bottom = top - h; + p->start = bottom; + p->offset = h - 1; + p->X = p->x[h - 1]; } - oldProfile = ras.cProfile; - ras.cProfile = (PProfile)ras.top; + if ( Insert_Y_Turns( RAS_VARS bottom, top ) ) + return FAILURE; - ras.top += AlignProfileSize; + if ( !ras.gProfile ) + ras.gProfile = p; - ras.cProfile->height = 0; - ras.cProfile->offset = ras.top; + /* preliminary values to be finalized */ + p->next = ras.gProfile; + p->link = (PProfile)ras.top; - oldProfile->next = ras.cProfile; ras.num_Profs++; } - if ( ras.top >= ras.maxBuff ) - { - FT_TRACE1(( "overflow in End_Profile\n" )); - ras.error = FT_THROW( Raster_Overflow ); - return FAILURE; - } - - ras.joint = FALSE; - - return SUCCESS; - } - - - /************************************************************************** - * - * @Function: - * Insert_Y_Turn - * - * @Description: - * Insert a salient into the sorted list placed on top of the render - * pool. - * - * @Input: - * New y scanline position. - * - * @Return: - * SUCCESS on success. FAILURE in case of overflow. - */ - static Bool - Insert_Y_Turn( RAS_ARGS Int y ) - { - PLong y_turns; - Int n; - - - n = ras.numTurns - 1; - y_turns = ras.sizeBuff - ras.numTurns; - - /* look for first y value that is <= */ - while ( n >= 0 && y < y_turns[n] ) - n--; - - /* if it is <, simply insert it, ignore if == */ - if ( n >= 0 && y > y_turns[n] ) - do - { - Int y2 = (Int)y_turns[n]; - - - y_turns[n] = y; - y = y2; - } while ( --n >= 0 ); - - if ( n < 0 ) - { - ras.maxBuff--; - if ( ras.maxBuff <= ras.top ) - { - ras.error = FT_THROW( Raster_Overflow ); - return FAILURE; - } - ras.numTurns++; - ras.sizeBuff[-ras.numTurns] = y; - } - return SUCCESS; } @@ -807,56 +776,29 @@ * * @Description: * Adjust all links in the profiles list. - * - * @Return: - * SUCCESS on success. FAILURE in case of overflow. */ - static Bool + static void Finalize_Profile_Table( RAS_ARG ) { - UShort n; - PProfile p; - + UShort n = ras.num_Profs; + PProfile p = ras.fProfile; + PProfile q; - n = ras.num_Profs; - p = ras.fProfile; - if ( n > 1 && p ) + /* there should be at least two profiles, up and down */ + while ( --n ) { - do - { - Int bottom, top; + q = p->link; + /* fix the contour loop */ + if ( q->next == p->next ) + p->next = q; - if ( n > 1 ) - p->link = (PProfile)( p->offset + p->height ); - else - p->link = NULL; - - if ( p->flags & Flow_Up ) - { - bottom = (Int)p->start; - top = (Int)( p->start + p->height - 1 ); - } - else - { - bottom = (Int)( p->start - p->height + 1 ); - top = (Int)p->start; - p->start = bottom; - p->offset += p->height - 1; - } - - if ( Insert_Y_Turn( RAS_VARS bottom ) || - Insert_Y_Turn( RAS_VARS top + 1 ) ) - return FAILURE; - - p = p->link; - } while ( --n ); + p = q; } - else - ras.fProfile = NULL; - return SUCCESS; + /* null-terminate */ + p->link = NULL; } @@ -986,107 +928,78 @@ Long miny, Long maxy ) { - Long Dx, Dy; - Int e1, e2, f1, f2, size; /* XXX: is `Short' sufficient? */ - Long Ix, Rx, Ax; + Long e, e2, Dx, Dy; + Long Ix, Rx, Ax; + Int size; PLong top; - Dx = x2 - x1; - Dy = y2 - y1; - - if ( Dy <= 0 || y2 < miny || y1 > maxy ) + if ( y2 < miny || y1 > maxy ) return SUCCESS; - if ( y1 < miny ) - { - /* Take care: miny-y1 can be a very large value; we use */ - /* a slow MulDiv function to avoid clipping bugs */ - x1 += SMulDiv( Dx, miny - y1, Dy ); - e1 = (Int)TRUNC( miny ); - f1 = 0; - } - else - { - e1 = (Int)TRUNC( y1 ); - f1 = (Int)FRAC( y1 ); - } + e2 = y2 > maxy ? maxy : FLOOR( y2 ); + e = y1 < miny ? miny : CEILING( y1 ); - if ( y2 > maxy ) - { - /* x2 += FMulDiv( Dx, maxy - y2, Dy ); UNNECESSARY */ - e2 = (Int)TRUNC( maxy ); - f2 = 0; - } - else - { - e2 = (Int)TRUNC( y2 ); - f2 = (Int)FRAC( y2 ); - } + if ( y1 == e ) + e += ras.precision; - if ( f1 > 0 ) - { - if ( e1 == e2 ) - return SUCCESS; - else - { - x1 += SMulDiv( Dx, ras.precision - f1, Dy ); - e1 += 1; - } - } - else - if ( ras.joint ) - { - ras.top--; - ras.joint = FALSE; - } - - ras.joint = (char)( f2 == 0 ); + if ( e2 < e ) /* nothing to do */ + return SUCCESS; - if ( ras.fresh ) - { - ras.cProfile->start = e1; - ras.fresh = FALSE; - } + size = (Int)TRUNC( e2 - e ) + 1; + top = ras.top; - size = e2 - e1 + 1; - if ( ras.top + size >= ras.maxBuff ) + if ( top + size >= ras.maxBuff ) { ras.error = FT_THROW( Raster_Overflow ); return FAILURE; } - if ( Dx > 0 ) - { - Ix = SMulDiv_No_Round( ras.precision, Dx, Dy ); - Rx = ( ras.precision * Dx ) % Dy; - Dx = 1; - } - else + Dx = x2 - x1; + Dy = y2 - y1; + + if ( Dx == 0 ) /* very easy */ { - Ix = -SMulDiv_No_Round( ras.precision, -Dx, Dy ); - Rx = ( ras.precision * -Dx ) % Dy; - Dx = -1; + do + *top++ = x1; + while ( --size ); + goto Fin; } - Ax = -Dy; - top = ras.top; + Ix = SMulDiv_No_Round( e - y1, Dx, Dy ); + x1 += Ix; + *top++ = x1; - while ( size > 0 ) + if ( --size ) { - *top++ = x1; + Ax = Dx * ( e - y1 ) - Dy * Ix; /* remainder */ + Ix = FMulDiv( ras.precision, Dx, Dy ); + Rx = Dx * ras.precision - Dy * Ix; /* remainder */ + Dx = 1; - x1 += Ix; - Ax += Rx; - if ( Ax >= 0 ) + if ( x2 < x1 ) + { + Ax = -Ax; + Rx = -Rx; + Dx = -Dx; + } + + do { - Ax -= Dy; - x1 += Dx; + x1 += Ix; + Ax += Rx; + if ( Ax >= Dy ) + { + Ax -= Dy; + x1 += Dx; + } + *top++ = x1; } - size--; + while ( --size ); } + Fin: ras.top = top; return SUCCESS; } @@ -1131,17 +1044,7 @@ Long miny, Long maxy ) { - Bool result, fresh; - - - fresh = ras.fresh; - - result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny ); - - if ( fresh && !ras.fresh ) - ras.cProfile->start = -ras.cProfile->start; - - return result; + return Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny ); } @@ -1181,105 +1084,73 @@ Long miny, Long maxy ) { - Long y1, y2, e, e2, e0; - Short f1; + Long y1, y2, e, e2, dy; + Long dx, x2; - TPoint* start_arc; - - PLong top; + PLong top; y1 = arc[degree].y; y2 = arc[0].y; - top = ras.top; if ( y2 < miny || y1 > maxy ) - goto Fin; - - e2 = FLOOR( y2 ); - - if ( e2 > maxy ) - e2 = maxy; - - e0 = miny; - - if ( y1 < miny ) - e = miny; - else - { - e = CEILING( y1 ); - f1 = (Short)( FRAC( y1 ) ); - e0 = e; - - if ( f1 == 0 ) - { - if ( ras.joint ) - { - top--; - ras.joint = FALSE; - } + return SUCCESS; - *top++ = arc[degree].x; + e2 = y2 > maxy ? maxy : FLOOR( y2 ); + e = y1 < miny ? miny : CEILING( y1 ); - e += ras.precision; - } - } + if ( y1 == e ) + e += ras.precision; - if ( ras.fresh ) - { - ras.cProfile->start = TRUNC( e0 ); - ras.fresh = FALSE; - } + if ( e2 < e ) /* nothing to do */ + return SUCCESS; - if ( e2 < e ) - goto Fin; + top = ras.top; if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff ) { - ras.top = top; ras.error = FT_THROW( Raster_Overflow ); return FAILURE; } - start_arc = arc; - do { - ras.joint = FALSE; - y2 = arc[0].y; + x2 = arc[0].x; if ( y2 > e ) { - y1 = arc[degree].y; - if ( y2 - y1 >= ras.precision_step ) + dy = y2 - arc[degree].y; + dx = x2 - arc[degree].x; + + /* split condition should be invariant of direction */ + if ( dy > ras.precision_step || + dx > ras.precision_step || + -dx > ras.precision_step ) { splitter( arc ); arc += degree; } else { - *top++ = arc[degree].x + FMulDiv( arc[0].x - arc[degree].x, - e - y1, y2 - y1 ); + *top++ = x2 - FMulDiv( y2 - e, dx, dy ); + e += ras.precision; arc -= degree; - e += ras.precision; } } else { if ( y2 == e ) { - ras.joint = TRUE; - *top++ = arc[0].x; - - e += ras.precision; + *top++ = x2; + e += ras.precision; } - arc -= degree; + arc -= degree; } - } while ( arc >= start_arc && e <= e2 ); + } + while ( e <= e2 ); - Fin: - ras.top = top; + ras.top = top; return SUCCESS; } @@ -1316,7 +1187,7 @@ Long miny, Long maxy ) { - Bool result, fresh; + Bool result; arc[0].y = -arc[0].y; @@ -1325,13 +1196,8 @@ if ( degree > 2 ) arc[3].y = -arc[3].y; - fresh = ras.fresh; - result = Bezier_Up( RAS_VARS degree, arc, splitter, -maxy, -miny ); - if ( fresh && !ras.fresh ) - ras.cProfile->start = -ras.cProfile->start; - arc[0].y = -arc[0].y; return result; } @@ -1362,74 +1228,50 @@ Line_To( RAS_ARGS Long x, Long y ) { - /* First, detect a change of direction */ + TStates state; - switch ( ras.state ) - { - case Unknown_State: - if ( y > ras.lastY ) - { - if ( New_Profile( RAS_VARS Ascending_State, - IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ) - return FAILURE; - } - else - { - if ( y < ras.lastY ) - if ( New_Profile( RAS_VARS Descending_State, - IS_TOP_OVERSHOOT( ras.lastY ) ) ) - return FAILURE; - } - break; - case Ascending_State: - if ( y < ras.lastY ) - { - if ( End_Profile( RAS_VARS IS_TOP_OVERSHOOT( ras.lastY ) ) || - New_Profile( RAS_VARS Descending_State, - IS_TOP_OVERSHOOT( ras.lastY ) ) ) - return FAILURE; - } - break; + if ( y == ras.lastY ) + goto Fin; - case Descending_State: - if ( y > ras.lastY ) - { - if ( End_Profile( RAS_VARS IS_BOTTOM_OVERSHOOT( ras.lastY ) ) || - New_Profile( RAS_VARS Ascending_State, - IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ) - return FAILURE; - } - break; + /* First, detect a change of direction */ - default: - ; + state = ras.lastY < y ? Ascending_State : Descending_State; + + if ( ras.state != state ) + { + /* finalize current profile if any */ + if ( ras.state != Unknown_State && + End_Profile( RAS_VAR ) ) + goto Fail; + + /* create a new profile */ + if ( New_Profile( RAS_VARS state ) ) + goto Fail; } /* Then compute the lines */ - switch ( ras.state ) + if ( state == Ascending_State ) { - case Ascending_State: if ( Line_Up( RAS_VARS ras.lastX, ras.lastY, x, y, ras.minY, ras.maxY ) ) - return FAILURE; - break; - - case Descending_State: + goto Fail; + } + else + { if ( Line_Down( RAS_VARS ras.lastX, ras.lastY, x, y, ras.minY, ras.maxY ) ) - return FAILURE; - break; - - default: - ; + goto Fail; } + Fin: ras.lastX = x; ras.lastY = y; - return SUCCESS; + + Fail: + return FAILURE; } @@ -1500,7 +1342,7 @@ ymax = y1; } - if ( y2 < ymin || y2 > ymax ) + if ( y2 < FLOOR( ymin ) || y2 > CEILING( ymax ) ) { /* this arc has no given direction, split it! */ Split_Conic( arc ); @@ -1508,8 +1350,12 @@ } else if ( y1 == y3 ) { - /* this arc is flat, ignore it and pop it from the Bezier stack */ + /* this arc is flat, advance position */ + /* and pop it from the Bezier stack */ arc -= 2; + + ras.lastX = x3; + ras.lastY = y3; } else { @@ -1518,18 +1364,13 @@ state_bez = y1 < y3 ? Ascending_State : Descending_State; if ( ras.state != state_bez ) { - Bool o = ( state_bez == Ascending_State ) - ? IS_BOTTOM_OVERSHOOT( y1 ) - : IS_TOP_OVERSHOOT( y1 ); - - /* finalize current profile if any */ if ( ras.state != Unknown_State && - End_Profile( RAS_VARS o ) ) + End_Profile( RAS_VAR ) ) goto Fail; /* create a new profile */ - if ( New_Profile( RAS_VARS state_bez, o ) ) + if ( New_Profile( RAS_VARS state_bez ) ) goto Fail; } @@ -1545,13 +1386,13 @@ ras.minY, ras.maxY ) ) goto Fail; arc -= 2; + + ras.lastX = x3; + ras.lastY = y3; } } while ( arc >= arcs ); - ras.lastX = x3; - ras.lastY = y3; - return SUCCESS; Fail: @@ -1648,7 +1489,7 @@ ymax2 = y2; } - if ( ymin2 < ymin1 || ymax2 > ymax1 ) + if ( ymin2 < FLOOR( ymin1 ) || ymax2 > CEILING( ymax1 ) ) { /* this arc has no given direction, split it! */ Split_Cubic( arc ); @@ -1656,27 +1497,26 @@ } else if ( y1 == y4 ) { - /* this arc is flat, ignore it and pop it from the Bezier stack */ + /* this arc is flat, advance position */ + /* and pop it from the Bezier stack */ arc -= 3; + + ras.lastX = x4; + ras.lastY = y4; } else { - state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State; + state_bez = y1 < y4 ? Ascending_State : Descending_State; /* detect a change of direction */ if ( ras.state != state_bez ) { - Bool o = ( state_bez == Ascending_State ) - ? IS_BOTTOM_OVERSHOOT( y1 ) - : IS_TOP_OVERSHOOT( y1 ); - - /* finalize current profile if any */ if ( ras.state != Unknown_State && - End_Profile( RAS_VARS o ) ) + End_Profile( RAS_VAR ) ) goto Fail; - if ( New_Profile( RAS_VARS state_bez, o ) ) + if ( New_Profile( RAS_VARS state_bez ) ) goto Fail; } @@ -1692,13 +1532,13 @@ ras.minY, ras.maxY ) ) goto Fail; arc -= 3; + + ras.lastX = x4; + ras.lastY = y4; } } while ( arc >= arcs ); - ras.lastX = x4; - ras.lastY = y4; - return SUCCESS; Fail: @@ -1740,6 +1580,11 @@ * * @Return: * SUCCESS on success, FAILURE on error. + * + * @Note: + * Unlike FT_Outline_Decompose(), this function handles the scanmode + * dropout tags in the individual contours. Therefore, it cannot be + * replaced. */ static Bool Decompose_Curve( RAS_ARGS Int first, @@ -1753,7 +1598,7 @@ FT_Vector* points; FT_Vector* point; FT_Vector* limit; - char* tags; + FT_Byte* tags; UInt tag; /* current point's state */ @@ -1974,24 +1819,17 @@ ras.fProfile = NULL; - ras.joint = FALSE; - ras.fresh = FALSE; - - ras.maxBuff = ras.sizeBuff - AlignProfileSize; + ras.cProfile = NULL; - ras.numTurns = 0; + ras.top = ras.buff; + ras.maxBuff = ras.sizeBuff - 1; /* top reserve */ - ras.cProfile = (PProfile)ras.top; - ras.cProfile->offset = ras.top; - ras.num_Profs = 0; + ras.numTurns = 0; + ras.num_Profs = 0; last = -1; for ( i = 0; i < ras.outline.n_contours; i++ ) { - PProfile lastProfile; - Bool o; - - ras.state = Unknown_State; ras.gProfile = NULL; @@ -2001,35 +1839,30 @@ if ( Decompose_Curve( RAS_VARS first, last, flipped ) ) return FAILURE; + /* Note that ras.gProfile can stay nil if the contour was */ + /* too small to be drawn or degenerate. */ + if ( !ras.gProfile ) + continue; + /* we must now check whether the extreme arcs join or not */ if ( FRAC( ras.lastY ) == 0 && ras.lastY >= ras.minY && ras.lastY <= ras.maxY ) - if ( ras.gProfile && - ( ras.gProfile->flags & Flow_Up ) == + if ( ( ras.gProfile->flags & Flow_Up ) == ( ras.cProfile->flags & Flow_Up ) ) ras.top--; - /* Note that ras.gProfile can be nil if the contour was too small */ - /* to be drawn. */ - lastProfile = ras.cProfile; - if ( ras.top != ras.cProfile->offset && - ( ras.cProfile->flags & Flow_Up ) ) - o = IS_TOP_OVERSHOOT( ras.lastY ); - else - o = IS_BOTTOM_OVERSHOOT( ras.lastY ); - if ( End_Profile( RAS_VARS o ) ) + if ( End_Profile( RAS_VAR ) ) return FAILURE; - /* close the `next profile in contour' linked list */ - if ( ras.gProfile ) - lastProfile->next = ras.gProfile; + if ( !ras.fProfile ) + ras.fProfile = ras.gProfile; } - if ( Finalize_Profile_Table( RAS_VAR ) ) - return FAILURE; + if ( ras.fProfile ) + Finalize_Profile_Table( RAS_VAR ); - return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE ); + return SUCCESS; } @@ -2042,24 +1875,11 @@ /*************************************************************************/ - /************************************************************************** - * - * Init_Linked - * - * Initializes an empty linked list. - */ - static void - Init_Linked( TProfileList* l ) - { - *l = NULL; - } - - /************************************************************************** * * InsNew * - * Inserts a new profile in a linked list. + * Inserts a new profile in a linked list, sorted by coordinate. */ static void InsNew( PProfileList list, @@ -2073,10 +1893,8 @@ current = *old; x = profile->X; - while ( current ) + while ( current && current->X < x ) { - if ( x < current->X ) - break; old = ¤t->link; current = *old; } @@ -2088,79 +1906,51 @@ /************************************************************************** * - * DelOld + * Increment * - * Removes an old profile from a linked list. + * Advances all profile in the list to the next scanline. It also + * sorts the trace list in the unlikely case of profile crossing. + * The profiles are inserted in sorted order. We might need a single + * swap to fix it when profiles (contours) cross. + * Bubble sort with immediate restart is good enough and simple. */ static void - DelOld( PProfileList list, - const PProfile profile ) + Increment( PProfileList list, + Int flow ) { - PProfile *old, current; - + PProfile *old, current, next; - old = list; - current = *old; - while ( current ) + /* First, set the new X coordinates and remove exhausted profiles */ + old = list; + while ( *old ) { - if ( current == profile ) + current = *old; + if ( --current->height ) { - *old = current->link; - return; + current->offset += flow; + current->X = current->x[current->offset]; + old = ¤t->link; } - - old = ¤t->link; - current = *old; - } - - /* we should never get there, unless the profile was not part of */ - /* the list. */ - } - - - /************************************************************************** - * - * Sort - * - * Sorts a trace list. In 95%, the list is already sorted. We need - * an algorithm which is fast in this case. Bubble sort is enough - * and simple. - */ - static void - Sort( PProfileList list ) - { - PProfile *old, current, next; - - - /* First, set the new X coordinate of each profile */ - current = *list; - while ( current ) - { - current->X = *current->offset; - current->offset += ( current->flags & Flow_Up ) ? 1 : -1; - current->height--; - current = current->link; + else + *old = current->link; /* remove */ } - /* Then sort them */ + /* Then make sure the list remains sorted */ old = list; current = *old; if ( !current ) return; - next = current->link; - - while ( next ) + while ( current->link ) { + next = current->link; + if ( current->X <= next->X ) { old = ¤t->link; - current = *old; - - if ( !current ) - return; + current = next; } else { @@ -2168,11 +1958,10 @@ current->link = next->link; next->link = current; + /* this is likely the only necessary swap -- restart */ old = list; current = *old; } - - next = current->link; } } @@ -2187,74 +1976,51 @@ */ static void - Vertical_Sweep_Init( RAS_ARGS Short min, - Short max ) + Vertical_Sweep_Init( RAS_ARGS Int min, + Int max ) { FT_UNUSED( max ); - ras.bLine = ras.bOrigin - min * ras.target.pitch; + ras.bLine = ras.bOrigin - min * ras.bPitch; } static void - Vertical_Sweep_Span( RAS_ARGS Short y, + Vertical_Sweep_Span( RAS_ARGS Int y, FT_F26Dot6 x1, - FT_F26Dot6 x2, - PProfile left, - PProfile right ) + FT_F26Dot6 x2 ) { - Long e1, e2; - - Int dropOutControl = left->flags & 7; + Int e1 = (Int)TRUNC( CEILING( x1 ) ); + Int e2 = (Int)TRUNC( FLOOR( x2 ) ); FT_UNUSED( y ); - FT_UNUSED( left ); - FT_UNUSED( right ); - /* in high-precision mode, we need 12 digits after the comma to */ - /* represent multiples of 1/(1<<12) = 1/4096 */ - FT_TRACE7(( " y=%d x=[% .12f;% .12f]", + FT_TRACE7(( " y=%d x=[% .*f;% .*f]", y, - (double)x1 / (double)ras.precision, - (double)x2 / (double)ras.precision )); - - /* Drop-out control */ - - e1 = CEILING( x1 ); - e2 = FLOOR( x2 ); - - /* take care of the special case where both the left */ - /* and right contour lie exactly on pixel centers */ - if ( dropOutControl != 2 && - x2 - x1 - ras.precision <= ras.precision_jitter && - e1 != x1 && e2 != x2 ) - e2 = e1; + ras.precision_bits, (double)x1 / (double)ras.precision, + ras.precision_bits, (double)x2 / (double)ras.precision )); - e1 = TRUNC( e1 ); - e2 = TRUNC( e2 ); - - if ( e2 >= 0 && e1 < ras.bWidth ) + if ( e2 >= 0 && e1 <= ras.bRight ) { - Byte* target; + PByte target; - Int c1, c2; - Byte f1, f2; + Int c1, f1, c2, f2; if ( e1 < 0 ) e1 = 0; - if ( e2 >= ras.bWidth ) - e2 = ras.bWidth - 1; + if ( e2 > ras.bRight ) + e2 = ras.bRight; - FT_TRACE7(( " -> x=[%ld;%ld]", e1, e2 )); + FT_TRACE7(( " -> x=[%d;%d]", e1, e2 )); - c1 = (Short)( e1 >> 3 ); - c2 = (Short)( e2 >> 3 ); + c1 = e1 >> 3; + c2 = e2 >> 3; - f1 = (Byte) ( 0xFF >> ( e1 & 7 ) ); - f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) ); + f1 = 0xFF >> ( e1 & 7 ); + f2 = ~0x7F >> ( e2 & 7 ); target = ras.bLine + c1; c2 -= c1; @@ -2280,163 +2046,50 @@ static void - Vertical_Sweep_Drop( RAS_ARGS Short y, + Vertical_Sweep_Drop( RAS_ARGS Int y, FT_F26Dot6 x1, - FT_F26Dot6 x2, - PProfile left, - PProfile right ) + FT_F26Dot6 x2 ) { - Long e1, e2, pxl; - Short c1, f1; - - - FT_TRACE7(( " y=%d x=[% .12f;% .12f]", - y, - (double)x1 / (double)ras.precision, - (double)x2 / (double)ras.precision )); - - /* Drop-out control */ - - /* e2 x2 x1 e1 */ - /* */ - /* ^ | */ - /* | | */ - /* +-------------+---------------------+------------+ */ - /* | | */ - /* | v */ - /* */ - /* pixel contour contour pixel */ - /* center center */ - - /* drop-out mode scan conversion rules (as defined in OpenType) */ - /* --------------------------------------------------------------- */ - /* 0 1, 2, 3 */ - /* 1 1, 2, 4 */ - /* 2 1, 2 */ - /* 3 same as mode 2 */ - /* 4 1, 2, 5 */ - /* 5 1, 2, 6 */ - /* 6, 7 same as mode 2 */ - - e1 = CEILING( x1 ); - e2 = FLOOR ( x2 ); - pxl = e1; - - if ( e1 > e2 ) - { - Int dropOutControl = left->flags & 7; - - - if ( e1 == e2 + ras.precision ) - { - switch ( dropOutControl ) - { - case 0: /* simple drop-outs including stubs */ - pxl = e2; - break; - - case 4: /* smart drop-outs including stubs */ - pxl = SMART( x1, x2 ); - break; - - case 1: /* simple drop-outs excluding stubs */ - case 5: /* smart drop-outs excluding stubs */ - - /* Drop-out Control Rules #4 and #6 */ - - /* The specification neither provides an exact definition */ - /* of a `stub' nor gives exact rules to exclude them. */ - /* */ - /* Here the constraints we use to recognize a stub. */ - /* */ - /* upper stub: */ - /* */ - /* - P_Left and P_Right are in the same contour */ - /* - P_Right is the successor of P_Left in that contour */ - /* - y is the top of P_Left and P_Right */ - /* */ - /* lower stub: */ - /* */ - /* - P_Left and P_Right are in the same contour */ - /* - P_Left is the successor of P_Right in that contour */ - /* - y is the bottom of P_Left */ - /* */ - /* We draw a stub if the following constraints are met. */ - /* */ - /* - for an upper or lower stub, there is top or bottom */ - /* overshoot, respectively */ - /* - the covered interval is greater or equal to a half */ - /* pixel */ - - /* upper stub test */ - if ( left->next == right && - left->height <= 0 && - !( left->flags & Overshoot_Top && - x2 - x1 >= ras.precision_half ) ) - goto Exit; - - /* lower stub test */ - if ( right->next == left && - left->start == y && - !( left->flags & Overshoot_Bottom && - x2 - x1 >= ras.precision_half ) ) - goto Exit; - - if ( dropOutControl == 1 ) - pxl = e2; - else - pxl = SMART( x1, x2 ); - break; - - default: /* modes 2, 3, 6, 7 */ - goto Exit; /* no drop-out control */ - } + Int e1 = (Int)TRUNC( x1 ); + Int e2 = (Int)TRUNC( x2 ); + Int c1, f1; - /* undocumented but confirmed: If the drop-out would result in a */ - /* pixel outside of the bounding box, use the pixel inside of the */ - /* bounding box instead */ - if ( pxl < 0 ) - pxl = e1; - else if ( TRUNC( pxl ) >= ras.bWidth ) - pxl = e2; + FT_UNUSED( y ); - /* check that the other pixel isn't set */ - e1 = ( pxl == e1 ) ? e2 : e1; - e1 = TRUNC( e1 ); + /* undocumented but confirmed: If the drop-out would result in a */ + /* pixel outside of the bounding box, use the pixel inside of the */ + /* bounding box instead */ + if ( e1 < 0 || e1 > ras.bRight ) + e1 = e2; - c1 = (Short)( e1 >> 3 ); - f1 = (Short)( e1 & 7 ); + /* otherwise check that the other pixel isn't set */ + else if ( e2 >=0 && e2 <= ras.bRight ) + { + c1 = e2 >> 3; + f1 = 0x80 >> ( e2 & 7 ); - if ( e1 >= 0 && e1 < ras.bWidth && - ras.bLine[c1] & ( 0x80 >> f1 ) ) - goto Exit; - } - else - goto Exit; + if ( ras.bLine[c1] & f1 ) + return; } - e1 = TRUNC( pxl ); - - if ( e1 >= 0 && e1 < ras.bWidth ) + if ( e1 >= 0 && e1 <= ras.bRight ) { - FT_TRACE7(( " -> x=%ld", e1 )); + c1 = e1 >> 3; + f1 = 0x80 >> ( e1 & 7 ); - c1 = (Short)( e1 >> 3 ); - f1 = (Short)( e1 & 7 ); + FT_TRACE7(( " y=%d x=%d%s\n", y, e1, + ras.bLine[c1] & f1 ? " redundant" : "" )); - ras.bLine[c1] |= (char)( 0x80 >> f1 ); + ras.bLine[c1] |= f1; } - - Exit: - FT_TRACE7(( " dropout=%d\n", left->flags & 7 )); } static void Vertical_Sweep_Step( RAS_ARG ) { - ras.bLine -= ras.target.pitch; + ras.bLine -= ras.bPitch; } @@ -2450,8 +2103,8 @@ */ static void - Horizontal_Sweep_Init( RAS_ARGS Short min, - Short max ) + Horizontal_Sweep_Init( RAS_ARGS Int min, + Int max ) { /* nothing, really */ FT_UNUSED_RASTER; @@ -2461,22 +2114,18 @@ static void - Horizontal_Sweep_Span( RAS_ARGS Short y, + Horizontal_Sweep_Span( RAS_ARGS Int y, FT_F26Dot6 x1, - FT_F26Dot6 x2, - PProfile left, - PProfile right ) + FT_F26Dot6 x2 ) { - Long e1, e2; + Long e1 = CEILING( x1 ); + Long e2 = FLOOR( x2 ); - FT_UNUSED( left ); - FT_UNUSED( right ); - - FT_TRACE7(( " x=%d y=[% .12f;% .12f]", + FT_TRACE7(( " x=%d y=[% .*f;% .*f]", y, - (double)x1 / (double)ras.precision, - (double)x2 / (double)ras.precision )); + ras.precision_bits, (double)x1 / (double)ras.precision, + ras.precision_bits, (double)x2 / (double)ras.precision )); /* We should not need this procedure but the vertical sweep */ /* mishandles horizontal lines through pixel centers. So we */ @@ -2484,20 +2133,18 @@ /* */ /* XXX: Can we handle horizontal lines better and drop this? */ - e1 = CEILING( x1 ); - if ( x1 == e1 ) { e1 = TRUNC( e1 ); - if ( e1 >= 0 && (ULong)e1 < ras.target.rows ) + if ( e1 >= 0 && e1 <= ras.bTop ) { - Byte f1; + Int f1; PByte bits; - bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch; - f1 = (Byte)( 0x80 >> ( y & 7 ) ); + bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.bPitch; + f1 = 0x80 >> ( y & 7 ); FT_TRACE7(( bits[0] & f1 ? " redundant" : " -> y=%ld edge", e1 )); @@ -2506,20 +2153,18 @@ } } - e2 = FLOOR ( x2 ); - if ( x2 == e2 ) { e2 = TRUNC( e2 ); - if ( e2 >= 0 && (ULong)e2 < ras.target.rows ) + if ( e2 >= 0 && e2 <= ras.bTop ) { - Byte f1; + Int f1; PByte bits; - bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.target.pitch; - f1 = (Byte)( 0x80 >> ( y & 7 ) ); + bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.bPitch; + f1 = 0x80 >> ( y & 7 ); FT_TRACE7(( bits[0] & f1 ? " redundant" : " -> y=%ld edge", e2 )); @@ -2533,122 +2178,42 @@ static void - Horizontal_Sweep_Drop( RAS_ARGS Short y, + Horizontal_Sweep_Drop( RAS_ARGS Int y, FT_F26Dot6 x1, - FT_F26Dot6 x2, - PProfile left, - PProfile right ) + FT_F26Dot6 x2 ) { - Long e1, e2, pxl; + Int e1 = (Int)TRUNC( x1 ); + Int e2 = (Int)TRUNC( x2 ); PByte bits; - Byte f1; - - - FT_TRACE7(( " x=%d y=[% .12f;% .12f]", - y, - (double)x1 / (double)ras.precision, - (double)x2 / (double)ras.precision )); - - /* During the horizontal sweep, we only take care of drop-outs */ - - /* e1 + <-- pixel center */ - /* | */ - /* x1 ---+--> <-- contour */ - /* | */ - /* | */ - /* x2 <--+--- <-- contour */ - /* | */ - /* | */ - /* e2 + <-- pixel center */ - - e1 = CEILING( x1 ); - e2 = FLOOR ( x2 ); - pxl = e1; - - if ( e1 > e2 ) - { - Int dropOutControl = left->flags & 7; - + Int f1; - if ( e1 == e2 + ras.precision ) - { - switch ( dropOutControl ) - { - case 0: /* simple drop-outs including stubs */ - pxl = e2; - break; - - case 4: /* smart drop-outs including stubs */ - pxl = SMART( x1, x2 ); - break; - - case 1: /* simple drop-outs excluding stubs */ - case 5: /* smart drop-outs excluding stubs */ - /* see Vertical_Sweep_Drop for details */ - - /* rightmost stub test */ - if ( left->next == right && - left->height <= 0 && - !( left->flags & Overshoot_Top && - x2 - x1 >= ras.precision_half ) ) - goto Exit; - - /* leftmost stub test */ - if ( right->next == left && - left->start == y && - !( left->flags & Overshoot_Bottom && - x2 - x1 >= ras.precision_half ) ) - goto Exit; - - if ( dropOutControl == 1 ) - pxl = e2; - else - pxl = SMART( x1, x2 ); - break; - default: /* modes 2, 3, 6, 7 */ - goto Exit; /* no drop-out control */ - } - - /* undocumented but confirmed: If the drop-out would result in a */ - /* pixel outside of the bounding box, use the pixel inside of the */ - /* bounding box instead */ - if ( pxl < 0 ) - pxl = e1; - else if ( (ULong)( TRUNC( pxl ) ) >= ras.target.rows ) - pxl = e2; - - /* check that the other pixel isn't set */ - e1 = ( pxl == e1 ) ? e2 : e1; - - e1 = TRUNC( e1 ); + /* undocumented but confirmed: If the drop-out would result in a */ + /* pixel outside of the bounding box, use the pixel inside of the */ + /* bounding box instead */ + if ( e1 < 0 || e1 > ras.bTop ) + e1 = e2; - bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch; - f1 = (Byte)( 0x80 >> ( y & 7 ) ); + /* otherwise check that the other pixel isn't set */ + else if ( e2 >=0 && e2 <= ras.bTop ) + { + bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.bPitch; + f1 = 0x80 >> ( y & 7 ); - if ( e1 >= 0 && - (ULong)e1 < ras.target.rows && - *bits & f1 ) - goto Exit; - } - else - goto Exit; + if ( *bits & f1 ) + return; } - e1 = TRUNC( pxl ); - - if ( e1 >= 0 && (ULong)e1 < ras.target.rows ) + if ( e1 >= 0 && e1 <= ras.bTop ) { - FT_TRACE7(( " -> y=%ld", e1 )); + bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.bPitch; + f1 = 0x80 >> ( y & 7 ); - bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch; - f1 = (Byte)( 0x80 >> ( y & 7 ) ); + FT_TRACE7(( " x=%d y=%d%s\n", y, e1, + *bits & f1 ? " redundant" : "" )); - bits[0] |= f1; + *bits |= f1; } - - Exit: - FT_TRACE7(( " dropout=%d\n", left->flags & 7 )); } @@ -2664,116 +2229,61 @@ * * Generic Sweep Drawing routine * + * Note that this routine is executed with the pool containing at least + * two valid profiles (up and down) and two y-turns (top and bottom). + * */ - static Bool + static void Draw_Sweep( RAS_ARG ) { - Short y, y_change, y_height; - - PProfile P, Q, P_Left, P_Right; - - Short min_Y, max_Y, top, bottom, dropouts; - - Long x1, x2, xs, e1, e2; - - TProfileList waiting; - TProfileList draw_left, draw_right; - - - /* initialize empty linked lists */ - - Init_Linked( &waiting ); - - Init_Linked( &draw_left ); - Init_Linked( &draw_right ); - - /* first, compute min and max Y */ - - P = ras.fProfile; - max_Y = (Short)TRUNC( ras.minY ); - min_Y = (Short)TRUNC( ras.maxY ); - - while ( P ) - { - Q = P->link; + Int min_Y, max_Y, dropouts; + Int y, y_turn; - bottom = (Short)P->start; - top = (Short)( P->start + P->height - 1 ); + PProfile *Q, P, P_Left, P_Right; - if ( min_Y > bottom ) - min_Y = bottom; - if ( max_Y < top ) - max_Y = top; + TProfileList waiting = ras.fProfile; + TProfileList draw_left = NULL; + TProfileList draw_right = NULL; - P->X = 0; - InsNew( &waiting, P ); - P = Q; - } + /* use y_turns to set the drawing range */ - /* check the Y-turns */ - if ( ras.numTurns == 0 ) - { - ras.error = FT_THROW( Invalid_Outline ); - return FAILURE; - } + min_Y = (Int)ras.maxBuff[0]; + max_Y = (Int)ras.maxBuff[ras.numTurns] - 1; /* now initialize the sweep */ ras.Proc_Sweep_Init( RAS_VARS min_Y, max_Y ); - /* then compute the distance of each profile from min_Y */ - - P = waiting; - - while ( P ) - { - P->countL = P->start - min_Y; - P = P->link; - } - /* let's go */ - y = min_Y; - y_height = 0; - - if ( ras.numTurns > 0 && - ras.sizeBuff[-ras.numTurns] == min_Y ) - ras.numTurns--; - - while ( ras.numTurns > 0 ) + for ( y = min_Y; y <= max_Y; ) { - /* check waiting list for new activations */ - - P = waiting; + /* check waiting list for new profile activations */ - while ( P ) + Q = &waiting; + while ( *Q ) { - Q = P->link; - P->countL -= y_height; - if ( P->countL == 0 ) + P = *Q; + if ( P->start == y ) { - DelOld( &waiting, P ); + *Q = P->link; /* remove */ + /* each active list contains profiles with the same flow */ + /* left and right are arbitrary, correspond to TrueType */ if ( P->flags & Flow_Up ) InsNew( &draw_left, P ); else InsNew( &draw_right, P ); } - - P = Q; + else + Q = &P->link; } - /* sort the drawing lists */ + y_turn = (Int)*++ras.maxBuff; - Sort( &draw_left ); - Sort( &draw_right ); - - y_change = (Short)ras.sizeBuff[-ras.numTurns--]; - y_height = (Short)( y_change - y ); - - while ( y < y_change ) + do { /* let's trace */ @@ -2784,9 +2294,13 @@ while ( P_Left && P_Right ) { - x1 = P_Left ->X; - x2 = P_Right->X; + Long x1 = P_Left ->X; + Long x2 = P_Right->X; + Long xs; + + /* TrueType should have x2 > x1, but can be opposite */ + /* by mistake or in CFF/Type1, fix it then */ if ( x1 > x2 ) { xs = x1; @@ -2794,205 +2308,130 @@ x2 = xs; } - e1 = FLOOR( x1 ); - e2 = CEILING( x2 ); + if ( CEILING( x1 ) <= FLOOR( x2 ) ) + ras.Proc_Sweep_Span( RAS_VARS y, x1, x2 ); - if ( x2 - x1 <= ras.precision && - e1 != x1 && e2 != x2 ) + /* otherwise, bottom ceiling > top floor, it is a drop-out */ + else { - if ( e1 > e2 || e2 == e1 + ras.precision ) + Int dropOutControl = P_Left->flags & 7; + + + /* Drop-out control */ + + /* e2 x2 x1 e1 */ + /* */ + /* ^ | */ + /* | | */ + /* +-------------+---------------------+------------+ */ + /* | | */ + /* | v */ + /* */ + /* pixel contour contour pixel */ + /* center center */ + + /* drop-out mode scan conversion rules (OpenType specs) */ + /* ------------------------------------------------------- */ + /* bit 0 exclude stubs if set */ + /* bit 1 ignore drop-outs if set */ + /* bit 2 smart rounding if set */ + + if ( dropOutControl & 2 ) + goto Next_Pair; + + /* The specification neither provides an exact definition */ + /* of a `stub' nor gives exact rules to exclude them. */ + /* */ + /* Here the constraints we use to recognize a stub. */ + /* */ + /* upper stub: */ + /* */ + /* - P_Left and P_Right are in the same contour */ + /* - P_Right is the successor of P_Left in that contour */ + /* - y is the top of P_Left and P_Right */ + /* */ + /* lower stub: */ + /* */ + /* - P_Left and P_Right are in the same contour */ + /* - P_Left is the successor of P_Right in that contour */ + /* - y is the bottom of P_Left */ + /* */ + /* We draw a stub if the following constraints are met. */ + /* */ + /* - for an upper or lower stub, there is top or bottom */ + /* overshoot, respectively */ + /* - the covered interval is greater or equal to a half */ + /* pixel */ + + if ( dropOutControl & 1 ) { - Int dropOutControl = P_Left->flags & 7; - - - if ( dropOutControl != 2 ) - { - /* a drop-out was detected */ - - P_Left ->X = x1; - P_Right->X = x2; - - /* mark profile for drop-out processing */ - P_Left->countL = 1; - dropouts++; - } + /* upper stub test */ + if ( P_Left->height == 1 && + P_Left->next == P_Right && + !( P_Left->flags & Overshoot_Top && + x2 - x1 >= ras.precision_half ) ) + goto Next_Pair; + + /* lower stub test */ + if ( P_Left->offset == 0 && + P_Right->next == P_Left && + !( P_Left->flags & Overshoot_Bottom && + x2 - x1 >= ras.precision_half ) ) + goto Next_Pair; + } - goto Skip_To_Next; + /* select the pixel to set and the other pixel */ + if ( dropOutControl & 4 ) + { + x2 = SMART( x1, x2 ); + x1 = x1 > x2 ? x2 + ras.precision : x2 - ras.precision; + } + else + { + x2 = FLOOR ( x2 ); + x1 = CEILING( x1 ); } - } - ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right ); + P_Left ->X = x2; + P_Right->X = x1; - Skip_To_Next: + /* mark profile for drop-out processing */ + P_Left->flags |= Dropout; + dropouts++; + } + Next_Pair: P_Left = P_Left->link; P_Right = P_Right->link; } - /* handle drop-outs _after_ the span drawing -- */ - /* drop-out processing has been moved out of the loop */ - /* for performance tuning */ - if ( dropouts > 0 ) - goto Scan_DropOuts; - - Next_Line: - - ras.Proc_Sweep_Step( RAS_VAR ); - - y++; + /* handle drop-outs _after_ the span drawing */ + P_Left = draw_left; + P_Right = draw_right; - if ( y < y_change ) + while ( dropouts ) { - Sort( &draw_left ); - Sort( &draw_right ); - } - } - - /* now finalize the profiles that need it */ - - P = draw_left; - while ( P ) - { - Q = P->link; - if ( P->height == 0 ) - DelOld( &draw_left, P ); - P = Q; - } - - P = draw_right; - while ( P ) - { - Q = P->link; - if ( P->height == 0 ) - DelOld( &draw_right, P ); - P = Q; - } - } - - /* for gray-scaling, flush the bitmap scanline cache */ - while ( y <= max_Y ) - { - ras.Proc_Sweep_Step( RAS_VAR ); - y++; - } - - return SUCCESS; - - Scan_DropOuts: - - P_Left = draw_left; - P_Right = draw_right; - - while ( P_Left && P_Right ) - { - if ( P_Left->countL ) - { - P_Left->countL = 0; -#if 0 - dropouts--; /* -- this is useful when debugging only */ -#endif - ras.Proc_Sweep_Drop( RAS_VARS y, - P_Left->X, - P_Right->X, - P_Left, - P_Right ); - } - - P_Left = P_Left->link; - P_Right = P_Right->link; - } - - goto Next_Line; - } - - -#ifdef STANDALONE_ - - /************************************************************************** - * - * The following functions should only compile in stand-alone mode, - * i.e., when building this component without the rest of FreeType. - * - */ - - /************************************************************************** - * - * @Function: - * FT_Outline_Get_CBox - * - * @Description: - * Return an outline's `control box'. The control box encloses all - * the outline's points, including Bézier control points. Though it - * coincides with the exact bounding box for most glyphs, it can be - * slightly larger in some situations (like when rotating an outline - * that contains Bézier outside arcs). - * - * Computing the control box is very fast, while getting the bounding - * box can take much more time as it needs to walk over all segments - * and arcs in the outline. To get the latter, you can use the - * `ftbbox' component, which is dedicated to this single task. - * - * @Input: - * outline :: - * A pointer to the source outline descriptor. - * - * @Output: - * acbox :: - * The outline's control box. - * - * @Note: - * See @FT_Glyph_Get_CBox for a discussion of tricky fonts. - */ - - static void - FT_Outline_Get_CBox( const FT_Outline* outline, - FT_BBox *acbox ) - { - if ( outline && acbox ) - { - Long xMin, yMin, xMax, yMax; - - - if ( outline->n_points == 0 ) - { - xMin = 0; - yMin = 0; - xMax = 0; - yMax = 0; - } - else - { - FT_Vector* vec = outline->points; - FT_Vector* limit = vec + outline->n_points; - - - xMin = xMax = vec->x; - yMin = yMax = vec->y; - vec++; + if ( P_Left->flags & Dropout ) + { + ras.Proc_Sweep_Drop( RAS_VARS y, P_Left->X, P_Right->X ); - for ( ; vec < limit; vec++ ) - { - Long x, y; + P_Left->flags &= ~Dropout; + dropouts--; + } + P_Left = P_Left->link; + P_Right = P_Right->link; + } - x = vec->x; - if ( x < xMin ) xMin = x; - if ( x > xMax ) xMax = x; + ras.Proc_Sweep_Step( RAS_VAR ); - y = vec->y; - if ( y < yMin ) yMin = y; - if ( y > yMax ) yMax = y; - } + Increment( &draw_left, 1 ); + Increment( &draw_right, -1 ); } - acbox->xMin = xMin; - acbox->xMax = xMax; - acbox->yMin = yMin; - acbox->yMax = yMax; + while ( ++y < y_turn ); } } -#endif /* STANDALONE_ */ - /************************************************************************** * @@ -3019,13 +2458,15 @@ Int band_stack[32]; /* enough to bisect 32-bit int bands */ + FT_TRACE6(( "%s pass [%d..%d]\n", + flipped ? "Horizontal" : "Vertical", + y_min, y_max )); + while ( 1 ) { ras.minY = (Long)y_min * ras.precision; ras.maxY = (Long)y_max * ras.precision; - ras.top = ras.buff; - ras.error = Raster_Err_Ok; if ( Convert_Glyph( RAS_VARS flipped ) ) @@ -3038,6 +2479,9 @@ if ( y_min == y_max ) return ras.error; /* still Raster_Overflow */ + FT_TRACE6(( "band [%d..%d]: to be bisected\n", + y_min, y_max )); + y_mid = ( y_min + y_max ) >> 1; band_stack[band_top++] = y_min; @@ -3045,9 +2489,12 @@ } else { + FT_TRACE6(( "band [%d..%d]: %hd profiles; %td bytes remaining\n", + y_min, y_max, ras.num_Profs, + (char*)ras.maxBuff - (char*)ras.top )); + if ( ras.fProfile ) - if ( Draw_Sweep( RAS_VAR ) ) - return ras.error; + Draw_Sweep( RAS_VAR ); if ( --band_top < 0 ) break; @@ -3076,53 +2523,48 @@ Render_Glyph( RAS_ARG ) { FT_Error error; + Long buffer[FT_MAX_BLACK_POOL]; + ras.buff = buffer; + ras.sizeBuff = (&buffer)[1]; /* Points to right after buffer. */ + Set_High_Precision( RAS_VARS ras.outline.flags & FT_OUTLINE_HIGH_PRECISION ); + ras.dropOutControl = 0; + if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS ) - ras.dropOutControl = 2; - else - { - if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS ) - ras.dropOutControl = 4; - else - ras.dropOutControl = 0; + ras.dropOutControl |= 2; - if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) ) - ras.dropOutControl += 1; - } + if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS ) + ras.dropOutControl |= 4; - /* Vertical Sweep */ - FT_TRACE7(( "Vertical pass (ftraster)\n" )); + if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) ) + ras.dropOutControl |= 1; + + FT_TRACE6(( "BW Raster: precision 1/%d, dropout mode %d\n", + ras.precision, ras.dropOutControl )); + /* Vertical Sweep */ ras.Proc_Sweep_Init = Vertical_Sweep_Init; ras.Proc_Sweep_Span = Vertical_Sweep_Span; ras.Proc_Sweep_Drop = Vertical_Sweep_Drop; ras.Proc_Sweep_Step = Vertical_Sweep_Step; - ras.bWidth = (UShort)ras.target.width; - ras.bOrigin = (Byte*)ras.target.buffer; - - if ( ras.target.pitch > 0 ) - ras.bOrigin += (Long)( ras.target.rows - 1 ) * ras.target.pitch; - - error = Render_Single_Pass( RAS_VARS 0, 0, (Int)ras.target.rows - 1 ); + error = Render_Single_Pass( RAS_VARS 0, 0, ras.bTop ); if ( error ) return error; /* Horizontal Sweep */ if ( !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS ) ) { - FT_TRACE7(( "Horizontal pass (ftraster)\n" )); - ras.Proc_Sweep_Init = Horizontal_Sweep_Init; ras.Proc_Sweep_Span = Horizontal_Sweep_Span; ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop; ras.Proc_Sweep_Step = Horizontal_Sweep_Step; - error = Render_Single_Pass( RAS_VARS 1, 0, (Int)ras.target.width - 1 ); + error = Render_Single_Pass( RAS_VARS 1, 0, ras.bRight ); if ( error ) return error; } @@ -3233,8 +2675,6 @@ black_TWorker worker[1]; #endif - Long buffer[FT_MAX_BLACK_POOL]; - if ( !raster ) return FT_THROW( Raster_Uninitialized ); @@ -3243,7 +2683,7 @@ return FT_THROW( Invalid_Outline ); /* return immediately if the outline is empty */ - if ( outline->n_points == 0 || outline->n_contours <= 0 ) + if ( outline->n_points == 0 || outline->n_contours == 0 ) return Raster_Err_Ok; if ( !outline->contours || !outline->points ) @@ -3269,10 +2709,14 @@ return FT_THROW( Invalid_Argument ); ras.outline = *outline; - ras.target = *target_map; - ras.buff = buffer; - ras.sizeBuff = (&buffer)[1]; /* Points to right after buffer. */ + ras.bTop = (Int)target_map->rows - 1; + ras.bRight = (Int)target_map->width - 1; + ras.bPitch = (Int)target_map->pitch; + ras.bOrigin = (PByte)target_map->buffer; + + if ( ras.bPitch > 0 ) + ras.bOrigin += ras.bTop * ras.bPitch; return Render_Glyph( RAS_VAR ); } diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h index b511b3a99e9..ad9cb1b9fe0 100644 --- a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c index 6d442b1ff8c..fd9f174f2e1 100644 --- a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer interface (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h index cec35c8528a..cf3e73c0a24 100644 --- a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer interface (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h b/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h index 989d8b44be1..326d42e0438 100644 --- a/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h +++ b/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h @@ -4,7 +4,7 @@ * * monochrome renderer error codes (specification only). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c index 33712162e00..76181568af9 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c @@ -4,7 +4,7 @@ * * PNG Bitmap glyph support. * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * Google, Inc. * Written by Stuart Gill and Behdad Esfahbod. * diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h index 903bd2bc348..6e7a5c08e71 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h @@ -4,7 +4,7 @@ * * PNG Bitmap glyph support. * - * Copyright (C) 2013-2023 by + * Copyright (C) 2013-2024 by * Google, Inc. * Written by Stuart Gill and Behdad Esfahbod. * diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c index 0925940b03f..81072207b49 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c @@ -4,7 +4,7 @@ * * High-level SFNT driver interface (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -49,6 +49,10 @@ #include <freetype/internal/services/svbdf.h> #endif +#ifdef TT_CONFIG_OPTION_GPOS_KERNING +#include "ttgpos.h" +#endif + #include "ttcmap.h" #include "ttkern.h" #include "ttmtx.h" @@ -1249,6 +1253,12 @@ #define PUT_PS_NAMES( a ) a #else #define PUT_PS_NAMES( a ) NULL +#endif + +#ifdef TT_CONFIG_OPTION_GPOS_KERNING +#define PUT_GPOS_KERNING( a ) a +#else +#define PUT_GPOS_KERNING( a ) NULL #endif FT_DEFINE_SFNT_INTERFACE( @@ -1274,6 +1284,8 @@ tt_face_free_name, /* TT_Free_Table_Func free_name */ tt_face_load_kern, /* TT_Load_Table_Func load_kern */ + PUT_GPOS_KERNING( tt_face_load_gpos ), + /* TT_Load_Table_Func load_gpos */ tt_face_load_gasp, /* TT_Load_Table_Func load_gasp */ tt_face_load_pclt, /* TT_Load_Table_Func load_init */ @@ -1292,6 +1304,9 @@ /* since version 2.1.8 */ tt_face_get_kerning, /* TT_Face_GetKerningFunc get_kerning */ + PUT_GPOS_KERNING( tt_face_get_gpos_kerning ), + /* TT_Face_GetKerningFunc get_gpos_kerning */ + /* since version 2.2 */ tt_face_load_font_dir, /* TT_Load_Table_Func load_font_dir */ tt_face_load_hmtx, /* TT_Load_Metrics_Func load_hmtx */ diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h index 2445958b69f..6f71489fdc1 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h @@ -4,7 +4,7 @@ * * High-level SFNT driver interface (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h index e7a8eb04bb8..d3ca1d9aa8b 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h @@ -4,7 +4,7 @@ * * SFNT error codes (specification only). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c index f5d66ef8403..6ee4e5e939b 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c @@ -4,7 +4,7 @@ * * SFNT object management (base). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -40,6 +40,10 @@ #include "ttbdf.h" #endif +#ifdef TT_CONFIG_OPTION_GPOS_KERNING +#include "ttgpos.h" +#endif + /************************************************************************** * @@ -1026,6 +1030,10 @@ LOAD_( gasp ); LOAD_( kern ); +#ifdef TT_CONFIG_OPTION_GPOS_KERNING + LOAD_( gpos ); +#endif + face->root.num_glyphs = face->max_profile.numGlyphs; /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */ @@ -1119,7 +1127,11 @@ flags |= FT_FACE_FLAG_VERTICAL; /* kerning available ? */ - if ( TT_FACE_HAS_KERNING( face ) ) + if ( TT_FACE_HAS_KERNING( face ) +#ifdef TT_CONFIG_OPTION_GPOS_KERNING + || face->gpos_kerning_available +#endif + ) flags |= FT_FACE_FLAG_KERNING; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT @@ -1470,6 +1482,11 @@ /* freeing the kerning table */ tt_face_done_kern( face ); +#ifdef TT_CONFIG_OPTION_GPOS_KERNING + /* freeing the GPOS table */ + tt_face_done_gpos( face ); +#endif + /* freeing the collection table */ FT_FREE( face->ttc_header.offsets ); face->ttc_header.count = 0; diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h index 906aebbf904..90847d95732 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h @@ -4,7 +4,7 @@ * * SFNT object management (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c index 7c0ce2205e6..14514bf9574 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c @@ -4,7 +4,7 @@ * * WOFF format management (base). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -18,6 +18,7 @@ #include "sfwoff.h" #include <freetype/tttags.h> +#include <freetype/internal/ftcalc.h> #include <freetype/internal/ftdebug.h> #include <freetype/internal/ftstream.h> #include <freetype/ftgzip.h> @@ -149,6 +150,7 @@ /* Miscellaneous checks. */ if ( woff.length != stream->size || woff.num_tables == 0 || + woff.num_tables > 0xFFFU || 44 + woff.num_tables * 20UL >= woff.length || 12 + woff.num_tables * 16UL >= woff.totalSfntSize || ( woff.totalSfntSize & 3 ) != 0 || @@ -169,21 +171,11 @@ /* Write sfnt header. */ { - FT_UInt searchRange, entrySelector, rangeShift, x; + FT_Int entrySelector = FT_MSB( woff.num_tables ); + FT_Int searchRange = ( 1 << entrySelector ) * 16; + FT_Int rangeShift = woff.num_tables * 16 - searchRange; - x = woff.num_tables; - entrySelector = 0; - while ( x ) - { - x >>= 1; - entrySelector += 1; - } - entrySelector--; - - searchRange = ( 1 << entrySelector ) * 16; - rangeShift = woff.num_tables * 16 - searchRange; - WRITE_ULONG ( sfnt_header, woff.flavor ); WRITE_USHORT( sfnt_header, woff.num_tables ); WRITE_USHORT( sfnt_header, searchRange ); diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h index d4384227376..a04735ffe28 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h @@ -4,7 +4,7 @@ * * WOFFF format management (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c index 2be44a347ad..589b3e0c6b7 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c @@ -4,7 +4,7 @@ * * WOFF2 format management (base). * - * Copyright (C) 2019-2023 by + * Copyright (C) 2019-2024 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -18,6 +18,7 @@ #include "sfwoff2.h" #include "woff2tags.h" #include <freetype/tttags.h> +#include <freetype/internal/ftcalc.h> #include <freetype/internal/ftdebug.h> #include <freetype/internal/ftstream.h> @@ -289,23 +290,15 @@ FT_ULong checksum = 0; FT_ULong aligned_size = size & ~3UL; FT_ULong i; - FT_ULong v; + FT_Int shift; for ( i = 0; i < aligned_size; i += 4 ) - checksum += ( (FT_ULong)buf[i ] << 24 ) | - ( (FT_ULong)buf[i + 1] << 16 ) | - ( (FT_ULong)buf[i + 2] << 8 ) | - ( (FT_ULong)buf[i + 3] << 0 ); + checksum += FT_NEXT_ULONG( buf ); - /* If size is not aligned to 4, treat as if it is padded with 0s. */ - if ( size != aligned_size ) - { - v = 0; - for ( i = aligned_size ; i < size; ++i ) - v |= (FT_ULong)buf[i] << ( 24 - 8 * ( i & 3 ) ); - checksum += v; - } + /* remaining bytes can be shifted and added one at a time */ + for ( shift = 24; i < size; i++, shift -= 8 ) + checksum += (FT_UInt32)FT_NEXT_BYTE( buf ) << shift; return checksum; } @@ -1799,7 +1792,6 @@ FT_Byte* sfnt = NULL; FT_Stream sfnt_stream = NULL; - FT_Byte* sfnt_header; FT_ULong sfnt_size; FT_Byte* uncompressed_buf = NULL; @@ -1853,6 +1845,7 @@ /* Miscellaneous checks. */ if ( woff2.length != stream->size || woff2.num_tables == 0 || + woff2.num_tables > 0xFFFU || 48 + woff2.num_tables * 20UL >= woff2.length || ( woff2.metaOffset == 0 && ( woff2.metaLength != 0 || woff2.metaOrigLength != 0 ) ) || @@ -2143,6 +2136,13 @@ WOFF2_TtcFont ttc_font = woff2.ttc_fonts + face_index; + if ( ttc_font->num_tables == 0 || ttc_font->num_tables > 0xFFFU ) + { + FT_ERROR(( "woff2_open_font: invalid WOFF2 CollectionFontEntry\n" )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + /* Create a temporary array. */ if ( FT_QNEW_ARRAY( temp_indices, ttc_font->num_tables ) ) @@ -2198,27 +2198,15 @@ FT_NEW( sfnt_stream ) ) goto Exit; - sfnt_header = sfnt; - - WRITE_ULONG( sfnt_header, woff2.flavor ); - - if ( woff2.num_tables ) { - FT_UInt searchRange, entrySelector, rangeShift, x; + FT_Byte* sfnt_header = sfnt; + FT_Int entrySelector = FT_MSB( woff2.num_tables ); + FT_Int searchRange = ( 1 << entrySelector ) * 16; + FT_Int rangeShift = woff2.num_tables * 16 - searchRange; - x = woff2.num_tables; - entrySelector = 0; - while ( x ) - { - x >>= 1; - entrySelector += 1; - } - entrySelector--; - - searchRange = ( 1 << entrySelector ) * 16; - rangeShift = ( woff2.num_tables * 16 ) - searchRange; + WRITE_ULONG ( sfnt_header, woff2.flavor ); WRITE_USHORT( sfnt_header, woff2.num_tables ); WRITE_USHORT( sfnt_header, searchRange ); WRITE_USHORT( sfnt_header, entrySelector ); diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h index 4901286ee08..f41140648dc 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h @@ -4,7 +4,7 @@ * * WOFFF2 format management (specification). * - * Copyright (C) 2019-2023 by + * Copyright (C) 2019-2024 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c index 9ba25dcbc13..28f4d1173c0 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c @@ -4,7 +4,7 @@ * * TrueType character mapping table (cmap) support (body). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h index ff52917ed5b..e2c5e72bf02 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h @@ -4,7 +4,7 @@ * * TrueType character mapping table (cmap) support (specification). * - * Copyright (C) 2002-2023 by + * Copyright (C) 2002-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h index 0af48c2478a..370898363f3 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h @@ -4,7 +4,7 @@ * * TT CMAP classes definitions (specification only). * - * Copyright (C) 2009-2023 by + * Copyright (C) 2009-2024 by * Oran Agra and Mickey Gabel. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c index 281e7135eea..b37658dde9e 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c @@ -4,7 +4,7 @@ * * TrueType and OpenType colored glyph layer support (body). * - * Copyright (C) 2018-2023 by + * Copyright (C) 2018-2024 by * David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. * * Originally written by Shao Yu Zhang <shaozhang@fb.com>. @@ -208,18 +208,19 @@ colr->num_base_glyphs = FT_NEXT_USHORT( p ); base_glyph_offset = FT_NEXT_ULONG( p ); - if ( base_glyph_offset >= table_size ) + if ( table_size <= base_glyph_offset ) goto InvalidTable; - if ( colr->num_base_glyphs * BASE_GLYPH_SIZE > - table_size - base_glyph_offset ) + if ( ( table_size - base_glyph_offset ) / BASE_GLYPH_SIZE + < colr->num_base_glyphs ) goto InvalidTable; layer_offset = FT_NEXT_ULONG( p ); colr->num_layers = FT_NEXT_USHORT( p ); - if ( layer_offset >= table_size ) + if ( table_size <= layer_offset ) goto InvalidTable; - if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset ) + if ( ( table_size - layer_offset ) / LAYER_SIZE + < colr->num_layers ) goto InvalidTable; if ( colr->version == 1 ) @@ -229,14 +230,14 @@ base_glyphs_offset_v1 = FT_NEXT_ULONG( p ); - if ( base_glyphs_offset_v1 >= table_size - 4 ) + if ( table_size - 4 <= base_glyphs_offset_v1 ) goto InvalidTable; p1 = (FT_Byte*)( table + base_glyphs_offset_v1 ); num_base_glyphs_v1 = FT_PEEK_ULONG( p1 ); - if ( num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE > - table_size - base_glyphs_offset_v1 ) + if ( ( table_size - base_glyphs_offset_v1 ) / BASE_GLYPH_PAINT_RECORD_SIZE + < num_base_glyphs_v1 ) goto InvalidTable; colr->num_base_glyphs_v1 = num_base_glyphs_v1; @@ -244,19 +245,19 @@ layer_offset_v1 = FT_NEXT_ULONG( p ); - if ( layer_offset_v1 >= table_size ) + if ( table_size <= layer_offset_v1 ) goto InvalidTable; if ( layer_offset_v1 ) { - if ( layer_offset_v1 >= table_size - 4 ) + if ( table_size - 4 <= layer_offset_v1 ) goto InvalidTable; p1 = (FT_Byte*)( table + layer_offset_v1 ); num_layers_v1 = FT_PEEK_ULONG( p1 ); - if ( num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE > - table_size - layer_offset_v1 ) + if ( ( table_size - layer_offset_v1 ) / LAYER_V1_LIST_PAINT_OFFSET_SIZE + < num_layers_v1 ) goto InvalidTable; colr->num_layers_v1 = num_layers_v1; @@ -279,7 +280,7 @@ clip_list_offset = FT_NEXT_ULONG( p ); - if ( clip_list_offset >= table_size ) + if ( table_size <= clip_list_offset ) goto InvalidTable; if ( clip_list_offset ) @@ -311,7 +312,7 @@ goto InvalidTable; var_store_offset = FT_NEXT_ULONG( p ); - if ( var_store_offset >= table_size ) + if ( table_size <= var_store_offset ) goto InvalidTable; if ( var_store_offset ) @@ -661,6 +662,7 @@ FT_UInt32 first_layer_index; + ENSURE_READ_BYTES( 5 ); num_layers = FT_NEXT_BYTE( p ); if ( num_layers > colr->num_layers_v1 ) return 0; @@ -1278,7 +1280,8 @@ while ( min < max ) { - FT_UInt mid = min + ( max - min ) / 2; + FT_UInt mid = min + ( max - min ) / 2; + FT_UShort gid; /* * `base_glyph_begin` is the beginning of `BaseGlyphV1List`; @@ -1287,8 +1290,7 @@ */ FT_Byte *p = base_glyph_begin + 4 + mid * BASE_GLYPH_PAINT_RECORD_SIZE; - FT_UShort gid = FT_NEXT_USHORT( p ); - + gid = FT_NEXT_USHORT( p ); if ( gid < glyph_id ) min = mid + 1; diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h index 20c85f0359f..30031464c73 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h @@ -4,7 +4,7 @@ * * TrueType and OpenType colored glyph layer support (specification). * - * Copyright (C) 2018-2023 by + * Copyright (C) 2018-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang <shaozhang@fb.com>. diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c index 46ae08596f3..997eb869ffc 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c @@ -4,7 +4,7 @@ * * TrueType and OpenType color palette support (body). * - * Copyright (C) 2018-2023 by + * Copyright (C) 2018-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang <shaozhang@fb.com>. diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h index 8e9913f0ccd..bb301ae88b6 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h @@ -4,7 +4,7 @@ * * TrueType and OpenType color palette support (specification). * - * Copyright (C) 2018-2023 by + * Copyright (C) 2018-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang <shaozhang@fb.com>. diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c index a47d08bd6de..f0411366af4 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c @@ -5,7 +5,7 @@ * Load the basic TrueType kerning table. This doesn't handle * kerning data within the GPOS table at the moment. * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h index 960c7da4946..a54e51df12d 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h @@ -5,7 +5,7 @@ * Load the basic TrueType kerning table. This doesn't handle * kerning data within the GPOS table at the moment. * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c index 7b44e9cd2e7..c3a5fae2cb9 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c @@ -5,7 +5,7 @@ * Load the basic TrueType tables, i.e., tables that can be either in * TTF or OTF fonts (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -1046,7 +1046,7 @@ FT_LOCAL_DEF( void ) tt_face_free_name( TT_Face face ) { - FT_Memory memory = face->root.driver->root.memory; + FT_Memory memory = face->root.memory; TT_NameTable table = &face->name_table; diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h index 1499dd5735f..2b1d62d9bd9 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h @@ -5,7 +5,7 @@ * Load the basic TrueType tables, i.e., tables that can be either in * TTF or OTF fonts (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c index 38ee9ae728a..27884118563 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c @@ -4,7 +4,7 @@ * * Load the metrics tables common to TTF and OTF fonts (body). * - * Copyright (C) 2006-2023 by + * Copyright (C) 2006-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h index 56d2b627661..34b3c0e18f2 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h @@ -4,7 +4,7 @@ * * Load the metrics tables common to TTF and OTF fonts (specification). * - * Copyright (C) 2006-2023 by + * Copyright (C) 2006-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c index 1dfad4298bd..5698a62c8d1 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c @@ -5,7 +5,7 @@ * PostScript name table processing for TrueType and OpenType fonts * (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -204,8 +204,8 @@ /* now load the name strings */ if ( num_names ) { - FT_ULong p; - FT_Byte* strings; + FT_Byte* p; + FT_Byte* p_end; post_len -= (FT_ULong)num_glyphs * 2; @@ -214,36 +214,36 @@ post_len + 1 ) ) goto Fail; - strings = (FT_Byte*)( name_strings + num_names ); - if ( FT_STREAM_READ( strings, post_len ) ) + p = (FT_Byte*)( name_strings + num_names ); + if ( FT_STREAM_READ( p, post_len ) ) goto Fail; + p_end = p + post_len; + /* convert from Pascal- to C-strings and set pointers */ - for ( p = 0, n = 0; p < post_len && n < num_names; n++ ) + for ( n = 0; p < p_end && n < num_names; n++ ) { - FT_UInt len = strings[p]; + FT_UInt len = *p; - if ( len > 63U ) - { - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } + /* names in the Adobe Glyph List are shorter than 40 characters */ + if ( len >= 40U ) + FT_TRACE4(( "load_format_20: unusual %u-char name found\n", len )); - strings[p] = 0; - name_strings[n] = strings + p + 1; - p += len + 1; + *p++ = 0; + name_strings[n] = p; + p += len; } - strings[post_len] = 0; + *p_end = 0; /* deal with missing or insufficient string data */ if ( n < num_names ) { FT_TRACE4(( "load_format_20: %hu PostScript names are truncated\n", - num_names - n )); + (FT_UShort)( num_names - n ) )); for ( ; n < num_names; n++ ) - name_strings[n] = strings + post_len; + name_strings[n] = p_end; } } @@ -436,13 +436,8 @@ format = face->postscript.FormatType; - if ( format == 0x00010000L ) - { - if ( idx < 258 ) /* paranoid checking */ - *PSname = MAC_NAME( idx ); - } - else if ( format == 0x00020000L || - format == 0x00025000L ) + if ( format == 0x00020000L || + format == 0x00025000L ) { TT_Post_Names names = &face->postscript_names; @@ -466,6 +461,11 @@ } } + /* version 1.0 is only valid with 258 glyphs */ + else if ( format == 0x00010000L && + face->max_profile.numGlyphs == 258 ) + *PSname = MAC_NAME( idx ); + /* nothing to do for format == 0x00030000L */ End: diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h index 528f1c5f2f2..150db6c3981 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h @@ -5,7 +5,7 @@ * PostScript name table processing for TrueType and OpenType fonts * (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c index 03f90a628d6..cb3a8abf182 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded bitmap support (body). * - * Copyright (C) 2005-2023 by + * Copyright (C) 2005-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Copyright 2013 by Google, Inc. diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h index 07e2db461a5..96f80a58424 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded bitmap support (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c index eeedd9906be..532ccfa1737 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c @@ -4,7 +4,7 @@ * * WOFF2 Font table tags (base). * - * Copyright (C) 2019-2023 by + * Copyright (C) 2019-2024 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h index 1201848e5ec..d03b4b41bc9 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h @@ -4,7 +4,7 @@ * * WOFF2 Font table tags (specification). * - * Copyright (C) 2019-2023 by + * Copyright (C) 2019-2024 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c index 0918272f870..b7c0632a6fa 100644 --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c @@ -4,7 +4,7 @@ * * A new `perfect' anti-aliasing renderer (body). * - * Copyright (C) 2000-2023 by + * Copyright (C) 2000-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -489,7 +489,7 @@ typedef ptrdiff_t FT_PtrDist; typedef struct gray_TWorker_ { - ft_jmp_buf jump_buffer; + FT_BBox cbox; TCoord min_ex, max_ex; /* min and max integer pixel coordinates */ TCoord min_ey, max_ey; @@ -510,6 +510,8 @@ typedef ptrdiff_t FT_PtrDist; FT_Raster_Span_Func render_span; void* render_span_data; + ft_jmp_buf jump_buffer; + } gray_TWorker, *gray_PWorker; #if defined( _MSC_VER ) @@ -997,49 +999,12 @@ typedef ptrdiff_t FT_PtrDist; #endif /* - * Benchmarking shows that using DDA to flatten the quadratic Bézier arcs - * is slightly faster in the following cases: - * - * - When the host CPU is 64-bit. - * - When SSE2 SIMD registers and instructions are available (even on - * x86). - * - * For other cases, using binary splits is actually slightly faster. - */ -#if ( defined( __SSE2__ ) || \ - defined( __x86_64__ ) || \ - defined( _M_AMD64 ) || \ - ( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 ) ) && \ - !defined( __VMS ) -# define FT_SSE2 1 -#else -# define FT_SSE2 0 -#endif - -#if FT_SSE2 || \ - defined( __aarch64__ ) || \ - defined( _M_ARM64 ) -# define BEZIER_USE_DDA 1 -#else -# define BEZIER_USE_DDA 0 -#endif - - /* - * For now, the code that depends on `BEZIER_USE_DDA` requires `FT_Int64` - * to be defined. If `FT_INT64` is not defined, meaning there is no - * 64-bit type available, disable it to avoid compilation errors. See for - * example https://gitlab.freedesktop.org/freetype/freetype/-/issues/1071. + * For now, the code that uses DDA to render conic curves requires + * `FT_Int64` to be defined. See for example + * https://gitlab.freedesktop.org/freetype/freetype/-/issues/1071. */ -#if !defined( FT_INT64 ) -# undef BEZIER_USE_DDA -# define BEZIER_USE_DDA 0 -#endif - -#if BEZIER_USE_DDA -#if FT_SSE2 -# include <emmintrin.h> -#endif +#ifdef FT_INT64 #define LEFT_SHIFT( a, b ) (FT_Int64)( (FT_UInt64)(a) << (b) ) @@ -1095,16 +1060,17 @@ typedef ptrdiff_t FT_PtrDist; return; } - /* We can calculate the number of necessary bisections because */ + /* We can calculate the number of necessary segments because */ /* each bisection predictably reduces deviation exactly 4-fold. */ /* Even 32-bit deviation would vanish after 16 bisections. */ - shift = 0; + shift = 16; do { - dx >>= 2; - shift += 1; + dx >>= 2; + shift--; } while ( dx > ONE_PIXEL / 4 ); + count = 0x10000U >> shift; /* * The (P0,P1,P2) arc equation, for t in [0,1] range: @@ -1150,75 +1116,19 @@ typedef ptrdiff_t FT_PtrDist; * = (B << (33 - N)) + (A << (32 - 2*N)) */ -#if FT_SSE2 - /* Experience shows that for small shift values, */ - /* SSE2 is actually slower. */ - if ( shift > 2 ) - { - union - { - struct { FT_Int64 ax, ay, bx, by; } i; - struct { __m128i a, b; } vec; - - } u; - - union - { - struct { FT_Int32 px_lo, px_hi, py_lo, py_hi; } i; - __m128i vec; - - } v; - - __m128i a, b; - __m128i r, q, q2; - __m128i p; - - - u.i.ax = ax; - u.i.ay = ay; - u.i.bx = bx; - u.i.by = by; - - a = _mm_load_si128( &u.vec.a ); - b = _mm_load_si128( &u.vec.b ); - - r = _mm_slli_epi64( a, 33 - 2 * shift ); - q = _mm_slli_epi64( b, 33 - shift ); - q2 = _mm_slli_epi64( a, 32 - 2 * shift ); - - q = _mm_add_epi64( q2, q ); - - v.i.px_lo = 0; - v.i.px_hi = p0.x; - v.i.py_lo = 0; - v.i.py_hi = p0.y; - - p = _mm_load_si128( &v.vec ); - - for ( count = 1U << shift; count > 0; count-- ) - { - p = _mm_add_epi64( p, q ); - q = _mm_add_epi64( q, r ); - - _mm_store_si128( &v.vec, p ); - - gray_render_line( RAS_VAR_ v.i.px_hi, v.i.py_hi ); - } - - return; - } -#endif /* FT_SSE2 */ + rx = LEFT_SHIFT( ax, shift + shift ); + ry = LEFT_SHIFT( ay, shift + shift ); - rx = LEFT_SHIFT( ax, 33 - 2 * shift ); - ry = LEFT_SHIFT( ay, 33 - 2 * shift ); + qx = LEFT_SHIFT( bx, shift + 17 ) + rx; + qy = LEFT_SHIFT( by, shift + 17 ) + ry; - qx = LEFT_SHIFT( bx, 33 - shift ) + LEFT_SHIFT( ax, 32 - 2 * shift ); - qy = LEFT_SHIFT( by, 33 - shift ) + LEFT_SHIFT( ay, 32 - 2 * shift ); + rx *= 2; + ry *= 2; px = LEFT_SHIFT( p0.x, 32 ); py = LEFT_SHIFT( p0.y, 32 ); - for ( count = 1U << shift; count > 0; count-- ) + do { px += qx; py += qy; @@ -1227,10 +1137,10 @@ typedef ptrdiff_t FT_PtrDist; gray_render_line( RAS_VAR_ (FT_Pos)( px >> 32 ), (FT_Pos)( py >> 32 ) ); - } + } while ( --count ); } -#else /* !BEZIER_USE_DDA */ +#else /* !FT_INT64 */ /* * Note that multiple attempts to speed up the function below @@ -1324,7 +1234,7 @@ typedef ptrdiff_t FT_PtrDist; } while ( --draw ); } -#endif /* !BEZIER_USE_DDA */ +#endif /* !FT_INT64 */ /* @@ -1486,139 +1396,6 @@ typedef ptrdiff_t FT_PtrDist; } - static void - gray_sweep( RAS_ARG ) - { - int fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100 - : INT_MIN; - int coverage; - int y; - - - for ( y = ras.min_ey; y < ras.max_ey; y++ ) - { - PCell cell = ras.ycells[y - ras.min_ey]; - TCoord x = ras.min_ex; - TArea cover = 0; - - unsigned char* line = ras.target.origin - ras.target.pitch * y; - - - for ( ; cell != ras.cell_null; cell = cell->next ) - { - TArea area; - - - if ( cover != 0 && cell->x > x ) - { - FT_FILL_RULE( coverage, cover, fill ); - FT_GRAY_SET( line + x, coverage, cell->x - x ); - } - - cover += (TArea)cell->cover * ( ONE_PIXEL * 2 ); - area = cover - cell->area; - - if ( area != 0 && cell->x >= ras.min_ex ) - { - FT_FILL_RULE( coverage, area, fill ); - line[cell->x] = (unsigned char)coverage; - } - - x = cell->x + 1; - } - - if ( cover != 0 ) /* only if cropped */ - { - FT_FILL_RULE( coverage, cover, fill ); - FT_GRAY_SET( line + x, coverage, ras.max_ex - x ); - } - } - } - - - static void - gray_sweep_direct( RAS_ARG ) - { - int fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100 - : INT_MIN; - int coverage; - int y; - - FT_Span span[FT_MAX_GRAY_SPANS]; - int n = 0; - - - for ( y = ras.min_ey; y < ras.max_ey; y++ ) - { - PCell cell = ras.ycells[y - ras.min_ey]; - TCoord x = ras.min_ex; - TArea cover = 0; - - - for ( ; cell != ras.cell_null; cell = cell->next ) - { - TArea area; - - - if ( cover != 0 && cell->x > x ) - { - FT_FILL_RULE( coverage, cover, fill ); - - span[n].coverage = (unsigned char)coverage; - span[n].x = (short)x; - span[n].len = (unsigned short)( cell->x - x ); - - if ( ++n == FT_MAX_GRAY_SPANS ) - { - /* flush the span buffer and reset the count */ - ras.render_span( y, n, span, ras.render_span_data ); - n = 0; - } - } - - cover += (TArea)cell->cover * ( ONE_PIXEL * 2 ); - area = cover - cell->area; - - if ( area != 0 && cell->x >= ras.min_ex ) - { - FT_FILL_RULE( coverage, area, fill ); - - span[n].coverage = (unsigned char)coverage; - span[n].x = (short)cell->x; - span[n].len = 1; - - if ( ++n == FT_MAX_GRAY_SPANS ) - { - /* flush the span buffer and reset the count */ - ras.render_span( y, n, span, ras.render_span_data ); - n = 0; - } - } - - x = cell->x + 1; - } - - if ( cover != 0 ) /* only if cropped */ - { - FT_FILL_RULE( coverage, cover, fill ); - - span[n].coverage = (unsigned char)coverage; - span[n].x = (short)x; - span[n].len = (unsigned short)( ras.max_ex - x ); - - ++n; - } - - if ( n ) - { - /* flush the span buffer and reset the count */ - ras.render_span( y, n, span, ras.render_span_data ); - n = 0; - } - } - } - - #ifdef STANDALONE_ /************************************************************************** @@ -1934,7 +1711,7 @@ typedef ptrdiff_t FT_PtrDist; if ( continued ) FT_Trace_Enable(); - FT_TRACE7(( "band [%d..%d]: %td cell%s remaining/\n", + FT_TRACE7(( "band [%d..%d]: %td cell%s remaining\n", ras.min_ey, ras.max_ey, ras.cell_null - ras.cell_free, @@ -1952,14 +1729,144 @@ typedef ptrdiff_t FT_PtrDist; } + static void + gray_sweep( RAS_ARG ) + { + int fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100 + : INT_MIN; + int coverage; + int y; + + + for ( y = ras.min_ey; y < ras.max_ey; y++ ) + { + PCell cell = ras.ycells[y - ras.min_ey]; + TCoord x = ras.min_ex; + TArea cover = 0; + + unsigned char* line = ras.target.origin - ras.target.pitch * y; + + + for ( ; cell != ras.cell_null; cell = cell->next ) + { + TArea area; + + + if ( cover != 0 && cell->x > x ) + { + FT_FILL_RULE( coverage, cover, fill ); + FT_GRAY_SET( line + x, coverage, cell->x - x ); + } + + cover += (TArea)cell->cover * ( ONE_PIXEL * 2 ); + area = cover - cell->area; + + if ( area != 0 && cell->x >= ras.min_ex ) + { + FT_FILL_RULE( coverage, area, fill ); + line[cell->x] = (unsigned char)coverage; + } + + x = cell->x + 1; + } + + if ( cover != 0 ) /* only if cropped */ + { + FT_FILL_RULE( coverage, cover, fill ); + FT_GRAY_SET( line + x, coverage, ras.max_ex - x ); + } + } + } + + + static void + gray_sweep_direct( RAS_ARG ) + { + int fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100 + : INT_MIN; + int coverage; + int y; + + FT_Span span[FT_MAX_GRAY_SPANS]; + int n = 0; + + + for ( y = ras.min_ey; y < ras.max_ey; y++ ) + { + PCell cell = ras.ycells[y - ras.min_ey]; + TCoord x = ras.min_ex; + TArea cover = 0; + + + for ( ; cell != ras.cell_null; cell = cell->next ) + { + TArea area; + + + if ( cover != 0 && cell->x > x ) + { + FT_FILL_RULE( coverage, cover, fill ); + + span[n].coverage = (unsigned char)coverage; + span[n].x = (short)x; + span[n].len = (unsigned short)( cell->x - x ); + + if ( ++n == FT_MAX_GRAY_SPANS ) + { + /* flush the span buffer and reset the count */ + ras.render_span( y, n, span, ras.render_span_data ); + n = 0; + } + } + + cover += (TArea)cell->cover * ( ONE_PIXEL * 2 ); + area = cover - cell->area; + + if ( area != 0 && cell->x >= ras.min_ex ) + { + FT_FILL_RULE( coverage, area, fill ); + + span[n].coverage = (unsigned char)coverage; + span[n].x = (short)cell->x; + span[n].len = 1; + + if ( ++n == FT_MAX_GRAY_SPANS ) + { + /* flush the span buffer and reset the count */ + ras.render_span( y, n, span, ras.render_span_data ); + n = 0; + } + } + + x = cell->x + 1; + } + + if ( cover != 0 ) /* only if cropped */ + { + FT_FILL_RULE( coverage, cover, fill ); + + span[n].coverage = (unsigned char)coverage; + span[n].x = (short)x; + span[n].len = (unsigned short)( ras.max_ex - x ); + + ++n; + } + + if ( n ) + { + /* flush the span buffer and reset the count */ + ras.render_span( y, n, span, ras.render_span_data ); + n = 0; + } + } + } + + static int gray_convert_glyph( RAS_ARG ) { - const TCoord yMin = ras.min_ey; - const TCoord yMax = ras.max_ey; - TCell buffer[FT_MAX_GRAY_POOL]; - size_t height = (size_t)( yMax - yMin ); + size_t height = (size_t)( ras.cbox.yMax - ras.cbox.yMin ); size_t n = FT_MAX_GRAY_POOL / 8; TCoord y; TCoord bands[32]; /* enough to accommodate bisections */ @@ -1985,35 +1892,36 @@ typedef ptrdiff_t FT_PtrDist; height = ( height + n - 1 ) / n; } - for ( y = yMin; y < yMax; ) + for ( y = ras.cbox.yMin; y < ras.cbox.yMax; ) { ras.min_ey = y; y += height; - ras.max_ey = FT_MIN( y, yMax ); + ras.max_ey = FT_MIN( y, ras.cbox.yMax ); + + ras.count_ey = ras.max_ey - ras.min_ey; band = bands; - band[1] = ras.min_ey; - band[0] = ras.max_ey; + band[1] = ras.cbox.xMin; + band[0] = ras.cbox.xMax; do { - TCoord width = band[0] - band[1]; - TCoord w; + TCoord i; int error; - for ( w = 0; w < width; ++w ) - ras.ycells[w] = ras.cell_null; + ras.min_ex = band[1]; + ras.max_ex = band[0]; + + /* memory management: zero out and skip ycells */ + for ( i = 0; i < ras.count_ey; ++i ) + ras.ycells[i] = ras.cell_null; - /* memory management: skip ycells */ - n = ( (size_t)width * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) / - sizeof ( TCell ); + n = ( (size_t)ras.count_ey * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) + / sizeof ( TCell ); ras.cell_free = buffer + n; ras.cell = ras.cell_null; - ras.min_ey = band[1]; - ras.max_ey = band[0]; - ras.count_ey = width; error = gray_convert_glyph_inner( RAS_VAR_ continued ); continued = 1; @@ -2031,10 +1939,10 @@ typedef ptrdiff_t FT_PtrDist; return error; /* render pool overflow; we will reduce the render band by half */ - width >>= 1; + i = ( band[0] - band[1] ) >> 1; /* this should never happen even with tiny rendering pool */ - if ( width == 0 ) + if ( i == 0 ) { FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" )); return FT_THROW( Raster_Overflow ); @@ -2042,7 +1950,7 @@ typedef ptrdiff_t FT_PtrDist; band++; band[1] = band[0]; - band[0] += width; + band[0] += i; } while ( band >= bands ); } @@ -2073,7 +1981,7 @@ typedef ptrdiff_t FT_PtrDist; return FT_THROW( Invalid_Outline ); /* return immediately if the outline is empty */ - if ( outline->n_points == 0 || outline->n_contours <= 0 ) + if ( outline->n_points == 0 || outline->n_contours == 0 ) return Smooth_Err_Ok; if ( !outline->contours || !outline->points ) @@ -2093,10 +2001,7 @@ typedef ptrdiff_t FT_PtrDist; ras.render_span = (FT_Raster_Span_Func)params->gray_spans; ras.render_span_data = params->user; - ras.min_ex = params->clip_box.xMin; - ras.min_ey = params->clip_box.yMin; - ras.max_ex = params->clip_box.xMax; - ras.max_ey = params->clip_box.yMax; + ras.cbox = params->clip_box; } else { @@ -2122,14 +2027,14 @@ typedef ptrdiff_t FT_PtrDist; ras.render_span = (FT_Raster_Span_Func)NULL; ras.render_span_data = NULL; - ras.min_ex = 0; - ras.min_ey = 0; - ras.max_ex = (FT_Pos)target_map->width; - ras.max_ey = (FT_Pos)target_map->rows; + ras.cbox.xMin = 0; + ras.cbox.yMin = 0; + ras.cbox.xMax = (FT_Pos)target_map->width; + ras.cbox.yMax = (FT_Pos)target_map->rows; } /* exit if nothing to do */ - if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey ) + if ( ras.cbox.xMin >= ras.cbox.xMax || ras.cbox.yMin >= ras.cbox.yMax ) return Smooth_Err_Ok; return gray_convert_glyph( RAS_VAR ); diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h index a5001bf40d3..940fbe8c79b 100644 --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h @@ -4,7 +4,7 @@ * * FreeType smooth renderer declaration * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h index f4ac93dc410..6d41fb8e0fd 100644 --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h @@ -4,7 +4,7 @@ * * smooth renderer error codes (specification only). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c index 9b0e8886cb3..f0acc1ea4a6 100644 --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c @@ -4,7 +4,7 @@ * * Anti-aliasing renderer interface (body). * - * Copyright (C) 2000-2023 by + * Copyright (C) 2000-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h index f8bdc9938b3..d7b61a9e60e 100644 --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h @@ -4,7 +4,7 @@ * * Anti-aliasing renderer interface (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c index d1496fec7fa..4ab68eb9a12 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c @@ -4,7 +4,7 @@ * * TrueType font driver implementation (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -217,7 +217,20 @@ kerning->y = 0; if ( sfnt ) - kerning->x = sfnt->get_kerning( ttface, left_glyph, right_glyph ); + { + /* Use 'kern' table if available since that can be faster; otherwise */ + /* use GPOS kerning pairs if available. */ + if ( ttface->kern_avail_bits != 0 ) + kerning->x = sfnt->get_kerning( ttface, + left_glyph, + right_glyph ); +#ifdef TT_CONFIG_OPTION_GPOS_KERNING + else if ( ttface->gpos_kerning_available ) + kerning->x = sfnt->get_gpos_kerning( ttface, + left_glyph, + right_glyph ); +#endif + } return 0; } diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h index 757a66f425d..3e1cf234fcf 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h @@ -4,7 +4,7 @@ * * High-level TrueType driver interface (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h b/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h index 008ee99853c..7ad937bd04d 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h @@ -4,7 +4,7 @@ * * TrueType error codes (specification only). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c index dc427e8a116..b656ccf04e3 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c @@ -4,7 +4,7 @@ * * TrueType Glyph Loader (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -353,7 +353,8 @@ FT_Byte c, count; FT_Vector *vec, *vec_limit; FT_Pos x, y; - FT_Short *cont, *cont_limit, last; + FT_UShort *cont, *cont_limit; + FT_Int last; /* check that we can add the contours to the glyph */ @@ -372,7 +373,7 @@ last = -1; for ( ; cont < cont_limit; cont++ ) { - *cont = FT_NEXT_SHORT( p ); + *cont = FT_NEXT_USHORT( p ); if ( *cont <= last ) goto Invalid_Outline; @@ -418,11 +419,9 @@ /* and thus allocate the bytecode array size by ourselves */ if ( n_ins ) { - if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) ) + if ( FT_DUP( exec->glyphIns, p, n_ins ) ) return error; - FT_MEM_COPY( exec->glyphIns, p, (FT_Long)n_ins ); - exec->glyphSize = n_ins; } } @@ -432,7 +431,7 @@ p += n_ins; /* reading the point tags */ - flag = (FT_Byte*)outline->tags; + flag = outline->tags; flag_limit = flag + n_points; FT_ASSERT( flag ); @@ -465,7 +464,7 @@ vec = outline->points; vec_limit = vec + n_points; - flag = (FT_Byte*)outline->tags; + flag = outline->tags; x = 0; for ( ; vec < vec_limit; vec++, flag++ ) @@ -499,7 +498,7 @@ vec = outline->points; vec_limit = vec + n_points; - flag = (FT_Byte*)outline->tags; + flag = outline->tags; y = 0; for ( ; vec < vec_limit; vec++, flag++ ) @@ -532,8 +531,8 @@ *flag = (FT_Byte)( f & ON_CURVE_POINT ); } - outline->n_points = (FT_Short)n_points; - outline->n_contours = (FT_Short)n_contours; + outline->n_points = (FT_UShort)n_points; + outline->n_contours = (FT_UShort)n_contours; load->cursor = p; @@ -754,15 +753,13 @@ FT_UInt start_point, FT_UInt start_contour ) { - zone->n_points = (FT_UShort)load->outline.n_points + 4 - - (FT_UShort)start_point; - zone->n_contours = load->outline.n_contours - - (FT_Short)start_contour; + zone->n_points = load->outline.n_points + 4 - (FT_UShort)start_point; + zone->n_contours = load->outline.n_contours - (FT_UShort)start_contour; zone->org = load->extra_points + start_point; zone->cur = load->outline.points + start_point; zone->orus = load->extra_points2 + start_point; - zone->tags = (FT_Byte*)load->outline.tags + start_point; - zone->contours = (FT_UShort*)load->outline.contours + start_contour; + zone->tags = load->outline.tags + start_point; + zone->contours = load->outline.contours + start_contour; zone->first_point = (FT_UShort)start_point; } @@ -1046,7 +1043,7 @@ current.points = gloader->base.outline.points + num_base_points; current.n_points = gloader->base.outline.n_points - - (short)num_base_points; + (FT_UShort)num_base_points; have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE | WE_HAVE_AN_XY_SCALE | @@ -1059,7 +1056,7 @@ /* get offset */ if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) ) { - FT_UInt num_points = (FT_UInt)gloader->base.outline.n_points; + FT_UInt num_points = gloader->base.outline.n_points; FT_UInt k = (FT_UInt)subglyph->arg1; FT_UInt l = (FT_UInt)subglyph->arg2; FT_Vector* p1; @@ -1721,8 +1718,8 @@ FT_List_Add( &loader->composites, node ); } - start_point = (FT_UInt)gloader->base.outline.n_points; - start_contour = (FT_UInt)gloader->base.outline.n_contours; + start_point = gloader->base.outline.n_points; + start_contour = gloader->base.outline.n_contours; /* for each subglyph, read composite header */ error = face->read_composite_glyph( loader ); @@ -1741,14 +1738,14 @@ if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || FT_IS_VARIATION( FT_FACE( face ) ) ) { - short i, limit; + FT_UShort i, limit; FT_SubGlyph subglyph; FT_Outline outline = { 0, 0, NULL, NULL, NULL, 0 }; FT_Vector* unrounded = NULL; - limit = (short)gloader->current.num_subglyphs; + limit = (FT_UShort)gloader->current.num_subglyphs; /* construct an outline structure for */ /* communication with `TT_Vary_Apply_Glyph_Deltas' */ @@ -1874,7 +1871,7 @@ linear_hadvance = loader->linear; linear_vadvance = loader->vadvance; - num_base_points = (FT_UInt)gloader->base.outline.n_points; + num_base_points = gloader->base.outline.n_points; error = load_truetype_glyph( loader, (FT_UInt)subglyph->index, @@ -1898,7 +1895,7 @@ loader->vadvance = linear_vadvance; } - num_points = (FT_UInt)gloader->base.outline.n_points; + num_points = gloader->base.outline.n_points; if ( num_points == num_base_points ) continue; @@ -2313,7 +2310,7 @@ * * 1) we have a `tricky' font that heavily relies on the interpreter to * render glyphs correctly, for example DFKai-SB, or - * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested. + * 2) FT_RENDER_MODE_MONO (i.e, monochrome rendering) is requested. * * In those cases, backward compatibility needs to be turned off to get * correct rendering. The rendering is then completely up to the @@ -2719,7 +2716,7 @@ size->metrics->y_ppem < 24 ) glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; - FT_TRACE1(( " subglyphs = %u, contours = %hd, points = %hd," + FT_TRACE1(( " subglyphs = %u, contours = %hu, points = %hu," " flags = 0x%.3x\n", loader.gloader->base.num_subglyphs, glyph->outline.n_contours, diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h index f18637dce33..22ea967f301 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h @@ -4,7 +4,7 @@ * * TrueType Glyph Loader (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c index 9d149ea365c..4f0083c96b7 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c @@ -4,7 +4,7 @@ * * TrueType GX Font Variation loader * - * Copyright (C) 2004-2023 by + * Copyright (C) 2004-2024 by * David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. * * This file is part of the FreeType project, and may only be used, @@ -129,9 +129,6 @@ * stream :: * The data stream. * - * size :: - * The size of the table holding the data. - * * @Output: * point_cnt :: * The number of points read. A zero value means that @@ -144,14 +141,14 @@ */ static FT_UShort* ft_var_readpackedpoints( FT_Stream stream, - FT_ULong size, FT_UInt *point_cnt ) { FT_UShort *points = NULL; FT_UInt n; - FT_UInt runcnt; + FT_UInt runcnt, cnt; FT_UInt i, j; FT_UShort first; + FT_Byte* p; FT_Memory memory = stream->memory; FT_Error error; @@ -169,56 +166,60 @@ n |= FT_GET_BYTE(); } - if ( n > size ) - { - FT_TRACE1(( "ft_var_readpackedpoints: number of points too large\n" )); + if ( FT_QNEW_ARRAY( points, n ) ) return NULL; - } - - /* in the nested loops below we increase `i' twice; */ - /* it is faster to simply allocate one more slot */ - /* than to add another test within the loop */ - if ( FT_QNEW_ARRAY( points, n + 1 ) ) - return NULL; - - *point_cnt = n; + p = stream->cursor; first = 0; i = 0; while ( i < n ) { - runcnt = FT_GET_BYTE(); + if ( p >= stream->limit ) + goto Fail; + + runcnt = FT_NEXT_BYTE( p ); + cnt = runcnt & GX_PT_POINT_RUN_COUNT_MASK; + + /* first point not included in run count */ + cnt++; + if ( cnt > n - i ) + cnt = n - i; + if ( runcnt & GX_PT_POINTS_ARE_WORDS ) { - runcnt &= GX_PT_POINT_RUN_COUNT_MASK; - first += FT_GET_USHORT(); - points[i++] = first; + if ( 2 * cnt > (FT_UInt)( stream->limit - p ) ) + goto Fail; - /* first point not included in run count */ - for ( j = 0; j < runcnt; j++ ) + for ( j = 0; j < cnt; j++ ) { - first += FT_GET_USHORT(); + first += FT_NEXT_USHORT( p ); points[i++] = first; - if ( i >= n ) - break; } } else { - first += FT_GET_BYTE(); - points[i++] = first; + if ( cnt > (FT_UInt)( stream->limit - p ) ) + goto Fail; - for ( j = 0; j < runcnt; j++ ) + for ( j = 0; j < cnt; j++ ) { - first += FT_GET_BYTE(); + first += FT_NEXT_BYTE( p ); points[i++] = first; - if ( i >= n ) - break; } } } + stream->cursor = p; + + *point_cnt = n; + return points; + + Fail: + FT_TRACE1(( "ft_var_readpackedpoints: invalid table\n" )); + + FT_FREE( points ); + return NULL; } @@ -240,9 +241,6 @@ * stream :: * The data stream. * - * size :: - * The size of the table holding the data. - * * delta_cnt :: * The number of deltas to be read. * @@ -258,13 +256,12 @@ */ static FT_Fixed* ft_var_readpackeddeltas( FT_Stream stream, - FT_ULong size, FT_UInt delta_cnt ) { FT_Fixed *deltas = NULL; FT_UInt runcnt, cnt; FT_UInt i, j; - FT_UInt bytes_used; + FT_Byte* p; FT_Memory memory = stream->memory; FT_Error error; @@ -272,68 +269,51 @@ if ( FT_QNEW_ARRAY( deltas, delta_cnt ) ) return NULL; - i = 0; - bytes_used = 0; - - while ( i < delta_cnt && bytes_used < size ) + p = stream->cursor; + i = 0; + while ( i < delta_cnt ) { - runcnt = FT_GET_BYTE(); + if ( p >= stream->limit ) + goto Fail; + + runcnt = FT_NEXT_BYTE( p ); cnt = runcnt & GX_DT_DELTA_RUN_COUNT_MASK; - bytes_used++; + /* first point not included in run count */ + cnt++; + if ( cnt > delta_cnt - i ) + cnt = delta_cnt - i; if ( runcnt & GX_DT_DELTAS_ARE_ZERO ) { - /* `cnt` + 1 zeroes get added */ - for ( j = 0; j <= cnt && i < delta_cnt; j++ ) + for ( j = 0; j < cnt; j++ ) deltas[i++] = 0; } else if ( runcnt & GX_DT_DELTAS_ARE_WORDS ) { - /* `cnt` + 1 shorts from the stack */ - bytes_used += 2 * ( cnt + 1 ); - if ( bytes_used > size ) - { - FT_TRACE1(( "ft_var_readpackeddeltas:" - " number of short deltas too large\n" )); + if ( 2 * cnt > (FT_UInt)( stream->limit - p ) ) goto Fail; - } - for ( j = 0; j <= cnt && i < delta_cnt; j++ ) - deltas[i++] = FT_intToFixed( FT_GET_SHORT() ); + for ( j = 0; j < cnt; j++ ) + deltas[i++] = FT_intToFixed( FT_NEXT_SHORT( p ) ); } else { - /* `cnt` + 1 signed bytes from the stack */ - bytes_used += cnt + 1; - if ( bytes_used > size ) - { - FT_TRACE1(( "ft_var_readpackeddeltas:" - " number of byte deltas too large\n" )); + if ( cnt > (FT_UInt)( stream->limit - p ) ) goto Fail; - } - for ( j = 0; j <= cnt && i < delta_cnt; j++ ) - deltas[i++] = FT_intToFixed( FT_GET_CHAR() ); - } - - if ( j <= cnt ) - { - FT_TRACE1(( "ft_var_readpackeddeltas:" - " number of deltas too large\n" )); - goto Fail; + for ( j = 0; j < cnt; j++ ) + deltas[i++] = FT_intToFixed( FT_NEXT_CHAR( p ) ); } } - if ( i < delta_cnt ) - { - FT_TRACE1(( "ft_var_readpackeddeltas: not enough deltas\n" )); - goto Fail; - } + stream->cursor = p; return deltas; Fail: + FT_TRACE1(( "ft_var_readpackeddeltas: invalid table\n" )); + FT_FREE( deltas ); return NULL; } @@ -596,7 +576,7 @@ for ( j = 0; j < itemStore->axisCount; j++ ) { - FT_Short start, peak, end; + FT_Int start, peak, end; if ( FT_READ_SHORT( start ) || @@ -604,6 +584,10 @@ FT_READ_SHORT( end ) ) goto Exit; + /* immediately tag invalid ranges with special peak = 0 */ + if ( ( start < 0 && end > 0 ) || start > peak || peak > end ) + peak = 0; + axisCoords[j].startCoord = FT_fdot14ToFixed( start ); axisCoords[j].peakCoord = FT_fdot14ToFixed( peak ); axisCoords[j].endCoord = FT_fdot14ToFixed( end ); @@ -1024,6 +1008,9 @@ if ( innerIndex >= varData->itemCount ) return 0; /* Out of range. */ + if ( varData->regionIdxCount == 0 ) + return 0; /* Avoid "applying zero offset to null pointer". */ + if ( varData->regionIdxCount < 16 ) { deltaSet = deltaSetStack; @@ -1074,43 +1061,32 @@ /* inner loop steps through axes in this region */ for ( j = 0; j < itemStore->axisCount; j++, axis++ ) { - /* compute the scalar contribution of this axis; */ - /* ignore invalid ranges */ - if ( axis->startCoord > axis->peakCoord || - axis->peakCoord > axis->endCoord ) - continue; + FT_Fixed ncv = ttface->blend->normalizedcoords[j]; - else if ( axis->startCoord < 0 && - axis->endCoord > 0 && - axis->peakCoord != 0 ) - continue; - /* peak of 0 means ignore this axis */ - else if ( axis->peakCoord == 0 ) - continue; - - else if ( ttface->blend->normalizedcoords[j] == axis->peakCoord ) + /* compute the scalar contribution of this axis */ + /* with peak of 0 used for invalid axes */ + if ( axis->peakCoord == ncv || + axis->peakCoord == 0 ) continue; /* ignore this region if coords are out of range */ - else if ( ttface->blend->normalizedcoords[j] <= axis->startCoord || - ttface->blend->normalizedcoords[j] >= axis->endCoord ) + else if ( ncv <= axis->startCoord || + ncv >= axis->endCoord ) { scalar = 0; break; } /* cumulative product of all the axis scalars */ - else if ( ttface->blend->normalizedcoords[j] < axis->peakCoord ) - scalar = - FT_MulDiv( scalar, - ttface->blend->normalizedcoords[j] - axis->startCoord, - axis->peakCoord - axis->startCoord ); - else - scalar = - FT_MulDiv( scalar, - axis->endCoord - ttface->blend->normalizedcoords[j], - axis->endCoord - axis->peakCoord ); + else if ( ncv < axis->peakCoord ) + scalar = FT_MulDiv( scalar, + ncv - axis->startCoord, + axis->peakCoord - axis->startCoord ); + else /* ncv > axis->peakCoord */ + scalar = FT_MulDiv( scalar, + axis->endCoord - ncv, + axis->endCoord - axis->peakCoord ); } /* per-axis loop */ @@ -1920,32 +1896,27 @@ for ( i = 0; i < blend->num_axis; i++ ) { - FT_TRACE6(( " axis %d coordinate %.5f:\n", - i, (double)blend->normalizedcoords[i] / 65536 )); + FT_Fixed ncv = blend->normalizedcoords[i]; + + + FT_TRACE6(( " axis %d coordinate %.5f:\n", i, (double)ncv / 65536 )); /* It's not clear why (for intermediate tuples) we don't need */ /* to check against start/end -- the documentation says we don't. */ /* Similarly, it's unclear why we don't need to scale along the */ /* axis. */ - if ( tuple_coords[i] == 0 ) + if ( tuple_coords[i] == ncv ) { - FT_TRACE6(( " tuple coordinate is zero, ignore\n" )); + FT_TRACE6(( " tuple coordinate %.5f fits perfectly\n", + (double)tuple_coords[i] / 65536 )); + /* `apply' does not change */ continue; } - if ( blend->normalizedcoords[i] == 0 ) - { - FT_TRACE6(( " axis coordinate is zero, stop\n" )); - apply = 0; - break; - } - - if ( blend->normalizedcoords[i] == tuple_coords[i] ) + if ( tuple_coords[i] == 0 ) { - FT_TRACE6(( " tuple coordinate %.5f fits perfectly\n", - (double)tuple_coords[i] / 65536 )); - /* `apply' does not change */ + FT_TRACE6(( " tuple coordinate is zero, ignore\n" )); continue; } @@ -1953,27 +1924,27 @@ { /* not an intermediate tuple */ - if ( blend->normalizedcoords[i] < FT_MIN( 0, tuple_coords[i] ) || - blend->normalizedcoords[i] > FT_MAX( 0, tuple_coords[i] ) ) + if ( ( tuple_coords[i] > ncv && ncv > 0 ) || + ( tuple_coords[i] < ncv && ncv < 0 ) ) + { + FT_TRACE6(( " tuple coordinate %.5f fits\n", + (double)tuple_coords[i] / 65536 )); + apply = FT_MulDiv( apply, ncv, tuple_coords[i] ); + } + else { FT_TRACE6(( " tuple coordinate %.5f is exceeded, stop\n", (double)tuple_coords[i] / 65536 )); apply = 0; break; } - - FT_TRACE6(( " tuple coordinate %.5f fits\n", - (double)tuple_coords[i] / 65536 )); - apply = FT_MulDiv( apply, - blend->normalizedcoords[i], - tuple_coords[i] ); } else { /* intermediate tuple */ - if ( blend->normalizedcoords[i] <= im_start_coords[i] || - blend->normalizedcoords[i] >= im_end_coords[i] ) + if ( ncv <= im_start_coords[i] || + ncv >= im_end_coords[i] ) { FT_TRACE6(( " intermediate tuple range ]%.5f;%.5f[ is exceeded," " stop\n", @@ -1986,13 +1957,13 @@ FT_TRACE6(( " intermediate tuple range ]%.5f;%.5f[ fits\n", (double)im_start_coords[i] / 65536, (double)im_end_coords[i] / 65536 )); - if ( blend->normalizedcoords[i] < tuple_coords[i] ) + if ( ncv < tuple_coords[i] ) apply = FT_MulDiv( apply, - blend->normalizedcoords[i] - im_start_coords[i], + ncv - im_start_coords[i], tuple_coords[i] - im_start_coords[i] ); - else + else /* ncv > tuple_coords[i] */ apply = FT_MulDiv( apply, - im_end_coords[i] - blend->normalizedcoords[i], + im_end_coords[i] - ncv, im_end_coords[i] - tuple_coords[i] ); } } @@ -2141,11 +2112,12 @@ outerIndex, innerIndex ); - v += delta << 2; + /* Convert delta in F2DOT14 to 16.16 before adding. */ + v += MUL_INT( delta, 4 ); - /* Clamp value range. */ - v = v >= 0x10000L ? 0x10000 : v; - v = v <= -0x10000L ? -0x10000 : v; + /* Clamp value to range [-1, 1]. */ + v = v >= 0x10000L ? 0x10000 : v; + v = v <= -0x10000L ? -0x10000 : v; new_normalized[i] = v; } @@ -2721,9 +2693,8 @@ FT_UInt n; - if ( FT_ALLOC( mmvar, ttface->blend->mmvar_len ) ) + if ( FT_DUP( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len ) ) goto Exit; - FT_MEM_COPY( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len ); axis_flags = (FT_UShort*)( (char*)mmvar + mmvar_size ); @@ -3533,9 +3504,10 @@ FT_ULong here; FT_UInt i, j; - FT_Fixed* tuple_coords = NULL; - FT_Fixed* im_start_coords = NULL; - FT_Fixed* im_end_coords = NULL; + FT_Fixed* peak_coords = NULL; + FT_Fixed* tuple_coords; + FT_Fixed* im_start_coords; + FT_Fixed* im_end_coords; GX_Blend blend = face->blend; @@ -3556,16 +3528,16 @@ { FT_TRACE2(( "\n" )); FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" )); - error = FT_Err_Ok; - goto Exit; + + return FT_Err_Ok; } if ( !face->cvt ) { FT_TRACE2(( "\n" )); FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" )); - error = FT_Err_Ok; - goto Exit; + + return FT_Err_Ok; } error = face->goto_table( face, TTAG_cvar, stream, &table_len ); @@ -3573,15 +3545,11 @@ { FT_TRACE2(( "is missing\n" )); - error = FT_Err_Ok; - goto Exit; + return FT_Err_Ok; } if ( FT_FRAME_ENTER( table_len ) ) - { - error = FT_Err_Ok; - goto Exit; - } + return FT_Err_Ok; table_start = FT_Stream_FTell( stream ); if ( FT_GET_LONG() != 0x00010000L ) @@ -3594,11 +3562,6 @@ FT_TRACE2(( "loaded\n" )); - if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) || - FT_NEW_ARRAY( im_start_coords, blend->num_axis ) || - FT_NEW_ARRAY( im_end_coords, blend->num_axis ) ) - goto FExit; - tupleCount = FT_GET_USHORT(); offsetToData = FT_GET_USHORT(); @@ -3621,9 +3584,8 @@ FT_Stream_SeekSet( stream, offsetToData ); - sharedpoints = ft_var_readpackedpoints( stream, - table_len, - &spoint_count ); + sharedpoints = ft_var_readpackedpoints( stream, &spoint_count ); + offsetToData = FT_Stream_FTell( stream ); FT_Stream_SeekSet( stream, here ); @@ -3634,8 +3596,12 @@ tupleCount & GX_TC_TUPLE_COUNT_MASK, ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" )); - if ( FT_NEW_ARRAY( cvt_deltas, face->cvt_size ) ) - goto FExit; + if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) || + FT_NEW_ARRAY( cvt_deltas, face->cvt_size ) ) + goto Exit; + + im_start_coords = peak_coords + blend->num_axis; + im_end_coords = im_start_coords + blend->num_axis; for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ ) { @@ -3652,32 +3618,19 @@ if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD ) { for ( j = 0; j < blend->num_axis; j++ ) - tuple_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() ); + peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() ); + tuple_coords = peak_coords; } - else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount ) + else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount ) + tuple_coords = blend->tuplecoords + + ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis; + else { FT_TRACE2(( "tt_face_vary_cvt:" " invalid tuple index\n" )); error = FT_THROW( Invalid_Table ); - goto FExit; - } - else - { - if ( !blend->tuplecoords ) - { - FT_TRACE2(( "tt_face_vary_cvt:" - " no valid tuple coordinates available\n" )); - - error = FT_THROW( Invalid_Table ); - goto FExit; - } - - FT_MEM_COPY( - tuple_coords, - blend->tuplecoords + - ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis, - blend->num_axis * sizeof ( FT_Fixed ) ); + goto Exit; } if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) @@ -3706,9 +3659,7 @@ if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) { - localpoints = ft_var_readpackedpoints( stream, - table_len, - &point_count ); + localpoints = ft_var_readpackedpoints( stream, &point_count ); points = localpoints; } else @@ -3719,7 +3670,6 @@ } deltas = ft_var_readpackeddeltas( stream, - table_len, point_count == 0 ? face->cvt_size : point_count ); @@ -3820,22 +3770,20 @@ for ( i = 0; i < face->cvt_size; i++ ) face->cvt[i] += FT_fixedToFdot6( cvt_deltas[i] ); - FExit: - FT_FRAME_EXIT(); + /* Iterate over all `FT_Size` objects and set `cvt_ready` to -1 */ + /* to trigger rescaling of all CVT values. */ + FT_List_Iterate( &root->sizes_list, + tt_cvt_ready_iterator, + NULL ); Exit: if ( sharedpoints != ALL_POINTS ) FT_FREE( sharedpoints ); - FT_FREE( tuple_coords ); - FT_FREE( im_start_coords ); - FT_FREE( im_end_coords ); FT_FREE( cvt_deltas ); + FT_FREE( peak_coords ); - /* iterate over all FT_Size objects and set `cvt_ready' to -1 */ - /* to trigger rescaling of all CVT values */ - FT_List_Iterate( &root->sizes_list, - tt_cvt_ready_iterator, - NULL ); + FExit: + FT_FRAME_EXIT(); return error; @@ -4099,9 +4047,10 @@ FT_ULong here; FT_UInt i, j; - FT_Fixed* tuple_coords = NULL; - FT_Fixed* im_start_coords = NULL; - FT_Fixed* im_end_coords = NULL; + FT_Fixed* peak_coords = NULL; + FT_Fixed* tuple_coords; + FT_Fixed* im_start_coords; + FT_Fixed* im_end_coords; GX_Blend blend = face->blend; @@ -4136,27 +4085,17 @@ return FT_Err_Ok; } - if ( FT_NEW_ARRAY( points_org, n_points ) || - FT_NEW_ARRAY( points_out, n_points ) || - FT_NEW_ARRAY( has_delta, n_points ) ) - goto Fail1; - dataSize = blend->glyphoffsets[glyph_index + 1] - blend->glyphoffsets[glyph_index]; if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) || FT_FRAME_ENTER( dataSize ) ) - goto Fail1; + return error; glyph_start = FT_Stream_FTell( stream ); /* each set of glyph variation data is formatted similarly to `cvar' */ - if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) || - FT_NEW_ARRAY( im_start_coords, blend->num_axis ) || - FT_NEW_ARRAY( im_end_coords, blend->num_axis ) ) - goto Fail2; - tupleCount = FT_GET_USHORT(); offsetToData = FT_GET_USHORT(); @@ -4168,7 +4107,7 @@ " invalid glyph variation array header\n" )); error = FT_THROW( Invalid_Table ); - goto Fail2; + goto FExit; } offsetToData += glyph_start; @@ -4179,9 +4118,8 @@ FT_Stream_SeekSet( stream, offsetToData ); - sharedpoints = ft_var_readpackedpoints( stream, - blend->gvar_size, - &spoint_count ); + sharedpoints = ft_var_readpackedpoints( stream, &spoint_count ); + offsetToData = FT_Stream_FTell( stream ); FT_Stream_SeekSet( stream, here ); @@ -4192,9 +4130,16 @@ tupleCount & GX_TC_TUPLE_COUNT_MASK, ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" )); - if ( FT_NEW_ARRAY( point_deltas_x, n_points ) || - FT_NEW_ARRAY( point_deltas_y, n_points ) ) - goto Fail3; + if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) || + FT_NEW_ARRAY( point_deltas_x, 2 * n_points ) || + FT_QNEW_ARRAY( points_org, n_points ) || + FT_QNEW_ARRAY( points_out, n_points ) || + FT_QNEW_ARRAY( has_delta, n_points ) ) + goto Exit; + + im_start_coords = peak_coords + blend->num_axis; + im_end_coords = im_start_coords + blend->num_axis; + point_deltas_y = point_deltas_x + n_points; for ( j = 0; j < n_points; j++ ) { @@ -4217,22 +4162,20 @@ if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD ) { for ( j = 0; j < blend->num_axis; j++ ) - tuple_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() ); + peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() ); + tuple_coords = peak_coords; } - else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount ) + else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount ) + tuple_coords = blend->tuplecoords + + ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis; + else { FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:" " invalid tuple index\n" )); error = FT_THROW( Invalid_Table ); - goto Fail3; + goto Exit; } - else - FT_MEM_COPY( - tuple_coords, - blend->tuplecoords + - ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis, - blend->num_axis * sizeof ( FT_Fixed ) ); if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) { @@ -4260,9 +4203,7 @@ if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) { - localpoints = ft_var_readpackedpoints( stream, - blend->gvar_size, - &point_count ); + localpoints = ft_var_readpackedpoints( stream, &point_count ); points = localpoints; } else @@ -4272,11 +4213,9 @@ } deltas_x = ft_var_readpackeddeltas( stream, - blend->gvar_size, point_count == 0 ? n_points : point_count ); deltas_y = ft_var_readpackeddeltas( stream, - blend->gvar_size, point_count == 0 ? n_points : point_count ); @@ -4460,23 +4399,17 @@ unrounded[n_points - 2].y ) / 64; } - Fail3: - FT_FREE( point_deltas_x ); - FT_FREE( point_deltas_y ); - - Fail2: + Exit: if ( sharedpoints != ALL_POINTS ) FT_FREE( sharedpoints ); - FT_FREE( tuple_coords ); - FT_FREE( im_start_coords ); - FT_FREE( im_end_coords ); - - FT_FRAME_EXIT(); - - Fail1: FT_FREE( points_org ); FT_FREE( points_out ); FT_FREE( has_delta ); + FT_FREE( peak_coords ); + FT_FREE( point_deltas_x ); + + FExit: + FT_FRAME_EXIT(); return error; } diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h index e3da6d1705c..9326011e3a2 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h @@ -4,7 +4,7 @@ * * TrueType GX Font Variation loader (specification) * - * Copyright (C) 2004-2023 by + * Copyright (C) 2004-2024 by * David Turner, Robert Wilhelm, Werner Lemberg and George Williams. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c index 79df4555d94..951891dbf51 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c @@ -4,7 +4,7 @@ * * TrueType bytecode interpreter (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -5270,11 +5270,11 @@ FT_UShort refp; FT_F26Dot6 dx, dy; - FT_Short contour, bounds; + FT_UShort contour, bounds; FT_UShort start, limit, i; - contour = (FT_Short)args[0]; + contour = (FT_UShort)args[0]; bounds = ( exc->GS.gep2 == 0 ) ? 1 : exc->zp2.n_contours; if ( BOUNDS( contour, bounds ) ) @@ -5290,15 +5290,13 @@ if ( contour == 0 ) start = 0; else - start = (FT_UShort)( exc->zp2.contours[contour - 1] + 1 - - exc->zp2.first_point ); + start = exc->zp2.contours[contour - 1] + 1 - exc->zp2.first_point; /* we use the number of points if in the twilight zone */ if ( exc->GS.gep2 == 0 ) limit = exc->zp2.n_points; else - limit = (FT_UShort)( exc->zp2.contours[contour] - - exc->zp2.first_point + 1 ); + limit = exc->zp2.contours[contour] + 1 - exc->zp2.first_point; for ( i = start; i < limit; i++ ) { @@ -5341,9 +5339,9 @@ /* Normal zone's `n_points' includes phantoms, so must */ /* use end of last contour. */ if ( exc->GS.gep2 == 0 ) - limit = (FT_UShort)exc->zp2.n_points; + limit = exc->zp2.n_points; else if ( exc->GS.gep2 == 1 && exc->zp2.n_contours > 0 ) - limit = (FT_UShort)( exc->zp2.contours[exc->zp2.n_contours - 1] + 1 ); + limit = exc->zp2.contours[exc->zp2.n_contours - 1] + 1; else limit = 0; diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h index e98e258fe7e..4f1a9bbc679 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h @@ -4,7 +4,7 @@ * * TrueType bytecode interpreter (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c index 5b56af711df..d0ac3181204 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c @@ -4,7 +4,7 @@ * * Objects manager (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -115,7 +115,7 @@ FT_LOCAL_DEF( FT_Error ) tt_glyphzone_new( FT_Memory memory, FT_UShort maxPoints, - FT_Short maxContours, + FT_UShort maxContours, TT_GlyphZone zone ) { FT_Error error; @@ -152,18 +152,20 @@ static const FT_String* tt_skip_pdffont_random_tag( const FT_String* name ) { - unsigned int i; - - - if ( ft_strlen( name ) < 8 || name[6] != '+' ) - return name; - - for ( i = 0; i < 6; i++ ) - if ( !ft_isupper( name[i] ) ) - return name; + if ( ft_isupper( name[0] ) && + ft_isupper( name[1] ) && + ft_isupper( name[2] ) && + ft_isupper( name[3] ) && + ft_isupper( name[4] ) && + ft_isupper( name[5] ) && + '+' == name[6] && + name[7] ) + { + FT_TRACE7(( "name without randomization tag: %s\n", name + 7 )); + return name + 7; + } - FT_TRACE7(( "name without randomization tag: %s\n", name + 7 )); - return name + 7; + return name; } @@ -254,17 +256,20 @@ { FT_Error error; FT_UInt32 checksum = 0; - FT_UInt i; + FT_Byte* p; + FT_Int shift; if ( FT_FRAME_ENTER( length ) ) return 0; + p = (FT_Byte*)stream->cursor; + for ( ; length > 3; length -= 4 ) - checksum += (FT_UInt32)FT_GET_ULONG(); + checksum += FT_NEXT_ULONG( p ); - for ( i = 3; length > 0; length--, i-- ) - checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 ); + for ( shift = 24; length > 0; length--, shift -=8 ) + checksum += (FT_UInt32)FT_NEXT_BYTE( p ) << shift; FT_FRAME_EXIT(); @@ -782,8 +787,7 @@ FT_UInt instance_index = (FT_UInt)face_index >> 16; - if ( FT_HAS_MULTIPLE_MASTERS( ttface ) && - instance_index > 0 ) + if ( FT_HAS_MULTIPLE_MASTERS( ttface ) ) { error = FT_Set_Named_Instance( ttface, instance_index ); if ( error ) @@ -990,16 +994,16 @@ FT_Error error; FT_UInt i; - /* unscaled CVT values are already stored in 26.6 format */ - FT_Fixed scale = size->ttmetrics.scale >> 6; - /* Scale the cvt values to the new ppem. */ /* By default, we use the y ppem value for scaling. */ FT_TRACE6(( "CVT values:\n" )); for ( i = 0; i < size->cvt_size; i++ ) { - size->cvt[i] = FT_MulFix( face->cvt[i], scale ); + /* Unscaled CVT values are already stored in 26.6 format. */ + /* Note that this scaling operation is very sensitive to rounding; */ + /* the integer division by 64 must be applied to the first argument. */ + size->cvt[i] = FT_MulFix( face->cvt[i] / 64, size->ttmetrics.scale ); FT_TRACE6(( " %3d: %f (%f)\n", i, (double)face->cvt[i] / 64, (double)size->cvt[i] / 64 )); } diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h index 40eb37b4c43..9c36ca78362 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h @@ -4,7 +4,7 @@ * * Objects manager (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -105,7 +105,7 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) tt_glyphzone_new( FT_Memory memory, FT_UShort maxPoints, - FT_Short maxContours, + FT_UShort maxContours, TT_GlyphZone zone ); #endif /* TT_USE_BYTECODE_INTERPRETER */ diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c index 54a64c7b462..9505b5f179f 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c @@ -4,7 +4,7 @@ * * TrueType-specific tables loader (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h index ed229fa4616..bc32b58020c 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h @@ -4,7 +4,7 @@ * * TrueType-specific tables loader (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c index d9b9398b013..a63cd4dc48a 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c @@ -4,7 +4,7 @@ * * AFM support for Type 1 fonts (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h index e0d5aa5a882..7f5cdda191f 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h @@ -4,7 +4,7 @@ * * AFM support for Type 1 fonts (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c index a4cdf372a9e..8ed01914a5a 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c @@ -4,7 +4,7 @@ * * Type 1 driver interface (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -312,10 +312,7 @@ { retval = ft_strlen( type1->glyph_names[idx] ) + 1; if ( value && value_len >= retval ) - { ft_memcpy( value, (void *)( type1->glyph_names[idx] ), retval ); - ((FT_Char *)value)[retval - 1] = (FT_Char)'\0'; - } } break; @@ -344,11 +341,8 @@ { retval = ft_strlen( type1->encoding.char_name[idx] ) + 1; if ( value && value_len >= retval ) - { ft_memcpy( value, (void *)( type1->encoding.char_name[idx] ), - retval - 1 ); - ((FT_Char *)value)[retval - 1] = (FT_Char)'\0'; - } + retval ); } break; diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h index ee7fcf43e01..5ff52b55b1a 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h @@ -4,7 +4,7 @@ * * High-level Type 1 driver interface (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h b/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h index 2fbd1e513f3..8aeb24ae188 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h @@ -4,7 +4,7 @@ * * Type 1 error codes (specification only). * - * Copyright (C) 2001-2023 by + * Copyright (C) 2001-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c index a32a4649d6d..c29e682510c 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c @@ -4,7 +4,7 @@ * * Type 1 Glyph Loader (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h index c06484758a5..17a6a5941e3 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h @@ -4,7 +4,7 @@ * * Type 1 Glyph Loader (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1load.c b/src/java.desktop/share/native/libfreetype/src/type1/t1load.c index be7cd0fd5e9..ee7fb42a517 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1load.c +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1load.c @@ -4,7 +4,7 @@ * * Type 1 font loader (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -751,6 +751,7 @@ PS_DesignMap dmap = blend->design_map + n; + FT_FREE( dmap->blend_points ); FT_FREE( dmap->design_points ); dmap->num_points = 0; } @@ -1043,9 +1044,9 @@ } /* allocate design map data */ - if ( FT_QNEW_ARRAY( map->design_points, num_points * 2 ) ) + if ( FT_QNEW_ARRAY( map->design_points, num_points ) || + FT_QNEW_ARRAY( map->blend_points, num_points ) ) goto Exit; - map->blend_points = map->design_points + num_points; map->num_points = (FT_Byte)num_points; for ( p = 0; p < num_points; p++ ) @@ -1876,9 +1877,8 @@ } /* t1_decrypt() shouldn't write to base -- make temporary copy */ - if ( FT_QALLOC( temp, size ) ) + if ( FT_DUP( temp, base, size ) ) goto Fail; - FT_MEM_COPY( temp, base, size ); psaux->t1_decrypt( temp, size, 4330 ); size -= (FT_ULong)t1face->type1.private_dict.lenIV; error = T1_Add_Table( table, @@ -2090,9 +2090,8 @@ } /* t1_decrypt() shouldn't write to base -- make temporary copy */ - if ( FT_QALLOC( temp, size ) ) + if ( FT_DUP( temp, base, size ) ) goto Fail; - FT_MEM_COPY( temp, base, size ); psaux->t1_decrypt( temp, size, 4330 ); size -= (FT_ULong)t1face->type1.private_dict.lenIV; error = T1_Add_Table( code_table, @@ -2284,7 +2283,7 @@ T1_FIELD_DICT_PRIVATE ) #endif - { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 } + T1_FIELD_ZERO }; @@ -2392,18 +2391,13 @@ T1_Field keyword = (T1_Field)t1_keywords; - for (;;) + while ( keyword->len ) { - FT_Byte* name; + FT_Byte* name = (FT_Byte*)keyword->ident; - name = (FT_Byte*)keyword->ident; - if ( !name ) - break; - - if ( cur[0] == name[0] && - len == ft_strlen( (const char *)name ) && - ft_memcmp( cur, name, len ) == 0 ) + if ( keyword->len == len && + ft_memcmp( cur, name, len ) == 0 ) { /* We found it -- run the parsing callback! */ /* We record every instance of every field */ diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1load.h b/src/java.desktop/share/native/libfreetype/src/type1/t1load.h index d8c9d2d8abe..a45efa7cb7b 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1load.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1load.h @@ -4,7 +4,7 @@ * * Type 1 font loader (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c index 69e4fd5065e..b1b27c31fe3 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c @@ -4,7 +4,7 @@ * * Type 1 objects manager (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h index 03847b27e96..3809370c1e0 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h @@ -4,7 +4,7 @@ * * Type 1 objects manager (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c index 6dec6c16c3e..3717ea7c572 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c @@ -4,7 +4,7 @@ * * Type 1 parser (body). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h index 0d9a2865df0..a0a2134d45c 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h @@ -4,7 +4,7 @@ * * Type 1 parser (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h b/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h index 40f36092622..5a3d2f1ef08 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h @@ -4,7 +4,7 @@ * * Type 1 tokenizer (specification). * - * Copyright (C) 1996-2023 by + * Copyright (C) 1996-2024 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java index b17b4c45644..39ecb13c6a4 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java +++ b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,6 +72,15 @@ public final class X11GraphicsDevice extends GraphicsDevice private boolean shutdownHookRegistered; private int scale; + // Wayland clients are by design not allowed to change the resolution in Wayland. + // XRandR in Xwayland is just an emulation, it doesn't actually change the resolution. + // This emulation is per window/x11 client, so different clients can have + // different emulated resolutions at the same time. + // So any request to get the current display mode will always return + // the original screen resolution, even if we are in emulated resolution. + // To handle this situation, we store the last set display mode in this variable. + private volatile DisplayMode xwlCurrentDisplayMode; + public X11GraphicsDevice(int screennum) { this.screen = screennum; this.scale = initScaleFactor(); @@ -117,6 +126,20 @@ public int scaleDown(int x) { private Rectangle getBoundsImpl() { Rectangle rect = pGetBounds(getScreen()); + + if (XToolkit.isOnWayland() && xwlCurrentDisplayMode != null) { + // XRandR resolution change in Xwayland is an emulation, + // and implemented in such a way that multiple display modes + // for a device are only available in a single screen scenario, + // if we have multiple screens they will each have a single display mode + // (no emulated resolution change is available). + // So we don't have to worry about x and y for a screen here. + rect.setSize( + xwlCurrentDisplayMode.getWidth(), + xwlCurrentDisplayMode.getHeight() + ); + } + if (getScaleFactor() != 1) { rect.x = scaleDown(rect.x); rect.y = scaleDown(rect.y); @@ -400,10 +423,19 @@ private DisplayMode getDefaultDisplayMode() { @Override public synchronized DisplayMode getDisplayMode() { if (isFullScreenSupported()) { + if (XToolkit.isOnWayland() && xwlCurrentDisplayMode != null) { + return xwlCurrentDisplayMode; + } + DisplayMode mode = getCurrentDisplayMode(screen); if (mode == null) { mode = getDefaultDisplayMode(); } + + if (XToolkit.isOnWayland()) { + xwlCurrentDisplayMode = mode; + } + return mode; } else { if (origDisplayMode == null) { @@ -474,6 +506,10 @@ public synchronized void setDisplayMode(DisplayMode dm) { dm.getWidth(), dm.getHeight(), dm.getRefreshRate()); + if (XToolkit.isOnWayland()) { + xwlCurrentDisplayMode = dm; + } + // update bounds of the fullscreen window w.setBounds(0, 0, dm.getWidth(), dm.getHeight()); diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java index 0695894f300..636d8f5fe2b 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, 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 @@ -1227,7 +1227,6 @@ protected NamingEnumeration<Binding> c_listBindings(Name name, Continuation cont // process the referrals sequentially while (true) { - @SuppressWarnings("unchecked") LdapReferralContext refCtx = (LdapReferralContext)e.getReferralContext(envprops, bindCtls); @@ -1886,7 +1885,6 @@ NamingEnumeration<SearchResult> searchAux(Name name, // process the referrals sequentially while (true) { - @SuppressWarnings("unchecked") LdapReferralContext refCtx = (LdapReferralContext) e.getReferralContext(envprops, bindCtls); diff --git a/src/java.naming/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java b/src/java.naming/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java index 1a6d930460e..aa63bd1a738 100644 --- a/src/java.naming/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java +++ b/src/java.naming/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,7 +96,6 @@ public Continuation() { * @param environment The environment used by the caller. It is used * when setting the "environment" of a CannotProceedException. */ - @SuppressWarnings("unchecked") // For Hashtable clone: environment.clone() public Continuation(Name top, Hashtable<?,?> environment) { super(); starter = top; diff --git a/src/java.naming/share/classes/javax/naming/Name.java b/src/java.naming/share/classes/javax/naming/Name.java index 24865fb64e4..b4466a02f2f 100644 --- a/src/java.naming/share/classes/javax/naming/Name.java +++ b/src/java.naming/share/classes/javax/naming/Name.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, 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 @@ -68,7 +68,6 @@ public interface Name * ineffectual. Do not use; no replacement. */ @Deprecated - @SuppressWarnings("serial") static final long serialVersionUID = -3617482732056931635L; /** diff --git a/src/java.naming/share/classes/javax/naming/directory/Attribute.java b/src/java.naming/share/classes/javax/naming/directory/Attribute.java index 4a0b51ba812..f1bd438457a 100644 --- a/src/java.naming/share/classes/javax/naming/directory/Attribute.java +++ b/src/java.naming/share/classes/javax/naming/directory/Attribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, 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 @@ -340,6 +340,5 @@ public interface Attribute extends Cloneable, java.io.Serializable { * ineffectual. Do not use; no replacement. */ @Deprecated - @SuppressWarnings("serial") static final long serialVersionUID = 8707690322213556804L; } diff --git a/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java b/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java index 4f75f434745..681abec46c3 100644 --- a/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java +++ b/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,6 @@ private static void loadPrefsLib() { /** * Sync interval in seconds. */ - @SuppressWarnings("removal") private static final int SYNC_INTERVAL = Math.max(1, Integer.getInteger("java.util.prefs.syncInterval", 30)); diff --git a/src/java.rmi/share/classes/java/rmi/server/RemoteRef.java b/src/java.rmi/share/classes/java/rmi/server/RemoteRef.java index 57201cd8dc3..a32f56dabc1 100644 --- a/src/java.rmi/share/classes/java/rmi/server/RemoteRef.java +++ b/src/java.rmi/share/classes/java/rmi/server/RemoteRef.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,6 @@ public interface RemoteRef extends java.io.Externalizable { * ineffectual. Do not use; no replacement. */ @Deprecated - @SuppressWarnings("serial") static final long serialVersionUID = 3632638527362204081L; /** diff --git a/src/java.rmi/share/classes/java/rmi/server/ServerRef.java b/src/java.rmi/share/classes/java/rmi/server/ServerRef.java index 1562f67fe7a..9ffb208640a 100644 --- a/src/java.rmi/share/classes/java/rmi/server/ServerRef.java +++ b/src/java.rmi/share/classes/java/rmi/server/ServerRef.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,6 @@ public interface ServerRef extends RemoteRef { * ineffectual. Do not use; no replacement. */ @Deprecated - @SuppressWarnings("serial") static final long serialVersionUID = -4557750989390278438L; /** diff --git a/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl_Skel.java b/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl_Skel.java index 22cfee5e0a7..95b94c57e1c 100644 --- a/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl_Skel.java +++ b/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl_Skel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * Skeleton to dispatch RegistryImpl methods. * Originally generated by RMIC but frozen to match the stubs. */ -@SuppressWarnings({"deprecation", "serial"}) +@SuppressWarnings("deprecation") public final class RegistryImpl_Skel implements java.rmi.server.Skeleton { private static final java.rmi.server.Operation[] operations = { diff --git a/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl_Skel.java b/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl_Skel.java index 1b413cffc19..20485dcd1e3 100644 --- a/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl_Skel.java +++ b/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl_Skel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, 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,7 +31,7 @@ * Skeleton to dispatch DGC methods. * Originally generated by RMIC but frozen to match the stubs. */ -@SuppressWarnings({"deprecation", "serial"}) +@SuppressWarnings("deprecation") public final class DGCImpl_Skel implements java.rmi.server.Skeleton { private static final java.rmi.server.Operation[] operations = { diff --git a/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java b/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java index 9cc7a5b2da8..9bc730569cd 100644 --- a/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java +++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -318,7 +318,6 @@ public static synchronized void unregisterProvider(String providerID) private static String colon = ":"; private static String strFileSep = "/"; - @SuppressWarnings("removal") private static synchronized void initMapIfNecessary() throws SyncFactoryException { // Local implementation class names and keys from Properties diff --git a/src/java.sql/share/classes/java/sql/Date.java b/src/java.sql/share/classes/java/sql/Date.java index c1d4fed3023..56d138afdce 100644 --- a/src/java.sql/share/classes/java/sql/Date.java +++ b/src/java.sql/share/classes/java/sql/Date.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, 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 @@ -286,7 +286,6 @@ public void setSeconds(int i) { * @throws NullPointerException if {@code date} is null * @since 1.8 */ - @SuppressWarnings("deprecation") public static Date valueOf(LocalDate date) { return new Date(date.getYear() - 1900, date.getMonthValue() -1, date.getDayOfMonth()); diff --git a/src/java.sql/share/classes/java/sql/Time.java b/src/java.sql/share/classes/java/sql/Time.java index 32df3644354..802a7433162 100644 --- a/src/java.sql/share/classes/java/sql/Time.java +++ b/src/java.sql/share/classes/java/sql/Time.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -249,7 +249,6 @@ public void setDate(int i) { * @throws NullPointerException if {@code time} is null * @since 1.8 */ - @SuppressWarnings("deprecation") public static Time valueOf(LocalTime time) { return new Time(time.getHour(), time.getMinute(), time.getSecond()); } diff --git a/src/java.sql/share/classes/java/sql/Timestamp.java b/src/java.sql/share/classes/java/sql/Timestamp.java index 8fb85f73c7e..a91ab7210c5 100644 --- a/src/java.sql/share/classes/java/sql/Timestamp.java +++ b/src/java.sql/share/classes/java/sql/Timestamp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, 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 @@ -493,7 +493,6 @@ public int hashCode() { * @throws NullPointerException if {@code dateTime} is null. * @since 1.8 */ - @SuppressWarnings("deprecation") public static Timestamp valueOf(LocalDateTime dateTime) { return new Timestamp(dateTime.getYear() - 1900, dateTime.getMonthValue() - 1, diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/NodeSortRecord.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/NodeSortRecord.java index 83071b62347..bd0b0355ee6 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/NodeSortRecord.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/NodeSortRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -30,7 +30,7 @@ /** * Base class for sort records containing application specific sort keys * - * @LastModified: May 2019 + * @LastModified: Jan 2025 */ public abstract class NodeSortRecord { public static final int COMPARE_STRING = 0; @@ -127,7 +127,7 @@ public final int compareDocOrder(NodeSortRecord other) { * element. The value is extracted from the DOM if it is not already in * our sort key vector. */ - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings("rawtypes") private final Comparable stringValue(int level) { // Get value from our array if possible if (_scanned <= level) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/SAX2StAXEventWriter.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/SAX2StAXEventWriter.java index fbe41a17028..a34f4fe3e8a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/SAX2StAXEventWriter.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/SAX2StAXEventWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -250,7 +250,7 @@ public void endCDATA() throws SAXException { super.endCDATA(); } - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings("unchecked") protected void createStartEvents(Attributes attributes, Collection<Attribute>[] events) { Map<String, Attribute> nsMap = null; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/StAXStream2SAX.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/StAXStream2SAX.java index 4667226f1bc..6746ede9d9b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/StAXStream2SAX.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/StAXStream2SAX.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -275,32 +275,18 @@ private void handlePI() throws XMLStreamException { } private void handleCharacters() throws XMLStreamException { - - // workaround for bugid 5046319 - switch over to commented section - // below when it is fixed. int textLength = staxStreamReader.getTextLength(); char[] chars = new char[textLength]; - staxStreamReader.getTextCharacters(0, chars, 0, textLength); + if (textLength > 0) { + staxStreamReader.getTextCharacters(0, chars, 0, textLength); + } try { _sax.characters(chars, 0, chars.length); } catch (SAXException e) { throw new XMLStreamException(e); } - - -// int start = 0; -// int len; -// do { -// len = staxStreamReader.getTextCharacters(start, buf, 0, buf.length); -// start += len; -// try { -// _sax.characters(buf, 0, len); -// } catch (SAXException e) { -// throw new XMLStreamException(e); -// } -// } while (len == buf.length); } private void handleEndElement() throws XMLStreamException { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java index f167cf78d5a..24f10e69853 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -65,7 +65,7 @@ * @author G. Todd Millerj * @author Jochen Cordes <Jochen.Cordes@t-online.de> * @author Santiago Pericas-Geertsen - * @LastModified: Nov 2024 + * @LastModified: Jan 2025 */ public final class TemplatesImpl implements Templates, Serializable { static final long serialVersionUID = 673094361519270707L; @@ -255,7 +255,6 @@ public TemplatesImpl() { } * if yes then we need to deserialize the URIResolver * Fix for bugzilla bug 22438 */ - @SuppressWarnings("unchecked") private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TrAXFilter.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TrAXFilter.java index 95c8540ca28..2cecf112bd3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TrAXFilter.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TrAXFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -43,9 +43,8 @@ * @author Santiago Pericas-Geertsen * @author G. Todd Miller * - * @LastModified: July 2023 + * @LastModified: Jan 2025 */ -@SuppressWarnings("deprecation") //org.xml.sax.helpers.XMLReaderFactory public class TrAXFilter extends XMLFilterImpl { private Templates _templates; private TransformerImpl _transformer; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java index 32eaec026bf..b48b9d2a657 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -100,7 +100,7 @@ * @author Morten Jorgensen * @author G. Todd Miller * @author Santiago Pericas-Geertsen - * @LastModified: Dec 2024 + * @LastModified: Jan 2025 */ public final class TransformerImpl extends Transformer implements DOMCache @@ -1355,7 +1355,6 @@ public DOM retrieveDocument(String baseURI, String href, Translet translet) { * Performs the access check without any interface changes * (e.g. Translet and DOMCache). */ - @SuppressWarnings("unchecked") //AbstractTranslet is the sole impl. AbstractTranslet t = (AbstractTranslet)translet; String systemId = SystemIDResolver.getAbsoluteURI(href, baseURI); String errMsg = null; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java index b4dd0ef6b97..fe685dcf5a6 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -50,9 +50,8 @@ * * Added Catalog Support for URI resolution * - * @LastModified: Nov 2024 + * @LastModified: Jan 2025 */ -@SuppressWarnings("deprecation") //org.xml.sax.helpers.XMLReaderFactory public final class Util { private static final String property = "org.xml.sax.driver"; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DocumentImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DocumentImpl.java index 9b7938ca5b2..decd9943850 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DocumentImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DocumentImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -84,7 +84,7 @@ * @author Andy Clark, IBM * @author Ralf Pfeiffer, IBM * @since PR-DOM-Level-1-19980818. - * @LastModified: Nov 2017 + * @LastModified: Jan 2025 */ public class DocumentImpl extends CoreDocumentImpl @@ -681,7 +681,7 @@ protected void copyEventListeners(NodeImpl src, NodeImpl tgt) { * method was invoked by an EventListener; otherwise false. */ @Override - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings("unchecked") protected boolean dispatchEvent(NodeImpl node, Event event) { if (event == null) return false; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/NamedNodeMapImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/NamedNodeMapImpl.java index a2b3e3269a5..c95dfd2fd87 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/NamedNodeMapImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/NamedNodeMapImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -56,7 +56,7 @@ * @xerces.internal * * @since PR-DOM-Level-1-19980818. - * @LastModified: June 2022 + * @LastModified: Jan 2025 */ public class NamedNodeMapImpl implements NamedNodeMap, Serializable { @@ -596,7 +596,6 @@ public void removeAll (){ } } - @SuppressWarnings("unchecked") private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java index bd11ac73c60..9ebaf895c5c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -131,9 +131,8 @@ * @author Neil Graham, IBM * @author Pavani Mukthipudi, Sun Microsystems * - * @LastModified: July 2023 + * @LastModified: Jan 2025 */ -@SuppressWarnings("deprecation") //org.xml.sax.helpers.XMLReaderFactory public class XSDHandler { /** Feature identifier: validation. */ @@ -2768,7 +2767,6 @@ private void addNewGrammarLocations(SchemaGrammar srcGrammar, SchemaGrammar dstG } } - @SuppressWarnings("unchecked") private void addNewImportedGrammars(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { final ArrayList<SchemaGrammar> src = (ArrayList<SchemaGrammar>)srcGrammar.getImportedGrammars(); if (src != null) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/StringComparable.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/StringComparable.java index db6fe80824a..1b950591bac 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/StringComparable.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/StringComparable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -29,7 +29,7 @@ /** * International friendly string comparison with case-order * @author Igor Hersht, igorh@ca.ibm.com - * @LastModified: Oct 2017 + * @LastModified: Jan 2025 */ public class StringComparable implements Comparable<StringComparable> { @@ -52,7 +52,7 @@ public StringComparable(final String text, final Locale locale, m_mask = getMask(m_collator.getStrength()); } - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings("rawtypes") public final static Comparable getComparator( final String text, final Locale locale, final Collator collator, final String caseOrder){ if((caseOrder == null) ||(caseOrder.length() == 0)){// no case-order specified diff --git a/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java b/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java index 1305beeceaa..0cee5cfa41d 100644 --- a/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java +++ b/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,7 +84,6 @@ class CatalogReader extends DefaultHandler implements EntityResolver, URIResolve * * @param catalog The Catalog object that represents a catalog */ - @SuppressWarnings("unchecked") public CatalogReader(Catalog catalog, SAXParser parser) { this.catalog = (CatalogImpl) catalog; this.parser = parser; diff --git a/src/jdk.hotspot.agent/doc/cireplay.html b/src/jdk.hotspot.agent/doc/cireplay.html deleted file mode 100644 index 71da428e58e..00000000000 --- a/src/jdk.hotspot.agent/doc/cireplay.html +++ /dev/null @@ -1,41 +0,0 @@ -<html> -<head> -<title> -Replay -</title> -</head> -<body> - -<h1>Compiler replay</h1> -<p> -The compiler replay is a function to repeat the compiling process from a crashed java process in compiled method<br> -This function only exists in debug version of VM -</p> -<h2>Usage</h2> -<pre> -First, use SA to attach to the core file, if succeeded, do - hsdb> dumpreplaydata <address> | -a | <thread_id> [> replay.txt] - create file replay.txt, address is address of Method, or nmethod(CodeBlob) - hsdb> buildreplayjars [all | boot | app] - create files: - all: - app.jar, boot.jar - boot: - boot.jar - app: - app.jar - exit SA now. -Second, use the obtained replay text file, replay.txt and jar files, app.jar and boot.jar, using debug version of java - java -Xbootclasspath/p:boot.jar -cp app.jar -XX:ReplayDataFile=<datafile> -XX:+ReplayCompiles .... - This will replay the compiling process. - - With ReplayCompiles, the replay will recompile all the methods in app.jar, and in boot.jar to emulate the process in java app. - -notes: - 1) Most time, we don't need the boot.jar which is the classes loaded from JDK. It will be only modified when an agent(JVMDI) is running and modifies the classes. - 2) If encounter error as "<flag>" not found, that means the SA is using a VMStructs which is different from the one with corefile. In this case, SA has a utility tool vmstructsdump which is located at agent/src/os/<os>/proc/<os_platform> - - Use this tool to dump VM type library: - vmstructsdump libjvm.so > <type_name>.db - - set env SA_TYPEDB=<type_name>.db (refer different shell for set envs) diff --git a/src/jdk.hotspot.agent/doc/clhsdb.html b/src/jdk.hotspot.agent/doc/clhsdb.html index 69fd228a52e..a225530774f 100644 --- a/src/jdk.hotspot.agent/doc/clhsdb.html +++ b/src/jdk.hotspot.agent/doc/clhsdb.html @@ -38,9 +38,6 @@ <h3>Annotated output of CLHSDB help command</h3> dumpclass { address | name } [ directory ] <font color="red">dump .class file for given Klass* or class name</font> dumpcodecache <font color="red">dump codecache contents</font> dumpheap [ file ] <font color="red">dump heap in hprof binary format</font> - dumpideal -a | id <font color="red">dump ideal graph like debug flag -XX:+PrintIdeal</font> - dumpilt -a | id <font color="red">dump inline tree for C2 compilation</font> - dumpreplaydata <address> | -a | <thread_id> [>replay.txt] <font color="red">dump replay data into a file</font> echo [ true | false ] <font color="red">turn on/off command echo mode</font> examine { address[/count] | address,address } <font color="red">show contents of memory range</font> field [ type [ name fieldtype isStatic offset address ] ] <font color="red">print info about a field of HotSpot type</font> @@ -84,11 +81,5 @@ <h3>Annotated output of CLHSDB help command</h3> </code> </pre> -<h3>Compilation Replay</h3> -<p> -When a java process crashes in compiled method, usually a core file is saved. -The replay function can reproduce the compiling process in the core. -<a href="cireplay.html">cireplay.html</a> - </body> </html> diff --git a/src/jdk.hotspot.agent/doc/index.html b/src/jdk.hotspot.agent/doc/index.html index 2e3ba38e4b8..0ce8cd45970 100644 --- a/src/jdk.hotspot.agent/doc/index.html +++ b/src/jdk.hotspot.agent/doc/index.html @@ -40,12 +40,6 @@ <h3>Command line HSDB</h3> </ul> </p> -<h3>Compilation Replay</h3> -<p> -When a java process crashes in a compiled method, usually a core file is saved. -The compiler replay function can reproduce the compiling process in the core. -See <a href="cireplay.html">cireplay.html</a> - <h3>Debugging transported core dumps</h3> <p> When a core dump is moved from the machine where it was produced to a diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java index 79709cce132..01b9a4a447e 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import sun.jvm.hotspot.ci.ciEnv; import sun.jvm.hotspot.code.CodeBlob; import sun.jvm.hotspot.code.CodeCacheVisitor; import sun.jvm.hotspot.code.NMethod; @@ -66,8 +65,6 @@ import sun.jvm.hotspot.oops.RawHeapVisitor; import sun.jvm.hotspot.oops.Symbol; import sun.jvm.hotspot.oops.UnknownOopException; -import sun.jvm.hotspot.opto.Compile; -import sun.jvm.hotspot.opto.InlineTree; import sun.jvm.hotspot.runtime.CompiledVFrame; import sun.jvm.hotspot.runtime.CompilerThread; import sun.jvm.hotspot.runtime.JavaThread; @@ -562,57 +559,6 @@ public void doit(Tokens t) { } } }, - new Command("dumpreplaydata", "dumpreplaydata { <address > | -a | <thread_id> }", false) { - // This is used to dump replay data from ciInstanceKlass, ciMethodData etc - // default file name is replay.txt, also if java crashes in compiler - // thread, this file will be dumped in error processing. - public void doit(Tokens t) { - if (t.countTokens() != 1) { - usage(); - return; - } - String name = t.nextToken(); - Address a = null; - try { - a = VM.getVM().getDebugger().parseAddress(name); - } catch (NumberFormatException e) { } - if (a != null) { - // only nmethod, Method, MethodData and InstanceKlass needed to - // dump replay data - - CodeBlob cb = VM.getVM().getCodeCache().findBlob(a); - if (cb instanceof NMethod nMethod) { - nMethod.dumpReplayData(out); - return; - } - // assume it is Metadata - Metadata meta = Metadata.instantiateWrapperFor(a); - if (meta != null) { - meta.dumpReplayData(out); - } else { - usage(); - return; - } - } - // Not an address - boolean all = name.equals("-a"); - Threads threads = VM.getVM().getThreads(); - for (int i = 0; i < threads.getNumberOfThreads(); i++) { - JavaThread thread = threads.getJavaThreadAt(i); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - thread.printThreadIDOn(new PrintStream(bos)); - if (all || bos.toString().equals(name)) { - if (thread instanceof CompilerThread) { - CompilerThread ct = (CompilerThread)thread; - ciEnv env = ct.env(); - if (env != null) { - env.dumpReplayData(out); - } - } - } - } - } - }, new Command("buildreplayjars", "buildreplayjars [ all | app | boot ] | [ prefix ]", false) { // This is used to dump jar files of all the classes // loaded in the core. Everything with null classloader @@ -973,94 +919,6 @@ public void visit(Klass k) { } } }, - new Command("dumpideal", "dumpideal { -a | id }", false) { - // Do a full dump of the nodes reachable from root in each compiler thread. - public void doit(Tokens t) { - if (t.countTokens() != 1) { - usage(); - } else { - String name = t.nextToken(); - boolean all = name.equals("-a"); - Threads threads = VM.getVM().getThreads(); - for (int i = 0; i < threads.getNumberOfThreads(); i++) { - JavaThread thread = threads.getJavaThreadAt(i); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - thread.printThreadIDOn(new PrintStream(bos)); - if (all || bos.toString().equals(name)) { - if (thread instanceof CompilerThread) { - CompilerThread ct = (CompilerThread)thread; - out.println(ct); - ciEnv env = ct.env(); - if (env != null) { - Compile c = env.compilerData(); - c.root().dump(9999, out); - } else { - out.println(" not compiling"); - } - } - } - } - } - } - }, - new Command("dumpcfg", "dumpcfg { -a | id }", false) { - // Dump the PhaseCFG for every compiler thread that has one live. - public void doit(Tokens t) { - if (t.countTokens() != 1) { - usage(); - } else { - String name = t.nextToken(); - boolean all = name.equals("-a"); - Threads threads = VM.getVM().getThreads(); - for (int i = 0; i < threads.getNumberOfThreads(); i++) { - JavaThread thread = threads.getJavaThreadAt(i); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - thread.printThreadIDOn(new PrintStream(bos)); - if (all || bos.toString().equals(name)) { - if (thread instanceof CompilerThread) { - CompilerThread ct = (CompilerThread)thread; - out.println(ct); - ciEnv env = ct.env(); - if (env != null) { - Compile c = env.compilerData(); - c.cfg().dump(out); - } - } - } - } - } - } - }, - new Command("dumpilt", "dumpilt { -a | id }", false) { - // dumps the InlineTree of a C2 compile - public void doit(Tokens t) { - if (t.countTokens() != 1) { - usage(); - } else { - String name = t.nextToken(); - boolean all = name.equals("-a"); - Threads threads = VM.getVM().getThreads(); - for (int i = 0; i < threads.getNumberOfThreads(); i++) { - JavaThread thread = threads.getJavaThreadAt(i); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - thread.printThreadIDOn(new PrintStream(bos)); - if (all || bos.toString().equals(name)) { - if (thread instanceof CompilerThread) { - CompilerThread ct = (CompilerThread)thread; - ciEnv env = ct.env(); - if (env != null) { - Compile c = env.compilerData(); - InlineTree ilt = c.ilt(); - if (ilt != null) { - ilt.print(out); - } - } - } - } - } - } - } - }, new Command("vmstructsdump", "vmstructsdump", false) { public void doit(Tokens t) { if (t.countTokens() != 0) { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/c1/Runtime1.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/c1/Runtime1.java deleted file mode 100644 index b26e42ebfdf..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/c1/Runtime1.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.c1; - -import java.util.*; -import sun.jvm.hotspot.code.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -/** Currently a minimal port to get C1 frame traversal working */ - -public class Runtime1 { - private static Field blobsField; - - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("Runtime1"); - - blobsField = type.getField("_blobs"); - } - - public Runtime1() { - } - - /** FIXME: consider making argument "type-safe" in Java port */ - public Address entryFor(int id) { - return blobFor(id).codeBegin(); - } - - /** FIXME: consider making argument "type-safe" in Java port */ - public CodeBlob blobFor(int id) { - Address blobAddr = blobsField.getStaticFieldAddress().getAddressAt(id * VM.getVM().getAddressSize()); - return VM.getVM().getCodeCache().createCodeBlobWrapper(blobAddr, blobAddr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciArrayKlass.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciArrayKlass.java deleted file mode 100644 index c0421c39b25..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciArrayKlass.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.io.PrintStream; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciArrayKlass extends ciKlass { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciArrayKlass"); - dimensionField = new IntField(type.getJIntField("_dimension"), 0); - } - - private static IntField dimensionField; - - public ciArrayKlass(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciBaseObject.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciBaseObject.java deleted file mode 100644 index c3de39a705a..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciBaseObject.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.io.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciBaseObject extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciBaseObject"); - identField = new CIntField(type.getCIntegerField("_ident"), 0); - } - - private static CIntField identField; - - public ciBaseObject(Address addr) { - super(addr); - } - - public void dumpReplayData(PrintStream out) { - out.println("# Unknown ci type " + getAddress().getAddressAt(0)); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciConstant.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciConstant.java deleted file mode 100644 index 24029bdd031..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciConstant.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.io.PrintStream; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciConstant extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciConstant"); - valueObjectField = type.getAddressField("_value._object"); - valueDoubleField = type.getJDoubleField("_value._double"); - valueFloatField = type.getJFloatField("_value._float"); - valueLongField = type.getJLongField("_value._long"); - valueIntField = type.getJIntField("_value._int"); - typeField = new CIntField(type.getCIntegerField("_type"), 0); - } - - private static AddressField valueObjectField; - private static JDoubleField valueDoubleField; - private static JFloatField valueFloatField; - private static JLongField valueLongField; - private static JIntField valueIntField; - private static CIntField typeField; - - public ciConstant(Address addr) { - super(addr); - } - - public void dumpReplayData(PrintStream out) { - // Nothing to be done - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciEnv.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciEnv.java deleted file mode 100644 index 9e5aa030046..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciEnv.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.io.PrintStream; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.opto.*; -import sun.jvm.hotspot.compiler.CompileTask; -import sun.jvm.hotspot.prims.JvmtiExport; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.GrowableArray; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciEnv extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciEnv"); - dependenciesField = type.getAddressField("_dependencies"); - factoryField = type.getAddressField("_factory"); - compilerDataField = type.getAddressField("_compiler_data"); - taskField = type.getAddressField("_task"); - } - - private static AddressField dependenciesField; - private static AddressField factoryField; - private static AddressField compilerDataField; - private static AddressField taskField; - - public ciEnv(Address addr) { - super(addr); - } - - public Compile compilerData() { - Address addr = compilerDataField.getValue(this.getAddress()); - if (addr == null) { - return null; - } - return new Compile(addr); - } - - public ciObjectFactory factory() { - return new ciObjectFactory(factoryField.getValue(this.getAddress())); - } - - public CompileTask task() { - return new CompileTask(taskField.getValue(this.getAddress())); - } - - public void dumpReplayData(PrintStream out) { - out.println("JvmtiExport can_access_local_variables " + - (JvmtiExport.canAccessLocalVariables() ? '1' : '0')); - out.println("JvmtiExport can_hotswap_or_post_breakpoint " + - (JvmtiExport.canHotswapOrPostBreakpoint() ? '1' : '0')); - out.println("JvmtiExport can_post_on_exceptions " + - (JvmtiExport.canPostOnExceptions() ? '1' : '0')); - - GrowableArray<ciMetadata> objects = factory().objects(); - out.println("# " + objects.length() + " ciObject found"); - for (int i = 0; i < objects.length(); i++) { - ciMetadata o = objects.at(i); - out.println("# ciMetadata" + i + " @ " + o); - o.dumpReplayData(out); - } - CompileTask task = task(); - Method method = task.method(); - int entryBci = task.osrBci(); - int compLevel = task.compLevel(); - out.print("compile " + method.nameAsAscii() + " " + - entryBci + " " + compLevel); - Compile compiler = compilerData(); - if (compiler != null) { - // Dump inlining data. - compiler.dumpInlineData(out); - } - out.println(); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciField.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciField.java deleted file mode 100644 index 9c96e20c0ad..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciField.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciField extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciField"); - constantValueField = type.getAddressField("_constant_value"); - isConstantField = type.getAddressField("_is_constant"); - offsetField = new CIntField(type.getCIntegerField("_offset"), 0); - signatureField = type.getAddressField("_signature"); - nameField = type.getAddressField("_name"); - holderField = type.getAddressField("_holder"); - } - - private static AddressField constantValueField; - private static AddressField isConstantField; - private static CIntField offsetField; - private static AddressField signatureField; - private static AddressField nameField; - private static AddressField holderField; - - public ciField(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciInstance.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciInstance.java deleted file mode 100644 index dcf69cacdbb..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciInstance.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.io.PrintStream; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciInstance extends ciObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciInstance"); - } - - - public ciInstance(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciInstanceKlass.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciInstanceKlass.java deleted file mode 100644 index febf476e6a6..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciInstanceKlass.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.io.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.memory.SystemDictionary; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.Type; -import sun.jvm.hotspot.types.TypeDataBase; -import sun.jvm.hotspot.types.WrongTypeException; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciInstanceKlass extends ciKlass { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciInstanceKlass"); - initStateField = new CIntField(type.getCIntegerField("_init_state"), 0); - isSharedField = new CIntField(type.getCIntegerField("_is_shared"), 0); - CLASS_STATE_LINKED = db.lookupIntConstant("InstanceKlass::linked").intValue(); - CLASS_STATE_FULLY_INITIALIZED = db.lookupIntConstant("InstanceKlass::fully_initialized").intValue(); - } - - private static CIntField initStateField; - private static CIntField isSharedField; - private static int CLASS_STATE_LINKED; - private static int CLASS_STATE_FULLY_INITIALIZED; - - public ciInstanceKlass(Address addr) { - super(addr); - } - - public int initState() { - int initState = (int)initStateField.getValue(getAddress()); - if (isShared() && initState < CLASS_STATE_LINKED) { - InstanceKlass ik = (InstanceKlass)getMetadata(); - initState = ik.getInitStateAsInt(); - } - return initState; - } - - public boolean isShared() { - return isSharedField.getValue(getAddress()) != 0; - } - - public boolean isLinked() { - return initState() >= CLASS_STATE_LINKED; - } - - public boolean isInitialized() { - return initState() == CLASS_STATE_FULLY_INITIALIZED; - } - - public void dumpReplayData(PrintStream out) { - InstanceKlass ik = (InstanceKlass)getMetadata(); - ConstantPool cp = ik.getConstants(); - - // Try to record related loaded classes - Klass sub = ik.getSubklassKlass(); - while (sub != null) { - if (sub instanceof InstanceKlass) { - out.println("instanceKlass " + sub.getName().asString()); - } - sub = sub.getNextSiblingKlass(); - } - - final int length = cp.getLength(); - out.print("ciInstanceKlass " + name() + " " + (isLinked() ? 1 : 0) + " " + (isInitialized() ? 1 : 0) + " " + length); - for (int index = 1; index < length; index++) { - out.print(" " + cp.getTags().at(index)); - } - out.println(); - if (isInitialized()) { - Field[] staticFields = ik.getStaticFields(); - for (int i = 0; i < staticFields.length; i++) { - Field f = staticFields[i]; - Oop mirror = ik.getJavaMirror(); - if (f.isFinal() && !f.hasInitialValue()) { - out.print("staticfield " + name() + " " + - OopUtilities.escapeString(f.getID().getName()) + " " + - f.getFieldType().getSignature().asString() + " "); - if (f instanceof ByteField) { - ByteField bf = (ByteField)f; - out.println(bf.getValue(mirror)); - } else if (f instanceof BooleanField) { - BooleanField bf = (BooleanField)f; - out.println(bf.getValue(mirror) ? 1 : 0); - } else if (f instanceof ShortField) { - ShortField bf = (ShortField)f; - out.println(bf.getValue(mirror)); - } else if (f instanceof CharField) { - CharField bf = (CharField)f; - out.println(bf.getValue(mirror) & 0xffff); - } else if (f instanceof IntField) { - IntField bf = (IntField)f; - out.println(bf.getValue(mirror)); - } else if (f instanceof LongField) { - LongField bf = (LongField)f; - out.println(bf.getValue(mirror)); - } else if (f instanceof FloatField) { - FloatField bf = (FloatField)f; - out.println(Float.floatToRawIntBits(bf.getValue(mirror))); - } else if (f instanceof DoubleField) { - DoubleField bf = (DoubleField)f; - out.println(Double.doubleToRawLongBits(bf.getValue(mirror))); - } else if (f instanceof OopField) { - OopField bf = (OopField)f; - Oop value = bf.getValue(mirror); - if (value == null) { - out.println("null"); - } else if (value.isInstance()) { - Instance inst = (Instance)value; - if (inst.isA(SystemDictionary.getStringKlass())) { - out.println("\"" + OopUtilities.stringOopToEscapedString(inst) + "\""); - } else { - out.println(inst.getKlass().getName().asString()); - } - } else if (value.isObjArray()) { - ObjArray oa = (ObjArray)value; - Klass ek = (ObjArrayKlass)oa.getKlass(); - out.println(oa.getLength() + " " + ek.getName().asString()); - } else if (value.isTypeArray()) { - TypeArray ta = (TypeArray)value; - out.println(ta.getLength()); - } else { - out.println(value); - } - } - } - } - } - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciKlass.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciKlass.java deleted file mode 100644 index 168486cecd9..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciKlass.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.io.PrintStream; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciKlass extends ciType { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciKlass"); - nameField = type.getAddressField("_name"); - } - - private static AddressField nameField; - - public String name() { - ciSymbol sym = new ciSymbol(nameField.getValue(getAddress())); - return sym.asUtf88(); - } - - public ciKlass(Address addr) { - super(addr); - } - - public void printValueOn(PrintStream tty) { - Klass k = (Klass)getMetadata(); - k.printValueOn(tty); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciMetadata.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciMetadata.java deleted file mode 100644 index e64ad9ef8f0..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciMetadata.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.io.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciMetadata extends ciBaseObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciMetadata"); - metadataField = new MetadataField(type.getAddressField("_metadata"), 0); - } - - private static MetadataField metadataField; - - public Metadata getMetadata() { - return metadataField.getValue(getAddress()); - } - - public ciMetadata(Address addr) { - super(addr); - } - - public void printOn(PrintStream out) { - getMetadata().printValueOn(out); - } - - public String toString() { - return getMetadata().toString(); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciMethod.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciMethod.java deleted file mode 100644 index 132c54d9ba0..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciMethod.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.io.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.code.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciMethod extends ciMetadata { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciMethod"); - interpreterThrowoutCountField = new CIntField(type.getCIntegerField("_interpreter_throwout_count"), 0); - interpreterInvocationCountField = new CIntField(type.getCIntegerField("_interpreter_invocation_count"), 0); - try { - // XXX - instructionsSizeField = new CIntField(type.getCIntegerField("_instructions_size"), 0); - } catch (Exception e) { - } - } - - private static CIntField interpreterThrowoutCountField; - private static CIntField interpreterInvocationCountField; - private static CIntField instructionsSizeField; - - public ciMethod(Address addr) { - super(addr); - } - - public Method method() { - return (Method)getMetadata(); - } - - public int interpreterThrowoutCount() { - return (int) interpreterThrowoutCountField.getValue(getAddress()); - } - - public int interpreterInvocationCount() { - return (int) interpreterInvocationCountField.getValue(getAddress()); - } - - public int instructionsSize() { - if (instructionsSizeField == null) { - // XXX - Method method = method(); - NMethod nm = method.getNativeMethod(); - if (nm != null) return (int)nm.codeEnd().minus(nm.getVerifiedEntryPoint()); - return 0; - } - return (int) instructionsSizeField.getValue(getAddress()); - } - - public void printShortName(PrintStream st) { - Method method = method(); - st.printf(" %s::%s", method.getMethodHolder().getName().asString().replace('/', '.'), - method.getName().asString()); - } - - public void dumpReplayData(PrintStream out) { - Method method = (Method)getMetadata(); - NMethod nm = method.getNativeMethod(); - out.println("ciMethod " + - nameAsAscii() + " " + - method.getInvocationCount() + " " + - method.getBackedgeCount() + " " + - interpreterInvocationCount() + " " + - interpreterThrowoutCount() + " " + - instructionsSize()); - } - - public void printValueOn(PrintStream tty) { - tty.print("ciMethod " + method().getName().asString() + method().getSignature().asString() + "@" + getAddress()); - } - - public String nameAsAscii() { - Method method = (Method)getMetadata(); - return method.nameAsAscii(); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciMethodData.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciMethodData.java deleted file mode 100644 index 237eb6227d9..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciMethodData.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.io.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.types.Field; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciMethodData extends ciMetadata implements MethodDataInterface<ciKlass,ciMethod> { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciMethodData"); - origField = type.getField("_orig"); - argReturnedField = new CIntField(type.getCIntegerField("_arg_returned"), 0); - argStackField = new CIntField(type.getCIntegerField("_arg_stack"), 0); - argLocalField = new CIntField(type.getCIntegerField("_arg_local"), 0); - eflagsField = new CIntField(type.getCIntegerField("_eflags"), 0); - hintDiField = new CIntField(type.getCIntegerField("_hint_di"), 0); - dataField = type.getAddressField("_data"); - extraDataSizeField = new CIntField(type.getCIntegerField("_extra_data_size"), 0); - dataSizeField = new CIntField(type.getCIntegerField("_data_size"), 0); - stateField = new CIntField(type.getCIntegerField("_state"), 0); - Type typeMethodData = db.lookupType("MethodData"); - sizeofMethodDataOopDesc = (int)typeMethodData.getSize(); - parametersTypeDataDi = new CIntField(typeMethodData.getCIntegerField("_parameters_type_data_di"), 0); - } - - private static Field origField; - private static CIntField argReturnedField; - private static CIntField argStackField; - private static CIntField argLocalField; - private static CIntField eflagsField; - private static CIntField hintDiField; - private static AddressField dataField; - private static CIntField extraDataSizeField; - private static CIntField dataSizeField; - private static CIntField stateField; - private static int sizeofMethodDataOopDesc; - private static CIntField parametersTypeDataDi; - - public ciMethodData(Address addr) { - super(addr); - } - - public ciKlass getKlassAtAddress(Address addr) { - return (ciKlass)ciObjectFactory.getMetadata(addr); - } - - public ciMethod getMethodAtAddress(Address addr) { - return (ciMethod)ciObjectFactory.getMetadata(addr); - } - - public void printKlassValueOn(ciKlass klass, PrintStream st) { - klass.printValueOn(st); - } - - public void printMethodValueOn(ciMethod method, PrintStream st) { - method.printValueOn(st); - } - - private byte[] fetchDataAt(Address base, long size) { - byte[] result = new byte[(int)size]; - for (int i = 0; i < size; i++) { - result[i] = base.getJByteAt(i); - } - return result; - } - - public byte[] orig() { - // fetch the orig MethodData data between header and dataSize - Address base = getAddress().addOffsetTo(origField.getOffset()); - byte[] result = new byte[(int)origField.getType().getSize()]; - for (int i = 0; i < result.length; i++) { - result[i] = base.getJByteAt(i); - } - return result; - } - - public long[] data() { - // Read the data as an array of intptr_t elements - Address base = dataField.getValue(getAddress()); - int elements = (dataSize() + extraDataSize()) / MethodData.cellSize; - long[] result = new long[elements]; - for (int i = 0; i < elements; i++) { - Address value = base.getAddressAt(i * MethodData.cellSize); - if (value != null) { - result[i] = value.minus(null); - } - } - return result; - } - - int dataSize() { - return (int)dataSizeField.getValue(getAddress()); - } - - int extraDataSize() { - return (int)extraDataSizeField.getValue(getAddress()); - } - - int state() { - return (int)stateField.getValue(getAddress()); - } - - int currentMileage() { - return 0; - } - - boolean outOfBounds(int dataIndex) { - return dataIndex >= dataSize(); - } - - ParametersTypeData<ciKlass,ciMethod> parametersTypeData() { - int di = (int)parametersTypeDataDi.getValue(getMetadata().getAddress()); - if (di == -1 || di == -2) { - return null; - } - DataLayout dataLayout = new DataLayout(dataField.getValue(getAddress()), di); - return new ParametersTypeData<ciKlass,ciMethod>(this, dataLayout); - } - - ProfileData dataAt(int dataIndex) { - if (outOfBounds(dataIndex)) { - return null; - } - DataLayout dataLayout = new DataLayout(dataField.getValue(getAddress()), dataIndex); - - switch (dataLayout.tag()) { - case DataLayout.noTag: - default: - throw new InternalError(); - case DataLayout.bitDataTag: - return new BitData(dataLayout); - case DataLayout.counterDataTag: - return new CounterData(dataLayout); - case DataLayout.jumpDataTag: - return new JumpData(dataLayout); - case DataLayout.receiverTypeDataTag: - return new ReceiverTypeData<ciKlass,ciMethod>(this, dataLayout); - case DataLayout.virtualCallDataTag: - return new VirtualCallData<ciKlass,ciMethod>(this, dataLayout); - case DataLayout.retDataTag: - return new RetData(dataLayout); - case DataLayout.branchDataTag: - return new BranchData(dataLayout); - case DataLayout.multiBranchDataTag: - return new MultiBranchData(dataLayout); - case DataLayout.callTypeDataTag: - return new CallTypeData<ciKlass,ciMethod>(this, dataLayout); - case DataLayout.virtualCallTypeDataTag: - return new VirtualCallTypeData<ciKlass,ciMethod>(this, dataLayout); - case DataLayout.parametersTypeDataTag: - return new ParametersTypeData<ciKlass,ciMethod>(this, dataLayout); - } - } - - int dpToDi(int dp) { - return dp; - } - - int firstDi() { return 0; } - ProfileData firstData() { return dataAt(firstDi()); } - ProfileData nextData(ProfileData current) { - int currentIndex = dpToDi(current.dp()); - int nextIndex = currentIndex + current.sizeInBytes(); - return dataAt(nextIndex); - } - boolean isValid(ProfileData current) { return current != null; } - - DataLayout limitDataPosition() { - return new DataLayout(dataField.getValue(getAddress()), dataSize()); - } - DataLayout extraDataBase() { - return limitDataPosition(); - } - DataLayout extraDataLimit() { - return new DataLayout(dataField.getValue(getAddress()), dataSize() + extraDataSize()); - } - DataLayout nextExtra(DataLayout dataLayout) { - return new DataLayout(dataField.getValue(getAddress()), dataLayout.dp() + DataLayout.computeSizeInBytes(MethodData.extraNbCells(dataLayout))); - } - - public void printDataOn(PrintStream st) { - if (parametersTypeData() != null) { - parametersTypeData().printDataOn(st); - } - ProfileData data = firstData(); - for ( ; isValid(data); data = nextData(data)) { - st.print(dpToDi(data.dp())); - st.print(" "); - // st->fillTo(6); - data.printDataOn(st); - } - st.println("--- Extra data:"); - DataLayout dp = extraDataBase(); - DataLayout end = extraDataLimit(); - for (;; dp = nextExtra(dp)) { - switch(dp.tag()) { - case DataLayout.noTag: - continue; - case DataLayout.bitDataTag: - data = new BitData(dp); - break; - case DataLayout.speculativeTrapDataTag: - data = new SpeculativeTrapData<ciKlass,ciMethod>(this, dp); - break; - case DataLayout.argInfoDataTag: - data = new ArgInfoData(dp); - dp = end; // ArgInfoData is at the end of extra data section. - break; - default: - throw new InternalError("unexpected tag " + dp.tag()); - } - st.print(dpToDi(data.dp())); - st.print(" "); - data.printDataOn(st); - if (dp == end) return; - } - } - - int dumpReplayDataTypeHelper(PrintStream out, int round, int count, int index, ProfileData pdata, ciKlass k) { - if (k != null) { - if (round == 0) count++; - else out.print(" " + ((pdata.dp() + pdata.cellOffset(index)) / MethodData.cellSize) + " " + k.name()); - } - return count; - } - - int dumpReplayDataReceiverTypeHelper(PrintStream out, int round, int count, ReceiverTypeData<ciKlass,ciMethod> vdata) { - for (int i = 0; i < vdata.rowLimit(); i++) { - ciKlass k = vdata.receiver(i); - count = dumpReplayDataTypeHelper(out, round, count, vdata.receiverCellIndex(i), vdata, k); - } - return count; - } - - int dumpReplayDataCallTypeHelper(PrintStream out, int round, int count, CallTypeDataInterface<ciKlass> callTypeData) { - if (callTypeData.hasArguments()) { - for (int i = 0; i < callTypeData.numberOfArguments(); i++) { - count = dumpReplayDataTypeHelper(out, round, count, callTypeData.argumentTypeIndex(i), (ProfileData)callTypeData, callTypeData.argumentType(i)); - } - } - if (callTypeData.hasReturn()) { - count = dumpReplayDataTypeHelper(out, round, count, callTypeData.returnTypeIndex(), (ProfileData)callTypeData, callTypeData.returnType()); - } - return count; - } - - int dumpReplayDataExtraDataHelper(PrintStream out, int round, int count) { - DataLayout dp = extraDataBase(); - DataLayout end = extraDataLimit(); - - for (;dp != end; dp = nextExtra(dp)) { - switch(dp.tag()) { - case DataLayout.noTag: - case DataLayout.argInfoDataTag: - return count; - case DataLayout.bitDataTag: - break; - case DataLayout.speculativeTrapDataTag: { - SpeculativeTrapData<ciKlass,ciMethod> data = new SpeculativeTrapData<ciKlass,ciMethod>(this, dp); - ciMethod m = data.method(); - if (m != null) { - if (round == 0) { - count++; - } else { - out.print(" " + (dpToDi(data.dp() + data.cellOffset(SpeculativeTrapData.methodIndex())) / MethodData.cellSize) + " " + m.nameAsAscii()); - } - } - break; - } - default: - throw new InternalError("bad tag " + dp.tag()); - } - } - return count; - } - - public void dumpReplayData(PrintStream out) { - MethodData mdo = (MethodData)getMetadata(); - Method method = mdo.getMethod(); - out.print("ciMethodData " + - method.nameAsAscii() + " " + - state() + " " + currentMileage()); - byte[] orig = orig(); - out.print(" orig " + orig.length); - for (int i = 0; i < orig.length; i++) { - out.print(" " + (orig[i] & 0xff)); - } - - long[] data = data(); - out.print(" data " + data.length); - for (int i = 0; i < data.length; i++) { - out.print(" 0x" + Long.toHexString(data[i])); - } - int count = 0; - ParametersTypeData<ciKlass,ciMethod> parameters = parametersTypeData(); - for (int round = 0; round < 2; round++) { - if (round == 1) out.print(" oops " + count); - ProfileData pdata = firstData(); - for ( ; isValid(pdata); pdata = nextData(pdata)) { - if (pdata instanceof ReceiverTypeData) { - @SuppressWarnings("unchecked") - ReceiverTypeData<ciKlass,ciMethod> receiverTypeData = (ReceiverTypeData<ciKlass,ciMethod>)pdata; - count = dumpReplayDataReceiverTypeHelper(out, round, count, receiverTypeData); - } - if (pdata instanceof CallTypeDataInterface) { - @SuppressWarnings("unchecked") - CallTypeDataInterface<ciKlass> callTypeData = (CallTypeDataInterface<ciKlass>)pdata; - count = dumpReplayDataCallTypeHelper(out, round, count, callTypeData); - } - } - if (parameters != null) { - for (int i = 0; i < parameters.numberOfParameters(); i++) { - count = dumpReplayDataTypeHelper(out, round, count, ParametersTypeData.typeIndex(i), parameters, parameters.type(i)); - } - } - } - count = 0; - for (int round = 0; round < 2; round++) { - if (round == 1) out.print(" methods " + count); - count = dumpReplayDataExtraDataHelper(out, round, count); - } - out.println(); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciObjArrayKlass.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciObjArrayKlass.java deleted file mode 100644 index ce87a98dd20..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciObjArrayKlass.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.io.PrintStream; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciObjArrayKlass extends ciArrayKlass { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciObjArrayKlass"); - elementKlassField = type.getAddressField("_element_klass"); - baseElementKlassField = type.getAddressField("_base_element_klass"); - } - - private static AddressField elementKlassField; - private static AddressField baseElementKlassField; - - public ciObjArrayKlass(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciObject.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciObject.java deleted file mode 100644 index 0d462ce85dc..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciObject.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.io.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciObject extends ciBaseObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciObject"); - klassField = type.getAddressField("_klass"); - handleField = type.getAddressField("_handle"); - } - - private static AddressField klassField; - private static AddressField handleField; - - public Oop getOop() { - OopHandle oh = handleField.getValue(getAddress()).getOopHandleAt(0); - return VM.getVM().getObjectHeap().newOop(oh); - } - - public ciObject(Address addr) { - super(addr); - } - - public void printOn(PrintStream out) { - getOop().printValueOn(out); - out.println(); - } - - public String toString() { - return getOop().toString(); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciObjectFactory.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciObjectFactory.java deleted file mode 100644 index 3de3ba908b2..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciObjectFactory.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.lang.reflect.Constructor; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.utilities.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciObjectFactory extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciObjectFactory"); - ciMetadataField = type.getAddressField("_ci_metadata"); - symbolsField = type.getAddressField("_symbols"); - - ciObjectConstructor = new VirtualBaseConstructor<ciObject>(db, db.lookupType("ciObject"), "sun.jvm.hotspot.ci", ciObject.class); - ciMetadataConstructor = new VirtualBaseConstructor<ciMetadata>(db, db.lookupType("ciMetadata"), "sun.jvm.hotspot.ci", ciMetadata.class); - ciSymbolConstructor = new VirtualBaseConstructor<ciSymbol>(db, db.lookupType("ciSymbol"), "sun.jvm.hotspot.ci", ciSymbol.class); - } - - private static AddressField ciMetadataField; - private static AddressField symbolsField; - - private static VirtualBaseConstructor<ciObject> ciObjectConstructor; - private static VirtualBaseConstructor<ciMetadata> ciMetadataConstructor; - private static VirtualBaseConstructor<ciSymbol> ciSymbolConstructor; - - public static ciObject get(Address addr) { - if (addr == null) return null; - - return ciObjectConstructor.instantiateWrapperFor(addr); - } - - public static ciMetadata getMetadata(Address addr) { - if (addr == null) return null; - - return ciMetadataConstructor.instantiateWrapperFor(addr); - } - - public GrowableArray<ciMetadata> objects() { - Address addr = getAddress().addOffsetTo(ciMetadataField.getOffset()); - return GrowableArray.create(addr, ciMetadataConstructor); - } - - public GrowableArray<ciSymbol> symbols() { - Address addr = getAddress().addOffsetTo(symbolsField.getOffset()); - return GrowableArray.create(addr, ciSymbolConstructor); - } - - public ciObjectFactory(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciSymbol.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciSymbol.java deleted file mode 100644 index b9f5bcce6fb..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciSymbol.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.io.PrintStream; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciSymbol extends ciMetadata { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciSymbol"); - symbolField = type.getAddressField("_symbol"); - } - - private static AddressField symbolField; - - public String asUtf88() { - Symbol sym = Symbol.create(symbolField.getValue(getAddress())); - return sym.asString(); - } - - public ciSymbol(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciType.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciType.java deleted file mode 100644 index 656b2e56479..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciType.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciType extends ciMetadata { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciType"); - basicTypeField = new CIntField(type.getCIntegerField("_basic_type"), 0); - } - - private static CIntField basicTypeField; - - public ciType(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciTypeArrayKlass.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciTypeArrayKlass.java deleted file mode 100644 index 43f546a5da0..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciTypeArrayKlass.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.ci; - -import java.io.PrintStream; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ciTypeArrayKlass extends ciArrayKlass { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ciTypeArrayKlass"); - } - - public ciTypeArrayKlass(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java index b401f3656f9..a085edf9936 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java @@ -65,8 +65,6 @@ public CodeBlob(Address addr) { super(addr); } - protected static int matcherInterpreterFramePointerReg; - private static void initialize(TypeDataBase db) { Type type = db.lookupType("CodeBlob"); @@ -83,11 +81,6 @@ private static void initialize(TypeDataBase db) { oopMapsField = type.getAddressField("_oop_maps"); callerMustGCArgumentsField = type.getCIntegerField("_caller_must_gc_arguments"); - if (VM.getVM().isServerCompiler()) { - matcherInterpreterFramePointerReg = - db.lookupIntConstant("Matcher::interpreter_frame_pointer_reg").intValue(); - } - NMethodKind = db.lookupIntConstant("CodeBlobKind::Nmethod").intValue(); RuntimeStubKind = db.lookupIntConstant("CodeBlobKind::RuntimeStub").intValue(); UpcallKind = db.lookupIntConstant("CodeBlobKind::Upcall").intValue(); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java index 8cd2342750d..44d51b005ae 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java @@ -489,42 +489,6 @@ public String getName() { method.getSignature().asString(); } - public void dumpReplayData(PrintStream out) { - HashMap<Metadata, Metadata> h = new HashMap<>(); - for (int i = 1; i < getMetadataLength(); i++) { - Metadata meta = Metadata.instantiateWrapperFor(getMetadataAt(i)); - System.err.println(meta); - if (h.get(meta) != null) continue; - h.put(meta, meta); - if (meta instanceof InstanceKlass) { - meta.dumpReplayData(out); - } else if (meta instanceof Method) { - meta.dumpReplayData(out); - MethodData mdo = ((Method)meta).getMethodData(); - if (mdo != null) { - mdo.dumpReplayData(out); - } - } - } - Method method = getMethod(); - if (h.get(method) == null) { - method.dumpReplayData(out); - MethodData mdo = method.getMethodData(); - if (mdo != null) { - mdo.dumpReplayData(out); - } - } - if (h.get(method.getMethodHolder()) == null) { - method.getMethodHolder().dumpReplayData(out); - } - Klass holder = method.getMethodHolder(); - out.println("compile " + holder.getName().asString() + " " + - OopUtilities.escapeString(method.getName().asString()) + " " + - method.getSignature().asString() + " " + - getEntryBCI() + " " + getCompLevel()); - - } - //-------------------------------------------------------------------------------- // Internals only below this point // diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/compiler/CompileTask.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/compiler/CompileTask.java index 7b5fba44bc2..e54facaeb72 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/compiler/CompileTask.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/compiler/CompileTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, 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 @@ -29,7 +29,6 @@ import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.opto.*; import sun.jvm.hotspot.prims.JvmtiExport; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.Observable; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index 05d511d422f..0cd743372d5 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, 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 @@ -965,84 +965,4 @@ private static int linearSearch(MethodArray methods, String name, String signatu } return -1; } - - public void dumpReplayData(PrintStream out) { - ConstantPool cp = getConstants(); - - // Try to record related loaded classes - Klass sub = getSubklassKlass(); - while (sub != null) { - if (sub instanceof InstanceKlass) { - out.println("instanceKlass " + sub.getName().asString()); - } - sub = sub.getNextSiblingKlass(); - } - - final int length = cp.getLength(); - out.print("ciInstanceKlass " + getName().asString() + " " + (isLinked() ? 1 : 0) + " " + (isInitialized() ? 1 : 0) + " " + length); - for (int index = 1; index < length; index++) { - out.print(" " + cp.getTags().at(index)); - } - out.println(); - if (isInitialized()) { - Field[] staticFields = getStaticFields(); - for (int i = 0; i < staticFields.length; i++) { - Field f = staticFields[i]; - Oop mirror = getJavaMirror(); - if (f.isFinal() && !f.hasInitialValue()) { - out.print("staticfield " + getName().asString() + " " + - OopUtilities.escapeString(f.getID().getName()) + " " + - f.getFieldType().getSignature().asString() + " "); - if (f instanceof ByteField) { - ByteField bf = (ByteField)f; - out.println(bf.getValue(mirror)); - } else if (f instanceof BooleanField) { - BooleanField bf = (BooleanField)f; - out.println(bf.getValue(mirror) ? 1 : 0); - } else if (f instanceof ShortField) { - ShortField bf = (ShortField)f; - out.println(bf.getValue(mirror)); - } else if (f instanceof CharField) { - CharField bf = (CharField)f; - out.println(bf.getValue(mirror) & 0xffff); - } else if (f instanceof IntField) { - IntField bf = (IntField)f; - out.println(bf.getValue(mirror)); - } else if (f instanceof LongField) { - LongField bf = (LongField)f; - out.println(bf.getValue(mirror)); - } else if (f instanceof FloatField) { - FloatField bf = (FloatField)f; - out.println(Float.floatToRawIntBits(bf.getValue(mirror))); - } else if (f instanceof DoubleField) { - DoubleField bf = (DoubleField)f; - out.println(Double.doubleToRawLongBits(bf.getValue(mirror))); - } else if (f instanceof OopField) { - OopField bf = (OopField)f; - - Oop value = bf.getValue(mirror); - if (value == null) { - out.println("null"); - } else if (value.isInstance()) { - Instance inst = (Instance)value; - if (inst.isA(SystemDictionary.getStringKlass())) { - out.println("\"" + OopUtilities.stringOopToEscapedString(inst) + "\""); - } else { - out.println(inst.getKlass().getName().asString()); - } - } else if (value.isObjArray()) { - ObjArray oa = (ObjArray)value; - Klass ek = (ObjArrayKlass)oa.getKlass(); - out.println(oa.getLength() + " " + ek.getName().asString()); - } else if (value.isTypeArray()) { - TypeArray ta = (TypeArray)value; - out.println(ta.getLength()); - } else { - out.println(value); - } - } - } - } - } - } } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Metadata.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Metadata.java index 4d9d733b2c7..2542a72ebe1 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Metadata.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Metadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,9 +91,6 @@ void iterateFields(MetadataVisitor visitor) { } public abstract void printValueOn(PrintStream tty); - public void dumpReplayData(PrintStream out) { - out.println("# Unknown Metadata"); - } public boolean isShared() { VM vm = VM.getVM(); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Method.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Method.java index 3477a1a1b52..28ee11a89eb 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Method.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Method.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, 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 @@ -356,22 +356,6 @@ public String externalNameAndSignature() { return buf.toString().replace('/', '.'); } - public void dumpReplayData(PrintStream out) { - NMethod nm = getNativeMethod(); - int code_size = 0; - if (nm != null) { - code_size = (int)nm.codeEnd().minus(nm.getVerifiedEntryPoint()); - } - Klass holder = getMethodHolder(); - out.println("ciMethod " + - nameAsAscii() + " " + - getInvocationCount() + " " + - getBackedgeCount() + " " + - interpreterInvocationCount() + " " + - interpreterThrowoutCount() + " " + - code_size); - } - public int interpreterThrowoutCount() { return getMethodCounters().interpreterThrowoutCount(); } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java index 0c05cabe32d..a7c2e2bccb7 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, 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 @@ -439,111 +439,4 @@ public int currentMileage() { return 20000; } - int dumpReplayDataTypeHelper(PrintStream out, int round, int count, int index, ProfileData pdata, Klass k) { - if (k != null) { - if (round == 0) count++; - else out.print(" " + - (dpToDi(pdata.dp() + - pdata.cellOffset(index)) / cellSize) + " " + - k.getName().asString()); - } - return count; - } - - int dumpReplayDataReceiverTypeHelper(PrintStream out, int round, int count, ReceiverTypeData<Klass,Method> vdata) { - for (int i = 0; i < vdata.rowLimit(); i++) { - Klass k = vdata.receiver(i); - count = dumpReplayDataTypeHelper(out, round, count, vdata.receiverCellIndex(i), vdata, k); - } - return count; - } - - int dumpReplayDataCallTypeHelper(PrintStream out, int round, int count, CallTypeDataInterface<Klass> callTypeData) { - if (callTypeData.hasArguments()) { - for (int i = 0; i < callTypeData.numberOfArguments(); i++) { - count = dumpReplayDataTypeHelper(out, round, count, callTypeData.argumentTypeIndex(i), (ProfileData)callTypeData, callTypeData.argumentType(i)); - } - } - if (callTypeData.hasReturn()) { - count = dumpReplayDataTypeHelper(out, round, count, callTypeData.returnTypeIndex(), (ProfileData)callTypeData, callTypeData.returnType()); - } - return count; - } - - int dumpReplayDataExtraDataHelper(PrintStream out, int round, int count) { - DataLayout dp = extraDataBase(); - DataLayout end = extraDataLimit(); - - for (;dp != end; dp = nextExtra(dp)) { - switch(dp.tag()) { - case DataLayout.noTag: - case DataLayout.argInfoDataTag: - return count; - case DataLayout.bitDataTag: - break; - case DataLayout.speculativeTrapDataTag: { - SpeculativeTrapData<Klass,Method> data = new SpeculativeTrapData<Klass,Method>(this, dp); - Method m = data.method(); - if (m != null) { - if (round == 0) { - count++; - } else { - out.print(" " + (dpToDi(data.dp() + data.cellOffset(SpeculativeTrapData.methodIndex())) / cellSize) + " " + m.nameAsAscii()); - } - } - break; - } - default: - throw new InternalError("bad tag " + dp.tag()); - } - } - return count; - } - - public void dumpReplayData(PrintStream out) { - Method method = getMethod(); - out.print("ciMethodData " + method.nameAsAscii() - + " " + "2" + " " + - currentMileage()); - byte[] orig = orig(); - out.print(" orig " + orig.length); - for (int i = 0; i < orig.length; i++) { - out.print(" " + (orig[i] & 0xff)); - } - - long[] data = data(); - out.print(" data " + data.length); - for (int i = 0; i < data.length; i++) { - out.print(" 0x" + Long.toHexString(data[i])); - } - int count = 0; - ParametersTypeData<Klass,Method> parameters = parametersTypeData(); - for (int round = 0; round < 2; round++) { - if (round == 1) out.print(" oops " + count); - ProfileData pdata = firstData(); - for ( ; isValid(pdata); pdata = nextData(pdata)) { - if (pdata instanceof ReceiverTypeData) { - @SuppressWarnings("unchecked") - ReceiverTypeData<Klass,Method> receiverTypeData = (ReceiverTypeData<Klass,Method>)pdata; - count = dumpReplayDataReceiverTypeHelper(out, round, count, receiverTypeData); - } - if (pdata instanceof CallTypeDataInterface) { - @SuppressWarnings("unchecked") - CallTypeDataInterface<Klass> callTypeData = (CallTypeDataInterface<Klass>)pdata; - count = dumpReplayDataCallTypeHelper(out, round, count, callTypeData); - } - } - if (parameters != null) { - for (int i = 0; i < parameters.numberOfParameters(); i++) { - count = dumpReplayDataTypeHelper(out, round, count, ParametersTypeData.typeIndex(i), parameters, parameters.type(i)); - } - } - } - count = 0; - for (int round = 0; round < 2; round++) { - if (round == 1) out.print(" methods " + count); - count = dumpReplayDataExtraDataHelper(out, round, count); - } - out.println(); - } } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Block.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Block.java deleted file mode 100644 index 857e6da9bf8..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Block.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import java.io.PrintStream; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class Block extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("Block"); - nodesField = type.getAddressField("_nodes"); - succsField = type.getAddressField("_succs"); - numSuccsField = new CIntField(type.getCIntegerField("_num_succs"), 0); - preOrderField = new CIntField(type.getCIntegerField("_pre_order"), 0); - domDepthField = new CIntField(type.getCIntegerField("_dom_depth"), 0); - idomField = type.getAddressField("_idom"); - freqField = type.getJDoubleField("_freq"); - } - - private static AddressField nodesField; - private static AddressField succsField; - private static CIntField numSuccsField; - private static CIntField preOrderField; - private static CIntField domDepthField; - private static AddressField idomField; - private static JDoubleField freqField; - - public Block(Address addr) { - super(addr); - } - - public int preOrder() { - return (int)preOrderField.getValue(getAddress()); - } - - public double freq() { - return freqField.getValue(getAddress()); - } - - public Node_List nodes() { - return new Node_List(getAddress().addOffsetTo(nodesField.getOffset())); - } - - public void dump(PrintStream out) { - out.print("B" + preOrder()); - out.print(" Freq: " + freq()); - out.println(); - Node_List nl = nodes(); - int cnt = nl.size(); - for( int i=0; i<cnt; i++ ) - nl.at(i).dump(out); - out.print("\n"); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Block_Array.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Block_Array.java deleted file mode 100644 index fe6d6072129..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Block_Array.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class Block_Array extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("Block_Array"); - sizeField = new CIntField(type.getCIntegerField("_size"), 0); - blocksField = type.getAddressField("_blocks"); - arenaField = type.getAddressField("_arena"); - } - - private static CIntField sizeField; - private static AddressField blocksField; - private static AddressField arenaField; - - public Block_Array(Address addr) { - super(addr); - } - - public int Max() { - return (int) sizeField.getValue(getAddress()); - } - - public Block at(int i) { - return new Block(blocksField.getValue(getAddress()).getAddressAt(i * (int)VM.getVM().getAddressSize())); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Block_List.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Block_List.java deleted file mode 100644 index ee10e6f6243..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Block_List.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class Block_List extends Block_Array { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("Block_List"); - cntField = new CIntField(type.getCIntegerField("_cnt"), 0); - } - - private static CIntField cntField; - - public Block_List(Address addr) { - super(addr); - } - - public int size() { - return (int) cntField.getValue(getAddress()); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallDynamicJavaNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallDynamicJavaNode.java deleted file mode 100644 index 39f1a05f0d1..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallDynamicJavaNode.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class CallDynamicJavaNode extends CallJavaNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("CallDynamicJavaNode"); - } - - - public CallDynamicJavaNode(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallJavaNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallJavaNode.java deleted file mode 100644 index 9e330a923d3..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallJavaNode.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import java.io.*; -import sun.jvm.hotspot.code.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.ci.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class CallJavaNode extends CallNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("CallJavaNode"); - methodField = type.getAddressField("_method"); - } - - private static AddressField methodField; - - public CallJavaNode(Address addr) { - super(addr); - } - - public ciMethod method() { - return (ciMethod) ciObjectFactory.getMetadata(methodField.getValue(getAddress())); - } - - public void dumpSpec(PrintStream out) { - if (method() != null) { - out.print(" " + method().method().externalNameAndSignature()); - } - super.dumpSpec(out); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallNode.java deleted file mode 100644 index 3dfd8862830..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallNode.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.io.PrintStream; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class CallNode extends SafePointNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("CallNode"); - entryPointField = type.getAddressField("_entry_point"); - } - - private static AddressField entryPointField; - - public Address entryPoint() { - return entryPointField.getValue(getAddress()); - } - - public CallNode(Address addr) { - super(addr); - } - - public void dumpSpec(PrintStream out) { - out.print(" "); - // tf()->dumpOn(st); - // if (_cnt != countUnknown) st->print(" C=%f",_cnt); - JVMState jvms = jvms(); - if (jvms != null) jvms.dumpSpec(out); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallRuntimeNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallRuntimeNode.java deleted file mode 100644 index 3bfd221395e..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallRuntimeNode.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.io.PrintStream; -import java.util.*; -import sun.jvm.hotspot.utilities.CStringUtilities; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class CallRuntimeNode extends CallNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("CallRuntimeNode"); - nameField = type.getAddressField("_name"); - } - - private static AddressField nameField; - - public String name() { - return CStringUtilities.getString(nameField.getValue(getAddress())); - } - - public CallRuntimeNode(Address addr) { - super(addr); - } - - public void dumpSpec(PrintStream out) { - out.print(" #"); - out.print(name()); - super.dumpSpec(out); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallStaticJavaNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallStaticJavaNode.java deleted file mode 100644 index ab678d0e6c6..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CallStaticJavaNode.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.io.PrintStream; -import java.util.*; -import sun.jvm.hotspot.utilities.CStringUtilities; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class CallStaticJavaNode extends CallJavaNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("CallStaticJavaNode"); - nameField = type.getAddressField("_name"); - } - - private static AddressField nameField; - - public String name() { - return CStringUtilities.getString(nameField.getValue(getAddress())); - } - - public CallStaticJavaNode(Address addr) { - super(addr); - } - - public void dumpSpec(PrintStream out) { - out.print(" Static "); - String name = name(); - if (name != null) { - out.print(name); - // int trapReq = uncommonTrapRequest(); - // if (trapReq != 0) { - // char buf[100]; - // st->print("(%s)", - // Deoptimization::formatTrapRequest(buf, sizeof(buf), - // trapReq)); - // } - out.print(" "); - } - super.dumpSpec(out); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Compile.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Compile.java deleted file mode 100644 index 725c95619fc..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Compile.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import java.io.PrintStream; -import sun.jvm.hotspot.ci.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class Compile extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("Compile"); - rootField = type.getAddressField("_root"); - uniqueField = new CIntField(type.getCIntegerField("_unique"), 0); - entryBciField = new CIntField(type.getCIntegerField("_entry_bci"), 0); - topField = type.getAddressField("_top"); - cfgField = type.getAddressField("_cfg"); - regallocField = type.getAddressField("_regalloc"); - methodField = type.getAddressField("_method"); - iltField = type.getAddressField("_ilt"); - } - - private static AddressField rootField; - private static CIntField uniqueField; - private static CIntField entryBciField; - private static AddressField topField; - private static AddressField cfgField; - private static AddressField regallocField; - private static AddressField methodField; - private static AddressField iltField; - - public Compile(Address addr) { - super(addr); - } - - public Node root() { - return new RootNode(rootField.getValue(this.getAddress())); - } - - public int entryBci() { - return (int)entryBciField.getValue(getAddress()); - } - - public ciMethod method() { - return (ciMethod) ciObjectFactory.getMetadata(methodField.getValue(getAddress())); - } - - public PhaseCFG cfg() { - Address a = cfgField.getValue(this.getAddress()); - if (a != null) { - return new PhaseCFG(a); - } - return null; - } - - public InlineTree ilt() { - Address a = iltField.getValue(this.getAddress()); - if (a != null) { - return new InlineTree(a); - } - return null; - } - - public void dumpInlineData(PrintStream out) { - InlineTree inlTree = ilt(); - if (inlTree != null) { - out.print(" inline " + inlTree.count()); - inlTree.dumpReplayData(out); - } - } - -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CompilerPhaseType.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CompilerPhaseType.java deleted file mode 100644 index a745d682069..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/CompilerPhaseType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -//These definitions should be kept in sync with the definitions in the HotSpot code. - -public enum CompilerPhaseType { - PHASE_BEFORE_STRINGOPTS ("Before StringOpts"), - PHASE_AFTER_STRINGOPTS ("After StringOpts"), - PHASE_BEFORE_REMOVEUSELESS ("Before RemoveUseless"), - PHASE_AFTER_PARSING ("After Parsing"), - PHASE_ITER_GVN1 ("Iter GVN 1"), - PHASE_PHASEIDEAL_BEFORE_EA ("PhaseIdealLoop before EA"), - PHASE_ITER_GVN_AFTER_EA ("Iter GVN after EA"), - PHASE_ITER_GVN_AFTER_ELIMINATION ("Iter GVN after eliminating allocations and locks"), - PHASE_PHASEIDEALLOOP1 ("PhaseIdealLoop 1"), - PHASE_PHASEIDEALLOOP2 ("PhaseIdealLoop 2"), - PHASE_PHASEIDEALLOOP3 ("PhaseIdealLoop 3"), - PHASE_CCP1 ("PhaseCCP 1"), - PHASE_ITER_GVN2 ("Iter GVN 2"), - PHASE_PHASEIDEALLOOP_ITERATIONS ("PhaseIdealLoop iterations"), - PHASE_OPTIMIZE_FINISHED ("Optimize finished"), - PHASE_GLOBAL_CODE_MOTION ("Global code motion"), - PHASE_FINAL_CODE ("Final Code"), - PHASE_AFTER_EA ("After Escape Analysis"), - PHASE_BEFORE_CLOOPS ("Before CountedLoop"), - PHASE_AFTER_CLOOPS ("After CountedLoop"), - PHASE_BEFORE_BEAUTIFY_LOOPS ("Before beautify loops"), - PHASE_AFTER_BEAUTIFY_LOOPS ("After beautify loops"), - PHASE_BEFORE_MATCHING ("Before Matching"), - PHASE_INCREMENTAL_INLINE ("Incremental Inline"), - PHASE_INCREMENTAL_BOXING_INLINE ("Incremental Boxing Inline"), - PHASE_END ("End"), - PHASE_FAILURE ("Failure"), - PHASE_NUM_TYPES ("Number of Phase Types"); - - private final String value; - - CompilerPhaseType(String val) { - this.value = val; - } - public String value() { - return value; - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/InlineTree.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/InlineTree.java deleted file mode 100644 index 9a11b1c962c..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/InlineTree.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import java.io.PrintStream; -import sun.jvm.hotspot.ci.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.utilities.GrowableArray; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class InlineTree extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("InlineTree"); - callerJvmsField = type.getAddressField("_caller_jvms"); - methodField = type.getAddressField("_method"); - callerTreeField = type.getAddressField("_caller_tree"); - subtreesField = type.getAddressField("_subtrees"); - } - - private static AddressField callerJvmsField; - private static AddressField methodField; - private static AddressField callerTreeField; - private static AddressField subtreesField; - - private static StaticBaseConstructor<InlineTree> inlineTreeConstructor = new StaticBaseConstructor<>(InlineTree.class); - - public InlineTree(Address addr) { - super(addr); - } - - public InlineTree callerTree() { - Address addr = callerTreeField.getValue(getAddress()); - if (addr == null) return null; - - return new InlineTree(addr); - } - - public ciMethod method() { - return (ciMethod) ciObjectFactory.getMetadata(methodField.getValue(getAddress())); - } - - public JVMState callerJvms() { - return JVMState.create(callerJvmsField.getValue(getAddress())); - } - - public int callerBci() { - JVMState jvms = callerJvms(); - return (jvms != null) ? jvms.bci() : -1; - } - - public GrowableArray<InlineTree> subtrees() { - Address addr = getAddress().addOffsetTo(subtreesField.getOffset()); - - return GrowableArray.create(addr, inlineTreeConstructor); - } - - public int inlineLevel() { - JVMState jvms = callerJvms(); - return (jvms != null) ? jvms.depth() : 0; - } - - public void printImpl(PrintStream st, int indent) { - for (int i = 0; i < indent; i++) st.print(" "); - st.printf(" @ %d ", callerBci()); - method().printShortName(st); - st.println(); - - GrowableArray<InlineTree> subt = subtrees(); - for (int i = 0 ; i < subt.length(); i++) { - subt.at(i).printImpl(st, indent + 2); - } - } - public void print(PrintStream st) { - printImpl(st, 2); - } - - // Count number of nodes in this subtree - public int count() { - int result = 1; - GrowableArray<InlineTree> subt = subtrees(); - for (int i = 0 ; i < subt.length(); i++) { - result += subt.at(i).count(); - } - return result; - } - - public void dumpReplayData(PrintStream out) { - out.printf(" %d %d ", inlineLevel(), callerBci()); - Method method = (Method)method().getMetadata(); - Klass holder = method.getMethodHolder(); - out.print(holder.getName().asString() + " " + - OopUtilities.escapeString(method.getName().asString()) + " " + - method.getSignature().asString()); - - GrowableArray<InlineTree> subt = subtrees(); - for (int i = 0 ; i < subt.length(); i++) { - subt.at(i).dumpReplayData(out); - } - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/JVMState.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/JVMState.java deleted file mode 100644 index d83c1df8b0d..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/JVMState.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.io.PrintStream; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.ci.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class JVMState extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("JVMState"); - mapField = type.getAddressField("_map"); - methodField = type.getAddressField("_method"); - bciField = new CIntField(type.getCIntegerField("_bci"), 0); - spField = new CIntField(type.getCIntegerField("_sp"), 0); - endoffField = new CIntField(type.getCIntegerField("_endoff"), 0); - try { - scloffField = new CIntField(type.getCIntegerField("_scloff"), 0); - } catch (Exception e) { - } - monoffField = new CIntField(type.getCIntegerField("_monoff"), 0); - stkoffField = new CIntField(type.getCIntegerField("_stkoff"), 0); - locoffField = new CIntField(type.getCIntegerField("_locoff"), 0); - depthField = new CIntField(type.getCIntegerField("_depth"), 0); - callerField = type.getAddressField("_caller"); - } - - private static AddressField mapField; - private static AddressField methodField; - private static CIntField bciField; - private static CIntField spField; - private static CIntField endoffField; - private static CIntField scloffField; - private static CIntField monoffField; - private static CIntField stkoffField; - private static CIntField locoffField; - private static CIntField depthField; - private static AddressField callerField; - - public static JVMState create(Address addr) { - if (addr == null) return null; - return new JVMState(addr); - } - - public JVMState(Address addr) { - super(addr); - } - - public ciMethod method() { - return (ciMethod) ciObjectFactory.getMetadata(methodField.getValue(getAddress())); - } - - public int bci() { - return (int)bciField.getValue(getAddress()); - } - - public int depth() { - return (int)depthField.getValue(getAddress()); - } - - public JVMState caller() { - return create(callerField.getValue(getAddress())); - } - - public void dumpSpec(PrintStream out) { - ciMethod m = method(); - if (m != null) { - Method meth = m.method(); - out.print(" " + meth.getMethodHolder().getName().asString().replace('/', '.') + "::" + - meth.getName().asString() + " @ bci:" + bci()); - } else { - out.print(" runtime stub"); - } - if (caller() != null) caller().dumpSpec(out); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/LoopNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/LoopNode.java deleted file mode 100644 index 96d96d3348c..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/LoopNode.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class LoopNode extends RegionNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("LoopNode"); - } - - - public LoopNode(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachCallJavaNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachCallJavaNode.java deleted file mode 100644 index 29c411da4d7..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachCallJavaNode.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import java.io.PrintStream; -import sun.jvm.hotspot.ci.ciMethod; -import sun.jvm.hotspot.ci.ciObjectFactory; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class MachCallJavaNode extends MachCallNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("MachCallJavaNode"); - methodField = type.getAddressField("_method"); - bciField = new CIntField(type.getCIntegerField("_bci"), 0); - } - - private static AddressField methodField; - private static CIntField bciField; - - public ciMethod method() { - return (ciMethod) ciObjectFactory.getMetadata(methodField.getValue(getAddress())); - } - - public MachCallJavaNode(Address addr) { - super(addr); - } - - public void dumpSpec(PrintStream st) { - ciMethod m = method(); - if (m != null) { - m.printShortName(st); - st.print(" "); - } - super.dumpSpec(st); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachCallNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachCallNode.java deleted file mode 100644 index 040616b4b5c..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachCallNode.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import java.io.PrintStream; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class MachCallNode extends MachSafePointNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("MachCallNode"); - } - - public MachCallNode(Address addr) { - super(addr); - } - - public void dumpSpec(PrintStream st) { - st.print("# "); - // tf()->dump_on(st); - // if (_cnt != COUNT_UNKNOWN) st->print(" C=%f",_cnt); - if (jvms() != null) jvms().dumpSpec(st); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachCallRuntimeNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachCallRuntimeNode.java deleted file mode 100644 index 7fff61bb147..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachCallRuntimeNode.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import java.io.PrintStream; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.CStringUtilities; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class MachCallRuntimeNode extends MachCallJavaNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("MachCallRuntimeNode"); - nameField = type.getAddressField("_name"); - } - - private static AddressField nameField; - - public String name() { - return CStringUtilities.getString(nameField.getValue(getAddress())); - } - - public MachCallRuntimeNode(Address addr) { - super(addr); - } - - public void dumpSpec(PrintStream out) { - out.printf("%s ", name()); - super.dumpSpec(out); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachCallStaticJavaNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachCallStaticJavaNode.java deleted file mode 100644 index 6124a0c353d..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachCallStaticJavaNode.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import java.io.PrintStream; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.CStringUtilities; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class MachCallStaticJavaNode extends MachCallJavaNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("MachCallStaticJavaNode"); - nameField = type.getAddressField("_name"); - } - - private static AddressField nameField; - - public String name() { - return CStringUtilities.getString(nameField.getValue(getAddress())); - } - - public MachCallStaticJavaNode(Address addr) { - super(addr); - } - - public void dumpSpec(PrintStream st) { - st.print("Static "); - String n = name(); - if (n != null) { - st.printf("wrapper for: %s", n); - // dump_trap_args(st); - st.print(" "); - } - super.dumpSpec(st); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachIfNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachIfNode.java deleted file mode 100644 index dec4fd73f97..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachIfNode.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import java.io.PrintStream; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class MachIfNode extends MachNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("MachIfNode"); - probField = type.getJFloatField("_prob"); - fcntField = type.getJFloatField("_fcnt"); - } - - private static JFloatField probField; - private static JFloatField fcntField; - - float prob() { - return probField.getValue(getAddress()); - } - - float cnt() { - return fcntField.getValue(getAddress()); - } - - public MachIfNode(Address addr) { - super(addr); - } - - public void dumpSpec(PrintStream out) { - out.print("P=" + prob() + ", C=" + cnt()); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachNode.java deleted file mode 100644 index f300f52864b..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachNode.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class MachNode extends Node { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("MachNode"); - } - - public MachNode(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachReturnNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachReturnNode.java deleted file mode 100644 index db3a8398322..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachReturnNode.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class MachReturnNode extends MachNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("MachReturnNode"); - } - - public MachReturnNode(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachSafePointNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachSafePointNode.java deleted file mode 100644 index 8e54f0c1df0..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MachSafePointNode.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import java.io.PrintStream; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class MachSafePointNode extends MachReturnNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("MachSafePointNode"); - jvmsField = type.getAddressField("_jvms"); - jvmadjField = new CIntField(type.getCIntegerField("_jvmadj"), 0); - } - - private static AddressField jvmsField; - private static CIntField jvmadjField; - - public MachSafePointNode(Address addr) { - super(addr); - } - - public JVMState jvms() { - return JVMState.create(jvmsField.getValue(getAddress())); - } - - public void dumpSpec(PrintStream out) { - try { - JVMState jvms = jvms(); - if (jvms != null) out.print(" !"); - if (jvms == null) out.print("empty jvms"); - while (jvms != null) { - Method m = jvms.method().method(); - int bci = jvms.bci(); - out.print(" " + m.getMethodHolder().getName().asString().replace('/', '.') + "::" + m.getName().asString() + " @ bci:" + bci); - jvms = jvms.caller(); - } - } catch (Exception e) { - out.print(e); - } - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MultiNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MultiNode.java deleted file mode 100644 index f82e574dac6..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/MultiNode.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class MultiNode extends Node { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("MultiNode"); - } - - - public MultiNode(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Node.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Node.java deleted file mode 100644 index e79abaeb1d1..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Node.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.io.*; -import java.lang.reflect.Constructor; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class Node extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("Node"); - outmaxField = new CIntField(type.getCIntegerField("_outmax"), 0); - outcntField = new CIntField(type.getCIntegerField("_outcnt"), 0); - maxField = new CIntField(type.getCIntegerField("_max"), 0); - cntField = new CIntField(type.getCIntegerField("_cnt"), 0); - idxField = new CIntField(type.getCIntegerField("_idx"), 0); - outField = type.getAddressField("_out"); - inField = type.getAddressField("_in"); - - nodeType = db.lookupType("Node"); - - virtualConstructor = new VirtualBaseConstructor<>(db, nodeType, "sun.jvm.hotspot.opto", Node.class); - } - - private static CIntField outmaxField; - private static CIntField outcntField; - private static CIntField maxField; - private static CIntField cntField; - private static CIntField idxField; - private static AddressField outField; - private static AddressField inField; - - private static VirtualBaseConstructor<Node> virtualConstructor; - - private static Type nodeType; - - static HashMap<Address, Node> nodes = new HashMap<>(); - - static HashMap constructors = new HashMap(); - - abstract static class Instantiator { - abstract Node create(Address addr); - } - - public static Node create(Address addr) { - if (addr == null) return null; - Node result = nodes.get(addr); - if (result == null) { - result = virtualConstructor.instantiateWrapperFor(addr); - nodes.put(addr, result); - } - return result; - } - - public Node(Address addr) { - super(addr); - } - - public int outcnt() { - return (int)outcntField.getValue(this.getAddress()); - } - - public int req() { - return (int)cntField.getValue(this.getAddress()); - } - - public int len() { - return (int)maxField.getValue(this.getAddress()); - } - - public int idx() { - return (int)idxField.getValue(this.getAddress()); - } - - private Node[] _out; - private Node[] _in; - - public Node rawOut(int i) { - if (_out == null) { - int addressSize = (int)VM.getVM().getAddressSize(); - _out = new Node[outcnt()]; - Address ptr = outField.getValue(this.getAddress()); - for (int j = 0; j < outcnt(); j++) { - _out[j] = Node.create(ptr.getAddressAt(j * addressSize)); - } - } - return _out[i]; - } - - public Node in(int i) { - if (_in == null) { - int addressSize = (int)VM.getVM().getAddressSize(); - _in = new Node[len()]; - Address ptr = inField.getValue(this.getAddress()); - for (int j = 0; j < len(); j++) { - _in[j] = Node.create(ptr.getAddressAt(j * addressSize)); - } - } - return _in[i]; - } - - public ArrayList<Node> collect(int d, boolean onlyCtrl) { - int depth = Math.abs(d); - ArrayList<Node> nstack = new ArrayList<>(); - BitSet set = new BitSet(); - - nstack.add(this); - set.set(idx()); - int begin = 0; - int end = 0; - for (int i = 0; i < depth; i++) { - end = nstack.size(); - for(int j = begin; j < end; j++) { - Node tp = nstack.get(j); - int limit = d > 0 ? tp.len() : tp.outcnt(); - for(int k = 0; k < limit; k++) { - Node n = d > 0 ? tp.in(k) : tp.rawOut(k); - - // if (not_a_node(n)) continue; - if (n == null) continue; - // do not recurse through top or the root (would reach unrelated stuff) - // if (n.isRoot() || n.isTop()) continue; - // if (onlyCtrl && !n.isCfg()) continue; - - if (!set.get(n.idx())) { - nstack.add(n); - set.set(n.idx()); - } - } - } - begin = end; - } - return nstack; - } - - protected void dumpNodes(Node s, int d, boolean onlyCtrl, PrintStream out) { - if (s == null) return; - - ArrayList nstack = s.collect(d, onlyCtrl); - int end = nstack.size(); - if (d > 0) { - for(int j = end-1; j >= 0; j--) { - ((Node)nstack.get(j)).dump(out); - } - } else { - for(int j = 0; j < end; j++) { - ((Node)nstack.get(j)).dump(out); - } - } - } - - public void dump(int depth, PrintStream out) { - dumpNodes(this, depth, false, out); - } - - public String Name() { - Type t = VM.getVM().getTypeDataBase().findDynamicTypeForAddress(getAddress(), nodeType); - String name = null; - if (t != null) { - name = t.toString(); - } else { - Class c = getClass(); - if (c == Node.class) { - // couldn't identify class type - return "UnknownNode<" + getAddress().getAddressAt(0) + ">"; - } - name = getClass().getName(); - if (name.startsWith("sun.jvm.hotspot.opto.")) { - name = name.substring("sun.jvm.hotspot.opto.".length()); - } - } - if (name.endsWith("Node")) { - return name.substring(0, name.length() - 4); - } - return name; - } - - public void dump(PrintStream out) { - out.print(" "); - out.print(idx()); - out.print("\t"); - out.print(Name()); - out.print("\t=== "); - int i = 0; - for (i = 0; i < req(); i++) { - Node n = in(i); - if (n != null) { - out.print(' '); - out.print(in(i).idx()); - } else { - out.print("_"); - } - out.print(" "); - } - if (len() != req()) { - int prec = 0; - for (; i < len(); i++) { - Node n = in(i); - if (n != null) { - if (prec++ == 0) { - out.print("| "); - } - out.print(in(i).idx()); - } - out.print(" "); - } - } - dumpOut(out); - dumpSpec(out); - out.println(); - } - - void dumpOut(PrintStream out) { - // Delimit the output edges - out.print(" [["); - // Dump the output edges - for (int i = 0; i < outcnt(); i++) { // For all outputs - Node u = rawOut(i); - if (u == null) { - out.print("_ "); - // } else if (not_a_node(u)) { - // out.print("not_a_node "); - } else { - // out.print("%c%d ", Compile::current()->nodeArena()->contains(u) ? ' ' : 'o', u->_idx); - out.print(' '); - out.print(u.idx()); - out.print(' '); - } - } - out.print("]] "); - } - - public void dumpSpec(PrintStream out) { - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Node_Array.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Node_Array.java deleted file mode 100644 index 35b51cb5833..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Node_Array.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class Node_Array extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("Node_Array"); - maxField = new CIntField(type.getCIntegerField("_max"), 0); - nodesField = type.getAddressField("_nodes"); - aField = type.getAddressField("_a"); - } - - private static CIntField maxField; - private static AddressField nodesField; - private static AddressField aField; - - public Node_Array(Address addr) { - super(addr); - } - - public int Size() { - return (int) maxField.getValue(getAddress()); - } - - public Node at(int i) { - return Node.create(nodesField.getValue(getAddress()).getAddressAt(i * (int)VM.getVM().getAddressSize())); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Node_List.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Node_List.java deleted file mode 100644 index 50abdb75ad1..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Node_List.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class Node_List extends Node_Array { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("Node_List"); - cntField = new CIntField(type.getCIntegerField("_cnt"), 0); - } - - private static CIntField cntField; - - public Node_List(Address addr) { - super(addr); - } - - public int size() { - return (int) cntField.getValue(getAddress()); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Phase.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Phase.java deleted file mode 100644 index fe23efff73d..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/Phase.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class Phase extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("Phase"); - } - - - public Phase(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/PhaseCFG.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/PhaseCFG.java deleted file mode 100644 index c2561edbe40..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/PhaseCFG.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import java.io.PrintStream; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class PhaseCFG extends Phase { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("PhaseCFG"); - numBlocksField = new CIntField(type.getCIntegerField("_number_of_blocks"), 0); - blocksField = type.getAddressField("_blocks"); - bbsField = type.getAddressField("_node_to_block_mapping"); - brootField = type.getAddressField("_root_block"); - } - - private static CIntField numBlocksField; - private static AddressField blocksField; - private static AddressField bbsField; - private static AddressField brootField; - - public PhaseCFG(Address addr) { - super(addr); - } - - public void dump(PrintStream out) { - int addressSize = (int)VM.getVM().getAddressSize(); - int numBlocks = (int)numBlocksField.getValue(getAddress()); - Block_List blocks = new Block_List(getAddress().addOffsetTo(blocksField.getOffset())); - int offset = 0; - for (int i = 0; i < numBlocks; i++) { - blocks.at(i).dump(out); - } - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/PhaseRegAlloc.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/PhaseRegAlloc.java deleted file mode 100644 index 1d0f20b34c3..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/PhaseRegAlloc.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class PhaseRegAlloc extends Phase { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("PhaseRegAlloc"); - nodeRegsField = type.getAddressField("_node_regs"); - nodeRegsMaxIndexField = new CIntField(type.getCIntegerField("_node_regs_max_index"), 0); - framesizeField = new CIntField(type.getCIntegerField("_framesize"), 0); - maxRegField = new CIntField(type.getCIntegerField("_max_reg"), 0); - } - - private static AddressField nodeRegsField; - private static CIntField nodeRegsMaxIndexField; - private static CIntField framesizeField; - private static CIntField maxRegField; - - public PhaseRegAlloc(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/PhiNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/PhiNode.java deleted file mode 100644 index dce9ba1cac3..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/PhiNode.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class PhiNode extends TypeNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("PhiNode"); - } - - - public PhiNode(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/ProjNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/ProjNode.java deleted file mode 100644 index cd615b4bbfd..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/ProjNode.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class ProjNode extends Node { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ProjNode"); - } - - - public ProjNode(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/RegionNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/RegionNode.java deleted file mode 100644 index 6c678c2a686..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/RegionNode.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class RegionNode extends Node { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("RegionNode"); - } - - - public RegionNode(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/RootNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/RootNode.java deleted file mode 100644 index 5a39af1388c..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/RootNode.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class RootNode extends LoopNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("RootNode"); - } - - - public RootNode(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/SafePointNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/SafePointNode.java deleted file mode 100644 index daea02a9601..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/SafePointNode.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.io.PrintStream; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class SafePointNode extends MultiNode { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("SafePointNode"); - jvmsField = type.getAddressField("_jvms"); - } - - private static AddressField jvmsField; - - public SafePointNode(Address addr) { - super(addr); - } - - public JVMState jvms() { - return JVMState.create(jvmsField.getValue(getAddress())); - } - - public void dumpSpec(PrintStream out) { - JVMState jvms = jvms(); - if (jvms != null) out.print(" !"); - while (jvms != null) { - Method m = jvms.method().method(); - int bci = jvms.bci(); - out.print(" " + m.getMethodHolder().getName().asString().replace('/', '.') + "::" + m.getName().asString() + " @ bci:" + bci); - jvms = jvms.caller(); - } - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/TypeNode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/TypeNode.java deleted file mode 100644 index 5c0e42cf21f..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/TypeNode.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.opto; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; - -public class TypeNode extends Node { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("TypeNode"); - } - - - public TypeNode(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/CompilerThread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/CompilerThread.java index e5c3ec30887..7e129827c52 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/CompilerThread.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/CompilerThread.java @@ -28,7 +28,6 @@ import java.util.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.ci.*; import sun.jvm.hotspot.utilities.Observable; import sun.jvm.hotspot.utilities.Observer; @@ -43,23 +42,7 @@ public void update(Observable o, Object data) { private static AddressField envField; - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("CompilerThread"); - - envField = type.getAddressField("_env"); - } - - private ciEnv _env; - - public synchronized ciEnv env() { - if (_env == null) { - Address v = envField.getValue(this.getAddress()); - if (v != null) { - _env = new ciEnv(v); - } - } - return _env; - } + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { } public CompilerThread(Address addr) { super(addr); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java index 202217b6071..c558374d23c 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, 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 @@ -29,7 +29,6 @@ import java.util.*; import java.util.regex.*; import sun.jvm.hotspot.code.*; -import sun.jvm.hotspot.c1.*; import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.interpreter.*; @@ -120,8 +119,6 @@ public class VM { private static int Flags_WAS_SET_ON_COMMAND_LINE; /** This is only present in a non-core build */ private CodeCache codeCache; - /** This is only present in a C1 build */ - private Runtime1 runtime1; /** These constants come from globalDefinitions.hpp */ private int invocationEntryBCI; private ReversePtrs revPtrs; @@ -479,7 +476,7 @@ private VM(TypeDataBase db, JVMDebugger debugger, boolean isBigEndian) { usingServerCompiler = false; } else { // Determine whether C2 is present - if (db.lookupType("Matcher", false) != null) { + if (db.lookupIntConstant("COMPILER2") != null) { usingServerCompiler = true; } else { usingClientCompiler = true; @@ -866,17 +863,6 @@ public CodeCache getCodeCache() { return codeCache; } - /** Should only be called for C1 builds */ - public Runtime1 getRuntime1() { - if (Assert.ASSERTS_ENABLED) { - Assert.that(isClientCompiler(), "C1 builds only"); - } - if (runtime1 == null) { - runtime1 = new Runtime1(); - } - return runtime1; - } - /** Test to see whether we're in debugging mode (NOTE: this really should not be tested by this code; currently only used in StackFrameStream) */ diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VMReg.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VMReg.java index 31b2b969530..a3632058b6f 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VMReg.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VMReg.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, 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,9 +38,6 @@ public class VMReg { private int value; - // C2 only - public static Address matcherRegEncodeAddr; - static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -49,13 +46,7 @@ public void update(Observable o, Object data) { }); } - private static void initialize(TypeDataBase db) { - if (VM.getVM().isServerCompiler()) { - Type type = db.lookupType("Matcher"); - Field f = type.getField("_regEncode"); - matcherRegEncodeAddr = f.getStaticFieldAddress(); - } - } + private static void initialize(TypeDataBase db) { } public VMReg(int i) { value = i; @@ -65,13 +56,6 @@ public int getValue() { return value; } - public int regEncode() { - if (matcherRegEncodeAddr != null) { - return (int) matcherRegEncodeAddr.getCIntegerAt(value, 1, true); - } - return value; - } - public boolean equals(Object arg) { if ((arg != null) || (!(arg instanceof VMReg))) { return false; diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java index e3829141683..678ae25f29a 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java @@ -3060,7 +3060,8 @@ ByteVector fromArray(VectorSpecies<Byte> species, return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_IN_RANGE); } - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Byte>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_OUT_OF_RANGE); } @@ -3249,7 +3250,8 @@ ByteVector fromBooleanArray(VectorSpecies<Byte> species, return vsp.dummyVector().fromBooleanArray0(a, offset, m, OFFSET_IN_RANGE); } - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Byte>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); return vsp.dummyVector().fromBooleanArray0(a, offset, m, OFFSET_OUT_OF_RANGE); } @@ -3431,7 +3433,8 @@ ByteVector fromMemorySegment(VectorSpecies<Byte> species, return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_IN_RANGE).maybeSwap(bo); } - checkMaskFromIndexSize(offset, vsp, m, 1, ms.byteSize()); + ((AbstractMask<Byte>)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), 1); return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_OUT_OF_RANGE).maybeSwap(bo); } @@ -3499,7 +3502,8 @@ void intoArray(byte[] a, int offset, } else { ByteSpecies vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.length(), a.length)) { - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Byte>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); } intoArray0(a, offset, m); } @@ -3656,7 +3660,8 @@ void intoBooleanArray(boolean[] a, int offset, } else { ByteSpecies vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.length(), a.length)) { - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Byte>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); } intoBooleanArray0(a, offset, m); } @@ -3788,7 +3793,8 @@ void intoMemorySegment(MemorySegment ms, long offset, } ByteSpecies vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.vectorByteSize(), ms.byteSize())) { - checkMaskFromIndexSize(offset, vsp, m, 1, ms.byteSize()); + ((AbstractMask<Byte>)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), 1); } maybeSwap(bo).intoMemorySegment0(ms, offset, m); } @@ -4040,26 +4046,6 @@ void intoMemorySegment0Template(Class<M> maskClass, MemorySegment ms, long offse // End of low-level memory operations. - private static - void checkMaskFromIndexSize(int offset, - ByteSpecies vsp, - VectorMask<Byte> m, - int scale, - int limit) { - ((AbstractMask<Byte>)m) - .checkIndexByLane(offset, limit, vsp.iota(), scale); - } - - private static - void checkMaskFromIndexSize(long offset, - ByteSpecies vsp, - VectorMask<Byte> m, - int scale, - long limit) { - ((AbstractMask<Byte>)m) - .checkIndexByLane(offset, limit, vsp.iota(), scale); - } - @ForceInline private void conditionalStoreNYI(int offset, ByteSpecies vsp, diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java index cbb21667a15..9f1e7f9ece4 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java @@ -2836,7 +2836,8 @@ DoubleVector fromArray(VectorSpecies<Double> species, return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_IN_RANGE); } - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Double>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_OUT_OF_RANGE); } @@ -3064,7 +3065,8 @@ DoubleVector fromMemorySegment(VectorSpecies<Double> species, return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_IN_RANGE).maybeSwap(bo); } - checkMaskFromIndexSize(offset, vsp, m, 8, ms.byteSize()); + ((AbstractMask<Double>)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), 8); return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_OUT_OF_RANGE).maybeSwap(bo); } @@ -3132,7 +3134,8 @@ void intoArray(double[] a, int offset, } else { DoubleSpecies vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.length(), a.length)) { - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Double>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); } intoArray0(a, offset, m); } @@ -3290,7 +3293,8 @@ void intoMemorySegment(MemorySegment ms, long offset, } DoubleSpecies vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.vectorByteSize(), ms.byteSize())) { - checkMaskFromIndexSize(offset, vsp, m, 8, ms.byteSize()); + ((AbstractMask<Double>)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), 8); } maybeSwap(bo).intoMemorySegment0(ms, offset, m); } @@ -3554,26 +3558,6 @@ void intoMemorySegment0Template(Class<M> maskClass, MemorySegment ms, long offse // End of low-level memory operations. - private static - void checkMaskFromIndexSize(int offset, - DoubleSpecies vsp, - VectorMask<Double> m, - int scale, - int limit) { - ((AbstractMask<Double>)m) - .checkIndexByLane(offset, limit, vsp.iota(), scale); - } - - private static - void checkMaskFromIndexSize(long offset, - DoubleSpecies vsp, - VectorMask<Double> m, - int scale, - long limit) { - ((AbstractMask<Double>)m) - .checkIndexByLane(offset, limit, vsp.iota(), scale); - } - @ForceInline private void conditionalStoreNYI(int offset, DoubleSpecies vsp, diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java index 78259e7698b..cef1b431bf0 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java @@ -2860,7 +2860,8 @@ FloatVector fromArray(VectorSpecies<Float> species, return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_IN_RANGE); } - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Float>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_OUT_OF_RANGE); } @@ -3070,7 +3071,8 @@ FloatVector fromMemorySegment(VectorSpecies<Float> species, return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_IN_RANGE).maybeSwap(bo); } - checkMaskFromIndexSize(offset, vsp, m, 4, ms.byteSize()); + ((AbstractMask<Float>)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), 4); return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_OUT_OF_RANGE).maybeSwap(bo); } @@ -3138,7 +3140,8 @@ void intoArray(float[] a, int offset, } else { FloatSpecies vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.length(), a.length)) { - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Float>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); } intoArray0(a, offset, m); } @@ -3277,7 +3280,8 @@ void intoMemorySegment(MemorySegment ms, long offset, } FloatSpecies vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.vectorByteSize(), ms.byteSize())) { - checkMaskFromIndexSize(offset, vsp, m, 4, ms.byteSize()); + ((AbstractMask<Float>)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), 4); } maybeSwap(bo).intoMemorySegment0(ms, offset, m); } @@ -3504,26 +3508,6 @@ void intoMemorySegment0Template(Class<M> maskClass, MemorySegment ms, long offse // End of low-level memory operations. - private static - void checkMaskFromIndexSize(int offset, - FloatSpecies vsp, - VectorMask<Float> m, - int scale, - int limit) { - ((AbstractMask<Float>)m) - .checkIndexByLane(offset, limit, vsp.iota(), scale); - } - - private static - void checkMaskFromIndexSize(long offset, - FloatSpecies vsp, - VectorMask<Float> m, - int scale, - long limit) { - ((AbstractMask<Float>)m) - .checkIndexByLane(offset, limit, vsp.iota(), scale); - } - @ForceInline private void conditionalStoreNYI(int offset, FloatSpecies vsp, diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java index d68bba1d7e2..e11381e82c5 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, 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 @@ -3038,7 +3038,8 @@ IntVector fromArray(VectorSpecies<Integer> species, return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_IN_RANGE); } - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Integer>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_OUT_OF_RANGE); } @@ -3248,7 +3249,8 @@ IntVector fromMemorySegment(VectorSpecies<Integer> species, return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_IN_RANGE).maybeSwap(bo); } - checkMaskFromIndexSize(offset, vsp, m, 4, ms.byteSize()); + ((AbstractMask<Integer>)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), 4); return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_OUT_OF_RANGE).maybeSwap(bo); } @@ -3316,7 +3318,8 @@ void intoArray(int[] a, int offset, } else { IntSpecies vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.length(), a.length)) { - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Integer>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); } intoArray0(a, offset, m); } @@ -3455,7 +3458,8 @@ void intoMemorySegment(MemorySegment ms, long offset, } IntSpecies vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.vectorByteSize(), ms.byteSize())) { - checkMaskFromIndexSize(offset, vsp, m, 4, ms.byteSize()); + ((AbstractMask<Integer>)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), 4); } maybeSwap(bo).intoMemorySegment0(ms, offset, m); } @@ -3682,26 +3686,6 @@ void intoMemorySegment0Template(Class<M> maskClass, MemorySegment ms, long offse // End of low-level memory operations. - private static - void checkMaskFromIndexSize(int offset, - IntSpecies vsp, - VectorMask<Integer> m, - int scale, - int limit) { - ((AbstractMask<Integer>)m) - .checkIndexByLane(offset, limit, vsp.iota(), scale); - } - - private static - void checkMaskFromIndexSize(long offset, - IntSpecies vsp, - VectorMask<Integer> m, - int scale, - long limit) { - ((AbstractMask<Integer>)m) - .checkIndexByLane(offset, limit, vsp.iota(), scale); - } - @ForceInline private void conditionalStoreNYI(int offset, IntSpecies vsp, diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java index 1fa1cafac4e..4d54fbf7ad3 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java @@ -2899,7 +2899,8 @@ LongVector fromArray(VectorSpecies<Long> species, return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_IN_RANGE); } - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Long>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_OUT_OF_RANGE); } @@ -3127,7 +3128,8 @@ LongVector fromMemorySegment(VectorSpecies<Long> species, return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_IN_RANGE).maybeSwap(bo); } - checkMaskFromIndexSize(offset, vsp, m, 8, ms.byteSize()); + ((AbstractMask<Long>)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), 8); return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_OUT_OF_RANGE).maybeSwap(bo); } @@ -3195,7 +3197,8 @@ void intoArray(long[] a, int offset, } else { LongSpecies vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.length(), a.length)) { - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Long>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); } intoArray0(a, offset, m); } @@ -3353,7 +3356,8 @@ void intoMemorySegment(MemorySegment ms, long offset, } LongSpecies vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.vectorByteSize(), ms.byteSize())) { - checkMaskFromIndexSize(offset, vsp, m, 8, ms.byteSize()); + ((AbstractMask<Long>)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), 8); } maybeSwap(bo).intoMemorySegment0(ms, offset, m); } @@ -3617,26 +3621,6 @@ void intoMemorySegment0Template(Class<M> maskClass, MemorySegment ms, long offse // End of low-level memory operations. - private static - void checkMaskFromIndexSize(int offset, - LongSpecies vsp, - VectorMask<Long> m, - int scale, - int limit) { - ((AbstractMask<Long>)m) - .checkIndexByLane(offset, limit, vsp.iota(), scale); - } - - private static - void checkMaskFromIndexSize(long offset, - LongSpecies vsp, - VectorMask<Long> m, - int scale, - long limit) { - ((AbstractMask<Long>)m) - .checkIndexByLane(offset, limit, vsp.iota(), scale); - } - @ForceInline private void conditionalStoreNYI(int offset, LongSpecies vsp, diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java index 19d7fa1d95e..92ca4b1ca70 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java @@ -3061,7 +3061,8 @@ ShortVector fromArray(VectorSpecies<Short> species, return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_IN_RANGE); } - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Short>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_OUT_OF_RANGE); } @@ -3242,7 +3243,8 @@ ShortVector fromCharArray(VectorSpecies<Short> species, return vsp.dummyVector().fromCharArray0(a, offset, m, OFFSET_IN_RANGE); } - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Short>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); return vsp.dummyVector().fromCharArray0(a, offset, m, OFFSET_OUT_OF_RANGE); } @@ -3430,7 +3432,8 @@ ShortVector fromMemorySegment(VectorSpecies<Short> species, return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_IN_RANGE).maybeSwap(bo); } - checkMaskFromIndexSize(offset, vsp, m, 2, ms.byteSize()); + ((AbstractMask<Short>)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), 2); return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_OUT_OF_RANGE).maybeSwap(bo); } @@ -3498,7 +3501,8 @@ void intoArray(short[] a, int offset, } else { ShortSpecies vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.length(), a.length)) { - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Short>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); } intoArray0(a, offset, m); } @@ -3647,7 +3651,8 @@ void intoCharArray(char[] a, int offset, } else { ShortSpecies vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.length(), a.length)) { - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<Short>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); } intoCharArray0(a, offset, m); } @@ -3774,7 +3779,8 @@ void intoMemorySegment(MemorySegment ms, long offset, } ShortSpecies vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.vectorByteSize(), ms.byteSize())) { - checkMaskFromIndexSize(offset, vsp, m, 2, ms.byteSize()); + ((AbstractMask<Short>)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), 2); } maybeSwap(bo).intoMemorySegment0(ms, offset, m); } @@ -4026,26 +4032,6 @@ a, charArrayAddress(a, offset), false, // End of low-level memory operations. - private static - void checkMaskFromIndexSize(int offset, - ShortSpecies vsp, - VectorMask<Short> m, - int scale, - int limit) { - ((AbstractMask<Short>)m) - .checkIndexByLane(offset, limit, vsp.iota(), scale); - } - - private static - void checkMaskFromIndexSize(long offset, - ShortSpecies vsp, - VectorMask<Short> m, - int scale, - long limit) { - ((AbstractMask<Short>)m) - .checkIndexByLane(offset, limit, vsp.iota(), scale); - } - @ForceInline private void conditionalStoreNYI(int offset, ShortSpecies vsp, diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template index 05979330ab1..235641b57a0 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template @@ -3666,7 +3666,8 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_IN_RANGE); } - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<$Boxtype$>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); return vsp.dummyVector().fromArray0(a, offset, m, OFFSET_OUT_OF_RANGE); } @@ -3902,7 +3903,8 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { return vsp.dummyVector().fromCharArray0(a, offset, m, OFFSET_IN_RANGE); } - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<$Boxtype$>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); return vsp.dummyVector().fromCharArray0(a, offset, m, OFFSET_OUT_OF_RANGE); } @@ -4061,7 +4063,8 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { return vsp.dummyVector().fromBooleanArray0(a, offset, m, OFFSET_IN_RANGE); } - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<$Boxtype$>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); return vsp.dummyVector().fromBooleanArray0(a, offset, m, OFFSET_OUT_OF_RANGE); } @@ -4253,7 +4256,8 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_IN_RANGE).maybeSwap(bo); } - checkMaskFromIndexSize(offset, vsp, m, $sizeInBytes$, ms.byteSize()); + ((AbstractMask<$Boxtype$>)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), $sizeInBytes$); return vsp.dummyVector().fromMemorySegment0(ms, offset, m, OFFSET_OUT_OF_RANGE).maybeSwap(bo); } @@ -4321,7 +4325,8 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { } else { $Type$Species vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.length(), a.length)) { - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<$Boxtype$>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); } intoArray0(a, offset, m); } @@ -4541,7 +4546,8 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { } else { $Type$Species vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.length(), a.length)) { - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<$Boxtype$>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); } intoCharArray0(a, offset, m); } @@ -4705,7 +4711,8 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { } else { $Type$Species vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.length(), a.length)) { - checkMaskFromIndexSize(offset, vsp, m, 1, a.length); + ((AbstractMask<$Boxtype$>)m) + .checkIndexByLane(offset, a.length, vsp.iota(), 1); } intoBooleanArray0(a, offset, m); } @@ -4838,7 +4845,8 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { } $Type$Species vsp = vspecies(); if (!VectorIntrinsics.indexInRange(offset, vsp.vectorByteSize(), ms.byteSize())) { - checkMaskFromIndexSize(offset, vsp, m, $sizeInBytes$, ms.byteSize()); + ((AbstractMask<$Boxtype$>)m) + .checkIndexByLane(offset, ms.byteSize(), vsp.iota(), $sizeInBytes$); } maybeSwap(bo).intoMemorySegment0(ms, offset, m); } @@ -5263,26 +5271,6 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { // End of low-level memory operations. - private static - void checkMaskFromIndexSize(int offset, - $Type$Species vsp, - VectorMask<$Boxtype$> m, - int scale, - int limit) { - ((AbstractMask<$Boxtype$>)m) - .checkIndexByLane(offset, limit, vsp.iota(), scale); - } - - private static - void checkMaskFromIndexSize(long offset, - $Type$Species vsp, - VectorMask<$Boxtype$> m, - int scale, - long limit) { - ((AbstractMask<$Boxtype$>)m) - .checkIndexByLane(offset, limit, vsp.iota(), scale); - } - @ForceInline private void conditionalStoreNYI(int offset, $Type$Species vsp, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java index 49dfdcea5a2..2cd5e839ee8 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java @@ -63,6 +63,10 @@ import static jdk.vm.ci.hotspot.HotSpotCompiledCodeStream.Tag.STACK_SLOT_OOP; import static jdk.vm.ci.hotspot.HotSpotCompiledCodeStream.Tag.STACK_SLOT_PRIMITIVE; import static jdk.vm.ci.hotspot.HotSpotCompiledCodeStream.Tag.STACK_SLOT_VECTOR; +import static jdk.vm.ci.hotspot.HotSpotCompiledCodeStream.Tag.STACK_SLOT4_NARROW_OOP; +import static jdk.vm.ci.hotspot.HotSpotCompiledCodeStream.Tag.STACK_SLOT4_OOP; +import static jdk.vm.ci.hotspot.HotSpotCompiledCodeStream.Tag.STACK_SLOT4_PRIMITIVE; +import static jdk.vm.ci.hotspot.HotSpotCompiledCodeStream.Tag.STACK_SLOT4_VECTOR; import static jdk.vm.ci.hotspot.HotSpotCompiledCodeStream.Tag.VIRTUAL_OBJECT_ID; import static jdk.vm.ci.hotspot.HotSpotCompiledCodeStream.Tag.VIRTUAL_OBJECT_ID2; @@ -178,6 +182,10 @@ enum Tag { STACK_SLOT_OOP, STACK_SLOT_NARROW_OOP, STACK_SLOT_VECTOR, + STACK_SLOT4_PRIMITIVE, + STACK_SLOT4_OOP, + STACK_SLOT4_NARROW_OOP, + STACK_SLOT4_VECTOR, VIRTUAL_OBJECT_ID, VIRTUAL_OBJECT_ID2, NULL_CONSTANT, @@ -457,8 +465,12 @@ private void writeU2(String name, int value) { rawWriteU2(name, value); } + private static boolean isS2(int value) { + return value >= Short.MIN_VALUE && value <= Short.MAX_VALUE; + } + private void writeS2(String name, int value) { - if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { + if (!isS2(value)) { throw error("value not an s2: " + value); } rawWriteU2(name, value); @@ -581,7 +593,8 @@ private String codeDesc() { writeInt("targetCodeSize", code.targetCodeSize); writeInt("totalFrameSize", code.totalFrameSize); if (isSet(flags, HAS_DEOPT_RESCUE_SLOT)) { - writeS2("offset", deoptRescueSlot.getRawOffset()); + int offset = deoptRescueSlot.getRawOffset(); + writeInt("offset", offset); writeBoolean("addRawFrameSize", deoptRescueSlot.getRawAddFrameSize()); } writeInt("dataSectionSize", code.dataSection.length); @@ -1063,17 +1076,25 @@ private void writeJavaValue(JavaValue value, JavaKind kind) { } else if (value instanceof StackSlot) { StackSlot slot = (StackSlot) value; Tag tag; + int offset = slot.getRawOffset(); + boolean s2 = isS2(offset); if (kind == JavaKind.Object) { if (isVector(slot)) { - tag = STACK_SLOT_VECTOR; + tag = s2 ? STACK_SLOT_VECTOR : STACK_SLOT4_VECTOR; + } else if (isNarrowOop(slot)) { + tag = s2 ? STACK_SLOT_NARROW_OOP : STACK_SLOT4_NARROW_OOP; } else { - tag = isNarrowOop(slot) ? STACK_SLOT_NARROW_OOP : STACK_SLOT_OOP; + tag = s2 ? STACK_SLOT_OOP : STACK_SLOT4_OOP; } } else { - tag = STACK_SLOT_PRIMITIVE; + tag = s2 ? STACK_SLOT_PRIMITIVE : STACK_SLOT4_PRIMITIVE; } writeTag(tag); - writeS2("offset", slot.getRawOffset()); + if (s2) { + writeS2("offset", slot.getRawOffset()); + } else { + writeInt("offset4", slot.getRawOffset()); + } writeBoolean("addRawFrameSize", slot.getRawAddFrameSize()); } else if (value instanceof VirtualObject) { VirtualObject vo = (VirtualObject) value; diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java index ae6893c021b..baedbf85205 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java +++ b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, 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 @@ -243,7 +243,6 @@ private static File createTempFileInSameDirectoryAs(File file) /** * Starts main program with the specified arguments. */ - @SuppressWarnings({"removal"}) public synchronized boolean run(String[] args) { ok = true; if (!parseArgs(args)) { @@ -1364,7 +1363,6 @@ void replaceFSC(Map<Integer, String []> filesMap) { }); } - @SuppressWarnings("serial") Set<ZipEntry> newDirSet() { return new HashSet<ZipEntry>() { public boolean add(ZipEntry e) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/SnippetTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/SnippetTaglet.java index 93f83c5ba90..37333552e10 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/SnippetTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/SnippetTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,8 +26,6 @@ package jdk.javadoc.internal.doclets.formats.html.taglets; import java.io.IOException; -import java.net.URI; -import java.nio.file.Path; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; @@ -133,43 +131,39 @@ private Content snippetTagOutput(Element element, SnippetTree tag, StyledText co if (lang != null && !lang.isBlank()) { code.addStyle("language-" + lang); } - content.consumeBy((styles, sequence) -> { CharSequence text = Text.normalizeNewlines(sequence); if (styles.isEmpty()) { code.add(text); } else { Element e = null; - String t = null; - boolean linkEncountered = false; + String linkTarget = null; boolean markupEncountered = false; Set<String> classes = new HashSet<>(); for (Style s : styles) { - if (s instanceof Style.Name n) { - classes.add(n.name()); - } else if (s instanceof Style.Link l) { - assert !linkEncountered; // TODO: do not assert; pick the first link report on subsequent - linkEncountered = true; - t = l.target(); - e = getLinkedElement(element, t); - if (e == null) { - // TODO: diagnostic output + switch (s) { + case Style.Name n -> classes.add(n.name()); + case Style.Link l -> { + if (linkTarget != null) { + messages.error(utils.getCommentHelper(element).getDocTreePath(tag), + "doclet.error.snippet.ambiguous.link", + linkTarget, + l.target(), + content.asCharSequence().toString().trim()); + } + linkTarget = l.target(); + e = getLinkedElement(element, linkTarget); + if (e == null) { + // TODO: diagnostic output + } } - } else if (s instanceof Style.Markup) { - markupEncountered = true; - break; - } else { - // TODO: transform this if...else into an exhaustive - // switch over the sealed Style hierarchy when "Pattern - // Matching for switch" has been implemented (JEP 406 - // and friends) - throw new AssertionError(styles); + case Style.Markup m -> markupEncountered = true; } } Content c; if (markupEncountered) { return; - } else if (linkEncountered) { + } else if (linkTarget != null) { assert e != null; //disable preview tagging inside the snippets: Utils.PreviewFlagProvider prevPreviewProvider = utils.setPreviewFlagProvider(el -> false); @@ -177,7 +171,7 @@ private Content snippetTagOutput(Element element, SnippetTree tag, StyledText co var lt = (LinkTaglet) config.tagletManager.getTaglet(DocTree.Kind.LINK); c = lt.linkSeeReferenceOutput(element, null, - t, + linkTarget, e, false, // TODO: for now Text.of(sequence.toString()), diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties index 0ee9429ec0c..6b1cd9b0fc8 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2025, 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 @@ -432,3 +432,7 @@ doclet.cannot_use_snippet_path=\ # 0: path; 1: exception doclet.error_setting_snippet_path=\ Error setting snippet path {0}: {1} + +# 0: location +doclet.error.snippet.ambiguous.link=\ + snippet link tags: {0} and {1} overlap in {2} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java index 22377715a1e..ea61d79a6c0 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -336,7 +336,6 @@ Archive targetArchive() { } @Override - @SuppressWarnings("unchecked") public boolean equals(Object o) { if (o instanceof Dep) { Dep d = (Dep) o; diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Dependencies.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Dependencies.java index c0ac835f4b6..90682c478c7 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Dependencies.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Dependencies.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,6 @@ public class Dependencies { /** * Thrown when a class file cannot be found. */ - @SuppressWarnings("this-escape") public static class ClassFileNotFoundException extends Exception { private static final long serialVersionUID = 3632265927794475048L; @@ -76,7 +75,6 @@ public ClassFileNotFoundException(String className, Throwable cause) { /** * Thrown when an exception is found processing a class file. */ - @SuppressWarnings("this-escape") public static class ClassFileError extends Error { private static final long serialVersionUID = 4111110813961313203L; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java index e664f2c728b..67143ee1265 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java @@ -127,7 +127,11 @@ private ChunkParser(ChunkHeader header, ChunkParser previous, ParserConfiguratio this.configuration = previous.configuration; } this.metadata = header.readMetadata(previousMetadata); - this.timeConverter = new TimeConverter(chunkHeader, metadata.getGMTOffset() + metadata.getDST()); + if (previous == null) { + this.timeConverter = new TimeConverter(chunkHeader, metadata.getGMTOffset() + metadata.getDST()); + } else { + this.timeConverter = previous.timeConverter; + } if (metadata != previousMetadata) { ParserFactory factory = new ParserFactory(metadata, constantLookups, timeConverter); parsers = factory.getParsers(); diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/VersionPropsPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/VersionPropsPlugin.java index 86f68098453..a07661fd339 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/VersionPropsPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/VersionPropsPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -99,7 +99,6 @@ public void configure(Map<String, String> config) { private boolean redefined = false; - @SuppressWarnings("deprecation") private byte[] redefine(String path, byte[] classFile) { return ClassFile.of().transformClass(newClassReader(path, classFile), ClassTransform.transformingMethodBodies( diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java index 69ecce068e7..beb8072ea37 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,16 +102,20 @@ public abstract class MacBaseInstallerBundler extends AbstractBundler { static String getInstallDir( Map<String, ? super Object> params, boolean defaultOnly) { String returnValue = INSTALL_DIR.fetchFrom(params); - if (defaultOnly && returnValue != null) { - Log.info(I18N.getString("message.install-dir-ignored")); + + final String defaultInstallDir; + if (StandardBundlerParam.isRuntimeInstaller(params)) { + defaultInstallDir = "/Library/Java/JavaVirtualMachines"; + } else { + defaultInstallDir = "/Applications"; + } + + if (defaultOnly && returnValue != null && !Path.of(returnValue).equals(Path.of(defaultInstallDir))) { + Log.info(MessageFormat.format(I18N.getString("message.install-dir-ignored"), defaultInstallDir)); returnValue = null; } if (returnValue == null) { - if (StandardBundlerParam.isRuntimeInstaller(params)) { - returnValue = "/Library/Java/JavaVirtualMachines"; - } else { - returnValue = "/Applications"; - } + returnValue = defaultInstallDir; } return returnValue; } diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties index e0a555b3698..2f6d5b02bb6 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -91,7 +91,7 @@ message.preparing-scripts=Preparing package scripts. message.preparing-distribution-dist=Preparing distribution.dist: {0}. message.signing.pkg=Warning: For signing PKG, you might need to set "Always Trust" for your certificate using "Keychain Access" tool. message.setfile.dmg=Setting custom icon on DMG file skipped because 'SetFile' utility was not found. Installing Xcode with Command Line Tools should resolve this issue. -message.install-dir-ignored=Warning: "--install-dir" is not supported by DMG and will be default to /Applications. +message.install-dir-ignored=Warning: "--install-dir" option is ignored for DMG packaging. The installation directory will default to {0}. message.codesign.failed.reason.app.content="codesign" failed and additional application content was supplied via the "--app-content" parameter. Probably the additional content broke the integrity of the application bundle and caused the failure. Ensure content supplied via the "--app-content" parameter does not break the integrity of the application bundle, or add it in the post-processing step. message.codesign.failed.reason.xcode.tools=Possible reason for "codesign" failure is missing Xcode with command line developer tools. Install Xcode with command line developer tools to see if it resolves the problem. warning.unsigned.app.image=Warning: Using unsigned app-image to build signed {0}. diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BundlerParamInfo.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BundlerParamInfo.java index fa99073ff7f..48499dcf29c 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BundlerParamInfo.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BundlerParamInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -94,7 +94,6 @@ boolean getIsDefaultValue(Map<String, ? super Object> params) { return stringConverter; } - @SuppressWarnings("unchecked") final T fetchFrom(Map<String, ? super Object> params) { return fetchFrom(params, true); } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java index 0209eea584a..ec5b1aceaab 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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,7 +276,6 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> { (s, p) -> s ); - @SuppressWarnings("unchecked") public static final StandardBundlerParam<String> LICENSE_FILE = new StandardBundlerParam<>( Arguments.CLIOptions.LICENSE_FILE.getId(), diff --git a/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java b/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java index f18fa429339..0c80b6d4388 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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 @@ -148,9 +148,9 @@ public String toString() { ",previousStatus=" + previousStatus + ",status=" + status + ",isSignatureChange=" + isSignatureChange + - ",causeSnippet" + causeSnippet + - (value == null? "" : "value=" + value) + - (exception == null? "" : "exception=" + exception) + + ",causeSnippet=" + causeSnippet + + (value == null? "" : ",value=" + value) + + (exception == null? "" : ",exception=" + exception) + ")"; } } diff --git a/src/jdk.management/windows/native/libmanagement_ext/OperatingSystemImpl.c b/src/jdk.management/windows/native/libmanagement_ext/OperatingSystemImpl.c index 3cfd4679134..37c30bbc898 100644 --- a/src/jdk.management/windows/native/libmanagement_ext/OperatingSystemImpl.c +++ b/src/jdk.management/windows/native/libmanagement_ext/OperatingSystemImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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 @@ -436,13 +436,13 @@ makeFullCounterPath(const char* const objectName, return NULL; } - snprintf(fullCounterPath, - fullCounterPathLen, - PROCESS_OBJECT_INSTANCE_COUNTER_FMT, - objectName, - imageName, - instance, - counterName); + _snprintf(fullCounterPath, + fullCounterPathLen, + PROCESS_OBJECT_INSTANCE_COUNTER_FMT, + objectName, + imageName, + instance, + counterName); } else { if (instance) { /* @@ -472,18 +472,18 @@ makeFullCounterPath(const char* const objectName, } if (instance) { - snprintf(fullCounterPath, - fullCounterPathLen, - OBJECT_WITH_INSTANCES_COUNTER_FMT, - objectName, - instance, - counterName); + _snprintf(fullCounterPath, + fullCounterPathLen, + OBJECT_WITH_INSTANCES_COUNTER_FMT, + objectName, + instance, + counterName); } else { - snprintf(fullCounterPath, - fullCounterPathLen, - OBJECT_COUNTER_FMT, - objectName, - counterName); + _snprintf(fullCounterPath, + fullCounterPathLen, + OBJECT_COUNTER_FMT, + objectName, + counterName); } } @@ -719,10 +719,10 @@ currentQueryIndexForProcess(void) { PDH_FMT_COUNTERVALUE counterValue; PDH_STATUS res; - snprintf(fullIDProcessCounterPath, - MAX_PATH, - pdhIDProcessCounterFmt, - index); + _snprintf(fullIDProcessCounterPath, + MAX_PATH, + pdhIDProcessCounterFmt, + index); if (addCounter(tmpQuery, fullIDProcessCounterPath, &handleCounter) != 0) { break; @@ -1059,13 +1059,13 @@ allocateAndInitializePdhConstants() { } /* "\Process(java#%d)\ID Process" */ - snprintf(pdhIDProcessCounterFmt, - pdhIDProcessCounterFmtLen, - PROCESS_OBJECT_INSTANCE_COUNTER_FMT, - pdhLocalizedProcessObject, - pdhProcessImageName, - "%d", - pdhLocalizedIDProcessCounter); + _snprintf(pdhIDProcessCounterFmt, + pdhIDProcessCounterFmtLen, + PROCESS_OBJECT_INSTANCE_COUNTER_FMT, + pdhLocalizedProcessObject, + pdhProcessImageName, + "%d", + pdhLocalizedIDProcessCounter); pdhIDProcessCounterFmt[pdhIDProcessCounterFmtLen] = '\0'; diff --git a/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/ReferenceWrapper_Stub.java b/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/ReferenceWrapper_Stub.java index 211da640e20..6cac42e63f2 100644 --- a/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/ReferenceWrapper_Stub.java +++ b/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/ReferenceWrapper_Stub.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ /** * ReferenceWrapper_Stub. */ -@SuppressWarnings({"deprecation", "rawtypes", "unchecked"}) +@SuppressWarnings({"deprecation", "rawtypes"}) public final class ReferenceWrapper_Stub extends java.rmi.server.RemoteStub implements com.sun.jndi.rmi.registry.RemoteReference, java.rmi.Remote { diff --git a/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java b/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java index 2f77c383bd6..337f00fd7c7 100644 --- a/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java +++ b/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, 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 diff --git a/test/hotspot/gtest/aarch64/aarch64-asmtest.py b/test/hotspot/gtest/aarch64/aarch64-asmtest.py index 64f3e787356..45ecf57e971 100644 --- a/test/hotspot/gtest/aarch64/aarch64-asmtest.py +++ b/test/hotspot/gtest/aarch64/aarch64-asmtest.py @@ -1833,6 +1833,11 @@ def generate(kind, names): ["sminp", "sminp", "8B"], ["sminp", "sminp", "16B"], ["sminp", "sminp", "4H"], ["sminp", "sminp", "8H"], ["sminp", "sminp", "2S"], ["sminp", "sminp", "4S"], + ["sqdmulh", "sqdmulh", "4H"], ["sqdmulh", "sqdmulh", "8H"], + ["sqdmulh", "sqdmulh", "2S"], ["sqdmulh", "sqdmulh", "4S"], + ["shsubv", "shsub", "8B"], ["shsubv", "shsub", "16B"], + ["shsubv", "shsub", "4H"], ["shsubv", "shsub", "8H"], + ["shsubv", "shsub", "2S"], ["shsubv", "shsub", "4S"], ["fmin", "fmin", "2S"], ["fmin", "fmin", "4S"], ["fmin", "fmin", "2D"], ["facgt", "facgt", "2S"], ["facgt", "facgt", "4S"], diff --git a/test/hotspot/gtest/aarch64/asmtest.out.h b/test/hotspot/gtest/aarch64/asmtest.out.h index 9805a05c5c1..3bcd40ba2aa 100644 --- a/test/hotspot/gtest/aarch64/asmtest.out.h +++ b/test/hotspot/gtest/aarch64/asmtest.out.h @@ -745,93 +745,103 @@ __ sminp(v2, __ T8H, v3, v4); // sminp v2.8H, v3.8H, v4.8H __ sminp(v0, __ T2S, v1, v2); // sminp v0.2S, v1.2S, v2.2S __ sminp(v9, __ T4S, v10, v11); // sminp v9.4S, v10.4S, v11.4S - __ fmin(v24, __ T2S, v25, v26); // fmin v24.2S, v25.2S, v26.2S - __ fmin(v26, __ T4S, v27, v28); // fmin v26.4S, v27.4S, v28.4S - __ fmin(v16, __ T2D, v17, v18); // fmin v16.2D, v17.2D, v18.2D - __ facgt(v30, __ T2S, v31, v0); // facgt v30.2S, v31.2S, v0.2S - __ facgt(v3, __ T4S, v4, v5); // facgt v3.4S, v4.4S, v5.4S - __ facgt(v10, __ T2D, v11, v12); // facgt v10.2D, v11.2D, v12.2D + __ sqdmulh(v24, __ T4H, v25, v26); // sqdmulh v24.4H, v25.4H, v26.4H + __ sqdmulh(v26, __ T8H, v27, v28); // sqdmulh v26.8H, v27.8H, v28.8H + __ sqdmulh(v16, __ T2S, v17, v18); // sqdmulh v16.2S, v17.2S, v18.2S + __ sqdmulh(v30, __ T4S, v31, v0); // sqdmulh v30.4S, v31.4S, v0.4S + __ shsubv(v3, __ T8B, v4, v5); // shsub v3.8B, v4.8B, v5.8B + __ shsubv(v10, __ T16B, v11, v12); // shsub v10.16B, v11.16B, v12.16B + __ shsubv(v23, __ T4H, v24, v25); // shsub v23.4H, v24.4H, v25.4H + __ shsubv(v10, __ T8H, v11, v12); // shsub v10.8H, v11.8H, v12.8H + __ shsubv(v4, __ T2S, v5, v6); // shsub v4.2S, v5.2S, v6.2S + __ shsubv(v18, __ T4S, v19, v20); // shsub v18.4S, v19.4S, v20.4S + __ fmin(v2, __ T2S, v3, v4); // fmin v2.2S, v3.2S, v4.2S + __ fmin(v11, __ T4S, v12, v13); // fmin v11.4S, v12.4S, v13.4S + __ fmin(v8, __ T2D, v9, v10); // fmin v8.2D, v9.2D, v10.2D + __ facgt(v10, __ T2S, v11, v12); // facgt v10.2S, v11.2S, v12.2S + __ facgt(v15, __ T4S, v16, v17); // facgt v15.4S, v16.4S, v17.4S + __ facgt(v17, __ T2D, v18, v19); // facgt v17.2D, v18.2D, v19.2D // VectorScalarNEONInstruction - __ fmlavs(v5, __ T2S, v6, v7, 1); // fmla v5.2S, v6.2S, v7.S[1] - __ mulvs(v9, __ T4S, v10, v11, 0); // mul v9.4S, v10.4S, v11.S[0] - __ fmlavs(v5, __ T2D, v6, v7, 0); // fmla v5.2D, v6.2D, v7.D[0] - __ fmlsvs(v5, __ T2S, v6, v7, 0); // fmls v5.2S, v6.2S, v7.S[0] - __ mulvs(v8, __ T4S, v9, v10, 1); // mul v8.4S, v9.4S, v10.S[1] - __ fmlsvs(v5, __ T2D, v6, v7, 0); // fmls v5.2D, v6.2D, v7.D[0] - __ fmulxvs(v6, __ T2S, v7, v8, 0); // fmulx v6.2S, v7.2S, v8.S[0] + __ fmlavs(v5, __ T2S, v6, v7, 0); // fmla v5.2S, v6.2S, v7.S[0] __ mulvs(v6, __ T4S, v7, v8, 1); // mul v6.4S, v7.4S, v8.S[1] - __ fmulxvs(v3, __ T2D, v4, v5, 0); // fmulx v3.2D, v4.2D, v5.D[0] - __ mulvs(v13, __ T4H, v14, v15, 2); // mul v13.4H, v14.4H, v15.H[2] - __ mulvs(v2, __ T8H, v3, v4, 4); // mul v2.8H, v3.8H, v4.H[4] - __ mulvs(v2, __ T2S, v3, v4, 0); // mul v2.2S, v3.2S, v4.S[0] + __ fmlavs(v6, __ T2D, v7, v8, 0); // fmla v6.2D, v7.2D, v8.D[0] + __ fmlsvs(v3, __ T2S, v4, v5, 0); // fmls v3.2S, v4.2S, v5.S[0] + __ mulvs(v13, __ T4S, v14, v15, 2); // mul v13.4S, v14.4S, v15.S[2] + __ fmlsvs(v2, __ T2D, v3, v4, 1); // fmls v2.2D, v3.2D, v4.D[1] + __ fmulxvs(v2, __ T2S, v3, v4, 0); // fmulx v2.2S, v3.2S, v4.S[0] __ mulvs(v9, __ T4S, v10, v11, 1); // mul v9.4S, v10.4S, v11.S[1] + __ fmulxvs(v8, __ T2D, v9, v10, 1); // fmulx v8.2D, v9.2D, v10.D[1] + __ mulvs(v5, __ T4H, v6, v7, 2); // mul v5.4H, v6.4H, v7.H[2] + __ mulvs(v11, __ T8H, v12, v13, 5); // mul v11.8H, v12.8H, v13.H[5] + __ mulvs(v13, __ T2S, v14, v15, 0); // mul v13.2S, v14.2S, v15.S[0] + __ mulvs(v14, __ T4S, v15, v16, 2); // mul v14.4S, v15.4S, v16.S[2] // NEONVectorCompare - __ cm(Assembler::GT, v21, __ T8B, v22, v23); // cmgt v21.8B, v22.8B, v23.8B - __ cm(Assembler::GT, v16, __ T16B, v17, v18); // cmgt v16.16B, v17.16B, v18.16B - __ cm(Assembler::GT, v18, __ T4H, v19, v20); // cmgt v18.4H, v19.4H, v20.4H - __ cm(Assembler::GT, v11, __ T8H, v12, v13); // cmgt v11.8H, v12.8H, v13.8H - __ cm(Assembler::GT, v21, __ T2S, v22, v23); // cmgt v21.2S, v22.2S, v23.2S - __ cm(Assembler::GT, v23, __ T4S, v24, v25); // cmgt v23.4S, v24.4S, v25.4S - __ cm(Assembler::GT, v12, __ T2D, v13, v14); // cmgt v12.2D, v13.2D, v14.2D - __ cm(Assembler::GE, v26, __ T8B, v27, v28); // cmge v26.8B, v27.8B, v28.8B - __ cm(Assembler::GE, v23, __ T16B, v24, v25); // cmge v23.16B, v24.16B, v25.16B - __ cm(Assembler::GE, v28, __ T4H, v29, v30); // cmge v28.4H, v29.4H, v30.4H - __ cm(Assembler::GE, v14, __ T8H, v15, v16); // cmge v14.8H, v15.8H, v16.8H - __ cm(Assembler::GE, v11, __ T2S, v12, v13); // cmge v11.2S, v12.2S, v13.2S - __ cm(Assembler::GE, v24, __ T4S, v25, v26); // cmge v24.4S, v25.4S, v26.4S - __ cm(Assembler::GE, v1, __ T2D, v2, v3); // cmge v1.2D, v2.2D, v3.2D - __ cm(Assembler::EQ, v12, __ T8B, v13, v14); // cmeq v12.8B, v13.8B, v14.8B - __ cm(Assembler::EQ, v31, __ T16B, v0, v1); // cmeq v31.16B, v0.16B, v1.16B - __ cm(Assembler::EQ, v10, __ T4H, v11, v12); // cmeq v10.4H, v11.4H, v12.4H - __ cm(Assembler::EQ, v16, __ T8H, v17, v18); // cmeq v16.8H, v17.8H, v18.8H - __ cm(Assembler::EQ, v7, __ T2S, v8, v9); // cmeq v7.2S, v8.2S, v9.2S - __ cm(Assembler::EQ, v2, __ T4S, v3, v4); // cmeq v2.4S, v3.4S, v4.4S - __ cm(Assembler::EQ, v3, __ T2D, v4, v5); // cmeq v3.2D, v4.2D, v5.2D - __ cm(Assembler::HI, v13, __ T8B, v14, v15); // cmhi v13.8B, v14.8B, v15.8B - __ cm(Assembler::HI, v19, __ T16B, v20, v21); // cmhi v19.16B, v20.16B, v21.16B - __ cm(Assembler::HI, v17, __ T4H, v18, v19); // cmhi v17.4H, v18.4H, v19.4H - __ cm(Assembler::HI, v16, __ T8H, v17, v18); // cmhi v16.8H, v17.8H, v18.8H - __ cm(Assembler::HI, v3, __ T2S, v4, v5); // cmhi v3.2S, v4.2S, v5.2S - __ cm(Assembler::HI, v1, __ T4S, v2, v3); // cmhi v1.4S, v2.4S, v3.4S - __ cm(Assembler::HI, v11, __ T2D, v12, v13); // cmhi v11.2D, v12.2D, v13.2D - __ cm(Assembler::HS, v30, __ T8B, v31, v0); // cmhs v30.8B, v31.8B, v0.8B - __ cm(Assembler::HS, v5, __ T16B, v6, v7); // cmhs v5.16B, v6.16B, v7.16B - __ cm(Assembler::HS, v8, __ T4H, v9, v10); // cmhs v8.4H, v9.4H, v10.4H - __ cm(Assembler::HS, v15, __ T8H, v16, v17); // cmhs v15.8H, v16.8H, v17.8H - __ cm(Assembler::HS, v29, __ T2S, v30, v31); // cmhs v29.2S, v30.2S, v31.2S - __ cm(Assembler::HS, v30, __ T4S, v31, v0); // cmhs v30.4S, v31.4S, v0.4S - __ cm(Assembler::HS, v0, __ T2D, v1, v2); // cmhs v0.2D, v1.2D, v2.2D - __ fcm(Assembler::EQ, v20, __ T2S, v21, v22); // fcmeq v20.2S, v21.2S, v22.2S - __ fcm(Assembler::EQ, v7, __ T4S, v8, v9); // fcmeq v7.4S, v8.4S, v9.4S - __ fcm(Assembler::EQ, v20, __ T2D, v21, v22); // fcmeq v20.2D, v21.2D, v22.2D - __ fcm(Assembler::GT, v23, __ T2S, v24, v25); // fcmgt v23.2S, v24.2S, v25.2S - __ fcm(Assembler::GT, v28, __ T4S, v29, v30); // fcmgt v28.4S, v29.4S, v30.4S - __ fcm(Assembler::GT, v21, __ T2D, v22, v23); // fcmgt v21.2D, v22.2D, v23.2D - __ fcm(Assembler::GE, v27, __ T2S, v28, v29); // fcmge v27.2S, v28.2S, v29.2S - __ fcm(Assembler::GE, v25, __ T4S, v26, v27); // fcmge v25.4S, v26.4S, v27.4S - __ fcm(Assembler::GE, v5, __ T2D, v6, v7); // fcmge v5.2D, v6.2D, v7.2D + __ cm(Assembler::GT, v14, __ T8B, v15, v16); // cmgt v14.8B, v15.8B, v16.8B + __ cm(Assembler::GT, v11, __ T16B, v12, v13); // cmgt v11.16B, v12.16B, v13.16B + __ cm(Assembler::GT, v24, __ T4H, v25, v26); // cmgt v24.4H, v25.4H, v26.4H + __ cm(Assembler::GT, v1, __ T8H, v2, v3); // cmgt v1.8H, v2.8H, v3.8H + __ cm(Assembler::GT, v12, __ T2S, v13, v14); // cmgt v12.2S, v13.2S, v14.2S + __ cm(Assembler::GT, v31, __ T4S, v0, v1); // cmgt v31.4S, v0.4S, v1.4S + __ cm(Assembler::GT, v10, __ T2D, v11, v12); // cmgt v10.2D, v11.2D, v12.2D + __ cm(Assembler::GE, v16, __ T8B, v17, v18); // cmge v16.8B, v17.8B, v18.8B + __ cm(Assembler::GE, v7, __ T16B, v8, v9); // cmge v7.16B, v8.16B, v9.16B + __ cm(Assembler::GE, v2, __ T4H, v3, v4); // cmge v2.4H, v3.4H, v4.4H + __ cm(Assembler::GE, v3, __ T8H, v4, v5); // cmge v3.8H, v4.8H, v5.8H + __ cm(Assembler::GE, v13, __ T2S, v14, v15); // cmge v13.2S, v14.2S, v15.2S + __ cm(Assembler::GE, v19, __ T4S, v20, v21); // cmge v19.4S, v20.4S, v21.4S + __ cm(Assembler::GE, v17, __ T2D, v18, v19); // cmge v17.2D, v18.2D, v19.2D + __ cm(Assembler::EQ, v16, __ T8B, v17, v18); // cmeq v16.8B, v17.8B, v18.8B + __ cm(Assembler::EQ, v3, __ T16B, v4, v5); // cmeq v3.16B, v4.16B, v5.16B + __ cm(Assembler::EQ, v1, __ T4H, v2, v3); // cmeq v1.4H, v2.4H, v3.4H + __ cm(Assembler::EQ, v11, __ T8H, v12, v13); // cmeq v11.8H, v12.8H, v13.8H + __ cm(Assembler::EQ, v30, __ T2S, v31, v0); // cmeq v30.2S, v31.2S, v0.2S + __ cm(Assembler::EQ, v5, __ T4S, v6, v7); // cmeq v5.4S, v6.4S, v7.4S + __ cm(Assembler::EQ, v8, __ T2D, v9, v10); // cmeq v8.2D, v9.2D, v10.2D + __ cm(Assembler::HI, v15, __ T8B, v16, v17); // cmhi v15.8B, v16.8B, v17.8B + __ cm(Assembler::HI, v29, __ T16B, v30, v31); // cmhi v29.16B, v30.16B, v31.16B + __ cm(Assembler::HI, v30, __ T4H, v31, v0); // cmhi v30.4H, v31.4H, v0.4H + __ cm(Assembler::HI, v0, __ T8H, v1, v2); // cmhi v0.8H, v1.8H, v2.8H + __ cm(Assembler::HI, v20, __ T2S, v21, v22); // cmhi v20.2S, v21.2S, v22.2S + __ cm(Assembler::HI, v7, __ T4S, v8, v9); // cmhi v7.4S, v8.4S, v9.4S + __ cm(Assembler::HI, v20, __ T2D, v21, v22); // cmhi v20.2D, v21.2D, v22.2D + __ cm(Assembler::HS, v23, __ T8B, v24, v25); // cmhs v23.8B, v24.8B, v25.8B + __ cm(Assembler::HS, v28, __ T16B, v29, v30); // cmhs v28.16B, v29.16B, v30.16B + __ cm(Assembler::HS, v21, __ T4H, v22, v23); // cmhs v21.4H, v22.4H, v23.4H + __ cm(Assembler::HS, v27, __ T8H, v28, v29); // cmhs v27.8H, v28.8H, v29.8H + __ cm(Assembler::HS, v25, __ T2S, v26, v27); // cmhs v25.2S, v26.2S, v27.2S + __ cm(Assembler::HS, v5, __ T4S, v6, v7); // cmhs v5.4S, v6.4S, v7.4S + __ cm(Assembler::HS, v1, __ T2D, v2, v3); // cmhs v1.2D, v2.2D, v3.2D + __ fcm(Assembler::EQ, v23, __ T2S, v24, v25); // fcmeq v23.2S, v24.2S, v25.2S + __ fcm(Assembler::EQ, v16, __ T4S, v17, v18); // fcmeq v16.4S, v17.4S, v18.4S + __ fcm(Assembler::EQ, v31, __ T2D, v0, v1); // fcmeq v31.2D, v0.2D, v1.2D + __ fcm(Assembler::GT, v5, __ T2S, v6, v7); // fcmgt v5.2S, v6.2S, v7.2S + __ fcm(Assembler::GT, v12, __ T4S, v13, v14); // fcmgt v12.4S, v13.4S, v14.4S + __ fcm(Assembler::GT, v9, __ T2D, v10, v11); // fcmgt v9.2D, v10.2D, v11.2D + __ fcm(Assembler::GE, v28, __ T2S, v29, v30); // fcmge v28.2S, v29.2S, v30.2S + __ fcm(Assembler::GE, v15, __ T4S, v16, v17); // fcmge v15.4S, v16.4S, v17.4S + __ fcm(Assembler::GE, v29, __ T2D, v30, v31); // fcmge v29.2D, v30.2D, v31.2D // SVEComparisonWithZero - __ sve_fcm(Assembler::EQ, p0, __ D, p7, z23, 0.0); // fcmeq p0.d, p7/z, z23.d, #0.0 - __ sve_fcm(Assembler::GT, p2, __ S, p7, z12, 0.0); // fcmgt p2.s, p7/z, z12.s, #0.0 - __ sve_fcm(Assembler::GE, p7, __ D, p7, z29, 0.0); // fcmge p7.d, p7/z, z29.d, #0.0 - __ sve_fcm(Assembler::LT, p9, __ S, p3, z31, 0.0); // fcmlt p9.s, p3/z, z31.s, #0.0 - __ sve_fcm(Assembler::LE, p9, __ D, p6, z31, 0.0); // fcmle p9.d, p6/z, z31.d, #0.0 - __ sve_fcm(Assembler::NE, p10, __ S, p2, z16, 0.0); // fcmne p10.s, p2/z, z16.s, #0.0 + __ sve_fcm(Assembler::EQ, p11, __ D, p7, z31, 0.0); // fcmeq p11.d, p7/z, z31.d, #0.0 + __ sve_fcm(Assembler::GT, p2, __ D, p7, z14, 0.0); // fcmgt p2.d, p7/z, z14.d, #0.0 + __ sve_fcm(Assembler::GE, p9, __ D, p4, z27, 0.0); // fcmge p9.d, p4/z, z27.d, #0.0 + __ sve_fcm(Assembler::LT, p6, __ S, p1, z11, 0.0); // fcmlt p6.s, p1/z, z11.s, #0.0 + __ sve_fcm(Assembler::LE, p15, __ D, p7, z17, 0.0); // fcmle p15.d, p7/z, z17.d, #0.0 + __ sve_fcm(Assembler::NE, p15, __ S, p5, z7, 0.0); // fcmne p15.s, p5/z, z7.s, #0.0 // SVEComparisonWithImm - __ sve_cmp(Assembler::EQ, p4, __ D, p4, z6, 11); // cmpeq p4.d, p4/z, z6.d, #11 - __ sve_cmp(Assembler::GT, p14, __ B, p2, z30, 4); // cmpgt p14.b, p2/z, z30.b, #4 - __ sve_cmp(Assembler::GE, p5, __ D, p4, z4, 1); // cmpge p5.d, p4/z, z4.d, #1 - __ sve_cmp(Assembler::LT, p11, __ D, p3, z3, 6); // cmplt p11.d, p3/z, z3.d, #6 - __ sve_cmp(Assembler::LE, p9, __ S, p0, z19, -1); // cmple p9.s, p0/z, z19.s, #-1 - __ sve_cmp(Assembler::NE, p3, __ S, p2, z12, -3); // cmpne p3.s, p2/z, z12.s, #-3 - __ sve_cmp(Assembler::HS, p11, __ D, p4, z1, 20); // cmphs p11.d, p4/z, z1.d, #20 - __ sve_cmp(Assembler::HI, p8, __ S, p5, z2, 53); // cmphi p8.s, p5/z, z2.s, #53 - __ sve_cmp(Assembler::LS, p5, __ D, p6, z21, 49); // cmpls p5.d, p6/z, z21.d, #49 - __ sve_cmp(Assembler::LO, p13, __ B, p7, z3, 97); // cmplo p13.b, p7/z, z3.b, #97 + __ sve_cmp(Assembler::EQ, p5, __ D, p4, z4, 1); // cmpeq p5.d, p4/z, z4.d, #1 + __ sve_cmp(Assembler::GT, p11, __ D, p3, z3, 6); // cmpgt p11.d, p3/z, z3.d, #6 + __ sve_cmp(Assembler::GE, p9, __ S, p0, z19, -1); // cmpge p9.s, p0/z, z19.s, #-1 + __ sve_cmp(Assembler::LT, p3, __ S, p2, z12, -3); // cmplt p3.s, p2/z, z12.s, #-3 + __ sve_cmp(Assembler::LE, p11, __ D, p4, z1, -11); // cmple p11.d, p4/z, z1.d, #-11 + __ sve_cmp(Assembler::NE, p8, __ S, p5, z2, -3); // cmpne p8.s, p5/z, z2.s, #-3 + __ sve_cmp(Assembler::HS, p5, __ D, p6, z21, 49); // cmphs p5.d, p6/z, z21.d, #49 + __ sve_cmp(Assembler::HI, p13, __ B, p7, z3, 97); // cmphi p13.b, p7/z, z3.b, #97 + __ sve_cmp(Assembler::LS, p9, __ H, p7, z17, 109); // cmpls p9.h, p7/z, z17.h, #109 + __ sve_cmp(Assembler::LO, p7, __ S, p5, z7, 127); // cmplo p7.s, p5/z, z7.s, #127 // SpecialCases __ ccmn(zr, zr, 3u, Assembler::LE); // ccmn xzr, xzr, #3, LE @@ -1086,229 +1096,229 @@ __ fmovd(v0, -1.0625); // fmov d0, #-1.0625 // LSEOp - __ swp(Assembler::xword, r19, r17, r9); // swp x19, x17, [x9] - __ ldadd(Assembler::xword, r28, r27, r15); // ldadd x28, x27, [x15] - __ ldbic(Assembler::xword, r7, r21, r23); // ldclr x7, x21, [x23] - __ ldeor(Assembler::xword, zr, r25, r2); // ldeor xzr, x25, [x2] - __ ldorr(Assembler::xword, zr, r27, r15); // ldset xzr, x27, [x15] - __ ldsmin(Assembler::xword, r10, r23, r19); // ldsmin x10, x23, [x19] - __ ldsmax(Assembler::xword, r3, r16, r0); // ldsmax x3, x16, [x0] - __ ldumin(Assembler::xword, r25, r26, r23); // ldumin x25, x26, [x23] - __ ldumax(Assembler::xword, r2, r16, r12); // ldumax x2, x16, [x12] + __ swp(Assembler::xword, r25, r2, sp); // swp x25, x2, [sp] + __ ldadd(Assembler::xword, r27, r16, r10); // ldadd x27, x16, [x10] + __ ldbic(Assembler::xword, r23, r19, r3); // ldclr x23, x19, [x3] + __ ldeor(Assembler::xword, r16, r0, r25); // ldeor x16, x0, [x25] + __ ldorr(Assembler::xword, r26, r23, r2); // ldset x26, x23, [x2] + __ ldsmin(Assembler::xword, r16, r12, r4); // ldsmin x16, x12, [x4] + __ ldsmax(Assembler::xword, r28, r30, r29); // ldsmax x28, x30, [x29] + __ ldumin(Assembler::xword, r16, r27, r6); // ldumin x16, x27, [x6] + __ ldumax(Assembler::xword, r9, r29, r15); // ldumax x9, x29, [x15] // LSEOp - __ swpa(Assembler::xword, r4, r28, r30); // swpa x4, x28, [x30] - __ ldadda(Assembler::xword, r29, r16, r27); // ldadda x29, x16, [x27] - __ ldbica(Assembler::xword, r6, r9, r29); // ldclra x6, x9, [x29] - __ ldeora(Assembler::xword, r16, r7, r4); // ldeora x16, x7, [x4] - __ ldorra(Assembler::xword, r7, r15, r9); // ldseta x7, x15, [x9] - __ ldsmina(Assembler::xword, r23, r8, r2); // ldsmina x23, x8, [x2] - __ ldsmaxa(Assembler::xword, r28, r21, sp); // ldsmaxa x28, x21, [sp] - __ ldumina(Assembler::xword, r5, r27, r0); // ldumina x5, x27, [x0] - __ ldumaxa(Assembler::xword, r17, r15, r4); // ldumaxa x17, x15, [x4] + __ swpa(Assembler::xword, r7, r4, r7); // swpa x7, x4, [x7] + __ ldadda(Assembler::xword, r15, r9, r23); // ldadda x15, x9, [x23] + __ ldbica(Assembler::xword, r8, r2, r28); // ldclra x8, x2, [x28] + __ ldeora(Assembler::xword, r21, zr, r5); // ldeora x21, xzr, [x5] + __ ldorra(Assembler::xword, r27, r0, r17); // ldseta x27, x0, [x17] + __ ldsmina(Assembler::xword, r15, r4, r26); // ldsmina x15, x4, [x26] + __ ldsmaxa(Assembler::xword, r8, r28, r22); // ldsmaxa x8, x28, [x22] + __ ldumina(Assembler::xword, r27, r27, r25); // ldumina x27, x27, [x25] + __ ldumaxa(Assembler::xword, r23, r0, r4); // ldumaxa x23, x0, [x4] // LSEOp - __ swpal(Assembler::xword, r26, r8, r28); // swpal x26, x8, [x28] - __ ldaddal(Assembler::xword, r22, r27, r27); // ldaddal x22, x27, [x27] - __ ldbical(Assembler::xword, r25, r23, r0); // ldclral x25, x23, [x0] - __ ldeoral(Assembler::xword, r4, r6, r15); // ldeoral x4, x6, [x15] - __ ldorral(Assembler::xword, r0, r4, r15); // ldsetal x0, x4, [x15] - __ ldsminal(Assembler::xword, r1, r10, r7); // ldsminal x1, x10, [x7] - __ ldsmaxal(Assembler::xword, r5, r10, r28); // ldsmaxal x5, x10, [x28] - __ lduminal(Assembler::xword, r7, r20, r23); // lduminal x7, x20, [x23] - __ ldumaxal(Assembler::xword, r21, r6, r11); // ldumaxal x21, x6, [x11] + __ swpal(Assembler::xword, r6, r16, r0); // swpal x6, x16, [x0] + __ ldaddal(Assembler::xword, r4, r15, r1); // ldaddal x4, x15, [x1] + __ ldbical(Assembler::xword, r10, r7, r5); // ldclral x10, x7, [x5] + __ ldeoral(Assembler::xword, r10, r28, r7); // ldeoral x10, x28, [x7] + __ ldorral(Assembler::xword, r20, r23, r21); // ldsetal x20, x23, [x21] + __ ldsminal(Assembler::xword, r6, r11, r8); // ldsminal x6, x11, [x8] + __ ldsmaxal(Assembler::xword, r17, zr, r6); // ldsmaxal x17, xzr, [x6] + __ lduminal(Assembler::xword, r17, r2, r12); // lduminal x17, x2, [x12] + __ ldumaxal(Assembler::xword, r30, r29, r3); // ldumaxal x30, x29, [x3] // LSEOp - __ swpl(Assembler::xword, r8, r17, sp); // swpl x8, x17, [sp] - __ ldaddl(Assembler::xword, r6, r17, r2); // ldaddl x6, x17, [x2] - __ ldbicl(Assembler::xword, r12, r30, r29); // ldclrl x12, x30, [x29] - __ ldeorl(Assembler::xword, r3, r27, r22); // ldeorl x3, x27, [x22] - __ ldorrl(Assembler::xword, r29, r14, r13); // ldsetl x29, x14, [x13] - __ ldsminl(Assembler::xword, r28, r17, r24); // ldsminl x28, x17, [x24] - __ ldsmaxl(Assembler::xword, r5, r2, r14); // ldsmaxl x5, x2, [x14] - __ lduminl(Assembler::xword, r10, r16, r11); // lduminl x10, x16, [x11] - __ ldumaxl(Assembler::xword, r27, r23, r12); // ldumaxl x27, x23, [x12] + __ swpl(Assembler::xword, r27, r22, r29); // swpl x27, x22, [x29] + __ ldaddl(Assembler::xword, r14, r13, r28); // ldaddl x14, x13, [x28] + __ ldbicl(Assembler::xword, r17, r24, r5); // ldclrl x17, x24, [x5] + __ ldeorl(Assembler::xword, r2, r14, r10); // ldeorl x2, x14, [x10] + __ ldorrl(Assembler::xword, r16, r11, r27); // ldsetl x16, x11, [x27] + __ ldsminl(Assembler::xword, r23, r12, r4); // ldsminl x23, x12, [x4] + __ ldsmaxl(Assembler::xword, r22, r17, r4); // ldsmaxl x22, x17, [x4] + __ lduminl(Assembler::xword, r1, r19, r16); // lduminl x1, x19, [x16] + __ ldumaxl(Assembler::xword, r16, r13, r14); // ldumaxl x16, x13, [x14] // LSEOp - __ swp(Assembler::word, r4, r22, r17); // swp w4, w22, [x17] - __ ldadd(Assembler::word, r4, r1, r19); // ldadd w4, w1, [x19] - __ ldbic(Assembler::word, r16, r16, r13); // ldclr w16, w16, [x13] - __ ldeor(Assembler::word, r14, r12, r2); // ldeor w14, w12, [x2] - __ ldorr(Assembler::word, r17, r3, r21); // ldset w17, w3, [x21] - __ ldsmin(Assembler::word, r23, r5, r6); // ldsmin w23, w5, [x6] - __ ldsmax(Assembler::word, r7, r19, r13); // ldsmax w7, w19, [x13] - __ ldumin(Assembler::word, r28, r17, r16); // ldumin w28, w17, [x16] - __ ldumax(Assembler::word, r6, r2, r29); // ldumax w6, w2, [x29] + __ swp(Assembler::word, r12, r2, r17); // swp w12, w2, [x17] + __ ldadd(Assembler::word, r3, r21, r23); // ldadd w3, w21, [x23] + __ ldbic(Assembler::word, r5, r6, r7); // ldclr w5, w6, [x7] + __ ldeor(Assembler::word, r19, r13, r28); // ldeor w19, w13, [x28] + __ ldorr(Assembler::word, r17, r16, r6); // ldset w17, w16, [x6] + __ ldsmin(Assembler::word, r2, r29, r3); // ldsmin w2, w29, [x3] + __ ldsmax(Assembler::word, r4, r6, r15); // ldsmax w4, w6, [x15] + __ ldumin(Assembler::word, r20, r13, r12); // ldumin w20, w13, [x12] + __ ldumax(Assembler::word, r20, r8, r25); // ldumax w20, w8, [x25] // LSEOp - __ swpa(Assembler::word, r3, r4, r6); // swpa w3, w4, [x6] - __ ldadda(Assembler::word, r16, r20, r13); // ldadda w16, w20, [x13] - __ ldbica(Assembler::word, r12, r20, r8); // ldclra w12, w20, [x8] - __ ldeora(Assembler::word, r25, r20, r19); // ldeora w25, w20, [x19] - __ ldorra(Assembler::word, r0, r11, r24); // ldseta w0, w11, [x24] - __ ldsmina(Assembler::word, r6, r20, sp); // ldsmina w6, w20, [sp] - __ ldsmaxa(Assembler::word, r14, r16, r6); // ldsmaxa w14, w16, [x6] - __ ldumina(Assembler::word, r0, r7, r15); // ldumina w0, w7, [x15] - __ ldumaxa(Assembler::word, r19, r26, r9); // ldumaxa w19, w26, [x9] + __ swpa(Assembler::word, r20, r19, r0); // swpa w20, w19, [x0] + __ ldadda(Assembler::word, r11, r24, r6); // ldadda w11, w24, [x6] + __ ldbica(Assembler::word, r20, zr, r14); // ldclra w20, wzr, [x14] + __ ldeora(Assembler::word, r16, r6, r0); // ldeora w16, w6, [x0] + __ ldorra(Assembler::word, r7, r15, r19); // ldseta w7, w15, [x19] + __ ldsmina(Assembler::word, r26, r9, r10); // ldsmina w26, w9, [x10] + __ ldsmaxa(Assembler::word, r23, r21, r22); // ldsmaxa w23, w21, [x22] + __ ldumina(Assembler::word, r28, r2, r3); // ldumina w28, w2, [x3] + __ ldumaxa(Assembler::word, r15, r19, r20); // ldumaxa w15, w19, [x20] // LSEOp - __ swpal(Assembler::word, r10, r23, r21); // swpal w10, w23, [x21] - __ ldaddal(Assembler::word, r22, r28, r2); // ldaddal w22, w28, [x2] - __ ldbical(Assembler::word, r3, r15, r19); // ldclral w3, w15, [x19] - __ ldeoral(Assembler::word, r20, r7, r4); // ldeoral w20, w7, [x4] - __ ldorral(Assembler::word, r29, r7, r0); // ldsetal w29, w7, [x0] - __ ldsminal(Assembler::word, r9, r16, r20); // ldsminal w9, w16, [x20] - __ ldsmaxal(Assembler::word, r23, r4, r16); // ldsmaxal w23, w4, [x16] - __ lduminal(Assembler::word, r10, r23, r11); // lduminal w10, w23, [x11] - __ ldumaxal(Assembler::word, r25, r6, sp); // ldumaxal w25, w6, [sp] + __ swpal(Assembler::word, r7, r4, r29); // swpal w7, w4, [x29] + __ ldaddal(Assembler::word, r7, r0, r9); // ldaddal w7, w0, [x9] + __ ldbical(Assembler::word, r16, r20, r23); // ldclral w16, w20, [x23] + __ ldeoral(Assembler::word, r4, r16, r10); // ldeoral w4, w16, [x10] + __ ldorral(Assembler::word, r23, r11, r25); // ldsetal w23, w11, [x25] + __ ldsminal(Assembler::word, r6, zr, r16); // ldsminal w6, wzr, [x16] + __ ldsmaxal(Assembler::word, r13, r23, r12); // ldsmaxal w13, w23, [x12] + __ lduminal(Assembler::word, r1, r14, r9); // lduminal w1, w14, [x9] + __ ldumaxal(Assembler::word, r21, r16, r26); // ldumaxal w21, w16, [x26] // LSEOp - __ swpl(Assembler::word, r16, r13, r23); // swpl w16, w13, [x23] - __ ldaddl(Assembler::word, r12, r1, r14); // ldaddl w12, w1, [x14] - __ ldbicl(Assembler::word, r9, r21, r16); // ldclrl w9, w21, [x16] - __ ldeorl(Assembler::word, r26, r15, r4); // ldeorl w26, w15, [x4] - __ ldorrl(Assembler::word, r4, r16, r8); // ldsetl w4, w16, [x8] - __ ldsminl(Assembler::word, r6, r30, r4); // ldsminl w6, w30, [x4] - __ ldsmaxl(Assembler::word, r29, r17, r29); // ldsmaxl w29, w17, [x29] - __ lduminl(Assembler::word, r26, r9, r15); // lduminl w26, w9, [x15] - __ ldumaxl(Assembler::word, r2, r11, r29); // ldumaxl w2, w11, [x29] + __ swpl(Assembler::word, r15, r4, r4); // swpl w15, w4, [x4] + __ ldaddl(Assembler::word, r16, r8, r6); // ldaddl w16, w8, [x6] + __ ldbicl(Assembler::word, r30, r4, r29); // ldclrl w30, w4, [x29] + __ ldeorl(Assembler::word, r17, r29, r26); // ldeorl w17, w29, [x26] + __ ldorrl(Assembler::word, r9, r15, r2); // ldsetl w9, w15, [x2] + __ ldsminl(Assembler::word, r11, r29, r3); // ldsminl w11, w29, [x3] + __ ldsmaxl(Assembler::word, r7, r1, r27); // ldsmaxl w7, w1, [x27] + __ lduminl(Assembler::word, r21, r16, r14); // lduminl w21, w16, [x14] + __ ldumaxl(Assembler::word, r8, r16, r22); // ldumaxl w8, w16, [x22] // SHA3SIMDOp - __ bcax(v3, __ T16B, v7, v1, v27); // bcax v3.16B, v7.16B, v1.16B, v27.16B - __ eor3(v21, __ T16B, v18, v14, v8); // eor3 v21.16B, v18.16B, v14.16B, v8.16B - __ rax1(v18, __ T2D, v22, v25); // rax1 v18.2D, v22.2D, v25.2D - __ xar(v5, __ T2D, v20, v21, 37); // xar v5.2D, v20.2D, v21.2D, #37 + __ bcax(v25, __ T16B, v5, v20, v21); // bcax v25.16B, v5.16B, v20.16B, v21.16B + __ eor3(v18, __ T16B, v23, v16, v30); // eor3 v18.16B, v23.16B, v16.16B, v30.16B + __ rax1(v20, __ T2D, v20, v0); // rax1 v20.2D, v20.2D, v0.2D + __ xar(v4, __ T2D, v19, v24, 9); // xar v4.2D, v19.2D, v24.2D, #9 // SHA512SIMDOp - __ sha512h(v23, __ T2D, v16, v30); // sha512h q23, q16, v30.2D - __ sha512h2(v20, __ T2D, v20, v0); // sha512h2 q20, q20, v0.2D - __ sha512su0(v4, __ T2D, v19); // sha512su0 v4.2D, v19.2D - __ sha512su1(v24, __ T2D, v4, v20); // sha512su1 v24.2D, v4.2D, v20.2D + __ sha512h(v20, __ T2D, v4, v24); // sha512h q20, q4, v24.2D + __ sha512h2(v26, __ T2D, v19, v2); // sha512h2 q26, q19, v2.2D + __ sha512su0(v8, __ T2D, v8); // sha512su0 v8.2D, v8.2D + __ sha512su1(v14, __ T2D, v24, v18); // sha512su1 v14.2D, v24.2D, v18.2D // SVEBinaryImmOp - __ sve_add(z4, __ D, 210u); // add z4.d, z4.d, #0xd2 - __ sve_sub(z19, __ B, 71u); // sub z19.b, z19.b, #0x47 - __ sve_and(z8, __ H, 49663u); // and z8.h, z8.h, #0xc1ff - __ sve_eor(z31, __ S, 4294967231u); // eor z31.s, z31.s, #0xffffffbf - __ sve_orr(z1, __ H, 16368u); // orr z1.h, z1.h, #0x3ff0 + __ sve_add(z31, __ S, 36u); // add z31.s, z31.s, #0x24 + __ sve_sub(z31, __ B, 85u); // sub z31.b, z31.b, #0x55 + __ sve_and(z20, __ H, 4032u); // and z20.h, z20.h, #0xfc0 + __ sve_eor(z7, __ D, 274877904896u); // eor z7.d, z7.d, #0x3ffffff800 + __ sve_orr(z27, __ B, 243u); // orr z27.b, z27.b, #0xf3 // SVEBinaryImmOp - __ sve_add(z0, __ H, 61u); // add z0.h, z0.h, #0x3d - __ sve_sub(z24, __ S, 36u); // sub z24.s, z24.s, #0x24 - __ sve_and(z27, __ B, 243u); // and z27.b, z27.b, #0xf3 - __ sve_eor(z24, __ H, 65534u); // eor z24.h, z24.h, #0xfffe - __ sve_orr(z22, __ S, 4294967293u); // orr z22.s, z22.s, #0xfffffffd + __ sve_add(z24, __ H, 132u); // add z24.h, z24.h, #0x84 + __ sve_sub(z31, __ S, 183u); // sub z31.s, z31.s, #0xb7 + __ sve_and(z20, __ D, 4503599627354112u); // and z20.d, z20.d, #0xfffffffffc000 + __ sve_eor(z14, __ S, 4042322160u); // eor z14.s, z14.s, #0xf0f0f0f0 + __ sve_orr(z28, __ H, 32256u); // orr z28.h, z28.h, #0x7e00 // SVEBinaryImmOp - __ sve_add(z29, __ H, 113u); // add z29.h, z29.h, #0x71 - __ sve_sub(z20, __ B, 165u); // sub z20.b, z20.b, #0xa5 - __ sve_and(z28, __ H, 32256u); // and z28.h, z28.h, #0x7e00 - __ sve_eor(z12, __ S, 4287102855u); // eor z12.s, z12.s, #0xff87ff87 - __ sve_orr(z9, __ S, 3825205247u); // orr z9.s, z9.s, #0xe3ffffff + __ sve_add(z12, __ S, 13u); // add z12.s, z12.s, #0xd + __ sve_sub(z24, __ H, 159u); // sub z24.h, z24.h, #0x9f + __ sve_and(z13, __ S, 2151677951u); // and z13.s, z13.s, #0x803fffff + __ sve_eor(z5, __ B, 124u); // eor z5.b, z5.b, #0x7c + __ sve_orr(z8, __ H, 32768u); // orr z8.h, z8.h, #0x8000 // SVEBinaryImmOp - __ sve_add(z18, __ S, 41u); // add z18.s, z18.s, #0x29 - __ sve_sub(z0, __ B, 98u); // sub z0.b, z0.b, #0x62 - __ sve_and(z8, __ H, 32768u); // and z8.h, z8.h, #0x8000 - __ sve_eor(z4, __ H, 508u); // eor z4.h, z4.h, #0x1fc - __ sve_orr(z0, __ H, 64512u); // orr z0.h, z0.h, #0xfc00 + __ sve_add(z4, __ H, 243u); // add z4.h, z4.h, #0xf3 + __ sve_sub(z5, __ B, 86u); // sub z5.b, z5.b, #0x56 + __ sve_and(z22, __ D, 8064u); // and z22.d, z22.d, #0x1f80 + __ sve_eor(z9, __ S, 130023424u); // eor z9.s, z9.s, #0x7c00000 + __ sve_orr(z24, __ B, 62u); // orr z24.b, z24.b, #0x3e // SVEBinaryImmOp - __ sve_add(z3, __ B, 79u); // add z3.b, z3.b, #0x4f - __ sve_sub(z19, __ D, 84u); // sub z19.d, z19.d, #0x54 - __ sve_and(z24, __ B, 62u); // and z24.b, z24.b, #0x3e - __ sve_eor(z24, __ D, 18428729675200069887u); // eor z24.d, z24.d, #0xffc00000000000ff - __ sve_orr(z11, __ D, 17296056810822168583u); // orr z11.d, z11.d, #0xf007f007f007f007 + __ sve_add(z24, __ D, 113u); // add z24.d, z24.d, #0x71 + __ sve_sub(z21, __ H, 217u); // sub z21.h, z21.h, #0xd9 + __ sve_and(z13, __ S, 3221229567u); // and z13.s, z13.s, #0xc0000fff + __ sve_eor(z14, __ B, 131u); // eor z14.b, z14.b, #0x83 + __ sve_orr(z22, __ S, 4042322160u); // orr z22.s, z22.s, #0xf0f0f0f0 // SVEBinaryImmOp - __ sve_add(z31, __ S, 115u); // add z31.s, z31.s, #0x73 - __ sve_sub(z3, __ D, 134u); // sub z3.d, z3.d, #0x86 - __ sve_and(z22, __ S, 4042322160u); // and z22.s, z22.s, #0xf0f0f0f0 - __ sve_eor(z3, __ B, 225u); // eor z3.b, z3.b, #0xe1 - __ sve_orr(z9, __ S, 4164941887u); // orr z9.s, z9.s, #0xf83ff83f + __ sve_add(z3, __ B, 215u); // add z3.b, z3.b, #0xd7 + __ sve_sub(z19, __ H, 134u); // sub z19.h, z19.h, #0x86 + __ sve_and(z17, __ S, 491520u); // and z17.s, z17.s, #0x78000 + __ sve_eor(z2, __ D, 8796093020160u); // eor z2.d, z2.d, #0x7fffffff800 + __ sve_orr(z11, __ S, 3221229567u); // orr z11.s, z11.s, #0xc0000fff // SVEVectorOp - __ sve_add(z0, __ D, z4, z2); // add z0.d, z4.d, z2.d - __ sve_sub(z14, __ S, z6, z11); // sub z14.s, z6.s, z11.s - __ sve_fadd(z14, __ S, z17, z30); // fadd z14.s, z17.s, z30.s - __ sve_fmul(z3, __ S, z3, z23); // fmul z3.s, z3.s, z23.s - __ sve_fsub(z3, __ S, z24, z28); // fsub z3.s, z24.s, z28.s - __ sve_abs(z19, __ D, p5, z7); // abs z19.d, p5/m, z7.d - __ sve_add(z21, __ H, p3, z5); // add z21.h, p3/m, z21.h, z5.h - __ sve_and(z26, __ S, p1, z22); // and z26.s, p1/m, z26.s, z22.s - __ sve_asr(z17, __ H, p0, z3); // asr z17.h, p0/m, z17.h, z3.h - __ sve_bic(z20, __ H, p3, z8); // bic z20.h, p3/m, z20.h, z8.h - __ sve_clz(z14, __ H, p4, z17); // clz z14.h, p4/m, z17.h - __ sve_cnt(z13, __ D, p6, z18); // cnt z13.d, p6/m, z18.d - __ sve_eor(z19, __ H, p2, z16); // eor z19.h, p2/m, z19.h, z16.h - __ sve_lsl(z27, __ S, p5, z28); // lsl z27.s, p5/m, z27.s, z28.s - __ sve_lsr(z8, __ D, p2, z5); // lsr z8.d, p2/m, z8.d, z5.d - __ sve_mul(z28, __ H, p2, z0); // mul z28.h, p2/m, z28.h, z0.h - __ sve_neg(z25, __ B, p5, z21); // neg z25.b, p5/m, z21.b - __ sve_not(z3, __ B, p5, z26); // not z3.b, p5/m, z26.b - __ sve_orr(z26, __ S, p7, z19); // orr z26.s, p7/m, z26.s, z19.s - __ sve_rbit(z1, __ D, p3, z14); // rbit z1.d, p3/m, z14.d - __ sve_revb(z14, __ H, p0, z18); // revb z14.h, p0/m, z18.h - __ sve_smax(z31, __ S, p5, z23); // smax z31.s, p5/m, z31.s, z23.s - __ sve_smin(z30, __ B, p3, z8); // smin z30.b, p3/m, z30.b, z8.b - __ sve_sub(z0, __ S, p3, z23); // sub z0.s, p3/m, z0.s, z23.s - __ sve_fabs(z0, __ D, p4, z26); // fabs z0.d, p4/m, z26.d - __ sve_fadd(z24, __ D, p3, z22); // fadd z24.d, p3/m, z24.d, z22.d - __ sve_fdiv(z2, __ D, p0, z11); // fdiv z2.d, p0/m, z2.d, z11.d - __ sve_fmax(z12, __ D, p5, z24); // fmax z12.d, p5/m, z12.d, z24.d - __ sve_fmin(z9, __ D, p7, z17); // fmin z9.d, p7/m, z9.d, z17.d - __ sve_fmul(z20, __ D, p5, z4); // fmul z20.d, p5/m, z20.d, z4.d - __ sve_fneg(z13, __ D, p7, z22); // fneg z13.d, p7/m, z22.d - __ sve_frintm(z31, __ D, p6, z18); // frintm z31.d, p6/m, z18.d - __ sve_frintn(z15, __ D, p2, z13); // frintn z15.d, p2/m, z13.d - __ sve_frintp(z20, __ S, p1, z1); // frintp z20.s, p1/m, z1.s - __ sve_fsqrt(z14, __ S, p0, z7); // fsqrt z14.s, p0/m, z7.s - __ sve_fsub(z12, __ D, p4, z4); // fsub z12.d, p4/m, z12.d, z4.d - __ sve_fmad(z15, __ S, p0, z3, z30); // fmad z15.s, p0/m, z3.s, z30.s - __ sve_fmla(z20, __ D, p1, z20, z31); // fmla z20.d, p1/m, z20.d, z31.d - __ sve_fmls(z13, __ D, p3, z9, z14); // fmls z13.d, p3/m, z9.d, z14.d - __ sve_fmsb(z1, __ S, p3, z28, z3); // fmsb z1.s, p3/m, z28.s, z3.s - __ sve_fnmad(z26, __ S, p2, z25, z9); // fnmad z26.s, p2/m, z25.s, z9.s - __ sve_fnmsb(z26, __ D, p2, z14, z1); // fnmsb z26.d, p2/m, z14.d, z1.d - __ sve_fnmla(z26, __ D, p1, z29, z20); // fnmla z26.d, p1/m, z29.d, z20.d - __ sve_fnmls(z6, __ D, p7, z13, z1); // fnmls z6.d, p7/m, z13.d, z1.d - __ sve_mla(z11, __ B, p2, z1, z1); // mla z11.b, p2/m, z1.b, z1.b - __ sve_mls(z27, __ B, p6, z15, z2); // mls z27.b, p6/m, z15.b, z2.b - __ sve_and(z30, z17, z25); // and z30.d, z17.d, z25.d - __ sve_eor(z2, z24, z3); // eor z2.d, z24.d, z3.d - __ sve_orr(z29, z13, z3); // orr z29.d, z13.d, z3.d - __ sve_bic(z14, z16, z28); // bic z14.d, z16.d, z28.d - __ sve_uzp1(z4, __ S, z11, z27); // uzp1 z4.s, z11.s, z27.s - __ sve_uzp2(z2, __ D, z16, z1); // uzp2 z2.d, z16.d, z1.d - __ sve_fabd(z7, __ D, p5, z31); // fabd z7.d, p5/m, z7.d, z31.d - __ sve_bext(z16, __ S, z10, z22); // bext z16.s, z10.s, z22.s - __ sve_bdep(z29, __ B, z7, z22); // bdep z29.b, z7.b, z22.b - __ sve_eor3(z12, z24, z11); // eor3 z12.d, z12.d, z24.d, z11.d + __ sve_add(z30, __ B, z12, z3); // add z30.b, z12.b, z3.b + __ sve_sub(z23, __ D, z9, z3); // sub z23.d, z9.d, z3.d + __ sve_fadd(z28, __ D, z3, z19); // fadd z28.d, z3.d, z19.d + __ sve_fmul(z7, __ S, z26, z21); // fmul z7.s, z26.s, z21.s + __ sve_fsub(z5, __ S, z8, z26); // fsub z5.s, z8.s, z26.s + __ sve_abs(z22, __ B, p4, z17); // abs z22.b, p4/m, z17.b + __ sve_add(z3, __ H, p2, z20); // add z3.h, p2/m, z3.h, z20.h + __ sve_and(z8, __ S, p3, z14); // and z8.s, p3/m, z8.s, z14.s + __ sve_asr(z17, __ D, p2, z13); // asr z17.d, p2/m, z17.d, z13.d + __ sve_bic(z18, __ H, p7, z19); // bic z18.h, p7/m, z18.h, z19.h + __ sve_clz(z16, __ S, p3, z27); // clz z16.s, p3/m, z27.s + __ sve_cnt(z28, __ H, p5, z8); // cnt z28.h, p5/m, z8.h + __ sve_eor(z5, __ H, p7, z28); // eor z5.h, p7/m, z5.h, z28.h + __ sve_lsl(z0, __ S, p3, z25); // lsl z0.s, p3/m, z0.s, z25.s + __ sve_lsr(z21, __ S, p0, z3); // lsr z21.s, p0/m, z21.s, z3.s + __ sve_mul(z26, __ D, p1, z26); // mul z26.d, p1/m, z26.d, z26.d + __ sve_neg(z19, __ H, p4, z1); // neg z19.h, p4/m, z1.h + __ sve_not(z14, __ B, p7, z14); // not z14.b, p7/m, z14.b + __ sve_orr(z18, __ S, p0, z31); // orr z18.s, p0/m, z18.s, z31.s + __ sve_rbit(z23, __ H, p5, z30); // rbit z23.h, p5/m, z30.h + __ sve_revb(z8, __ S, p0, z0); // revb z8.s, p0/m, z0.s + __ sve_smax(z23, __ S, p5, z0); // smax z23.s, p5/m, z23.s, z0.s + __ sve_smin(z26, __ H, p6, z24); // smin z26.h, p6/m, z26.h, z24.h + __ sve_sub(z22, __ B, p5, z2); // sub z22.b, p5/m, z22.b, z2.b + __ sve_fabs(z11, __ D, p5, z12); // fabs z11.d, p5/m, z12.d + __ sve_fadd(z24, __ D, p6, z9); // fadd z24.d, p6/m, z24.d, z9.d + __ sve_fdiv(z17, __ D, p5, z20); // fdiv z17.d, p5/m, z17.d, z20.d + __ sve_fmax(z4, __ D, p5, z13); // fmax z4.d, p5/m, z4.d, z13.d + __ sve_fmin(z22, __ D, p7, z31); // fmin z22.d, p7/m, z22.d, z31.d + __ sve_fmul(z18, __ S, p4, z15); // fmul z18.s, p4/m, z18.s, z15.s + __ sve_fneg(z13, __ S, p7, z20); // fneg z13.s, p7/m, z20.s + __ sve_frintm(z1, __ S, p3, z14); // frintm z1.s, p3/m, z14.s + __ sve_frintn(z7, __ D, p2, z12); // frintn z7.d, p2/m, z12.d + __ sve_frintp(z4, __ S, p6, z15); // frintp z4.s, p6/m, z15.s + __ sve_fsqrt(z3, __ D, p7, z1); // fsqrt z3.d, p7/m, z1.d + __ sve_fsub(z5, __ D, p5, z31); // fsub z5.d, p5/m, z5.d, z31.d + __ sve_fmad(z13, __ D, p3, z9, z14); // fmad z13.d, p3/m, z9.d, z14.d + __ sve_fmla(z1, __ S, p3, z28, z3); // fmla z1.s, p3/m, z28.s, z3.s + __ sve_fmls(z26, __ S, p2, z25, z9); // fmls z26.s, p2/m, z25.s, z9.s + __ sve_fmsb(z26, __ D, p2, z14, z1); // fmsb z26.d, p2/m, z14.d, z1.d + __ sve_fnmad(z26, __ D, p1, z29, z20); // fnmad z26.d, p1/m, z29.d, z20.d + __ sve_fnmsb(z6, __ D, p7, z13, z1); // fnmsb z6.d, p7/m, z13.d, z1.d + __ sve_fnmla(z11, __ S, p2, z1, z1); // fnmla z11.s, p2/m, z1.s, z1.s + __ sve_fnmls(z27, __ S, p6, z15, z2); // fnmls z27.s, p6/m, z15.s, z2.s + __ sve_mla(z30, __ B, p4, z25, z2); // mla z30.b, p4/m, z25.b, z2.b + __ sve_mls(z24, __ H, p0, z26, z29); // mls z24.h, p0/m, z26.h, z29.h + __ sve_and(z3, z22, z14); // and z3.d, z22.d, z14.d + __ sve_eor(z28, z17, z4); // eor z28.d, z17.d, z4.d + __ sve_orr(z27, z16, z2); // orr z27.d, z16.d, z2.d + __ sve_bic(z1, z28, z7); // bic z1.d, z28.d, z7.d + __ sve_uzp1(z31, __ H, z28, z16); // uzp1 z31.h, z28.h, z16.h + __ sve_uzp2(z22, __ B, z17, z29); // uzp2 z22.b, z17.b, z29.b + __ sve_fabd(z22, __ D, p1, z12); // fabd z22.d, p1/m, z22.d, z12.d + __ sve_bext(z11, __ H, z9, z11); // bext z11.h, z9.h, z11.h + __ sve_bdep(z0, __ S, z4, z23); // bdep z0.s, z4.s, z23.s + __ sve_eor3(z20, z4, z3); // eor3 z20.d, z20.d, z4.d, z3.d // SVEReductionOp - __ sve_andv(v11, __ B, p2, z0); // andv b11, p2, z0.b - __ sve_orv(v23, __ B, p5, z20); // orv b23, p5, z20.b - __ sve_eorv(v3, __ B, p3, z15); // eorv b3, p3, z15.b - __ sve_smaxv(v30, __ B, p6, z27); // smaxv b30, p6, z27.b - __ sve_sminv(v21, __ D, p6, z10); // sminv d21, p6, z10.d - __ sve_fminv(v3, __ S, p6, z4); // fminv s3, p6, z4.s - __ sve_fmaxv(v6, __ S, p0, z21); // fmaxv s6, p0, z21.s - __ sve_fadda(v25, __ D, p6, z30); // fadda d25, p6, d25, z30.d - __ sve_uaddv(v31, __ H, p4, z1); // uaddv d31, p4, z1.h + __ sve_andv(v15, __ D, p1, z30); // andv d15, p1, z30.d + __ sve_orv(v27, __ D, p1, z21); // orv d27, p1, z21.d + __ sve_eorv(v10, __ D, p7, z3); // eorv d10, p7, z3.d + __ sve_smaxv(v4, __ B, p2, z6); // smaxv b4, p2, z6.b + __ sve_sminv(v21, __ D, p1, z25); // sminv d21, p1, z25.d + __ sve_fminv(v30, __ D, p6, z31); // fminv d30, p6, z31.d + __ sve_fmaxv(v1, __ D, p2, z12); // fmaxv d1, p2, z12.d + __ sve_fadda(v13, __ D, p2, z25); // fadda d13, p2, d13, z25.d + __ sve_uaddv(v1, __ D, p7, z23); // uaddv d1, p7, z23.d // AddWideNEONOp - __ saddwv(v12, v13, __ T8H, v14, __ T8B); // saddw v12.8H, v13.8H, v14.8B - __ saddwv2(v30, v31, __ T8H, v0, __ T16B); // saddw2 v30.8H, v31.8H, v0.16B - __ saddwv(v13, v14, __ T4S, v15, __ T4H); // saddw v13.4S, v14.4S, v15.4H - __ saddwv2(v8, v9, __ T4S, v10, __ T8H); // saddw2 v8.4S, v9.4S, v10.8H - __ saddwv(v25, v26, __ T2D, v27, __ T2S); // saddw v25.2D, v26.2D, v27.2S + __ saddwv(v20, v21, __ T8H, v22, __ T8B); // saddw v20.8H, v21.8H, v22.8B + __ saddwv2(v0, v1, __ T8H, v2, __ T16B); // saddw2 v0.8H, v1.8H, v2.16B + __ saddwv(v21, v22, __ T4S, v23, __ T4H); // saddw v21.4S, v22.4S, v23.4H + __ saddwv2(v7, v8, __ T4S, v9, __ T8H); // saddw2 v7.4S, v8.4S, v9.8H + __ saddwv(v31, v0, __ T2D, v1, __ T2S); // saddw v31.2D, v0.2D, v1.2S __ saddwv2(v29, v30, __ T2D, v31, __ T4S); // saddw2 v29.2D, v30.2D, v31.4S - __ uaddwv(v1, v2, __ T8H, v3, __ T8B); // uaddw v1.8H, v2.8H, v3.8B - __ uaddwv2(v31, v0, __ T8H, v1, __ T16B); // uaddw2 v31.8H, v0.8H, v1.16B - __ uaddwv(v23, v24, __ T4S, v25, __ T4H); // uaddw v23.4S, v24.4S, v25.4H - __ uaddwv2(v31, v0, __ T4S, v1, __ T8H); // uaddw2 v31.4S, v0.4S, v1.8H - __ uaddwv(v20, v21, __ T2D, v22, __ T2S); // uaddw v20.2D, v21.2D, v22.2S - __ uaddwv2(v0, v1, __ T2D, v2, __ T4S); // uaddw2 v0.2D, v1.2D, v2.4S + __ uaddwv(v27, v28, __ T8H, v29, __ T8B); // uaddw v27.8H, v28.8H, v29.8B + __ uaddwv2(v22, v23, __ T8H, v24, __ T16B); // uaddw2 v22.8H, v23.8H, v24.16B + __ uaddwv(v8, v9, __ T4S, v10, __ T4H); // uaddw v8.4S, v9.4S, v10.4H + __ uaddwv2(v29, v30, __ T4S, v31, __ T8H); // uaddw2 v29.4S, v30.4S, v31.8H + __ uaddwv(v26, v27, __ T2D, v28, __ T2S); // uaddw v26.2D, v27.2D, v28.2S + __ uaddwv2(v20, v21, __ T2D, v22, __ T4S); // uaddw2 v20.2D, v21.2D, v22.4S __ bind(forth); @@ -1327,30 +1337,30 @@ 0x9101a1a0, 0xb10a5cc8, 0xd10810aa, 0xf10fd061, 0x120cb166, 0x321764bc, 0x52174681, 0x720c0227, 0x9241018e, 0xb25a2969, 0xd278b411, 0xf26aad01, - 0x14000000, 0x17ffffd7, 0x14000441, 0x94000000, - 0x97ffffd4, 0x9400043e, 0x3400000a, 0x34fffa2a, - 0x3400876a, 0x35000008, 0x35fff9c8, 0x35008708, - 0xb400000b, 0xb4fff96b, 0xb40086ab, 0xb500001d, - 0xb5fff91d, 0xb500865d, 0x10000013, 0x10fff8b3, - 0x100085f3, 0x90000013, 0x36300016, 0x3637f836, - 0x36308576, 0x3758000c, 0x375ff7cc, 0x3758850c, + 0x14000000, 0x17ffffd7, 0x1400044b, 0x94000000, + 0x97ffffd4, 0x94000448, 0x3400000a, 0x34fffa2a, + 0x340088aa, 0x35000008, 0x35fff9c8, 0x35008848, + 0xb400000b, 0xb4fff96b, 0xb40087eb, 0xb500001d, + 0xb5fff91d, 0xb500879d, 0x10000013, 0x10fff8b3, + 0x10008733, 0x90000013, 0x36300016, 0x3637f836, + 0x363086b6, 0x3758000c, 0x375ff7cc, 0x3758864c, 0x128313a0, 0x528a32c7, 0x7289173b, 0x92ab3acc, 0xd2a0bf94, 0xf2c285e8, 0x9358722f, 0x330e652f, 0x53067f3b, 0x93577c53, 0xb34a1aac, 0xd35a4016, 0x13946c63, 0x93c3dbc8, 0x54000000, 0x54fff5a0, - 0x540082e0, 0x54000001, 0x54fff541, 0x54008281, - 0x54000002, 0x54fff4e2, 0x54008222, 0x54000002, - 0x54fff482, 0x540081c2, 0x54000003, 0x54fff423, - 0x54008163, 0x54000003, 0x54fff3c3, 0x54008103, - 0x54000004, 0x54fff364, 0x540080a4, 0x54000005, - 0x54fff305, 0x54008045, 0x54000006, 0x54fff2a6, - 0x54007fe6, 0x54000007, 0x54fff247, 0x54007f87, - 0x54000008, 0x54fff1e8, 0x54007f28, 0x54000009, - 0x54fff189, 0x54007ec9, 0x5400000a, 0x54fff12a, - 0x54007e6a, 0x5400000b, 0x54fff0cb, 0x54007e0b, - 0x5400000c, 0x54fff06c, 0x54007dac, 0x5400000d, - 0x54fff00d, 0x54007d4d, 0x5400000e, 0x54ffefae, - 0x54007cee, 0x5400000f, 0x54ffef4f, 0x54007c8f, + 0x54008420, 0x54000001, 0x54fff541, 0x540083c1, + 0x54000002, 0x54fff4e2, 0x54008362, 0x54000002, + 0x54fff482, 0x54008302, 0x54000003, 0x54fff423, + 0x540082a3, 0x54000003, 0x54fff3c3, 0x54008243, + 0x54000004, 0x54fff364, 0x540081e4, 0x54000005, + 0x54fff305, 0x54008185, 0x54000006, 0x54fff2a6, + 0x54008126, 0x54000007, 0x54fff247, 0x540080c7, + 0x54000008, 0x54fff1e8, 0x54008068, 0x54000009, + 0x54fff189, 0x54008009, 0x5400000a, 0x54fff12a, + 0x54007faa, 0x5400000b, 0x54fff0cb, 0x54007f4b, + 0x5400000c, 0x54fff06c, 0x54007eec, 0x5400000d, + 0x54fff00d, 0x54007e8d, 0x5400000e, 0x54ffefae, + 0x54007e2e, 0x5400000f, 0x54ffef4f, 0x54007dcf, 0xd40658e1, 0xd4014d22, 0xd4046543, 0xd4273f60, 0xd44cad80, 0xd503201f, 0xd503203f, 0xd503205f, 0xd503209f, 0xd50320bf, 0xd503219f, 0xd50323bf, @@ -1471,134 +1481,137 @@ 0x4e60f7fe, 0x0e3c6f7a, 0x4e346e72, 0x0e6b6d49, 0x4e6a6d28, 0x0eae6dac, 0x4ea26c20, 0x0e36aeb4, 0x4e23ac41, 0x0e7aaf38, 0x4e64ac62, 0x0ea2ac20, - 0x4eabad49, 0x0ebaf738, 0x4ebcf77a, 0x4ef2f630, - 0x2ea0effe, 0x6ea5ec83, 0x6eeced6a, 0x0fa710c5, - 0x4f8b8149, 0x4fc710c5, 0x0f8750c5, 0x4faa8128, - 0x4fc750c5, 0x2f8890e6, 0x4fa880e6, 0x6fc59083, - 0x0f6f81cd, 0x4f448862, 0x0f848062, 0x4fab8149, - 0x0e3736d5, 0x4e323630, 0x0e743672, 0x4e6d358b, - 0x0eb736d5, 0x4eb93717, 0x4eee35ac, 0x0e3c3f7a, - 0x4e393f17, 0x0e7e3fbc, 0x4e703dee, 0x0ead3d8b, - 0x4eba3f38, 0x4ee33c41, 0x2e2e8dac, 0x6e218c1f, - 0x2e6c8d6a, 0x6e728e30, 0x2ea98d07, 0x6ea48c62, - 0x6ee58c83, 0x2e2f35cd, 0x6e353693, 0x2e733651, - 0x6e723630, 0x2ea53483, 0x6ea33441, 0x6eed358b, - 0x2e203ffe, 0x6e273cc5, 0x2e6a3d28, 0x6e713e0f, - 0x2ebf3fdd, 0x6ea03ffe, 0x6ee23c20, 0x0e36e6b4, - 0x4e29e507, 0x4e76e6b4, 0x2eb9e717, 0x6ebee7bc, - 0x6ef7e6d5, 0x2e3de79b, 0x6e3be759, 0x6e67e4c5, - 0x65d23ee0, 0x65903d92, 0x65d03fa7, 0x65912fe9, - 0x65d13bf9, 0x65932a0a, 0x25cb90c4, 0x25040bde, - 0x25c11085, 0x25c62c6b, 0x259f2279, 0x259d8993, - 0x24e5102b, 0x24ad5458, 0x24ec7ab5, 0x24387c6d, - 0xba5fd3e3, 0x3a5f03e5, 0xfa411be4, 0x7a42cbe2, - 0x93df03ff, 0xc820ffff, 0x8822fc7f, 0xc8247cbf, - 0x88267fff, 0x4e010fe0, 0x5e040420, 0x4e081fe1, - 0x4e0c1fe1, 0x4e0a1fe1, 0x4e071fe1, 0x4e042c20, - 0x4e062c20, 0x4e052c20, 0x4e083c20, 0x0e0c3c20, - 0x0e0a3c20, 0x0e073c20, 0x9eae0020, 0x0f03f409, - 0x6f03f40e, 0x4cc0ac3f, 0x0ea1b820, 0x4e21c862, - 0x4e61b8a4, 0x05a08020, 0x05104fe0, 0x05505001, - 0x05906fe2, 0x05d03005, 0x05101fea, 0x05901feb, - 0x04b0e3e0, 0x0470e7e1, 0x042f9c20, 0x043f9c35, - 0x047f9c20, 0x04ff9c20, 0x04299420, 0x04319160, - 0x0461943e, 0x04a19020, 0x04038100, 0x040381a0, - 0x040387e1, 0x04438be2, 0x04c38fe3, 0x040181e0, - 0x04018100, 0x04018621, 0x04418b22, 0x04418822, - 0x04818c23, 0x040081e0, 0x04008120, 0x04008761, - 0x04008621, 0x04408822, 0x04808c23, 0x042053ff, - 0x047f5401, 0x25208028, 0x2538cfe0, 0x2578d001, - 0x25b8efe2, 0x25f8f007, 0x2538dfea, 0x25b8dfeb, - 0xa400a3e0, 0xa420a7e0, 0xa4484be0, 0xa467afe0, - 0xa4a8a7ea, 0xa547a814, 0xa4084ffe, 0xa55c53e0, - 0xa5e1540b, 0xe400fbf6, 0xe408ffff, 0xe420e7e0, - 0xe4484be0, 0xe460efe0, 0xe547e400, 0xe4014be0, - 0xe4a84fe0, 0xe5f15000, 0x858043e0, 0x85a043ff, - 0xe59f5d08, 0x0420e3e9, 0x0460e3ea, 0x04a0e3eb, - 0x04e0e3ec, 0x25104042, 0x25104871, 0x25904861, - 0x25904c92, 0x05344020, 0x05744041, 0x05b44062, - 0x05f44083, 0x252c8840, 0x253c1420, 0x25681572, - 0x25a21ce3, 0x25ea1e34, 0x253c0421, 0x25680572, - 0x25a20ce3, 0x25ea0e34, 0x0522c020, 0x05e6c0a4, - 0x2401a001, 0x2443a051, 0x24858881, 0x24c78cd1, - 0x24850891, 0x24c70cc1, 0x250f9001, 0x25508051, - 0x25802491, 0x25df28c1, 0x25850c81, 0x251e10d1, - 0x65816001, 0x65c36051, 0x65854891, 0x65c74cc1, - 0x05733820, 0x05b238a4, 0x05f138e6, 0x0570396a, - 0x65d0a001, 0x65d6a443, 0x65d4a826, 0x6594ac26, - 0x6554ac26, 0x6556ac26, 0x6552ac26, 0x65cbac85, - 0x65caac01, 0x6589ac85, 0x6588ac01, 0x65c9ac85, - 0x65c8ac01, 0x65dea833, 0x659ca509, 0x65d8a801, - 0x65dcac01, 0x655cb241, 0x0520a1e0, 0x0521a601, - 0x052281e0, 0x05238601, 0x04a14026, 0x042244a6, - 0x046344a6, 0x04a444a6, 0x04e544a7, 0x0568aca7, - 0x05b23230, 0x853040af, 0xc5b040af, 0xe57080af, - 0xe5b080af, 0x25034440, 0x254054c4, 0x25034640, - 0x25415a05, 0x25834440, 0x25c54489, 0x250b5d3a, - 0x2550dc20, 0x2518e3e1, 0x2518e021, 0x2518e0a1, - 0x2518e121, 0x2518e1a1, 0x2558e3e2, 0x2558e042, - 0x2558e0c2, 0x2558e142, 0x2598e3e3, 0x2598e063, - 0x2598e0e3, 0x2598e163, 0x25d8e3e4, 0x25d8e084, - 0x25d8e104, 0x25d8e184, 0x2518e407, 0x05214800, - 0x05614800, 0x05a14800, 0x05e14800, 0x05214c00, - 0x05614c00, 0x05a14c00, 0x05e14c00, 0x05304001, - 0x05314001, 0x05a18610, 0x05e18610, 0x05271e11, - 0x6545e891, 0x6585e891, 0x65c5e891, 0x6545c891, - 0x6585c891, 0x65c5c891, 0x45b0c210, 0x45f1c231, - 0x1e601000, 0x1e603000, 0x1e621000, 0x1e623000, - 0x1e641000, 0x1e643000, 0x1e661000, 0x1e663000, - 0x1e681000, 0x1e683000, 0x1e6a1000, 0x1e6a3000, - 0x1e6c1000, 0x1e6c3000, 0x1e6e1000, 0x1e6e3000, - 0x1e701000, 0x1e703000, 0x1e721000, 0x1e723000, - 0x1e741000, 0x1e743000, 0x1e761000, 0x1e763000, - 0x1e781000, 0x1e783000, 0x1e7a1000, 0x1e7a3000, - 0x1e7c1000, 0x1e7c3000, 0x1e7e1000, 0x1e7e3000, - 0xf8338131, 0xf83c01fb, 0xf82712f5, 0xf83f2059, - 0xf83f31fb, 0xf82a5277, 0xf8234010, 0xf83972fa, - 0xf8226190, 0xf8a483dc, 0xf8bd0370, 0xf8a613a9, - 0xf8b02087, 0xf8a7312f, 0xf8b75048, 0xf8bc43f5, - 0xf8a5701b, 0xf8b1608f, 0xf8fa8388, 0xf8f6037b, - 0xf8f91017, 0xf8e421e6, 0xf8e031e4, 0xf8e150ea, - 0xf8e5438a, 0xf8e772f4, 0xf8f56166, 0xf86883f1, - 0xf8660051, 0xf86c13be, 0xf86322db, 0xf87d31ae, - 0xf87c5311, 0xf86541c2, 0xf86a7170, 0xf87b6197, - 0xb8248236, 0xb8240261, 0xb83011b0, 0xb82e204c, - 0xb83132a3, 0xb83750c5, 0xb82741b3, 0xb83c7211, - 0xb82663a2, 0xb8a380c4, 0xb8b001b4, 0xb8ac1114, - 0xb8b92274, 0xb8a0330b, 0xb8a653f4, 0xb8ae40d0, - 0xb8a071e7, 0xb8b3613a, 0xb8ea82b7, 0xb8f6005c, - 0xb8e3126f, 0xb8f42087, 0xb8fd3007, 0xb8e95290, - 0xb8f74204, 0xb8ea7177, 0xb8f963e6, 0xb87082ed, - 0xb86c01c1, 0xb8691215, 0xb87a208f, 0xb8643110, - 0xb866509e, 0xb87d43b1, 0xb87a71e9, 0xb86263ab, - 0xce216ce3, 0xce0e2255, 0xce798ed2, 0xce959685, - 0xce7e8217, 0xce608694, 0xcec08264, 0xce748898, - 0x25e0da44, 0x2521c8f3, 0x05801548, 0x0540cbdf, - 0x05006521, 0x2560c7a0, 0x25a1c498, 0x058026bb, - 0x05407dd8, 0x0500f3d6, 0x2560ce3d, 0x2521d4b4, - 0x05803cbc, 0x05404d6c, 0x05001b89, 0x25a0c532, - 0x2521cc40, 0x05800c08, 0x054074c4, 0x050034a0, - 0x2520c9e3, 0x25e1ca93, 0x05803e98, 0x05425238, - 0x050024cb, 0x25a0ce7f, 0x25e1d0c3, 0x05802676, - 0x05401e63, 0x05002d49, 0x04e20080, 0x04ab04ce, - 0x659e022e, 0x65970863, 0x659c0703, 0x04d6b4f3, - 0x04400cb5, 0x049a06da, 0x04508071, 0x045b0d14, - 0x0459b22e, 0x04daba4d, 0x04590a13, 0x0493979b, - 0x04d188a8, 0x0450081c, 0x0417b6b9, 0x041eb743, - 0x04981e7a, 0x05e78dc1, 0x0564824e, 0x048816ff, - 0x040a0d1e, 0x04810ee0, 0x04dcb340, 0x65c08ed8, - 0x65cd8162, 0x65c6970c, 0x65c79e29, 0x65c29494, - 0x04ddbecd, 0x65c2ba5f, 0x65c0a9af, 0x6581a434, - 0x658da0ee, 0x65c1908c, 0x65be806f, 0x65ff0694, - 0x65ee2d2d, 0x65a3af81, 0x65a9cb3a, 0x65e1e9da, - 0x65f447ba, 0x65e17da6, 0x0401482b, 0x040279fb, - 0x0439323e, 0x04a33302, 0x046331bd, 0x04fc320e, - 0x05bb6964, 0x05e16e02, 0x65c897e7, 0x4596b150, - 0x4516b4fd, 0x0438396c, 0x041a280b, 0x04183697, - 0x04192de3, 0x04083b7e, 0x04ca3955, 0x65873883, - 0x658622a6, 0x65d83bd9, 0x0441303f, 0x0e2e11ac, - 0x4e2013fe, 0x0e6f11cd, 0x4e6a1128, 0x0ebb1359, - 0x4ebf13dd, 0x2e231041, 0x6e21101f, 0x2e791317, - 0x6e61101f, 0x2eb612b4, 0x6ea21020, + 0x4eabad49, 0x0e7ab738, 0x4e7cb77a, 0x0eb2b630, + 0x4ea0b7fe, 0x0e252483, 0x4e2c256a, 0x0e792717, + 0x4e6c256a, 0x0ea624a4, 0x4eb42672, 0x0ea4f462, + 0x4eadf58b, 0x4eeaf528, 0x2eaced6a, 0x6eb1ee0f, + 0x6ef3ee51, 0x0f8710c5, 0x4fa880e6, 0x4fc810e6, + 0x0f855083, 0x4f8f89cd, 0x4fc45862, 0x2f849062, + 0x4fab8149, 0x6fca9928, 0x0f6780c5, 0x4f5d898b, + 0x0f8f81cd, 0x4f9089ee, 0x0e3035ee, 0x4e2d358b, + 0x0e7a3738, 0x4e633441, 0x0eae35ac, 0x4ea1341f, + 0x4eec356a, 0x0e323e30, 0x4e293d07, 0x0e643c62, + 0x4e653c83, 0x0eaf3dcd, 0x4eb53e93, 0x4ef33e51, + 0x2e328e30, 0x6e258c83, 0x2e638c41, 0x6e6d8d8b, + 0x2ea08ffe, 0x6ea78cc5, 0x6eea8d28, 0x2e31360f, + 0x6e3f37dd, 0x2e6037fe, 0x6e623420, 0x2eb636b4, + 0x6ea93507, 0x6ef636b4, 0x2e393f17, 0x6e3e3fbc, + 0x2e773ed5, 0x6e7d3f9b, 0x2ebb3f59, 0x6ea73cc5, + 0x6ee33c41, 0x0e39e717, 0x4e32e630, 0x4e61e41f, + 0x2ea7e4c5, 0x6eaee5ac, 0x6eebe549, 0x2e3ee7bc, + 0x6e31e60f, 0x6e7fe7dd, 0x65d23feb, 0x65d03dd2, + 0x65d03369, 0x65912566, 0x65d13e3f, 0x659334ef, + 0x25c19085, 0x25c60c7b, 0x259f0269, 0x259d2983, + 0x25d5303b, 0x259d9458, 0x24ec5aa5, 0x24385c7d, + 0x247b7e39, 0x24bff4e7, 0xba5fd3e3, 0x3a5f03e5, + 0xfa411be4, 0x7a42cbe2, 0x93df03ff, 0xc820ffff, + 0x8822fc7f, 0xc8247cbf, 0x88267fff, 0x4e010fe0, + 0x5e040420, 0x4e081fe1, 0x4e0c1fe1, 0x4e0a1fe1, + 0x4e071fe1, 0x4e042c20, 0x4e062c20, 0x4e052c20, + 0x4e083c20, 0x0e0c3c20, 0x0e0a3c20, 0x0e073c20, + 0x9eae0020, 0x0f03f409, 0x6f03f40e, 0x4cc0ac3f, + 0x0ea1b820, 0x4e21c862, 0x4e61b8a4, 0x05a08020, + 0x05104fe0, 0x05505001, 0x05906fe2, 0x05d03005, + 0x05101fea, 0x05901feb, 0x04b0e3e0, 0x0470e7e1, + 0x042f9c20, 0x043f9c35, 0x047f9c20, 0x04ff9c20, + 0x04299420, 0x04319160, 0x0461943e, 0x04a19020, + 0x04038100, 0x040381a0, 0x040387e1, 0x04438be2, + 0x04c38fe3, 0x040181e0, 0x04018100, 0x04018621, + 0x04418b22, 0x04418822, 0x04818c23, 0x040081e0, + 0x04008120, 0x04008761, 0x04008621, 0x04408822, + 0x04808c23, 0x042053ff, 0x047f5401, 0x25208028, + 0x2538cfe0, 0x2578d001, 0x25b8efe2, 0x25f8f007, + 0x2538dfea, 0x25b8dfeb, 0xa400a3e0, 0xa420a7e0, + 0xa4484be0, 0xa467afe0, 0xa4a8a7ea, 0xa547a814, + 0xa4084ffe, 0xa55c53e0, 0xa5e1540b, 0xe400fbf6, + 0xe408ffff, 0xe420e7e0, 0xe4484be0, 0xe460efe0, + 0xe547e400, 0xe4014be0, 0xe4a84fe0, 0xe5f15000, + 0x858043e0, 0x85a043ff, 0xe59f5d08, 0x0420e3e9, + 0x0460e3ea, 0x04a0e3eb, 0x04e0e3ec, 0x25104042, + 0x25104871, 0x25904861, 0x25904c92, 0x05344020, + 0x05744041, 0x05b44062, 0x05f44083, 0x252c8840, + 0x253c1420, 0x25681572, 0x25a21ce3, 0x25ea1e34, + 0x253c0421, 0x25680572, 0x25a20ce3, 0x25ea0e34, + 0x0522c020, 0x05e6c0a4, 0x2401a001, 0x2443a051, + 0x24858881, 0x24c78cd1, 0x24850891, 0x24c70cc1, + 0x250f9001, 0x25508051, 0x25802491, 0x25df28c1, + 0x25850c81, 0x251e10d1, 0x65816001, 0x65c36051, + 0x65854891, 0x65c74cc1, 0x05733820, 0x05b238a4, + 0x05f138e6, 0x0570396a, 0x65d0a001, 0x65d6a443, + 0x65d4a826, 0x6594ac26, 0x6554ac26, 0x6556ac26, + 0x6552ac26, 0x65cbac85, 0x65caac01, 0x6589ac85, + 0x6588ac01, 0x65c9ac85, 0x65c8ac01, 0x65dea833, + 0x659ca509, 0x65d8a801, 0x65dcac01, 0x655cb241, + 0x0520a1e0, 0x0521a601, 0x052281e0, 0x05238601, + 0x04a14026, 0x042244a6, 0x046344a6, 0x04a444a6, + 0x04e544a7, 0x0568aca7, 0x05b23230, 0x853040af, + 0xc5b040af, 0xe57080af, 0xe5b080af, 0x25034440, + 0x254054c4, 0x25034640, 0x25415a05, 0x25834440, + 0x25c54489, 0x250b5d3a, 0x2550dc20, 0x2518e3e1, + 0x2518e021, 0x2518e0a1, 0x2518e121, 0x2518e1a1, + 0x2558e3e2, 0x2558e042, 0x2558e0c2, 0x2558e142, + 0x2598e3e3, 0x2598e063, 0x2598e0e3, 0x2598e163, + 0x25d8e3e4, 0x25d8e084, 0x25d8e104, 0x25d8e184, + 0x2518e407, 0x05214800, 0x05614800, 0x05a14800, + 0x05e14800, 0x05214c00, 0x05614c00, 0x05a14c00, + 0x05e14c00, 0x05304001, 0x05314001, 0x05a18610, + 0x05e18610, 0x05271e11, 0x6545e891, 0x6585e891, + 0x65c5e891, 0x6545c891, 0x6585c891, 0x65c5c891, + 0x45b0c210, 0x45f1c231, 0x1e601000, 0x1e603000, + 0x1e621000, 0x1e623000, 0x1e641000, 0x1e643000, + 0x1e661000, 0x1e663000, 0x1e681000, 0x1e683000, + 0x1e6a1000, 0x1e6a3000, 0x1e6c1000, 0x1e6c3000, + 0x1e6e1000, 0x1e6e3000, 0x1e701000, 0x1e703000, + 0x1e721000, 0x1e723000, 0x1e741000, 0x1e743000, + 0x1e761000, 0x1e763000, 0x1e781000, 0x1e783000, + 0x1e7a1000, 0x1e7a3000, 0x1e7c1000, 0x1e7c3000, + 0x1e7e1000, 0x1e7e3000, 0xf83983e2, 0xf83b0150, + 0xf8371073, 0xf8302320, 0xf83a3057, 0xf830508c, + 0xf83c43be, 0xf83070db, 0xf82961fd, 0xf8a780e4, + 0xf8af02e9, 0xf8a81382, 0xf8b520bf, 0xf8bb3220, + 0xf8af5344, 0xf8a842dc, 0xf8bb733b, 0xf8b76080, + 0xf8e68010, 0xf8e4002f, 0xf8ea10a7, 0xf8ea20fc, + 0xf8f432b7, 0xf8e6510b, 0xf8f140df, 0xf8f17182, + 0xf8fe607d, 0xf87b83b6, 0xf86e038d, 0xf87110b8, + 0xf862214e, 0xf870336b, 0xf877508c, 0xf8764091, + 0xf8617213, 0xf87061cd, 0xb82c8222, 0xb82302f5, + 0xb82510e6, 0xb833238d, 0xb83130d0, 0xb822507d, + 0xb82441e6, 0xb834718d, 0xb8346328, 0xb8b48013, + 0xb8ab00d8, 0xb8b411df, 0xb8b02006, 0xb8a7326f, + 0xb8ba5149, 0xb8b742d5, 0xb8bc7062, 0xb8af6293, + 0xb8e783a4, 0xb8e70120, 0xb8f012f4, 0xb8e42150, + 0xb8f7332b, 0xb8e6521f, 0xb8ed4197, 0xb8e1712e, + 0xb8f56350, 0xb86f8084, 0xb87000c8, 0xb87e13a4, + 0xb871235d, 0xb869304f, 0xb86b507d, 0xb8674361, + 0xb87571d0, 0xb86862d0, 0xce3454b9, 0xce107af2, + 0xce608e94, 0xce982664, 0xce788094, 0xce62867a, + 0xcec08108, 0xce728b0e, 0x25a0c49f, 0x2521cabf, + 0x058054b4, 0x0543ab47, 0x050026bb, 0x2560d098, + 0x25a1d6ff, 0x058394b4, 0x0540266e, 0x05003cbc, + 0x25a0c1ac, 0x2561d3f8, 0x05800acd, 0x05403685, + 0x05000c08, 0x2560de64, 0x2521cac5, 0x0583c8b6, + 0x05405089, 0x05003e98, 0x25e0ce38, 0x2561db35, + 0x058011ad, 0x05400e4e, 0x05002676, 0x2520dae3, + 0x2561d0d3, 0x05808871, 0x0543abe2, 0x050011ab, + 0x0423019e, 0x04e30537, 0x65d3007c, 0x65950b47, + 0x659a0505, 0x0416b236, 0x04400a83, 0x049a0dc8, + 0x04d089b1, 0x045b1e72, 0x0499af70, 0x045ab51c, + 0x04591f85, 0x04938f20, 0x04918075, 0x04d0075a, + 0x0457b033, 0x041ebdce, 0x049803f2, 0x056797d7, + 0x05a48008, 0x04881417, 0x044a1b1a, 0x04011456, + 0x04dcb58b, 0x65c09938, 0x65cd9691, 0x65c695a4, + 0x65c79ff6, 0x658291f2, 0x049dbe8d, 0x6582adc1, + 0x65c0a987, 0x6581b9e4, 0x65cdbc23, 0x65c197e5, + 0x65ee8d2d, 0x65a30f81, 0x65a92b3a, 0x65e1a9da, + 0x65f4c7ba, 0x65e1fda6, 0x65a1482b, 0x65a279fb, + 0x0402533e, 0x045d6358, 0x042e32c3, 0x04a4323c, + 0x0462321b, 0x04e73381, 0x05706b9f, 0x053d6e36, + 0x65c88596, 0x454bb12b, 0x4597b480, 0x04243874, + 0x04da27cf, 0x04d826bb, 0x04d93c6a, 0x040828c4, + 0x04ca2735, 0x65c73bfe, 0x65c62981, 0x65d82b2d, + 0x04c13ee1, 0x0e3612b4, 0x4e221020, 0x0e7712d5, + 0x4e691107, 0x0ea1101f, 0x4ebf13dd, 0x2e3d139b, + 0x6e3812f6, 0x2e6a1128, 0x6e7f13dd, 0x2ebc137a, + 0x6eb612b4, }; // END Generated code -- do not edit diff --git a/test/hotspot/gtest/logging/test_asynclog.cpp b/test/hotspot/gtest/logging/test_asynclog.cpp index cb674603563..ebc3e35a4b9 100644 --- a/test/hotspot/gtest/logging/test_asynclog.cpp +++ b/test/hotspot/gtest/logging/test_asynclog.cpp @@ -253,18 +253,6 @@ TEST_VM_F(AsyncLogTest, droppingMessage) { EXPECT_TRUE(file_contains_substring(TestLogFileName, "messages dropped due to async logging")); } -TEST_VM_F(AsyncLogTest, StallingModePreventsDroppedMessages) { - if (AsyncLogWriter::instance() == nullptr) { - return; - } - set_log_config(TestLogFileName, "logging=debug"); - LogConfiguration::AsyncMode prev_mode = LogConfiguration::async_mode(); - LogConfiguration::set_async_mode(LogConfiguration::AsyncMode::Off); - test_asynclog_drop_messages(); - EXPECT_FALSE(file_contains_substring(TestLogFileName, "messages dropped due to async logging")); - LogConfiguration::set_async_mode(prev_mode); -} - TEST_VM_F(AsyncLogTest, stdoutOutput) { testing::internal::CaptureStdout(); @@ -272,7 +260,8 @@ TEST_VM_F(AsyncLogTest, stdoutOutput) { return; } - bool async = AsyncLogWriter::instance() != nullptr; + bool async = AsyncLogWriter::instance() != nullptr + && LogConfiguration::async_mode() == LogConfiguration::AsyncMode::Drop; if (async) { test_asynclog_drop_messages(); AsyncLogWriter::flush(); @@ -301,7 +290,8 @@ TEST_VM_F(AsyncLogTest, stderrOutput) { return; } - bool async = AsyncLogWriter::instance() != nullptr; + bool async = AsyncLogWriter::instance() != nullptr + && LogConfiguration::async_mode() == LogConfiguration::AsyncMode::Drop; if (async) { test_asynclog_drop_messages(); AsyncLogWriter::flush(); diff --git a/test/hotspot/gtest/metaspace/test_clms.cpp b/test/hotspot/gtest/metaspace/test_clms.cpp index ca126b7f615..a1bcb65eaed 100644 --- a/test/hotspot/gtest/metaspace/test_clms.cpp +++ b/test/hotspot/gtest/metaspace/test_clms.cpp @@ -38,7 +38,7 @@ #ifdef _LP64 -#define LOG_PLEASE +// #define LOG_PLEASE #include "metaspaceGtestCommon.hpp" #include "metaspaceGtestContexts.hpp" #include "metaspaceGtestRangeHelpers.hpp" diff --git a/test/hotspot/gtest/metaspace/test_metaspacearena.cpp b/test/hotspot/gtest/metaspace/test_metaspacearena.cpp index e44e3abe398..e99c22abf88 100644 --- a/test/hotspot/gtest/metaspace/test_metaspacearena.cpp +++ b/test/hotspot/gtest/metaspace/test_metaspacearena.cpp @@ -40,7 +40,7 @@ #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" -#define LOG_PLEASE +// #define LOG_PLEASE #include "metaspaceGtestCommon.hpp" #include "metaspaceGtestContexts.hpp" #include "metaspaceGtestRangeHelpers.hpp" diff --git a/test/hotspot/gtest/nmt/test_vmatree.cpp b/test/hotspot/gtest/nmt/test_vmatree.cpp index 1a618604de6..80b5df50062 100644 --- a/test/hotspot/gtest/nmt/test_vmatree.cpp +++ b/test/hotspot/gtest/nmt/test_vmatree.cpp @@ -724,3 +724,19 @@ TEST_VM_F(NMTVMATreeTest, TestConsistencyWithSimpleTracker) { } } } + +TEST_VM_F(NMTVMATreeTest, SummaryAccountingWhenUseFlagInplace) { + Tree tree; + VMATree::RegionData rd1(si[0], mtTest); + VMATree::RegionData rd2(si[1], mtNone); + tree.reserve_mapping(0, 100, rd1); + VMATree::SummaryDiff diff = tree.commit_mapping(0, 50, rd2, true); + EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); + EXPECT_EQ(50, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); + diff = tree.commit_mapping(60, 10, rd2, true); + EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); + EXPECT_EQ(10, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); + diff = tree.uncommit_mapping(0, 50, rd2); + EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); + EXPECT_EQ(-50, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); +} \ No newline at end of file diff --git a/test/hotspot/gtest/runtime/test_cgroupSubsystem_linux.cpp b/test/hotspot/gtest/runtime/test_cgroupSubsystem_linux.cpp index c8e2beff52b..c090aa28e9a 100644 --- a/test/hotspot/gtest/runtime/test_cgroupSubsystem_linux.cpp +++ b/test/hotspot/gtest/runtime/test_cgroupSubsystem_linux.cpp @@ -25,6 +25,7 @@ #include "runtime/os.hpp" #include "cgroupSubsystem_linux.hpp" +#include "cgroupUtil_linux.hpp" #include "cgroupV1Subsystem_linux.hpp" #include "cgroupV2Subsystem_linux.hpp" #include "unittest.hpp" @@ -432,9 +433,16 @@ TEST(cgroupTest, set_cgroupv1_subsystem_path) { "/user.slice/user-1000.slice/user@1000.service", // cgroup_path "/sys/fs/cgroup/mem" // expected_path }; - int length = 2; + TestCase container_moving_cgroup = { + "/sys/fs/cgroup/cpu,cpuacct", // mount_path + "/system.slice/garden.service/garden/good/2f57368b-0eda-4e52-64d8-af5c", // root_path + "/system.slice/garden.service/garden/bad/2f57368b-0eda-4e52-64d8-af5c", // cgroup_path + "/sys/fs/cgroup/cpu,cpuacct" // expected_path + }; + int length = 3; TestCase* testCases[] = { &host, - &container_engine }; + &container_engine, + &container_moving_cgroup }; for (int i = 0; i < length; i++) { CgroupV1Controller* ctrl = new CgroupV1Controller( (char*)testCases[i]->root_path, (char*)testCases[i]->mount_path, @@ -444,6 +452,72 @@ TEST(cgroupTest, set_cgroupv1_subsystem_path) { } } +TEST(cgroupTest, set_cgroupv1_subsystem_path_adjusted) { + TestCase memory = { + "/sys/fs/cgroup/memory", // mount_path + "/", // root_path + "../test1", // cgroup_path + "/sys/fs/cgroup/memory" // expected_path + }; + TestCase cpu = { + "/sys/fs/cgroup/cpu", // mount_path + "/", // root_path + "../../test2", // cgroup_path + "/sys/fs/cgroup/cpu" // expected_path + }; + CgroupCpuController* ccc = new CgroupV1CpuController(CgroupV1Controller((char*)cpu.root_path, + (char*)cpu.mount_path, + true /* read-only mount */)); + ccc->set_subsystem_path((char*)cpu.cgroup_path); + EXPECT_TRUE(ccc->needs_hierarchy_adjustment()); + + CgroupUtil::adjust_controller(ccc); + ASSERT_STREQ(cpu.expected_path, ccc->subsystem_path()); + EXPECT_FALSE(ccc->needs_hierarchy_adjustment()); + + CgroupMemoryController* cmc = new CgroupV1MemoryController(CgroupV1Controller((char*)memory.root_path, + (char*)memory.mount_path, + true /* read-only mount */)); + cmc->set_subsystem_path((char*)memory.cgroup_path); + EXPECT_TRUE(cmc->needs_hierarchy_adjustment()); + + CgroupUtil::adjust_controller(cmc); + ASSERT_STREQ(memory.expected_path, cmc->subsystem_path()); + EXPECT_FALSE(cmc->needs_hierarchy_adjustment()); +} + +TEST(cgroupTest, set_cgroupv2_subsystem_path_adjusted) { + TestCase memory = { + "/sys/fs/cgroup", // mount_path + "/", // root_path + "../test1", // cgroup_path + "/sys/fs/cgroup" // expected_path + }; + TestCase cpu = { + "/sys/fs/cgroup", // mount_path + "/", // root_path + "../../test2", // cgroup_path + "/sys/fs/cgroup" // expected_path + }; + CgroupCpuController* ccc = new CgroupV2CpuController(CgroupV2Controller((char*)cpu.mount_path, + (char*)cpu.cgroup_path, + true /* read-only mount */)); + EXPECT_TRUE(ccc->needs_hierarchy_adjustment()); + + CgroupUtil::adjust_controller(ccc); + ASSERT_STREQ(cpu.expected_path, ccc->subsystem_path()); + EXPECT_FALSE(ccc->needs_hierarchy_adjustment()); + + CgroupMemoryController* cmc = new CgroupV2MemoryController(CgroupV2Controller((char*)memory.mount_path, + (char*)memory.cgroup_path, + true /* read-only mount */)); + EXPECT_TRUE(cmc->needs_hierarchy_adjustment()); + + CgroupUtil::adjust_controller(cmc); + ASSERT_STREQ(memory.expected_path, cmc->subsystem_path()); + EXPECT_FALSE(cmc->needs_hierarchy_adjustment()); +} + TEST(cgroupTest, set_cgroupv2_subsystem_path) { TestCase at_mount_root = { "/sys/fs/cgroup", // mount_path diff --git a/test/hotspot/gtest/runtime/test_os_reserve_between.cpp b/test/hotspot/gtest/runtime/test_os_reserve_between.cpp index 7e326fda439..34dd26dcf17 100644 --- a/test/hotspot/gtest/runtime/test_os_reserve_between.cpp +++ b/test/hotspot/gtest/runtime/test_os_reserve_between.cpp @@ -30,7 +30,7 @@ #include "utilities/macros.hpp" #include "utilities/resourceHash.hpp" -#define LOG_PLEASE +// #define LOG_PLEASE #include "testutils.hpp" #include "unittest.hpp" diff --git a/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp b/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp index 83ecb39b7ef..2985dd7438d 100644 --- a/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp +++ b/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp @@ -58,9 +58,9 @@ namespace { static void diagnostic_print(ReservedMemoryRegion* rmr) { CommittedRegionIterator iter = rmr->iterate_committed_regions(); - LOG("In reserved region " PTR_FORMAT ", size " SIZE_FORMAT_HEX ":", p2i(rmr->base()), rmr->size()); + LOG("In reserved region " PTR_FORMAT ", size 0x%zx:", p2i(rmr->base()), rmr->size()); for (const CommittedMemoryRegion* region = iter.next(); region != nullptr; region = iter.next()) { - LOG(" committed region: " PTR_FORMAT ", size " SIZE_FORMAT_HEX, p2i(region->base()), region->size()); + LOG(" committed region: " PTR_FORMAT ", size 0x%zx", p2i(region->base()), region->size()); } } diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index c88d944c633..242e39fc445 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -43,7 +43,6 @@ # :hotspot_compiler -compiler/ciReplay/TestSAServer.java 8029528 generic-all compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java 8225370 generic-all compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java 8190680 generic-all diff --git a/test/hotspot/jtreg/compiler/c2/irTests/ModDNodeTests.java b/test/hotspot/jtreg/compiler/c2/irTests/ModDNodeTests.java index 4cdae04c39c..3c28c936d31 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/ModDNodeTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/ModDNodeTests.java @@ -41,7 +41,13 @@ public static void main(String[] args) { TestFramework.run(); } - @Run(test = {"constant", "notConstant", "veryNotConstant"}) + @Run(test = {"constant", "notConstant", "veryNotConstant", + "unusedResult", + "repeatedlyUnused", + "unusedResultAfterLoopOpt1", + "unusedResultAfterLoopOpt2", + "unusedResultAfterLoopOpt3", + }) public void runMethod() { Asserts.assertEQ(constant(), q % 72.0d % 30.0d); Asserts.assertEQ(alsoConstant(), q % 31.432d); @@ -49,6 +55,11 @@ public void runMethod() { Asserts.assertTrue(Double.isNaN(nanRightConstant())); Asserts.assertEQ(notConstant(37.5d), 37.5d % 32.0d); Asserts.assertEQ(veryNotConstant(531.25d, 14.5d), 531.25d % 32.0d % 14.5d); + unusedResult(1.1d, 2.2d); + repeatedlyUnused(1.1d, 2.2d); + Asserts.assertEQ(unusedResultAfterLoopOpt1(1.1d, 2.2d), 0.d); + Asserts.assertEQ(unusedResultAfterLoopOpt2(1.1d, 2.2d), 0.d); + Asserts.assertEQ(unusedResultAfterLoopOpt3(1.1d, 2.2d), 0.d); } @Test @@ -114,4 +125,80 @@ public double notConstant(double x) { public double veryNotConstant(double x, double y) { return x % 32.0d % y; } + + @Test + @IR(failOn = IRNode.MOD_D, phase = CompilePhase.ITER_GVN1) + @IR(counts = {IRNode.MOD_D, "1"}, phase = CompilePhase.AFTER_PARSING) + public void unusedResult(double x, double y) { + double unused = x % y; + } + + @Test + @IR(failOn = IRNode.MOD_D, phase = CompilePhase.ITER_GVN1) + @IR(counts = {IRNode.MOD_D, "1"}, phase = CompilePhase.AFTER_PARSING) + public void repeatedlyUnused(double x, double y) { + double unused = 1.d; + for (int i = 0; i < 100_000; i++) { + unused = x % y; + } + } + + // The difference between unusedResultAfterLoopOpt1 and unusedResultAfterLoopOpt2 + // is that they exercise a slightly different reason why the node is being removed, + // and thus a different execution path. In unusedResultAfterLoopOpt1 the modulo is + // used in the traps of the parse predicates. In unusedResultAfterLoopOpt2, it is not. + @Test + @IR(counts = {IRNode.MOD_D, "1"}, phase = CompilePhase.ITER_GVN2) + @IR(failOn = IRNode.MOD_D, phase = CompilePhase.BEFORE_MACRO_EXPANSION) + public double unusedResultAfterLoopOpt1(double x, double y) { + double unused = x % y; + + int a = 77; + int b = 0; + do { + a--; + b++; + } while (a > 0); + + if (b == 78) { // dead + return unused; + } + return 0.d; + } + + @Test + @IR(counts = {IRNode.MOD_D, "1"}, phase = CompilePhase.AFTER_CLOOPS) + @IR(failOn = IRNode.MOD_D, phase = CompilePhase.PHASEIDEALLOOP1) + public double unusedResultAfterLoopOpt2(double x, double y) { + int a = 77; + int b = 0; + do { + a--; + b++; + } while (a > 0); + + double unused = x % y; + + if (b == 78) { // dead + return unused; + } + return 0.d; + } + + @Test + @IR(counts = {IRNode.MOD_D, "2"}, phase = CompilePhase.AFTER_CLOOPS) + @IR(failOn = IRNode.MOD_D, phase = CompilePhase.PHASEIDEALLOOP1) + public double unusedResultAfterLoopOpt3(double x, double y) { + double unused = x % y; + + int a = 77; + int b = 0; + do { + a--; + b++; + } while (a > 0); + + int other = (b - 77) * (int)(x % y % 1.d); + return (double)other; + } } diff --git a/test/hotspot/jtreg/compiler/c2/irTests/ModFNodeTests.java b/test/hotspot/jtreg/compiler/c2/irTests/ModFNodeTests.java index f3adf5ca44f..1b5e14b4835 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/ModFNodeTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/ModFNodeTests.java @@ -41,7 +41,13 @@ public static void main(String[] args) { TestFramework.run(); } - @Run(test = {"constant", "notConstant", "veryNotConstant"}) + @Run(test = {"constant", "notConstant", "veryNotConstant", + "unusedResult", + "repeatedlyUnused", + "unusedResultAfterLoopOpt1", + "unusedResultAfterLoopOpt2", + "unusedResultAfterLoopOpt3", + }) public void runMethod() { Asserts.assertEQ(constant(), q % 72.0f % 30.0f); Asserts.assertEQ(alsoConstant(), q % 31.432f); @@ -49,6 +55,11 @@ public void runMethod() { Asserts.assertTrue(Float.isNaN(nanRightConstant())); Asserts.assertEQ(notConstant(37.5f), 37.5f % 32.0f); Asserts.assertEQ(veryNotConstant(531.25f, 14.5f), 531.25f % 32.0f % 14.5f); + unusedResult(1.1f, 2.2f); + repeatedlyUnused(1.1f, 2.2f); + Asserts.assertEQ(unusedResultAfterLoopOpt1(1.1f, 2.2f), 0.f); + Asserts.assertEQ(unusedResultAfterLoopOpt2(1.1f, 2.2f), 0.f); + Asserts.assertEQ(unusedResultAfterLoopOpt3(1.1f, 2.2f), 0.f); } @Test @@ -114,4 +125,80 @@ public float notConstant(float x) { public float veryNotConstant(float x, float y) { return x % 32.0f % y; } + + @Test + @IR(failOn = IRNode.MOD_F, phase = CompilePhase.ITER_GVN1) + @IR(counts = {IRNode.MOD_F, "1"}, phase = CompilePhase.AFTER_PARSING) + public void unusedResult(float x, float y) { + float unused = x % y; + } + + @Test + @IR(failOn = IRNode.MOD_F, phase = CompilePhase.ITER_GVN1) + @IR(counts = {IRNode.MOD_F, "1"}, phase = CompilePhase.AFTER_PARSING) + public void repeatedlyUnused(float x, float y) { + float unused = 1.f; + for (int i = 0; i < 100_000; i++) { + unused = x % y; + } + } + + // The difference between unusedResultAfterLoopOpt1 and unusedResultAfterLoopOpt2 + // is that they exercise a slightly different reason why the node is being removed, + // and thus a different execution path. In unusedResultAfterLoopOpt1 the modulo is + // used in the traps of the parse predicates. In unusedResultAfterLoopOpt2, it is not. + @Test + @IR(counts = {IRNode.MOD_F, "1"}, phase = CompilePhase.ITER_GVN2) + @IR(failOn = IRNode.MOD_F, phase = CompilePhase.BEFORE_MACRO_EXPANSION) + public float unusedResultAfterLoopOpt1(float x, float y) { + float unused = x % y; + + int a = 77; + int b = 0; + do { + a--; + b++; + } while (a > 0); + + if (b == 78) { // dead + return unused; + } + return 0.f; + } + + @Test + @IR(counts = {IRNode.MOD_F, "1"}, phase = CompilePhase.AFTER_CLOOPS) + @IR(failOn = IRNode.MOD_F, phase = CompilePhase.PHASEIDEALLOOP1) + public float unusedResultAfterLoopOpt2(float x, float y) { + int a = 77; + int b = 0; + do { + a--; + b++; + } while (a > 0); + + float unused = x % y; + + if (b == 78) { // dead + return unused; + } + return 0.f; + } + + @Test + @IR(counts = {IRNode.MOD_F, "2"}, phase = CompilePhase.AFTER_CLOOPS) + @IR(failOn = IRNode.MOD_F, phase = CompilePhase.PHASEIDEALLOOP1) + public float unusedResultAfterLoopOpt3(float x, float y) { + float unused = x % y; + + int a = 77; + int b = 0; + do { + a--; + b++; + } while (a > 0); + + int other = (b - 77) * (int)(x % y % 1.f); + return (float)other; + } } diff --git a/test/hotspot/jtreg/compiler/ciReplay/SABase.java b/test/hotspot/jtreg/compiler/ciReplay/SABase.java deleted file mode 100644 index 66f2eb1106f..00000000000 --- a/test/hotspot/jtreg/compiler/ciReplay/SABase.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2016, 2023, 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 compiler.ciReplay; - -import java.nio.file.Files; -import java.nio.file.Paths; -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; -import java.io.File; -import java.io.FileInputStream; -import java.io.OutputStream; -import java.util.Arrays; -import jdk.test.lib.Platform; -import jdk.test.lib.Asserts; -import jdk.test.lib.JDKToolFinder; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; - -public class SABase extends CiReplayBase { - private static final String REPLAY_FILE_COPY = "replay_vm.txt"; - - public static void main(String args[]) throws Exception { - checkSetLimits(); - SABase base = new SABase(args); - boolean c2 = base.runServer.orElseThrow(() -> new Error("runServer must be set")); - String[] extra = {}; - if (Platform.isTieredSupported()) { - if (c2) { - // Replay produced on first compilation. We want that - // compilation delayed so profile data is produced. - extra = new String[] {"-XX:-TieredCompilation"}; - } else { - extra = new String[] {"-XX:TieredStopAtLevel=1"}; - } - } - base.runTest(/* needCoreDump = */ true, extra); - } - - public SABase(String[] args) { - super(args); - } - - @Override - public void testAction() { - try { - Files.move(Paths.get(REPLAY_FILE_NAME), Paths.get(REPLAY_FILE_COPY)); - } catch (IOException ioe) { - throw new Error("Can't move files: " + ioe, ioe); - } - ProcessBuilder pb; - try { - pb = ProcessTools.createTestJavaProcessBuilder("--add-modules", "jdk.hotspot.agent", - "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED", - "sun.jvm.hotspot.CLHSDB", JDKToolFinder.getTestJDKTool("java"), - TEST_CORE_FILE_NAME); - } catch (Exception e) { - throw new Error("Can't create process builder: " + e, e); - } - Process p; - try { - p = pb.start(); - } catch (IOException ioe) { - throw new Error("Can't start child process: " + ioe, ioe); - } - OutputStream input = p.getOutputStream(); - String str = "dumpreplaydata -a > " + REPLAY_FILE_NAME + "\nquit\n"; - try { - input.write(str.getBytes()); - input.flush(); - } catch (IOException ioe) { - throw new Error("Problem writing process input: " + str, ioe); - } - try { - p.waitFor(); - } catch (InterruptedException ie) { - throw new Error("Problem waitinig child process: " + ie, ie); - } - int exitValue = p.exitValue(); - if (exitValue != 0) { - String output; - try { - output = new OutputAnalyzer(p).getOutput(); - } catch (IOException ioe) { - throw new Error("Can't get failed CLHSDB process output: " + ioe, ioe); - } - throw new AssertionError("CLHSDB wasn't run successfully: " + output); - } - File replay = new File(REPLAY_FILE_NAME); - Asserts.assertTrue(replay.exists() && replay.isFile() && replay.length() > 0, - "Replay data wasn't generated by SA"); - // other than comment lines, content of 2 files should be identical - try { - BufferedReader rep = new BufferedReader(new FileReader(replay)); - BufferedReader repCopy = new BufferedReader(new FileReader(REPLAY_FILE_COPY)); - boolean failure = false; - while (true) { - String l1; - while ((l1 = rep.readLine()) != null) { - if (!l1.startsWith("#")) { - break; - } - } - String l2; - while ((l2 = repCopy.readLine()) != null) { - if (!l2.startsWith("#")) { - break; - } - } - if (l1 == null || l2 == null) { - if (l1 != null || l2 != null) { - System.out.println("Warning: replay files are not equal"); - System.out.println("1: " + l1); - System.out.println("2: " + l2); - failure = true; - } - break; - } - if (!l1.equals(l2)) { - System.out.println("Warning: replay files are not equal"); - System.out.println("1: " + l1); - System.out.println("2: " + l2); - failure = true; - } - } - if (failure) { - throw new RuntimeException("Warning: replay files are not equal"); - } - } catch (IOException ioe) { - throw new Error("Can't read replay files: " + ioe, ioe); - } - commonTests(); - runVmTests(); - } - - public static void checkSetLimits() { - if (!Platform.isWindows()) { - OutputAnalyzer oa; - try { - // first check if setting limit is possible - oa = ProcessTools.executeProcess("sh", "-c", RUN_SHELL_NO_LIMIT + "ulimit -c"); - } catch (Throwable t) { - throw new Error("Can't set limits: " + t, t); - } - oa.shouldHaveExitValue(0); - - String out = oa.getOutput().trim(); // cut win/*nix newlines - if (!out.equals("unlimited") && !out.equals("-1")) { - throw new Error("Unable to set limits"); - } - } - } -} - diff --git a/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIntrinsics.java b/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIntrinsics.java index 062866d657f..f82a4899d97 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIntrinsics.java +++ b/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIntrinsics.java @@ -160,6 +160,7 @@ private void checkIntrinsics(Operation op, Method m, String latin1, String utf16 // Different lengths invokeAndCheck(m, 1, "ABCD", "ABC"); + invokeAndCheck(m, '\uff21' - 'A', "ABCEFGHIJKLMNOPQRSTUVWXY\uff21Z", "ABCEFGHIJKLMNOPQRSTUVWXYAZ"); invokeAndCheck(m, -1, "\uff21\uff22\uff23", "\uff21\uff22\uff23\uff24"); invokeAndCheck(m, 1, "ABC\uff24", "ABC"); invokeAndCheck(m, 3, "ABC\uff24\uff25\uff26", "ABC"); diff --git a/test/hotspot/jtreg/compiler/jsr292/MHDeoptTest.java b/test/hotspot/jtreg/compiler/jsr292/MHDeoptTest.java new file mode 100644 index 00000000000..61dd330cfdd --- /dev/null +++ b/test/hotspot/jtreg/compiler/jsr292/MHDeoptTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2025, 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 compiler.jsr292; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; +import java.lang.reflect.Method; + +/* + * @test + * @bug 8336042 + * @library /test/lib / + * + * @run main/bootclasspath/othervm -Xbatch -XX:-TieredCompilation compiler.jsr292.MHDeoptTest + * + */ +public class MHDeoptTest { + + static int xx = 0; + + public static void main(String[] args) throws Throwable { + MethodHandle mh1 = MethodHandles.lookup().findStatic(MHDeoptTest.class, "body1", MethodType.methodType(int.class)); + MethodHandle mh2 = MethodHandles.lookup().findStatic(MHDeoptTest.class, "body2", MethodType.methodType(int.class)); + MethodHandle[] arr = new MethodHandle[] {mh2, mh1}; + + for (MethodHandle mh : arr) { + for (int i = 1; i < 50_000; i++) { + xx = i; + mainLink(mh); + } + } + + } + + static int mainLink(MethodHandle mh) throws Throwable { + return (int)mh.invokeExact(); + } + + static int cnt = 1000; + + static int body1() { + int limit = 0x7fff; + // uncommon trap + if (xx == limit) { + // OSR + for (int i = 0; i < 50_000; i++) { + } + ++cnt; + ++xx; + } + if (xx == limit + 1) { + return cnt + 1; + } + return cnt; + } + + static int body2() { + int limit = 0x7fff; + int dummy = 0; + // uncommon trap + if (xx == limit) { + // OSR + for (int i = 0; i < 50_000; i++) { + } + ++cnt; + ++xx; + } + if (xx == limit + 1) { + return cnt + 1; + } + return cnt; + } + +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index c129b0a8737..f1752d56803 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -2543,6 +2543,16 @@ public class IRNode { machOnlyNameRegex(X86_CMOVEL_IMM01UCF, "cmovL_imm_01UCF"); } + public static final String MOD_F = PREFIX + "MOD_F" + POSTFIX; + static { + macroNodes(MOD_F, "ModF"); + } + + public static final String MOD_D = PREFIX + "MOD_D" + POSTFIX; + static { + macroNodes(MOD_D, "ModD"); + } + /* * Utility methods to set up IR_NODE_MAPPINGS. */ @@ -2588,6 +2598,16 @@ private static void allocNodes(String irNode, String irNodeName, String optoRege IR_NODE_MAPPINGS.put(irNode, entry); } + /** + * Apply {@code regex} on all ideal graph phases up to and including {@link CompilePhase#BEFORE_MACRO_EXPANSION}. + */ + private static void macroNodes(String irNodePlaceholder, String irNodeRegex) { + String regex = START + irNodeRegex + MID + END; + IR_NODE_MAPPINGS.put(irNodePlaceholder, new SinglePhaseRangeEntry(CompilePhase.BEFORE_MACRO_EXPANSION, regex, + CompilePhase.BEFORE_STRINGOPTS, + CompilePhase.BEFORE_MACRO_EXPANSION)); + } + private static void callOfNodes(String irNodePlaceholder, String callRegex) { String regex = START + callRegex + MID + IS_REPLACED + " " + END; IR_NODE_MAPPINGS.put(irNodePlaceholder, new RegexTypeEntry(RegexType.IDEAL_INDEPENDENT, regex)); @@ -2648,19 +2668,6 @@ private static void afterBarrierExpansionToBeforeMatching(String irNodePlacehold CompilePhase.BEFORE_MATCHING)); } - /** - * Apply a regex that matches a macro node IR node name {@code macroNodeName} exactly on all machine independent - * ideal graph phases up to and including {@link CompilePhase#BEFORE_MACRO_EXPANSION}. By default, we match on - * {@link CompilePhase#BEFORE_MACRO_EXPANSION} when no {@link CompilePhase} is chosen. - */ - private static void macroNodes(String irNodePlaceholder, String macroNodeName) { - String macroNodeRegex = START + macroNodeName + "\\b" + MID + END; - IR_NODE_MAPPINGS.put(irNodePlaceholder, new SinglePhaseRangeEntry(CompilePhase.BEFORE_MACRO_EXPANSION, - macroNodeRegex, - CompilePhase.BEFORE_STRINGOPTS, - CompilePhase.BEFORE_MACRO_EXPANSION)); - } - private static void trapNodes(String irNodePlaceholder, String trapReason) { String regex = START + "CallStaticJava" + MID + "uncommon_trap.*" + trapReason + END; beforeMatching(irNodePlaceholder, regex); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/VMInfo.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/VMInfo.java index d76dea902c2..932bacdc795 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/VMInfo.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/VMInfo.java @@ -42,7 +42,7 @@ public class VMInfo { private final Map<String, String> keyValueMap; private static final Pattern CPU_SKYLAKE_PATTERN = - Pattern.compile("family 6 model 85 stepping (\\d) "); + Pattern.compile("family 6 model 85 stepping (\\d+) "); public VMInfo(Map<String, String> map) { this.keyValueMap = map; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/HaltNode.java b/test/hotspot/jtreg/compiler/longcountedloops/TestAssertWhenOuterStripMinedLoopRemoved.java similarity index 53% rename from src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/HaltNode.java rename to test/hotspot/jtreg/compiler/longcountedloops/TestAssertWhenOuterStripMinedLoopRemoved.java index 5c84b2e9a6e..7452a5be616 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/opto/HaltNode.java +++ b/test/hotspot/jtreg/compiler/longcountedloops/TestAssertWhenOuterStripMinedLoopRemoved.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -19,34 +19,37 @@ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. - * */ -package sun.jvm.hotspot.opto; +/* + * @test + * @bug 8347040 + * @summary C2: assert(!loop->_body.contains(in)) failed + * @run main/othervm -XX:-BackgroundCompilation TestAssertWhenOuterStripMinedLoopRemoved + */ -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.Observable; -import sun.jvm.hotspot.utilities.Observer; -public class HaltNode extends Node { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } +import static java.lang.foreign.ValueLayout.JAVA_LONG; - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("HaltNode"); - } +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +public class TestAssertWhenOuterStripMinedLoopRemoved { + static final int COUNT = 100000; + static final MemorySegment segment = Arena.global().allocate(JAVA_LONG, COUNT); - public HaltNode(Address addr) { - super(addr); - } + public static void main(String[] args) { + for (int i = 0; i < 10000; i++) { + test(); + } + } + + static void test() { + var i = 0; + var j = 0; + while (i < 100000) { + segment.setAtIndex(JAVA_LONG, i++, 0); + segment.setAtIndex(JAVA_LONG, j++, 0); + } + } } diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestEquivalentInvariants.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestEquivalentInvariants.java index 09b087bee54..b3032b1fa4e 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestEquivalentInvariants.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestEquivalentInvariants.java @@ -39,7 +39,7 @@ * i.e. where the invariants have the same summands, but in a different order. * @modules java.base/jdk.internal.misc * @library /test/lib / - * @run driver compiler.loopopts.superword.TestEquivalentInvariants + * @run driver/timeout=1200 compiler.loopopts.superword.TestEquivalentInvariants */ public class TestEquivalentInvariants { diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegmentUnalignedAddress.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegmentUnalignedAddress.java new file mode 100644 index 00000000000..13fd9ff9b17 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegmentUnalignedAddress.java @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2025, 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 compiler.loopopts.superword; + +import compiler.lib.ir_framework.*; +import compiler.lib.verify.*; +import jdk.test.lib.Utils; +import java.nio.ByteBuffer; +import java.util.Map; +import java.util.HashMap; +import java.util.Random; +import java.lang.foreign.*; + +/* + * @test id=byte-buffer-direct + * @bug 8323582 + * @summary Test vectorization of loops over MemorySegment, with native memory where the address is not always aligned. + * @library /test/lib / + * @run driver compiler.loopopts.superword.TestMemorySegmentUnalignedAddress ByteBufferDirect + */ + +/* + * @test id=byte-buffer-direct-AlignVector + * @bug 8323582 + * @summary Test vectorization of loops over MemorySegment, with native memory where the address is not always aligned. + * @library /test/lib / + * @run driver compiler.loopopts.superword.TestMemorySegmentUnalignedAddress ByteBufferDirect AlignVector + */ + +/* + * @test id=byte-buffer-direct-VerifyAlignVector + * @bug 8323582 + * @summary Test vectorization of loops over MemorySegment, with native memory where the address is not always aligned. + * @library /test/lib / + * @run driver compiler.loopopts.superword.TestMemorySegmentUnalignedAddress ByteBufferDirect VerifyAlignVector + */ + +/* + * @test id=native + * @bug 8323582 + * @summary Test vectorization of loops over MemorySegment, with native memory where the address is not always aligned. + * @library /test/lib / + * @run driver compiler.loopopts.superword.TestMemorySegmentUnalignedAddress Native + */ + +/* + * @test id=native-AlignVector + * @bug 8323582 + * @summary Test vectorization of loops over MemorySegment, with native memory where the address is not always aligned. + * @library /test/lib / + * @run driver compiler.loopopts.superword.TestMemorySegmentUnalignedAddress Native AlignVector + */ + +/* + * @test id=native-VerifyAlignVector + * @bug 8323582 + * @summary Test vectorization of loops over MemorySegment, with native memory where the address is not always aligned. + * @library /test/lib / + * @run driver compiler.loopopts.superword.TestMemorySegmentUnalignedAddress Native VerifyAlignVector + */ + +public class TestMemorySegmentUnalignedAddress { + public static void main(String[] args) { + TestFramework framework = new TestFramework(TestMemorySegmentUnalignedAddressImpl.class); + framework.addFlags("-DmemorySegmentProviderNameForTestVM=" + args[0]); + if (args.length > 1) { + switch (args[1]) { + case "AlignVector" -> { framework.addFlags("-XX:+AlignVector"); } + case "VerifyAlignVector" -> { framework.addFlags("-XX:+AlignVector", "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+VerifyAlignVector"); } + default -> { throw new RuntimeException("unexpected: " + args[1]); } + } + } + framework.setDefaultWarmup(100); + framework.start(); + } +} + +class TestMemorySegmentUnalignedAddressImpl { + static final int SIZE = 10_000; + static final int BACKING_SIZE = 10_000 + 1; + static final Random RANDOM = Utils.getRandomInstance(); + + interface TestFunction { + Object run(int i); + } + + interface MemorySegmentProvider { + MemorySegment newMemorySegment(); + } + + static MemorySegmentProvider provider; + + static { + String providerName = System.getProperty("memorySegmentProviderNameForTestVM"); + provider = switch (providerName) { + case "ByteBufferDirect" -> TestMemorySegmentUnalignedAddressImpl::newMemorySegmentOfByteBufferDirect; + case "Native" -> TestMemorySegmentUnalignedAddressImpl::newMemorySegmentOfNative; + default -> throw new RuntimeException("Test argument not recognized: " + providerName); + }; + } + + // List of tests + Map<String, TestFunction> tests = new HashMap<>(); + + // List of gold, the results from the first run before compilation + Map<String, Object> golds = new HashMap<>(); + + public TestMemorySegmentUnalignedAddressImpl () { + // Generate two MemorySegments as inputs + MemorySegment a = sliceAligned(newMemorySegment()); + MemorySegment b = sliceAligned(newMemorySegment()); + fillRandom(a); + fillRandom(b); + + // Add all tests to list + tests.put("testAlwaysAligned", (int i) -> { + MemorySegment ms = newMemorySegment(); + MemorySegment slice = sliceAligned(ms); + copy(a, slice); + return testAlwaysAligned(slice); + }); + tests.put("testAlwaysUnaligned", (int i) -> { + MemorySegment ms = newMemorySegment(); + MemorySegment slice = sliceUnaligned(ms); + copy(a, slice); + return testAlwaysUnaligned(slice); + }); + tests.put("testMixedAlignedAndUnaligned", (int i) -> { + MemorySegment ms = newMemorySegment(); + MemorySegment slice = (i % 2 == 0) ? sliceUnaligned(ms) : sliceAligned(ms); + copy(a, slice); + return testMixedAlignedAndUnaligned(slice); + }); + + // Compute gold value for all test methods before compilation + for (Map.Entry<String,TestFunction> entry : tests.entrySet()) { + String name = entry.getKey(); + TestFunction test = entry.getValue(); + Object gold = test.run(0); + golds.put(name, gold); + } + } + + MemorySegment sliceAligned(MemorySegment src) { + return src.asSlice(0, SIZE); + } + + MemorySegment sliceUnaligned(MemorySegment src) { + return src.asSlice(1, SIZE); + } + + MemorySegment newMemorySegment() { + return provider.newMemorySegment(); + } + + static void copy(MemorySegment src, MemorySegment dst) { + MemorySegment.copy(src, 0, dst, 0, src.byteSize()); + } + + static MemorySegment newMemorySegmentOfByteBufferDirect() { + return MemorySegment.ofBuffer(ByteBuffer.allocateDirect(BACKING_SIZE)); + } + + static MemorySegment newMemorySegmentOfNative() { + // Auto arena: GC decides when there is no reference to the MemorySegment, + // and then it deallocates the backing memory. + return Arena.ofAuto().allocate(BACKING_SIZE, 1); + } + + static void fillRandom(MemorySegment data) { + for (int i = 0; i < (int)data.byteSize(); i++) { + data.set(ValueLayout.JAVA_BYTE, i, (byte)RANDOM.nextInt()); + } + } + + static void verify(String name, Object gold, Object result) { + try { + Verify.checkEQ(gold, result); + } catch (VerifyException e) { + throw new RuntimeException("Verify: wrong result in " + name, e); + } + } + + static int runInvocationCounter = 0; + + @Run(test = {"testAlwaysAligned", + "testAlwaysUnaligned", + "testMixedAlignedAndUnaligned"}) + void runTests() { + runInvocationCounter++; + for (Map.Entry<String,TestFunction> entry : tests.entrySet()) { + String name = entry.getKey(); + TestFunction test = entry.getValue(); + // Recall gold value from before compilation + Object gold = golds.get(name); + // Compute new result + Object result = test.run(runInvocationCounter); + // Compare gold and new result + verify(name, gold, result); + } + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", + IRNode.ADD_VI, "> 0", + IRNode.STORE_VECTOR, "> 0", + "multiversion", "= 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + phase = CompilePhase.PRINT_IDEAL) + // We never fail the alignment check in the auto vectorization Predicate, + // hence we never even create the multiversioned loops. + static Object testAlwaysAligned(MemorySegment ms) { + for (long i = 0; i < ms.byteSize(); i += 4) { + int v = ms.get(ValueLayout.JAVA_INT_UNALIGNED, i); + ms.set(ValueLayout.JAVA_INT_UNALIGNED, i, (int)(v + 1)); + } + return new Object[]{ ms }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", + IRNode.ADD_VI, "> 0", + IRNode.STORE_VECTOR, "> 0", + "multiversion_fast", "= 4", // pre, main, drain, post + "multiversion_slow", "= 2"}, // main, post + applyIf = {"AlignVector", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + phase = CompilePhase.PRINT_IDEAL) + // We add alignment checks to the auto vectorization Predicate. It fails + // at runtime, deopts, and recompiles with multiversioning. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", + IRNode.ADD_VI, "> 0", + IRNode.STORE_VECTOR, "> 0", + "multiversion_fast", "= 0", + "multiversion_slow", "= 0"}, + applyIf = {"AlignVector", "false"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + phase = CompilePhase.PRINT_IDEAL) + // We never add any conditions to the auto vectorization Predicate, so + // we also never deopt and never end up multiversioning. + static Object testAlwaysUnaligned(MemorySegment ms) { + for (long i = 0; i < ms.byteSize(); i += 4) { + int v = ms.get(ValueLayout.JAVA_INT_UNALIGNED, i); + ms.set(ValueLayout.JAVA_INT_UNALIGNED, i, (int)(v + 1)); + } + return new Object[]{ ms }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", + IRNode.ADD_VI, "> 0", + IRNode.STORE_VECTOR, "> 0", + "multiversion_fast", "= 4", // pre, main, drain, post + "multiversion_slow", "= 2"}, // main, post + applyIf = {"AlignVector", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + phase = CompilePhase.PRINT_IDEAL) + // We add alignment checks to the auto vectorization Predicate. It fails + // at runtime, deopts, and recompiles with multiversioning. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", + IRNode.ADD_VI, "> 0", + IRNode.STORE_VECTOR, "> 0", + "multiversion_fast", "= 0", + "multiversion_slow", "= 0"}, + applyIf = {"AlignVector", "false"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + phase = CompilePhase.PRINT_IDEAL) + // We never add any conditions to the auto vectorization Predicate, so + // we also never deopt and never end up multiversioning. + static Object testMixedAlignedAndUnaligned(MemorySegment ms) { + for (long i = 0; i < ms.byteSize(); i += 4) { + int v = ms.get(ValueLayout.JAVA_INT_UNALIGNED, i); + ms.set(ValueLayout.JAVA_INT_UNALIGNED, i, (int)(v + 1)); + } + return new Object[]{ ms }; + } +} diff --git a/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java b/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java index f1565db47d9..aef477f4402 100644 --- a/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java +++ b/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2023, 2024, Red Hat, Inc. All rights reserved. - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Red Hat, Inc. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,33 +25,33 @@ /* * @test id=c1_crash * @requires vm.compiler1.enabled - * @summary Checks that -XX:CompileCommand=MemLimit,...,crash causes C1 to crash + * @summary Checks that -XX:CompileCommand=MemLimit,...,xx~crash causes C1 to crash * @library /test/lib - * @run driver compiler.print.CompileCommandMemLimit crash false + * @run driver compiler.print.CompileCommandMemLimit c1 crash */ /* * @test id=c2_crash * @requires vm.compiler2.enabled - * @summary Checks that -XX:CompileCommand=MemLimit,...,crash causes C2 to crash + * @summary Checks that -XX:CompileCommand=MemLimit,...,xx~crash causes C2 to crash * @library /test/lib - * @run driver compiler.print.CompileCommandMemLimit crash true + * @run driver compiler.print.CompileCommandMemLimit c2 crash */ /* * @test id=c1_stop * @requires vm.compiler1.enabled - * @summary Checks that -XX:CompileCommand=MemLimit,...,stop causes C1 to stop + * @summary Checks that -XX:CompileCommand=MemLimit,...,xx causes C1 to bail out from the compilation * @library /test/lib - * @run driver compiler.print.CompileCommandMemLimit stop false + * @run driver compiler.print.CompileCommandMemLimit c1 stop */ /* * @test id=c2_stop * @requires vm.compiler2.enabled - * @summary Checks that -XX:CompileCommand=MemLimit,...,stop causes C2 to stop + * @summary Checks that -XX:CompileCommand=MemLimit,...,xx causes C2 to bail out from the compilation * @library /test/lib - * @run driver compiler.print.CompileCommandMemLimit stop true + * @run driver compiler.print.CompileCommandMemLimit c2 stop */ package compiler.print; @@ -73,16 +73,12 @@ public class CompileCommandMemLimit { // Method for which we explicitly disable a limit on the command line. final static String METHOD3 = "method3"; - static boolean c2; - static boolean test_crash; + enum TestMode { crash, stop }; + enum CompilerType { c1, c2 }; public static void main(String[] args) throws Exception { - switch (args[0]) { - case "crash" : test_crash = true; break; - case "stop" : test_crash = false; break; - default: throw new RuntimeException("invalid argument"); - } - c2 = Boolean.parseBoolean(args[1]); + CompilerType ctyp = CompilerType.valueOf(args[0]); + TestMode mode = TestMode.valueOf(args[1]); List<String> options = new ArrayList<String>(); options.add("-Xcomp"); @@ -92,19 +88,40 @@ public static void main(String[] args) throws Exception { options.add("-XX:CompileCommand=compileonly," + getTestClass() + "::*"); // We want a final report - options.add("-XX:CompileCommand=MemStat,*.*,print"); - - // We limit method 2 to a very small limit that is guaranteed to trigger - options.add("-XX:CompileCommand=MemLimit," + getTestMethod(METHOD2) + ",4k" + (test_crash ? "~crash" : "")); - - // We disable any limit set on method 3 - options.add("-XX:CompileCommand=MemLimit," + getTestMethod(METHOD3) + ",0"); - - if (c2) { + options.add("-XX:CompileCommand=MemStat," + getTestMethod(METHOD2) + ",print"); + + String suffix = mode == TestMode.crash ? "~crash" : ""; + + // About the limit: + // + // In the debug JVM, for this test class, compilers will allocate (near the very end of the compilation) + // 32MB of arena memory. + // + // C1 will allocate them in a single step from RA, leaked until end of compilation. + // + // C2 will allocate them in two steps: first 2MB inside phase "testPhase1" in a temporary arena + // that will be gone by phase end. So, in the phase timeline these 2MB must show up as + // "significant temporary peak". + // In a second phase "testPhase2", we allocate 32MB from resource area, which is leaked until + // the end of the compilation. This means that these 32MB will show up as permanent memory + // increase in the per-phase-timeline. + // + // We then set the limit to 31MB (just shy of the 32MB we allocate), which should reliably trigger the mem limit. + // The 32MB are deliberately chosen to be large, because this will harden the test against normal allocation fluctuations + // (the methods are tiny, so compiling them should accrue normally only a few dozen KB). + // + // In the release JVM, we just use a very tiny memlimit that we are sure to hit every time. + + long limit = Platform.isDebugBuild() ? (1024 * 1024 * 31) : 4096; + + options.add("-XX:CompileCommand=MemLimit," + getTestMethod(METHOD2) + "," + limit + suffix); + + if (ctyp == CompilerType.c2) { options.add("-XX:-TieredCompilation"); } else { options.add("-XX:TieredStopAtLevel=1"); } + options.add(getTestClass()); OutputAnalyzer oa = ProcessTools.executeTestJava(options); @@ -114,14 +131,14 @@ public static void main(String[] args) throws Exception { String method1regex = testMethodNameForRegex(getTestMethod(METHOD1)); String method2regex = testMethodNameForRegex(getTestMethod(METHOD2)); String method3regex = testMethodNameForRegex(getTestMethod(METHOD3)); - String ct = c2 ? "c2" : "c1"; + String limitHitRegex = ctyp + " \\(\\d+\\) compiler/print/CompileCommandMemLimit\\$TestMain::method2.*: Hit MemLimit - limit: " + limit + " now: \\d+"; - if (test_crash) { + if (mode == TestMode.crash) { oa.shouldNotHaveExitValue(0); oa.shouldMatch("# *Internal Error.*"); // method 2 should have hit its tiny limit - oa.shouldMatch("# *fatal error: " + ct + " *" + method2regex + ".*: Hit MemLimit .*limit: 4096.*"); + oa.shouldMatch("# *fatal error: " + limitHitRegex); // none of the other ones should have hit a limit oa.shouldNotMatch(method1regex + ".*Hit MemLimit"); @@ -143,36 +160,28 @@ public static void main(String[] args) throws Exception { } else { oa.shouldHaveExitValue(0); - // In debug builds we have an inbuilt MemLimit. It is very high, so we don't expect it to fire in this test. - // But it will still show up in the final report. - String implicitMemoryLimit = Platform.isDebugBuild() ? "1024M" : "-"; - - // With C2, we print number of nodes, with C1 we don't - String numberNodesRegex = c2 ? "\\d+" : "-"; - // method 2 should have hit its tiny limit - oa.shouldMatch(ct + " " + method2regex + ".*: Hit MemLimit \\(limit: 4096 now: \\d+\\)"); + oa.shouldMatch(limitHitRegex); + + // Compilation should have been aborted and marked as oom + oa.shouldMatch(ctyp + " \\(\\d+\\) \\(oom\\) Arena usage " + method2regex + ".*\\d+.*"); // neither of the other ones should have hit a limit oa.shouldNotMatch(method1regex + ".*Hit MemLimit"); oa.shouldNotMatch(method3regex + ".*Hit MemLimit"); + } - // Final report: - // Method 1 should show up as "ok" and with the default limit, e.g. - // total NA RA result #nodes limit time type #rc thread method - // 32728 0 32728 ok - 1024M 0.045 c1 1 0x000000011b019c10 compiler/print/CompileCommandMemLimit$TestMain::method1(()J) - oa.shouldMatch("\\d+ +\\d+ +\\d+ +ok +" + numberNodesRegex + " +" + implicitMemoryLimit + " +.* +" + method1regex); - - // Method 2 should show up as "oom" and with its tiny limit, e.g. - // total NA RA result #nodes limit time type #rc thread method - // 32728 0 32728 oom - 4096B 0.045 c1 1 0x000000011b019c10 compiler/print/CompileCommandMemLimit$TestMain::method1(()J) - oa.shouldMatch("\\d+ +\\d+ +\\d+ +oom +" + numberNodesRegex + " +4096B +.* +" + method2regex); - - // Method 3 should show up as "ok", and with no limit, even in debug builds, e.g. - // total NA RA result #nodes limit time type #rc thread method - // 32728 0 32728 ok - - 0.045 c1 1 0x000000011b019c10 compiler/print/CompileCommandMemLimit$TestMain::method1(()J) - oa.shouldMatch("\\d+ +\\d+ +\\d+ +ok +" + numberNodesRegex + " +- +.* +" + method3regex); + // In C2, analyze phase timeline and per-phase accumulation + if (ctyp == CompilerType.c2) { + oa.shouldMatch("--- Arena Usage by Arena Type and compilation phase, at arena usage peak of \\d+ ---"); + oa.shouldContain("--- Allocation timelime by phase ---"); + if (Platform.isDebugBuild()) { + oa.shouldMatch(".*testPhase2 +33554432 +33554432 +0 +0 +0 +0 +0.*"); + oa.shouldMatch(" +>\\d+ +testPhase1.*significant temporary peak: \\d+ \\(\\+2098136\\)"); + oa.shouldMatch(" +>\\d+ +testPhase2 +\\d+ +\\(\\+33554432\\).*"); + } } + } // Test class that is invoked by the sub process diff --git a/test/hotspot/jtreg/compiler/print/CompileCommandPrintMemStat.java b/test/hotspot/jtreg/compiler/print/CompileCommandPrintMemStat.java index 2dbf46fd040..733cb3d8513 100644 --- a/test/hotspot/jtreg/compiler/print/CompileCommandPrintMemStat.java +++ b/test/hotspot/jtreg/compiler/print/CompileCommandPrintMemStat.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2023, 2024, Red Hat, Inc. All rights reserved. - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Red Hat, Inc. All rights reserved. + * Copyright (c) 2023, 2025, 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,11 +23,19 @@ */ /* - * @test - * @summary Checks that -XX:CompileCommand=PrintMemStat,... works - * @requires vm.compiler1.enabled | vm.compiler2.enabled + * @test id=c2 + * @summary Checks that -XX:CompileCommand=MemStat,...,print works with C2 + * @requires vm.compiler1.enabled & vm.compiler2.enabled * @library /test/lib - * @run driver compiler.print.CompileCommandPrintMemStat + * @run driver compiler.print.CompileCommandPrintMemStat c2 + */ + +/* + * @test id=c1 + * @summary Checks that -XX:CompileCommand=MemStat,...,print works with C1 + * @requires vm.compiler1.enabled & vm.compiler2.enabled + * @library /test/lib + * @run driver compiler.print.CompileCommandPrintMemStat c1 */ package compiler.print; @@ -44,22 +52,41 @@ public class CompileCommandPrintMemStat { final static String METHOD1 = "method1"; final static String METHOD2 = "method2"; + enum CompType { + c1, c2 + } + public static void main(String[] args) throws Exception { - test(METHOD1, METHOD2); - test(METHOD2, METHOD1); + if (args.length != 1) { + throw new RuntimeException("Missing Args"); + } + CompType ctyp = CompType.valueOf(args[0]); + test(METHOD1, METHOD2, ctyp); + test(METHOD2, METHOD1, ctyp); + test(METHOD1, METHOD2, ctyp); + test(METHOD2, METHOD1, ctyp); } - private static void test(String include, String exclude) throws Exception { + private static void test(String include, String exclude, CompType ctyp) throws Exception { List<String> options = new ArrayList<String>(); options.add("-Xcomp"); - options.add("-XX:-Inline"); options.add("-XX:CompileCommand=compileonly," + getTestClass() + "::*"); + options.add("-XX:-Inline"); + if (ctyp.equals(CompType.c2)) { + options.add("-XX:-TieredCompilation"); + } else { + options.add("-XX:TieredStopAtLevel=1"); + } options.add("-XX:CompileCommand=MemStat," + getTestMethod(include) + ",print"); + options.add("-XX:+UnlockDiagnosticVMOptions"); + options.add("-XX:+PrintCompilerMemoryStatisticsAtExit"); + options.add(getTestClass()); OutputAnalyzer oa = ProcessTools.executeTestJava(options); + oa.reportDiagnosticSummary(); - // We expect two printouts for "PrintMemStat". A line at compilation time, and a line in a summary report + // We expect two printouts for "MemStat". A line at compilation time, and a line in a summary report // that is printed when we exit. Both use the typical <class>::name format but use / as separator and also // print the signature. String expectedNameIncl = getTestMethod(include) @@ -69,27 +96,39 @@ private static void test(String include, String exclude) throws Exception { .replace('.', '/') .replace("$", "\\$"); - // Should see trace output when methods are compiled - oa.shouldHaveExitValue(0). - shouldMatch("Arena usage.*" + expectedNameIncl + ".*"). - shouldNotMatch("Arena usage.*" + expectedNameExcl + ".*"); + oa.shouldHaveExitValue(0); + if (ctyp == CompType.c1) { + // Example output for a C1 compilation output: + // c1 (885) (ok) Arena usage java/util/zip/ZipFile$Source::get((Ljava/io/File;ZLjava/util/zip/ZipCoder;)Ljava/util/zip/ZipFile$Source;): 752744 [ra 687288, cienv 65456] + oa.shouldMatch("c1.*Arena usage " + expectedNameIncl + ".*: \\d+.*"); + } + + // In C2, analyze phase timeline and per-phase accumulation + if (ctyp == CompType.c2) { + oa.shouldMatch("c2.*Arena usage " + expectedNameIncl + ".*: \\d+.*"); + oa.shouldMatch("--- Arena Usage by Arena Type and compilation phase, at arena usage peak of \\d+ ---"); + oa.shouldContain("--- Allocation timelime by phase ---"); + if (Platform.isDebugBuild()) { + oa.shouldMatch(".*testPhase2 +33554432 +33554432 +0 +0 +0 +0 +0.*"); + oa.shouldMatch(" +>\\d+ +testPhase1.*significant temporary peak: \\d+ \\(\\+2098136\\)"); + oa.shouldMatch(" +>\\d+ +testPhase2 +\\d+ +\\(\\+33554432\\).*"); + } + } - // Should see final report - // Looks like this: - // total Others RA HA NA result #nodes limit time type #rc thread method - // 523648 32728 490920 0 0 ok - - 0.250 c1 1 0x00007f4ec00d4ac0 java/lang/Class::descriptorString(()Ljava/lang/String;) - // or - // 1898600 853176 750872 0 294552 ok 934 - 1.501 c2 1 0x00007f4ec00d3330 java/lang/String::replace((CC)Ljava/lang/String;) - oa.shouldMatch("total.*method"); - oa.shouldMatch("\\d+ +(\\d+ +){4}ok +(\\d+|-) +.*" + expectedNameIncl + ".*"); + // We also print a final report to tty if print is enabled. Looks like this: + // + // Compilation Memory usage: + // ctyp total ra node comp type index reglive regsplit cienv other #nodes codesz result limit time id thread method + // c1 14104176 13776896 0 0 0 0 0 0 327280 0 - 0 oom 10240K 0,547 412 0x00007fb14c1fb640 jdk/internal/classfile/impl/StackMapGenerator::processBlock((Ljdk/internal/classfile/impl/RawBytecodeHelper;)Z) + // c2 5058384 4499056 262808 197352 0 0 0 0 32728 66440 293 1464 ok 10240K 0,200 191 0x00007fb14c1f9bb0 java/lang/StringLatin1::lastIndexOf(([BII)I) + oa.shouldMatch("\\s+ctyp\\s+total.*method.*"); + oa.shouldMatch("\\s+c(1|2)\\s+\\d+.*" + expectedNameIncl + ".*"); // In debug builds, we have a default memory limit enabled. That implies MemStat. Therefore we - // expect to see all methods, not just the one we specified on the command line. - if (Platform.isDebugBuild()) { - oa.shouldMatch("\\d+ +(\\d+ +){4}ok +(\\d+|-) +.*" + expectedNameExcl + ".*"); - } else { - oa.shouldNotMatch(".*" + expectedNameExcl + ".*"); + // may see the other method also. + if (!Platform.isDebugBuild()) { + oa.shouldNotContain(expectedNameExcl); } } diff --git a/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java b/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java index db0b563d1fe..3a273c7be8c 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. + * Copyright (c) 2025, 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 +24,7 @@ /** * @test +* @bug 8297172 8331993 8349637 * @key randomness * @summary Test vectorization of numberOfTrailingZeros/numberOfLeadingZeros for Long * @requires vm.compiler2.enabled @@ -30,16 +32,20 @@ * (os.simpleArch == "aarch64" & vm.cpu.features ~= ".*sve.*") | * (os.simpleArch == "riscv64" & vm.cpu.features ~= ".*zvbb.*") * @library /test/lib / +* @modules jdk.incubator.vector * @run driver compiler.vectorization.TestNumberOfContinuousZeros */ package compiler.vectorization; +import jdk.incubator.vector.*; import compiler.lib.ir_framework.*; import java.util.Random; import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; public class TestNumberOfContinuousZeros { + private static final int[] SPECIAL = { 0x01FFFFFF, 0x03FFFFFE, 0x07FFFFFC, 0x0FFFFFF8, 0x1FFFFFF0, 0x3FFFFFE0, 0xFFFFFFFF }; private long[] inputLong; private int[] outputLong; private int[] inputInt; @@ -47,8 +53,8 @@ public class TestNumberOfContinuousZeros { private static final int LEN = 1024; private Random rng; - public static void main(String args[]) { - TestFramework.run(); + public static void main(String[] args) { + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector"); } public TestNumberOfContinuousZeros() { @@ -56,7 +62,7 @@ public TestNumberOfContinuousZeros() { outputLong = new int[LEN]; inputInt = new int[LEN]; outputInt = new int[LEN]; - rng = new Random(42); + rng = Utils.getRandomInstance(); for (int i = 0; i < LEN; ++i) { inputLong[i] = rng.nextLong(); inputInt[i] = rng.nextInt(); @@ -119,5 +125,80 @@ public void checkResultInt() { Asserts.assertEquals(outputInt[i], Integer.numberOfLeadingZeros(inputInt[i])); } } + + @Setup + static Object[] setupSpecialIntArray() { + int[] res = new int[LEN]; + + for (int i = 0; i < LEN; i++) { + res[i] = SPECIAL[i % SPECIAL.length]; + } + + return new Object[] { res }; + } + + @Test + @IR(counts = {IRNode.COUNT_LEADING_ZEROS_VI, "> 0"}) + @Arguments(setup = "setupSpecialIntArray") + public Object[] testSpecialIntLeadingZeros(int[] ints) { + int[] res = new int[LEN]; + + for (int i = 0; i < LEN; ++i) { + res[i] = Integer.numberOfLeadingZeros(ints[i]); + } + + return new Object[] { ints, res }; + } + + @Check(test = "testSpecialIntLeadingZeros") + public void checkSpecialIntLeadingZeros(Object[] vals) { + int[] in = (int[]) vals[0]; + int[] out = (int[]) vals[1]; + + for (int i = 0; i < LEN; ++i) { + int value = Integer.numberOfLeadingZeros(in[i]); + + if (out[i] != value) { + throw new IllegalStateException("Expected lzcnt(" + in[i] + ") to be " + value + " but got " + out[i]); + } + } + } + + private static final VectorSpecies<Integer> SPECIES = IntVector.SPECIES_PREFERRED; + + @Test + @IR(counts = {IRNode.COUNT_LEADING_ZEROS_VI, "> 0"}) + @Arguments(setup = "setupSpecialIntArray") + public Object[] checkSpecialIntLeadingZerosVector(int[] ints) { + int[] res = new int[LEN]; + + for (int i = 0; i < ints.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, ints, i); + av.lanewise(VectorOperators.LEADING_ZEROS_COUNT).intoArray(res, i); + } + + return new Object[] { ints, res }; + } + + @Check(test = "checkSpecialIntLeadingZerosVector") + public void checkSpecialIntLeadingZerosVector(Object[] vals) { + int[] ints = (int[]) vals[0]; + int[] res = (int[]) vals[1]; + + // Verification + + int[] check = new int[LEN]; + + for (int i = 0; i < ints.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, ints, i); + av.lanewise(VectorOperators.LEADING_ZEROS_COUNT).intoArray(check, i); + } + + for (int i = 0; i < LEN; i++) { + if (res[i] != check[i]) { + throw new IllegalStateException("Expected " + check[i] + " but got " + res[i]); + } + } + } } diff --git a/test/hotspot/jtreg/compiler/vectorization/TestVectorZeroCount.java b/test/hotspot/jtreg/compiler/vectorization/TestVectorZeroCount.java new file mode 100644 index 00000000000..a29ade54008 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/TestVectorZeroCount.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8349637 + * @summary Ensure that vectorization of numberOfLeadingZeros and numberOfTrailingZeros outputs correct values + * @library /test/lib / + * @run main/othervm compiler.vectorization.TestVectorZeroCount + */ + +package compiler.vectorization; + +import java.util.Random; + +import jdk.test.lib.Utils; + +public class TestVectorZeroCount { + private static final int SIZE = 1024; + private static final Random RANDOM = Utils.getRandomInstance(); + + private static final int[] INT_VALUES = new int[SIZE]; + private static final int[] INT_EXPECTED_LEADING = new int[SIZE]; + private static final int[] INT_RESULT_LEADING = new int[SIZE]; + private static final int[] INT_EXPECTED_TRAILING = new int[SIZE]; + private static final int[] INT_RESULT_TRAILING = new int[SIZE]; + + private static final long[] LONG_VALUES = new long[SIZE]; + private static final long[] LONG_EXPECTED_LEADING = new long[SIZE]; + private static final long[] LONG_RESULT_LEADING = new long[SIZE]; + private static final long[] LONG_EXPECTED_TRAILING = new long[SIZE]; + private static final long[] LONG_RESULT_TRAILING = new long[SIZE]; + + private static int intCounter = Integer.MIN_VALUE; + private static int longIterations = 100_000_000; + + public static boolean testInt() { + boolean done = false; + + // Non-vectorized loop as baseline (not vectorized because source array is initialized) + for (int i = 0; i < SIZE; ++i) { + INT_VALUES[i] = intCounter++; + if (intCounter == Integer.MAX_VALUE) { + done = true; + } + INT_EXPECTED_LEADING[i] = Integer.numberOfLeadingZeros(INT_VALUES[i]); + INT_EXPECTED_TRAILING[i] = Integer.numberOfTrailingZeros(INT_VALUES[i]); + } + // Vectorized loop + for (int i = 0; i < SIZE; ++i) { + INT_RESULT_LEADING[i] = Integer.numberOfLeadingZeros(INT_VALUES[i]); + } + for (int i = 0; i < SIZE; ++i) { + INT_RESULT_TRAILING[i] = Integer.numberOfTrailingZeros(INT_VALUES[i]); + } + + // Compare results + for (int i = 0; i < SIZE; ++i) { + if (INT_RESULT_LEADING[i] != INT_EXPECTED_LEADING[i]) { + throw new RuntimeException("Unexpected result for Integer.numberOfLeadingZeros(" + INT_VALUES[i] + "): " + INT_RESULT_LEADING[i] + ", expected " + INT_EXPECTED_LEADING[i]); + } + if (INT_RESULT_TRAILING[i] != INT_EXPECTED_TRAILING[i]) { + throw new RuntimeException("Unexpected result for Integer.numberOfTrailingZeros(" + INT_VALUES[i] + "): " + INT_RESULT_TRAILING[i] + ", expected " + INT_EXPECTED_TRAILING[i]); + } + } + return done; + } + + public static boolean testLong() { + boolean done = false; + + // Non-vectorized loop as baseline (not vectorized because source array is initialized) + for (int i = 0; i < SIZE; ++i) { + // Use random values because the long range is too large to iterate over it + LONG_VALUES[i] = RANDOM.nextLong(); + if (longIterations-- == 0) { + done = true; + } + LONG_EXPECTED_LEADING[i] = Long.numberOfLeadingZeros(LONG_VALUES[i]); + LONG_EXPECTED_TRAILING[i] = Long.numberOfTrailingZeros(LONG_VALUES[i]); + } + // Vectorized loop + for (int i = 0; i < SIZE; ++i) { + LONG_RESULT_LEADING[i] = Long.numberOfLeadingZeros(LONG_VALUES[i]); + } + for (int i = 0; i < SIZE; ++i) { + LONG_RESULT_TRAILING[i] = Long.numberOfTrailingZeros(LONG_VALUES[i]); + } + + // Compare results + for (int i = 0; i < SIZE; ++i) { + if (LONG_RESULT_LEADING[i] != LONG_EXPECTED_LEADING[i]) { + throw new RuntimeException("Unexpected result for Long.numberOfLeadingZeros(" + LONG_VALUES[i] + "): " + LONG_RESULT_LEADING[i] + ", expected " + LONG_EXPECTED_LEADING[i]); + } + if (LONG_RESULT_TRAILING[i] != LONG_EXPECTED_TRAILING[i]) { + throw new RuntimeException("Unexpected result for Long.numberOfTrailingZeros(" + LONG_VALUES[i] + "): " + LONG_RESULT_TRAILING[i] + ", expected " + LONG_EXPECTED_TRAILING[i]); + } + } + return done; + } + + public static void main(String[] args) { + // Run twice to make sure compiled code is used from the beginning + for (int i = 0; i < 2; ++i) { + while (!testLong()) ; + while (!testInt()) ; + } + } +} diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java b/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java new file mode 100644 index 00000000000..e7989874d7a --- /dev/null +++ b/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2025, BELLSOFT. 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. + */ + +import jdk.test.lib.containers.docker.Common; +import jdk.test.lib.containers.docker.DockerTestUtils; +import jdk.test.lib.containers.docker.DockerRunOptions; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.internal.platform.Metrics; + +import java.util.ArrayList; + +import jtreg.SkippedException; + +/* + * @test + * @bug 8343191 + * @requires os.family == "linux" + * @modules java.base/jdk.internal.platform + * @library /test/lib + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar whitebox.jar jdk.test.whitebox.WhiteBox + * @run main TestMemoryWithSubgroups + */ +public class TestMemoryWithSubgroups { + + private static final String imageName = Common.imageName("subgroup"); + + public static void main(String[] args) throws Exception { + Metrics metrics = Metrics.systemMetrics(); + if (metrics == null) { + System.out.println("Cgroup not configured."); + return; + } + if (!DockerTestUtils.canTestDocker()) { + System.out.println("Unable to run docker tests."); + return; + } + Common.prepareWhiteBox(); + DockerTestUtils.buildJdkContainerImage(imageName); + + if ("cgroupv1".equals(metrics.getProvider())) { + try { + testMemoryLimitSubgroupV1("200m", "100m", "104857600", false); + testMemoryLimitSubgroupV1("1g", "500m", "524288000", false); + testMemoryLimitSubgroupV1("200m", "100m", "104857600", true); + testMemoryLimitSubgroupV1("1g", "500m", "524288000", true); + } finally { + DockerTestUtils.removeDockerImage(imageName); + } + } else if ("cgroupv2".equals(metrics.getProvider())) { + try { + testMemoryLimitSubgroupV2("200m", "100m", "104857600", false); + testMemoryLimitSubgroupV2("1g", "500m", "524288000", false); + testMemoryLimitSubgroupV2("200m", "100m", "104857600", true); + testMemoryLimitSubgroupV2("1g", "500m", "524288000", true); + } finally { + DockerTestUtils.removeDockerImage(imageName); + } + } else { + throw new SkippedException("Metrics are from neither cgroup v1 nor v2, skipped for now."); + } + } + + private static void testMemoryLimitSubgroupV1(String containerMemorySize, String valueToSet, String expectedValue, boolean privateNamespace) + throws Exception { + + Common.logNewTestCase("Cgroup V1 subgroup memory limit: " + valueToSet); + + DockerRunOptions opts = new DockerRunOptions(imageName, "sh", "-c"); + opts.javaOpts = new ArrayList<>(); + opts.appendTestJavaOptions = false; + opts.addDockerOpts("--privileged") + .addDockerOpts("--cgroupns=" + (privateNamespace ? "private" : "host")) + .addDockerOpts("--memory", containerMemorySize); + opts.addClassOptions("mkdir -p /sys/fs/cgroup/memory/test ; " + + "echo " + valueToSet + " > /sys/fs/cgroup/memory/test/memory.limit_in_bytes ; " + + "echo $$ > /sys/fs/cgroup/memory/test/cgroup.procs ; " + + "/jdk/bin/java -Xlog:os+container=trace -version"); + + Common.run(opts) + .shouldMatch("Lowest limit was:.*" + expectedValue); + } + + private static void testMemoryLimitSubgroupV2(String containerMemorySize, String valueToSet, String expectedValue, boolean privateNamespace) + throws Exception { + + Common.logNewTestCase("Cgroup V2 subgroup memory limit: " + valueToSet); + + DockerRunOptions opts = new DockerRunOptions(imageName, "sh", "-c"); + opts.javaOpts = new ArrayList<>(); + opts.appendTestJavaOptions = false; + opts.addDockerOpts("--privileged") + .addDockerOpts("--cgroupns=" + (privateNamespace ? "private" : "host")) + .addDockerOpts("--memory", containerMemorySize); + opts.addClassOptions("mkdir -p /sys/fs/cgroup/memory/test ; " + + "echo $$ > /sys/fs/cgroup/memory/test/cgroup.procs ; " + + "echo '+memory' > /sys/fs/cgroup/cgroup.subtree_control ; " + + "echo '+memory' > /sys/fs/cgroup/memory/cgroup.subtree_control ; " + + "echo " + valueToSet + " > /sys/fs/cgroup/memory/test/memory.max ; " + + "/jdk/bin/java -Xlog:os+container=trace -version"); + + Common.run(opts) + .shouldMatch("Lowest limit was:.*" + expectedValue); + } +} diff --git a/test/hotspot/jtreg/gc/epsilon/TestDieDefault.java b/test/hotspot/jtreg/gc/epsilon/TestDieDefault.java index 016bb517c3c..8c393ceb178 100644 --- a/test/hotspot/jtreg/gc/epsilon/TestDieDefault.java +++ b/test/hotspot/jtreg/gc/epsilon/TestDieDefault.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved. + * Copyright (c) 2017, 2025, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,13 +37,13 @@ public class TestDieDefault { public static void passWith(String... args) throws Exception { - OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args); + OutputAnalyzer out = ProcessTools.executeTestJava(args); out.shouldNotContain("OutOfMemoryError"); out.shouldHaveExitValue(0); } public static void failWith(String... args) throws Exception { - OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args); + OutputAnalyzer out = ProcessTools.executeTestJava(args); out.shouldContain("OutOfMemoryError"); if (out.getExitValue() == 0) { throw new IllegalStateException("Should have failed with non-zero exit code"); diff --git a/test/hotspot/jtreg/gc/epsilon/TestDieWithHeapDump.java b/test/hotspot/jtreg/gc/epsilon/TestDieWithHeapDump.java index 8f6e9a36d77..e9f94f47f0c 100644 --- a/test/hotspot/jtreg/gc/epsilon/TestDieWithHeapDump.java +++ b/test/hotspot/jtreg/gc/epsilon/TestDieWithHeapDump.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved. + * Copyright (c) 2017, 2025, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,13 +38,13 @@ public class TestDieWithHeapDump { public static void passWith(String... args) throws Exception { - OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args); + OutputAnalyzer out = ProcessTools.executeTestJava(args); out.shouldNotContain("OutOfMemoryError"); out.shouldHaveExitValue(0); } public static void failWith(String... args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(args); + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(args); Process p = pb.start(); OutputAnalyzer out = new OutputAnalyzer(p); out.shouldContain("OutOfMemoryError"); diff --git a/test/hotspot/jtreg/gc/epsilon/TestDieWithOnError.java b/test/hotspot/jtreg/gc/epsilon/TestDieWithOnError.java index 7be60c59595..9212cac807f 100644 --- a/test/hotspot/jtreg/gc/epsilon/TestDieWithOnError.java +++ b/test/hotspot/jtreg/gc/epsilon/TestDieWithOnError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved. + * Copyright (c) 2017, 2025, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,14 +39,14 @@ public class TestDieWithOnError { static String ON_ERR_MSG = "Epsilon error handler message"; public static void passWith(String... args) throws Exception { - OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args); + OutputAnalyzer out = ProcessTools.executeTestJava(args); out.shouldNotContain("OutOfMemoryError"); out.stdoutShouldNotMatch("^" + ON_ERR_MSG); out.shouldHaveExitValue(0); } public static void failWith(String... args) throws Exception { - OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args); + OutputAnalyzer out = ProcessTools.executeTestJava(args); out.shouldContain("OutOfMemoryError"); if (out.getExitValue() == 0) { throw new IllegalStateException("Should have failed with non-zero exit code"); diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestClone.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestClone.java index 2b1340890e1..2e98c72ee17 100644 --- a/test/hotspot/jtreg/gc/shenandoah/compiler/TestClone.java +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestClone.java @@ -232,6 +232,32 @@ * TestClone */ +/* + * @test id=generational-small-card-size + * @summary Test clone barriers work correctly + * @requires vm.gc.Shenandoah + * + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xms1g -Xmx1g + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -XX:GCCardSizeInBytes=128 + * TestClone + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xms1g -Xmx1g + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -XX:GCCardSizeInBytes=128 + * -Xint + * TestClone + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xms1g -Xmx1g + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -XX:GCCardSizeInBytes=128 + * -XX:-TieredCompilation + * TestClone + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xms1g -Xmx1g + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -XX:GCCardSizeInBytes=128 + * -XX:TieredStopAtLevel=1 + * TestClone + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xms1g -Xmx1g + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -XX:GCCardSizeInBytes=128 + * -XX:TieredStopAtLevel=4 + * TestClone + */ + /* * @test id=generational-verify * @summary Test clone barriers work correctly diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTClassLinkingVMOptions.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTClassLinkingVMOptions.java index 0d75d16d2b0..470bb699bc3 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTClassLinkingVMOptions.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTClassLinkingVMOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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 @@ -80,6 +80,15 @@ public static void main(String[] args) throws Exception { .assertAbnormalExit("CDS archive has aot-linked classes." + " It cannot be used with -Djava.security.manager=default."); + // Dumping with AOTInvokeDynamicLinking disabled + TestCommon.testDump(appJar, TestCommon.list("Hello"), + "-XX:+UnlockDiagnosticVMOptions", "-XX:+AOTClassLinking", "-XX:-AOTInvokeDynamicLinking"); + + testCase("Archived full module graph must be enabled at runtime (with -XX:-AOTInvokeDynamicLinking)"); + TestCommon.run("-cp", appJar, "-Djdk.module.validation=1", "Hello") + .assertAbnormalExit("CDS archive has aot-linked classes." + + " It cannot be used when archived full module graph is not used"); + // NOTE: tests for ClassFileLoadHook + AOTClassLinking is in // ../jvmti/ClassFileLoadHookTest.java diff --git a/test/hotspot/jtreg/runtime/logging/StressAsyncUL.java b/test/hotspot/jtreg/runtime/logging/StressAsyncUL.java index 1fa6ab76ec2..e14cad6cc65 100644 --- a/test/hotspot/jtreg/runtime/logging/StressAsyncUL.java +++ b/test/hotspot/jtreg/runtime/logging/StressAsyncUL.java @@ -35,19 +35,22 @@ import jdk.test.lib.process.ProcessTools; public class StressAsyncUL { - static void analyze_output(String... args) throws Exception { + static void analyze_output(boolean stalling_mode, String... args) throws Exception { ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(args); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); + if (stalling_mode) { + output.shouldNotContain("messages dropped due to async logging"); + } } public static void main(String[] args) throws Exception { - analyze_output("-Xlog:async:drop", "-Xlog:all=trace", InnerClass.class.getName()); - analyze_output("-Xlog:async:stall", "-Xlog:all=trace", InnerClass.class.getName()); + analyze_output(false, "-Xlog:async:drop", "-Xlog:all=trace", InnerClass.class.getName()); + analyze_output(true, "-Xlog:async:stall", "-Xlog:all=trace", InnerClass.class.getName()); // Stress test with a very small buffer. Note: Any valid buffer size must be able to hold a flush token. // Therefore the size of the buffer cannot be zero. - analyze_output("-Xlog:async:drop", "-Xlog:all=trace", "-XX:AsyncLogBufferSize=192", InnerClass.class.getName()); - analyze_output("-Xlog:async:stall", "-Xlog:all=trace", "-XX:AsyncLogBufferSize=192", InnerClass.class.getName()); + analyze_output(false, "-Xlog:async:drop", "-Xlog:all=trace", "-XX:AsyncLogBufferSize=192", InnerClass.class.getName()); + analyze_output(true, "-Xlog:async:stall", "-Xlog:all=trace", "-XX:AsyncLogBufferSize=192", InnerClass.class.getName()); } public static class InnerClass { diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp b/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp index 7d898bcab25..b9db8b9cc93 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, 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 @@ -127,7 +127,6 @@ Agent_OnAttach(JavaVM *vm, char *options, void *reserved) { jvmtiCapabilities caps; jvmtiError err; JNIEnv *env; - jsize nVMs; jint res; jclass clazz; jmethodID mid; @@ -166,12 +165,6 @@ Agent_OnAttach(JavaVM *vm, char *options, void *reserved) { // call VThreadEventTest.agentStarted to notify test that agent has started - res = JNI_GetCreatedJavaVMs(&vm, 1, &nVMs); - if (res != JNI_OK) { - LOG("JNI_GetCreatedJavaVMs failed: %d\n", res); - return JNI_ERR; - } - res = vm->GetEnv((void **) &env, JNI_VERSION_21); if (res != JNI_OK) { LOG("GetEnv failed: %d\n", res); diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java index d53e5e47f26..abbcb552876 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, 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 @@ -49,7 +49,7 @@ public static void main(String[] args) throws Exception { System.out.println("Started LingeredApp with pid " + theApp.getPid()); List<String> cmds = List.of( - "printstatics", "printstatics SystemDictionary", + "printstatics", "printstatics Threads", "printstatics Universe", "printstatics JvmtiExport"); diff --git a/test/hotspot/jtreg/testlibrary/asm/org/objectweb/asm/ClassReader.java b/test/hotspot/jtreg/testlibrary/asm/org/objectweb/asm/ClassReader.java index 643a6501470..7e499412dc2 100644 --- a/test/hotspot/jtreg/testlibrary/asm/org/objectweb/asm/ClassReader.java +++ b/test/hotspot/jtreg/testlibrary/asm/org/objectweb/asm/ClassReader.java @@ -205,7 +205,6 @@ public ClassReader(final byte[] classFile) { * @param classFileOffset the offset in byteBuffer of the first byte of the ClassFile to be read. * @param classFileLength the length in bytes of the ClassFile to be read. */ - @SuppressWarnings("this-escape") public ClassReader( final byte[] classFileBuffer, final int classFileOffset, diff --git a/test/hotspot/jtreg/testlibrary/asm/org/objectweb/asm/ClassWriter.java b/test/hotspot/jtreg/testlibrary/asm/org/objectweb/asm/ClassWriter.java index ea28726914f..e3c0ad707a0 100644 --- a/test/hotspot/jtreg/testlibrary/asm/org/objectweb/asm/ClassWriter.java +++ b/test/hotspot/jtreg/testlibrary/asm/org/objectweb/asm/ClassWriter.java @@ -292,7 +292,6 @@ public ClassWriter(final int flags) { * do not affect methods that are copied as is in the new class. This means that neither the * maximum stack size nor the stack frames will be computed for these methods</i>. */ - @SuppressWarnings("this-escape") public ClassWriter(final ClassReader classReader, final int flags) { super(/* latest api = */ Opcodes.ASM9); this.flags = flags; diff --git a/test/hotspot/jtreg/testlibrary/asm/org/objectweb/asm/tree/MethodNode.java b/test/hotspot/jtreg/testlibrary/asm/org/objectweb/asm/tree/MethodNode.java index 4c265d44290..31da5e5c5ef 100644 --- a/test/hotspot/jtreg/testlibrary/asm/org/objectweb/asm/tree/MethodNode.java +++ b/test/hotspot/jtreg/testlibrary/asm/org/objectweb/asm/tree/MethodNode.java @@ -275,7 +275,6 @@ public void visitParameter(final String name, final int access) { } @Override - @SuppressWarnings("serial") public AnnotationVisitor visitAnnotationDefault() { return new AnnotationNode( new ArrayList<Object>(0) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadController.cpp b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadController.cpp index 90fd4df97e6..247705d9b9a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadController.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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 @@ -465,8 +465,8 @@ extern "C" { return env->NewStringUTF("TIMED_WAITING"); } // should never reach - assert(0); - return 0; + assert(false); + return nullptr; } /* diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/native/native_thread.cpp b/test/hotspot/jtreg/vmTestbase/nsk/share/native/native_thread.cpp index 089aab78bb5..1929864e0d0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/native/native_thread.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/native/native_thread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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 @@ -98,7 +98,11 @@ void* procedure(void* t) { thread->started = 1; thread->status = thread->procedure(thread->context); thread->finished = 1; +#ifdef windows return 0; +#else // !windows + return nullptr; +#endif } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_list.cpp b/test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_list.cpp index 736ddafdfaf..3da3858445b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_list.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_list.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, 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 @@ -109,7 +109,7 @@ int nsk_list_remove(const void *plist, int ind) { list_info->arr[i - 1] = list_info->arr[i]; } } - list_info->arr[--list_info->elements_count] = 0; + list_info->arr[--list_info->elements_count] = nullptr; return NSK_TRUE; } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress001.cpp b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress001.cpp index 2a5c78488c3..0702f9e5c09 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress001.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress001.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, 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 @@ Java_nsk_stress_jni_JNIter001_jnistress (JNIEnv *env, jobject jobj, jstring jstr for (j = 0; j < DIGESTLENGTH; j++) { digest[j] = 0; } - element->str[allocs] = env->GetStringUTFChars(jstr, 0); CE + element->str[allocs] = env->GetStringUTFChars(jstr, nullptr); CE if (strlen(element->str[allocs]) != (size_t) env->GetStringUTFLength(jstr)) { printf("Length is wrong in string No. %d\n", allocs); } else { @@ -177,7 +177,7 @@ Java_nsk_stress_jni_JNIter001_jnistress1(JNIEnv *env, jobject jobj, jstring jstr for (j = 0; j < DIGESTLENGTH; j++) { digest[j] = 0; } - javachars->str[index] = env->GetStringChars(jstr, 0); CE + javachars->str[index] = env->GetStringChars(jstr, nullptr); CE javachars->size[index] = env->GetStringUTFLength(jstr); CE elem_len = javachars->size[index]; len += elem_len; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress003.cpp b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress003.cpp index 4a261ff6aad..66e8e67d2e0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress003.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress003.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -171,14 +171,14 @@ Java_nsk_stress_jni_JNIter003_jniBodyChangeArray (JNIEnv *env, jobject jobj, /* Take the elements from Java arrays into native buffers */ /* Use Get<Type>ArrayElements */ - boolOrig = env->GetBooleanArrayElements((jbooleanArray) arrayOrig[BOOL], 0); CE - byteOrig = env->GetByteArrayElements((jbyteArray) arrayOrig[BYTE], 0); CE - charOrig = env->GetCharArrayElements((jcharArray) arrayOrig[CHAR], 0); CE - shortOrig = env->GetShortArrayElements((jshortArray) arrayOrig[SHORT], 0); CE - intOrig = env->GetIntArrayElements((jintArray) arrayOrig[INT], 0); CE - longOrig = env->GetLongArrayElements((jlongArray) arrayOrig[LONG], 0); CE - floatOrig = env->GetFloatArrayElements((jfloatArray) arrayOrig[FLOAT], 0); CE - doubleOrig = env->GetDoubleArrayElements((jdoubleArray) arrayOrig[DOUBLE], 0); CE + boolOrig = env->GetBooleanArrayElements((jbooleanArray) arrayOrig[BOOL], nullptr); CE + byteOrig = env->GetByteArrayElements((jbyteArray) arrayOrig[BYTE], nullptr); CE + charOrig = env->GetCharArrayElements((jcharArray) arrayOrig[CHAR], nullptr); CE + shortOrig = env->GetShortArrayElements((jshortArray) arrayOrig[SHORT], nullptr); CE + intOrig = env->GetIntArrayElements((jintArray) arrayOrig[INT], nullptr); CE + longOrig = env->GetLongArrayElements((jlongArray) arrayOrig[LONG], nullptr); CE + floatOrig = env->GetFloatArrayElements((jfloatArray) arrayOrig[FLOAT], nullptr); CE + doubleOrig = env->GetDoubleArrayElements((jdoubleArray) arrayOrig[DOUBLE], nullptr); CE /* Alloc some memory for cloned arrays buffers */ boolClone = (jboolean *)c_malloc(env, SIZE(BOOL) * sizeof(jboolean)); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress004.cpp b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress004.cpp index 8347d00da80..3e3b0ea1cdf 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress004.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress004.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, 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,13 +47,13 @@ Java_nsk_stress_jni_JNIter004_CheckSum (JNIEnv *env, jobject jobj, jstring jstr) digest[i] = 0; } str = (char *)c_malloc(env, len * sizeof(char)); - /* const char *threadName = env->GetStringUTFChars(jstr, 0); */ + /* const char *threadName = env->GetStringUTFChars(jstr, nullptr); */ CHECK(env->MonitorEnter(jobj)); if (upper == 0) { tmp = (jchar *) c_malloc(env, DIGESTLENGTH * sizeof(char)); } - critstr = env->GetStringCritical(jstr, 0); CE + critstr = env->GetStringCritical(jstr, nullptr); CE for (i = 0; i < len; i++) { str[i] = (char) critstr[i]; } @@ -101,7 +101,7 @@ Java_nsk_stress_jni_JNIter004_CheckCompare (JNIEnv *env, jobject jobj, jstring j return JNI_FALSE; } tmp = (jchar *)c_malloc(env, DIGESTLENGTH * sizeof(char)); - critstr = env->GetStringCritical(jstr, 0); CE + critstr = env->GetStringCritical(jstr, nullptr); CE for (i = 0; i < strlen; i++) { str[i] = (char) critstr[i]; } @@ -121,7 +121,7 @@ Java_nsk_stress_jni_JNIter004_CheckCompare (JNIEnv *env, jobject jobj, jstring j /* Compare */ /* env->MonitorEnter(jobj); */ - ch = (jchar *)env->GetPrimitiveArrayCritical(cArr, 0); CE + ch = (jchar *)env->GetPrimitiveArrayCritical(cArr, nullptr); CE printf("Comparing: "); for (i = 0; i < len; i++) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress006.cpp b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress006.cpp index c84685a50fe..5cb9b9385f0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress006.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress006.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, 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,7 +31,7 @@ extern "C" { JNIEXPORT jboolean JNICALL Java_nsk_stress_jni_JNIter006_refs (JNIEnv *env, jobject jobj, jobject tobj, jint LIMIT) { - static jobject *globRefsArray = 0; + static jobject *globRefsArray = nullptr; static int upper = 0; jclass clazz; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress007.cpp b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress007.cpp index 44c195cfd6b..8b3a0d41b1d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress007.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress007.cpp @@ -32,7 +32,7 @@ Java_nsk_stress_jni_JNIter007_incCount (JNIEnv *env, jobject jobj, jstring name) jclass clazz; jfieldID fld; jint value; - const char *str = env->GetStringUTFChars(name, 0); CE + const char *str = env->GetStringUTFChars(name, nullptr); CE CHECK(env->MonitorEnter(jobj)); clazz = env->GetObjectClass(jobj); CE diff --git a/test/jaxp/javax/xml/jaxp/unittest/validation/ValidationTest.java b/test/jaxp/javax/xml/jaxp/unittest/validation/ValidationTest.java index a4538bcf5b5..198196a6d13 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/validation/ValidationTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/validation/ValidationTest.java @@ -26,6 +26,8 @@ import java.io.File; import java.io.FileInputStream; +import java.io.Reader; +import java.io.StringReader; import javax.xml.XMLConstants; import javax.xml.parsers.SAXParserFactory; import javax.xml.stream.XMLInputFactory; @@ -33,6 +35,7 @@ import javax.xml.stream.events.XMLEvent; import javax.xml.transform.Source; import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.stax.StAXSource; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; @@ -48,7 +51,7 @@ /* * @test - * @bug 8220818 8176447 + * @bug 8220818 8176447 8349516 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @run testng/othervm validation.ValidationTest * @summary Runs validations with schemas and sources @@ -139,6 +142,55 @@ public void startElement(String uri, String localName, String qName, Attributes } + /** + * Verifies the bug fix for 8349516, which adds a guard against empty text. + * Prior to the fix, calling {@link XMLStreamReader#getTextCharacters() XMLStreamReader#getTextCharacters()} + * with {@code length = 0} resulted in an {@code IndexOutOfBoundsException}. + * + * This test ensures that the fix prevents such an exception. + * + * @throws Exception if the test fails due to unexpected issues, such as errors + * in creating the schema or reader, or validation errors other than the + * {@code IndexOutOfBoundsException}. + */ + @Test + public void testValidationWithStAX() throws Exception { + String schema = """ + <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" + targetNamespace="http://xxxx.com/schema/test" + attributeFormDefault="unqualified" + elementFormDefault="qualified" + > + + <xs:element name="test"> + <xs:complexType> + <xs:choice> + <xs:element name="tag" type="xs:string" /> + </xs:choice> + </xs:complexType> + </xs:element> + + </xs:schema> + """; + + String xml = """ + <test xmlns="http://xxxx.com/schema/test"> + <tag><![CDATA[]]></tag> + </test> + """; + + Reader schemaReader = new StringReader(schema); + Reader xmlReader = new StringReader(xml); + + Source source = new StreamSource(schemaReader); + + Validator validator = + SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(source).newValidator(); + + XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(xmlReader); + validator.validate(new StAXSource(xmlStreamReader)); + } + private static String getTargetNamespace(String xsdFile) throws Exception { XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(new FileInputStream(xsdFile)); while (reader.hasNext()) { diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index b66e8c26d4c..7e8f5574ba2 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -499,7 +499,6 @@ java/awt/image/multiresolution/MultiResolutionJOptionPaneIconTest.java 8274106 m # Wayland related -java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java 8280991 linux-x64 java/awt/FullScreen/SetFullScreenTest.java 8332155 linux-x64 ############################################################################ @@ -546,6 +545,9 @@ java/io/IO/IO.java 8337935 linux-pp com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java 8030957 aix-all com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java 8030957 aix-all +com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java 8351002 windows-all +com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java 8351002 windows-all + java/lang/management/MemoryMXBean/Pending.java 8158837 generic-all java/lang/management/MemoryMXBean/PendingAllGC.sh 8158837 generic-all java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java 8247426 generic-all @@ -758,6 +760,7 @@ sun/tools/jstat/jstatLineCounts4.sh 8248691,8268211 jdk/incubator/vector/ShortMaxVectorTests.java 8306592 generic-i586 jdk/incubator/vector/LoadJsvmlTest.java 8305390 windows-x64 +jdk/incubator/vector/Long256VectorTests.java 8350840 generic-x64 ############################################################################ diff --git a/test/jdk/com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java b/test/jdk/com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java index bbf26e099f3..ecb65b7b3ea 100644 --- a/test/jdk/com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java +++ b/test/jdk/com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ public static void main(String[] argv) throws Exception { double load; for(int i=0; i<10; i++) { load = mbean.getProcessCpuLoad(); - if((load<0.0 || load>1.0) && load != -1.0) { + if(load<0.0 || load>1.0) { throw new RuntimeException("getProcessCpuLoad() returns " + load + " which is not in the [0.0,1.0] interval"); } diff --git a/test/jdk/com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java b/test/jdk/com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java index 71ee209258a..7bd9d162cb3 100644 --- a/test/jdk/com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java +++ b/test/jdk/com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, 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 @@ -24,7 +24,7 @@ /* * @test * @bug 7028071 - * @summary Basic unit test of OperatingSystemMXBean.getProcessCpuLoad() + * @summary Basic unit test of OperatingSystemMXBean.getSystemCpuLoad() * * @run main GetSystemCpuLoad */ @@ -39,7 +39,7 @@ public static void main(String[] argv) throws Exception { double load; for(int i=0; i<10; i++) { load = mbean.getSystemCpuLoad(); - if((load<0.0 || load>1.0) && load != -1.0) { + if(load<0.0 || load>1.0) { throw new RuntimeException("getSystemCpuLoad() returns " + load + " which is not in the [0.0,1.0] interval"); } diff --git a/test/jdk/java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java b/test/jdk/java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java index f5f77d47319..66f358d64ce 100644 --- a/test/jdk/java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java +++ b/test/jdk/java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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 @@ -52,6 +52,10 @@ public void paint(Graphics g) { super.paint(g); g.setColor(Color.GREEN); g.fillRect(0, 0, getWidth(), getHeight()); + g.setColor(Color.RED); + DisplayMode displayMode = + getGraphicsConfiguration().getDevice().getDisplayMode(); + g.drawString(displayMode.toString(), 100, 100); } }; try { diff --git a/test/jdk/java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java b/test/jdk/java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java index 455ad2f2b0a..c7277e8b96c 100644 --- a/test/jdk/java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java +++ b/test/jdk/java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ * @bug 6646411 * @summary Tests that full screen window and its children receive resize event when display mode changes + * @library /test/lib + * @build jdk.test.lib.Platform jtreg.SkippedException * @run main/othervm NoResizeEventOnDMChangeTest * @run main/othervm -Dsun.java2d.d3d=false NoResizeEventOnDMChangeTest */ @@ -44,9 +46,21 @@ import java.awt.event.ComponentEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.io.BufferedReader; +import java.io.IOException; + +import static java.util.concurrent.TimeUnit.SECONDS; +import jdk.test.lib.Platform; +import jtreg.SkippedException; public class NoResizeEventOnDMChangeTest { + public static void main(String[] args) { + if (Platform.isOnWayland() && !isFixDelivered()) { + throw new SkippedException("Test skipped because fix was not" + + "delivered in current GnomeShell version"); + } + final GraphicsDevice gd = GraphicsEnvironment. getLocalGraphicsEnvironment().getDefaultScreenDevice(); @@ -231,4 +245,34 @@ public synchronized int getDmChanges() { return dmChanges; } } + + private static boolean isFixDelivered() { + try { + Process process = + new ProcessBuilder("/usr/bin/gnome-shell", "--version") + .start(); + + try (BufferedReader reader = process.inputReader()) { + if (process.waitFor(2, SECONDS) && process.exitValue() == 0) { + String line = reader.readLine(); + if (line != null) { + System.out.println("Gnome shell version: " + line); + String[] versionComponents = line + .replaceAll("[^\\d.]", "") + .split("\\."); + + if (versionComponents.length >= 1) { + return Integer.parseInt(versionComponents[0]) > 42; + } + } + } + } + } catch (IOException + | InterruptedException + | IllegalThreadStateException + | NumberFormatException ignored) { + } + + return false; + } } diff --git a/test/jdk/java/foreign/TestAccessModes.java b/test/jdk/java/foreign/TestAccessModes.java index 0cedcc9058e..a721c87484d 100644 --- a/test/jdk/java/foreign/TestAccessModes.java +++ b/test/jdk/java/foreign/TestAccessModes.java @@ -61,6 +61,7 @@ public void testAccessModes(MemorySegment segment, MemoryLayout layout, AccessMo // access is unaligned assertTrue(segment.maxByteAlignment() < layout.byteAlignment()); } + assertEquals(varHandle.isAccessModeSupported(mode), compatible); } static ValueLayout accessLayout(MemoryLayout layout) { diff --git a/test/jdk/java/lang/Thread/ThreadSleepEvent.java b/test/jdk/java/lang/Thread/ThreadSleepEvent.java index 7aa2f507ff0..441e79f3a94 100644 --- a/test/jdk/java/lang/Thread/ThreadSleepEvent.java +++ b/test/jdk/java/lang/Thread/ThreadSleepEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, 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 @@ -24,6 +24,7 @@ /** * @test * @summary Test that Thread.sleep emits a JFR jdk.ThreadSleep event + * @requires vm.hasJFR * @modules jdk.jfr * @run junit ThreadSleepEvent */ diff --git a/test/jdk/java/lang/Thread/virtual/JfrEvents.java b/test/jdk/java/lang/Thread/virtual/JfrEvents.java index badecba7a54..0b0c2ccc7a0 100644 --- a/test/jdk/java/lang/Thread/virtual/JfrEvents.java +++ b/test/jdk/java/lang/Thread/virtual/JfrEvents.java @@ -24,7 +24,7 @@ /** * @test * @summary Basic test for JFR jdk.VirtualThreadXXX events - * @requires vm.continuations + * @requires vm.continuations & vm.hasJFR * @modules jdk.jfr java.base/java.lang:+open jdk.management * @library /test/lib * @run junit/othervm/native --enable-native-access=ALL-UNNAMED JfrEvents diff --git a/test/jdk/java/lang/Thread/virtual/MonitorPinnedEvents.java b/test/jdk/java/lang/Thread/virtual/MonitorPinnedEvents.java index bf63404d79e..23078c4b892 100644 --- a/test/jdk/java/lang/Thread/virtual/MonitorPinnedEvents.java +++ b/test/jdk/java/lang/Thread/virtual/MonitorPinnedEvents.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @summary Test JFR jdk.VirtualThreadPinned event recorded for contended monitor enter * and Object.wait when pinned - * @requires vm.continuations + * @requires vm.continuations & vm.hasJFR * @modules jdk.jfr jdk.management * @library /test/lib * @run junit/othervm --enable-native-access=ALL-UNNAMED MonitorPinnedEvents diff --git a/test/jdk/java/net/InetAddress/IsReachableViaLoopbackTest.java b/test/jdk/java/net/InetAddress/IsReachableViaLoopbackTest.java index 4d340a72fba..2f2ad0ac7dd 100644 --- a/test/jdk/java/net/InetAddress/IsReachableViaLoopbackTest.java +++ b/test/jdk/java/net/InetAddress/IsReachableViaLoopbackTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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 @@ -21,22 +21,24 @@ * questions. */ -import java.io.*; -import java.net.*; -import java.util.*; +import java.io.IOException; +import java.net.InetAddress; +import java.net.NetworkInterface; /** * @test * @bug 8135305 * @key intermittent + * @library /test/lib * @summary ensure we can't ping external hosts via loopback if + * @run main IsReachableViaLoopbackTest */ public class IsReachableViaLoopbackTest { public static void main(String[] args) { try { - InetAddress addr = InetAddress.getByName("localhost"); - InetAddress remoteAddr = InetAddress.getByName("bugs.openjdk.org"); + InetAddress addr = InetAddress.getLoopbackAddress(); + InetAddress remoteAddr = InetAddress.getByName("23.197.138.208"); // use literal address to avoid DNS checks if (!addr.isReachable(10000)) throw new RuntimeException("Localhost should always be reachable"); NetworkInterface inf = NetworkInterface.getByInetAddress(addr); @@ -54,7 +56,6 @@ public static void main(String[] args) { } else { System.out.println("inf == null"); } - } catch (IOException e) { throw new RuntimeException("Unexpected exception:" + e); } diff --git a/test/jdk/java/net/InetAddress/getOriginalHostName.java b/test/jdk/java/net/InetAddress/getOriginalHostName.java index 9f1e6e965d1..71567a7915d 100644 --- a/test/jdk/java/net/InetAddress/getOriginalHostName.java +++ b/test/jdk/java/net/InetAddress/getOriginalHostName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,9 @@ public class getOriginalHostName { public static void main(String[] args) throws Exception { final String HOST = "dummyserver.java.net"; InetAddress ia = null; - ia = InetAddress.getByName(HOST); + ia = getInetAddress(HOST); + if (ia != null) testInetAddress(ia, HOST); + ia = InetAddress.getByAddress(HOST, new byte[] { 1, 2, 3, 4}); testInetAddress(ia, HOST); ia = InetAddress.getByName("255.255.255.0"); testInetAddress(ia, null); @@ -53,6 +55,14 @@ public static void main(String[] args) throws Exception { testInetAddress(ia, ia.getHostName()); } + private static InetAddress getInetAddress(String host) { + try { + return InetAddress.getByName(host); + } catch (java.net.UnknownHostException uhe) { + System.out.println("Skipping " + host + " due to " + uhe); + return null; + } + } private static void testInetAddress(InetAddress ia, String expected) throws Exception { diff --git a/test/jdk/java/net/ipv6tests/TcpTest.java b/test/jdk/java/net/ipv6tests/TcpTest.java index e0ee7e49dc5..0ca35737a76 100644 --- a/test/jdk/java/net/ipv6tests/TcpTest.java +++ b/test/jdk/java/net/ipv6tests/TcpTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import java.net.*; import java.io.*; +import java.util.concurrent.TimeUnit; public class TcpTest extends Tests { static ServerSocket server, server1, server2; @@ -193,13 +194,14 @@ static void test3 () throws Exception { server = new ServerSocket (0); server.setSoTimeout (5000); int port = server.getLocalPort(); - long t1 = System.currentTimeMillis(); + long t1 = System.nanoTime(); try { server.accept (); throw new RuntimeException ("accept should not have returned"); } catch (SocketTimeoutException e) {} - t1 = System.currentTimeMillis() - t1; - checkTime (t1, 5000); + t1 = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t1); + final long expectedTime = TimeUnit.SECONDS.toMillis(5); + checkIfTimeOut(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t1), expectedTime); c1 = new Socket (); c1.connect (new InetSocketAddress (ia4addr, port), 1000); diff --git a/test/jdk/java/net/ipv6tests/Tests.java b/test/jdk/java/net/ipv6tests/Tests.java index 7a6917a6038..21cc83571ae 100644 --- a/test/jdk/java/net/ipv6tests/Tests.java +++ b/test/jdk/java/net/ipv6tests/Tests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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 @@ -151,19 +151,14 @@ public static void comparePackets (DatagramPacket p1, DatagramPacket p2) } } - /* check the time got is within 50% of the time expected */ - public static void checkTime (long got, long expected) { - checkTime(got, expected, expected); - } - /* check the time got is between start and end, given 50% tolerance */ - public static void checkTime(long got, long start, long end) { - dprintln("checkTime: got = " + got + " start = " + start + " end = " + end); - long upper = end + (end / 2); - long lower = start - (start / 2); - if (got > upper || got < lower) { - throw new RuntimeException("checkTime failed: got " + got - + ", expected between " + start + " and " + end); + /* check the timeout breached lower bound time rule */ + public static void checkIfTimeOut(long got, long expected) { + dprintln("checkIfTimeOut: got = " + got + " lower bound = " + expected); + + if (got < expected) { + throw new RuntimeException("checkIfTimeOut failed: got " + got + + ", expected at least " + expected ); } } diff --git a/test/jdk/java/net/ipv6tests/UdpTest.java b/test/jdk/java/net/ipv6tests/UdpTest.java index 8986af74ff4..6139db85407 100644 --- a/test/jdk/java/net/ipv6tests/UdpTest.java +++ b/test/jdk/java/net/ipv6tests/UdpTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ import java.net.InetAddress; import java.net.PortUnreachableException; import java.net.SocketTimeoutException; +import java.util.concurrent.TimeUnit; public class UdpTest extends Tests { static DatagramSocket c3, s1, s2, s3; @@ -138,26 +139,27 @@ static void test2 () throws Exception { s1 = new DatagramSocket (); s2 = new DatagramSocket (); s1.setSoTimeout (4000); - long t1 = System.currentTimeMillis(); + long t1 = System.nanoTime(); try { s1.receive (new DatagramPacket (new byte [128], 128)); throw new Exception ("expected receive timeout "); } catch (SocketTimeoutException e) { } - checkTime (System.currentTimeMillis() - t1, 4000); + final long expectedTime = TimeUnit.SECONDS.toMillis(4); + checkIfTimeOut(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t1), expectedTime); /* check data can be exchanged now */ simpleDataExchange (s1, ia6addr, s2, ia4addr); /* double check timeout still works */ - t1 = System.currentTimeMillis(); + t1 = System.nanoTime(); try { s1.receive (new DatagramPacket (new byte [128], 128)); throw new Exception ("expected receive timeout "); } catch (SocketTimeoutException e) { } - checkTime (System.currentTimeMillis() - t1, 4000); + checkIfTimeOut(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t1), expectedTime); /* check receive works after a delay < timeout */ @@ -174,9 +176,10 @@ public void run () { } catch (Exception e) {} } }); - t1 = System.currentTimeMillis(); + t1 = System.nanoTime(); s1.receive (new DatagramPacket (new byte [128], 128)); - checkTime (System.currentTimeMillis() - t1, 2000, 10000); + final long startTime = TimeUnit.SECONDS.toMillis(2); + checkIfTimeOut(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t1), startTime); s1.close (); s2.close (); System.out.println ("Test2: OK"); diff --git a/test/hotspot/jtreg/compiler/ciReplay/TestSAServer.java b/test/jdk/java/text/Format/DecimalFormat/AffixTest.java similarity index 53% rename from test/hotspot/jtreg/compiler/ciReplay/TestSAServer.java rename to test/jdk/java/text/Format/DecimalFormat/AffixTest.java index 998f63e9ceb..28b14e750a2 100644 --- a/test/hotspot/jtreg/compiler/ciReplay/TestSAServer.java +++ b/test/jdk/java/text/Format/DecimalFormat/AffixTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 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 @@ -21,15 +21,30 @@ * questions. */ -/** +/* * @test - * @bug 8011675 - * @library / /test/lib - * @summary testing of ciReplay with using generated by SA replay.txt - * @requires vm.hasSA & vm.flightRecorder != true & vm.compMode != "Xint" & vm.debug == true & vm.flavor == "server" - * @modules java.base/jdk.internal.misc - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * compiler.ciReplay.SABase server + * @bug 8351074 + * @summary Test input value check for DecimalFormat affix setter methods + * @run junit AffixTest */ + +import org.junit.jupiter.api.Test; + +import java.text.DecimalFormat; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class AffixTest { + + @Test + public void nullPrefixTest() { + assertThrows(NullPointerException.class, () -> new DecimalFormat().setPositivePrefix(null)); + assertThrows(NullPointerException.class, () -> new DecimalFormat().setNegativePrefix(null)); + } + + @Test + public void nullSuffixTest() { + assertThrows(NullPointerException.class, () -> new DecimalFormat().setPositiveSuffix(null)); + assertThrows(NullPointerException.class, () -> new DecimalFormat().setNegativeSuffix(null)); + } +} diff --git a/test/jdk/java/util/Calendar/Builder/BuilderTest.java b/test/jdk/java/util/Calendar/Builder/BuilderTest.java index d74c38c067a..34fab9204ed 100644 --- a/test/jdk/java/util/Calendar/Builder/BuilderTest.java +++ b/test/jdk/java/util/Calendar/Builder/BuilderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, 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,8 +23,9 @@ /* * @test - * @bug 4745761 + * @bug 4745761 8350646 * @summary Unit test for Calendar.Builder. + * @run main BuilderTest */ import java.time.LocalDateTime; @@ -245,6 +246,11 @@ private static void testExceptions() { checkException(calb, IllegalArgumentException.class); calb = builder().setCalendarType("japanese").setWeekDate(2013, 1, MONDAY); checkException(calb, IllegalArgumentException.class); + // JDK-8350646 : Ensure IAE (instead of AIOOBE) for ERA over largest supported + calb = builder().setCalendarType("japanese").setFields(ERA, 6); + checkException(calb, IllegalArgumentException.class); + // Note that we don't check ERAs under BEFORE_MEIJI, i.e. -1, -2, ... as + // historically JapaneseImperialCalendar ignores such values when normalizing } private static Calendar.Builder builder() { diff --git a/test/jdk/java/util/Calendar/SupplementalJapaneseEraTest.java b/test/jdk/java/util/Calendar/SupplementalJapaneseEraTest.java index 010519dc89e..411fc528dce 100644 --- a/test/jdk/java/util/Calendar/SupplementalJapaneseEraTest.java +++ b/test/jdk/java/util/Calendar/SupplementalJapaneseEraTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,6 +67,22 @@ public static void main(String[] args) { } private static void testProperty() { + // JDK-8350646: Ensure that IAE is thrown for out of range era, when + // additional era is defined + try { + new Calendar.Builder() + .setCalendarType("japanese") + .setFields(ERA, JapaneseEra.values().length + 2) + .build(); + System.err.println("Out of range era should have thrown IAE"); + errors++; + } catch (Exception e) { + if (!(e instanceof IllegalArgumentException)) { + System.err.printf("Out of range era threw \"%s\" instead of IAE\n", e); + errors++; + } + } + Calendar jcal = new Calendar.Builder() .setCalendarType("japanese") .setFields(ERA, 6, YEAR, 1, DAY_OF_YEAR, 1) diff --git a/test/jdk/java/util/Calendar/SupplementalJapaneseEraTestRun.java b/test/jdk/java/util/Calendar/SupplementalJapaneseEraTestRun.java index 5383d0d1240..8eac4a97ef7 100644 --- a/test/jdk/java/util/Calendar/SupplementalJapaneseEraTestRun.java +++ b/test/jdk/java/util/Calendar/SupplementalJapaneseEraTestRun.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8048123 8054214 8173423 + * @bug 8048123 8054214 8173423 8350646 * @summary Test for jdk.calendar.japanese.supplemental.era support * @library /test/lib * @build SupplementalJapaneseEraTest diff --git a/test/jdk/javax/swing/JMenu/4213634/bug4213634.java b/test/jdk/javax/swing/JMenu/4213634/bug4213634.java index dd699b7e5bc..ad26ff2bc59 100644 --- a/test/jdk/javax/swing/JMenu/4213634/bug4213634.java +++ b/test/jdk/javax/swing/JMenu/4213634/bug4213634.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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 @@ -21,103 +21,91 @@ * questions. */ -import java.awt.AWTException; import java.awt.Robot; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.KeyEvent; -import java.lang.reflect.InvocationTargetException; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; -import javax.swing.JTextArea; import javax.swing.SwingUtilities; /* * @test * @key headful * @bug 4213634 8017187 - * @author Scott Violet * @library ../../regtesthelpers * @build Util + * @summary Verifies if Alt+mnemonic char works when + * menu & menuitem have same mnemonic char * @run main bug4213634 */ - public class bug4213634 { - private JMenu menu; - - private JFrame frame; + private static JMenu menu; + private static JFrame frame; + private static Robot robot; - public static void main(String[] args) throws Throwable { - new bug4213634(); - } + public static void main(String[] args) throws Exception { + try { + robot = new Robot(); + SwingUtilities.invokeAndWait(bug4213634::createAndShowGUI); - bug4213634() throws AWTException, InterruptedException, InvocationTargetException { - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { - createAndShowGUI(); - } - }); - - test(); + robot.waitForIdle(); + robot.delay(1000); + test(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } } - public void createAndShowGUI() { - frame = new JFrame("TEST"); + public static void createAndShowGUI() { + frame = new JFrame("bug4213634"); JMenuBar mb = new JMenuBar(); menu = mb.add(createMenu("1 - First Menu", true)); mb.add(createMenu("2 - Second Menu", false)); frame.setJMenuBar(mb); - JTextArea ta = new JTextArea("This test dedicated to Nancy and Kathleen, testers and bowlers extraordinaire\n\n\nNo exception means pass."); - frame.getContentPane().add("Center", ta); JButton button = new JButton("Test"); frame.getContentPane().add("South", button); - frame.setBounds(100, 100, 400, 400); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); frame.setVisible(true); button.requestFocusInWindow(); } - private void test() throws AWTException, InterruptedException, InvocationTargetException { - Robot robot = new Robot(); - robot.setAutoDelay(50); - robot.waitForIdle(); - + private static void test() throws Exception { Util.hitMnemonics(robot, KeyEvent.VK_1); robot.waitForIdle(); + robot.delay(100); - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { - if (!menu.isSelected()) { - throw new RuntimeException( - "Failed: Menu didn't remain posted at end of test"); - } else { - System.out.println("Test passed!"); - frame.dispose(); - } + SwingUtilities.invokeAndWait(() -> { + if (!menu.isSelected()) { + throw new RuntimeException( + "Failed: Menu didn't remain posted at end of test"); + } else { + System.out.println("Test passed!"); } }); } - private JMenu createMenu(String str, boolean bFlag) { + + private static JMenu createMenu(String str, boolean bFlag) { JMenuItem menuitem; JMenu menu = new JMenu(str); menu.setMnemonic(str.charAt(0)); - for(int i = 0; i < 10; i ++) { + for (int i = 0; i < 10; i++) { menuitem = new JMenuItem("JMenuItem" + i); - menuitem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - throw new RuntimeException( - "Failed: Mnemonic activated"); - } + menuitem.addActionListener(e -> { + throw new RuntimeException("Failed: Mnemonic activated"); }); - if(bFlag) + if (bFlag) { menuitem.setMnemonic('0' + i); + } menu.add(menuitem); } return menu; diff --git a/test/jdk/jdk/internal/platform/cgroup/CgroupV1SubsystemControllerTest.java b/test/jdk/jdk/internal/platform/cgroup/CgroupV1SubsystemControllerTest.java index a97edd581fe..3ab8b35ae0a 100644 --- a/test/jdk/jdk/internal/platform/cgroup/CgroupV1SubsystemControllerTest.java +++ b/test/jdk/jdk/internal/platform/cgroup/CgroupV1SubsystemControllerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Red Hat, Inc. + * Copyright (c) 2022, 2025, Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,6 +64,9 @@ public void testCgPathNonEmptyRoot() { assertEquals(expectedPath, ctrl.path()); } + /* + * Less common cases: Containers + */ @Test public void testCgPathSubstring() { String root = "/foo/bar/baz"; @@ -71,8 +74,18 @@ public void testCgPathSubstring() { CgroupV1SubsystemController ctrl = new CgroupV1SubsystemController(root, mountPoint); String cgroupPath = "/foo/bar/baz/some"; ctrl.setPath(cgroupPath); - String expectedPath = mountPoint + "/some"; + String expectedPath = mountPoint; assertEquals(expectedPath, ctrl.path()); } + @Test + public void testCgPathToMovedPath() { + String root = "/system.slice/garden.service/garden/good/2f57368b-0eda-4e52-64d8-af5c"; + String mountPoint = "/sys/fs/cgroup/cpu,cpuacct"; + CgroupV1SubsystemController ctrl = new CgroupV1SubsystemController(root, mountPoint); + String cgroupPath = "/system.slice/garden.service/garden/bad/2f57368b-0eda-4e52-64d8-af5c"; + ctrl.setPath(cgroupPath); + String expectedPath = mountPoint; + assertEquals(expectedPath, ctrl.path()); + } } diff --git a/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java b/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java index ede74b5011e..8cf53c66e8a 100644 --- a/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java +++ b/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Red Hat Inc. + * Copyright (c) 2020, 2025, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,7 @@ import jdk.internal.platform.CgroupSubsystemFactory.CgroupTypeResult; import jdk.internal.platform.CgroupV1MetricsImpl; import jdk.internal.platform.cgroupv1.CgroupV1Subsystem; +import jdk.internal.platform.cgroupv1.CgroupV1SubsystemController; import jdk.internal.platform.Metrics; import jdk.test.lib.Utils; import jdk.test.lib.util.FileUtils; @@ -75,8 +76,10 @@ public class TestCgroupSubsystemFactory { private Path cgroupv1MntInfoDoubleControllers; private Path cgroupv1MntInfoDoubleControllers2; private Path cgroupv1MntInfoColonsHierarchy; + private Path cgroupv1MntInfoNonTrivialRoot; private Path cgroupv1SelfCgroup; private Path cgroupv1SelfColons; + private Path cgroupv1SelfNonTrivialRoot; private Path cgroupv2SelfCgroup; private Path cgroupv1SelfCgroupJoinCtrl; private Path cgroupv1CgroupsOnlyCPUCtrl; @@ -175,6 +178,7 @@ public class TestCgroupSubsystemFactory { "42 30 0:38 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:14 - cgroup none rw,seclabel,cpuset\n" + "43 30 0:39 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup none rw,seclabel,blkio\n" + "44 30 0:40 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:16 - cgroup none rw,seclabel,freezer\n"; + private String mntInfoNonTrivialRoot = "2207 2196 0:43 /system.slice/garden.service/garden/good/2f57368b-0eda-4e52-64d8-af5c /sys/fs/cgroup/cpu,cpuacct ro,nosuid,nodev,noexec,relatime master:25 - cgroup cgroup rw,cpu,cpuacct\n"; private String cgroupsNonZeroHierarchy = "#subsys_name hierarchy num_cgroups enabled\n" + "cpuset 9 1 1\n" + @@ -230,6 +234,7 @@ public class TestCgroupSubsystemFactory { "2:cpu,cpuacct:/\n" + "1:name=systemd:/user.slice/user-1000.slice/user@1000.service/apps.slice/apps-org.gnome.Terminal.slice/vte-spawn-3c00b338-5b65-439f-8e97-135e183d135d.scope\n" + "0::/user.slice/user-1000.slice/user@1000.service/apps.slice/apps-org.gnome.Terminal.slice/vte-spawn-3c00b338-5b65-439f-8e97-135e183d135d.scope\n"; + private String cgroupv1SelfNTRoot = "11:cpu,cpuacct:/system.slice/garden.service/garden/bad/2f57368b-0eda-4e52-64d8-af5c\n"; private String cgroupv2SelfCgroupContent = "0::/user.slice/user-1000.slice/session-2.scope"; // We have a mix of V1 and V2 controllers, but none of the V1 controllers @@ -294,12 +299,18 @@ public void setup() { cgroupv1MntInfoColonsHierarchy = Paths.get(existingDirectory.toString(), "mountinfo_colons"); Files.writeString(cgroupv1MntInfoColonsHierarchy, mntInfoColons); + cgroupv1MntInfoNonTrivialRoot = Paths.get(existingDirectory.toString(), "mountinfo_nt_root"); + Files.writeString(cgroupv1MntInfoNonTrivialRoot, mntInfoNonTrivialRoot); + cgroupv1SelfCgroup = Paths.get(existingDirectory.toString(), "self_cgroup_cgv1"); Files.writeString(cgroupv1SelfCgroup, cgroupv1SelfCgroupContent); cgroupv1SelfColons = Paths.get(existingDirectory.toString(), "self_colons_cgv1"); Files.writeString(cgroupv1SelfColons, cgroupv1SelfColonsContent); + cgroupv1SelfNonTrivialRoot = Paths.get(existingDirectory.toString(), "self_nt_root_cgv1"); + Files.writeString(cgroupv1SelfNonTrivialRoot, cgroupv1SelfNTRoot); + cgroupv2SelfCgroup = Paths.get(existingDirectory.toString(), "self_cgroup_cgv2"); Files.writeString(cgroupv2SelfCgroup, cgroupv2SelfCgroupContent); @@ -449,6 +460,27 @@ public void testColonsCgroupsV1() throws IOException { assertEquals(memoryInfo.getMountRoot(), memoryInfo.getCgroupPath()); } + @Test + public void testMountPrefixCgroupsV1() throws IOException { + String cgroups = cgroupv1CgInfoNonZeroHierarchy.toString(); + String mountInfo = cgroupv1MntInfoNonTrivialRoot.toString(); + String selfCgroup = cgroupv1SelfNonTrivialRoot.toString(); + Optional<CgroupTypeResult> result = CgroupSubsystemFactory.determineType(mountInfo, cgroups, selfCgroup); + + assertTrue("Expected non-empty cgroup result", result.isPresent()); + CgroupTypeResult res = result.get(); + CgroupInfo cpuInfo = res.getInfos().get("cpu"); + assertEquals(cpuInfo.getCgroupPath(), "/system.slice/garden.service/garden/bad/2f57368b-0eda-4e52-64d8-af5c"); + String expectedMountPoint = "/sys/fs/cgroup/cpu,cpuacct"; + assertEquals(expectedMountPoint, cpuInfo.getMountPoint()); + CgroupV1SubsystemController cgroupv1MemoryController = new CgroupV1SubsystemController(cpuInfo.getMountRoot(), cpuInfo.getMountPoint()); + cgroupv1MemoryController.setPath(cpuInfo.getCgroupPath()); + String actualPath = cgroupv1MemoryController.path(); + assertNotNull(actualPath); + String expectedPath = expectedMountPoint; + assertEquals("Should be equal to the mount point path", expectedPath, actualPath); + } + @Test public void testZeroHierarchyCgroupsV1() throws IOException { String cgroups = cgroupv1CgInfoZeroHierarchy.toString(); diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java new file mode 100644 index 00000000000..2ac79c173ef --- /dev/null +++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025, BELLSOFT. 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. + */ + +import jdk.internal.platform.Metrics; +import jdk.test.lib.Utils; +import jdk.test.lib.containers.docker.Common; +import jdk.test.lib.containers.docker.DockerfileConfig; +import jdk.test.lib.containers.docker.DockerRunOptions; +import jdk.test.lib.containers.docker.DockerTestUtils; + +import java.util.ArrayList; + +import jtreg.SkippedException; + +/* + * @test + * @bug 8343191 + * @key cgroups + * @summary Cgroup v1 subsystem fails to set subsystem path + * @requires container.support + * @library /test/lib + * @modules java.base/jdk.internal.platform + * @build MetricsMemoryTester + * @run main TestDockerMemoryMetricsSubgroup + */ + +public class TestDockerMemoryMetricsSubgroup { + private static final String imageName = + DockerfileConfig.getBaseImageName() + ":" + + DockerfileConfig.getBaseImageVersion(); + + public static void main(String[] args) throws Exception { + Metrics metrics = Metrics.systemMetrics(); + if (metrics == null) { + System.out.println("Cgroup not configured."); + return; + } + if (!DockerTestUtils.canTestDocker()) { + System.out.println("Unable to run docker tests."); + return; + } + if ("cgroupv1".equals(metrics.getProvider())) { + testMemoryLimitSubgroupV1("200m", "400m", false); + testMemoryLimitSubgroupV1("500m", "1G", false); + testMemoryLimitSubgroupV1("200m", "400m", true); + testMemoryLimitSubgroupV1("500m", "1G", true); + } else if ("cgroupv2".equals(metrics.getProvider())) { + testMemoryLimitSubgroupV2("200m", "400m", false); + testMemoryLimitSubgroupV2("500m", "1G", false); + testMemoryLimitSubgroupV2("200m", "400m", true); + testMemoryLimitSubgroupV2("500m", "1G", true); + } else { + throw new SkippedException("Metrics are from neither cgroup v1 nor v2, skipped for now."); + } + } + + private static void testMemoryLimitSubgroupV1(String innerSize, String outerGroupMemorySize, boolean privateNamespace) throws Exception { + Common.logNewTestCase("testMemoryLimitSubgroup, innerSize = " + innerSize); + DockerRunOptions opts = + new DockerRunOptions(imageName, "sh", "-c"); + opts.javaOpts = new ArrayList<>(); + opts.appendTestJavaOptions = false; + opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/") + .addDockerOpts("--volume", Utils.TEST_JDK + ":/jdk") + .addDockerOpts("--privileged") + .addDockerOpts("--cgroupns=" + (privateNamespace ? "private" : "host")) + .addDockerOpts("--memory", outerGroupMemorySize); + opts.addClassOptions("mkdir -p /sys/fs/cgroup/memory/test ; " + + "echo " + innerSize + " > /sys/fs/cgroup/memory/test/memory.limit_in_bytes ; " + + "echo $$ > /sys/fs/cgroup/memory/test/cgroup.procs ; " + + "/jdk/bin/java -cp /test-classes/ " + + "--add-exports java.base/jdk.internal.platform=ALL-UNNAMED " + + "MetricsMemoryTester memory " + innerSize); + + DockerTestUtils.dockerRunJava(opts).shouldHaveExitValue(0).shouldContain("TEST PASSED!!!"); + } + + private static void testMemoryLimitSubgroupV2(String innerSize, String outerGroupMemorySize, boolean privateNamespace) throws Exception { + Common.logNewTestCase("testMemoryLimitSubgroup, innerSize = " + innerSize); + DockerRunOptions opts = + new DockerRunOptions(imageName, "sh", "-c"); + opts.javaOpts = new ArrayList<>(); + opts.appendTestJavaOptions = false; + opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/") + .addDockerOpts("--volume", Utils.TEST_JDK + ":/jdk") + .addDockerOpts("--privileged") + .addDockerOpts("--cgroupns=" + (privateNamespace ? "private" : "host")) + .addDockerOpts("--memory", outerGroupMemorySize); + opts.addClassOptions("mkdir -p /sys/fs/cgroup/memory/test ; " + + "echo $$ > /sys/fs/cgroup/memory/test/cgroup.procs ; " + + "echo '+memory' > /sys/fs/cgroup/cgroup.subtree_control ; " + + "echo '+memory' > /sys/fs/cgroup/memory/cgroup.subtree_control ; " + + "echo " + innerSize + " > /sys/fs/cgroup/memory/test/memory.max ; " + + "/jdk/bin/java -cp /test-classes/ " + + "--add-exports java.base/jdk.internal.platform=ALL-UNNAMED " + + "MetricsMemoryTester memory " + innerSize); + + DockerTestUtils.dockerRunJava(opts).shouldHaveExitValue(0).shouldContain("TEST PASSED!!!"); + } +} diff --git a/test/jdk/jdk/jfr/event/gc/collection/TestSystemGC.java b/test/jdk/jdk/jfr/event/gc/collection/TestSystemGC.java index c22670e4528..f36a48686ee 100644 --- a/test/jdk/jdk/jfr/event/gc/collection/TestSystemGC.java +++ b/test/jdk/jdk/jfr/event/gc/collection/TestSystemGC.java @@ -66,12 +66,12 @@ public static void main(String[] args) throws Exception { RecordedEvent event2 = events.get(1); Events.assertFrame(event2, Runtime.class, "gc"); Events.assertEventThread(event2, Thread.currentThread()); - Events.assertField(event1, "invokedConcurrent").isEqual(concurrent); + Events.assertField(event2, "invokedConcurrent").isEqual(concurrent); RecordedEvent event3 = events.get(2); // MemoryMXBean.class is an interface so can't assertFrame on it Events.assertEventThread(event3, Thread.currentThread()); - Events.assertField(event1, "invokedConcurrent").isEqual(concurrent); + Events.assertField(event3, "invokedConcurrent").isEqual(concurrent); } } } diff --git a/test/jdk/sun/security/krb5/MicroTime.java b/test/jdk/sun/security/krb5/MicroTime.java index 8b6b9232415..84a88cedf83 100644 --- a/test/jdk/sun/security/krb5/MicroTime.java +++ b/test/jdk/sun/security/krb5/MicroTime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,9 +44,10 @@ public static void main(String[] args) throws Exception { count++; } } - // We believe a nice KerberosTime can at least tell the - // difference of 100 musec. - if (count < 10000) { + // Before JDK-6882687, KerberosTime was measured in milliseconds. + // Now it's in microseconds. We should be able to record more than + // 1000 distinct KerberosTime values within one second. + if (count < 1001) { throw new Exception("What? only " + (1000000/count) + " musec precision?"); } diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java new file mode 100644 index 00000000000..433db6fc6f6 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java @@ -0,0 +1,894 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jpackage.test; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; +import jdk.jpackage.internal.util.function.ThrowingBiConsumer; +import jdk.jpackage.internal.util.function.ThrowingConsumer; +import jdk.jpackage.internal.util.function.ThrowingRunnable; +import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.Annotations.ParameterSupplier; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.PackageTest.PackageHandlers; +import jdk.jpackage.test.RunnablePackageTest.Action; + +public class PackageTestTest extends JUnitAdapter { + + private interface Verifiable { + void verify(); + } + + private static class CallbackFactory { + + CallbackFactory(int tickCount) { + this.tickCount = tickCount; + } + + CountingInstaller createInstaller(int exitCode) { + return new CountingInstaller(tickCount, exitCode); + } + + CountingConsumer createUninstaller() { + return new CountingConsumer(tickCount, "uninstall"); + } + + CountingUnpacker createUnpacker() { + return new CountingUnpacker(tickCount); + } + + CountingConsumer createInitializer() { + return new CountingConsumer(tickCount, "init"); + } + + CountingRunnable createRunOnceInitializer() { + return new CountingRunnable(tickCount, "once-init"); + } + + CountingConsumer createInstallVerifier() { + return new CountingConsumer(tickCount, "on-install"); + } + + CountingConsumer createUninstallVerifier() { + return new CountingConsumer(tickCount, "on-uninstall"); + } + + CountingConsumer createBundleVerifier() { + return new CountingConsumer(tickCount, "on-bundle"); + } + + CountingBundleVerifier createBundleVerifier(int jpackageExitCode) { + return new CountingBundleVerifier(tickCount, jpackageExitCode); + } + + private final int tickCount; + } + + private final static int ERROR_EXIT_CODE_JPACKAGE = 35; + private final static int ERROR_EXIT_CODE_INSTALL = 27; + + private final static CallbackFactory NEVER = new CallbackFactory(0); + private final static CallbackFactory ONCE = new CallbackFactory(1); + private final static CallbackFactory TWICE = new CallbackFactory(2); + + enum BundleVerifier { + ONCE_SUCCESS(ONCE), + ONCE_FAIL(ONCE), + NEVER(PackageTestTest.NEVER), + ONCE_SUCCESS_EXIT_CODE(ONCE, 0), + ONCE_FAIL_EXIT_CODE(ONCE, ERROR_EXIT_CODE_JPACKAGE), + NEVER_EXIT_CODE(PackageTestTest.NEVER, 0); + + BundleVerifier(CallbackFactory factory) { + specSupplier = () -> new BundleVerifierSpec(Optional.of(factory.createBundleVerifier()), Optional.empty()); + } + + BundleVerifier(CallbackFactory factory, int jpackageExitCode) { + specSupplier = () -> new BundleVerifierSpec(Optional.empty(), + Optional.of(factory.createBundleVerifier(jpackageExitCode))); + } + + BundleVerifierSpec spec() { + return specSupplier.get(); + } + + private final Supplier<BundleVerifierSpec> specSupplier; + } + + private static class TickCounter implements Verifiable { + + TickCounter(int expectedTicks) { + this.expectedTicks = expectedTicks; + } + + void tick() { + ticks++; + } + + @Override + public void verify() { + switch (expectedTicks) { + case 0 -> { + TKit.assertEquals(expectedTicks, ticks, String.format("%s: never called", this)); + } + case 1 -> { + TKit.assertEquals(expectedTicks, ticks, String.format("%s: called once", this)); + } + case 2 -> { + TKit.assertEquals(expectedTicks, ticks, String.format("%s: called twice", this)); + } + default -> { + TKit.assertEquals(expectedTicks, ticks, toString()); + } + } + } + + protected int tickCount() { + return ticks; + } + + protected static String getDescription(TickCounter o) { + return "tk=" + o.expectedTicks; + } + + private int ticks; + protected final int expectedTicks; + } + + private static class CountingConsumer extends TickCounter implements ThrowingConsumer<JPackageCommand> { + + @Override + public void accept(JPackageCommand cmd) { + tick(); + } + + @Override + public String toString() { + return String.format("%s(%s)", label, TickCounter.getDescription(this)); + } + + CountingConsumer(int expectedTicks, String label) { + super(expectedTicks); + this.label = Objects.requireNonNull(label); + } + + private final String label; + } + + private static class CountingRunnable extends TickCounter implements ThrowingRunnable { + + @Override + public void run() { + tick(); + } + + @Override + public String toString() { + return String.format("%s(%s)", label, TickCounter.getDescription(this)); + } + + CountingRunnable(int expectedTicks, String label) { + super(expectedTicks); + this.label = Objects.requireNonNull(label); + } + + private final String label; + } + + private static class CountingBundleVerifier extends TickCounter implements ThrowingBiConsumer<JPackageCommand, Executor.Result> { + + @Override + public void accept(JPackageCommand cmd, Executor.Result result) { + tick(); + jpackageExitCode = result.exitCode(); + } + + @Override + public void verify() { + super.verify(); + if (expectedTicks > 0) { + TKit.assertEquals(expectedJPackageExitCode, jpackageExitCode, String.format("%s: run jpackage", this)); + } + } + + @Override + public String toString() { + return String.format("on-bundle-ex(exit=%d, %s)", expectedJPackageExitCode, TickCounter.getDescription(this)); + } + + CountingBundleVerifier(int expectedTicks, int expectedJPackageExitCode) { + super(expectedTicks); + this.expectedJPackageExitCode = expectedJPackageExitCode; + } + + private int jpackageExitCode; + private final int expectedJPackageExitCode; + } + + private final static class CountingInstaller extends TickCounter implements Function<JPackageCommand, Integer> { + + @Override + public Integer apply(JPackageCommand cmd) { + tick(); + return exitCode; + } + + @Override + public String toString() { + return String.format("install(exit=%d, %s)", exitCode, TickCounter.getDescription(this)); + } + + CountingInstaller(int expectedTicks, int exitCode) { + super(expectedTicks); + this.exitCode = exitCode; + } + + private final int exitCode; + } + + private static class CountingUnpacker extends TickCounter implements BiFunction<JPackageCommand, Path, Path> { + + @Override + public Path apply(JPackageCommand cmd, Path path) { + tick(); + try { + Files.createDirectories(path.resolve("mockup-installdir")); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + unpackPaths.add(path); + return path; + } + + @Override + public String toString() { + return String.format("unpack(%s)", TickCounter.getDescription(this)); + } + + CountingUnpacker(int expectedTicks) { + super(expectedTicks); + } + + List<Path> unpackPaths() { + return unpackPaths; + } + + private final List<Path> unpackPaths = new ArrayList<>(); + } + + record BundleVerifierSpec(Optional<CountingConsumer> verifier, Optional<CountingBundleVerifier> verifierWithExitCode) { + BundleVerifierSpec { + if (verifier.isPresent() == verifierWithExitCode.isPresent()) { + throw new IllegalArgumentException(); + } + } + + Verifiable apply(PackageTest test) { + verifier.ifPresent(test::addBundleVerifier); + verifierWithExitCode.ifPresent(test::addBundleVerifier); + return verifier.map(Verifiable.class::cast).orElseGet(verifierWithExitCode::orElseThrow); + } + + @Override + public String toString() { + return verifier.map(Verifiable.class::cast).orElseGet(verifierWithExitCode::orElseThrow).toString(); + } + } + + record PackageHandlersSpec(CountingInstaller installer, CountingConsumer uninstaller, + Optional<CountingUnpacker> unpacker, int installExitCode) { + + PackageHandlers createPackageHandlers(Consumer<Verifiable> verifiableAccumulator) { + List.of(installer, uninstaller).forEach(verifiableAccumulator::accept); + unpacker.ifPresent(verifiableAccumulator::accept); + return new PackageHandlers(installer, uninstaller::accept, unpacker); + } + } + + record TestSpec(PackageType type, PackageHandlersSpec handlersSpec, + List<CountingConsumer> initializers, List<BundleVerifierSpec> bundleVerifierSpecs, + List<CountingConsumer> installVerifiers, List<CountingConsumer> uninstallVerifiers, + int expectedJPackageExitCode, int actualJPackageExitCode, List<Action> actions) { + + PackageTest createTest(Consumer<Verifiable> verifiableAccumulator) { + return createTest(handlersSpec.createPackageHandlers(verifiableAccumulator)); + } + + PackageTest createTest(PackageHandlers handlers) { + return new PackageTest().jpackageFactory(() -> { + return new JPackageCommand() { + @Override + public Path outputBundle() { + return outputDir().resolve("mockup-bundle" + super.packageType().getSuffix()); + } + + @Override + public PackageType packageType() { + return null; + } + + @Override + JPackageCommand assertAppLayout() { + return this; + } + + @Override + JPackageCommand createImmutableCopy() { + return this; + } + + @Override + public void verifyIsOfType(PackageType ... types) { + } + + @Override + public String getPrintableCommandLine() { + return "'mockup jpackage'"; + } + + @Override + public Executor.Result execute(int expectedExitCode) { + final var outputBundle = outputBundle(); + try { + Files.createDirectories(outputBundle.getParent()); + if (actualJPackageExitCode == 0) { + Files.createFile(outputBundle); + } + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + return new Executor.Result(actualJPackageExitCode, null, + this::getPrintableCommandLine).assertExitCodeIs(expectedExitCode); + } + }; + }).setExpectedExitCode(expectedJPackageExitCode) + .setExpectedInstallExitCode(handlersSpec.installExitCode) + .isPackageTypeSupported(type -> true) + .forTypes().packageHandlers(handlers); + } + + void configureInitializers(PackageTest test, Consumer<Verifiable> verifiableAccumulator) { + for (final var initializer : initializers) { + verifiableAccumulator.accept(initializer); + test.addInitializer(initializer); + } + } + + void configureBundleVerifiers(PackageTest test, Consumer<Verifiable> verifiableAccumulator) { + for (final var verifierSpec : bundleVerifierSpecs) { + verifiableAccumulator.accept(verifierSpec.apply(test)); + } + } + + void configureInstallVerifiers(PackageTest test, Consumer<Verifiable> verifiableAccumulator) { + for (final var verifier : installVerifiers) { + verifiableAccumulator.accept(verifier); + test.addInstallVerifier(verifier); + } + } + + void configureUninstallVerifiers(PackageTest test, Consumer<Verifiable> verifiableAccumulator) { + for (final var verifier : uninstallVerifiers) { + verifiableAccumulator.accept(verifier); + test.addUninstallVerifier(verifier); + } + } + + void run(PackageTest test) { + final boolean expectedSuccess = (expectedJPackageExitCode == actualJPackageExitCode); + + TKit.assertAssert(expectedSuccess, () -> { + test.run(actions.toArray(Action[]::new)); + }); + } + + List<Verifiable> run() { + return run(Optional.empty()); + } + + List<Verifiable> run(Consumer<PackageTest> customConfigure) { + return run(Optional.of(customConfigure)); + } + + private List<Verifiable> run(Optional<Consumer<PackageTest>> customConfigure) { + final List<Verifiable> verifiers = new ArrayList<>(); + + final var test = createTest(verifiers::add); + test.forTypes(type); + configureInitializers(test, verifiers::add); + configureBundleVerifiers(test, verifiers::add); + configureInstallVerifiers(test, verifiers::add); + configureUninstallVerifiers(test, verifiers::add); + customConfigure.ifPresent(callback -> callback.accept(test)); + run(test); + verifiers.forEach(Verifiable::verify); + return verifiers; + } + } + + private final static class TestSpecBuilder { + + TestSpecBuilder type(PackageType v) { + type = Objects.requireNonNull(v); + return this; + } + + TestSpecBuilder install(CallbackFactory v) { + install = Objects.requireNonNull(v); + return this; + } + + TestSpecBuilder uninstall(CallbackFactory v) { + uninstall = Objects.requireNonNull(v); + return this; + } + + TestSpecBuilder unpack(CallbackFactory v) { + unpack = v; + return this; + } + + TestSpecBuilder installExitCode(int v) { + installExitCode = v; + return this; + } + + TestSpecBuilder jpackageExitCode(int v) { + return expectedJPackageExitCode(v).actualJPackageExitCode(v); + } + + TestSpecBuilder expectedJPackageExitCode(int v) { + expectedJPackageExitCode = v; + return this; + } + + TestSpecBuilder actualJPackageExitCode(int v) { + actualJPackageExitCode = v; + return this; + } + + TestSpecBuilder addActions(Action... v) { + actions.addAll(List.of(v)); + return this; + } + + TestSpecBuilder actions(Action... v) { + actions.clear(); + return addActions(v); + } + + TestSpecBuilder doCreateAndUnpack() { + actions(Action.CREATE_AND_UNPACK); + install(NEVER); + uninstall(NEVER); + if (willHaveBundle()) { + overrideNonNullUnpack(ONCE); + } else { + overrideNonNullUnpack(NEVER); + } + initializers(ONCE); + if (expectedJPackageExitCode != actualJPackageExitCode) { + bundleVerifiers(BundleVerifier.NEVER.spec()); + } else if (expectedJPackageExitCode == 0) { + bundleVerifiers(BundleVerifier.ONCE_SUCCESS.spec()); + bundleVerifiers(BundleVerifier.ONCE_SUCCESS_EXIT_CODE.spec()); + } else { + bundleVerifiers(BundleVerifier.ONCE_FAIL.spec()); + if (expectedJPackageExitCode == ERROR_EXIT_CODE_JPACKAGE) { + bundleVerifiers(BundleVerifier.ONCE_FAIL_EXIT_CODE.spec()); + } + } + uninstallVerifiers(NEVER); + if (willVerifyUnpack()) { + installVerifiers(ONCE); + } else { + installVerifiers(NEVER); + } + return this; + } + + TestSpecBuilder doCreateUnpackInstallUninstall() { + actions(Action.CREATE, Action.UNPACK, Action.VERIFY_INSTALL, Action.INSTALL, + Action.VERIFY_INSTALL, Action.UNINSTALL, Action.VERIFY_UNINSTALL); + initializers(ONCE); + uninstallVerifiers(NEVER); + if (willHaveBundle()) { + overrideNonNullUnpack(ONCE); + install(ONCE); + if (installExitCode == 0) { + uninstall(ONCE); + uninstallVerifiers(ONCE); + } else { + uninstall(NEVER); + } + } else { + overrideNonNullUnpack(NEVER); + install(NEVER); + uninstall(NEVER); + } + + if (expectedJPackageExitCode != actualJPackageExitCode) { + bundleVerifiers(BundleVerifier.NEVER.spec()); + installVerifiers(NEVER); + } else if (expectedJPackageExitCode == 0) { + bundleVerifiers(BundleVerifier.ONCE_SUCCESS.spec()); + bundleVerifiers(BundleVerifier.ONCE_SUCCESS_EXIT_CODE.spec()); + if (installExitCode == 0) { + if (willVerifyUnpack()) { + installVerifiers(TWICE); + } else { + installVerifiers(ONCE); + } + } else { + if (willVerifyUnpack()) { + installVerifiers(ONCE); + } else { + installVerifiers(NEVER); + } + } + } else { + bundleVerifiers(BundleVerifier.ONCE_FAIL.spec()); + if (expectedJPackageExitCode == ERROR_EXIT_CODE_JPACKAGE) { + bundleVerifiers(BundleVerifier.ONCE_FAIL_EXIT_CODE.spec()); + } + installVerifiers(NEVER); + } + return this; + } + + TestSpecBuilder addInitializers(CallbackFactory... v) { + initializers.addAll(List.of(v)); + return this; + } + + TestSpecBuilder addBundleVerifiers(BundleVerifierSpec... v) { + bundleVerifiers.addAll(List.of(v)); + return this; + } + + TestSpecBuilder addInstallVerifiers(CallbackFactory... v) { + installVerifiers.addAll(List.of(v)); + return this; + } + + TestSpecBuilder addUninstallVerifiers(CallbackFactory... v) { + uninstallVerifiers.addAll(List.of(v)); + return this; + } + + TestSpecBuilder initializers(CallbackFactory... v) { + initializers.clear(); + return addInitializers(v); + } + + TestSpecBuilder bundleVerifiers(BundleVerifierSpec... v) { + bundleVerifiers.clear(); + return addBundleVerifiers(v); + } + + TestSpecBuilder installVerifiers(CallbackFactory... v) { + installVerifiers.clear(); + return addInstallVerifiers(v); + } + + TestSpecBuilder uninstallVerifiers(CallbackFactory... v) { + uninstallVerifiers.clear(); + return addUninstallVerifiers(v); + } + + TestSpec create() { + final var handlersSpec = new PackageHandlersSpec( + install.createInstaller(installExitCode), uninstall.createUninstaller(), + Optional.ofNullable(unpack).map(CallbackFactory::createUnpacker), installExitCode); + return new TestSpec(type, handlersSpec, + initializers.stream().map(CallbackFactory::createInitializer).toList(), + bundleVerifiers, + installVerifiers.stream().map(CallbackFactory::createInstallVerifier).toList(), + uninstallVerifiers.stream().map(CallbackFactory::createUninstallVerifier).toList(), + expectedJPackageExitCode, + actualJPackageExitCode, actions); + } + + boolean willVerifyCreate() { + return actions.contains(Action.CREATE) && actualJPackageExitCode == 0 && expectedJPackageExitCode == actualJPackageExitCode; + } + + boolean willHaveBundle() { + return !actions.contains(Action.CREATE) || willVerifyCreate(); + } + + boolean willVerifyUnpack() { + return actions.contains(Action.UNPACK) && willHaveBundle() && unpack != null; + } + + boolean willVerifyInstall() { + return (actions.contains(Action.INSTALL) && installExitCode == 0) && willHaveBundle(); + } + + private void overrideNonNullUnpack(CallbackFactory v) { + if (unpack != null) { + unpack(v); + } + } + + private PackageType type = PackageType.LINUX_RPM; + private CallbackFactory install = NEVER; + private CallbackFactory uninstall = NEVER; + private CallbackFactory unpack = NEVER; + private int installExitCode; + private final List<CallbackFactory> initializers = new ArrayList<>(); + private final List<BundleVerifierSpec> bundleVerifiers = new ArrayList<>(); + private final List<CallbackFactory> installVerifiers = new ArrayList<>(); + private final List<CallbackFactory> uninstallVerifiers = new ArrayList<>(); + private int expectedJPackageExitCode; + private int actualJPackageExitCode; + private final List<Action> actions = new ArrayList<>(); + } + + @Test + @ParameterSupplier + public void test(TestSpec spec) { + spec.run(); + } + + public static List<Object[]> test() { + List<TestSpec> data = new ArrayList<>(); + + for (boolean withUnpack : List.of(false, true)) { + for (int actualJPackageExitCode : List.of(0, 1, ERROR_EXIT_CODE_INSTALL)) { + for (int expectedJPackageExitCode : List.of(0, 1, ERROR_EXIT_CODE_INSTALL)) { + data.add(new TestSpecBuilder() + .unpack(withUnpack ? ONCE : null) + .actualJPackageExitCode(actualJPackageExitCode) + .expectedJPackageExitCode(expectedJPackageExitCode) + .doCreateAndUnpack().create()); + } + } + } + + for (boolean withUnpack : List.of(false, true)) { + for (int installExitCode : List.of(0, 1, ERROR_EXIT_CODE_INSTALL)) { + for (int actualJPackageExitCode : List.of(0, 1, ERROR_EXIT_CODE_JPACKAGE)) { + for (int expectedJPackageExitCode : List.of(0, 1, ERROR_EXIT_CODE_JPACKAGE)) { + data.add(new TestSpecBuilder() + .unpack(withUnpack ? ONCE : null) + .installExitCode(installExitCode) + .actualJPackageExitCode(actualJPackageExitCode) + .expectedJPackageExitCode(expectedJPackageExitCode) + .doCreateUnpackInstallUninstall().create()); + } + } + } + } + + data.add(new TestSpecBuilder() + .actions(Action.VERIFY_INSTALL, Action.UNINSTALL, Action.VERIFY_INSTALL, Action.VERIFY_UNINSTALL) + .uninstall(ONCE) + .initializers(ONCE) + .bundleVerifiers(BundleVerifier.NEVER.spec()) + .installVerifiers(TWICE) + .uninstallVerifiers(ONCE) + .create()); + + return data.stream().map(v -> { + return new Object[] {v}; + }).toList(); + } + + @Test + @ParameterSupplier + public void testDisableInstallerUninstaller(TestSpec spec, boolean disableInstaller, boolean disableUninstaller) { + spec.run(test -> { + if (disableInstaller) { + test.disablePackageInstaller(); + } + if (disableUninstaller) { + test.disablePackageUninstaller(); + } + }); + } + + public static List<Object[]> testDisableInstallerUninstaller() { + List<Object[]> data = new ArrayList<>(); + + for (boolean disableInstaller : List.of(true, false)) { + for (boolean disableUninstaller : List.of(true, false)) { + if (disableInstaller || disableUninstaller) { + final var builder = new TestSpecBuilder().doCreateUnpackInstallUninstall(); + if (disableInstaller) { + builder.install(NEVER); + } + if (disableUninstaller) { + builder.uninstall(NEVER); + } + data.add(new Object[] { builder.create(), disableInstaller, disableUninstaller }); + } + } + } + + return data; + } + + private static List<Path> getUnpackPaths(Collection<Verifiable> verifiers) { + return verifiers.stream() + .filter(CountingUnpacker.class::isInstance) + .map(CountingUnpacker.class::cast) + .map(CountingUnpacker::unpackPaths) + .reduce((x , y) -> { + throw new UnsupportedOperationException(); + }).orElseThrow(); + } + + @Test + public void testUnpackTwice() { + final var testSpec = new TestSpecBuilder() + .actions(Action.CREATE, Action.UNPACK, Action.VERIFY_INSTALL, Action.UNPACK, Action.VERIFY_INSTALL) + .unpack(TWICE) + .initializers(ONCE) + .installVerifiers(TWICE) + .create(); + + final var unpackPaths = getUnpackPaths(testSpec.run()); + + TKit.assertEquals(2, unpackPaths.size(), "Check the bundle was unpacked in different directories"); + + unpackPaths.forEach(dir -> { + TKit.assertTrue(dir.startsWith(TKit.workDir()), "Check unpack directory is inside of the test work directory"); + }); + } + + @Test + public void testDeleteUnpackDirs() { + final int unpackActionCount = 4; + final var testSpec = new TestSpecBuilder() + .actions(Action.UNPACK, Action.UNPACK, Action.UNPACK, Action.UNPACK) + .unpack(new CallbackFactory(unpackActionCount) { + @Override + CountingUnpacker createUnpacker() { + return new CountingUnpacker(unpackActionCount) { + @Override + public Path apply(JPackageCommand cmd, Path path) { + switch (tickCount()) { + case 0 -> { + } + + case 2 -> { + path = path.resolve("foo"); + } + + case 1, 3 -> { + try { + path = Files.createTempDirectory("jpackage-test"); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + + default -> { + throw new IllegalStateException(); + } + } + return super.apply(cmd, path); + } + }; + } + }) + .initializers(ONCE) + .create(); + + final var unpackPaths = getUnpackPaths(testSpec.run()); + + TKit.assertEquals(unpackActionCount, unpackPaths.size(), "Check the bundle was unpacked in different directories"); + + // Unpack directories within the test work directory must exist. + TKit.assertDirectoryExists(unpackPaths.get(0)); + TKit.assertDirectoryExists(unpackPaths.get(2)); + + // Unpack directories outside of the test work directory must be deleted. + TKit.assertPathExists(unpackPaths.get(1), false); + TKit.assertPathExists(unpackPaths.get(3), false); + } + + @Test + public void testRunOnceInitializer() { + final var testSpec = new TestSpecBuilder().doCreateAndUnpack().unpack(TWICE).create(); + + final var initializer = TWICE.createInitializer(); + final var runOnceInitializer = ONCE.createRunOnceInitializer(); + testSpec.run(test -> { + test.forTypes(PackageType.LINUX_RPM, PackageType.WIN_MSI) + .addRunOnceInitializer(runOnceInitializer) + .addInitializer(initializer); + }); + + initializer.verify(); + runOnceInitializer.verify(); + } + + @Test + @Parameter("0") + @Parameter("1") + public void testPurge(int jpackageExitCode) { + + Path[] outputBundle = new Path[1]; + + final var builder = new TestSpecBuilder(); + + builder.actions(Action.CREATE).initializers(new CallbackFactory(1) { + @Override + CountingConsumer createInitializer() { + return new CountingConsumer(1, "custom-init") { + @Override + public void accept(JPackageCommand cmd) { + outputBundle[0] = cmd.outputBundle(); + super.accept(cmd); + } + }; + } + }).create().run(); + TKit.assertFileExists(outputBundle[0]); + + builder.actions(Action.PURGE).initializers(ONCE).jpackageExitCode(jpackageExitCode).create().run(); + TKit.assertPathExists(outputBundle[0], false); + } + + @Test + public void testPackageTestOrder() { + + Set<PackageType> packageTypes = new LinkedHashSet<>(); + + final var initializer = new CountingConsumer(PackageType.NATIVE.size(), "custom-init") { + @Override + public void accept(JPackageCommand cmd) { + packageTypes.add(new JPackageCommand().setArgumentValue( + "--type", cmd.getArgumentValue("--type")).packageType()); + super.accept(cmd); + } + }; + + new TestSpecBuilder().actions(Action.CREATE).create().run(test -> { + test.forTypes().addInitializer(initializer); + }); + + initializer.verify(); + + final var expectedOrder = PackageType.NATIVE.stream() + .sorted().map(PackageType::name).toList(); + final var actualOrder = packageTypes.stream().map(PackageType::name).toList(); + + TKit.assertStringListEquals(expectedOrder, actualOrder, "Check the order or packaging"); + } +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java index 6fc5cfad3f9..efcd0041579 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -25,6 +25,7 @@ import java.io.FileOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.security.SecureRandom; @@ -71,11 +72,13 @@ public JPackageCommand(JPackageCommand cmd) { ignoreDefaultRuntime = cmd.ignoreDefaultRuntime; ignoreDefaultVerbose = cmd.ignoreDefaultVerbose; immutable = cmd.immutable; + dmgInstallDir = cmd.dmgInstallDir; prerequisiteActions = new Actions(cmd.prerequisiteActions); verifyActions = new Actions(cmd.verifyActions); appLayoutAsserts = cmd.appLayoutAsserts; outputValidator = cmd.outputValidator; executeInDirectory = cmd.executeInDirectory; + winMsiLogFile = cmd.winMsiLogFile; } JPackageCommand createImmutableCopy() { @@ -497,7 +500,11 @@ public Path appInstallationDirectory() { } if (TKit.isOSX()) { - return MacHelper.getInstallationDirectory(this); + if (packageType() == PackageType.MAC_DMG && dmgInstallDir != null) { + return dmgInstallDir; + } else { + return MacHelper.getInstallationDirectory(this); + } } throw TKit.throwUnknownPlatformError(); @@ -868,6 +875,7 @@ private static JPackageCommand convertFromRuntime(JPackageCommand cmd) { var copy = new JPackageCommand(cmd); copy.immutable = false; copy.removeArgumentWithValue("--runtime-image"); + copy.dmgInstallDir = cmd.appInstallationDirectory(); return copy; } @@ -992,6 +1000,22 @@ JPackageCommand setUnpackedPackageLocation(Path path) { return this; } + JPackageCommand winMsiLogFile(Path v) { + this.winMsiLogFile = v; + return this; + } + + public Optional<Path> winMsiLogFile() { + return Optional.ofNullable(winMsiLogFile); + } + + public Optional<Stream<String>> winMsiLogFileContents() { + return winMsiLogFile().map(ThrowingFunction.toFunction(msiLog -> { + // MSI log files are UTF16LE-encoded + return Files.lines(msiLog, StandardCharsets.UTF_16LE); + })); + } + private JPackageCommand adjustArgumentsBeforeExecution() { if (!isWithToolProvider()) { // if jpackage is launched as a process then set the jlink.debug system property @@ -1165,9 +1189,11 @@ public void run() { private boolean ignoreDefaultRuntime; private boolean ignoreDefaultVerbose; private boolean immutable; + private Path dmgInstallDir; private final Actions prerequisiteActions; private final Actions verifyActions; private Path executeInDirectory; + private Path winMsiLogFile; private Set<AppLayoutAssert> appLayoutAsserts = Set.of(AppLayoutAssert.values()); private Consumer<Stream<String>> outputValidator; private static boolean defaultWithToolProvider; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java index f97b695d98f..d94b8aee8ac 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java @@ -195,58 +195,61 @@ public static String getBundleProperty(JPackageCommand cmd, } static PackageHandlers createDebPackageHandlers() { - PackageHandlers deb = new PackageHandlers(); - deb.installHandler = cmd -> { - cmd.verifyIsOfType(PackageType.LINUX_DEB); - Executor.of("sudo", "dpkg", "-i") - .addArgument(cmd.outputBundle()) - .execute(); - }; - deb.uninstallHandler = cmd -> { - cmd.verifyIsOfType(PackageType.LINUX_DEB); - var packageName = getPackageName(cmd); - String script = String.format("! dpkg -s %s || sudo dpkg -r %s", - packageName, packageName); - Executor.of("sh", "-c", script).execute(); - }; - deb.unpackHandler = (cmd, destinationDir) -> { - cmd.verifyIsOfType(PackageType.LINUX_DEB); - Executor.of("dpkg", "-x") - .addArgument(cmd.outputBundle()) - .addArgument(destinationDir) - .execute(); - return destinationDir; - }; - return deb; + return new PackageHandlers(LinuxHelper::installDeb, LinuxHelper::uninstallDeb, LinuxHelper::unpackDeb); + } + + private static int installDeb(JPackageCommand cmd) { + cmd.verifyIsOfType(PackageType.LINUX_DEB); + return Executor.of("sudo", "dpkg", "-i") + .addArgument(cmd.outputBundle()) + .execute().getExitCode(); + } + + private static void uninstallDeb(JPackageCommand cmd) { + cmd.verifyIsOfType(PackageType.LINUX_DEB); + var packageName = getPackageName(cmd); + String script = String.format("! dpkg -s %s || sudo dpkg -r %s", + packageName, packageName); + Executor.of("sh", "-c", script).execute(); + } + + private static Path unpackDeb(JPackageCommand cmd, Path destinationDir) { + cmd.verifyIsOfType(PackageType.LINUX_DEB); + Executor.of("dpkg", "-x") + .addArgument(cmd.outputBundle()) + .addArgument(destinationDir) + .execute(0); + return destinationDir; } static PackageHandlers createRpmPackageHandlers() { - PackageHandlers rpm = new PackageHandlers(); - rpm.installHandler = cmd -> { - cmd.verifyIsOfType(PackageType.LINUX_RPM); - Executor.of("sudo", "rpm", "-U") - .addArgument(cmd.outputBundle()) - .execute(); - }; - rpm.uninstallHandler = cmd -> { - cmd.verifyIsOfType(PackageType.LINUX_RPM); - var packageName = getPackageName(cmd); - String script = String.format("! rpm -q %s || sudo rpm -e %s", - packageName, packageName); - Executor.of("sh", "-c", script).execute(); - }; - rpm.unpackHandler = (cmd, destinationDir) -> { - cmd.verifyIsOfType(PackageType.LINUX_RPM); - Executor.of("sh", "-c", String.format( - "rpm2cpio '%s' | cpio -idm --quiet", - JPackageCommand.escapeAndJoin( - cmd.outputBundle().toAbsolutePath().toString()))) - .setDirectory(destinationDir) - .execute(); - return destinationDir; - }; + return new PackageHandlers(LinuxHelper::installRpm, LinuxHelper::uninstallRpm, LinuxHelper::unpackRpm); + } - return rpm; + private static int installRpm(JPackageCommand cmd) { + cmd.verifyIsOfType(PackageType.LINUX_RPM); + return Executor.of("sudo", "rpm", "-U") + .addArgument(cmd.outputBundle()) + .execute().getExitCode(); + } + + private static void uninstallRpm(JPackageCommand cmd) { + cmd.verifyIsOfType(PackageType.LINUX_RPM); + var packageName = getPackageName(cmd); + String script = String.format("! rpm -q %s || sudo rpm -e %s", + packageName, packageName); + Executor.of("sh", "-c", script).execute(); + } + + private static Path unpackRpm(JPackageCommand cmd, Path destinationDir) { + cmd.verifyIsOfType(PackageType.LINUX_RPM); + Executor.of("sh", "-c", String.format( + "rpm2cpio '%s' | cpio -idm --quiet", + JPackageCommand.escapeAndJoin( + cmd.outputBundle().toAbsolutePath().toString()))) + .setDirectory(destinationDir) + .execute(0); + return destinationDir; } static Path getLauncherPath(JPackageCommand cmd) { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java index 2256963999a..8d245fb4d96 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java @@ -22,6 +22,8 @@ */ package jdk.jpackage.test; +import static java.util.stream.Collectors.toSet; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; @@ -29,13 +31,12 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.List; import java.util.ArrayList; +import java.util.List; import java.util.Optional; import java.util.Set; import java.util.regex.Pattern; import java.util.stream.Collectors; -import static java.util.stream.Collectors.toSet; import java.util.stream.Stream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -43,13 +44,13 @@ import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; +import jdk.jpackage.internal.RetryExecutor; +import jdk.jpackage.internal.util.PathUtils; import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.internal.util.function.ThrowingSupplier; import jdk.jpackage.test.PackageTest.PackageHandlers; -import jdk.jpackage.internal.RetryExecutor; -import jdk.jpackage.internal.util.PathUtils; -import org.xml.sax.SAXException; import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; public final class MacHelper { @@ -149,113 +150,115 @@ public static PListWrapper readPList(Stream<String> lines) { } static PackageHandlers createDmgPackageHandlers() { - PackageHandlers dmg = new PackageHandlers(); + return new PackageHandlers(MacHelper::installDmg, MacHelper::uninstallDmg, MacHelper::unpackDmg); + } - dmg.installHandler = cmd -> { - withExplodedDmg(cmd, dmgImage -> { - Executor.of("sudo", "cp", "-r") - .addArgument(dmgImage) - .addArgument(getInstallationDirectory(cmd).getParent()) - .execute(); - }); - }; - dmg.unpackHandler = (cmd, destinationDir) -> { - Path unpackDir = destinationDir.resolve( - TKit.removeRootFromAbsolutePath( - getInstallationDirectory(cmd)).getParent()); - try { - Files.createDirectories(unpackDir); - } catch (IOException ex) { - throw new RuntimeException(ex); - } + private static int installDmg(JPackageCommand cmd) { + cmd.verifyIsOfType(PackageType.MAC_DMG); + withExplodedDmg(cmd, dmgImage -> { + Executor.of("sudo", "cp", "-r") + .addArgument(dmgImage) + .addArgument(getInstallationDirectory(cmd).getParent()) + .execute(0); + }); + return 0; + } - withExplodedDmg(cmd, dmgImage -> { - Executor.of("cp", "-r") - .addArgument(dmgImage) - .addArgument(unpackDir) - .execute(); - }); - return destinationDir; - }; - dmg.uninstallHandler = cmd -> { - cmd.verifyIsOfType(PackageType.MAC_DMG); - Executor.of("sudo", "rm", "-rf") - .addArgument(cmd.appInstallationDirectory()) - .execute(); - }; + private static void uninstallDmg(JPackageCommand cmd) { + cmd.verifyIsOfType(PackageType.MAC_DMG); + Executor.of("sudo", "rm", "-rf") + .addArgument(cmd.appInstallationDirectory()) + .execute(); + } + + private static Path unpackDmg(JPackageCommand cmd, Path destinationDir) { + cmd.verifyIsOfType(PackageType.MAC_DMG); + Path unpackDir = destinationDir.resolve( + TKit.removeRootFromAbsolutePath( + getInstallationDirectory(cmd)).getParent()); + try { + Files.createDirectories(unpackDir); + } catch (IOException ex) { + throw new RuntimeException(ex); + } - return dmg; + withExplodedDmg(cmd, dmgImage -> { + Executor.of("cp", "-r") + .addArgument(dmgImage) + .addArgument(unpackDir) + .execute(); + }); + return destinationDir; } static PackageHandlers createPkgPackageHandlers() { - PackageHandlers pkg = new PackageHandlers(); + return new PackageHandlers(MacHelper::installPkg, MacHelper::uninstallPkg, MacHelper::unpackPkg); + } - pkg.installHandler = cmd -> { - cmd.verifyIsOfType(PackageType.MAC_PKG); - Executor.of("sudo", "/usr/sbin/installer", "-allowUntrusted", "-pkg") - .addArgument(cmd.outputBundle()) - .addArguments("-target", "/") + private static int installPkg(JPackageCommand cmd) { + cmd.verifyIsOfType(PackageType.MAC_PKG); + return Executor.of("sudo", "/usr/sbin/installer", "-allowUntrusted", "-pkg") + .addArgument(cmd.outputBundle()) + .addArguments("-target", "/") + .execute().getExitCode(); + } + + private static void uninstallPkg(JPackageCommand cmd) { + cmd.verifyIsOfType(PackageType.MAC_PKG); + if (Files.exists(getUninstallCommand(cmd))) { + Executor.of("sudo", "/bin/sh", + getUninstallCommand(cmd).toString()).execute(); + } else { + Executor.of("sudo", "rm", "-rf") + .addArgument(cmd.appInstallationDirectory()) .execute(); - }; - pkg.unpackHandler = (cmd, destinationDir) -> { - cmd.verifyIsOfType(PackageType.MAC_PKG); + } + } - var dataDir = destinationDir.resolve("data"); + private static Path unpackPkg(JPackageCommand cmd, Path destinationDir) { + cmd.verifyIsOfType(PackageType.MAC_PKG); - Executor.of("pkgutil", "--expand") - .addArgument(cmd.outputBundle()) - .addArgument(dataDir) // We need non-existing folder - .execute(); + var dataDir = destinationDir.resolve("data"); - final Path unpackRoot = destinationDir.resolve("unpacked"); - - // Unpack all ".pkg" files from $dataDir folder in $unpackDir folder - try (var dataListing = Files.list(dataDir)) { - dataListing.filter(file -> { - return ".pkg".equals(PathUtils.getSuffix(file.getFileName())); - }).forEach(ThrowingConsumer.toConsumer(pkgDir -> { - // Installation root of the package is stored in - // /pkg-info@install-location attribute in $pkgDir/PackageInfo xml file - var doc = createDocumentBuilder().parse( - new ByteArrayInputStream(Files.readAllBytes( - pkgDir.resolve("PackageInfo")))); - var xPath = XPathFactory.newInstance().newXPath(); - - final String installRoot = (String) xPath.evaluate( - "/pkg-info/@install-location", doc, - XPathConstants.STRING); - - final Path unpackDir = unpackRoot.resolve( - TKit.removeRootFromAbsolutePath(Path.of(installRoot))); - - Files.createDirectories(unpackDir); - - Executor.of("tar", "-C") - .addArgument(unpackDir) - .addArgument("-xvf") - .addArgument(pkgDir.resolve("Payload")) - .execute(); - })); - } catch (IOException ex) { - throw new RuntimeException(ex); - } + Executor.of("pkgutil", "--expand") + .addArgument(cmd.outputBundle()) + .addArgument(dataDir) // We need non-existing folder + .execute(); - return unpackRoot; - }; - pkg.uninstallHandler = cmd -> { - cmd.verifyIsOfType(PackageType.MAC_PKG); + final Path unpackRoot = destinationDir.resolve("unpacked"); - if (Files.exists(getUninstallCommand(cmd))) { - Executor.of("sudo", "/bin/sh", - getUninstallCommand(cmd).toString()).execute(); - } else { - Executor.of("sudo", "rm", "-rf") - .addArgument(cmd.appInstallationDirectory()) + // Unpack all ".pkg" files from $dataDir folder in $unpackDir folder + try (var dataListing = Files.list(dataDir)) { + dataListing.filter(file -> { + return ".pkg".equals(PathUtils.getSuffix(file.getFileName())); + }).forEach(ThrowingConsumer.toConsumer(pkgDir -> { + // Installation root of the package is stored in + // /pkg-info@install-location attribute in $pkgDir/PackageInfo xml file + var doc = createDocumentBuilder().parse( + new ByteArrayInputStream(Files.readAllBytes( + pkgDir.resolve("PackageInfo")))); + var xPath = XPathFactory.newInstance().newXPath(); + + final String installRoot = (String) xPath.evaluate( + "/pkg-info/@install-location", doc, + XPathConstants.STRING); + + final Path unpackDir = unpackRoot.resolve( + TKit.removeRootFromAbsolutePath(Path.of(installRoot))); + + Files.createDirectories(unpackDir); + + Executor.of("tar", "-C") + .addArgument(unpackDir) + .addArgument("-xvf") + .addArgument(pkgDir.resolve("Payload")) .execute(); - } - }; + })); + } catch (IOException ex) { + throw new RuntimeException(ex); + } - return pkg; + return unpackRoot; } static void verifyBundleStructure(JPackageCommand cmd) { @@ -298,9 +301,18 @@ static String getBundleName(JPackageCommand cmd) { static Path getInstallationDirectory(JPackageCommand cmd) { cmd.verifyIsOfType(PackageType.MAC); - return Path.of(cmd.getArgumentValue("--install-dir", - () -> cmd.isRuntime() ? "/Library/Java/JavaVirtualMachines" : "/Applications")).resolve( - cmd.name() + (cmd.isRuntime() ? "" : ".app")); + + final var defaultInstallLocation = Path.of( + cmd.isRuntime() ? "/Library/Java/JavaVirtualMachines" : "/Applications"); + + final Path installLocation; + if (cmd.packageType() == PackageType.MAC_DMG) { + installLocation = defaultInstallLocation; + } else { + installLocation = cmd.getArgumentValue("--install-dir", () -> defaultInstallLocation, Path::of); + } + + return installLocation.resolve(cmd.name() + (cmd.isRuntime() ? "" : ".app")); } static Path getUninstallCommand(JPackageCommand cmd) { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java index f89bd0a60c8..e7b3f3e3a44 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java @@ -22,6 +22,15 @@ */ package jdk.jpackage.test; +import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; +import static jdk.jpackage.internal.util.function.ThrowingBiConsumer.toBiConsumer; +import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; +import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; +import static jdk.jpackage.test.PackageType.LINUX; +import static jdk.jpackage.test.PackageType.MAC_PKG; +import static jdk.jpackage.test.PackageType.NATIVE; +import static jdk.jpackage.test.PackageType.WINDOWS; + import java.awt.GraphicsEnvironment; import java.io.IOException; import java.nio.file.Files; @@ -29,6 +38,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -40,27 +50,15 @@ import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; import jdk.jpackage.internal.util.function.ThrowingBiConsumer; -import static jdk.jpackage.internal.util.function.ThrowingBiConsumer.toBiConsumer; import jdk.jpackage.internal.util.function.ThrowingConsumer; -import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; import jdk.jpackage.internal.util.function.ThrowingRunnable; -import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; -import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; -import static jdk.jpackage.test.PackageType.LINUX; -import static jdk.jpackage.test.PackageType.LINUX_DEB; -import static jdk.jpackage.test.PackageType.LINUX_RPM; -import static jdk.jpackage.test.PackageType.MAC_DMG; -import static jdk.jpackage.test.PackageType.MAC_PKG; -import static jdk.jpackage.test.PackageType.NATIVE; -import static jdk.jpackage.test.PackageType.WINDOWS; -import static jdk.jpackage.test.PackageType.WIN_EXE; -import static jdk.jpackage.test.PackageType.WIN_MSI; /** @@ -73,13 +71,18 @@ public final class PackageTest extends RunnablePackageTest { public PackageTest() { + isPackageTypeSupported = PackageType::isSupported; + jpackageFactory = JPackageCommand::new; + packageHandlers = new HashMap<>(); + disabledInstallers = new HashSet<>(); + disabledUninstallers = new HashSet<>(); excludeTypes = new HashSet<>(); forTypes(); setExpectedExitCode(0); + setExpectedInstallExitCode(0); namedInitializers = new HashSet<>(); - handlers = currentTypes.stream() + handlers = NATIVE.stream() .collect(Collectors.toMap(v -> v, v -> new Handler())); - packageHandlers = createDefaultPackageHandlers(); } public PackageTest excludeTypes(PackageType... types) { @@ -93,13 +96,13 @@ public PackageTest excludeTypes(Collection<PackageType> types) { public PackageTest forTypes(PackageType... types) { Collection<PackageType> newTypes; - if (types == null || types.length == 0) { + if (types.length == 0) { newTypes = NATIVE; } else { newTypes = Stream.of(types).collect(Collectors.toSet()); } currentTypes = newTypes.stream() - .filter(PackageType::isSupported) + .filter(isPackageTypeSupported) .filter(Predicate.not(excludeTypes::contains)) .collect(Collectors.toUnmodifiableSet()); return this; @@ -124,6 +127,11 @@ public PackageTest setExpectedExitCode(int v) { return this; } + public PackageTest setExpectedInstallExitCode(int v) { + expectedInstallExitCode = v; + return this; + } + public PackageTest ignoreBundleOutputDir() { return ignoreBundleOutputDir(true); } @@ -133,8 +141,8 @@ public PackageTest ignoreBundleOutputDir(boolean v) { return this; } - private PackageTest addInitializer(ThrowingConsumer<JPackageCommand> v, - String id) { + private PackageTest addInitializer(ThrowingConsumer<JPackageCommand> v, String id) { + Objects.requireNonNull(v); if (id != null) { if (namedInitializers.contains(id)) { return this; @@ -142,12 +150,12 @@ private PackageTest addInitializer(ThrowingConsumer<JPackageCommand> v, namedInitializers.add(id); } - currentTypes.forEach(type -> handlers.get(type).addInitializer( - toConsumer(v))); + currentTypes.forEach(type -> handlers.get(type).addInitializer(toConsumer(v))); return this; } private PackageTest addRunOnceInitializer(ThrowingRunnable v, String id) { + Objects.requireNonNull(v); return addInitializer(new ThrowingConsumer<JPackageCommand>() { @Override public void accept(JPackageCommand unused) throws Throwable { @@ -169,24 +177,26 @@ public PackageTest addRunOnceInitializer(ThrowingRunnable v) { return addRunOnceInitializer(v, null); } - public PackageTest addBundleVerifier( - ThrowingBiConsumer<JPackageCommand, Executor.Result> v) { - currentTypes.forEach(type -> handlers.get(type).addBundleVerifier( - toBiConsumer(v))); + public PackageTest addBundleVerifier(ThrowingBiConsumer<JPackageCommand, Executor.Result> v) { + Objects.requireNonNull(v); + currentTypes.forEach(type -> handlers.get(type).addBundleVerifier(toBiConsumer(v))); return this; } public PackageTest addBundleVerifier(ThrowingConsumer<JPackageCommand> v) { + Objects.requireNonNull(v); return addBundleVerifier((cmd, unused) -> toConsumer(v).accept(cmd)); } public PackageTest addBundlePropertyVerifier(String propertyName, Predicate<String> pred, String predLabel) { + Objects.requireNonNull(propertyName); + Objects.requireNonNull(pred); return addBundleVerifier(cmd -> { final String value; - if (TKit.isLinux()) { + if (isOfType(cmd, LINUX)) { value = LinuxHelper.getBundleProperty(cmd, propertyName); - } else if (TKit.isWindows()) { + } else if (isOfType(cmd, WINDOWS)) { value = WindowsHelper.getMsiProperty(cmd, propertyName); } else { throw new IllegalStateException(); @@ -223,19 +233,23 @@ public PackageTest addUninstallVerifier(ThrowingConsumer<JPackageCommand> v) { } public PackageTest disablePackageInstaller() { - currentTypes.forEach( - type -> packageHandlers.get(type).installHandler = cmd -> {}); + currentTypes.forEach(disabledInstallers::add); return this; } public PackageTest disablePackageUninstaller() { - currentTypes.forEach( - type -> packageHandlers.get(type).uninstallHandler = cmd -> {}); + currentTypes.forEach(disabledUninstallers::add); + return this; + } + + public PackageTest createMsiLog(boolean v) { + createMsiLog = v; return this; } static void withFileAssociationsTestRuns(FileAssociations fa, ThrowingBiConsumer<FileAssociations.TestRun, List<Path>> consumer) { + Objects.requireNonNull(consumer); for (var testRun : fa.getTestRuns()) { TKit.withTempDirectory("fa-test-files", tempDir -> { List<Path> testFiles = StreamSupport.stream(testRun.getFileNames().spliterator(), false).map(fname -> { @@ -254,6 +268,7 @@ static void withFileAssociationsTestRuns(FileAssociations fa, } PackageTest addHelloAppFileAssociationsVerifier(FileAssociations fa) { + Objects.requireNonNull(fa); // Setup test app to have valid jpackage command line before // running check of type of environment. @@ -290,7 +305,7 @@ PackageTest addHelloAppFileAssociationsVerifier(FileAssociations fa) { Collections.emptyMap()); }); - if (TKit.isWindows()) { + if (isOfType(cmd, WINDOWS)) { // Verify context menu label in registry. String progId = WindowsHelper.queryRegistryValue( String.format("HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\%s", fa.getSuffix()), ""); @@ -307,8 +322,7 @@ PackageTest addHelloAppFileAssociationsVerifier(FileAssociations fa) { } public PackageTest forTypes(Collection<PackageType> types, Runnable action) { - Set<PackageType> oldTypes = Set.of(currentTypes.toArray( - PackageType[]::new)); + final var oldTypes = Set.of(currentTypes.toArray(PackageType[]::new)); try { forTypes(types); action.run(); @@ -374,10 +388,59 @@ protected void runAction(Action... action) { private final List<Consumer<Action>> handlers; } - static final class PackageHandlers { - Consumer<JPackageCommand> installHandler; - Consumer<JPackageCommand> uninstallHandler; - BiFunction<JPackageCommand, Path, Path> unpackHandler; + PackageTest packageHandlers(PackageHandlers v) { + Objects.requireNonNull(v); + currentTypes.forEach(type -> packageHandlers.put(type, v)); + return this; + } + + PackageTest isPackageTypeSupported(Predicate<PackageType> v) { + Objects.requireNonNull(v); + isPackageTypeSupported = v; + return this; + } + + PackageTest jpackageFactory(Supplier<JPackageCommand> v) { + Objects.requireNonNull(v); + jpackageFactory = v; + return this; + } + + record PackageHandlers(Function<JPackageCommand, Integer> installHandler, + Consumer<JPackageCommand> uninstallHandler, + Optional<? extends BiFunction<JPackageCommand, Path, Path>> unpackHandler) { + + PackageHandlers(Function<JPackageCommand, Integer> installHandler, + Consumer<JPackageCommand> uninstallHandler, + BiFunction<JPackageCommand, Path, Path> unpackHandler) { + this(installHandler, uninstallHandler, Optional.of(unpackHandler)); + } + + PackageHandlers { + Objects.requireNonNull(installHandler); + Objects.requireNonNull(uninstallHandler); + Objects.requireNonNull(unpackHandler); + } + + PackageHandlers copyWithNopInstaller() { + return new PackageHandlers(cmd -> 0, uninstallHandler, unpackHandler); + } + + PackageHandlers copyWithNopUninstaller() { + return new PackageHandlers(installHandler, cmd -> {}, unpackHandler); + } + + int install(JPackageCommand cmd) { + return installHandler.apply(cmd); + } + + Path unpack(JPackageCommand cmd, Path unpackDir) { + return unpackHandler.orElseThrow().apply(cmd, unpackDir); + } + + void uninstall(JPackageCommand cmd) { + uninstallHandler.accept(cmd); + } } @Override @@ -393,164 +456,197 @@ protected void runAction(Action... action) { } private List<Consumer<Action>> createPackageTypeHandlers() { - return NATIVE.stream() - .map(type -> { - Handler handler = handlers.entrySet().stream() - .filter(entry -> !entry.getValue().isVoid()) - .filter(entry -> entry.getKey() == type) - .map(entry -> entry.getValue()) - .findAny().orElse(null); - Map.Entry<PackageType, Handler> result = null; - if (handler != null) { - result = Map.entry(type, handler); - } - return result; - }) - .filter(Objects::nonNull) - .map(entry -> createPackageTypeHandler( - entry.getKey(), entry.getValue())) - .collect(Collectors.toList()); + return handlers.entrySet().stream() + .filter(entry -> !entry.getValue().isVoid()) + .filter(entry -> NATIVE.contains(entry.getKey())) + .sorted(Comparator.comparing(Map.Entry::getKey)) + .map(entry -> { + return createPackageTypeHandler(entry.getKey(), entry.getValue()); + }).toList(); } - private Consumer<Action> createPackageTypeHandler( - PackageType type, Handler handler) { - return toConsumer(new ThrowingConsumer<Action>() { - @Override - public void accept(Action action) throws Throwable { - if (terminated) { - throw new IllegalStateException(); - } + private record PackageTypePipeline(PackageType type, int expectedJPackageExitCode, + int expectedInstallExitCode, PackageHandlers packageHandlers, Handler handler, + JPackageCommand cmd, State state) implements Consumer<Action> { - if (action == Action.FINALIZE) { - if (unpackDir != null) { - if (Files.isDirectory(unpackDir) - && !unpackDir.startsWith(TKit.workDir())) { - TKit.deleteDirectoryRecursive(unpackDir); - } - unpackDir = null; - } - terminated = true; - } + PackageTypePipeline { + Objects.requireNonNull(type); + Objects.requireNonNull(packageHandlers); + Objects.requireNonNull(handler); + Objects.requireNonNull(cmd); + Objects.requireNonNull(state); + } - boolean skip = false; - - if (unhandledAction != null) { - switch (unhandledAction) { - case CREATE: - skip = true; - break; - case UNPACK: - case INSTALL: - skip = (action == Action.VERIFY_INSTALL); - break; - case UNINSTALL: - skip = (action == Action.VERIFY_UNINSTALL); - break; - default: // NOP - } - } + PackageTypePipeline(PackageType type, int expectedJPackageExitCode, + int expectedInstallExitCode, PackageHandlers packageHandlers, + Handler handler, JPackageCommand cmd) { + this(type, expectedJPackageExitCode, expectedInstallExitCode, + packageHandlers, handler, cmd, new State()); + } - if (skip) { + @Override + public void accept(Action action) { + switch(analizeAction(action)) { + case SKIP_NO_PACKAGE_HANDLER -> { + TKit.trace(String.format("No handler of [%s] action for %s command", + action, cmd.getPrintableCommandLine())); + return; + } + case SKIP -> { TKit.trace(String.format("Skip [%s] action of %s command", action, cmd.getPrintableCommandLine())); return; } + case PROCESS -> { + } + } - final Supplier<JPackageCommand> curCmd = () -> { - if (Set.of(Action.INITIALIZE, Action.CREATE).contains(action)) { - return cmd; - } else { - return cmd.createImmutableCopy(); - } - }; - - switch (action) { - case UNPACK: { - cmd.setUnpackedPackageLocation(null); - handleAction(action, - packageHandlers.get(type).unpackHandler, - handler -> { - unpackDir = TKit.createTempDirectory( - String.format("unpacked-%s", - type.getName())); - unpackDir = handler.apply(cmd, unpackDir); - cmd.setUnpackedPackageLocation(unpackDir); - }); - break; + switch (action) { + case UNPACK -> { + cmd.setUnpackedPackageLocation(null); + final var unpackRootDir = TKit.createTempDirectory( + String.format("unpacked-%s", type.getName())); + final Path unpackDir = packageHandlers.unpack(cmd, unpackRootDir); + if (!unpackDir.startsWith(TKit.workDir())) { + state.deleteUnpackDirs.add(unpackDir); } + cmd.setUnpackedPackageLocation(unpackDir); + } - case INSTALL: { - cmd.setUnpackedPackageLocation(null); - handleAction(action, - packageHandlers.get(type).installHandler, - handler -> { - handler.accept(curCmd.get()); - }); - break; - } + case INSTALL -> { + cmd.setUnpackedPackageLocation(null); + final int installExitCode = packageHandlers.install(cmd); + TKit.assertEquals(expectedInstallExitCode, installExitCode, + String.format("Check installer exited with %d code", expectedInstallExitCode)); + } - case UNINSTALL: { - handleAction(action, - packageHandlers.get(type).uninstallHandler, - handler -> { - handler.accept(curCmd.get()); - }); - break; - } + case UNINSTALL -> { + cmd.setUnpackedPackageLocation(null); + packageHandlers.uninstall(cmd); + } - case CREATE: - cmd.setUnpackedPackageLocation(null); - handler.accept(action, curCmd.get()); - handleAction(action, - (expectedJPackageExitCode == 0) ? Boolean.TRUE : null, - handler -> { - }); - return; - - default: - handler.accept(action, curCmd.get()); - break; + case CREATE -> { + cmd.setUnpackedPackageLocation(null); + handler.processAction(action, cmd, expectedJPackageExitCode); } - Optional.ofNullable(unhandledAction).ifPresent(v -> { - TKit.trace(String.format( - "No handler of [%s] action for %s command", v, - cmd.getPrintableCommandLine())); - }); - } + case INITIALIZE -> { + handler.processAction(action, cmd, expectedJPackageExitCode); + } + + case FINALIZE -> { + state.deleteUnpackDirs.forEach(TKit::deleteDirectoryRecursive); + state.deleteUnpackDirs.clear(); + } - private <T> void handleAction(Action action, T handler, - ThrowingConsumer<T> consumer) throws Throwable { - if (handler == null) { - unhandledAction = action; - } else { - unhandledAction = null; - consumer.accept(handler); + default -> { + handler.processAction(action, cmd.createImmutableCopy(), expectedJPackageExitCode); } } + } + + private enum ActionAction { + PROCESS, + SKIP, + SKIP_NO_PACKAGE_HANDLER + } + + private ActionAction analizeAction(Action action) { + Objects.requireNonNull(action); + + if (jpackageFailed()) { + return ActionAction.SKIP; + } - private Path unpackDir; - private Action unhandledAction; - private boolean terminated; - private final JPackageCommand cmd = Functional.identity(() -> { - JPackageCommand result = new JPackageCommand(); - result.setDefaultInputOutput().setDefaultAppName(); - if (BUNDLE_OUTPUT_DIR != null && !ignoreBundleOutputDir) { - result.setArgumentValue("--dest", BUNDLE_OUTPUT_DIR.toString()); + switch (action) { + case CREATE -> { + state.packageActions.add(action); } - type.applyTo(result); - return result; - }).get(); - }); + case INSTALL -> { + state.packageActions.add(action); + state.packageActions.remove(Action.UNPACK); + } + case UNINSTALL -> { + state.packageActions.add(action); + if (installFailed()) { + return ActionAction.SKIP; + } + } + case UNPACK -> { + state.packageActions.add(action); + state.packageActions.remove(Action.INSTALL); + if (unpackNotSupported()) { + return ActionAction.SKIP_NO_PACKAGE_HANDLER; + } + } + case VERIFY_INSTALL -> { + if (unpackNotSupported()) { + return ActionAction.SKIP; + } + + if (installFailed()) { + return ActionAction.SKIP; + } + } + case VERIFY_UNINSTALL -> { + if (installFailed() && processed(Action.UNINSTALL)) { + return ActionAction.SKIP; + } + } + default -> { + // NOP + } + } + + return ActionAction.PROCESS; + } + + private boolean processed(Action action) { + Objects.requireNonNull(action); + return state.packageActions.contains(action); + } + + private boolean installFailed() { + return processed(Action.INSTALL) && expectedInstallExitCode != 0; + } + + private boolean jpackageFailed() { + return processed(Action.CREATE) && expectedJPackageExitCode != 0; + } + + private boolean unpackNotSupported() { + return processed(Action.UNPACK) && packageHandlers.unpackHandler().isEmpty(); + } + + private final static class State { + private final Set<Action> packageActions = new HashSet<>(); + private final List<Path> deleteUnpackDirs = new ArrayList<>(); + } } - private class Handler implements BiConsumer<Action, JPackageCommand> { + private Consumer<Action> createPackageTypeHandler(PackageType type, Handler handler) { + final var cmd = jpackageFactory.get(); + cmd.setDefaultInputOutput().setDefaultAppName(); + if (BUNDLE_OUTPUT_DIR != null && !ignoreBundleOutputDir) { + cmd.setArgumentValue("--dest", BUNDLE_OUTPUT_DIR.toString()); + } + type.applyTo(cmd); + return new PackageTypePipeline(type, expectedJPackageExitCode, + expectedInstallExitCode, getPackageHandlers(type), handler.copy(), cmd); + } + + private record Handler(List<Consumer<JPackageCommand>> initializers, + List<BiConsumer<JPackageCommand, Executor.Result>> bundleVerifiers, + List<Consumer<JPackageCommand>> installVerifiers, + List<Consumer<JPackageCommand>> uninstallVerifiers) { Handler() { - initializers = new ArrayList<>(); - bundleVerifiers = new ArrayList<>(); - installVerifiers = new ArrayList<>(); - uninstallVerifiers = new ArrayList<>(); + this(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + } + + Handler copy() { + return new Handler(List.copyOf(initializers), List.copyOf(bundleVerifiers), + List.copyOf(installVerifiers), List.copyOf(uninstallVerifiers)); } boolean isVoid() { @@ -573,18 +669,17 @@ void addUninstallVerifier(Consumer<JPackageCommand> v) { uninstallVerifiers.add(v); } - @Override - public void accept(Action action, JPackageCommand cmd) { + public void processAction(Action action, JPackageCommand cmd, int expectedJPackageExitCode) { switch (action) { - case INITIALIZE: + case INITIALIZE -> { initializers.forEach(v -> v.accept(cmd)); if (cmd.isImagePackageType()) { throw new UnsupportedOperationException(); } cmd.executePrerequisiteActions(); - break; + } - case CREATE: + case CREATE -> { Executor.Result result = cmd.execute(expectedJPackageExitCode); if (expectedJPackageExitCode == 0) { TKit.assertFileExists(cmd.outputBundle()); @@ -593,39 +688,38 @@ public void accept(Action action, JPackageCommand cmd) { TKit.assertPathExists(outputBundle, false); }); } - verifyPackageBundle(cmd, result); - break; + verifyPackageBundle(cmd, result, expectedJPackageExitCode); + } - case VERIFY_INSTALL: + case VERIFY_INSTALL -> { if (expectedJPackageExitCode == 0) { verifyPackageInstalled(cmd); } - break; + } - case VERIFY_UNINSTALL: + case VERIFY_UNINSTALL -> { if (expectedJPackageExitCode == 0) { verifyPackageUninstalled(cmd); } - break; + } - case PURGE: - if (expectedJPackageExitCode == 0) { - var bundle = cmd.outputBundle(); - if (toSupplier(() -> TKit.deleteIfExists(bundle)).get()) { - TKit.trace(String.format("Deleted [%s] package", - bundle)); - } + case PURGE -> { + var bundle = cmd.outputBundle(); + if (toSupplier(() -> TKit.deleteIfExists(bundle)).get()) { + TKit.trace(String.format("Deleted [%s] package", bundle)); } - break; + } - default: // NOP + default -> { + // NOP + } } } private void verifyPackageBundle(JPackageCommand cmd, - Executor.Result result) { + Executor.Result result, int expectedJPackageExitCode) { if (expectedJPackageExitCode == 0) { - if (LINUX.contains(cmd.packageType())) { + if (isOfType(cmd, LINUX)) { LinuxHelper.verifyPackageBundleEssential(cmd); } } @@ -647,9 +741,7 @@ private void verifyPackageInstalled(JPackageCommand cmd) { }); if (!cmd.isRuntime()) { - if (WINDOWS.contains(cmd.packageType()) - && !cmd.isPackageUnpacked( - "Not verifying desktop integration")) { + if (isOfType(cmd, WINDOWS) && !cmd.isPackageUnpacked("Not verifying desktop integration")) { // Check main launcher WindowsHelper.verifyDesktopIntegration(cmd, null); // Check additional launchers @@ -659,8 +751,7 @@ private void verifyPackageInstalled(JPackageCommand cmd) { } } - if (LauncherAsServiceVerifier.SUPPORTED_PACKAGES.contains( - cmd.packageType())) { + if (isOfType(cmd, LauncherAsServiceVerifier.SUPPORTED_PACKAGES)) { LauncherAsServiceVerifier.verify(cmd); } @@ -676,13 +767,13 @@ private void verifyRootCountInUnpackedPackage(JPackageCommand cmd, && !LauncherAsServiceVerifier.getLaunchersAsServices(cmd).isEmpty(); final long expectedRootCount; - if (WINDOWS.contains(cmd.packageType())) { + if (isOfType(cmd, WINDOWS)) { // On Windows it is always two entries: // installation home directory and MSI file expectedRootCount = 2; - } else if (withServices && MAC_PKG.equals(cmd.packageType())) { + } else if (withServices && isOfType(cmd, MAC_PKG)) { expectedRootCount = 2; - } else if (LINUX.contains(cmd.packageType())) { + } else if (isOfType(cmd, LINUX)) { Set<Path> roots = new HashSet<>(); roots.add(Path.of("/").resolve(Path.of(cmd.getArgumentValue( "--install-dir", () -> "/opt")).getName(0))); @@ -732,7 +823,7 @@ private void verifyPackageUninstalled(JPackageCommand cmd) { if (!cmd.isRuntime()) { TKit.assertPathExists(cmd.appLauncherPath(), false); - if (WINDOWS.contains(cmd.packageType())) { + if (isOfType(cmd, WINDOWS)) { // Check main launcher WindowsHelper.verifyDesktopIntegration(cmd, null); // Check additional launchers @@ -743,54 +834,94 @@ private void verifyPackageUninstalled(JPackageCommand cmd) { } Path appInstallDir = cmd.appInstallationDirectory(); - if (TKit.isLinux() && Path.of("/").equals(appInstallDir)) { + if (isOfType(cmd, LINUX) && Path.of("/").equals(appInstallDir)) { ApplicationLayout appLayout = cmd.appLayout(); TKit.assertPathExists(appLayout.runtimeDirectory(), false); } else { TKit.assertPathExists(appInstallDir, false); } - if (LauncherAsServiceVerifier.SUPPORTED_PACKAGES.contains( - cmd.packageType())) { + if (isOfType(cmd, LauncherAsServiceVerifier.SUPPORTED_PACKAGES)) { LauncherAsServiceVerifier.verifyUninstalled(cmd); } uninstallVerifiers.forEach(v -> v.accept(cmd)); } - - private final List<Consumer<JPackageCommand>> initializers; - private final List<BiConsumer<JPackageCommand, Executor.Result>> bundleVerifiers; - private final List<Consumer<JPackageCommand>> installVerifiers; - private final List<Consumer<JPackageCommand>> uninstallVerifiers; } - private static Map<PackageType, PackageHandlers> createDefaultPackageHandlers() { - HashMap<PackageType, PackageHandlers> handlers = new HashMap<>(); - if (TKit.isLinux()) { - handlers.put(LINUX_DEB, LinuxHelper.createDebPackageHandlers()); - handlers.put(LINUX_RPM, LinuxHelper.createRpmPackageHandlers()); + private PackageHandlers getDefaultPackageHandlers(PackageType type) { + switch (type) { + case LINUX_DEB -> { + return LinuxHelper.createDebPackageHandlers(); + } + case LINUX_RPM -> { + return LinuxHelper.createRpmPackageHandlers(); + } + case WIN_MSI -> { + return WindowsHelper.createMsiPackageHandlers(createMsiLog); + } + case WIN_EXE -> { + return WindowsHelper.createExePackageHandlers(createMsiLog); + } + case MAC_DMG -> { + return MacHelper.createDmgPackageHandlers(); + } + case MAC_PKG -> { + return MacHelper.createPkgPackageHandlers(); + } + default -> { + throw new IllegalArgumentException(); + } } + } + + private PackageHandlers getPackageHandlers(PackageType type) { + Objects.requireNonNull(type); - if (TKit.isWindows()) { - handlers.put(WIN_MSI, WindowsHelper.createMsiPackageHandlers()); - handlers.put(WIN_EXE, WindowsHelper.createExePackageHandlers()); + var reply = Optional.ofNullable(packageHandlers.get(type)).orElseGet(() -> { + if (TKit.isLinux() && !PackageType.LINUX.contains(type)) { + throw new IllegalArgumentException(); + } else if (TKit.isWindows() && !PackageType.WINDOWS.contains(type)) { + throw new IllegalArgumentException(); + } else if (TKit.isOSX() && !PackageType.MAC.contains(type)) { + throw new IllegalArgumentException(); + } else { + return getDefaultPackageHandlers(type); + } + }); + + if (disabledInstallers.contains(type)) { + reply = reply.copyWithNopInstaller(); } - if (TKit.isOSX()) { - handlers.put(MAC_DMG, MacHelper.createDmgPackageHandlers()); - handlers.put(MAC_PKG, MacHelper.createPkgPackageHandlers()); + if (disabledUninstallers.contains(type)) { + reply = reply.copyWithNopUninstaller(); } - return handlers; + return reply; + } + + private static boolean isOfType(JPackageCommand cmd, PackageType packageTypes) { + return isOfType(cmd, Set.of(packageTypes)); + } + + private static boolean isOfType(JPackageCommand cmd, Set<PackageType> packageTypes) { + return Optional.ofNullable(cmd.packageType()).map(packageTypes::contains).orElse(false); } private Collection<PackageType> currentTypes; private Set<PackageType> excludeTypes; private int expectedJPackageExitCode; - private Map<PackageType, Handler> handlers; - private Set<String> namedInitializers; - private Map<PackageType, PackageHandlers> packageHandlers; + private int expectedInstallExitCode; + private final Map<PackageType, Handler> handlers; + private final Set<String> namedInitializers; + private final Map<PackageType, PackageHandlers> packageHandlers; + private final Set<PackageType> disabledInstallers; + private final Set<PackageType> disabledUninstallers; + private Predicate<PackageType> isPackageTypeSupported; + private Supplier<JPackageCommand> jpackageFactory; private boolean ignoreBundleOutputDir; + private boolean createMsiLog; private static final Path BUNDLE_OUTPUT_DIR; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java index 48643463e0b..91705afd5fe 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java @@ -22,24 +22,25 @@ */ package jdk.jpackage.test; +import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; +import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; + import java.io.IOException; import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.function.BiConsumer; +import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; -import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; import jdk.jpackage.internal.util.function.ThrowingRunnable; -import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; import jdk.jpackage.test.PackageTest.PackageHandlers; public class WindowsHelper { @@ -67,21 +68,24 @@ private static Path getInstallationSubDirectory(JPackageCommand cmd) { return Path.of(cmd.getArgumentValue("--install-dir", cmd::name)); } - private static void runMsiexecWithRetries(Executor misexec) { + private static int runMsiexecWithRetries(Executor misexec, Optional<Path> msiLog) { Executor.Result result = null; + final boolean isUnpack = misexec.getExecutable().orElseThrow().equals(Path.of("cmd")); + final List<String> origArgs = msiLog.isPresent() ? misexec.getAllArguments() : null; for (int attempt = 0; attempt < 8; ++attempt) { + msiLog.ifPresent(v -> misexec.clearArguments().addArguments(origArgs).addArgument("/L*v").addArgument(v)); result = misexec.executeWithoutExitCodeCheck(); if (result.exitCode() == 1605) { // ERROR_UNKNOWN_PRODUCT, attempt to uninstall not installed // package - return; + return result.exitCode(); } // The given Executor may either be of an msiexec command or an // unpack.bat script containing the msiexec command. In the later // case, when misexec returns 1618, the unpack.bat may return 1603 - if ((result.exitCode() == 1618) || (result.exitCode() == 1603)) { + if ((result.exitCode() == 1618) || (result.exitCode() == 1603 && isUnpack)) { // Another installation is already in progress. // Wait a little and try again. Long timeout = 1000L * (attempt + 3); // from 3 to 10 seconds @@ -91,74 +95,123 @@ private static void runMsiexecWithRetries(Executor misexec) { break; } - result.assertExitCodeIsZero(); + return result.exitCode(); } - static PackageHandlers createMsiPackageHandlers() { - BiConsumer<JPackageCommand, Boolean> installMsi = (cmd, install) -> { - cmd.verifyIsOfType(PackageType.WIN_MSI); - var msiPath = TransientMsi.create(cmd).path(); - runMsiexecWithRetries(Executor.of("msiexec", "/qn", "/norestart", - install ? "/i" : "/x").addArgument(msiPath)); - }; + static PackageHandlers createMsiPackageHandlers(boolean createMsiLog) { + return new PackageHandlers(cmd -> installMsi(cmd, createMsiLog), + cmd -> uninstallMsi(cmd, createMsiLog), WindowsHelper::unpackMsi); + } - PackageHandlers msi = new PackageHandlers(); - msi.installHandler = cmd -> installMsi.accept(cmd, true); - msi.uninstallHandler = cmd -> { - if (Files.exists(cmd.outputBundle())) { - installMsi.accept(cmd, false); - } - }; - msi.unpackHandler = (cmd, destinationDir) -> { - cmd.verifyIsOfType(PackageType.WIN_MSI); - final Path unpackBat = destinationDir.resolve("unpack.bat"); - final Path unpackDir = destinationDir.resolve( - TKit.removeRootFromAbsolutePath( - getInstallationRootDirectory(cmd))); - - final Path msiPath = TransientMsi.create(cmd).path(); - - // Put msiexec in .bat file because can't pass value of TARGETDIR - // property containing spaces through ProcessBuilder properly. - // Set folder permissions to allow msiexec unpack msi bundle. - TKit.createTextFile(unpackBat, List.of( - String.format("icacls \"%s\" /inheritance:e /grant Users:M", - destinationDir), - String.join(" ", List.of( - "msiexec", - "/a", - String.format("\"%s\"", msiPath), - "/qn", - String.format("TARGETDIR=\"%s\"", - unpackDir.toAbsolutePath().normalize()))))); - runMsiexecWithRetries(Executor.of("cmd", "/c", unpackBat.toString())); - - // - // WiX3 uses "." as the value of "DefaultDir" field for "ProgramFiles64Folder" folder in msi's Directory table - // WiX4 uses "PFiles64" as the value of "DefaultDir" field for "ProgramFiles64Folder" folder in msi's Directory table - // msiexec creates "Program Files/./<App Installation Directory>" from WiX3 msi which translates to "Program Files/<App Installation Directory>" - // msiexec creates "Program Files/PFiles64/<App Installation Directory>" from WiX4 msi - // So for WiX4 msi we need to transform "Program Files/PFiles64/<App Installation Directory>" into "Program Files/<App Installation Directory>" - // - // WiX4 does the same thing for %LocalAppData%. - // - for (var extraPathComponent : List.of("PFiles64", "LocalApp")) { - if (Files.isDirectory(unpackDir.resolve(extraPathComponent))) { - Path installationSubDirectory = getInstallationSubDirectory(cmd); - Path from = Path.of(extraPathComponent).resolve(installationSubDirectory); - Path to = installationSubDirectory; - TKit.trace(String.format("Convert [%s] into [%s] in [%s] directory", from, to, - unpackDir)); - ThrowingRunnable.toRunnable(() -> { - Files.createDirectories(unpackDir.resolve(to).getParent()); - Files.move(unpackDir.resolve(from), unpackDir.resolve(to)); - TKit.deleteDirectoryRecursive(unpackDir.resolve(extraPathComponent)); - }).run(); - } + private static Optional<Path> configureMsiLogFile(JPackageCommand cmd, boolean createMsiLog) { + final Optional<Path> msiLogFile; + if (createMsiLog) { + msiLogFile = Optional.of(TKit.createTempFile(String.format("logs\\%s-msi.log", + cmd.packageType().getName()))); + } else { + msiLogFile = Optional.empty(); + } + + cmd.winMsiLogFile(msiLogFile.orElse(null)); + + return msiLogFile; + } + + private static int runMsiInstaller(JPackageCommand cmd, boolean createMsiLog, boolean install) { + cmd.verifyIsOfType(PackageType.WIN_MSI); + final var msiPath = TransientMsi.create(cmd).path(); + return runMsiexecWithRetries(Executor.of("msiexec", "/qn", "/norestart", + install ? "/i" : "/x").addArgument(msiPath), configureMsiLogFile(cmd, createMsiLog)); + } + + private static int installMsi(JPackageCommand cmd, boolean createMsiLog) { + return runMsiInstaller(cmd, createMsiLog, true); + } + + private static void uninstallMsi(JPackageCommand cmd, boolean createMsiLog) { + if (Files.exists(cmd.outputBundle())) { + runMsiInstaller(cmd, createMsiLog, false); + } else { + configureMsiLogFile(cmd, false); + } + } + + private static Path unpackMsi(JPackageCommand cmd, Path destinationDir) { + cmd.verifyIsOfType(PackageType.WIN_MSI); + configureMsiLogFile(cmd, false); + final Path unpackBat = destinationDir.resolve("unpack.bat"); + final Path unpackDir = destinationDir.resolve( + TKit.removeRootFromAbsolutePath( + getInstallationRootDirectory(cmd))); + + final Path msiPath = TransientMsi.create(cmd).path(); + + // Put msiexec in .bat file because can't pass value of TARGETDIR + // property containing spaces through ProcessBuilder properly. + // Set folder permissions to allow msiexec unpack msi bundle. + TKit.createTextFile(unpackBat, List.of( + String.format("icacls \"%s\" /inheritance:e /grant Users:M", + destinationDir), + String.join(" ", List.of( + "msiexec", + "/a", + String.format("\"%s\"", msiPath), + "/qn", + String.format("TARGETDIR=\"%s\"", + unpackDir.toAbsolutePath().normalize()))))); + runMsiexecWithRetries(Executor.of("cmd", "/c", unpackBat.toString()), Optional.empty()); + + // + // WiX3 uses "." as the value of "DefaultDir" field for "ProgramFiles64Folder" folder in msi's Directory table + // WiX4 uses "PFiles64" as the value of "DefaultDir" field for "ProgramFiles64Folder" folder in msi's Directory table + // msiexec creates "Program Files/./<App Installation Directory>" from WiX3 msi which translates to "Program Files/<App Installation Directory>" + // msiexec creates "Program Files/PFiles64/<App Installation Directory>" from WiX4 msi + // So for WiX4 msi we need to transform "Program Files/PFiles64/<App Installation Directory>" into "Program Files/<App Installation Directory>" + // + // WiX4 does the same thing for %LocalAppData%. + // + for (var extraPathComponent : List.of("PFiles64", "LocalApp")) { + if (Files.isDirectory(unpackDir.resolve(extraPathComponent))) { + Path installationSubDirectory = getInstallationSubDirectory(cmd); + Path from = Path.of(extraPathComponent).resolve(installationSubDirectory); + Path to = installationSubDirectory; + TKit.trace(String.format("Convert [%s] into [%s] in [%s] directory", from, to, + unpackDir)); + ThrowingRunnable.toRunnable(() -> { + Files.createDirectories(unpackDir.resolve(to).getParent()); + Files.move(unpackDir.resolve(from), unpackDir.resolve(to)); + TKit.deleteDirectoryRecursive(unpackDir.resolve(extraPathComponent)); + }).run(); } - return destinationDir; - }; - return msi; + } + return destinationDir; + } + + static PackageHandlers createExePackageHandlers(boolean createMsiLog) { + return new PackageHandlers(cmd -> installExe(cmd, createMsiLog), WindowsHelper::uninstallExe, Optional.empty()); + } + + private static int runExeInstaller(JPackageCommand cmd, boolean createMsiLog, boolean install) { + cmd.verifyIsOfType(PackageType.WIN_EXE); + Executor exec = new Executor().setExecutable(cmd.outputBundle()); + if (install) { + exec.addArgument("/qn").addArgument("/norestart"); + } else { + exec.addArgument("uninstall"); + } + return runMsiexecWithRetries(exec, configureMsiLogFile(cmd, createMsiLog)); + } + + private static int installExe(JPackageCommand cmd, boolean createMsiLog) { + return runExeInstaller(cmd, createMsiLog, true); + } + + private static void uninstallExe(JPackageCommand cmd) { + if (Files.exists(cmd.outputBundle())) { + runExeInstaller(cmd, false, false); + } else { + configureMsiLogFile(cmd, false); + } } record TransientMsi(Path path) { @@ -204,28 +257,6 @@ static Optional<Path> toShortPath(Path path) { } } - static PackageHandlers createExePackageHandlers() { - BiConsumer<JPackageCommand, Boolean> installExe = (cmd, install) -> { - cmd.verifyIsOfType(PackageType.WIN_EXE); - Executor exec = new Executor().setExecutable(cmd.outputBundle()); - if (install) { - exec.addArgument("/qn").addArgument("/norestart"); - } else { - exec.addArgument("uninstall"); - } - runMsiexecWithRetries(exec); - }; - - PackageHandlers exe = new PackageHandlers(); - exe.installHandler = cmd -> installExe.accept(cmd, true); - exe.uninstallHandler = cmd -> { - if (Files.exists(cmd.outputBundle())) { - installExe.accept(cmd, false); - } - }; - return exe; - } - static void verifyDesktopIntegration(JPackageCommand cmd, String launcherName) { new DesktopIntegrationVerifier(cmd, launcherName); @@ -415,14 +446,12 @@ private void verifyShortcut(Path path, boolean exists) { } private void verifySystemDesktopShortcut(boolean exists) { - Path dir = Path.of(queryRegistryValueCache( - SYSTEM_SHELL_FOLDERS_REGKEY, "Common Desktop")); + Path dir = SpecialFolder.COMMON_DESKTOP.getPath(); verifyShortcut(dir.resolve(desktopShortcutPath), exists); } private void verifyUserLocalDesktopShortcut(boolean exists) { - Path dir = Path.of( - queryRegistryValueCache(USER_SHELL_FOLDERS_REGKEY, "Desktop")); + Path dir = SpecialFolder.USER_DESKTOP.getPath(); verifyShortcut(dir.resolve(desktopShortcutPath), exists); } @@ -445,19 +474,22 @@ private void verifyStartMenuShortcut(Path shortcutsRoot, boolean exists) { Path shortcutPath = shortcutsRoot.resolve(startMenuShortcutPath); verifyShortcut(shortcutPath, exists); if (!exists) { - TKit.assertDirectoryNotEmpty(shortcutPath.getParent()); + final var parentDir = shortcutPath.getParent(); + if (Files.isDirectory(parentDir)) { + TKit.assertDirectoryNotEmpty(parentDir); + } else { + TKit.assertPathExists(parentDir, false); + } } } private void verifySystemStartMenuShortcut(boolean exists) { - verifyStartMenuShortcut(Path.of(queryRegistryValueCache( - SYSTEM_SHELL_FOLDERS_REGKEY, "Common Programs")), exists); + verifyStartMenuShortcut(SpecialFolder.COMMON_START_MENU_PROGRAMS.getPath(), exists); } private void verifyUserLocalStartMenuShortcut(boolean exists) { - verifyStartMenuShortcut(Path.of(queryRegistryValueCache( - USER_SHELL_FOLDERS_REGKEY, "Programs")), exists); + verifyStartMenuShortcut(SpecialFolder.USER_START_MENU_PROGRAMS.getPath(), exists); } private void verifyFileAssociationsRegistry(Path faFile) { @@ -565,16 +597,66 @@ static String queryRegistryValue(String keyPath, String valueName) { return value; } - private static String queryRegistryValueCache(String keyPath, - String valueName) { - String key = String.format("[%s][%s]", keyPath, valueName); - String value = REGISTRY_VALUES.get(key); - if (value == null) { - value = queryRegistryValue(keyPath, valueName); - REGISTRY_VALUES.put(key, value); + // See .NET special folders + private enum SpecialFolderDotNet { + Desktop, + CommonDesktop, + + Programs, + CommonPrograms; + + Path getPath() { + final var str = Executor.of("powershell", "-NoLogo", "-NoProfile", + "-NonInteractive", "-Command", + String.format("[Environment]::GetFolderPath('%s')", name()) + ).saveFirstLineOfOutput().execute().getFirstLineOfOutput(); + + TKit.trace(String.format("Value of .NET special folder '%s' is [%s]", name(), str)); + + return Path.of(str); + } + } + + private record RegValuePath(String keyPath, String valueName) { + RegValuePath { + Objects.requireNonNull(keyPath); + Objects.requireNonNull(valueName); } - return value; + Optional<String> findValue() { + return Optional.ofNullable(queryRegistryValue(keyPath, valueName)); + } + } + + private enum SpecialFolder { + COMMON_START_MENU_PROGRAMS(SYSTEM_SHELL_FOLDERS_REGKEY, "Common Programs", SpecialFolderDotNet.CommonPrograms), + USER_START_MENU_PROGRAMS(USER_SHELL_FOLDERS_REGKEY, "Programs", SpecialFolderDotNet.Programs), + + COMMON_DESKTOP(SYSTEM_SHELL_FOLDERS_REGKEY, "Common Desktop", SpecialFolderDotNet.CommonDesktop), + USER_DESKTOP(USER_SHELL_FOLDERS_REGKEY, "Desktop", SpecialFolderDotNet.Desktop); + + SpecialFolder(String keyPath, String valueName) { + reg = new RegValuePath(keyPath, valueName); + alt = Optional.empty(); + } + + SpecialFolder(String keyPath, String valueName, SpecialFolderDotNet alt) { + reg = new RegValuePath(keyPath, valueName); + this.alt = Optional.of(alt); + } + + Path getPath() { + return CACHE.computeIfAbsent(this, k -> reg.findValue().map(Path::of).orElseGet(() -> { + return alt.map(SpecialFolderDotNet::getPath).orElseThrow(() -> { + return new NoSuchElementException(String.format("Failed to find path to %s folder", name())); + }); + })); + } + + private final RegValuePath reg; + private final Optional<SpecialFolderDotNet> alt; + + private final static Map<SpecialFolder, Path> CACHE = new ConcurrentHashMap<>(); } private static final class ShortPathUtils { @@ -617,7 +699,5 @@ static Path toShortPath(Path path) { private static final String SYSTEM_SHELL_FOLDERS_REGKEY = "HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"; private static final String USER_SHELL_FOLDERS_REGKEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"; - private static final Map<String, String> REGISTRY_VALUES = new HashMap<>(); - private static final int WIN_MAX_PATH = 260; } diff --git a/test/hotspot/jtreg/compiler/ciReplay/TestSAClient.java b/test/jdk/tools/jpackage/resources/fail-os-condition.wxf similarity index 61% rename from test/hotspot/jtreg/compiler/ciReplay/TestSAClient.java rename to test/jdk/tools/jpackage/resources/fail-os-condition.wxf index a5a89d13c50..3b3a79ff2ae 100644 --- a/test/hotspot/jtreg/compiler/ciReplay/TestSAClient.java +++ b/test/jdk/tools/jpackage/resources/fail-os-condition.wxf @@ -1,5 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 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 @@ -20,16 +22,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +--> -/** - * @test - * @bug 8011675 - * @library / /test/lib - * @summary testing of ciReplay with using generated by SA replay.txt - * @requires vm.hasSA & vm.flightRecorder != true & vm.compMode != "Xint" & vm.debug == true & vm.flavor == "client" - * @modules java.base/jdk.internal.misc - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * compiler.ciReplay.SABase client - */ +<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> + <Fragment> + <Condition Message="Not supported on this version of Windows">0</Condition> + <ComponentGroup Id="FragmentOsCondition"/> + </Fragment> +</Wix> diff --git a/test/jdk/tools/jpackage/share/IconTest.java b/test/jdk/tools/jpackage/share/IconTest.java index f5498500c0b..6d84714f28b 100644 --- a/test/jdk/tools/jpackage/share/IconTest.java +++ b/test/jdk/tools/jpackage/share/IconTest.java @@ -52,7 +52,7 @@ * @library /test/jdk/tools/jpackage/helpers * @build jdk.jpackage.test.* * @compile -Xlint:all -Werror IconTest.java - * @run main/othervm/timeout=540 -Xmx512m + * @run main/othervm/timeout=720 -Xmx512m * jdk.jpackage.test.Main * --jpt-run=IconTest */ diff --git a/test/jdk/tools/jpackage/share/InOutPathTest.java b/test/jdk/tools/jpackage/share/InOutPathTest.java index 2d9fa1671de..f5fe3c618ae 100644 --- a/test/jdk/tools/jpackage/share/InOutPathTest.java +++ b/test/jdk/tools/jpackage/share/InOutPathTest.java @@ -50,7 +50,7 @@ * @library /test/jdk/tools/jpackage/helpers * @build jdk.jpackage.test.* * @compile -Xlint:all -Werror InOutPathTest.java - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main * --jpt-run=InOutPathTest */ public final class InOutPathTest { diff --git a/test/jdk/tools/jpackage/share/InstallDirTest.java b/test/jdk/tools/jpackage/share/InstallDirTest.java index 672a435d220..2c14e863910 100644 --- a/test/jdk/tools/jpackage/share/InstallDirTest.java +++ b/test/jdk/tools/jpackage/share/InstallDirTest.java @@ -22,12 +22,20 @@ */ import java.nio.file.Path; +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; import jdk.internal.util.OperatingSystem; -import jdk.jpackage.test.TKit; -import jdk.jpackage.test.PackageTest; -import jdk.jpackage.test.PackageType; import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.Annotations.ParameterSupplier; import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.JPackageStringBundle; +import jdk.jpackage.test.PackageTest; +import jdk.jpackage.test.PackageType; +import jdk.jpackage.test.RunnablePackageTest.Action; +import jdk.jpackage.test.TKit; +import jdk.jpackage.test.TKit.TextStreamVerifier; /** * Test --install-dir parameter. Output of the test should be @@ -57,6 +65,7 @@ * @key jpackagePlatformPackage * @build jdk.jpackage.test.* * @compile -Xlint:all -Werror InstallDirTest.java + * @requires (jpackage.test.SQETest != null) * @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main * --jpt-run=InstallDirTest.testCommon */ @@ -68,10 +77,9 @@ * @key jpackagePlatformPackage * @build jdk.jpackage.test.* * @compile -Xlint:all -Werror InstallDirTest.java - * @requires (os.family == "linux") * @requires (jpackage.test.SQETest == null) - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=InstallDirTest.testLinuxInvalid + * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main + * --jpt-run=InstallDirTest */ public class InstallDirTest { @@ -92,11 +100,6 @@ public static void testCommon(Path installDir) { @Parameter("foo") @Parameter("/opt/foo/.././.") public static void testLinuxInvalid(String installDir) { - testLinuxBad(installDir, "Invalid installation directory"); - } - - private static void testLinuxBad(String installDir, - String errorMessageSubstring) { new PackageTest().configureHelloApp() .setExpectedExitCode(1) .forTypes(PackageType.LINUX) @@ -105,9 +108,120 @@ private static void testLinuxBad(String installDir, cmd.saveConsoleOutput(true); }) .addBundleVerifier((cmd, result) -> { - TKit.assertTextStream(errorMessageSubstring).apply( - result.getOutput().stream()); + cmd.validateOutput(JPackageStringBundle.MAIN.cannedFormattedString("error.invalid-install-dir")); }) .run(); } + + record DmgTestSpec(Path installDir, boolean installDirIgnored, boolean runtimeInstaller) { + + DmgTestSpec { + Objects.requireNonNull(installDir); + } + + static Builder build() { + return new Builder(); + } + + static final class Builder { + + Builder ignoredInstallDir(String v) { + installDir = Path.of(v); + installDirIgnored = true; + return this; + } + + Builder acceptedInstallDir(String v) { + installDir = Path.of(v); + installDirIgnored = false; + return this; + } + + Builder runtimeInstaller() { + runtimeInstaller = true; + return this; + } + + DmgTestSpec create() { + return new DmgTestSpec(installDir, installDirIgnored, runtimeInstaller); + } + + private Path installDir; + private boolean installDirIgnored; + private boolean runtimeInstaller; + } + + @Override + public String toString() { + final var sb = new StringBuilder(); + sb.append(installDir); + if (installDirIgnored) { + sb.append(", ignore"); + } + if (runtimeInstaller) { + sb.append(", runtime"); + } + return sb.toString(); + } + + void run() { + final var test = new PackageTest().forTypes(PackageType.MAC_DMG).ignoreBundleOutputDir(); + if (runtimeInstaller) { + test.addInitializer(cmd -> { + cmd.removeArgumentWithValue("--input"); + }); + } else { + test.configureHelloApp(); + } + + test.addInitializer(JPackageCommand::setFakeRuntime).addInitializer(cmd -> { + cmd.addArguments("--install-dir", installDir); + cmd.validateOutput(createInstallDirWarningVerifier()); + }).run(Action.CREATE_AND_UNPACK); + } + + private TextStreamVerifier createInstallDirWarningVerifier() { + final var verifier = TKit.assertTextStream( + JPackageStringBundle.MAIN.cannedFormattedString("message.install-dir-ignored", defaultDmgInstallDir()).getValue()); + if (installDirIgnored) { + return verifier; + } else { + return verifier.negate(); + } + } + + private String defaultDmgInstallDir() { + if (runtimeInstaller) { + return "/Library/Java/JavaVirtualMachines"; + } else { + return "/Applications"; + } + } + } + + @Test(ifOS = OperatingSystem.MACOS) + @ParameterSupplier + public static void testDmg(DmgTestSpec testSpec) { + testSpec.run(); + } + + public static List<Object[]> testDmg() { + return Stream.of( + DmgTestSpec.build().ignoredInstallDir("/foo"), + DmgTestSpec.build().ignoredInstallDir("/foo/bar"), + DmgTestSpec.build().ignoredInstallDir("/foo").runtimeInstaller(), + DmgTestSpec.build().ignoredInstallDir("/foo/bar").runtimeInstaller(), + + DmgTestSpec.build().ignoredInstallDir("/Library/Java/JavaVirtualMachines"), + DmgTestSpec.build().ignoredInstallDir("/Applications").runtimeInstaller(), + + DmgTestSpec.build().acceptedInstallDir("/Applications"), + DmgTestSpec.build().ignoredInstallDir("/Applications/foo/bar/buz"), + + DmgTestSpec.build().runtimeInstaller().acceptedInstallDir("/Library/Java/JavaVirtualMachines"), + DmgTestSpec.build().runtimeInstaller().ignoredInstallDir("/Library/Java/JavaVirtualMachines/foo/bar/buz") + ).map(DmgTestSpec.Builder::create).map(testSpec -> { + return new Object[] { testSpec }; + }).toList(); + } } diff --git a/test/jdk/tools/jpackage/windows/WinOSConditionTest.java b/test/jdk/tools/jpackage/windows/WinOSConditionTest.java new file mode 100644 index 00000000000..3cf4fdd541c --- /dev/null +++ b/test/jdk/tools/jpackage/windows/WinOSConditionTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2025, 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. + */ + +import java.io.IOException; +import java.nio.file.Files; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.PackageTest; +import jdk.jpackage.test.PackageType; +import jdk.jpackage.test.RunnablePackageTest.Action; +import jdk.jpackage.test.TKit; + +/* + * @test + * @summary jpackage test that installer blocks on Windows of older version + * @library /test/jdk/tools/jpackage/helpers + * @key jpackagePlatformPackage + * @build jdk.jpackage.test.* + * @compile -Xlint:all -Werror WinOSConditionTest.java + * @requires (os.family == "windows") + * @requires (jpackage.test.SQETest == null) + * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * --jpt-run=WinOSConditionTest + */ +public class WinOSConditionTest { + + @Test + public static void test() throws IOException { + // Use custom always failing condition. Installation is expected to fail. + // This way the test covers: + // 1. If jpackage picks custom OS version condition from the resource directory; + // 2. If the installer created by jpackage uses OS version condition. + new PackageTest().ignoreBundleOutputDir() + .forTypes(PackageType.WINDOWS) + .configureHelloApp() + .addInitializer(JPackageCommand::setFakeRuntime) + .addInitializer(cmd -> { + final var resourceDir = TKit.createTempDirectory("resource-dir"); + Files.copy(TKit.TEST_SRC_ROOT.resolve("resources/fail-os-condition.wxf"), resourceDir.resolve("os-condition.wxf")); + // Create a per-user installer to let user without admin privileges install it. + cmd.addArguments("--win-per-user-install", + "--resource-dir", resourceDir.toString()).setFakeRuntime(); + }) + .addUninstallVerifier(cmd -> { + // MSI error code 1603 is generic. + // Dig into the last msi log file for log messages specific to failed condition. + try (final var lines = cmd.winMsiLogFileContents().orElseThrow()) { + TKit.assertTextStream("Doing action: LaunchConditions").predicate(String::endsWith) + .andThen(TKit.assertTextStream("Not supported on this version of Windows").predicate(String::endsWith)).apply(lines); + } + }) + .createMsiLog(true) + .setExpectedInstallExitCode(1603) + // Create, try install the package (installation should fail) and verify it is not installed. + .run(Action.CREATE, Action.INSTALL, Action.VERIFY_UNINSTALL); + } +} diff --git a/test/langtools/jdk/javadoc/doclet/ReproducibleSnippet/ReproducibleSnippetTest.java b/test/langtools/jdk/javadoc/doclet/ReproducibleSnippet/ReproducibleSnippetTest.java new file mode 100644 index 00000000000..5870d1be282 --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/ReproducibleSnippet/ReproducibleSnippetTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8346128 8346659 + * @summary Check that snippet generation is reproducible + * @library /tools/lib ../../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build toolbox.ToolBox javadoc.tester.* + * @run main ReproducibleSnippetTest + */ + +import javadoc.tester.JavadocTester; +import toolbox.ToolBox; + +import java.nio.file.Path; + +public class ReproducibleSnippetTest extends JavadocTester { + ToolBox tb = new ToolBox(); + + public static void main(String... args) throws Exception { + var tester = new ReproducibleSnippetTest(); + tester.runTests(); + } + + @Test + public void test(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, + """ + package p; + public interface One { + /** + * {@code One obj1} + * {@snippet lang = java: + * // @link substring="ab" target="One#ab" : + * obj1.ab(a()); // @link substring="a" target="#a" + *} class comment + */ + int a(); + void ab(int i); + } + """); + javadoc("-d", + "out", + "-sourcepath", + src.toString(), + "p"); + checkExit(Exit.ERROR); + + checkOutput(Output.OUT, true, + "One.java:5: error: snippet link tags:", + "#a", + "One#ab", + "overlap in obj1.ab(a());\n * {@snippet lang = java:\n ^"); + } +} diff --git a/test/langtools/jdk/javadoc/doclet/TestGlobalHtml/TestGlobalHtml.java b/test/langtools/jdk/javadoc/doclet/TestGlobalHtml/TestGlobalHtml.java index 8d2d8e7dd78..a0dd06a2e4a 100644 --- a/test/langtools/jdk/javadoc/doclet/TestGlobalHtml/TestGlobalHtml.java +++ b/test/langtools/jdk/javadoc/doclet/TestGlobalHtml/TestGlobalHtml.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @bug 8322708 * @summary Test to make sure global tags work properly * @library /tools/lib ../../lib - * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @modules jdk.javadoc/jdk.javadoc.internal.tool * @build toolbox.ToolBox javadoc.tester.* * @run main TestGlobalHtml */ diff --git a/test/langtools/jdk/jshell/SnippetEventToStringTest.java b/test/langtools/jdk/jshell/SnippetEventToStringTest.java new file mode 100644 index 00000000000..7d2de387951 --- /dev/null +++ b/test/langtools/jdk/jshell/SnippetEventToStringTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8350808 + * @summary Check for proper formatting of SnippetEvent.toString() + * @run testng SnippetEventToStringTest + */ + +import java.util.Map; +import java.util.List; + +import jdk.jshell.JShell; +import jdk.jshell.SnippetEvent; +import jdk.jshell.execution.LocalExecutionControlProvider; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static org.testng.Assert.assertEquals; + +public class SnippetEventToStringTest { + + @DataProvider(name = "cases") + public String[][] sourceLevels() { + return new String[][] { + { "*", ",causeSnippet=null" }, + { "123", ",value=123" }, + { "throw new Exception(\"foo\");", ",exception=jdk.jshell.EvalException: foo" } + }; + } + + @Test(dataProvider = "cases") + private void verifySnippetEvent(String source, String match) { + try (JShell jsh = JShell.builder().executionEngine(new LocalExecutionControlProvider(), Map.of()).build()) { + List<SnippetEvent> result = jsh.eval(source); + assertEquals(result.size(), 1); + String string = result.get(0).toString(); + if (!string.contains(match)) + throw new AssertionError(String.format("\"%s\" not found in \"%s\"", match, string)); + } + } +} diff --git a/test/lib/jdk/test/lib/jvmti/jvmti_common.hpp b/test/lib/jdk/test/lib/jvmti/jvmti_common.hpp index f16b9fefb99..5efd58e7773 100644 --- a/test/lib/jdk/test/lib/jvmti/jvmti_common.hpp +++ b/test/lib/jdk/test/lib/jvmti/jvmti_common.hpp @@ -283,7 +283,7 @@ get_thread_info(jvmtiEnv *jvmti, JNIEnv* jni, jthread thread) { static jint get_thread_state(jvmtiEnv *jvmti, JNIEnv* jni, jthread thread) { - jint thread_state; + jint thread_state = 0; jvmtiError err = jvmti->GetThreadState(thread, &thread_state); check_jvmti_status(jni, err, "get_thread_state: error in JVMTI GetThreadState call"); return thread_state; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromSliceTest.java b/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromSliceTest.java index c54aa2e0724..58c17f09997 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromSliceTest.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromSliceTest.java @@ -55,10 +55,10 @@ public class AllocFromSliceTest extends CLayouts { @Setup public void setup() { - arr = new byte[1024]; + arr = new byte[size * 2]; Random random = new Random(0); random.nextBytes(arr); - start = random.nextInt(1024 - size); + start = random.nextInt(size); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/net/SocketChannelConnectionSetup.java b/test/micro/org/openjdk/bench/java/net/SocketChannelConnectionSetup.java index dedaaa59229..505e124e43e 100644 --- a/test/micro/org/openjdk/bench/java/net/SocketChannelConnectionSetup.java +++ b/test/micro/org/openjdk/bench/java/net/SocketChannelConnectionSetup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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,11 +23,8 @@ package org.openjdk.bench.java.net; import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; import java.net.StandardProtocolFamily; import java.net.UnixDomainSocketAddress; -import java.nio.channels.ClosedChannelException; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.file.*; @@ -80,7 +77,6 @@ else if (family.equals("unix")) private ServerSocketChannel getInetServerSocketChannel() throws IOException { - InetAddress iaddr = InetAddress.getLoopbackAddress(); return ServerSocketChannel.open().bind(null); } @@ -97,11 +93,11 @@ public void beforeRun() throws IOException { } @TearDown(Level.Trial) - public void afterRun() throws IOException, InterruptedException { + public void afterRun() throws IOException { ssc.close(); if (family.equals("unix")) { - Files.delete(socket); - Files.delete(Path.of(tempDir)); + Files.deleteIfExists(socket); + Files.deleteIfExists(Path.of(tempDir)); } } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/IndexInRangeBenchmark.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/IndexInRangeBenchmark.java index 1875ea00feb..6a068bc4346 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/IndexInRangeBenchmark.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/IndexInRangeBenchmark.java @@ -48,7 +48,7 @@ public class IndexInRangeBenchmark { @Setup(Level.Trial) public void Setup() { - mask = new boolean[512]; + mask = new boolean[size + 64]; } @Benchmark diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/VectorCommutativeOperSharingBenchmark.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/VectorCommutativeOperSharingBenchmark.java index 91851efa4f3..cbb32ceb213 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/VectorCommutativeOperSharingBenchmark.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/VectorCommutativeOperSharingBenchmark.java @@ -32,7 +32,7 @@ @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Thread) -@Fork(jvmArgsPrepend = {"--add-modules=jdk.incubator.vector"}) +@Fork(jvmArgs = {"--add-modules=jdk.incubator.vector"}) public class VectorCommutativeOperSharingBenchmark { @Param({"1024","2048"}) int size;