Home | History | Annotate | Download | only in js
      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