diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 2aaa061dca3..ffa88a88b29 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -65,6 +65,7 @@ #include "sanitizers/leak.hpp" #include "services/memoryService.hpp" #include "utilities/align.hpp" +#include "utilities/integerCast.hpp" #include "utilities/vmError.hpp" #include "utilities/xmlstream.hpp" #ifdef COMPILER1 @@ -228,9 +229,14 @@ void CodeCache::initialize_heaps() { assert(heap_available(CodeBlobType::MethodNonProfiled), "MethodNonProfiled heap is always available for segmented code heap"); - size_t compiler_buffer_size = 0; - COMPILER1_PRESENT(compiler_buffer_size += CompilationPolicy::c1_count() * Compiler::code_buffer_size()); - COMPILER2_PRESENT(compiler_buffer_size += CompilationPolicy::c2_count() * C2Compiler::initial_code_buffer_size()); + uint64_t compiler_buffer_size_uint64 = 0; + COMPILER1_PRESENT(compiler_buffer_size_uint64 += (uint64_t)CompilationPolicy::c1_count() * Compiler::code_buffer_size()); + COMPILER2_PRESENT(compiler_buffer_size_uint64 += (uint64_t)CompilationPolicy::c2_count() * C2Compiler::initial_code_buffer_size()); + if (compiler_buffer_size_uint64 > (uint64_t)CODE_CACHE_SIZE_LIMIT) { + err_msg msg("CICompilerCount is too large (%" PRIdPTR "): compiler buffer size exceeds the CodeCache size limit", CICompilerCount); + vm_exit_during_initialization(msg); + } + size_t compiler_buffer_size = integer_cast_permit_tautology(compiler_buffer_size_uint64); if (!non_nmethod.set) { non_nmethod.size += compiler_buffer_size; diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp index 36eece6f013..ebcf6b4e14e 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp @@ -61,9 +61,21 @@ JVMFlag::Error CICompilerCountConstraintFunc(intx value, bool verbose) { "at least %d \n", value, min_number_of_compiler_threads); return JVMFlag::VIOLATES_CONSTRAINT; - } else { - return JVMFlag::SUCCESS; } + + // Limit CICompilerCount to a reasonable value in product builds. +#ifndef ASSERT + int active_processor_count = os::active_processor_count(); + // On a single-CPU machine we still can run C1 and C2 compiler threads, so allow up to 2x for tiered. + int reasonable_threads_num = CompilerConfig::is_tiered() ? active_processor_count * 2 : active_processor_count; + if (value > reasonable_threads_num) { + JVMFlag::printError(verbose, "CICompilerCount is too large (%" PRIdPTR ") for current active processor count %d \n", + CICompilerCount, active_processor_count); + return JVMFlag::VIOLATES_CONSTRAINT; + } +#endif + + return JVMFlag::SUCCESS; } JVMFlag::Error AllocatePrefetchStepSizeConstraintFunc(int value, bool verbose) { diff --git a/test/hotspot/jtreg/compiler/arguments/CheckCICompilerCount.java b/test/hotspot/jtreg/compiler/arguments/CheckCICompilerCount.java index 6f137e20261..ef9389542c4 100644 --- a/test/hotspot/jtreg/compiler/arguments/CheckCICompilerCount.java +++ b/test/hotspot/jtreg/compiler/arguments/CheckCICompilerCount.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * 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 CheckCheckCICompilerCount - * @bug 8130858 8132525 8162881 + * @bug 8130858 8132525 8162881 8379396 * @summary Check that correct range of values for CICompilerCount are allowed depending on whether tiered is enabled or not * @library /test/lib / * @requires vm.flagless @@ -186,7 +186,25 @@ public class CheckCICompilerCount { 0 }; - private static void verifyValidOption(String[] arguments, String expected_output, int exit, boolean tiered) throws Exception { + private static final String[][] INVALID_ARGUMENTS = { + { + "-XX:CICompilerCount=100M", + "-version" + }, + }; + + private static final String[] INVALID_EXPECTED_OUTPUTS = { + // "CICompilerCount is too large" is a common prefix for two different messages: + // - product build: flag constraint fires early: "CICompilerCount is too large for current active processor count N" + // - debug build: CodeCache overflow guard fires: "CICompilerCount is too large: compiler buffer size exceeds the CodeCache size limit" + "CICompilerCount is too large" + }; + + private static final int[] INVALID_EXIT = { + 1, + }; + + private static void verifyOptionBehavior(String[] arguments, String expected_output, int exit, boolean tiered) throws Exception { ProcessBuilder pb; OutputAnalyzer out; @@ -215,11 +233,15 @@ public class CheckCICompilerCount { } for (int i = 0; i < NON_TIERED_ARGUMENTS.length; i++) { - verifyValidOption(NON_TIERED_ARGUMENTS[i], NON_TIERED_EXPECTED_OUTPUTS[i], NON_TIERED_EXIT[i], false); + verifyOptionBehavior(NON_TIERED_ARGUMENTS[i], NON_TIERED_EXPECTED_OUTPUTS[i], NON_TIERED_EXIT[i], false); } for (int i = 0; i < TIERED_ARGUMENTS.length; i++) { - verifyValidOption(TIERED_ARGUMENTS[i], TIERED_EXPECTED_OUTPUTS[i], TIERED_EXIT[i], true); + verifyOptionBehavior(TIERED_ARGUMENTS[i], TIERED_EXPECTED_OUTPUTS[i], TIERED_EXIT[i], true); + } + + for (int i = 0; i < INVALID_ARGUMENTS.length; i++) { + verifyOptionBehavior(INVALID_ARGUMENTS[i], INVALID_EXPECTED_OUTPUTS[i], INVALID_EXIT[i], true); } } } diff --git a/test/hotspot/jtreg/compiler/startup/SmallCodeCacheStartup.java b/test/hotspot/jtreg/compiler/startup/SmallCodeCacheStartup.java index b3b92afa0d1..8e0d039ea52 100644 --- a/test/hotspot/jtreg/compiler/startup/SmallCodeCacheStartup.java +++ b/test/hotspot/jtreg/compiler/startup/SmallCodeCacheStartup.java @@ -52,8 +52,8 @@ public class SmallCodeCacheStartup { try { analyzer.shouldHaveExitValue(0); } catch (RuntimeException e) { - // Error occurred during initialization, did we run out of adapter space? - assertTrue(analyzer.getOutput().contains("VirtualMachineError: Out of space in CodeCache"), + // Error occurred during initialization + assertTrue(analyzer.getOutput().contains("CICompilerCount is too large"), "Expected VirtualMachineError"); }