Implement Linux-style likely()/unlikely() macros
This implement branch prediction macros likely() and unlikely() like in Linux. When using these macros please ensure that when you use them the condition in the branch really is very, very likely or unlikely. Think 90+% of the time. Primarily useful for error checking. (And I implement these macros for all our error checking macros now) See this article for more information: https://kernelnewbies.org/FAQ/LikelyUnlikely There are more places where these macros may make sense in renderer and physics engine. Placing them will come in another commit down the line.
This commit is contained in:
parent
4664d03a0e
commit
22358babda
4 changed files with 24 additions and 15 deletions
|
@ -30,6 +30,7 @@
|
||||||
#ifndef ERROR_MACROS_H
|
#ifndef ERROR_MACROS_H
|
||||||
#define ERROR_MACROS_H
|
#define ERROR_MACROS_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
/**
|
/**
|
||||||
* Error macros. Unlike exceptions and asserts, these macros try to mantain consistency and stability
|
* Error macros. Unlike exceptions and asserts, these macros try to mantain consistency and stability
|
||||||
* inside the code. It is recommended to always return processable data, so in case of an error, the
|
* inside the code. It is recommended to always return processable data, so in case of an error, the
|
||||||
|
@ -130,7 +131,7 @@ extern bool _err_error_exists;
|
||||||
|
|
||||||
#define ERR_FAIL_INDEX(m_index, m_size) \
|
#define ERR_FAIL_INDEX(m_index, m_size) \
|
||||||
do { \
|
do { \
|
||||||
if ((m_index) < 0 || (m_index) >= (m_size)) { \
|
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
|
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
|
||||||
return; \
|
return; \
|
||||||
} else \
|
} else \
|
||||||
|
@ -144,7 +145,7 @@ extern bool _err_error_exists;
|
||||||
|
|
||||||
#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
|
#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
|
||||||
do { \
|
do { \
|
||||||
if ((m_index) < 0 || (m_index) >= (m_size)) { \
|
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
|
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
|
||||||
return m_retval; \
|
return m_retval; \
|
||||||
} else \
|
} else \
|
||||||
|
@ -156,7 +157,7 @@ extern bool _err_error_exists;
|
||||||
*/
|
*/
|
||||||
#define CRASH_BAD_INDEX(m_index, m_size) \
|
#define CRASH_BAD_INDEX(m_index, m_size) \
|
||||||
do { \
|
do { \
|
||||||
if ((m_index) < 0 || (m_index) >= (m_size)) { \
|
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
|
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
|
||||||
GENERATE_TRAP \
|
GENERATE_TRAP \
|
||||||
} \
|
} \
|
||||||
|
@ -168,7 +169,7 @@ extern bool _err_error_exists;
|
||||||
|
|
||||||
#define ERR_FAIL_NULL(m_param) \
|
#define ERR_FAIL_NULL(m_param) \
|
||||||
{ \
|
{ \
|
||||||
if (!m_param) { \
|
if (unlikely(!m_param)) { \
|
||||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \
|
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \
|
||||||
return; \
|
return; \
|
||||||
} else \
|
} else \
|
||||||
|
@ -177,7 +178,7 @@ extern bool _err_error_exists;
|
||||||
|
|
||||||
#define ERR_FAIL_NULL_V(m_param, m_retval) \
|
#define ERR_FAIL_NULL_V(m_param, m_retval) \
|
||||||
{ \
|
{ \
|
||||||
if (!m_param) { \
|
if (unlikely(!m_param)) { \
|
||||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \
|
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \
|
||||||
return m_retval; \
|
return m_retval; \
|
||||||
} else \
|
} else \
|
||||||
|
@ -190,7 +191,7 @@ extern bool _err_error_exists;
|
||||||
|
|
||||||
#define ERR_FAIL_COND(m_cond) \
|
#define ERR_FAIL_COND(m_cond) \
|
||||||
{ \
|
{ \
|
||||||
if (m_cond) { \
|
if (unlikely(m_cond)) { \
|
||||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true."); \
|
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true."); \
|
||||||
return; \
|
return; \
|
||||||
} else \
|
} else \
|
||||||
|
@ -202,7 +203,7 @@ extern bool _err_error_exists;
|
||||||
|
|
||||||
#define CRASH_COND(m_cond) \
|
#define CRASH_COND(m_cond) \
|
||||||
{ \
|
{ \
|
||||||
if (m_cond) { \
|
if (unlikely(m_cond)) { \
|
||||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition ' " _STR(m_cond) " ' is true."); \
|
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition ' " _STR(m_cond) " ' is true."); \
|
||||||
GENERATE_TRAP \
|
GENERATE_TRAP \
|
||||||
} \
|
} \
|
||||||
|
@ -216,7 +217,7 @@ extern bool _err_error_exists;
|
||||||
|
|
||||||
#define ERR_FAIL_COND_V(m_cond, m_retval) \
|
#define ERR_FAIL_COND_V(m_cond, m_retval) \
|
||||||
{ \
|
{ \
|
||||||
if (m_cond) { \
|
if (unlikely(m_cond)) { \
|
||||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. returned: " _STR(m_retval)); \
|
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. returned: " _STR(m_retval)); \
|
||||||
return m_retval; \
|
return m_retval; \
|
||||||
} else \
|
} else \
|
||||||
|
@ -229,7 +230,7 @@ extern bool _err_error_exists;
|
||||||
|
|
||||||
#define ERR_CONTINUE(m_cond) \
|
#define ERR_CONTINUE(m_cond) \
|
||||||
{ \
|
{ \
|
||||||
if (m_cond) { \
|
if (unlikely(m_cond)) { \
|
||||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Continuing..:"); \
|
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Continuing..:"); \
|
||||||
continue; \
|
continue; \
|
||||||
} else \
|
} else \
|
||||||
|
@ -242,7 +243,7 @@ extern bool _err_error_exists;
|
||||||
|
|
||||||
#define ERR_BREAK(m_cond) \
|
#define ERR_BREAK(m_cond) \
|
||||||
{ \
|
{ \
|
||||||
if (m_cond) { \
|
if (unlikely(m_cond)) { \
|
||||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Breaking..:"); \
|
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Breaking..:"); \
|
||||||
break; \
|
break; \
|
||||||
} else \
|
} else \
|
||||||
|
|
|
@ -290,4 +290,12 @@ struct _GlobalLock {
|
||||||
#define __STRX(m_index) #m_index
|
#define __STRX(m_index) #m_index
|
||||||
#define __STR(m_index) __STRX(m_index)
|
#define __STR(m_index) __STRX(m_index)
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
|
#else
|
||||||
|
#define likely(x) x
|
||||||
|
#define unlikely(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* typedefs.h */
|
#endif /* typedefs.h */
|
||||||
|
|
|
@ -2469,10 +2469,10 @@ Variant::Variant(const Vector<Color> &p_array) {
|
||||||
|
|
||||||
void Variant::operator=(const Variant &p_variant) {
|
void Variant::operator=(const Variant &p_variant) {
|
||||||
|
|
||||||
if (this == &p_variant)
|
if (unlikely(this == &p_variant))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (type != p_variant.type) {
|
if (unlikely(type != p_variant.type)) {
|
||||||
reference(p_variant);
|
reference(p_variant);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ Variant *GDFunction::_get_variant(int p_address, GDInstance *p_instance, GDScrip
|
||||||
|
|
||||||
case ADDR_TYPE_SELF: {
|
case ADDR_TYPE_SELF: {
|
||||||
|
|
||||||
if (!p_instance) {
|
if (unlikely(!p_instance)) {
|
||||||
r_error = "Cannot access self without instance.";
|
r_error = "Cannot access self without instance.";
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ Variant *GDFunction::_get_variant(int p_address, GDInstance *p_instance, GDScrip
|
||||||
} break;
|
} break;
|
||||||
case ADDR_TYPE_MEMBER: {
|
case ADDR_TYPE_MEMBER: {
|
||||||
//member indexing is O(1)
|
//member indexing is O(1)
|
||||||
if (!p_instance) {
|
if (unlikely(!p_instance)) {
|
||||||
r_error = "Cannot access member without instance.";
|
r_error = "Cannot access member without instance.";
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -279,7 +279,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
|
||||||
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
|
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
|
||||||
Variant *m_v; \
|
Variant *m_v; \
|
||||||
m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, _class, self, stack, err_text); \
|
m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, _class, self, stack, err_text); \
|
||||||
if (!m_v) \
|
if (unlikely(!m_v)) \
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
Loading…
Reference in a new issue