Home | History | Annotate | Download | only in cctest
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include "src/v8.h"
     29 
     30 #include "src/base/atomicops.h"
     31 #include "test/cctest/cctest.h"
     32 
     33 using namespace v8::base;
     34 using namespace v8::internal;
     35 
     36 
     37 #define CHECK_EQU(v1, v2) \
     38   CHECK_EQ(static_cast<int64_t>(v1), static_cast<int64_t>(v2))
     39 
     40 #define NUM_BITS(T) (sizeof(T) * 8)
     41 
     42 
     43 template <class AtomicType>
     44 static void TestAtomicIncrement() {
     45   // For now, we just test the single-threaded execution.
     46 
     47   // Use a guard value to make sure that NoBarrier_AtomicIncrement doesn't
     48   // go outside the expected address bounds.  This is to test that the
     49   // 32-bit NoBarrier_AtomicIncrement doesn't do the wrong thing on 64-bit
     50   // machines.
     51   struct {
     52     AtomicType prev_word;
     53     AtomicType count;
     54     AtomicType next_word;
     55   } s;
     56 
     57   AtomicType prev_word_value, next_word_value;
     58   memset(&prev_word_value, 0xFF, sizeof(AtomicType));
     59   memset(&next_word_value, 0xEE, sizeof(AtomicType));
     60 
     61   s.prev_word = prev_word_value;
     62   s.count = 0;
     63   s.next_word = next_word_value;
     64 
     65   CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, 1), 1);
     66   CHECK_EQU(s.count, 1);
     67   CHECK_EQU(s.prev_word, prev_word_value);
     68   CHECK_EQU(s.next_word, next_word_value);
     69 
     70   CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, 2), 3);
     71   CHECK_EQU(s.count, 3);
     72   CHECK_EQU(s.prev_word, prev_word_value);
     73   CHECK_EQU(s.next_word, next_word_value);
     74 
     75   CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, 3), 6);
     76   CHECK_EQU(s.count, 6);
     77   CHECK_EQU(s.prev_word, prev_word_value);
     78   CHECK_EQU(s.next_word, next_word_value);
     79 
     80   CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, -3), 3);
     81   CHECK_EQU(s.count, 3);
     82   CHECK_EQU(s.prev_word, prev_word_value);
     83   CHECK_EQU(s.next_word, next_word_value);
     84 
     85   CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, -2), 1);
     86   CHECK_EQU(s.count, 1);
     87   CHECK_EQU(s.prev_word, prev_word_value);
     88   CHECK_EQU(s.next_word, next_word_value);
     89 
     90   CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, -1), 0);
     91   CHECK_EQU(s.count, 0);
     92   CHECK_EQU(s.prev_word, prev_word_value);
     93   CHECK_EQU(s.next_word, next_word_value);
     94 
     95   CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, -1), -1);
     96   CHECK_EQU(s.count, -1);
     97   CHECK_EQU(s.prev_word, prev_word_value);
     98   CHECK_EQU(s.next_word, next_word_value);
     99 
    100   CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, -4), -5);
    101   CHECK_EQU(s.count, -5);
    102   CHECK_EQU(s.prev_word, prev_word_value);
    103   CHECK_EQU(s.next_word, next_word_value);
    104 
    105   CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, 5), 0);
    106   CHECK_EQU(s.count, 0);
    107   CHECK_EQU(s.prev_word, prev_word_value);
    108   CHECK_EQU(s.next_word, next_word_value);
    109 }
    110 
    111 
    112 template <class AtomicType>
    113 static void TestCompareAndSwap() {
    114   AtomicType value = 0;
    115   AtomicType prev = NoBarrier_CompareAndSwap(&value, 0, 1);
    116   CHECK_EQU(1, value);
    117   CHECK_EQU(0, prev);
    118 
    119   // Use a test value that has non-zero bits in both halves, for testing
    120   // the 64-bit implementation on 32-bit platforms.
    121   const AtomicType k_test_val =
    122       (static_cast<AtomicType>(1) << (NUM_BITS(AtomicType) - 2)) + 11;
    123   value = k_test_val;
    124   prev = NoBarrier_CompareAndSwap(&value, 0, 5);
    125   CHECK_EQU(k_test_val, value);
    126   CHECK_EQU(k_test_val, prev);
    127 
    128   value = k_test_val;
    129   prev = NoBarrier_CompareAndSwap(&value, k_test_val, 5);
    130   CHECK_EQU(5, value);
    131   CHECK_EQU(k_test_val, prev);
    132 }
    133 
    134 
    135 template <class AtomicType>
    136 static void TestAtomicExchange() {
    137   AtomicType value = 0;
    138   AtomicType new_value = NoBarrier_AtomicExchange(&value, 1);
    139   CHECK_EQU(1, value);
    140   CHECK_EQU(0, new_value);
    141 
    142   // Use a test value that has non-zero bits in both halves, for testing
    143   // the 64-bit implementation on 32-bit platforms.
    144   const AtomicType k_test_val =
    145       (static_cast<AtomicType>(1) << (NUM_BITS(AtomicType) - 2)) + 11;
    146   value = k_test_val;
    147   new_value = NoBarrier_AtomicExchange(&value, k_test_val);
    148   CHECK_EQU(k_test_val, value);
    149   CHECK_EQU(k_test_val, new_value);
    150 
    151   value = k_test_val;
    152   new_value = NoBarrier_AtomicExchange(&value, 5);
    153   CHECK_EQU(5, value);
    154   CHECK_EQU(k_test_val, new_value);
    155 }
    156 
    157 
    158 template <class AtomicType>
    159 static void TestAtomicIncrementBounds() {
    160   // Test at 32-bit boundary for 64-bit atomic type.
    161   AtomicType test_val = static_cast<AtomicType>(1)
    162                         << (NUM_BITS(AtomicType) / 2);
    163   AtomicType value = test_val - 1;
    164   AtomicType new_value = NoBarrier_AtomicIncrement(&value, 1);
    165   CHECK_EQU(test_val, value);
    166   CHECK_EQU(value, new_value);
    167 
    168   NoBarrier_AtomicIncrement(&value, -1);
    169   CHECK_EQU(test_val - 1, value);
    170 }
    171 
    172 
    173 // Return an AtomicType with the value 0xa5a5a5..
    174 template <class AtomicType>
    175 static AtomicType TestFillValue() {
    176   AtomicType val = 0;
    177   memset(&val, 0xa5, sizeof(AtomicType));
    178   return val;
    179 }
    180 
    181 
    182 // This is a simple sanity check to ensure that values are correct.
    183 // Not testing atomicity.
    184 template <class AtomicType>
    185 static void TestStore() {
    186   const AtomicType kVal1 = TestFillValue<AtomicType>();
    187   const AtomicType kVal2 = static_cast<AtomicType>(-1);
    188 
    189   AtomicType value;
    190 
    191   NoBarrier_Store(&value, kVal1);
    192   CHECK_EQU(kVal1, value);
    193   NoBarrier_Store(&value, kVal2);
    194   CHECK_EQU(kVal2, value);
    195 
    196   Acquire_Store(&value, kVal1);
    197   CHECK_EQU(kVal1, value);
    198   Acquire_Store(&value, kVal2);
    199   CHECK_EQU(kVal2, value);
    200 
    201   Release_Store(&value, kVal1);
    202   CHECK_EQU(kVal1, value);
    203   Release_Store(&value, kVal2);
    204   CHECK_EQU(kVal2, value);
    205 }
    206 
    207 
    208 // Merge this test with TestStore as soon as we have Atomic8 acquire
    209 // and release stores.
    210 static void TestStoreAtomic8() {
    211   const Atomic8 kVal1 = TestFillValue<Atomic8>();
    212   const Atomic8 kVal2 = static_cast<Atomic8>(-1);
    213 
    214   Atomic8 value;
    215 
    216   NoBarrier_Store(&value, kVal1);
    217   CHECK_EQU(kVal1, value);
    218   NoBarrier_Store(&value, kVal2);
    219   CHECK_EQU(kVal2, value);
    220 }
    221 
    222 
    223 // This is a simple sanity check to ensure that values are correct.
    224 // Not testing atomicity.
    225 template <class AtomicType>
    226 static void TestLoad() {
    227   const AtomicType kVal1 = TestFillValue<AtomicType>();
    228   const AtomicType kVal2 = static_cast<AtomicType>(-1);
    229 
    230   AtomicType value;
    231 
    232   value = kVal1;
    233   CHECK_EQU(kVal1, NoBarrier_Load(&value));
    234   value = kVal2;
    235   CHECK_EQU(kVal2, NoBarrier_Load(&value));
    236 
    237   value = kVal1;
    238   CHECK_EQU(kVal1, Acquire_Load(&value));
    239   value = kVal2;
    240   CHECK_EQU(kVal2, Acquire_Load(&value));
    241 
    242   value = kVal1;
    243   CHECK_EQU(kVal1, Release_Load(&value));
    244   value = kVal2;
    245   CHECK_EQU(kVal2, Release_Load(&value));
    246 }
    247 
    248 
    249 // Merge this test with TestLoad as soon as we have Atomic8 acquire
    250 // and release loads.
    251 static void TestLoadAtomic8() {
    252   const Atomic8 kVal1 = TestFillValue<Atomic8>();
    253   const Atomic8 kVal2 = static_cast<Atomic8>(-1);
    254 
    255   Atomic8 value;
    256 
    257   value = kVal1;
    258   CHECK_EQU(kVal1, NoBarrier_Load(&value));
    259   value = kVal2;
    260   CHECK_EQU(kVal2, NoBarrier_Load(&value));
    261 }
    262 
    263 
    264 TEST(AtomicIncrement) {
    265   TestAtomicIncrement<Atomic32>();
    266   TestAtomicIncrement<AtomicWord>();
    267 }
    268 
    269 
    270 TEST(CompareAndSwap) {
    271   TestCompareAndSwap<Atomic32>();
    272   TestCompareAndSwap<AtomicWord>();
    273 }
    274 
    275 
    276 TEST(AtomicExchange) {
    277   TestAtomicExchange<Atomic32>();
    278   TestAtomicExchange<AtomicWord>();
    279 }
    280 
    281 
    282 TEST(AtomicIncrementBounds) {
    283   TestAtomicIncrementBounds<Atomic32>();
    284   TestAtomicIncrementBounds<AtomicWord>();
    285 }
    286 
    287 
    288 TEST(Store) {
    289   TestStoreAtomic8();
    290   TestStore<Atomic32>();
    291   TestStore<AtomicWord>();
    292 }
    293 
    294 
    295 TEST(Load) {
    296   TestLoadAtomic8();
    297   TestLoad<Atomic32>();
    298   TestLoad<AtomicWord>();
    299 }
    300