runtime-atomics.cc 21.2 KB
Newer Older
binji's avatar
binji committed
1 2 3 4
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "src/runtime/runtime-utils.h"
binji's avatar
binji committed
6 7 8 9

#include "src/arguments.h"
#include "src/base/macros.h"
#include "src/base/platform/mutex.h"
10 11
#include "src/conversions-inl.h"
#include "src/factory.h"
binji's avatar
binji committed
12 13 14

// Implement Atomic accesses to SharedArrayBuffers as defined in the
// SharedArrayBuffer draft spec, found here
15
// https://github.com/lars-t-hansen/ecmascript_sharedmem
binji's avatar
binji committed
16 17 18 19 20 21

namespace v8 {
namespace internal {

namespace {

22 23 24 25
inline bool AtomicIsLockFree(uint32_t size) {
  return size == 1 || size == 2 || size == 4;
}

binji's avatar
binji committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
#if V8_CC_GNU

template <typename T>
inline T CompareExchangeSeqCst(T* p, T oldval, T newval) {
  (void)__atomic_compare_exchange_n(p, &oldval, newval, 0, __ATOMIC_SEQ_CST,
                                    __ATOMIC_SEQ_CST);
  return oldval;
}

template <typename T>
inline T LoadSeqCst(T* p) {
  T result;
  __atomic_load(p, &result, __ATOMIC_SEQ_CST);
  return result;
}

template <typename T>
inline void StoreSeqCst(T* p, T value) {
  __atomic_store_n(p, value, __ATOMIC_SEQ_CST);
}

template <typename T>
inline T AddSeqCst(T* p, T value) {
  return __atomic_fetch_add(p, value, __ATOMIC_SEQ_CST);
}

template <typename T>
inline T SubSeqCst(T* p, T value) {
  return __atomic_fetch_sub(p, value, __ATOMIC_SEQ_CST);
}

template <typename T>
inline T AndSeqCst(T* p, T value) {
  return __atomic_fetch_and(p, value, __ATOMIC_SEQ_CST);
}

template <typename T>
inline T OrSeqCst(T* p, T value) {
  return __atomic_fetch_or(p, value, __ATOMIC_SEQ_CST);
}

template <typename T>
inline T XorSeqCst(T* p, T value) {
  return __atomic_fetch_xor(p, value, __ATOMIC_SEQ_CST);
}

template <typename T>
inline T ExchangeSeqCst(T* p, T value) {
  return __atomic_exchange_n(p, value, __ATOMIC_SEQ_CST);
}

#elif V8_CC_MSVC

79 80 81 82 83 84 85 86 87
#define InterlockedCompareExchange32 _InterlockedCompareExchange
#define InterlockedExchange32 _InterlockedExchange
#define InterlockedExchangeAdd32 _InterlockedExchangeAdd
#define InterlockedAnd32 _InterlockedAnd
#define InterlockedOr32 _InterlockedOr
#define InterlockedXor32 _InterlockedXor
#define InterlockedExchangeAdd16 _InterlockedExchangeAdd16
#define InterlockedCompareExchange8 _InterlockedCompareExchange8
#define InterlockedExchangeAdd8 _InterlockedExchangeAdd8
binji's avatar
binji committed
88

89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
#define ATOMIC_OPS(type, suffix, vctype)                                    \
  inline type AddSeqCst(type* p, type value) {                              \
    return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p),     \
                                          bit_cast<vctype>(value));         \
  }                                                                         \
  inline type SubSeqCst(type* p, type value) {                              \
    return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p),     \
                                          -bit_cast<vctype>(value));        \
  }                                                                         \
  inline type AndSeqCst(type* p, type value) {                              \
    return InterlockedAnd##suffix(reinterpret_cast<vctype*>(p),             \
                                  bit_cast<vctype>(value));                 \
  }                                                                         \
  inline type OrSeqCst(type* p, type value) {                               \
    return InterlockedOr##suffix(reinterpret_cast<vctype*>(p),              \
                                 bit_cast<vctype>(value));                  \
  }                                                                         \
  inline type XorSeqCst(type* p, type value) {                              \
    return InterlockedXor##suffix(reinterpret_cast<vctype*>(p),             \
                                  bit_cast<vctype>(value));                 \
  }                                                                         \
  inline type ExchangeSeqCst(type* p, type value) {                         \
    return InterlockedExchange##suffix(reinterpret_cast<vctype*>(p),        \
                                       bit_cast<vctype>(value));            \
  }                                                                         \
                                                                            \
