v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-atomicops.cc
Go to the documentation of this file.
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 "v8.h"
29 
30 #include "cctest.h"
31 #include "atomicops.h"
32 
33 using namespace v8::internal;
34 
35 
36 #define CHECK_EQU(v1, v2) \
37  CHECK_EQ(static_cast<int64_t>(v1), static_cast<int64_t>(v2))
38 
39 #define NUM_BITS(T) (sizeof(T) * 8)
40 
41 
42 template <class AtomicType>
43 static void TestAtomicIncrement() {
44  // For now, we just test the single-threaded execution.
45 
46  // Use a guard value to make sure that NoBarrier_AtomicIncrement doesn't
47  // go outside the expected address bounds. This is to test that the
48  // 32-bit NoBarrier_AtomicIncrement doesn't do the wrong thing on 64-bit
49  // machines.
50  struct {
51  AtomicType prev_word;
52  AtomicType count;
53  AtomicType next_word;
54  } s;
55 
56  AtomicType prev_word_value, next_word_value;
57  memset(&prev_word_value, 0xFF, sizeof(AtomicType));
58  memset(&next_word_value, 0xEE, sizeof(AtomicType));
59 
60  s.prev_word = prev_word_value;
61  s.count = 0;
62  s.next_word = next_word_value;
63 
64  CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, 1), 1);
65  CHECK_EQU(s.count, 1);
66  CHECK_EQU(s.prev_word, prev_word_value);
67  CHECK_EQU(s.next_word, next_word_value);
68 
69  CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, 2), 3);
70  CHECK_EQU(s.count, 3);
71  CHECK_EQU(s.prev_word, prev_word_value);
72  CHECK_EQU(s.next_word, next_word_value);
73 
74  CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, 3), 6);
75  CHECK_EQU(s.count, 6);
76  CHECK_EQU(s.prev_word, prev_word_value);
77  CHECK_EQU(s.next_word, next_word_value);
78 
79  CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, -3), 3);
80  CHECK_EQU(s.count, 3);
81  CHECK_EQU(s.prev_word, prev_word_value);
82  CHECK_EQU(s.next_word, next_word_value);
83 
84  CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, -2), 1);
85  CHECK_EQU(s.count, 1);
86  CHECK_EQU(s.prev_word, prev_word_value);
87  CHECK_EQU(s.next_word, next_word_value);
88 
89  CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, -1), 0);
90  CHECK_EQU(s.count, 0);
91  CHECK_EQU(s.prev_word, prev_word_value);
92  CHECK_EQU(s.next_word, next_word_value);
93 
94  CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, -1), -1);
95  CHECK_EQU(s.count, -1);
96  CHECK_EQU(s.prev_word, prev_word_value);
97  CHECK_EQU(s.next_word, next_word_value);
98 
99  CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, -4), -5);
100  CHECK_EQU(s.count, -5);
101  CHECK_EQU(s.prev_word, prev_word_value);
102  CHECK_EQU(s.next_word, next_word_value);
103 
104  CHECK_EQU(NoBarrier_AtomicIncrement(&s.count, 5), 0);
105  CHECK_EQU(s.count, 0);
106  CHECK_EQU(s.prev_word, prev_word_value);
107  CHECK_EQU(s.next_word, next_word_value);
108 }
109 
110 
111 template <class AtomicType>
112 static void TestCompareAndSwap() {
113  AtomicType value = 0;
114  AtomicType prev = NoBarrier_CompareAndSwap(&value, 0, 1);
115  CHECK_EQU(1, value);
116  CHECK_EQU(0, prev);
117 
118  // Use a test value that has non-zero bits in both halves, for testing
119  // the 64-bit implementation on 32-bit platforms.
120  const AtomicType k_test_val =
121  (static_cast<AtomicType>(1) << (NUM_BITS(AtomicType) - 2)) + 11;
122  value = k_test_val;
123  prev = NoBarrier_CompareAndSwap(&value, 0, 5);
124  CHECK_EQU(k_test_val, value);
125  CHECK_EQU(k_test_val, prev);
126 
127  value = k_test_val;
128  prev = NoBarrier_CompareAndSwap(&value, k_test_val, 5);
129  CHECK_EQU(5, value);
130  CHECK_EQU(k_test_val, prev);
131 }
132 
133 
134 template <class AtomicType>
135 static void TestAtomicExchange() {
136  AtomicType value = 0;
137  AtomicType new_value = NoBarrier_AtomicExchange(&value, 1);
138  CHECK_EQU(1, value);
139  CHECK_EQU(0, new_value);
140 
141  // Use a test value that has non-zero bits in both halves, for testing
142  // the 64-bit implementation on 32-bit platforms.
143  const AtomicType k_test_val =
144  (static_cast<AtomicType>(1) << (NUM_BITS(AtomicType) - 2)) + 11;
145  value = k_test_val;
146  new_value = NoBarrier_AtomicExchange(&value, k_test_val);
147  CHECK_EQU(k_test_val, value);
148  CHECK_EQU(k_test_val, new_value);
149 
150  value = k_test_val;
151  new_value = NoBarrier_AtomicExchange(&value, 5);
152  CHECK_EQU(5, value);
153  CHECK_EQU(k_test_val, new_value);
154 }
155 
156 
157 template <class AtomicType>
158 static void TestAtomicIncrementBounds() {
159  // Test at rollover boundary between int_max and int_min.
160  AtomicType test_val =
161  static_cast<AtomicType>(1) << (NUM_BITS(AtomicType) - 1);
162  AtomicType value = -1 ^ test_val;
163  AtomicType new_value = NoBarrier_AtomicIncrement(&value, 1);
164  CHECK_EQU(test_val, value);
165  CHECK_EQU(value, new_value);
166 
167  NoBarrier_AtomicIncrement(&value, -1);
168  CHECK_EQU(-1 ^ test_val, value);
169 
170  // Test at 32-bit boundary for 64-bit atomic type.
171  test_val = static_cast<AtomicType>(1) << (NUM_BITS(AtomicType) / 2);
172  value = test_val - 1;
173  new_value = NoBarrier_AtomicIncrement(&value, 1);
174  CHECK_EQU(test_val, value);
175  CHECK_EQU(value, new_value);
176 
177  NoBarrier_AtomicIncrement(&value, -1);
178  CHECK_EQU(test_val - 1, value);
179 }
180 
181 
182 // Return an AtomicType with the value 0xa5a5a5..
183 template <class AtomicType>
184 static AtomicType TestFillValue() {
185  AtomicType val = 0;
186  memset(&val, 0xa5, sizeof(AtomicType));
187  return val;
188 }
189 
190 
191 // This is a simple sanity check to ensure that values are correct.
192 // Not testing atomicity.
193 template <class AtomicType>
194 static void TestStore() {
195  const AtomicType kVal1 = TestFillValue<AtomicType>();
196  const AtomicType kVal2 = static_cast<AtomicType>(-1);
197 
198  AtomicType value;
199 
200  NoBarrier_Store(&value, kVal1);
201  CHECK_EQU(kVal1, value);
202  NoBarrier_Store(&value, kVal2);
203  CHECK_EQU(kVal2, value);
204 
205  Acquire_Store(&value, kVal1);
206  CHECK_EQU(kVal1, value);
207  Acquire_Store(&value, kVal2);
208  CHECK_EQU(kVal2, value);
209 
210  Release_Store(&value, kVal1);
211  CHECK_EQU(kVal1, value);
212  Release_Store(&value, kVal2);
213  CHECK_EQU(kVal2, value);
214 }
215 
216 
217 // This is a simple sanity check to ensure that values are correct.
218 // Not testing atomicity.
219 template <class AtomicType>
220 static void TestLoad() {
221  const AtomicType kVal1 = TestFillValue<AtomicType>();
222  const AtomicType kVal2 = static_cast<AtomicType>(-1);
223 
224  AtomicType value;
225 
226  value = kVal1;
227  CHECK_EQU(kVal1, NoBarrier_Load(&value));
228  value = kVal2;
229  CHECK_EQU(kVal2, NoBarrier_Load(&value));
230 
231  value = kVal1;
232  CHECK_EQU(kVal1, Acquire_Load(&value));
233  value = kVal2;
234  CHECK_EQU(kVal2, Acquire_Load(&value));
235 
236  value = kVal1;
237  CHECK_EQU(kVal1, Release_Load(&value));
238  value = kVal2;
239  CHECK_EQU(kVal2, Release_Load(&value));
240 }
241 
242 
243 TEST(AtomicIncrement) {
244  TestAtomicIncrement<Atomic32>();
245  TestAtomicIncrement<AtomicWord>();
246 }
247 
248 
249 TEST(CompareAndSwap) {
250  TestCompareAndSwap<Atomic32>();
251  TestCompareAndSwap<AtomicWord>();
252 }
253 
254 
255 TEST(AtomicExchange) {
256  TestAtomicExchange<Atomic32>();
257  TestAtomicExchange<AtomicWord>();
258 }
259 
260 
261 TEST(AtomicIncrementBounds) {
262  TestAtomicIncrementBounds<Atomic32>();
263  TestAtomicIncrementBounds<AtomicWord>();
264 }
265 
266 
267 TEST(Store) {
268  TestStore<Atomic32>();
269  TestStore<AtomicWord>();
270 }
271 
272 
274  TestLoad<Atomic32>();
275  TestLoad<AtomicWord>();
276 }
void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value)
Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr, Atomic32 old_value, Atomic32 new_value)
#define CHECK_EQU(v1, v2)
void NoBarrier_Store(volatile Atomic32 *ptr, Atomic32 value)
Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr, Atomic32 new_value)
Atomic32 Release_Load(volatile const Atomic32 *ptr)
Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr, Atomic32 increment)
void Release_Store(volatile Atomic32 *ptr, Atomic32 value)
Atomic32 NoBarrier_Load(volatile const Atomic32 *ptr)
void Load(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: shell.cc:171
Atomic32 Acquire_Load(volatile const Atomic32 *ptr)
#define NUM_BITS(T)