OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
6 | 6 |
7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
8 #include "src/base/macros.h" | 8 #include "src/base/macros.h" |
9 #include "src/base/platform/mutex.h" | 9 #include "src/base/platform/mutex.h" |
10 #include "src/conversions-inl.h" | 10 #include "src/conversions-inl.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 return __atomic_exchange_n(p, value, __ATOMIC_SEQ_CST); | 26 return __atomic_exchange_n(p, value, __ATOMIC_SEQ_CST); |
27 } | 27 } |
28 | 28 |
29 template <typename T> | 29 template <typename T> |
30 inline T CompareExchangeSeqCst(T* p, T oldval, T newval) { | 30 inline T CompareExchangeSeqCst(T* p, T oldval, T newval) { |
31 (void)__atomic_compare_exchange_n(p, &oldval, newval, 0, __ATOMIC_SEQ_CST, | 31 (void)__atomic_compare_exchange_n(p, &oldval, newval, 0, __ATOMIC_SEQ_CST, |
32 __ATOMIC_SEQ_CST); | 32 __ATOMIC_SEQ_CST); |
33 return oldval; | 33 return oldval; |
34 } | 34 } |
35 | 35 |
| 36 template <typename T> |
| 37 inline T AddSeqCst(T* p, T value) { |
| 38 return __atomic_fetch_add(p, value, __ATOMIC_SEQ_CST); |
| 39 } |
| 40 |
| 41 template <typename T> |
| 42 inline T SubSeqCst(T* p, T value) { |
| 43 return __atomic_fetch_sub(p, value, __ATOMIC_SEQ_CST); |
| 44 } |
| 45 |
| 46 template <typename T> |
| 47 inline T AndSeqCst(T* p, T value) { |
| 48 return __atomic_fetch_and(p, value, __ATOMIC_SEQ_CST); |
| 49 } |
| 50 |
| 51 template <typename T> |
| 52 inline T OrSeqCst(T* p, T value) { |
| 53 return __atomic_fetch_or(p, value, __ATOMIC_SEQ_CST); |
| 54 } |
| 55 |
| 56 template <typename T> |
| 57 inline T XorSeqCst(T* p, T value) { |
| 58 return __atomic_fetch_xor(p, value, __ATOMIC_SEQ_CST); |
| 59 } |
| 60 |
36 #elif V8_CC_MSVC | 61 #elif V8_CC_MSVC |
37 | 62 |
38 #define InterlockedExchange32 _InterlockedExchange | 63 #define InterlockedExchange32 _InterlockedExchange |
39 #define InterlockedCompareExchange32 _InterlockedCompareExchange | 64 #define InterlockedCompareExchange32 _InterlockedCompareExchange |
40 #define InterlockedCompareExchange8 _InterlockedCompareExchange8 | 65 #define InterlockedCompareExchange8 _InterlockedCompareExchange8 |
| 66 #define InterlockedExchangeAdd32 _InterlockedExchangeAdd |
| 67 #define InterlockedExchangeAdd16 _InterlockedExchangeAdd16 |
| 68 #define InterlockedExchangeAdd8 _InterlockedExchangeAdd8 |
| 69 #define InterlockedAnd32 _InterlockedAnd |
| 70 #define InterlockedOr32 _InterlockedOr |
| 71 #define InterlockedXor32 _InterlockedXor |
41 | 72 |
42 #define ATOMIC_OPS(type, suffix, vctype) \ | 73 #define ATOMIC_OPS(type, suffix, vctype) \ |
43 inline type ExchangeSeqCst(type* p, type value) { \ | 74 inline type ExchangeSeqCst(type* p, type value) { \ |
44 return InterlockedExchange##suffix(reinterpret_cast<vctype*>(p), \ | 75 return InterlockedExchange##suffix(reinterpret_cast<vctype*>(p), \ |
45 bit_cast<vctype>(value)); \ | 76 bit_cast<vctype>(value)); \ |
46 } \ | 77 } \ |
47 inline type CompareExchangeSeqCst(type* p, type oldval, type newval) { \ | 78 inline type CompareExchangeSeqCst(type* p, type oldval, type newval) { \ |
48 return InterlockedCompareExchange##suffix(reinterpret_cast<vctype*>(p), \ | 79 return InterlockedCompareExchange##suffix(reinterpret_cast<vctype*>(p), \ |
49 bit_cast<vctype>(newval), \ | 80 bit_cast<vctype>(newval), \ |
50 bit_cast<vctype>(oldval)); \ | 81 bit_cast<vctype>(oldval)); \ |
| 82 } \ |
| 83 inline type AddSeqCst(type* p, type value) { \ |
| 84 return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \ |
| 85 bit_cast<vctype>(value)); \ |
| 86 } \ |
| 87 inline type SubSeqCst(type* p, type value) { \ |
| 88 return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \ |
| 89 -bit_cast<vctype>(value)); \ |
| 90 } \ |
| 91 inline type AndSeqCst(type* p, type value) { \ |
| 92 return InterlockedAnd##suffix(reinterpret_cast<vctype*>(p), \ |
| 93 bit_cast<vctype>(value)); \ |
| 94 } \ |
| 95 inline type OrSeqCst(type* p, type value) { \ |
| 96 return InterlockedOr##suffix(reinterpret_cast<vctype*>(p), \ |
| 97 bit_cast<vctype>(value)); \ |
| 98 } \ |
| 99 inline type XorSeqCst(type* p, type value) { \ |
| 100 return InterlockedXor##suffix(reinterpret_cast<vctype*>(p), \ |
| 101 bit_cast<vctype>(value)); \ |
51 } | 102 } |
52 | 103 |
53 ATOMIC_OPS(int8_t, 8, char) | 104 ATOMIC_OPS(int8_t, 8, char) |
54 ATOMIC_OPS(uint8_t, 8, char) | 105 ATOMIC_OPS(uint8_t, 8, char) |
55 ATOMIC_OPS(int16_t, 16, short) /* NOLINT(runtime/int) */ | 106 ATOMIC_OPS(int16_t, 16, short) /* NOLINT(runtime/int) */ |
56 ATOMIC_OPS(uint16_t, 16, short) /* NOLINT(runtime/int) */ | 107 ATOMIC_OPS(uint16_t, 16, short) /* NOLINT(runtime/int) */ |
57 ATOMIC_OPS(int32_t, 32, long) /* NOLINT(runtime/int) */ | 108 ATOMIC_OPS(int32_t, 32, long) /* NOLINT(runtime/int) */ |
58 ATOMIC_OPS(uint32_t, 32, long) /* NOLINT(runtime/int) */ | 109 ATOMIC_OPS(uint32_t, 32, long) /* NOLINT(runtime/int) */ |
59 | 110 |
60 #undef ATOMIC_OPS_INTEGER | 111 #undef ATOMIC_OPS_INTEGER |
61 #undef ATOMIC_OPS | 112 #undef ATOMIC_OPS |
62 | 113 |
63 #undef InterlockedExchange32 | 114 #undef InterlockedExchange32 |
64 #undef InterlockedCompareExchange32 | 115 #undef InterlockedCompareExchange32 |
65 #undef InterlockedCompareExchange8 | 116 #undef InterlockedCompareExchange8 |
| 117 #undef InterlockedExchangeAdd32 |
| 118 #undef InterlockedExchangeAdd16 |
| 119 #undef InterlockedExchangeAdd8 |
| 120 #undef InterlockedAnd32 |
| 121 #undef InterlockedOr32 |
| 122 #undef InterlockedXor32 |
66 | 123 |
67 #else | 124 #else |
68 | 125 |
69 #error Unsupported platform! | 126 #error Unsupported platform! |
70 | 127 |
71 #endif | 128 #endif |
72 | 129 |
73 template <typename T> | 130 template <typename T> |
74 T FromObject(Handle<Object> number); | 131 T FromObject(Handle<Object> number); |
75 | 132 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 template <typename T> | 190 template <typename T> |
134 inline Object* DoCompareExchange(Isolate* isolate, void* buffer, size_t index, | 191 inline Object* DoCompareExchange(Isolate* isolate, void* buffer, size_t index, |
135 Handle<Object> oldobj, Handle<Object> newobj) { | 192 Handle<Object> oldobj, Handle<Object> newobj) { |
136 T oldval = FromObject<T>(oldobj); | 193 T oldval = FromObject<T>(oldobj); |
137 T newval = FromObject<T>(newobj); | 194 T newval = FromObject<T>(newobj); |
138 T result = | 195 T result = |
139 CompareExchangeSeqCst(static_cast<T*>(buffer) + index, oldval, newval); | 196 CompareExchangeSeqCst(static_cast<T*>(buffer) + index, oldval, newval); |
140 return ToObject(isolate, result); | 197 return ToObject(isolate, result); |
141 } | 198 } |
142 | 199 |
| 200 template <typename T> |
| 201 inline Object* DoAdd(Isolate* isolate, void* buffer, size_t index, |
| 202 Handle<Object> obj) { |
| 203 T value = FromObject<T>(obj); |
| 204 T result = AddSeqCst(static_cast<T*>(buffer) + index, value); |
| 205 return ToObject(isolate, result); |
| 206 } |
| 207 |
| 208 template <typename T> |
| 209 inline Object* DoSub(Isolate* isolate, void* buffer, size_t index, |
| 210 Handle<Object> obj) { |
| 211 T value = FromObject<T>(obj); |
| 212 T result = SubSeqCst(static_cast<T*>(buffer) + index, value); |
| 213 return ToObject(isolate, result); |
| 214 } |
| 215 |
| 216 template <typename T> |
| 217 inline Object* DoAnd(Isolate* isolate, void* buffer, size_t index, |
| 218 Handle<Object> obj) { |
| 219 T value = FromObject<T>(obj); |
| 220 T result = AndSeqCst(static_cast<T*>(buffer) + index, value); |
| 221 return ToObject(isolate, result); |
| 222 } |
| 223 |
| 224 template <typename T> |
| 225 inline Object* DoOr(Isolate* isolate, void* buffer, size_t index, |
| 226 Handle<Object> obj) { |
| 227 T value = FromObject<T>(obj); |
| 228 T result = OrSeqCst(static_cast<T*>(buffer) + index, value); |
| 229 return ToObject(isolate, result); |
| 230 } |
| 231 |
| 232 template <typename T> |
| 233 inline Object* DoXor(Isolate* isolate, void* buffer, size_t index, |
| 234 Handle<Object> obj) { |
| 235 T value = FromObject<T>(obj); |
| 236 T result = XorSeqCst(static_cast<T*>(buffer) + index, value); |
| 237 return ToObject(isolate, result); |
| 238 } |
| 239 |
143 } // anonymous namespace | 240 } // anonymous namespace |
144 | 241 |
145 // Duplicated from objects.h | 242 // Duplicated from objects.h |
146 // V has parameters (Type, type, TYPE, C type, element_size) | 243 // V has parameters (Type, type, TYPE, C type, element_size) |
147 #define INTEGER_TYPED_ARRAYS(V) \ | 244 #define INTEGER_TYPED_ARRAYS(V) \ |
148 V(Uint8, uint8, UINT8, uint8_t, 1) \ | 245 V(Uint8, uint8, UINT8, uint8_t, 1) \ |
149 V(Int8, int8, INT8, int8_t, 1) \ | 246 V(Int8, int8, INT8, int8_t, 1) \ |
150 V(Uint16, uint16, UINT16, uint16_t, 2) \ | 247 V(Uint16, uint16, UINT16, uint16_t, 2) \ |
151 V(Int16, int16, INT16, int16_t, 2) \ | 248 V(Int16, int16, INT16, int16_t, 2) \ |
152 V(Uint32, uint32, UINT32, uint32_t, 4) \ | 249 V(Uint32, uint32, UINT32, uint32_t, 4) \ |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 #undef TYPED_ARRAY_CASE | 323 #undef TYPED_ARRAY_CASE |
227 | 324 |
228 default: | 325 default: |
229 break; | 326 break; |
230 } | 327 } |
231 | 328 |
232 UNREACHABLE(); | 329 UNREACHABLE(); |
233 return isolate->heap()->undefined_value(); | 330 return isolate->heap()->undefined_value(); |
234 } | 331 } |
235 | 332 |
| 333 // ES #sec-atomics.add |
| 334 // Atomics.add( typedArray, index, value ) |
| 335 RUNTIME_FUNCTION(Runtime_AtomicsAdd) { |
| 336 HandleScope scope(isolate); |
| 337 DCHECK_EQ(3, args.length()); |
| 338 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); |
| 339 CONVERT_SIZE_ARG_CHECKED(index, 1); |
| 340 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); |
| 341 CHECK(sta->GetBuffer()->is_shared()); |
| 342 CHECK_LT(index, NumberToSize(sta->length())); |
| 343 |
| 344 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + |
| 345 NumberToSize(sta->byte_offset()); |
| 346 |
| 347 switch (sta->type()) { |
| 348 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |
| 349 case kExternal##Type##Array: \ |
| 350 return DoAdd<ctype>(isolate, source, index, value); |
| 351 |
| 352 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 353 #undef TYPED_ARRAY_CASE |
| 354 |
| 355 default: |
| 356 break; |
| 357 } |
| 358 |
| 359 UNREACHABLE(); |
| 360 return isolate->heap()->undefined_value(); |
| 361 } |
| 362 |
| 363 // ES #sec-atomics.sub |
| 364 // Atomics.sub( typedArray, index, value ) |
| 365 RUNTIME_FUNCTION(Runtime_AtomicsSub) { |
| 366 HandleScope scope(isolate); |
| 367 DCHECK_EQ(3, args.length()); |
| 368 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); |
| 369 CONVERT_SIZE_ARG_CHECKED(index, 1); |
| 370 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); |
| 371 CHECK(sta->GetBuffer()->is_shared()); |
| 372 CHECK_LT(index, NumberToSize(sta->length())); |
| 373 |
| 374 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + |
| 375 NumberToSize(sta->byte_offset()); |
| 376 |
| 377 switch (sta->type()) { |
| 378 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |
| 379 case kExternal##Type##Array: \ |
| 380 return DoSub<ctype>(isolate, source, index, value); |
| 381 |
| 382 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 383 #undef TYPED_ARRAY_CASE |
| 384 |
| 385 default: |
| 386 break; |
| 387 } |
| 388 |
| 389 UNREACHABLE(); |
| 390 return isolate->heap()->undefined_value(); |
| 391 } |
| 392 |
| 393 // ES #sec-atomics.and |
| 394 // Atomics.and( typedArray, index, value ) |
| 395 RUNTIME_FUNCTION(Runtime_AtomicsAnd) { |
| 396 HandleScope scope(isolate); |
| 397 DCHECK_EQ(3, args.length()); |
| 398 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); |
| 399 CONVERT_SIZE_ARG_CHECKED(index, 1); |
| 400 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); |
| 401 CHECK(sta->GetBuffer()->is_shared()); |
| 402 CHECK_LT(index, NumberToSize(sta->length())); |
| 403 |
| 404 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + |
| 405 NumberToSize(sta->byte_offset()); |
| 406 |
| 407 switch (sta->type()) { |
| 408 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |
| 409 case kExternal##Type##Array: \ |
| 410 return DoAnd<ctype>(isolate, source, index, value); |
| 411 |
| 412 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 413 #undef TYPED_ARRAY_CASE |
| 414 |
| 415 default: |
| 416 break; |
| 417 } |
| 418 |
| 419 UNREACHABLE(); |
| 420 return isolate->heap()->undefined_value(); |
| 421 } |
| 422 |
| 423 // ES #sec-atomics.or |
| 424 // Atomics.or( typedArray, index, value ) |
| 425 RUNTIME_FUNCTION(Runtime_AtomicsOr) { |
| 426 HandleScope scope(isolate); |
| 427 DCHECK_EQ(3, args.length()); |
| 428 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); |
| 429 CONVERT_SIZE_ARG_CHECKED(index, 1); |
| 430 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); |
| 431 CHECK(sta->GetBuffer()->is_shared()); |
| 432 CHECK_LT(index, NumberToSize(sta->length())); |
| 433 |
| 434 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + |
| 435 NumberToSize(sta->byte_offset()); |
| 436 |
| 437 switch (sta->type()) { |
| 438 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |
| 439 case kExternal##Type##Array: \ |
| 440 return DoOr<ctype>(isolate, source, index, value); |
| 441 |
| 442 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 443 #undef TYPED_ARRAY_CASE |
| 444 |
| 445 default: |
| 446 break; |
| 447 } |
| 448 |
| 449 UNREACHABLE(); |
| 450 return isolate->heap()->undefined_value(); |
| 451 } |
| 452 |
| 453 // ES #sec-atomics.xor |
| 454 // Atomics.xor( typedArray, index, value ) |
| 455 RUNTIME_FUNCTION(Runtime_AtomicsXor) { |
| 456 HandleScope scope(isolate); |
| 457 DCHECK_EQ(3, args.length()); |
| 458 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); |
| 459 CONVERT_SIZE_ARG_CHECKED(index, 1); |
| 460 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); |
| 461 CHECK(sta->GetBuffer()->is_shared()); |
| 462 CHECK_LT(index, NumberToSize(sta->length())); |
| 463 |
| 464 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + |
| 465 NumberToSize(sta->byte_offset()); |
| 466 |
| 467 switch (sta->type()) { |
| 468 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |
| 469 case kExternal##Type##Array: \ |
| 470 return DoXor<ctype>(isolate, source, index, value); |
| 471 |
| 472 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 473 #undef TYPED_ARRAY_CASE |
| 474 |
| 475 default: |
| 476 break; |
| 477 } |
| 478 |
| 479 UNREACHABLE(); |
| 480 return isolate->heap()->undefined_value(); |
| 481 } |
| 482 |
236 } // namespace internal | 483 } // namespace internal |
237 } // namespace v8 | 484 } // namespace v8 |
OLD | NEW |