• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
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;
15var MakeRangeError;
16var MakeTypeError;
17var MaxSimple;
18var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
19
20utils.Import(function(from) {
21  MakeTypeError = from.MakeTypeError;
22  MakeRangeError = from.MakeRangeError;
23  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
42// 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
55//-------------------------------------------------------------------
56
57function AtomicsCompareExchangeJS(sta, index, oldValue, newValue) {
58  CheckSharedIntegerTypedArray(sta);
59  index = ValidateIndex(index, %_TypedArrayGetLength(sta));
60  oldValue = TO_NUMBER(oldValue);
61  newValue = TO_NUMBER(newValue);
62  return %_AtomicsCompareExchange(sta, index, oldValue, newValue);
63}
64
65function AtomicsAddJS(ia, index, value) {
66  CheckSharedIntegerTypedArray(ia);
67  index = ValidateIndex(index, %_TypedArrayGetLength(ia));
68  value = TO_NUMBER(value);
69  return %_AtomicsAdd(ia, index, value);
70}
71
72function AtomicsSubJS(ia, index, value) {
73  CheckSharedIntegerTypedArray(ia);
74  index = ValidateIndex(index, %_TypedArrayGetLength(ia));
75  value = TO_NUMBER(value);
76  return %_AtomicsSub(ia, index, value);
77}
78
79function AtomicsAndJS(ia, index, value) {
80  CheckSharedIntegerTypedArray(ia);
81  index = ValidateIndex(index, %_TypedArrayGetLength(ia));
82  value = TO_NUMBER(value);
83  return %_AtomicsAnd(ia, index, value);
84}
85
86function AtomicsOrJS(ia, index, value) {
87  CheckSharedIntegerTypedArray(ia);
88  index = ValidateIndex(index, %_TypedArrayGetLength(ia));
89  value = TO_NUMBER(value);
90  return %_AtomicsOr(ia, index, value);
91}
92
93function AtomicsXorJS(ia, index, value) {
94  CheckSharedIntegerTypedArray(ia);
95  index = ValidateIndex(index, %_TypedArrayGetLength(ia));
96  value = TO_NUMBER(value);
97  return %_AtomicsXor(ia, index, value);
98}
99
100function AtomicsExchangeJS(ia, index, value) {
101  CheckSharedIntegerTypedArray(ia);
102  index = ValidateIndex(index, %_TypedArrayGetLength(ia));
103  value = TO_NUMBER(value);
104  return %_AtomicsExchange(ia, index, value);
105}
106
107function AtomicsIsLockFreeJS(size) {
108  return %_AtomicsIsLockFree(size);
109}
110
111// Futexes
112
113function AtomicsFutexWaitJS(ia, index, value, timeout) {
114  CheckSharedInteger32TypedArray(ia);
115  index = ValidateIndex(index, %_TypedArrayGetLength(ia));
116  if (IS_UNDEFINED(timeout)) {
117    timeout = INFINITY;
118  } else {
119    timeout = TO_NUMBER(timeout);
120    if (NUMBER_IS_NAN(timeout)) {
121      timeout = INFINITY;
122    } else {
123      timeout = MaxSimple(0, timeout);
124    }
125  }
126  return %AtomicsFutexWait(ia, index, value, timeout);
127}
128
129function AtomicsFutexWakeJS(ia, index, count) {
130  CheckSharedInteger32TypedArray(ia);
131  index = ValidateIndex(index, %_TypedArrayGetLength(ia));
132  count = MaxSimple(0, TO_INTEGER(count));
133  return %AtomicsFutexWake(ia, index, count);
134}
135
136function AtomicsFutexWakeOrRequeueJS(ia, index1, count, value, index2) {
137  CheckSharedInteger32TypedArray(ia);
138  index1 = ValidateIndex(index1, %_TypedArrayGetLength(ia));
139  count = MaxSimple(0, TO_INTEGER(count));
140  value = TO_INT32(value);
141  index2 = ValidateIndex(index2, %_TypedArrayGetLength(ia));
142  if (index1 < 0 || index1 >= %_TypedArrayGetLength(ia) ||
143      index2 < 0 || index2 >= %_TypedArrayGetLength(ia)) {
144    return UNDEFINED;
145  }
146  return %AtomicsFutexWakeOrRequeue(ia, index1, count, value, index2);
147}
148
149// -------------------------------------------------------------------
150
151var Atomics = global.Atomics;
152
153// The Atomics global is defined by the bootstrapper.
154
155%AddNamedProperty(Atomics, toStringTagSymbol, "Atomics", READ_ONLY | DONT_ENUM);
156
157// These must match the values in src/futex-emulation.h
158utils.InstallConstants(Atomics, [
159  "OK", 0,
160  "NOTEQUAL", -1,
161  "TIMEDOUT", -2,
162]);
163
164utils.InstallFunctions(Atomics, DONT_ENUM, [
165  // TODO(binji): remove the rest of the (non futex) Atomics functions as they
166  // become builtins.
167  "compareExchange", AtomicsCompareExchangeJS,
168  "add", AtomicsAddJS,
169  "sub", AtomicsSubJS,
170  "and", AtomicsAndJS,
171  "or", AtomicsOrJS,
172  "xor", AtomicsXorJS,
173  "exchange", AtomicsExchangeJS,
174  "isLockFree", AtomicsIsLockFreeJS,
175  "futexWait", AtomicsFutexWaitJS,
176  "futexWake", AtomicsFutexWakeJS,
177  "futexWakeOrRequeue", AtomicsFutexWakeOrRequeueJS,
178]);
179
180})
181