Skip to content
Permalink
Browse files
8262328: Templatize JVMFlag boilerplate access methods
Reviewed-by: dholmes, gziemski
  • Loading branch information
iklam committed Apr 10, 2021
1 parent c15680e commit 627ad9fe22a153410c14d0b2061bb7dee2c300af
Showing 10 changed files with 197 additions and 237 deletions.
@@ -190,7 +190,7 @@ bool JVMCIGlobals::enable_jvmci_product_mode(JVMFlagOrigin origin) {

bool value = true;
JVMFlag *jvmciEnableFlag = JVMFlag::find_flag("EnableJVMCIProduct");
if (JVMFlagAccess::boolAtPut(jvmciEnableFlag, &value, origin) != JVMFlag::SUCCESS) {
if (JVMFlagAccess::set_bool(jvmciEnableFlag, &value, origin) != JVMFlag::SUCCESS) {
return false;
}

@@ -1249,58 +1249,38 @@ WB_ENTRY(jobject, WB_GetBooleanVMFlag(JNIEnv* env, jobject o, jstring name))
return NULL;
WB_END

WB_ENTRY(jobject, WB_GetIntVMFlag(JNIEnv* env, jobject o, jstring name))
int result;
if (GetVMFlag <JVM_FLAG_TYPE(int)> (thread, env, name, &result)) {
template <typename T, int type_enum>
jobject GetVMFlag_longBox(JNIEnv* env, JavaThread* thread, jstring name) {
T result;
if (GetVMFlag <T, type_enum> (thread, env, name, &result)) {
ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
return longBox(thread, env, result);
}
return NULL;
}

WB_ENTRY(jobject, WB_GetIntVMFlag(JNIEnv* env, jobject o, jstring name))
return GetVMFlag_longBox<JVM_FLAG_TYPE(int)>(env, thread, name);
WB_END

WB_ENTRY(jobject, WB_GetUintVMFlag(JNIEnv* env, jobject o, jstring name))
uint result;
if (GetVMFlag <JVM_FLAG_TYPE(uint)> (thread, env, name, &result)) {
ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
return longBox(thread, env, result);
}
return NULL;
return GetVMFlag_longBox<JVM_FLAG_TYPE(uint)>(env, thread, name);
WB_END

WB_ENTRY(jobject, WB_GetIntxVMFlag(JNIEnv* env, jobject o, jstring name))
intx result;
if (GetVMFlag <JVM_FLAG_TYPE(intx)> (thread, env, name, &result)) {
ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
return longBox(thread, env, result);
}
return NULL;
return GetVMFlag_longBox<JVM_FLAG_TYPE(intx)>(env, thread, name);
WB_END

WB_ENTRY(jobject, WB_GetUintxVMFlag(JNIEnv* env, jobject o, jstring name))
uintx result;
if (GetVMFlag <JVM_FLAG_TYPE(uintx)> (thread, env, name, &result)) {
ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
return longBox(thread, env, result);
}
return NULL;
return GetVMFlag_longBox<JVM_FLAG_TYPE(uintx)>(env, thread, name);
WB_END

WB_ENTRY(jobject, WB_GetUint64VMFlag(JNIEnv* env, jobject o, jstring name))
uint64_t result;
if (GetVMFlag <JVM_FLAG_TYPE(uint64_t)> (thread, env, name, &result)) {
ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
return longBox(thread, env, result);
}
return NULL;
return GetVMFlag_longBox<JVM_FLAG_TYPE(uint64_t)>(env, thread, name);
WB_END

WB_ENTRY(jobject, WB_GetSizeTVMFlag(JNIEnv* env, jobject o, jstring name))
size_t result;
if (GetVMFlag <JVM_FLAG_TYPE(size_t)> (thread, env, name, &result)) {
ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
return longBox(thread, env, result);
}
return NULL;
return GetVMFlag_longBox<JVM_FLAG_TYPE(size_t)>(env, thread, name);
WB_END

WB_ENTRY(jobject, WB_GetDoubleVMFlag(JNIEnv* env, jobject o, jstring name))
@@ -804,7 +804,7 @@ void Arguments::describe_range_error(ArgsRange errcode) {
}

static bool set_bool_flag(JVMFlag* flag, bool value, JVMFlagOrigin origin) {
if (JVMFlagAccess::boolAtPut(flag, &value, origin) == JVMFlag::SUCCESS) {
if (JVMFlagAccess::set_bool(flag, &value, origin) == JVMFlag::SUCCESS) {
return true;
} else {
return false;
@@ -819,7 +819,7 @@ static bool set_fp_numeric_flag(JVMFlag* flag, char* value, JVMFlagOrigin origin
return false;
}

if (JVMFlagAccess::doubleAtPut(flag, &v, origin) == JVMFlag::SUCCESS) {
if (JVMFlagAccess::set_double(flag, &v, origin) == JVMFlag::SUCCESS) {
return true;
}
return false;
@@ -851,43 +851,43 @@ static bool set_numeric_flag(JVMFlag* flag, char* value, JVMFlagOrigin origin) {
if (is_neg) {
int_v = -int_v;
}
return JVMFlagAccess::intAtPut(flag, &int_v, origin) == JVMFlag::SUCCESS;
return JVMFlagAccess::set_int(flag, &int_v, origin) == JVMFlag::SUCCESS;
} else if (flag->is_uint()) {
uint uint_v = (uint) v;
return JVMFlagAccess::uintAtPut(flag, &uint_v, origin) == JVMFlag::SUCCESS;
return JVMFlagAccess::set_uint(flag, &uint_v, origin) == JVMFlag::SUCCESS;
} else if (flag->is_intx()) {
intx_v = (intx) v;
if (is_neg) {
intx_v = -intx_v;
}
return JVMFlagAccess::intxAtPut(flag, &intx_v, origin) == JVMFlag::SUCCESS;
return JVMFlagAccess::set_intx(flag, &intx_v, origin) == JVMFlag::SUCCESS;
} else if (flag->is_uintx()) {
uintx uintx_v = (uintx) v;
return JVMFlagAccess::uintxAtPut(flag, &uintx_v, origin) == JVMFlag::SUCCESS;
return JVMFlagAccess::set_uintx(flag, &uintx_v, origin) == JVMFlag::SUCCESS;
} else if (flag->is_uint64_t()) {
uint64_t uint64_t_v = (uint64_t) v;
return JVMFlagAccess::uint64_tAtPut(flag, &uint64_t_v, origin) == JVMFlag::SUCCESS;
return JVMFlagAccess::set_uint64_t(flag, &uint64_t_v, origin) == JVMFlag::SUCCESS;
} else if (flag->is_size_t()) {
size_t size_t_v = (size_t) v;
return JVMFlagAccess::size_tAtPut(flag, &size_t_v, origin) == JVMFlag::SUCCESS;
return JVMFlagAccess::set_size_t(flag, &size_t_v, origin) == JVMFlag::SUCCESS;
} else if (flag->is_double()) {
double double_v = (double) v;
return JVMFlagAccess::doubleAtPut(flag, &double_v, origin) == JVMFlag::SUCCESS;
return JVMFlagAccess::set_double(flag, &double_v, origin) == JVMFlag::SUCCESS;
} else {
return false;
}
}

static bool set_string_flag(JVMFlag* flag, const char* value, JVMFlagOrigin origin) {
if (JVMFlagAccess::ccstrAtPut(flag, &value, origin) != JVMFlag::SUCCESS) return false;
if (JVMFlagAccess::set_ccstr(flag, &value, origin) != JVMFlag::SUCCESS) return false;
// Contract: JVMFlag always returns a pointer that needs freeing.
FREE_C_HEAP_ARRAY(char, value);
return true;
}

static bool append_to_string_flag(JVMFlag* flag, const char* new_value, JVMFlagOrigin origin) {
const char* old_value = "";
if (JVMFlagAccess::ccstrAt(flag, &old_value) != JVMFlag::SUCCESS) return false;
if (JVMFlagAccess::get_ccstr(flag, &old_value) != JVMFlag::SUCCESS) return false;
size_t old_len = old_value != NULL ? strlen(old_value) : 0;
size_t new_len = strlen(new_value);
const char* value;
@@ -904,7 +904,7 @@ static bool append_to_string_flag(JVMFlag* flag, const char* new_value, JVMFlagO
value = buf;
free_this_too = buf;
}
(void) JVMFlagAccess::ccstrAtPut(flag, &value, origin);
(void) JVMFlagAccess::set_ccstr(flag, &value, origin);
// JVMFlag always returns a pointer that needs freeing.
FREE_C_HEAP_ARRAY(char, value);
// JVMFlag made its own copy, so I must delete my own temp. buffer.
@@ -561,6 +561,14 @@ constexpr JVMFlag flagTable_verify_constexpr[] = { MATERIALIZE_ALL_FLAGS };
JVMFlag* JVMFlag::flags = flagTable;
size_t JVMFlag::numFlags = (sizeof(flagTable) / sizeof(JVMFlag));

#define JVM_FLAG_TYPE_SIGNATURE(t) JVMFlag::type_signature<t>(),

const int JVMFlag::type_signatures[] = {
JVM_FLAG_NON_STRING_TYPES_DO(JVM_FLAG_TYPE_SIGNATURE)
JVMFlag::type_signature<ccstr>(),
JVMFlag::type_signature<ccstr>()
};

// Search the flag table for a named flag
JVMFlag* JVMFlag::find_flag(const char* name, size_t length, bool allow_locked, bool return_flag) {
JVMFlag* flag = JVMFlagLookup::find(name, length);
@@ -194,8 +194,7 @@ class JVMFlag {

#define JVM_FLAG_TYPE_ACCESSOR(t) \
bool is_##t() const { return _type == TYPE_##t;} \
t get_##t() const { assert(is_##t(), "sanity"); return *((t*) _addr); } \
void set_##t(t value) { assert(is_##t(), "sanity"); *((t*) _addr) = value; }
t get_##t() const { assert(is_##t(), "sanity"); return *((t*) _addr); }

JVM_FLAG_NON_STRING_TYPES_DO(JVM_FLAG_TYPE_ACCESSOR)

@@ -225,23 +224,15 @@ class JVMFlag {
int type() const { return _type; }
const char* name() const { return _name; }

void assert_type(int type_enum) const {
if (type_enum == JVMFlag::TYPE_ccstr) {
assert(is_ccstr(), "type check"); // ccstr or ccstrlist
} else {
assert(_type == type_enum, "type check");
}
}

// Do not use JVMFlag::read() or JVMFlag::write() directly unless you know
// what you're doing. Use FLAG_SET_XXX macros or JVMFlagAccess instead.
template <typename T, int type_enum> T read() const {
assert_type(type_enum);
template <typename T> T read() const {
assert_compatible_type<T>(_type);
return *static_cast<T*>(_addr);
}

template <typename T, int type_enum> void write(T value) {
assert_type(type_enum);
template <typename T> void write(T value) {
assert_compatible_type<T>(_type);
*static_cast<T*>(_addr) = value;
}

@@ -291,25 +282,37 @@ class JVMFlag {

static const char* flag_error_str(JVMFlag::Error error);

// type checking
#define CHECK_COMPATIBLE(type) \
case TYPE_##type: \
assert(sizeof(T) == sizeof(type) && \
std::is_integral<T>::value == std::is_integral<type>::value && \
std::is_signed <T>::value == std::is_signed <type>::value, "must be"); \
break;
private:
// type checking - the following functions make sure you access *_addr as
// the correct type <T>

static void assert_valid_type_enum(int type_enum) {
assert(0 <= type_enum && type_enum < NUM_FLAG_TYPES, "sanity");
}

// The following computation is not universal, but should be correct
// for the limited number of types that can be stored inside a JVMFlag.
template <typename T>
static constexpr int type_signature() {
return int(sizeof(T)) |
(((std::is_integral<T>::value) ? 1 : 0) << 8) |
(((std::is_signed<T>::value) ? 1 : 0) << 9) |
(((std::is_pointer<T>::value) ? 1 : 0) << 10);
}

static const int type_signatures[];

public:
template <typename T>
static void assert_compatible_type(int type_enum) {
#ifndef PRODUCT
switch (type_enum) {
JVM_FLAG_NON_STRING_TYPES_DO(CHECK_COMPATIBLE);
default: ShouldNotReachHere();
}
#endif
assert(is_compatible_type<T>(type_enum), "must be");
}

#undef CHECK_COMPATIBLE
template <typename T>
static bool is_compatible_type(int type_enum) {
assert_valid_type_enum(type_enum);
return type_signatures[type_enum] == type_signature<T>();
}

public:
static void printSetFlags(outputStream* out);

1 comment on commit 627ad9f

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on 627ad9f Apr 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.