115 116 117 118 119 120 121 122 123
  inline type CompareExchangeSeqCst(type* p, type oldval, type newval) {    \
    return InterlockedCompareExchange##suffix(reinterpret_cast<vctype*>(p), \
                                              bit_cast<vctype>(newval),     \
                                              bit_cast<vctype>(oldval));    \
  }                                                                         \
  inline type LoadSeqCst(type* p) { return *p; }                            \
  inline void StoreSeqCst(type* p, type value) {                            \
    InterlockedExchange##suffix(reinterpret_cast<vctype*>(p),               \
                                bit_cast<vctype>(value));                   \
binji's avatar
binji committed
124
  }
125 126 127 128 129 130 131 132 133

ATOMIC_OPS(int8_t, 8, char)
ATOMIC_OPS(uint8_t, 8, char)
ATOMIC_OPS(int16_t, 16, short)  /* NOLINT(runtime/int) */
ATOMIC_OPS(uint16_t, 16, short) /* NOLINT(runtime/int) */
ATOMIC_OPS(int32_t, 32, long)   /* NOLINT(runtime/int) */
ATOMIC_OPS(uint32_t, 32, long)  /* NOLINT(runtime/int) */

#undef ATOMIC_OPS_INTEGER
binji's avatar
binji committed
134 135
#undef ATOMIC_OPS

136 137 138 139 140 141 142 143 144
#undef InterlockedCompareExchange32
#undef InterlockedExchange32
#undef InterlockedExchangeAdd32
#undef InterlockedAnd32
#undef InterlockedOr32
#undef InterlockedXor32
#undef InterlockedExchangeAdd16
#undef InterlockedCompareExchange8
#undef InterlockedExchangeAdd8
binji's avatar
binji committed
145 146 147 148 149 150 151 152 153 154 155

#else

#error Unsupported platform!

#endif

template <typename T>
T FromObject(Handle<Object> number);

template <>
binji's avatar
binji committed
156
inline uint8_t FromObject<uint8_t>(Handle<Object> number) {
binji's avatar
binji committed
157 158 159 160
  return NumberToUint32(*number);
}

template <>
binji's avatar
binji committed
161
inline int8_t FromObject<int8_t>(Handle<Object> number) {
binji's avatar
binji committed
162 163 164 165
  return NumberToInt32(*number);
}

template <>
binji's avatar
binji committed
166 167
inline uint16_t FromObject<uint16_t>(Handle<Object> number) {
  return NumberToUint32(*number);
binji's avatar
binji committed
168 169 170
}

template <>
binji's avatar
binji committed
171 172
inline int16_t FromObject<int16_t>(Handle<Object> number) {
  return NumberToInt32(*number);
binji's avatar
binji committed
173 174 175
}

template <>
binji's avatar
binji committed
176 177
inline uint32_t FromObject<uint32_t>(Handle<Object> number) {
  return NumberToUint32(*number);
binji's avatar
binji committed
178 179 180
}

template <>
binji's avatar
binji committed
181 182
inline int32_t FromObject<int32_t>(Handle<Object> number) {
  return NumberToInt32(*number);
binji's avatar
binji committed
183 184 185
}


binji's avatar
binji committed
186
inline Object* ToObject(Isolate* isolate, int8_t t) { return Smi::FromInt(t); }
binji's avatar
binji committed
187

binji's avatar
binji committed
188
inline Object* ToObject(Isolate* isolate, uint8_t t) { return Smi::FromInt(t); }
binji's avatar
binji committed
189

binji's avatar
binji committed
190
inline Object* ToObject(Isolate* isolate, int16_t t) { return Smi::FromInt(t); }
binji's avatar
binji committed
191

binji's avatar
binji committed
192 193 194
inline Object* ToObject(Isolate* isolate, uint16_t t) {
  return Smi::FromInt(t);
}
binji's avatar
binji committed
195 196


