diff --- vm/em/src/DrlEMImpl.cpp | 2 ++ vm/em/src/NValueProfileCollector.cpp | 16 +++++++++++----- vm/em/src/NValueProfileCollector.h | 5 +++++ vm/port/include/port_atomic.h | 25 +++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/vm/em/src/DrlEMImpl.cpp b/vm/em/src/DrlEMImpl.cpp index 4aa12a7..12409c9 100644 --- a/vm/em/src/DrlEMImpl.cpp +++ b/vm/em/src/DrlEMImpl.cpp @@ -657,6 +657,8 @@ ProfileCollector* DrlEMImpl::createProfi updateStrategy = UPDATE_UNSAFE; }else if (strategy == "LOCKED_INSERT") { updateStrategy = UPDATE_LOCKED_INSERT; + }else if (strategy == "ATOMIC_INC") { + updateStrategy = UPDATE_ATOMIC_INC; }else if (strategy != "LOCKED") { LECHO(10, "EM: unsupported value profiler updateStrategy"); return NULL; diff --git a/vm/em/src/NValueProfileCollector.cpp b/vm/em/src/NValueProfileCollector.cpp index 59966b2..31823e5 100644 --- a/vm/em/src/NValueProfileCollector.cpp +++ b/vm/em/src/NValueProfileCollector.cpp @@ -185,11 +185,16 @@ void TNVTableFirstNManager::addNewValue( ValueT* last_value = &(instProfile->last_value); uint32* num_times_profiled = &(instProfile->num_times_profiled); if (curr_value == *last_value){ - // We increment the counter safely with UPDATE_FLAGGED_ALL and - // UPDATE_LOCKED - (*num_times_profiled)++; + // We increment the counter safely with: + // UPDATE_FLAGGED_ALL, UPDATE_LOCKED, UPDATE_ATOMIC_INC. + if (updateStrategy == UPDATE_ATOMIC_INC) { + port_atomic_inc32(num_times_profiled); + } else { + (*num_times_profiled)++; + } } else { - if (updateStrategy == UPDATE_LOCKED_INSERT) { + if (updateStrategy == UPDATE_LOCKED_INSERT || + updateStrategy == UPDATE_ATOMIC_INC) { methProfile->lockProfile(); }else if (updateStrategy == UPDATE_FLAGGED_INSERT) { if (port_atomic_cas8(updating_ptr, 1, 0) != 0) { @@ -202,7 +207,8 @@ void TNVTableFirstNManager::addNewValue( *num_times_profiled = 1; insert(steady_part, clear_part, curr_value, *num_times_profiled); *last_value = curr_value; - if (updateStrategy == UPDATE_LOCKED_INSERT) { + if (updateStrategy == UPDATE_LOCKED_INSERT || + updateStrategy == UPDATE_ATOMIC_INC) { methProfile->unlockProfile(); }else if (updateStrategy == UPDATE_FLAGGED_INSERT) { *updating_ptr = 0; diff --git a/vm/em/src/NValueProfileCollector.h b/vm/em/src/NValueProfileCollector.h index 090e8bf..253ce2c 100644 --- a/vm/em/src/NValueProfileCollector.h +++ b/vm/em/src/NValueProfileCollector.h @@ -61,6 +61,11 @@ enum ProfileUpdateStrategy { // processed unsafely UPDATE_FLAGGED_INSERT, + // Value increments in TNV table performed with an atomic instruction, + // insertions into each table are performed under the LOCKED_INSERT + // strategy. + UPDATE_ATOMIC_INC, + // Completely insafe updates of the TNV table (use with care) UPDATE_UNSAFE }; diff --git a/vm/port/include/port_atomic.h b/vm/port/include/port_atomic.h index 5d5eda1..2e1801c 100644 --- a/vm/port/include/port_atomic.h +++ b/vm/port/include/port_atomic.h @@ -94,6 +94,12 @@ APR_DECLARE(uint16) port_atomic_cas16(vo APR_DECLARE(uint64) port_atomic_cas64(volatile uint64 * data, uint64 value, uint64 comp); +/** +* The atomic increment operation on uint32. +* The function increments a 32 bit value located at address data by 1. +*/ +APR_DECLARE(void) port_atomic_inc32(volatile uint32 * data); + /** @} */ #elif defined(WIN32) && !defined(_WIN64) @@ -140,6 +146,9 @@ INLINE uint64 port_atomic_cas64(volatile return comp; } +// TODO: implement for WIN32: +// INLINE void port_atomic_inc32(volatile int32 * data) + #elif defined(_EM64T_) && defined (_WIN64) #pragma intrinsic(_InterlockedCompareExchange16) @@ -160,6 +169,8 @@ INLINE uint64 port_atomic_cas64(volatile return _InterlockedCompareExchange64((volatile LONG64 *)data, value, comp); } +// TODO: implement for WIN64: +// INLINE void port_atomic_inc32(volatile int32 * data) #elif defined (PLATFORM_POSIX) @@ -224,6 +235,20 @@ INLINE uint64 port_atomic_cas64(volatile #endif } +INLINE void port_atomic_inc32(volatile uint32 * data) +{ +#if defined(_IA32_) || defined(_EM64T_) + __asm__ __volatile__( + "lock addl $1, (%1)" + : "=m" (*data) /* output */ + : "r" (data) /* input */ + : "memory" + ); +#elif + ABORT("Not supported"); +#endif +} + INLINE void * port_atomic_compare_exchange_pointer(volatile void ** data, void * value, const void * comp) { #if defined(_IA32_) //return (void *) port_atomic_compare_exchange32((uint32 *)data, (uint32)value, (uint32)comp);