8028391: Make the Min/MaxHeapFreeRatio flags manageable
Made the flags Min- and MaxHeapFreeRatio manageable, and implemented support for these flags in ParallalGC. Reviewed-by: sla, mgerdin, brutisso
This commit is contained in:
parent
9d4f3dfd4f
commit
5301534dc3
@ -1575,8 +1575,6 @@ void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) {
|
||||
void
|
||||
G1CollectedHeap::
|
||||
resize_if_necessary_after_full_collection(size_t word_size) {
|
||||
assert(MinHeapFreeRatio <= MaxHeapFreeRatio, "sanity check");
|
||||
|
||||
// Include the current allocation, if any, and bytes that will be
|
||||
// pre-allocated to support collections, as "used".
|
||||
const size_t used_after_gc = used();
|
||||
|
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
|
||||
#include "gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp"
|
||||
#include "gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.hpp"
|
||||
#include "gc_implementation/parallelScavenge/psScavenge.hpp"
|
||||
@ -76,6 +77,38 @@ PSAdaptiveSizePolicy::PSAdaptiveSizePolicy(size_t init_eden_size,
|
||||
_old_gen_policy_is_ready = false;
|
||||
}
|
||||
|
||||
size_t PSAdaptiveSizePolicy::calculate_free_based_on_live(size_t live, uintx ratio_as_percentage) {
|
||||
// We want to calculate how much free memory there can be based on the
|
||||
// amount of live data currently in the old gen. Using the formula:
|
||||
// ratio * (free + live) = free
|
||||
// Some equation solving later we get:
|
||||
// free = (live * ratio) / (1 - ratio)
|
||||
|
||||
const double ratio = ratio_as_percentage / 100.0;
|
||||
const double ratio_inverse = 1.0 - ratio;
|
||||
const double tmp = live * ratio;
|
||||
size_t free = (size_t)(tmp / ratio_inverse);
|
||||
|
||||
return free;
|
||||
}
|
||||
|
||||
size_t PSAdaptiveSizePolicy::calculated_old_free_size_in_bytes() const {
|
||||
size_t free_size = (size_t)(_promo_size + avg_promoted()->padded_average());
|
||||
size_t live = ParallelScavengeHeap::heap()->old_gen()->used_in_bytes();
|
||||
|
||||
if (MinHeapFreeRatio != 0) {
|
||||
size_t min_free = calculate_free_based_on_live(live, MinHeapFreeRatio);
|
||||
free_size = MAX2(free_size, min_free);
|
||||
}
|
||||
|
||||
if (MaxHeapFreeRatio != 100) {
|
||||
size_t max_free = calculate_free_based_on_live(live, MaxHeapFreeRatio);
|
||||
free_size = MIN2(max_free, free_size);
|
||||
}
|
||||
|
||||
return free_size;
|
||||
}
|
||||
|
||||
void PSAdaptiveSizePolicy::major_collection_begin() {
|
||||
// Update the interval time
|
||||
_major_timer.stop();
|
||||
@ -1292,3 +1325,18 @@ bool PSAdaptiveSizePolicy::print_adaptive_size_policy_on(outputStream* st)
|
||||
st,
|
||||
PSScavenge::tenuring_threshold());
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
||||
void TestOldFreeSpaceCalculation_test() {
|
||||
assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(100, 20) == 25, "Calculation of free memory failed");
|
||||
assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(100, 50) == 100, "Calculation of free memory failed");
|
||||
assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(100, 60) == 150, "Calculation of free memory failed");
|
||||
assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(100, 75) == 300, "Calculation of free memory failed");
|
||||
assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(400, 20) == 100, "Calculation of free memory failed");
|
||||
assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(400, 50) == 400, "Calculation of free memory failed");
|
||||
assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(400, 60) == 600, "Calculation of free memory failed");
|
||||
assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(400, 75) == 1200, "Calculation of free memory failed");
|
||||
}
|
||||
|
||||
#endif /* !PRODUCT */
|
||||
|
@ -240,7 +240,6 @@ class PSAdaptiveSizePolicy : public AdaptiveSizePolicy {
|
||||
void major_collection_begin();
|
||||
void major_collection_end(size_t amount_live, GCCause::Cause gc_cause);
|
||||
|
||||
//
|
||||
void tenured_allocation(size_t size) {
|
||||
_avg_pretenured->sample(size);
|
||||
}
|
||||
@ -248,9 +247,9 @@ class PSAdaptiveSizePolicy : public AdaptiveSizePolicy {
|
||||
// Accessors
|
||||
// NEEDS_CLEANUP should use sizes.hpp
|
||||
|
||||
size_t calculated_old_free_size_in_bytes() const {
|
||||
return (size_t)(_promo_size + avg_promoted()->padded_average());
|
||||
}
|
||||
static size_t calculate_free_based_on_live(size_t live, uintx ratio_as_percentage);
|
||||
|
||||
size_t calculated_old_free_size_in_bytes() const;
|
||||
|
||||
size_t average_old_live_in_bytes() const {
|
||||
return (size_t) avg_old_live()->average();
|
||||
|
@ -529,8 +529,19 @@ bool PSScavenge::invoke_no_policy() {
|
||||
counters->update_survivor_overflowed(_survivor_overflow);
|
||||
}
|
||||
|
||||
size_t max_young_size = young_gen->max_size();
|
||||
|
||||
// Deciding a free ratio in the young generation is tricky, so if
|
||||
// MinHeapFreeRatio or MaxHeapFreeRatio are in use (implicating
|
||||
// that the old generation size may have been limited because of them) we
|
||||
// should then limit our young generation size using NewRatio to have it
|
||||
// follow the old generation size.
|
||||
if (MinHeapFreeRatio != 0 || MaxHeapFreeRatio != 100) {
|
||||
max_young_size = MIN2(old_gen->capacity_in_bytes() / NewRatio, young_gen->max_size());
|
||||
}
|
||||
|
||||
size_t survivor_limit =
|
||||
size_policy->max_survivor_size(young_gen->max_size());
|
||||
size_policy->max_survivor_size(max_young_size);
|
||||
_tenuring_threshold =
|
||||
size_policy->compute_survivor_space_size_and_threshold(
|
||||
_survivor_overflow,
|
||||
@ -553,8 +564,7 @@ bool PSScavenge::invoke_no_policy() {
|
||||
// Do call at minor collections?
|
||||
// Don't check if the size_policy is ready at this
|
||||
// level. Let the size_policy check that internally.
|
||||
if (UseAdaptiveSizePolicy &&
|
||||
UseAdaptiveGenerationSizePolicyAtMinorCollection &&
|
||||
if (UseAdaptiveGenerationSizePolicyAtMinorCollection &&
|
||||
((gc_cause != GCCause::_java_lang_system_gc) ||
|
||||
UseAdaptiveSizePolicyWithSystemGC)) {
|
||||
|
||||
@ -568,7 +578,7 @@ bool PSScavenge::invoke_no_policy() {
|
||||
size_t eden_live = young_gen->eden_space()->used_in_bytes();
|
||||
size_t cur_eden = young_gen->eden_space()->capacity_in_bytes();
|
||||
size_t max_old_gen_size = old_gen->max_gen_size();
|
||||
size_t max_eden_size = young_gen->max_size() -
|
||||
size_t max_eden_size = max_young_size -
|
||||
young_gen->from_space()->capacity_in_bytes() -
|
||||
young_gen->to_space()->capacity_in_bytes();
|
||||
|
||||
|
@ -127,7 +127,7 @@ class PSYoungGen : public CHeapObj<mtGC> {
|
||||
void adjust_pointers();
|
||||
void compact();
|
||||
|
||||
// Called during/after gc
|
||||
// Called during/after GC
|
||||
void swap_spaces();
|
||||
|
||||
// Resize generation using suggested free space size and survivor size
|
||||
@ -146,14 +146,14 @@ class PSYoungGen : public CHeapObj<mtGC> {
|
||||
size_t free_in_words() const;
|
||||
|
||||
// The max this generation can grow to
|
||||
size_t max_size() const { return _reserved.byte_size(); }
|
||||
size_t max_size() const { return _reserved.byte_size(); }
|
||||
|
||||
// The max this generation can grow to if the boundary between
|
||||
// the generations are allowed to move.
|
||||
size_t gen_size_limit() const { return _max_gen_size; }
|
||||
|
||||
bool is_maximal_no_gc() const {
|
||||
return true; // never expands except at a GC
|
||||
return true; // Never expands except at a GC
|
||||
}
|
||||
|
||||
// Allocation
|
||||
|
@ -5061,6 +5061,7 @@ void TestVirtualSpace_test();
|
||||
void TestMetaspaceAux_test();
|
||||
void TestMetachunk_test();
|
||||
void TestVirtualSpaceNode_test();
|
||||
void TestOldFreeSpaceCalculation_test();
|
||||
#if INCLUDE_ALL_GCS
|
||||
void TestG1BiasedArray_test();
|
||||
#endif
|
||||
@ -5081,6 +5082,7 @@ void execute_internal_vm_tests() {
|
||||
run_unit_test(QuickSort::test_quick_sort());
|
||||
run_unit_test(AltHashing::test_alt_hash());
|
||||
run_unit_test(test_loggc_filename());
|
||||
run_unit_test(TestOldFreeSpaceCalculation_test());
|
||||
#if INCLUDE_VM_STRUCTS
|
||||
run_unit_test(VMStructs::test());
|
||||
#endif
|
||||
|
@ -1569,6 +1569,16 @@ void Arguments::set_parallel_gc_flags() {
|
||||
vm_exit(1);
|
||||
}
|
||||
|
||||
if (UseAdaptiveSizePolicy) {
|
||||
// We don't want to limit adaptive heap sizing's freedom to adjust the heap
|
||||
// unless the user actually sets these flags.
|
||||
if (FLAG_IS_DEFAULT(MinHeapFreeRatio)) {
|
||||
FLAG_SET_DEFAULT(MinHeapFreeRatio, 0);
|
||||
}
|
||||
if (FLAG_IS_DEFAULT(MaxHeapFreeRatio)) {
|
||||
FLAG_SET_DEFAULT(MaxHeapFreeRatio, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// If InitialSurvivorRatio or MinSurvivorRatio were not specified, but the
|
||||
// SurvivorRatio has been set, reset their default values to SurvivorRatio +
|
||||
@ -1844,7 +1854,7 @@ bool Arguments::verify_min_value(intx val, intx min, const char* name) {
|
||||
}
|
||||
|
||||
bool Arguments::verify_percentage(uintx value, const char* name) {
|
||||
if (value <= 100) {
|
||||
if (is_percentage(value)) {
|
||||
return true;
|
||||
}
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
@ -1932,6 +1942,34 @@ bool is_filename_valid(const char *file_name) {
|
||||
return count_p < 2 && count_t < 2;
|
||||
}
|
||||
|
||||
bool Arguments::verify_MinHeapFreeRatio(FormatBuffer<80>& err_msg, uintx min_heap_free_ratio) {
|
||||
if (!is_percentage(min_heap_free_ratio)) {
|
||||
err_msg.print("MinHeapFreeRatio must have a value between 0 and 100");
|
||||
return false;
|
||||
}
|
||||
if (min_heap_free_ratio > MaxHeapFreeRatio) {
|
||||
err_msg.print("MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or "
|
||||
"equal to MaxHeapFreeRatio (" UINTX_FORMAT ")", min_heap_free_ratio,
|
||||
MaxHeapFreeRatio);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Arguments::verify_MaxHeapFreeRatio(FormatBuffer<80>& err_msg, uintx max_heap_free_ratio) {
|
||||
if (!is_percentage(max_heap_free_ratio)) {
|
||||
err_msg.print("MaxHeapFreeRatio must have a value between 0 and 100");
|
||||
return false;
|
||||
}
|
||||
if (max_heap_free_ratio < MinHeapFreeRatio) {
|
||||
err_msg.print("MaxHeapFreeRatio (" UINTX_FORMAT ") must be greater than or "
|
||||
"equal to MinHeapFreeRatio (" UINTX_FORMAT ")", max_heap_free_ratio,
|
||||
MinHeapFreeRatio);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check consistency of GC selection
|
||||
bool Arguments::check_gc_consistency() {
|
||||
check_gclog_consistency();
|
||||
@ -2037,8 +2075,6 @@ bool Arguments::check_vm_args_consistency() {
|
||||
status = status && verify_interval(AdaptiveSizePolicyWeight, 0, 100,
|
||||
"AdaptiveSizePolicyWeight");
|
||||
status = status && verify_percentage(ThresholdTolerance, "ThresholdTolerance");
|
||||
status = status && verify_percentage(MinHeapFreeRatio, "MinHeapFreeRatio");
|
||||
status = status && verify_percentage(MaxHeapFreeRatio, "MaxHeapFreeRatio");
|
||||
|
||||
// Divide by bucket size to prevent a large size from causing rollover when
|
||||
// calculating amount of memory needed to be allocated for the String table.
|
||||
@ -2048,15 +2084,19 @@ bool Arguments::check_vm_args_consistency() {
|
||||
status = status && verify_interval(SymbolTableSize, minimumSymbolTableSize,
|
||||
(max_uintx / SymbolTable::bucket_size()), "SymbolTable size");
|
||||
|
||||
if (MinHeapFreeRatio > MaxHeapFreeRatio) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or "
|
||||
"equal to MaxHeapFreeRatio (" UINTX_FORMAT ")\n",
|
||||
MinHeapFreeRatio, MaxHeapFreeRatio);
|
||||
status = false;
|
||||
{
|
||||
// Using "else if" below to avoid printing two error messages if min > max.
|
||||
// This will also prevent us from reporting both min>100 and max>100 at the
|
||||
// same time, but that is less annoying than printing two identical errors IMHO.
|
||||
FormatBuffer<80> err_msg("");
|
||||
if (!verify_MinHeapFreeRatio(err_msg, MinHeapFreeRatio)) {
|
||||
jio_fprintf(defaultStream::error_stream(), "%s\n", err_msg.buffer());
|
||||
status = false;
|
||||
} else if (!verify_MaxHeapFreeRatio(err_msg, MaxHeapFreeRatio)) {
|
||||
jio_fprintf(defaultStream::error_stream(), "%s\n", err_msg.buffer());
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
// Keeping the heap 100% free is hard ;-) so limit it to 99%.
|
||||
MinHeapFreeRatio = MIN2(MinHeapFreeRatio, (uintx) 99);
|
||||
|
||||
// Min/MaxMetaspaceFreeRatio
|
||||
status = status && verify_percentage(MinMetaspaceFreeRatio, "MinMetaspaceFreeRatio");
|
||||
@ -2689,7 +2729,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
} else if (match_option(option, "-Xmaxf", &tail)) {
|
||||
char* err;
|
||||
int maxf = (int)(strtod(tail, &err) * 100);
|
||||
if (*err != '\0' || maxf < 0 || maxf > 100) {
|
||||
if (*err != '\0' || *tail == '\0' || maxf < 0 || maxf > 100) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"Bad max heap free percentage size: %s\n",
|
||||
option->optionString);
|
||||
@ -2701,7 +2741,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
} else if (match_option(option, "-Xminf", &tail)) {
|
||||
char* err;
|
||||
int minf = (int)(strtod(tail, &err) * 100);
|
||||
if (*err != '\0' || minf < 0 || minf > 100) {
|
||||
if (*err != '\0' || *tail == '\0' || minf < 0 || minf > 100) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"Bad min heap free percentage size: %s\n",
|
||||
option->optionString);
|
||||
@ -3646,9 +3686,9 @@ jint Arguments::apply_ergo() {
|
||||
// Set per-collector flags
|
||||
if (UseParallelGC || UseParallelOldGC) {
|
||||
set_parallel_gc_flags();
|
||||
} else if (UseConcMarkSweepGC) { // should be done before ParNew check below
|
||||
} else if (UseConcMarkSweepGC) { // Should be done before ParNew check below
|
||||
set_cms_and_parnew_gc_flags();
|
||||
} else if (UseParNewGC) { // skipped if CMS is set above
|
||||
} else if (UseParNewGC) { // Skipped if CMS is set above
|
||||
set_parnew_gc_flags();
|
||||
} else if (UseG1GC) {
|
||||
set_g1_gc_flags();
|
||||
@ -3662,6 +3702,10 @@ jint Arguments::apply_ergo() {
|
||||
" using -XX:ParallelGCThreads=N");
|
||||
}
|
||||
}
|
||||
if (MinHeapFreeRatio == 100) {
|
||||
// Keeping the heap 100% free is hard ;-) so limit it to 99%.
|
||||
FLAG_SET_ERGO(uintx, MinHeapFreeRatio, 99);
|
||||
}
|
||||
#else // INCLUDE_ALL_GCS
|
||||
assert(verify_serial_gc_flags(), "SerialGC unset");
|
||||
#endif // INCLUDE_ALL_GCS
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "runtime/java.hpp"
|
||||
#include "runtime/perfData.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/top.hpp"
|
||||
|
||||
// Arguments parses the command line and recognizes options
|
||||
@ -370,11 +371,16 @@ class Arguments : AllStatic {
|
||||
static jint parse_vm_init_args(const JavaVMInitArgs* args);
|
||||
static jint parse_each_vm_init_arg(const JavaVMInitArgs* args, SysClassPath* scp_p, bool* scp_assembly_required_p, Flag::Flags origin);
|
||||
static jint finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_required);
|
||||
static bool is_bad_option(const JavaVMOption* option, jboolean ignore,
|
||||
const char* option_type);
|
||||
static bool is_bad_option(const JavaVMOption* option, jboolean ignore, const char* option_type);
|
||||
|
||||
static bool is_bad_option(const JavaVMOption* option, jboolean ignore) {
|
||||
return is_bad_option(option, ignore, NULL);
|
||||
}
|
||||
|
||||
static bool is_percentage(uintx val) {
|
||||
return val <= 100;
|
||||
}
|
||||
|
||||
static bool verify_interval(uintx val, uintx min,
|
||||
uintx max, const char* name);
|
||||
static bool verify_min_value(intx val, intx min, const char* name);
|
||||
@ -440,6 +446,15 @@ class Arguments : AllStatic {
|
||||
static jint apply_ergo();
|
||||
// Adjusts the arguments after the OS have adjusted the arguments
|
||||
static jint adjust_after_os();
|
||||
|
||||
// Verifies that the given value will fit as a MinHeapFreeRatio. If not, an error
|
||||
// message is returned in the provided buffer.
|
||||
static bool verify_MinHeapFreeRatio(FormatBuffer<80>& err_msg, uintx min_heap_free_ratio);
|
||||
|
||||
// Verifies that the given value will fit as a MaxHeapFreeRatio. If not, an error
|
||||
// message is returned in the provided buffer.
|
||||
static bool verify_MaxHeapFreeRatio(FormatBuffer<80>& err_msg, uintx max_heap_free_ratio);
|
||||
|
||||
// Check for consistency in the selection of the garbage collector.
|
||||
static bool check_gc_consistency();
|
||||
static void check_deprecated_gcs();
|
||||
|
@ -3135,15 +3135,15 @@ class CommandLineFlags {
|
||||
"Maximum size of class area in Metaspace when compressed " \
|
||||
"class pointers are used") \
|
||||
\
|
||||
product(uintx, MinHeapFreeRatio, 40, \
|
||||
manageable(uintx, MinHeapFreeRatio, 40, \
|
||||
"The minimum percentage of heap free after GC to avoid expansion."\
|
||||
" For most GCs this applies to the old generation. In G1 it" \
|
||||
" applies to the whole heap. Not supported by ParallelGC.") \
|
||||
" For most GCs this applies to the old generation. In G1 and" \
|
||||
" ParallelGC it applies to the whole heap.") \
|
||||
\
|
||||
product(uintx, MaxHeapFreeRatio, 70, \
|
||||
manageable(uintx, MaxHeapFreeRatio, 70, \
|
||||
"The maximum percentage of heap free after GC to avoid shrinking."\
|
||||
" For most GCs this applies to the old generation. In G1 it" \
|
||||
" applies to the whole heap. Not supported by ParallelGC.") \
|
||||
" For most GCs this applies to the old generation. In G1 and" \
|
||||
" ParallelGC it applies to the whole heap.") \
|
||||
\
|
||||
product(intx, SoftRefLRUPolicyMSPerMB, 1000, \
|
||||
"Number of milliseconds per MB of free space in the heap") \
|
||||
|
@ -282,6 +282,20 @@ static jint set_uintx_flag(const char* name, AttachOperation* op, outputStream*
|
||||
return JNI_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(name, "MaxHeapFreeRatio", 17) == 0) {
|
||||
FormatBuffer<80> err_msg("");
|
||||
if (!Arguments::verify_MaxHeapFreeRatio(err_msg, value)) {
|
||||
out->print_cr(err_msg.buffer());
|
||||
return JNI_ERR;
|
||||
}
|
||||
} else if (strncmp(name, "MinHeapFreeRatio", 17) == 0) {
|
||||
FormatBuffer<80> err_msg("");
|
||||
if (!Arguments::verify_MinHeapFreeRatio(err_msg, value)) {
|
||||
out->print_cr(err_msg.buffer());
|
||||
return JNI_ERR;
|
||||
}
|
||||
}
|
||||
bool res = CommandLineFlags::uintxAtPut((char*)name, &value, Flag::ATTACH_ON_DEMAND);
|
||||
if (! res) {
|
||||
out->print_cr("setting flag %s failed", name);
|
||||
|
@ -1833,6 +1833,18 @@ JVM_ENTRY(void, jmm_SetVMGlobal(JNIEnv *env, jstring flag_name, jvalue new_value
|
||||
succeed = CommandLineFlags::intxAtPut(name, &ivalue, Flag::MANAGEMENT);
|
||||
} else if (flag->is_uintx()) {
|
||||
uintx uvalue = (uintx)new_value.j;
|
||||
|
||||
if (strncmp(name, "MaxHeapFreeRatio", 17) == 0) {
|
||||
FormatBuffer<80> err_msg("");
|
||||
if (!Arguments::verify_MaxHeapFreeRatio(err_msg, uvalue)) {
|
||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), err_msg.buffer());
|
||||
}
|
||||
} else if (strncmp(name, "MinHeapFreeRatio", 17) == 0) {
|
||||
FormatBuffer<80> err_msg("");
|
||||
if (!Arguments::verify_MinHeapFreeRatio(err_msg, uvalue)) {
|
||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), err_msg.buffer());
|
||||
}
|
||||
}
|
||||
succeed = CommandLineFlags::uintxAtPut(name, &uvalue, Flag::MANAGEMENT);
|
||||
} else if (flag->is_uint64_t()) {
|
||||
uint64_t uvalue = (uint64_t)new_value.j;
|
||||
|
Loading…
x
Reference in New Issue
Block a user