binji's avatar
binji committed
197 198 199
inline Object* ToObject(Isolate* isolate, int32_t t) {
  return *isolate->factory()->NewNumber(t);
}
binji's avatar
binji committed
200 201


binji's avatar
binji committed
202 203 204
inline Object* ToObject(Isolate* isolate, uint32_t t) {
  return *isolate->factory()->NewNumber(t);
}
binji's avatar
binji committed
205 206 207 208 209


template <typename T>
inline Object* DoCompareExchange(Isolate* isolate, void* buffer, size_t index,
                                 Handle<Object> oldobj, Handle<Object> newobj) {
binji's avatar
binji committed
210 211 212 213 214
  T oldval = FromObject<T>(oldobj);
  T newval = FromObject<T>(newobj);
  T result =
      CompareExchangeSeqCst(static_cast<T*>(buffer) + index, oldval, newval);
  return ToObject(isolate, result);
binji's avatar
binji committed
215 216 217 218 219
}


template <typename T>
inline Object* DoLoad(Isolate* isolate, void* buffer, size_t index) {
binji's avatar
binji committed
220 221
  T result = LoadSeqCst(static_cast<T*>(buffer) + index);
  return ToObject(isolate, result);
binji's avatar
binji committed
222 223 224 225 226 227
}


template <typename T>
inline Object* DoStore(Isolate* isolate, void* buffer, size_t index,
                       Handle<Object> obj) {
binji's avatar
binji committed
228 229
  T value = FromObject<T>(obj);
  StoreSeqCst(static_cast<T*>(buffer) + index, value);
binji's avatar
binji committed
230 231 232 233 234 235 236
  return *obj;
}


template <typename T>
inline Object* DoAdd(Isolate* isolate, void* buffer, size_t index,
                     Handle<Object> obj) {
binji's avatar
binji committed
237 238 239
  T value = FromObject<T>(obj);
  T result = AddSeqCst(static_cast<T*>(buffer) + index, value);
  return ToObject(isolate, result);
binji's avatar
binji committed
240 241 242 243 244 245
}


template <typename T>
inline Object* DoSub(Isolate* isolate, void* buffer, size_t index,
                     Handle<Object> obj) {
binji's avatar
binji committed
246 247 248
  T value = FromObject<T>(obj);
  T result = SubSeqCst(static_cast<T*>(buffer) + index, value);
  return ToObject(isolate, result);
binji's avatar
binji committed
249 250 251 252 253 254
}


template <typename T>
inline Object* DoAnd(Isolate* isolate, void* buffer, size_t index,
                     Handle<Object> obj) {
binji's avatar
binji committed
255 256 257
  T value = FromObject<T>(obj);
  T result = AndSeqCst(static_cast<T*>(buffer) + index, value);
  return ToObject(isolate, result);
binji's avatar
binji committed
258 259 260 261 262 263
}


template <typename T>
inline Object* DoOr(Isolate* isolate, void* buffer, size_t index,
                    Handle<Object> obj) {
binji's avatar
binji committed
264 265 266
  T value = FromObject<T>(obj);
  T result = OrSeqCst(static_cast<T*>(buffer) + index, value);
  return ToObject(isolate, result);
binji's avatar
binji committed
267 268 269 270 271 272
}


template <typename T>
inline Object* DoXor(Isolate* isolate, void* buffer, size_t index,
                     Handle<Object> obj) {
binji's avatar
binji committed
273 274 275
  T value = FromObject<T>(obj);
  T result = XorSeqCst(static_cast<T*>(buffer) + index, value);
  return ToObject(isolate, result);
binji's avatar
binji committed
276 277 278 279 280 281
}


template <typename T>
inline Object* DoExchange(Isolate* isolate, void* buffer, size_t index,
                          Handle<Object> obj) {
binji's avatar
binji committed
282 283 284
  T value = FromObject<T>(obj);
  T result = ExchangeSeqCst(static_cast<T*>(buffer) + index, value);
  return ToObject(isolate, result);
binji's avatar
binji committed
285 286
}

287 288 289 290 291 292 293 294 295 296 297 298 299 300 301

// Uint8Clamped functions

uint8_t ClampToUint8(int32_t value) {
  if (value < 0) return 0;
  if (value > 255) return 255;
  return value;
}


