From d2cd4b666747ee4338532555a6f05def10a14d63 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Tue, 19 Apr 2016 09:37:41 +0200 Subject: [PATCH] Improve performance for locks and value conversions refs #11612 --- lib/base/i2-base.hpp | 9 +++++++++ lib/base/object.hpp | 2 +- lib/base/objectlock.hpp | 8 ++++---- lib/base/value.hpp | 2 +- lib/config/vmops.hpp | 4 ++-- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/lib/base/i2-base.hpp b/lib/base/i2-base.hpp index 1c46815a1..3d3b67395 100644 --- a/lib/base/i2-base.hpp +++ b/lib/base/i2-base.hpp @@ -91,4 +91,13 @@ # define I2_BASE_API I2_IMPORT #endif /* I2_BASE_BUILD */ +#if defined(__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 /* I2BASE_H */ diff --git a/lib/base/object.hpp b/lib/base/object.hpp index 654e56950..c454bdc12 100644 --- a/lib/base/object.hpp +++ b/lib/base/object.hpp @@ -191,7 +191,7 @@ inline void intrusive_ptr_release(Object *object) refs = __sync_sub_and_fetch(&object->m_References, 1); #endif /* _WIN32 */ - if (refs == 0) { + if (unlikely(refs == 0)) { #ifdef I2_LEAK_DEBUG TypeRemoveObject(object); #endif /* I2_LEAK_DEBUG */ diff --git a/lib/base/objectlock.hpp b/lib/base/objectlock.hpp index ea2e05484..9368a25bc 100644 --- a/lib/base/objectlock.hpp +++ b/lib/base/objectlock.hpp @@ -62,14 +62,14 @@ public: #ifdef _WIN32 # ifdef _WIN64 - while (InterlockedCompareExchange64((LONGLONG *)&object->m_Mutex, I2MUTEX_LOCKED, I2MUTEX_UNLOCKED) != I2MUTEX_UNLOCKED) { + while (likely(InterlockedCompareExchange64((LONGLONG *)&object->m_Mutex, I2MUTEX_LOCKED, I2MUTEX_UNLOCKED) != I2MUTEX_UNLOCKED)) { # else /* _WIN64 */ - while (InterlockedCompareExchange(&object->m_Mutex, I2MUTEX_LOCKED, I2MUTEX_UNLOCKED) != I2MUTEX_UNLOCKED) { + while (likely(InterlockedCompareExchange(&object->m_Mutex, I2MUTEX_LOCKED, I2MUTEX_UNLOCKED) != I2MUTEX_UNLOCKED)) { # endif /* _WIN64 */ #else /* _WIN32 */ - while (!__sync_bool_compare_and_swap(&object->m_Mutex, I2MUTEX_UNLOCKED, I2MUTEX_LOCKED)) { + while (likely(!__sync_bool_compare_and_swap(&object->m_Mutex, I2MUTEX_UNLOCKED, I2MUTEX_LOCKED))) { #endif /* _WIN32 */ - if (object->m_Mutex > I2MUTEX_LOCKED) { + if (likely(object->m_Mutex > I2MUTEX_LOCKED)) { boost::recursive_mutex *mtx = reinterpret_cast(object->m_Mutex); mtx->lock(); diff --git a/lib/base/value.hpp b/lib/base/value.hpp index df904ce22..34fe7cbd6 100644 --- a/lib/base/value.hpp +++ b/lib/base/value.hpp @@ -148,7 +148,7 @@ public: if (!IsObject()) BOOST_THROW_EXCEPTION(std::runtime_error("Cannot convert value of type '" + GetTypeName() + "' to an object.")); - Object::Ptr object = boost::get(m_Value); + const Object::Ptr& object = boost::get(m_Value); ASSERT(object); diff --git a/lib/config/vmops.hpp b/lib/config/vmops.hpp index c330b6cd8..1479da91f 100644 --- a/lib/config/vmops.hpp +++ b/lib/config/vmops.hpp @@ -193,10 +193,10 @@ public: static inline Value GetField(const Value& context, const String& field, bool sandboxed = false, const DebugInfo& debugInfo = DebugInfo()) { - if (context.IsEmpty() && !context.IsString()) + if (unlikely(context.IsEmpty() && !context.IsString())) return Empty; - if (!context.IsObject()) + if (unlikely(!context.IsObject())) return GetPrototypeField(context, field, true, debugInfo); Object::Ptr object = context;