| 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" | 
|   11 #include "src/factory.h" |   11 #include "src/factory.h" | 
|   12  |   12  | 
|   13 // Implement Atomic accesses to SharedArrayBuffers as defined in the |   13 // Implement Atomic accesses to SharedArrayBuffers as defined in the | 
|   14 // SharedArrayBuffer draft spec, found here |   14 // SharedArrayBuffer draft spec, found here | 
|   15 // https://github.com/tc39/ecmascript_sharedmem |   15 // https://github.com/tc39/ecmascript_sharedmem | 
|   16  |   16  | 
|   17 namespace v8 { |   17 namespace v8 { | 
|   18 namespace internal { |   18 namespace internal { | 
|   19  |   19  | 
|   20 namespace { |   20 namespace { | 
|   21  |   21  | 
|   22 inline bool AtomicIsLockFree(uint32_t size) { |  | 
|   23   return size == 1 || size == 2 || size == 4; |  | 
|   24 } |  | 
|   25  |  | 
|   26 #if V8_CC_GNU |   22 #if V8_CC_GNU | 
|   27  |   23  | 
|   28 template <typename T> |   24 template <typename T> | 
|   29 inline T CompareExchangeSeqCst(T* p, T oldval, T newval) { |  | 
|   30   (void)__atomic_compare_exchange_n(p, &oldval, newval, 0, __ATOMIC_SEQ_CST, |  | 
|   31                                     __ATOMIC_SEQ_CST); |  | 
|   32   return oldval; |  | 
|   33 } |  | 
|   34  |  | 
|   35 template <typename T> |  | 
|   36 inline T AddSeqCst(T* p, T value) { |  | 
|   37   return __atomic_fetch_add(p, value, __ATOMIC_SEQ_CST); |  | 
|   38 } |  | 
|   39  |  | 
|   40 template <typename T> |  | 
|   41 inline T SubSeqCst(T* p, T value) { |  | 
|   42   return __atomic_fetch_sub(p, value, __ATOMIC_SEQ_CST); |  | 
|   43 } |  | 
|   44  |  | 
|   45 template <typename T> |  | 
|   46 inline T AndSeqCst(T* p, T value) { |  | 
|   47   return __atomic_fetch_and(p, value, __ATOMIC_SEQ_CST); |  | 
|   48 } |  | 
|   49  |  | 
|   50 template <typename T> |  | 
|   51 inline T OrSeqCst(T* p, T value) { |  | 
|   52   return __atomic_fetch_or(p, value, __ATOMIC_SEQ_CST); |  | 
|   53 } |  | 
|   54  |  | 
|   55 template <typename T> |  | 
|   56 inline T XorSeqCst(T* p, T value) { |  | 
|   57   return __atomic_fetch_xor(p, value, __ATOMIC_SEQ_CST); |  | 
|   58 } |  | 
|   59  |  | 
|   60 template <typename T> |  | 
|   61 inline T ExchangeSeqCst(T* p, T value) { |   25 inline T ExchangeSeqCst(T* p, T value) { | 
|   62   return __atomic_exchange_n(p, value, __ATOMIC_SEQ_CST); |   26   return __atomic_exchange_n(p, value, __ATOMIC_SEQ_CST); | 
|   63 } |   27 } | 
|   64  |   28  | 
|   65 #elif V8_CC_MSVC |   29 #elif V8_CC_MSVC | 
|   66  |   30  | 
|   67 #define InterlockedCompareExchange32 _InterlockedCompareExchange |  | 
|   68 #define InterlockedExchange32 _InterlockedExchange |   31 #define InterlockedExchange32 _InterlockedExchange | 
|   69 #define InterlockedExchangeAdd32 _InterlockedExchangeAdd |  | 
|   70 #define InterlockedAnd32 _InterlockedAnd |  | 
|   71 #define InterlockedOr32 _InterlockedOr |  | 
|   72 #define InterlockedXor32 _InterlockedXor |  | 
|   73 #define InterlockedExchangeAdd16 _InterlockedExchangeAdd16 |  | 
|   74 #define InterlockedCompareExchange8 _InterlockedCompareExchange8 |  | 
|   75 #define InterlockedExchangeAdd8 _InterlockedExchangeAdd8 |  | 
|   76  |   32  | 
|   77 #define ATOMIC_OPS(type, suffix, vctype)                                    \ |   33 #define ATOMIC_OPS(type, suffix, vctype)                                    \ | 
|   78   inline type AddSeqCst(type* p, type value) {                              \ |  | 
|   79     return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p),     \ |  | 
|   80                                           bit_cast<vctype>(value));         \ |  | 
|   81   }                                                                         \ |  | 
|   82   inline type SubSeqCst(type* p, type value) {                              \ |  | 
|   83     return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p),     \ |  | 
|   84                                           -bit_cast<vctype>(value));        \ |  | 
|   85   }                                                                         \ |  | 
|   86   inline type AndSeqCst(type* p, type value) {                              \ |  | 
|   87     return InterlockedAnd##suffix(reinterpret_cast<vctype*>(p),             \ |  | 
|   88                                   bit_cast<vctype>(value));                 \ |  | 
|   89   }                                                                         \ |  | 
|   90   inline type OrSeqCst(type* p, type value) {                               \ |  | 
|   91     return InterlockedOr##suffix(reinterpret_cast<vctype*>(p),              \ |  | 
|   92                                  bit_cast<vctype>(value));                  \ |  | 
|   93   }                                                                         \ |  | 
|   94   inline type XorSeqCst(type* p, type value) {                              \ |  | 
|   95     return InterlockedXor##suffix(reinterpret_cast<vctype*>(p),             \ |  | 
|   96                                   bit_cast<vctype>(value));                 \ |  | 
|   97   }                                                                         \ |  | 
|   98   inline type ExchangeSeqCst(type* p, type value) {                         \ |   34   inline type ExchangeSeqCst(type* p, type value) {                         \ | 
|   99     return InterlockedExchange##suffix(reinterpret_cast<vctype*>(p),        \ |   35     return InterlockedExchange##suffix(reinterpret_cast<vctype*>(p),        \ | 
|  100                                        bit_cast<vctype>(value));            \ |   36                                        bit_cast<vctype>(value));            \ | 
|  101   }                                                                         \ |   37   }                                                                         \ | 
|  102                                                                             \ |  | 
|  103   inline type CompareExchangeSeqCst(type* p, type oldval, type newval) {    \ |  | 
|  104     return InterlockedCompareExchange##suffix(reinterpret_cast<vctype*>(p), \ |  | 
|  105                                               bit_cast<vctype>(newval),     \ |  | 
|  106                                               bit_cast<vctype>(oldval));    \ |  | 
|  107   } |  | 
|  108  |   38  | 
|  109 ATOMIC_OPS(int8_t, 8, char) |   39 ATOMIC_OPS(int8_t, 8, char) | 
|  110 ATOMIC_OPS(uint8_t, 8, char) |   40 ATOMIC_OPS(uint8_t, 8, char) | 
|  111 ATOMIC_OPS(int16_t, 16, short)  /* NOLINT(runtime/int) */ |   41 ATOMIC_OPS(int16_t, 16, short)  /* NOLINT(runtime/int) */ | 
|  112 ATOMIC_OPS(uint16_t, 16, short) /* NOLINT(runtime/int) */ |   42 ATOMIC_OPS(uint16_t, 16, short) /* NOLINT(runtime/int) */ | 
|  113 ATOMIC_OPS(int32_t, 32, long)   /* NOLINT(runtime/int) */ |   43 ATOMIC_OPS(int32_t, 32, long)   /* NOLINT(runtime/int) */ | 
|  114 ATOMIC_OPS(uint32_t, 32, long)  /* NOLINT(runtime/int) */ |   44 ATOMIC_OPS(uint32_t, 32, long)  /* NOLINT(runtime/int) */ | 
|  115  |   45  | 
|  116 #undef ATOMIC_OPS_INTEGER |   46 #undef ATOMIC_OPS_INTEGER | 
|  117 #undef ATOMIC_OPS |   47 #undef ATOMIC_OPS | 
|  118  |   48  | 
|  119 #undef InterlockedCompareExchange32 |  | 
|  120 #undef InterlockedExchange32 |   49 #undef InterlockedExchange32 | 
|  121 #undef InterlockedExchangeAdd32 |  | 
|  122 #undef InterlockedAnd32 |  | 
|  123 #undef InterlockedOr32 |  | 
|  124 #undef InterlockedXor32 |  | 
|  125 #undef InterlockedExchangeAdd16 |  | 
|  126 #undef InterlockedCompareExchange8 |  | 
|  127 #undef InterlockedExchangeAdd8 |  | 
|  128  |   50  | 
|  129 #else |   51 #else | 
|  130  |   52  | 
|  131 #error Unsupported platform! |   53 #error Unsupported platform! | 
|  132  |   54  | 
|  133 #endif |   55 #endif | 
|  134  |   56  | 
|  135 template <typename T> |   57 template <typename T> | 
|  136 T FromObject(Handle<Object> number); |   58 T FromObject(Handle<Object> number); | 
|  137  |   59  | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  169 inline Object* ToObject(Isolate* isolate, int8_t t) { return Smi::FromInt(t); } |   91 inline Object* ToObject(Isolate* isolate, int8_t t) { return Smi::FromInt(t); } | 
|  170  |   92  | 
|  171 inline Object* ToObject(Isolate* isolate, uint8_t t) { return Smi::FromInt(t); } |   93 inline Object* ToObject(Isolate* isolate, uint8_t t) { return Smi::FromInt(t); } | 
|  172  |   94  | 
|  173 inline Object* ToObject(Isolate* isolate, int16_t t) { return Smi::FromInt(t); } |   95 inline Object* ToObject(Isolate* isolate, int16_t t) { return Smi::FromInt(t); } | 
|  174  |   96  | 
|  175 inline Object* ToObject(Isolate* isolate, uint16_t t) { |   97 inline Object* ToObject(Isolate* isolate, uint16_t t) { | 
|  176   return Smi::FromInt(t); |   98   return Smi::FromInt(t); | 
|  177 } |   99 } | 
|  178  |  100  | 
|  179  |  | 
|  180 inline Object* ToObject(Isolate* isolate, int32_t t) { |  101 inline Object* ToObject(Isolate* isolate, int32_t t) { | 
|  181   return *isolate->factory()->NewNumber(t); |  102   return *isolate->factory()->NewNumber(t); | 
|  182 } |  103 } | 
|  183  |  104  | 
|  184  |  | 
|  185 inline Object* ToObject(Isolate* isolate, uint32_t t) { |  105 inline Object* ToObject(Isolate* isolate, uint32_t t) { | 
|  186   return *isolate->factory()->NewNumber(t); |  106   return *isolate->factory()->NewNumber(t); | 
|  187 } |  107 } | 
|  188  |  108  | 
|  189  |  | 
|  190 template <typename T> |  | 
|  191 inline Object* DoCompareExchange(Isolate* isolate, void* buffer, size_t index, |  | 
|  192                                  Handle<Object> oldobj, Handle<Object> newobj) { |  | 
|  193   T oldval = FromObject<T>(oldobj); |  | 
|  194   T newval = FromObject<T>(newobj); |  | 
|  195   T result = |  | 
|  196       CompareExchangeSeqCst(static_cast<T*>(buffer) + index, oldval, newval); |  | 
|  197   return ToObject(isolate, result); |  | 
|  198 } |  | 
|  199  |  | 
|  200  |  | 
|  201 template <typename T> |  | 
|  202 inline Object* DoAdd(Isolate* isolate, void* buffer, size_t index, |  | 
|  203                      Handle<Object> obj) { |  | 
|  204   T value = FromObject<T>(obj); |  | 
|  205   T result = AddSeqCst(static_cast<T*>(buffer) + index, value); |  | 
|  206   return ToObject(isolate, result); |  | 
|  207 } |  | 
|  208  |  | 
|  209  |  | 
|  210 template <typename T> |  | 
|  211 inline Object* DoSub(Isolate* isolate, void* buffer, size_t index, |  | 
|  212                      Handle<Object> obj) { |  | 
|  213   T value = FromObject<T>(obj); |  | 
|  214   T result = SubSeqCst(static_cast<T*>(buffer) + index, value); |  | 
|  215   return ToObject(isolate, result); |  | 
|  216 } |  | 
|  217  |  | 
|  218  |  | 
|  219 template <typename T> |  | 
|  220 inline Object* DoAnd(Isolate* isolate, void* buffer, size_t index, |  | 
|  221                      Handle<Object> obj) { |  | 
|  222   T value = FromObject<T>(obj); |  | 
|  223   T result = AndSeqCst(static_cast<T*>(buffer) + index, value); |  | 
|  224   return ToObject(isolate, result); |  | 
|  225 } |  | 
|  226  |  | 
|  227  |  | 
|  228 template <typename T> |  | 
|  229 inline Object* DoOr(Isolate* isolate, void* buffer, size_t index, |  | 
|  230                     Handle<Object> obj) { |  | 
|  231   T value = FromObject<T>(obj); |  | 
|  232   T result = OrSeqCst(static_cast<T*>(buffer) + index, value); |  | 
|  233   return ToObject(isolate, result); |  | 
|  234 } |  | 
|  235  |  | 
|  236  |  | 
|  237 template <typename T> |  | 
|  238 inline Object* DoXor(Isolate* isolate, void* buffer, size_t index, |  | 
|  239                      Handle<Object> obj) { |  | 
|  240   T value = FromObject<T>(obj); |  | 
|  241   T result = XorSeqCst(static_cast<T*>(buffer) + index, value); |  | 
|  242   return ToObject(isolate, result); |  | 
|  243 } |  | 
|  244  |  | 
|  245  |  | 
|  246 template <typename T> |  109 template <typename T> | 
|  247 inline Object* DoExchange(Isolate* isolate, void* buffer, size_t index, |  110 inline Object* DoExchange(Isolate* isolate, void* buffer, size_t index, | 
|  248                           Handle<Object> obj) { |  111                           Handle<Object> obj) { | 
|  249   T value = FromObject<T>(obj); |  112   T value = FromObject<T>(obj); | 
|  250   T result = ExchangeSeqCst(static_cast<T*>(buffer) + index, value); |  113   T result = ExchangeSeqCst(static_cast<T*>(buffer) + index, value); | 
|  251   return ToObject(isolate, result); |  114   return ToObject(isolate, result); | 
|  252 } |  115 } | 
|  253  |  116  | 
|  254  |  | 
|  255 // Uint8Clamped functions |  | 
|  256  |  | 
|  257 uint8_t ClampToUint8(int32_t value) { |  | 
|  258   if (value < 0) return 0; |  | 
|  259   if (value > 255) return 255; |  | 
|  260   return value; |  | 
|  261 } |  | 
|  262  |  | 
|  263  |  | 
|  264 inline Object* DoCompareExchangeUint8Clamped(Isolate* isolate, void* buffer, |  | 
|  265                                              size_t index, |  | 
|  266                                              Handle<Object> oldobj, |  | 
|  267                                              Handle<Object> newobj) { |  | 
|  268   typedef int32_t convert_type; |  | 
|  269   uint8_t oldval = ClampToUint8(FromObject<convert_type>(oldobj)); |  | 
|  270   uint8_t newval = ClampToUint8(FromObject<convert_type>(newobj)); |  | 
|  271   uint8_t result = CompareExchangeSeqCst(static_cast<uint8_t*>(buffer) + index, |  | 
|  272                                          oldval, newval); |  | 
|  273   return ToObject(isolate, result); |  | 
|  274 } |  | 
|  275  |  | 
|  276  |  | 
|  277 #define DO_UINT8_CLAMPED_OP(name, op)                                        \ |  | 
|  278   inline Object* Do##name##Uint8Clamped(Isolate* isolate, void* buffer,      \ |  | 
|  279                                         size_t index, Handle<Object> obj) {  \ |  | 
|  280     typedef int32_t convert_type;                                            \ |  | 
|  281     uint8_t* p = static_cast<uint8_t*>(buffer) + index;                      \ |  | 
|  282     convert_type operand = FromObject<convert_type>(obj);                    \ |  | 
|  283     uint8_t expected;                                                        \ |  | 
|  284     uint8_t result;                                                          \ |  | 
|  285     do {                                                                     \ |  | 
|  286       expected = *p;                                                         \ |  | 
|  287       result = ClampToUint8(static_cast<convert_type>(expected) op operand); \ |  | 
|  288     } while (CompareExchangeSeqCst(p, expected, result) != expected);        \ |  | 
|  289     return ToObject(isolate, expected);                                      \ |  | 
|  290   } |  | 
|  291  |  | 
|  292 DO_UINT8_CLAMPED_OP(Add, +) |  | 
|  293 DO_UINT8_CLAMPED_OP(Sub, -) |  | 
|  294 DO_UINT8_CLAMPED_OP(And, &) |  | 
|  295 DO_UINT8_CLAMPED_OP(Or, | ) |  | 
|  296 DO_UINT8_CLAMPED_OP(Xor, ^) |  | 
|  297  |  | 
|  298 #undef DO_UINT8_CLAMPED_OP |  | 
|  299  |  | 
|  300  |  | 
|  301 inline Object* DoExchangeUint8Clamped(Isolate* isolate, void* buffer, |  | 
|  302                                       size_t index, Handle<Object> obj) { |  | 
|  303   typedef int32_t convert_type; |  | 
|  304   uint8_t* p = static_cast<uint8_t*>(buffer) + index; |  | 
|  305   uint8_t result = ClampToUint8(FromObject<convert_type>(obj)); |  | 
|  306   uint8_t expected; |  | 
|  307   do { |  | 
|  308     expected = *p; |  | 
|  309   } while (CompareExchangeSeqCst(p, expected, result) != expected); |  | 
|  310   return ToObject(isolate, expected); |  | 
|  311 } |  | 
|  312  |  | 
|  313  |  | 
|  314 }  // anonymous namespace |  117 }  // anonymous namespace | 
|  315  |  118  | 
|  316 // Duplicated from objects.h |  119 // Duplicated from objects.h | 
|  317 // V has parameters (Type, type, TYPE, C type, element_size) |  120 // V has parameters (Type, type, TYPE, C type, element_size) | 
|  318 #define INTEGER_TYPED_ARRAYS(V)          \ |  121 #define INTEGER_TYPED_ARRAYS(V)          \ | 
|  319   V(Uint8, uint8, UINT8, uint8_t, 1)     \ |  122   V(Uint8, uint8, UINT8, uint8_t, 1)     \ | 
|  320   V(Int8, int8, INT8, int8_t, 1)         \ |  123   V(Int8, int8, INT8, int8_t, 1)         \ | 
|  321   V(Uint16, uint16, UINT16, uint16_t, 2) \ |  124   V(Uint16, uint16, UINT16, uint16_t, 2) \ | 
|  322   V(Int16, int16, INT16, int16_t, 2)     \ |  125   V(Int16, int16, INT16, int16_t, 2)     \ | 
|  323   V(Uint32, uint32, UINT32, uint32_t, 4) \ |  126   V(Uint32, uint32, UINT32, uint32_t, 4) \ | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
|  340       isolate, NewTypeError(MessageTemplate::kNotInt32SharedTypedArray, value)); |  143       isolate, NewTypeError(MessageTemplate::kNotInt32SharedTypedArray, value)); | 
|  341 } |  144 } | 
|  342  |  145  | 
|  343 RUNTIME_FUNCTION(Runtime_ThrowInvalidAtomicAccessIndexError) { |  146 RUNTIME_FUNCTION(Runtime_ThrowInvalidAtomicAccessIndexError) { | 
|  344   HandleScope scope(isolate); |  147   HandleScope scope(isolate); | 
|  345   DCHECK_EQ(0, args.length()); |  148   DCHECK_EQ(0, args.length()); | 
|  346   THROW_NEW_ERROR_RETURN_FAILURE( |  149   THROW_NEW_ERROR_RETURN_FAILURE( | 
|  347       isolate, NewRangeError(MessageTemplate::kInvalidAtomicAccessIndex)); |  150       isolate, NewRangeError(MessageTemplate::kInvalidAtomicAccessIndex)); | 
|  348 } |  151 } | 
|  349  |  152  | 
|  350 RUNTIME_FUNCTION(Runtime_AtomicsCompareExchange) { |  | 
|  351   HandleScope scope(isolate); |  | 
|  352   DCHECK_EQ(4, args.length()); |  | 
|  353   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); |  | 
|  354   CONVERT_SIZE_ARG_CHECKED(index, 1); |  | 
|  355   CONVERT_NUMBER_ARG_HANDLE_CHECKED(oldobj, 2); |  | 
|  356   CONVERT_NUMBER_ARG_HANDLE_CHECKED(newobj, 3); |  | 
|  357   CHECK(sta->GetBuffer()->is_shared()); |  | 
|  358   CHECK_LT(index, NumberToSize(sta->length())); |  | 
|  359  |  | 
|  360   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + |  | 
|  361                     NumberToSize(sta->byte_offset()); |  | 
|  362  |  | 
|  363   switch (sta->type()) { |  | 
|  364 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |  | 
|  365   case kExternal##Type##Array:                              \ |  | 
|  366     return DoCompareExchange<ctype>(isolate, source, index, oldobj, newobj); |  | 
|  367  |  | 
|  368     INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |  | 
|  369 #undef TYPED_ARRAY_CASE |  | 
|  370  |  | 
|  371     case kExternalUint8ClampedArray: |  | 
|  372       return DoCompareExchangeUint8Clamped(isolate, source, index, oldobj, |  | 
|  373                                            newobj); |  | 
|  374  |  | 
|  375     default: |  | 
|  376       break; |  | 
|  377   } |  | 
|  378  |  | 
|  379   UNREACHABLE(); |  | 
|  380   return isolate->heap()->undefined_value(); |  | 
|  381 } |  | 
|  382  |  | 
|  383  |  | 
|  384 RUNTIME_FUNCTION(Runtime_AtomicsAdd) { |  | 
|  385   HandleScope scope(isolate); |  | 
|  386   DCHECK_EQ(3, args.length()); |  | 
|  387   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); |  | 
|  388   CONVERT_SIZE_ARG_CHECKED(index, 1); |  | 
|  389   CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); |  | 
|  390   CHECK(sta->GetBuffer()->is_shared()); |  | 
|  391   CHECK_LT(index, NumberToSize(sta->length())); |  | 
|  392  |  | 
|  393   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + |  | 
|  394                     NumberToSize(sta->byte_offset()); |  | 
|  395  |  | 
|  396   switch (sta->type()) { |  | 
|  397 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |  | 
|  398   case kExternal##Type##Array:                              \ |  | 
|  399     return DoAdd<ctype>(isolate, source, index, value); |  | 
|  400  |  | 
|  401     INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |  | 
|  402 #undef TYPED_ARRAY_CASE |  | 
|  403  |  | 
|  404     case kExternalUint8ClampedArray: |  | 
|  405       return DoAddUint8Clamped(isolate, source, index, value); |  | 
|  406  |  | 
|  407     default: |  | 
|  408       break; |  | 
|  409   } |  | 
|  410  |  | 
|  411   UNREACHABLE(); |  | 
|  412   return isolate->heap()->undefined_value(); |  | 
|  413 } |  | 
|  414  |  | 
|  415  |  | 
|  416 RUNTIME_FUNCTION(Runtime_AtomicsSub) { |  | 
|  417   HandleScope scope(isolate); |  | 
|  418   DCHECK_EQ(3, args.length()); |  | 
|  419   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); |  | 
|  420   CONVERT_SIZE_ARG_CHECKED(index, 1); |  | 
|  421   CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); |  | 
|  422   CHECK(sta->GetBuffer()->is_shared()); |  | 
|  423   CHECK_LT(index, NumberToSize(sta->length())); |  | 
|  424  |  | 
|  425   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + |  | 
|  426                     NumberToSize(sta->byte_offset()); |  | 
|  427  |  | 
|  428   switch (sta->type()) { |  | 
|  429 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |  | 
|  430   case kExternal##Type##Array:                              \ |  | 
|  431     return DoSub<ctype>(isolate, source, index, value); |  | 
|  432  |  | 
|  433     INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |  | 
|  434 #undef TYPED_ARRAY_CASE |  | 
|  435  |  | 
|  436     case kExternalUint8ClampedArray: |  | 
|  437       return DoSubUint8Clamped(isolate, source, index, value); |  | 
|  438  |  | 
|  439     default: |  | 
|  440       break; |  | 
|  441   } |  | 
|  442  |  | 
|  443   UNREACHABLE(); |  | 
|  444   return isolate->heap()->undefined_value(); |  | 
|  445 } |  | 
|  446  |  | 
|  447  |  | 
|  448 RUNTIME_FUNCTION(Runtime_AtomicsAnd) { |  | 
|  449   HandleScope scope(isolate); |  | 
|  450   DCHECK_EQ(3, args.length()); |  | 
|  451   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); |  | 
|  452   CONVERT_SIZE_ARG_CHECKED(index, 1); |  | 
|  453   CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); |  | 
|  454   CHECK(sta->GetBuffer()->is_shared()); |  | 
|  455   CHECK_LT(index, NumberToSize(sta->length())); |  | 
|  456  |  | 
|  457   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + |  | 
|  458                     NumberToSize(sta->byte_offset()); |  | 
|  459  |  | 
|  460   switch (sta->type()) { |  | 
|  461 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |  | 
|  462   case kExternal##Type##Array:                              \ |  | 
|  463     return DoAnd<ctype>(isolate, source, index, value); |  | 
|  464  |  | 
|  465     INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |  | 
|  466 #undef TYPED_ARRAY_CASE |  | 
|  467  |  | 
|  468     case kExternalUint8ClampedArray: |  | 
|  469       return DoAndUint8Clamped(isolate, source, index, value); |  | 
|  470  |  | 
|  471     default: |  | 
|  472       break; |  | 
|  473   } |  | 
|  474  |  | 
|  475   UNREACHABLE(); |  | 
|  476   return isolate->heap()->undefined_value(); |  | 
|  477 } |  | 
|  478  |  | 
|  479  |  | 
|  480 RUNTIME_FUNCTION(Runtime_AtomicsOr) { |  | 
|  481   HandleScope scope(isolate); |  | 
|  482   DCHECK_EQ(3, args.length()); |  | 
|  483   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); |  | 
|  484   CONVERT_SIZE_ARG_CHECKED(index, 1); |  | 
|  485   CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); |  | 
|  486   CHECK(sta->GetBuffer()->is_shared()); |  | 
|  487   CHECK_LT(index, NumberToSize(sta->length())); |  | 
|  488  |  | 
|  489   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + |  | 
|  490                     NumberToSize(sta->byte_offset()); |  | 
|  491  |  | 
|  492   switch (sta->type()) { |  | 
|  493 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |  | 
|  494   case kExternal##Type##Array:                              \ |  | 
|  495     return DoOr<ctype>(isolate, source, index, value); |  | 
|  496  |  | 
|  497     INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |  | 
|  498 #undef TYPED_ARRAY_CASE |  | 
|  499  |  | 
|  500     case kExternalUint8ClampedArray: |  | 
|  501       return DoOrUint8Clamped(isolate, source, index, value); |  | 
|  502  |  | 
|  503     default: |  | 
|  504       break; |  | 
|  505   } |  | 
|  506  |  | 
|  507   UNREACHABLE(); |  | 
|  508   return isolate->heap()->undefined_value(); |  | 
|  509 } |  | 
|  510  |  | 
|  511  |  | 
|  512 RUNTIME_FUNCTION(Runtime_AtomicsXor) { |  | 
|  513   HandleScope scope(isolate); |  | 
|  514   DCHECK_EQ(3, args.length()); |  | 
|  515   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); |  | 
|  516   CONVERT_SIZE_ARG_CHECKED(index, 1); |  | 
|  517   CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); |  | 
|  518   CHECK(sta->GetBuffer()->is_shared()); |  | 
|  519   CHECK_LT(index, NumberToSize(sta->length())); |  | 
|  520  |  | 
|  521   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + |  | 
|  522                     NumberToSize(sta->byte_offset()); |  | 
|  523  |  | 
|  524   switch (sta->type()) { |  | 
|  525 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |  | 
|  526   case kExternal##Type##Array:                              \ |  | 
|  527     return DoXor<ctype>(isolate, source, index, value); |  | 
|  528  |  | 
|  529     INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |  | 
|  530 #undef TYPED_ARRAY_CASE |  | 
|  531  |  | 
|  532     case kExternalUint8ClampedArray: |  | 
|  533       return DoXorUint8Clamped(isolate, source, index, value); |  | 
|  534  |  | 
|  535     default: |  | 
|  536       break; |  | 
|  537   } |  | 
|  538  |  | 
|  539   UNREACHABLE(); |  | 
|  540   return isolate->heap()->undefined_value(); |  | 
|  541 } |  | 
|  542  |  | 
|  543  |  | 
|  544 RUNTIME_FUNCTION(Runtime_AtomicsExchange) { |  153 RUNTIME_FUNCTION(Runtime_AtomicsExchange) { | 
|  545   HandleScope scope(isolate); |  154   HandleScope scope(isolate); | 
|  546   DCHECK_EQ(3, args.length()); |  155   DCHECK_EQ(3, args.length()); | 
|  547   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); |  156   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); | 
|  548   CONVERT_SIZE_ARG_CHECKED(index, 1); |  157   CONVERT_SIZE_ARG_CHECKED(index, 1); | 
|  549   CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); |  158   CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); | 
|  550   CHECK(sta->GetBuffer()->is_shared()); |  159   CHECK(sta->GetBuffer()->is_shared()); | 
|  551   CHECK_LT(index, NumberToSize(sta->length())); |  160   CHECK_LT(index, NumberToSize(sta->length())); | 
|  552  |  161  | 
|  553   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + |  162   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + | 
|  554                     NumberToSize(sta->byte_offset()); |  163                     NumberToSize(sta->byte_offset()); | 
|  555  |  164  | 
|  556   switch (sta->type()) { |  165   switch (sta->type()) { | 
|  557 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |  166 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ | 
|  558   case kExternal##Type##Array:                              \ |  167   case kExternal##Type##Array:                              \ | 
|  559     return DoExchange<ctype>(isolate, source, index, value); |  168     return DoExchange<ctype>(isolate, source, index, value); | 
|  560  |  169  | 
|  561     INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |  170     INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) | 
|  562 #undef TYPED_ARRAY_CASE |  171 #undef TYPED_ARRAY_CASE | 
|  563  |  172  | 
|  564     case kExternalUint8ClampedArray: |  | 
|  565       return DoExchangeUint8Clamped(isolate, source, index, value); |  | 
|  566  |  | 
|  567     default: |  173     default: | 
|  568       break; |  174       break; | 
|  569   } |  175   } | 
|  570  |  176  | 
|  571   UNREACHABLE(); |  177   UNREACHABLE(); | 
|  572   return isolate->heap()->undefined_value(); |  178   return isolate->heap()->undefined_value(); | 
|  573 } |  179 } | 
|  574  |  180  | 
|  575  |  181  | 
|  576 RUNTIME_FUNCTION(Runtime_AtomicsIsLockFree) { |  | 
|  577   HandleScope scope(isolate); |  | 
|  578   DCHECK_EQ(1, args.length()); |  | 
|  579   CONVERT_NUMBER_ARG_HANDLE_CHECKED(size, 0); |  | 
|  580   uint32_t usize = NumberToUint32(*size); |  | 
|  581   return isolate->heap()->ToBoolean(AtomicIsLockFree(usize)); |  | 
|  582 } |  | 
|  583 }  // namespace internal |  182 }  // namespace internal | 
|  584 }  // namespace v8 |  183 }  // namespace v8 | 
| OLD | NEW |