inline Object* DoCompareExchangeUint8Clamped(Isolate* isolate, void* buffer,
                                             size_t index,
                                             Handle<Object> oldobj,
                                             Handle<Object> newobj) {
  typedef int32_t convert_type;
binji's avatar
binji committed
302 303 304 305 306
  uint8_t oldval = ClampToUint8(FromObject<convert_type>(oldobj));
  uint8_t newval = ClampToUint8(FromObject<convert_type>(newobj));
  uint8_t result = CompareExchangeSeqCst(static_cast<uint8_t*>(buffer) + index,
                                         oldval, newval);
  return ToObject(isolate, result);
307 308 309 310 311 312
}


inline Object* DoStoreUint8Clamped(Isolate* isolate, void* buffer, size_t index,
                                   Handle<Object> obj) {
  typedef int32_t convert_type;
binji's avatar
binji committed
313 314
  uint8_t value = ClampToUint8(FromObject<convert_type>(obj));
  StoreSeqCst(static_cast<uint8_t*>(buffer) + index, value);
315 316 317 318 319 320 321 322
  return *obj;
}


#define DO_UINT8_CLAMPED_OP(name, op)                                        \
  inline Object* Do##name##Uint8Clamped(Isolate* isolate, void* buffer,      \
                                        size_t index, Handle<Object> obj) {  \
    typedef int32_t convert_type;                                            \
binji's avatar
binji committed
323
    uint8_t* p = static_cast<uint8_t*>(buffer) + index;                      \
324
    convert_type operand = FromObject<convert_type>(obj);                    \
binji's avatar
binji committed
325 326
    uint8_t expected;                                                        \
    uint8_t result;                                                          \
327 328 329 330
    do {                                                                     \
      expected = *p;                                                         \
      result = ClampToUint8(static_cast<convert_type>(expected) op operand); \
    } while (CompareExchangeSeqCst(p, expected, result) != expected);        \
binji's avatar
binji committed
331
    return ToObject(isolate, expected);                                      \
332 333 334 335 336 337 338 339 340 341 342 343 344 345
  }

DO_UINT8_CLAMPED_OP(Add, +)
DO_UINT8_CLAMPED_OP(Sub, -)
DO_UINT8_CLAMPED_OP(And, &)
DO_UINT8_CLAMPED_OP(Or, | )
DO_UINT8_CLAMPED_OP(Xor, ^)

#undef DO_UINT8_CLAMPED_OP


inline Object* DoExchangeUint8Clamped(Isolate* isolate, void* buffer,
                                      size_t index, Handle<Object> obj) {
  typedef int32_t convert_type;
binji's avatar
binji committed
346 347 348
  uint8_t* p = static_cast<uint8_t*>(buffer) + index;
  uint8_t result = ClampToUint8(FromObject<convert_type>(obj));
  uint8_t expected;
349 350 351
  do {
    expected = *p;
  } while (CompareExchangeSeqCst(p, expected, result) != expected);
binji's avatar
binji committed
352
  return ToObject(isolate, expected);
353 354 355
}


binji's avatar
binji committed
356 357 358 359 360 361 362 363 364 365
}  // anonymous namespace

// Duplicated from objects.h
// V has parameters (Type, type, TYPE, C type, element_size)
#define INTEGER_TYPED_ARRAYS(V)          \
  V(Uint8, uint8, UINT8, uint8_t, 1)     \
  V(Int8, int8, INT8, int8_t, 1)         \
  V(Uint16, uint16, UINT16, uint16_t, 2) \
  V(Int16, int16, INT16, int16_t, 2)     \
  V(Uint32, uint32, UINT32, uint32_t, 4) \
366
  V(Int32, int32, INT32, int32_t, 4)
binji's avatar
binji committed
367 368 369 370 371 372 373 374 375


