X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Fpublic-api%2Fobject%2Fref-object.cpp;h=3060f4b48889676c987523013017b3f7b4e60bee;hb=refs%2Fchanges%2F06%2F82306%2F1;hp=b6961f3ded6edaf8755470b003750fd74898f789;hpb=df59eea2434495c32414fcf9ffafe4cb7dff5324;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/public-api/object/ref-object.cpp b/dali/public-api/object/ref-object.cpp index b6961f3..3060f4b 100644 --- a/dali/public-api/object/ref-object.cpp +++ b/dali/public-api/object/ref-object.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2015 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,9 @@ // INTERNAL INCLUDES #include +// EXTERNAL INCLUDES +#include + namespace Dali { @@ -36,7 +39,12 @@ RefObject::RefObject(const RefObject&) RefObject::~RefObject() { - DALI_ASSERT_DEBUG(mCount == 0); +#ifdef ENABLE_DEBUG + if(mCount) + { + DALI_LOG_ERROR("mCount should be zero, deleting referenced object!\n"); + } +#endif // ENABLE_DEBUG } RefObject& RefObject::operator=(const RefObject&) @@ -47,14 +55,107 @@ RefObject& RefObject::operator=(const RefObject&) void RefObject::Reference() { - // gcc > 4.1 builtin atomic add and fetch (++mCount; return mCount) - __sync_add_and_fetch(&mCount, 1); + // The inline assembly below was tested on an ARMv8 64 bit platform on + // 2015-02-06 and found to run in 11.8 nanoseconds, whereas + // __sync_add_and_fetch( address, 1 ) required 18.8 nanoseconds. + // Including the assembly here produced one fewer assembly instruction than if + // it was wrapped in a function and inlined here by the compiler. +#if defined __aarch64__ + + asm volatile( + "1:\tldxr w1, %[address] \n\t" + "add w1, w1, %[one] \n\t" + "stxr w2, w1, %[address] \n\t" + "cbnz w2, 1b \n\t" + // Outputs: + : // Q = A memory address with no offset + // ( https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints ) + [address] "+Q" (mCount) + // Inputs: + : [one] "Ir" (1) + // Clobbers: (explicitly clobber w1 register to hold the loaded value and + // register w2 to hold success/fail): + : "w1", "w2" + ); + + // 32 bit ARMv7 version of above: + // Better than the code emitted by GCC for __sync_add_and_fetch(), as that + // includes two dmb memory barrier instructions: one before and one after the + // loop. +#elif defined __arm__ + + asm volatile( + "1:\tldrex r1, %[address] \n\t" + "add r1, r1, %[one] \n\t" + "strex r2, r1, %[address] \n\t" + "teq r2, %[zero] \n\t" + "bne 1b \n\t" + // Outputs: + : [address] "+Q" (mCount) + // Inputs: + : [zero] "Ir" (0), + [one] "Ir" (1) + // Clobbers: (modified registers): + : "r1", "r2" + ); + +#else + + // gcc > 4.1 builtin atomic add and fetch: + __sync_add_and_fetch( &mCount, 1 ); + +#endif } void RefObject::Unreference() { + // The output register: + int32_t newValue; + +#if defined __aarch64__ + + asm volatile( + "1:\tldxr %w[newValue], %[address] \n\t" + "sub %w[newValue], %w[newValue], %[one] \n\t" + "stxr w2, %w[newValue], %[address] \n\t" + "cbnz w2, 1b \n\t" + // Outputs: + : [newValue] "=&r" (newValue), + // Q = A memory address with no offset + // ( https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints ) + [address] "+Q" (mCount) + // Inputs: + : [one] "Ir" (1) + // Clobbered: I.e., stuff that is modified. + : "w2" + ); + +#elif defined __arm__ + + asm volatile( + "1:\tldrex %[newValue], %[address] \n\t" + "sub %[newValue], %[newValue], %[one] \n\t" + "strex r2, %[newValue], %[address] \n\t" + "teq r2, %[zero] \n\t" + "bne 1b \n\t" + // Outputs: + : [newValue] "=&r" (newValue), + [address] "+Q" (mCount) + // Inputs: + : [zero] "Ir" (0), + [one] "Ir" (1) + // Clobbered: + : "r2" + ); + +#else + // gcc > 4.1 builtin atomic subtract and fetch (--mCount; return mCount) - if (__sync_sub_and_fetch(&mCount, 1) == 0) + newValue = __sync_sub_and_fetch( &mCount, 1 ); + +#endif + + if( newValue == 0 ) { delete this; }