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 14 var GlobalObject = global.Object; 15 var MaxSimple; 16 var MinSimple; 17 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); 18 19 utils.Import(function(from) { 20 MaxSimple = from.MaxSimple; 21 MinSimple = from.MinSimple; 22 }); 23 24 // ------------------------------------------------------------------- 25 26 27 function CheckSharedIntegerTypedArray(ia) { 28 if (!%IsSharedIntegerTypedArray(ia)) { 29 throw %make_type_error(kNotIntegerSharedTypedArray, ia); 30 } 31 } 32 33 function CheckSharedInteger32TypedArray(ia) { 34 CheckSharedIntegerTypedArray(ia); 35 if (!%IsSharedInteger32TypedArray(ia)) { 36 throw %make_type_error(kNotInt32SharedTypedArray, ia); 37 } 38 } 39 40 // https://tc39.github.io/ecmascript_sharedmem/shmem.html#Atomics.ValidateAtomicAccess 41 function ValidateIndex(index, length) { 42 var numberIndex = TO_NUMBER(index); 43 var accessIndex = TO_INTEGER(numberIndex); 44 if (numberIndex !== accessIndex) { 45 throw %make_range_error(kInvalidAtomicAccessIndex); 46 } 47 if (accessIndex < 0 || accessIndex >= length) { 48 throw %make_range_error(kInvalidAtomicAccessIndex); 49 } 50 return accessIndex; 51 } 52 53 //------------------------------------------------------------------- 54 55 function AtomicsCompareExchangeJS(sta, index, oldValue, newValue) { 56 CheckSharedIntegerTypedArray(sta); 57 index = ValidateIndex(index, %_TypedArrayGetLength(sta)); 58 oldValue = TO_NUMBER(oldValue); 59 newValue = TO_NUMBER(newValue); 60 return %_AtomicsCompareExchange(sta, index, oldValue, newValue); 61 } 62 63 function AtomicsAddJS(ia, index, value) { 64 CheckSharedIntegerTypedArray(ia); 65 index = ValidateIndex(index, %_TypedArrayGetLength(ia)); 66 value = TO_NUMBER(value); 67 return %_AtomicsAdd(ia, index, value); 68 } 69 70 function AtomicsSubJS(ia, index, value) { 71 CheckSharedIntegerTypedArray(ia); 72 index = ValidateIndex(index, %_TypedArrayGetLength(ia)); 73 value = TO_NUMBER(value); 74 return %_AtomicsSub(ia, index, value); 75 } 76 77 function AtomicsAndJS(ia, index, value) { 78 CheckSharedIntegerTypedArray(ia); 79 index = ValidateIndex(index, %_TypedArrayGetLength(ia)); 80 value = TO_NUMBER(value); 81 return %_AtomicsAnd(ia, index, value); 82 } 83 84 function AtomicsOrJS(ia, index, value) { 85 CheckSharedIntegerTypedArray(ia); 86 index = ValidateIndex(index, %_TypedArrayGetLength(ia)); 87 value = TO_NUMBER(value); 88 return %_AtomicsOr(ia, index, value); 89 } 90 91 function AtomicsXorJS(ia, index, value) { 92 CheckSharedIntegerTypedArray(ia); 93 index = ValidateIndex(index, %_TypedArrayGetLength(ia)); 94 value = TO_NUMBER(value); 95 return %_AtomicsXor(ia, index, value); 96 } 97 98 function AtomicsExchangeJS(ia, index, value) { 99 CheckSharedIntegerTypedArray(ia); 100 index = ValidateIndex(index, %_TypedArrayGetLength(ia)); 101 value = TO_NUMBER(value); 102 return %_AtomicsExchange(ia, index, value); 103 } 104 105 function AtomicsIsLockFreeJS(size) { 106 return %_AtomicsIsLockFree(TO_INTEGER(size)); 107 } 108 109 function AtomicsWaitJS(ia, index, value, timeout) { 110 CheckSharedInteger32TypedArray(ia); 111 index = ValidateIndex(index, %_TypedArrayGetLength(ia)); 112 if (IS_UNDEFINED(timeout)) { 113 timeout = INFINITY; 114 } else { 115 timeout = TO_NUMBER(timeout); 116 if (NUMBER_IS_NAN(timeout)) { 117 timeout = INFINITY; 118 } else { 119 timeout = MaxSimple(0, timeout); 120 } 121 } 122 return %AtomicsWait(ia, index, value, timeout); 123 } 124 125 function AtomicsWakeJS(ia, index, count) { 126 CheckSharedInteger32TypedArray(ia); 127 index = ValidateIndex(index, %_TypedArrayGetLength(ia)); 128 if (IS_UNDEFINED(count)) { 129 count = kMaxUint32; 130 } else { 131 // Clamp to [0, kMaxUint32]. 132 count = MinSimple(MaxSimple(0, TO_INTEGER(count)), kMaxUint32); 133 } 134 return %AtomicsWake(ia, index, count); 135 } 136 137 // ------------------------------------------------------------------- 138 139 var Atomics = global.Atomics; 140 141 // The Atomics global is defined by the bootstrapper. 142 143 %AddNamedProperty(Atomics, toStringTagSymbol, "Atomics", READ_ONLY | DONT_ENUM); 144 145 utils.InstallFunctions(Atomics, DONT_ENUM, [ 146 // TODO(binji): remove the rest of the (non futex) Atomics functions as they 147 // become builtins. 148 "compareExchange", AtomicsCompareExchangeJS, 149 "add", AtomicsAddJS, 150 "sub", AtomicsSubJS, 151 "and", AtomicsAndJS, 152 "or", AtomicsOrJS, 153 "xor", AtomicsXorJS, 154 "exchange", AtomicsExchangeJS, 155 "isLockFree", AtomicsIsLockFreeJS, 156 "wait", AtomicsWaitJS, 157 "wake", AtomicsWakeJS, 158 ]); 159 160 }) 161