RUNTIME_FUNCTION(Runtime_AtomicsCompareExchange) {
  HandleScope scope(isolate);
  DCHECK(args.length() == 4);
  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
  CONVERT_SIZE_ARG_CHECKED(index, 1);
  CONVERT_NUMBER_ARG_HANDLE_CHECKED(oldobj, 2);
  CONVERT_NUMBER_ARG_HANDLE_CHECKED(newobj, 3);
376 377
  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
binji's avatar
binji committed
378

379 380
  uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                    NumberToSize(isolate, sta->byte_offset());
binji's avatar
binji committed
381 382 383 384

  switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
  case kExternal##Type##Array:                              \
385
    return DoCompareExchange<ctype>(isolate, source, index, oldobj, newobj);
binji's avatar
binji committed
386

387
    INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
binji's avatar
binji committed
388 389
#undef TYPED_ARRAY_CASE

390
    case kExternalUint8ClampedArray:
391
      return DoCompareExchangeUint8Clamped(isolate, source, index, oldobj,
392 393
                                           newobj);

binji's avatar
binji committed
394 395 396 397 398 399 400 401 402 403 404 405 406 407
    default:
      break;
  }

  UNREACHABLE();
  return isolate->heap()->undefined_value();
}


RUNTIME_FUNCTION(Runtime_AtomicsLoad) {
  HandleScope scope(isolate);
  DCHECK(args.length() == 2);
  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
  CONVERT_SIZE_ARG_CHECKED(index, 1);
408 409
  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
binji's avatar
binji committed
410

411 412
  uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                    NumberToSize(isolate, sta->byte_offset());
binji's avatar
binji committed
413 414 415 416

  switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
  case kExternal##Type##Array:                              \
417
    return DoLoad<ctype>(isolate, source, index);
binji's avatar
binji committed
418

419
    INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
binji's avatar
binji committed
420 421
#undef TYPED_ARRAY_CASE

422
    case kExternalUint8ClampedArray:
423
      return DoLoad<uint8_t>(isolate, source, index);
424

binji's avatar
binji committed
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
    default:
      break;
  }

  UNREACHABLE();
  return isolate->heap()->undefined_value();
}


RUNTIME_FUNCTION(Runtime_AtomicsStore) {
  HandleScope scope(isolate);
  DCHECK(args.length() == 3);
  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
  CONVERT_SIZE_ARG_CHECKED(index, 1);
  CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
440 441
  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
binji's avatar
binji committed
442

443 444
  uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                    NumberToSize(isolate, sta->byte_offset());
binji's avatar
binji committed
445 446 447 448

  switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
  case kExternal##Type##Array:                              \
449
    return DoStore<ctype>(isolate, source, index, value);
binji's avatar
binji committed
450

451
    INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
binji's avatar
binji committed
452 453
#undef TYPED_ARRAY_CASE

454
    case kExternalUint8ClampedArray:
455
      return DoStoreUint8Clamped(isolate, source, index, value);
456

binji's avatar
binji committed
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
    default:
      break;
  }

  UNREACHABLE();
  return isolate->heap()->undefined_value();
}


RUNTIME_FUNCTION(Runtime_AtomicsAdd) {
  HandleScope scope(isolate);
  DCHECK(args.length() == 3);
  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
  CONVERT_SIZE_ARG_CHECKED(index, 1);
  CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
472 473
  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
binji's avatar
binji committed
474

475 476
  uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                    NumberToSize(isolate, sta->byte_offset());
binji's avatar
binji committed
477 478 479 480

  switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
  case kExternal##Type##Array:                              \
481
    return DoAdd<ctype>(isolate, source, index, value);
binji's avatar
binji committed
482 483 484 485

    INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE

486
    case kExternalUint8ClampedArray:
487
      return DoAddUint8Clamped(isolate, source, index, value);
488

binji's avatar
binji committed
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
    default:
      break;
  }

  UNREACHABLE();
  return isolate->heap()->undefined_value();
}


RUNTIME_FUNCTION(Runtime_AtomicsSub) {
  HandleScope scope(isolate);
  DCHECK(args.length() == 3);
  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
  CONVERT_SIZE_ARG_CHECKED(index, 1);
  CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
504 505
  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
binji's avatar
binji committed
506

507 508
  uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                    NumberToSize(isolate, sta->byte_offset());
binji's avatar
binji committed
509 510 511 512

  switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
  case kExternal##Type##Array:                              \
513
    return DoSub<ctype>(isolate, source, index, value);
binji's avatar
binji committed
514 515 516 517

    INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE

518
    case kExternalUint8ClampedArray:
519
      return DoSubUint8Clamped(isolate, source, index, value);
520

binji's avatar
binji committed
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
    default:
      break;
  }

  UNREACHABLE();
  return isolate->heap()->undefined_value();
}


