blob: 9f80227426b41f106d34bf1604702be0ad2ae377 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
3// found in the LICENSE file.
4
5(function(global, utils) {
6
7"use strict";
8
9%CheckIsBootstrapping();
10
11// -------------------------------------------------------------------
12// Imports
13
14var GlobalObject = global.Object;
Ben Murdochda12d292016-06-02 14:46:10 +010015var MakeRangeError;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016var MakeTypeError;
17var MaxSimple;
18var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
19
20utils.Import(function(from) {
21 MakeTypeError = from.MakeTypeError;
Ben Murdochda12d292016-06-02 14:46:10 +010022 MakeRangeError = from.MakeRangeError;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023 MaxSimple = from.MaxSimple;
24});
25
26// -------------------------------------------------------------------
27
28
29function CheckSharedIntegerTypedArray(ia) {
30 if (!%IsSharedIntegerTypedArray(ia)) {
31 throw MakeTypeError(kNotIntegerSharedTypedArray, ia);
32 }
33}
34
35function CheckSharedInteger32TypedArray(ia) {
36 CheckSharedIntegerTypedArray(ia);
37 if (!%IsSharedInteger32TypedArray(ia)) {
38 throw MakeTypeError(kNotInt32SharedTypedArray, ia);
39 }
40}
41
Ben Murdochda12d292016-06-02 14:46:10 +010042// https://tc39.github.io/ecmascript_sharedmem/shmem.html#Atomics.ValidateAtomicAccess
43function ValidateIndex(index, length) {
44 var numberIndex = TO_NUMBER(index);
45 var accessIndex = TO_INTEGER(numberIndex);
46 if (numberIndex !== accessIndex) {
47 throw MakeRangeError(kInvalidAtomicAccessIndex);
48 }
49 if (accessIndex < 0 || accessIndex >= length) {
50 throw MakeRangeError(kInvalidAtomicAccessIndex);
51 }
52 return accessIndex;
53}
54
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000055//-------------------------------------------------------------------
56
57function AtomicsCompareExchangeJS(sta, index, oldValue, newValue) {
58 CheckSharedIntegerTypedArray(sta);
Ben Murdochda12d292016-06-02 14:46:10 +010059 index = ValidateIndex(index, %_TypedArrayGetLength(sta));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060 oldValue = TO_NUMBER(oldValue);
61 newValue = TO_NUMBER(newValue);
62 return %_AtomicsCompareExchange(sta, index, oldValue, newValue);
63}
64
65function AtomicsLoadJS(sta, index) {
66 CheckSharedIntegerTypedArray(sta);
Ben Murdochda12d292016-06-02 14:46:10 +010067 index = ValidateIndex(index, %_TypedArrayGetLength(sta));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068 return %_AtomicsLoad(sta, index);
69}
70
71function AtomicsStoreJS(sta, index, value) {
72 CheckSharedIntegerTypedArray(sta);
Ben Murdochda12d292016-06-02 14:46:10 +010073 index = ValidateIndex(index, %_TypedArrayGetLength(sta));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074 value = TO_NUMBER(value);
75 return %_AtomicsStore(sta, index, value);
76}
77
78function AtomicsAddJS(ia, index, value) {
79 CheckSharedIntegerTypedArray(ia);
Ben Murdochda12d292016-06-02 14:46:10 +010080 index = ValidateIndex(index, %_TypedArrayGetLength(ia));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 value = TO_NUMBER(value);
82 return %_AtomicsAdd(ia, index, value);
83}
84
85function AtomicsSubJS(ia, index, value) {
86 CheckSharedIntegerTypedArray(ia);
Ben Murdochda12d292016-06-02 14:46:10 +010087 index = ValidateIndex(index, %_TypedArrayGetLength(ia));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088 value = TO_NUMBER(value);
89 return %_AtomicsSub(ia, index, value);
90}
91
92function AtomicsAndJS(ia, index, value) {
93 CheckSharedIntegerTypedArray(ia);
Ben Murdochda12d292016-06-02 14:46:10 +010094 index = ValidateIndex(index, %_TypedArrayGetLength(ia));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000095 value = TO_NUMBER(value);
96 return %_AtomicsAnd(ia, index, value);
97}
98
99function AtomicsOrJS(ia, index, value) {
100 CheckSharedIntegerTypedArray(ia);
Ben Murdochda12d292016-06-02 14:46:10 +0100101 index = ValidateIndex(index, %_TypedArrayGetLength(ia));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000102 value = TO_NUMBER(value);
103 return %_AtomicsOr(ia, index, value);
104}
105
106function AtomicsXorJS(ia, index, value) {
107 CheckSharedIntegerTypedArray(ia);
Ben Murdochda12d292016-06-02 14:46:10 +0100108 index = ValidateIndex(index, %_TypedArrayGetLength(ia));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109 value = TO_NUMBER(value);
110 return %_AtomicsXor(ia, index, value);
111}
112
113function AtomicsExchangeJS(ia, index, value) {
114 CheckSharedIntegerTypedArray(ia);
Ben Murdochda12d292016-06-02 14:46:10 +0100115 index = ValidateIndex(index, %_TypedArrayGetLength(ia));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 value = TO_NUMBER(value);
117 return %_AtomicsExchange(ia, index, value);
118}
119
120function AtomicsIsLockFreeJS(size) {
121 return %_AtomicsIsLockFree(size);
122}
123
124// Futexes
125
126function AtomicsFutexWaitJS(ia, index, value, timeout) {
127 CheckSharedInteger32TypedArray(ia);
Ben Murdochda12d292016-06-02 14:46:10 +0100128 index = ValidateIndex(index, %_TypedArrayGetLength(ia));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 if (IS_UNDEFINED(timeout)) {
130 timeout = INFINITY;
131 } else {
132 timeout = TO_NUMBER(timeout);
133 if (NUMBER_IS_NAN(timeout)) {
134 timeout = INFINITY;
135 } else {
136 timeout = MaxSimple(0, timeout);
137 }
138 }
139 return %AtomicsFutexWait(ia, index, value, timeout);
140}
141
142function AtomicsFutexWakeJS(ia, index, count) {
143 CheckSharedInteger32TypedArray(ia);
Ben Murdochda12d292016-06-02 14:46:10 +0100144 index = ValidateIndex(index, %_TypedArrayGetLength(ia));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145 count = MaxSimple(0, TO_INTEGER(count));
146 return %AtomicsFutexWake(ia, index, count);
147}
148
149function AtomicsFutexWakeOrRequeueJS(ia, index1, count, value, index2) {
150 CheckSharedInteger32TypedArray(ia);
Ben Murdochda12d292016-06-02 14:46:10 +0100151 index1 = ValidateIndex(index1, %_TypedArrayGetLength(ia));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152 count = MaxSimple(0, TO_INTEGER(count));
153 value = TO_INT32(value);
Ben Murdochda12d292016-06-02 14:46:10 +0100154 index2 = ValidateIndex(index2, %_TypedArrayGetLength(ia));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155 if (index1 < 0 || index1 >= %_TypedArrayGetLength(ia) ||
156 index2 < 0 || index2 >= %_TypedArrayGetLength(ia)) {
157 return UNDEFINED;
158 }
159 return %AtomicsFutexWakeOrRequeue(ia, index1, count, value, index2);
160}
161
162// -------------------------------------------------------------------
163
164function AtomicsConstructor() {}
165
166var Atomics = new AtomicsConstructor();
167
168%InternalSetPrototype(Atomics, GlobalObject.prototype);
169%AddNamedProperty(global, "Atomics", Atomics, DONT_ENUM);
170%FunctionSetInstanceClassName(AtomicsConstructor, 'Atomics');
171
172%AddNamedProperty(Atomics, toStringTagSymbol, "Atomics", READ_ONLY | DONT_ENUM);
173
174// These must match the values in src/futex-emulation.h
175utils.InstallConstants(Atomics, [
176 "OK", 0,
177 "NOTEQUAL", -1,
178 "TIMEDOUT", -2,
179]);
180
181utils.InstallFunctions(Atomics, DONT_ENUM, [
182 "compareExchange", AtomicsCompareExchangeJS,
183 "load", AtomicsLoadJS,
184 "store", AtomicsStoreJS,
185 "add", AtomicsAddJS,
186 "sub", AtomicsSubJS,
187 "and", AtomicsAndJS,
188 "or", AtomicsOrJS,
189 "xor", AtomicsXorJS,
190 "exchange", AtomicsExchangeJS,
191 "isLockFree", AtomicsIsLockFreeJS,
192 "futexWait", AtomicsFutexWaitJS,
193 "futexWake", AtomicsFutexWakeJS,
194 "futexWakeOrRequeue", AtomicsFutexWakeOrRequeueJS,
195]);
196
197})