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