RUNTIME_FUNCTION(Runtime_AtomicsAnd) {
  HandleScope scope(isolate);
  DCHECK(args.length() == 3);
  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
  CONVERT_SIZE_ARG_CHECKED(index, 1);
  CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
536 537
  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
binji's avatar
binji committed
538

539 540
  uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                    NumberToSize(isolate, sta->byte_offset());
binji's avatar
binji committed
541 542 543 544

  switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
  case kExternal##Type##Array:                              \
545
    return DoAnd<ctype>(isolate, source, index, value);
binji's avatar
binji committed
546 547 548 549

    INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE

550
    case kExternalUint8ClampedArray:
551
      return DoAndUint8Clamped(isolate, source, index, value);
552

binji's avatar
binji committed
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
    default:
      break;
  }

  UNREACHABLE();
  return isolate->heap()->undefined_value();
}


RUNTIME_FUNCTION(Runtime_AtomicsOr) {
  HandleScope scope(isolate);
  DCHECK(args.length() == 3);
  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
  CONVERT_SIZE_ARG_CHECKED(index, 1);
  CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
568 569
  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
binji's avatar
binji committed
570

571 572
  uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                    NumberToSize(isolate, sta->byte_offset());
binji's avatar
binji committed
573 574 575 576

  switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
  case kExternal##Type##Array:                              \
577
    return DoOr<ctype>(isolate, source, index, value);
binji's avatar
binji committed
578 579 580 581

    INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE

582
    case kExternalUint8ClampedArray:
583
      return DoOrUint8Clamped(isolate, source, index, value);
584

binji's avatar
binji committed
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
    default:
      break;
  }

  UNREACHABLE();
  return isolate->heap()->undefined_value();
}


RUNTIME_FUNCTION(Runtime_AtomicsXor) {
  HandleScope scope(isolate);
  DCHECK(args.length() == 3);
  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
  CONVERT_SIZE_ARG_CHECKED(index, 1);
  CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
600 601
  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
binji's avatar
binji committed
602

603 604
  uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                    NumberToSize(isolate, sta->byte_offset());
binji's avatar
binji committed
605 606 607 608

  switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
  case kExternal##Type##Array:                              \
609
    return DoXor<ctype>(isolate, source, index, value);
binji's avatar
binji committed
610 611 612 613

    INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE

614
    case kExternalUint8ClampedArray:
615
      return DoXorUint8Clamped(isolate, source, index, value);
616

binji's avatar
binji committed
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
    default:
      break;
  }

  UNREACHABLE();
  return isolate->heap()->undefined_value();
}


RUNTIME_FUNCTION(Runtime_AtomicsExchange) {
  HandleScope scope(isolate);
  DCHECK(args.length() == 3);
  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
  CONVERT_SIZE_ARG_CHECKED(index, 1);
  CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
632 633
  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
binji's avatar
binji committed
634

635 636
  uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                    NumberToSize(isolate, sta->byte_offset());
binji's avatar
binji committed
637 638 639 640

  switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
  case kExternal##Type##Array:                              \
641
    return DoExchange<ctype>(isolate, source, index, value);
binji's avatar
binji committed
642 643 644 645

    INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE

646
    case kExternalUint8ClampedArray:
647
      return DoExchangeUint8Clamped(isolate, source, index, value);
648

binji's avatar
binji committed
649 650 651 652 653 654 655 656 657 658 659 660 661 662
    default:
      break;
  }

  UNREACHABLE();
  return isolate->heap()->undefined_value();
}


RUNTIME_FUNCTION(Runtime_AtomicsIsLockFree) {
  HandleScope scope(isolate);
  DCHECK(args.length() == 1);
  CONVERT_NUMBER_ARG_HANDLE_CHECKED(size, 0);
  uint32_t usize = NumberToUint32(*size);
663
  return isolate->heap()->ToBoolean(AtomicIsLockFree(usize));
binji's avatar
binji committed
664
}
665 666
}  // namespace internal
}  // namespace v8