diff --git a/src/share/vm/code/codeCache.cpp b/src/share/vm/code/codeCache.cpp index f7be307b254f71a0a03ffd199dc446683435f11a..44d65e23345f175831ec315fce0c0df5c3c8d8f6 100644 --- a/src/share/vm/code/codeCache.cpp +++ b/src/share/vm/code/codeCache.cpp @@ -622,6 +622,15 @@ address CodeCache::last_address() { return (address)_heap->high(); } +/** + * Returns the reverse free ratio. E.g., if 25% (1/4) of the code cache + * is free, reverse_free_ratio() returns 4. + */ +double CodeCache::reverse_free_ratio() { + double unallocated_capacity = (double)(CodeCache::unallocated_capacity() - CodeCacheMinimumFreeSpace); + double max_capacity = (double)CodeCache::max_capacity(); + return max_capacity / unallocated_capacity; +} void icache_init(); diff --git a/src/share/vm/code/codeCache.hpp b/src/share/vm/code/codeCache.hpp index 38799019b8fe91ddc69bf7f2d7474ba2419565cf..3dde92702e34c1b3ec725f21f43d4261e3b69243 100644 --- a/src/share/vm/code/codeCache.hpp +++ b/src/share/vm/code/codeCache.hpp @@ -163,6 +163,7 @@ class CodeCache : AllStatic { static size_t max_capacity() { return _heap->max_capacity(); } static size_t unallocated_capacity() { return _heap->unallocated_capacity(); } static bool needs_flushing() { return unallocated_capacity() < CodeCacheFlushingMinimumFreeSpace; } + static double reverse_free_ratio(); static bool needs_cache_clean() { return _needs_cache_clean; } static void set_needs_cache_clean(bool v) { _needs_cache_clean = v; } diff --git a/src/share/vm/runtime/advancedThresholdPolicy.cpp b/src/share/vm/runtime/advancedThresholdPolicy.cpp index 81c2b74739d8dbf68407cdf81255fc14167d7840..7d72ca7f3eaa01264f186187c5192e80209d36b3 100644 --- a/src/share/vm/runtime/advancedThresholdPolicy.cpp +++ b/src/share/vm/runtime/advancedThresholdPolicy.cpp @@ -68,7 +68,7 @@ void AdvancedThresholdPolicy::initialize() { } #endif - + set_increase_threshold_at_ratio(); set_start_time(os::javaTimeMillis()); } @@ -205,6 +205,17 @@ double AdvancedThresholdPolicy::threshold_scale(CompLevel level, int feedback_k) double queue_size = CompileBroker::queue_size(level); int comp_count = compiler_count(level); double k = queue_size / (feedback_k * comp_count) + 1; + + // Increase C1 compile threshold when the code cache is filled more + // than specified by IncreaseFirstTierCompileThresholdAt percentage. + // The main intention is to keep enough free space for C2 compiled code + // to achieve peak performance if the code cache is under stress. + if ((TieredStopAtLevel == CompLevel_full_optimization) && (level != CompLevel_full_optimization)) { + double current_reverse_free_ratio = CodeCache::reverse_free_ratio(); + if (current_reverse_free_ratio > _increase_threshold_at_ratio) { + k *= exp(current_reverse_free_ratio - _increase_threshold_at_ratio); + } + } return k; } diff --git a/src/share/vm/runtime/advancedThresholdPolicy.hpp b/src/share/vm/runtime/advancedThresholdPolicy.hpp index 90a1ca174b9cc43e4f699a8f58c3fcc1053c5b40..4ab7653581b505f854d98f0016002207ee9b9f9b 100644 --- a/src/share/vm/runtime/advancedThresholdPolicy.hpp +++ b/src/share/vm/runtime/advancedThresholdPolicy.hpp @@ -201,9 +201,12 @@ class AdvancedThresholdPolicy : public SimpleThresholdPolicy { // Is method profiled enough? bool is_method_profiled(Method* method); + double _increase_threshold_at_ratio; + protected: void print_specific(EventType type, methodHandle mh, methodHandle imh, int bci, CompLevel level); + void set_increase_threshold_at_ratio() { _increase_threshold_at_ratio = 100 / (100 - (double)IncreaseFirstTierCompileThresholdAt); } void set_start_time(jlong t) { _start_time = t; } jlong start_time() const { return _start_time; } diff --git a/src/share/vm/runtime/arguments.cpp b/src/share/vm/runtime/arguments.cpp index b1cfb3cc3627f48d0951272babcba63b19382e94..83f4660a0c7b5a2082a7fbcc02370b8e08fb7871 100644 --- a/src/share/vm/runtime/arguments.cpp +++ b/src/share/vm/runtime/arguments.cpp @@ -2629,6 +2629,16 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, return JNI_EINVAL; } FLAG_SET_CMDLINE(uintx, ReservedCodeCacheSize, (uintx)long_ReservedCodeCacheSize); + //-XX:IncreaseFirstTierCompileThresholdAt= + } else if (match_option(option, "-XX:IncreaseFirstTierCompileThresholdAt=", &tail)) { + uintx uint_IncreaseFirstTierCompileThresholdAt = 0; + if (!parse_uintx(tail, &uint_IncreaseFirstTierCompileThresholdAt, 0) || uint_IncreaseFirstTierCompileThresholdAt > 99) { + jio_fprintf(defaultStream::error_stream(), + "Invalid value for IncreaseFirstTierCompileThresholdAt: %s. Should be between 0 and 99.\n", + option->optionString); + return JNI_EINVAL; + } + FLAG_SET_CMDLINE(uintx, IncreaseFirstTierCompileThresholdAt, (uintx)uint_IncreaseFirstTierCompileThresholdAt); // -green } else if (match_option(option, "-green", &tail)) { jio_fprintf(defaultStream::error_stream(), diff --git a/src/share/vm/runtime/globals.hpp b/src/share/vm/runtime/globals.hpp index 1131c8e103b123468299e823fe75f364941949ea..aec1736a43ca39dba2c230265ba1976d3ed03648 100644 --- a/src/share/vm/runtime/globals.hpp +++ b/src/share/vm/runtime/globals.hpp @@ -3436,6 +3436,10 @@ class CommandLineFlags { "Start profiling in interpreter if the counters exceed tier 3" \ "thresholds by the specified percentage") \ \ + product(uintx, IncreaseFirstTierCompileThresholdAt, 50, \ + "Increase the compile threshold for C1 compilation if the code" \ + "cache is filled by the specified percentage.") \ + \ product(intx, TieredRateUpdateMinTime, 1, \ "Minimum rate sampling interval (in milliseconds)") \ \