Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/builtins/builtins-sharedarraybuffer.cc

Issue 2623633003: [Atomics] Make Atomics.exchange a builtin using TF (Closed)
Patch Set: fix win Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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/base/macros.h" 5 #include "src/base/macros.h"
6 #include "src/base/platform/mutex.h" 6 #include "src/base/platform/mutex.h"
7 #include "src/base/platform/time.h" 7 #include "src/base/platform/time.h"
8 #include "src/builtins/builtins-utils.h" 8 #include "src/builtins/builtins-utils.h"
9 #include "src/builtins/builtins.h" 9 #include "src/builtins/builtins.h"
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 a.Bind(&u32); 266 a.Bind(&u32);
267 a.AtomicStore(MachineRepresentation::kWord32, backing_store, 267 a.AtomicStore(MachineRepresentation::kWord32, backing_store,
268 a.WordShl(index_word, 2), value_word32); 268 a.WordShl(index_word, 2), value_word32);
269 a.Return(value_integer); 269 a.Return(value_integer);
270 270
271 // This shouldn't happen, we've already validated the type. 271 // This shouldn't happen, we've already validated the type.
272 a.Bind(&other); 272 a.Bind(&other);
273 a.Return(a.SmiConstant(0)); 273 a.Return(a.SmiConstant(0));
274 } 274 }
275 275
276 void Builtins::Generate_AtomicsExchange(compiler::CodeAssemblerState* state) {
277 using compiler::Node;
278 CodeStubAssembler a(state);
279 Node* array = a.Parameter(1);
280 Node* index = a.Parameter(2);
281 Node* value = a.Parameter(3);
282 Node* context = a.Parameter(4 + 2);
283
284 Node* instance_type;
285 Node* backing_store;
286 ValidateSharedTypedArray(&a, array, context, &instance_type, &backing_store);
287
288 Node* index_word32 = ConvertTaggedAtomicIndexToWord32(&a, index, context);
289 Node* array_length_word32 = a.TruncateTaggedToWord32(
290 context, a.LoadObjectField(array, JSTypedArray::kLengthOffset));
291 ValidateAtomicIndex(&a, index_word32, array_length_word32, context);
292 Node* index_word = a.ChangeUint32ToWord(index_word32);
293
294 Node* value_integer = a.ToInteger(context, value);
295 Node* value_word32 = a.TruncateTaggedToWord32(context, value_integer);
296
297 CodeStubAssembler::Label i8(&a), u8(&a), i16(&a), u16(&a), i32(&a), u32(&a),
298 other(&a);
299 int32_t case_values[] = {
300 FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
301 FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
302 };
303 CodeStubAssembler::Label* case_labels[] = {
304 &i8, &u8, &i16, &u16, &i32, &u32,
305 };
306 a.Switch(instance_type, &other, case_values, case_labels,
307 arraysize(case_labels));
308
309 a.Bind(&i8);
310 a.Return(a.SmiFromWord32(a.AtomicExchange(MachineType::Int8(), backing_store,
311 index_word, value_word32)));
312
313 a.Bind(&u8);
314 a.Return(a.SmiFromWord32(a.AtomicExchange(MachineType::Uint8(), backing_store,
315 index_word, value_word32)));
316
317 a.Bind(&i16);
318 a.Return(a.SmiFromWord32(a.AtomicExchange(MachineType::Int16(), backing_store,
319 a.WordShl(index_word, 1),
320 value_word32)));
321
322 a.Bind(&u16);
323 a.Return(a.SmiFromWord32(
324 a.AtomicExchange(MachineType::Uint16(), backing_store,
325 a.WordShl(index_word, 1), value_word32)));
326
327 a.Bind(&i32);
328 a.Return(a.ChangeInt32ToTagged(
329 a.AtomicExchange(MachineType::Int32(), backing_store,
330 a.WordShl(index_word, 2), value_word32)));
331
332 a.Bind(&u32);
333 a.Return(a.ChangeUint32ToTagged(
334 a.AtomicExchange(MachineType::Uint32(), backing_store,
335 a.WordShl(index_word, 2), value_word32)));
336
337 // This shouldn't happen, we've already validated the type.
338 a.Bind(&other);
339 a.Return(a.SmiConstant(0));
340 }
341
276 inline bool AtomicIsLockFree(uint32_t size) { 342 inline bool AtomicIsLockFree(uint32_t size) {
277 return size == 1 || size == 2 || size == 4; 343 return size == 1 || size == 2 || size == 4;
278 } 344 }
279 345
280 // ES #sec-atomics.islockfree 346 // ES #sec-atomics.islockfree
281 BUILTIN(AtomicsIsLockFree) { 347 BUILTIN(AtomicsIsLockFree) {
282 HandleScope scope(isolate); 348 HandleScope scope(isolate);
283 Handle<Object> size = args.atOrUndefined(isolate, 1); 349 Handle<Object> size = args.atOrUndefined(isolate, 1);
284 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, size, Object::ToNumber(size)); 350 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, size, Object::ToNumber(size));
285 return *isolate->factory()->ToBoolean(AtomicIsLockFree(size->Number())); 351 return *isolate->factory()->ToBoolean(AtomicIsLockFree(size->Number()));
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 template <typename T> 513 template <typename T>
448 inline T OrSeqCst(T* p, T value) { 514 inline T OrSeqCst(T* p, T value) {
449 return __atomic_fetch_or(p, value, __ATOMIC_SEQ_CST); 515 return __atomic_fetch_or(p, value, __ATOMIC_SEQ_CST);
450 } 516 }
451 517
452 template <typename T> 518 template <typename T>
453 inline T XorSeqCst(T* p, T value) { 519 inline T XorSeqCst(T* p, T value) {
454 return __atomic_fetch_xor(p, value, __ATOMIC_SEQ_CST); 520 return __atomic_fetch_xor(p, value, __ATOMIC_SEQ_CST);
455 } 521 }
456 522
457 template <typename T>
458 inline T ExchangeSeqCst(T* p, T value) {
459 return __atomic_exchange_n(p, value, __ATOMIC_SEQ_CST);
460 }
461 523
462 #elif V8_CC_MSVC 524 #elif V8_CC_MSVC
463 525
464 #define InterlockedCompareExchange32 _InterlockedCompareExchange 526 #define InterlockedCompareExchange32 _InterlockedCompareExchange
465 #define InterlockedExchange32 _InterlockedExchange
466 #define InterlockedExchangeAdd32 _InterlockedExchangeAdd 527 #define InterlockedExchangeAdd32 _InterlockedExchangeAdd
467 #define InterlockedAnd32 _InterlockedAnd 528 #define InterlockedAnd32 _InterlockedAnd
468 #define InterlockedOr32 _InterlockedOr 529 #define InterlockedOr32 _InterlockedOr
469 #define InterlockedXor32 _InterlockedXor 530 #define InterlockedXor32 _InterlockedXor
470 #define InterlockedExchangeAdd16 _InterlockedExchangeAdd16 531 #define InterlockedExchangeAdd16 _InterlockedExchangeAdd16
471 #define InterlockedCompareExchange8 _InterlockedCompareExchange8 532 #define InterlockedCompareExchange8 _InterlockedCompareExchange8
472 #define InterlockedExchangeAdd8 _InterlockedExchangeAdd8 533 #define InterlockedExchangeAdd8 _InterlockedExchangeAdd8
473 534
474 #define ATOMIC_OPS(type, suffix, vctype) \ 535 #define ATOMIC_OPS(type, suffix, vctype) \
475 inline type AddSeqCst(type* p, type value) { \ 536 inline type AddSeqCst(type* p, type value) { \
476 return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \ 537 return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \
477 bit_cast<vctype>(value)); \ 538 bit_cast<vctype>(value)); \
478 } \ 539 } \
479 inline type SubSeqCst(type* p, type value) { \ 540 inline type SubSeqCst(type* p, type value) { \
480 return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \ 541 return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \
481 -bit_cast<vctype>(value)); \ 542 -bit_cast<vctype>(value)); \
482 } \ 543 } \
483 inline type AndSeqCst(type* p, type value) { \ 544 inline type AndSeqCst(type* p, type value) { \
484 return InterlockedAnd##suffix(reinterpret_cast<vctype*>(p), \ 545 return InterlockedAnd##suffix(reinterpret_cast<vctype*>(p), \
485 bit_cast<vctype>(value)); \ 546 bit_cast<vctype>(value)); \
486 } \ 547 } \
487 inline type OrSeqCst(type* p, type value) { \ 548 inline type OrSeqCst(type* p, type value) { \
488 return InterlockedOr##suffix(reinterpret_cast<vctype*>(p), \ 549 return InterlockedOr##suffix(reinterpret_cast<vctype*>(p), \
489 bit_cast<vctype>(value)); \ 550 bit_cast<vctype>(value)); \
490 } \ 551 } \
491 inline type XorSeqCst(type* p, type value) { \ 552 inline type XorSeqCst(type* p, type value) { \
492 return InterlockedXor##suffix(reinterpret_cast<vctype*>(p), \ 553 return InterlockedXor##suffix(reinterpret_cast<vctype*>(p), \
493 bit_cast<vctype>(value)); \ 554 bit_cast<vctype>(value)); \
494 } \ 555 } \
495 inline type ExchangeSeqCst(type* p, type value) { \
496 return InterlockedExchange##suffix(reinterpret_cast<vctype*>(p), \
497 bit_cast<vctype>(value)); \
498 } \
499 \ 556 \
500 inline type CompareExchangeSeqCst(type* p, type oldval, type newval) { \ 557 inline type CompareExchangeSeqCst(type* p, type oldval, type newval) { \
501 return InterlockedCompareExchange##suffix(reinterpret_cast<vctype*>(p), \ 558 return InterlockedCompareExchange##suffix(reinterpret_cast<vctype*>(p), \
502 bit_cast<vctype>(newval), \ 559 bit_cast<vctype>(newval), \
503 bit_cast<vctype>(oldval)); \ 560 bit_cast<vctype>(oldval)); \
504 } 561 }
505 562
506 ATOMIC_OPS(int8_t, 8, char) 563 ATOMIC_OPS(int8_t, 8, char)
507 ATOMIC_OPS(uint8_t, 8, char) 564 ATOMIC_OPS(uint8_t, 8, char)
508 ATOMIC_OPS(int16_t, 16, short) /* NOLINT(runtime/int) */ 565 ATOMIC_OPS(int16_t, 16, short) /* NOLINT(runtime/int) */
509 ATOMIC_OPS(uint16_t, 16, short) /* NOLINT(runtime/int) */ 566 ATOMIC_OPS(uint16_t, 16, short) /* NOLINT(runtime/int) */
510 ATOMIC_OPS(int32_t, 32, long) /* NOLINT(runtime/int) */ 567 ATOMIC_OPS(int32_t, 32, long) /* NOLINT(runtime/int) */
511 ATOMIC_OPS(uint32_t, 32, long) /* NOLINT(runtime/int) */ 568 ATOMIC_OPS(uint32_t, 32, long) /* NOLINT(runtime/int) */
512 569
513 #undef ATOMIC_OPS_INTEGER 570 #undef ATOMIC_OPS_INTEGER
514 #undef ATOMIC_OPS 571 #undef ATOMIC_OPS
515 572
516 #undef InterlockedCompareExchange32 573 #undef InterlockedCompareExchange32
517 #undef InterlockedExchange32
518 #undef InterlockedExchangeAdd32 574 #undef InterlockedExchangeAdd32
519 #undef InterlockedAnd32 575 #undef InterlockedAnd32
520 #undef InterlockedOr32 576 #undef InterlockedOr32
521 #undef InterlockedXor32 577 #undef InterlockedXor32
522 #undef InterlockedExchangeAdd16 578 #undef InterlockedExchangeAdd16
523 #undef InterlockedCompareExchange8 579 #undef InterlockedCompareExchange8
524 #undef InterlockedExchangeAdd8 580 #undef InterlockedExchangeAdd8
525 581
526 #else 582 #else
527 583
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 } 679 }
624 680
625 template <typename T> 681 template <typename T>
626 inline Object* DoXor(Isolate* isolate, void* buffer, size_t index, 682 inline Object* DoXor(Isolate* isolate, void* buffer, size_t index,
627 Handle<Object> obj) { 683 Handle<Object> obj) {
628 T value = FromObject<T>(obj); 684 T value = FromObject<T>(obj);
629 T result = XorSeqCst(static_cast<T*>(buffer) + index, value); 685 T result = XorSeqCst(static_cast<T*>(buffer) + index, value);
630 return ToObject(isolate, result); 686 return ToObject(isolate, result);
631 } 687 }
632 688
633 template <typename T>
634 inline Object* DoExchange(Isolate* isolate, void* buffer, size_t index,
635 Handle<Object> obj) {
636 T value = FromObject<T>(obj);
637 T result = ExchangeSeqCst(static_cast<T*>(buffer) + index, value);
638 return ToObject(isolate, result);
639 }
640
641 // Uint8Clamped functions 689 // Uint8Clamped functions
642 690
643 uint8_t ClampToUint8(int32_t value) { 691 uint8_t ClampToUint8(int32_t value) {
644 if (value < 0) return 0; 692 if (value < 0) return 0;
645 if (value > 255) return 255; 693 if (value > 255) return 255;
646 return value; 694 return value;
647 } 695 }
648 696
649 inline Object* DoCompareExchangeUint8Clamped(Isolate* isolate, void* buffer, 697 inline Object* DoCompareExchangeUint8Clamped(Isolate* isolate, void* buffer,
650 size_t index, 698 size_t index,
(...skipping 23 matching lines...) Expand all
674 } 722 }
675 723
676 DO_UINT8_CLAMPED_OP(Add, +) 724 DO_UINT8_CLAMPED_OP(Add, +)
677 DO_UINT8_CLAMPED_OP(Sub, -) 725 DO_UINT8_CLAMPED_OP(Sub, -)
678 DO_UINT8_CLAMPED_OP(And, &) 726 DO_UINT8_CLAMPED_OP(And, &)
679 DO_UINT8_CLAMPED_OP(Or, |) 727 DO_UINT8_CLAMPED_OP(Or, |)
680 DO_UINT8_CLAMPED_OP(Xor, ^) 728 DO_UINT8_CLAMPED_OP(Xor, ^)
681 729
682 #undef DO_UINT8_CLAMPED_OP 730 #undef DO_UINT8_CLAMPED_OP
683 731
684 inline Object* DoExchangeUint8Clamped(Isolate* isolate, void* buffer,
685 size_t index, Handle<Object> obj) {
686 typedef int32_t convert_type;
687 uint8_t* p = static_cast<uint8_t*>(buffer) + index;
688 uint8_t result = ClampToUint8(FromObject<convert_type>(obj));
689 uint8_t expected;
690 do {
691 expected = *p;
692 } while (CompareExchangeSeqCst(p, expected, result) != expected);
693 return ToObject(isolate, expected);
694 }
695 732
696 } // anonymous namespace 733 } // anonymous namespace
697 734
698 // Duplicated from objects.h 735 // Duplicated from objects.h
699 // V has parameters (Type, type, TYPE, C type, element_size) 736 // V has parameters (Type, type, TYPE, C type, element_size)
700 #define INTEGER_TYPED_ARRAYS(V) \ 737 #define INTEGER_TYPED_ARRAYS(V) \
701 V(Uint8, uint8, UINT8, uint8_t, 1) \ 738 V(Uint8, uint8, UINT8, uint8_t, 1) \
702 V(Int8, int8, INT8, int8_t, 1) \ 739 V(Int8, int8, INT8, int8_t, 1) \
703 V(Uint16, uint16, UINT16, uint16_t, 2) \ 740 V(Uint16, uint16, UINT16, uint16_t, 2) \
704 V(Int16, int16, INT16, int16_t, 2) \ 741 V(Int16, int16, INT16, int16_t, 2) \
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 return DoXorUint8Clamped(isolate, source, i, value); 987 return DoXorUint8Clamped(isolate, source, i, value);
951 988
952 default: 989 default:
953 break; 990 break;
954 } 991 }
955 992
956 UNREACHABLE(); 993 UNREACHABLE();
957 return isolate->heap()->undefined_value(); 994 return isolate->heap()->undefined_value();
958 } 995 }
959 996
960 // ES #sec-atomics.exchange
961 // Atomics.exchange( typedArray, index, value )
962 BUILTIN(AtomicsExchange) {
963 HandleScope scope(isolate);
964 Handle<Object> array = args.atOrUndefined(isolate, 1);
965 Handle<Object> index = args.atOrUndefined(isolate, 2);
966 Handle<Object> value = args.atOrUndefined(isolate, 3);
967
968 Handle<JSTypedArray> sta;
969 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
970 isolate, sta, ValidateSharedIntegerTypedArray(isolate, array));
971
972 Maybe<size_t> maybeIndex = ValidateAtomicAccess(isolate, sta, index);
973 if (maybeIndex.IsNothing()) return isolate->heap()->exception();
974 size_t i = maybeIndex.FromJust();
975
976 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
977 Object::ToInteger(isolate, value));
978
979 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
980 NumberToSize(sta->byte_offset());
981
982 switch (sta->type()) {
983 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
984 case kExternal##Type##Array: \
985 return DoExchange<ctype>(isolate, source, i, value);
986
987 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
988 #undef TYPED_ARRAY_CASE
989
990 case kExternalUint8ClampedArray:
991 return DoExchangeUint8Clamped(isolate, source, i, value);
992
993 default:
994 break;
995 }
996
997 UNREACHABLE();
998 return isolate->heap()->undefined_value();
999 }
1000 997
1001 } // namespace internal 998 } // namespace internal
1002 } // namespace v8 999 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698