LCOV - code coverage report
Current view: top level - src/builtins - builtins-sharedarraybuffer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 48 52 92.3 %
Date: 2017-10-20 Functions: 8 11 72.7 %

          Line data    Source code
       1             : // Copyright 2016 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             : #include "src/base/macros.h"
       6             : #include "src/base/platform/mutex.h"
       7             : #include "src/base/platform/time.h"
       8             : #include "src/builtins/builtins-utils.h"
       9             : #include "src/builtins/builtins.h"
      10             : #include "src/code-factory.h"
      11             : #include "src/conversions-inl.h"
      12             : #include "src/counters.h"
      13             : #include "src/factory.h"
      14             : #include "src/futex-emulation.h"
      15             : #include "src/globals.h"
      16             : #include "src/objects-inl.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : 
      21             : // See builtins-arraybuffer.cc for implementations of
      22             : // SharedArrayBuffer.prototye.byteLength and SharedArrayBuffer.prototype.slice
      23             : 
      24             : inline bool AtomicIsLockFree(uint32_t size) {
      25        9072 :   return size == 1 || size == 2 || size == 4;
      26             : }
      27             : 
      28             : // ES #sec-atomics.islockfree
      29       27216 : BUILTIN(AtomicsIsLockFree) {
      30             :   HandleScope scope(isolate);
      31             :   Handle<Object> size = args.atOrUndefined(isolate, 1);
      32       18144 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, size, Object::ToNumber(size));
      33       27216 :   return *isolate->factory()->ToBoolean(AtomicIsLockFree(size->Number()));
      34             : }
      35             : 
      36             : // ES #sec-validatesharedintegertypedarray
      37         789 : MUST_USE_RESULT MaybeHandle<JSTypedArray> ValidateSharedIntegerTypedArray(
      38             :     Isolate* isolate, Handle<Object> object, bool only_int32 = false) {
      39         789 :   if (object->IsJSTypedArray()) {
      40             :     Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(object);
      41        1578 :     if (typed_array->GetBuffer()->is_shared()) {
      42         627 :       if (only_int32) {
      43         627 :         if (typed_array->type() == kExternalInt32Array) return typed_array;
      44             :       } else {
      45           0 :         if (typed_array->type() != kExternalFloat32Array &&
      46           0 :             typed_array->type() != kExternalFloat64Array &&
      47           0 :             typed_array->type() != kExternalUint8ClampedArray)
      48           0 :           return typed_array;
      49             :       }
      50             :     }
      51             :   }
      52             : 
      53         612 :   THROW_NEW_ERROR(
      54             :       isolate,
      55             :       NewTypeError(only_int32 ? MessageTemplate::kNotInt32SharedTypedArray
      56             :                               : MessageTemplate::kNotIntegerSharedTypedArray,
      57             :                    object),
      58             :       JSTypedArray);
      59             : }
      60             : 
      61             : // ES #sec-validateatomicaccess
      62             : // ValidateAtomicAccess( typedArray, requestIndex )
      63         483 : MUST_USE_RESULT Maybe<size_t> ValidateAtomicAccess(
      64             :     Isolate* isolate, Handle<JSTypedArray> typed_array,
      65             :     Handle<Object> request_index) {
      66             :   Handle<Object> access_index_obj;
      67         966 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
      68             :       isolate, access_index_obj,
      69             :       Object::ToIndex(isolate, request_index,
      70             :                       MessageTemplate::kInvalidAtomicAccessIndex),
      71             :       Nothing<size_t>());
      72             : 
      73             :   size_t access_index;
      74         894 :   if (!TryNumberToSize(*access_index_obj, &access_index) ||
      75         447 :       access_index >= typed_array->length_value()) {
      76             :     isolate->Throw(*isolate->factory()->NewRangeError(
      77         216 :         MessageTemplate::kInvalidAtomicAccessIndex));
      78             :     return Nothing<size_t>();
      79             :   }
      80             :   return Just<size_t>(access_index);
      81             : }
      82             : 
      83             : // ES #sec-atomics.wake
      84             : // Atomics.wake( typedArray, index, count )
      85        1089 : BUILTIN(AtomicsWake) {
      86             :   HandleScope scope(isolate);
      87         363 :   Handle<Object> array = args.atOrUndefined(isolate, 1);
      88         363 :   Handle<Object> index = args.atOrUndefined(isolate, 2);
      89             :   Handle<Object> count = args.atOrUndefined(isolate, 3);
      90             : 
      91             :   Handle<JSTypedArray> sta;
      92         726 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      93             :       isolate, sta, ValidateSharedIntegerTypedArray(isolate, array, true));
      94             : 
      95         210 :   Maybe<size_t> maybe_index = ValidateAtomicAccess(isolate, sta, index);
      96         210 :   if (maybe_index.IsNothing()) return isolate->heap()->exception();
      97             :   size_t i = maybe_index.FromJust();
      98             : 
      99             :   uint32_t c;
     100         138 :   if (count->IsUndefined(isolate)) {
     101             :     c = kMaxUInt32;
     102             :   } else {
     103         138 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, count,
     104             :                                        Object::ToInteger(isolate, count));
     105             :     double count_double = count->Number();
     106         138 :     if (count_double < 0)
     107             :       count_double = 0;
     108         138 :     else if (count_double > kMaxUInt32)
     109             :       count_double = kMaxUInt32;
     110         138 :     c = static_cast<uint32_t>(count_double);
     111             :   }
     112             : 
     113         138 :   Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
     114         276 :   size_t addr = (i << 2) + NumberToSize(sta->byte_offset());
     115             : 
     116         138 :   return FutexEmulation::Wake(isolate, array_buffer, addr, c);
     117             : }
     118             : 
     119             : // ES #sec-atomics.wait
     120             : // Atomics.wait( typedArray, index, value, timeout )
     121        1479 : BUILTIN(AtomicsWait) {
     122             :   HandleScope scope(isolate);
     123         426 :   Handle<Object> array = args.atOrUndefined(isolate, 1);
     124         426 :   Handle<Object> index = args.atOrUndefined(isolate, 2);
     125             :   Handle<Object> value = args.atOrUndefined(isolate, 3);
     126             :   Handle<Object> timeout = args.atOrUndefined(isolate, 4);
     127             : 
     128             :   Handle<JSTypedArray> sta;
     129         852 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     130             :       isolate, sta, ValidateSharedIntegerTypedArray(isolate, array, true));
     131             : 
     132         273 :   Maybe<size_t> maybe_index = ValidateAtomicAccess(isolate, sta, index);
     133         273 :   if (maybe_index.IsNothing()) return isolate->heap()->exception();
     134             :   size_t i = maybe_index.FromJust();
     135             : 
     136         201 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
     137             :                                      Object::ToInt32(isolate, value));
     138         201 :   int32_t value_int32 = NumberToInt32(*value);
     139             : 
     140             :   double timeout_number;
     141         201 :   if (timeout->IsUndefined(isolate)) {
     142         102 :     timeout_number = isolate->heap()->infinity_value()->Number();
     143             :   } else {
     144         198 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, timeout,
     145             :                                        Object::ToNumber(timeout));
     146             :     timeout_number = timeout->Number();
     147          99 :     if (std::isnan(timeout_number))
     148          27 :       timeout_number = isolate->heap()->infinity_value()->Number();
     149          72 :     else if (timeout_number < 0)
     150             :       timeout_number = 0;
     151             :   }
     152             : 
     153         201 :   if (!isolate->allow_atomics_wait()) {
     154          18 :     THROW_NEW_ERROR_RETURN_FAILURE(
     155             :         isolate, NewTypeError(MessageTemplate::kAtomicsWaitNotAllowed));
     156             :   }
     157             : 
     158         192 :   Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
     159         384 :   size_t addr = (i << 2) + NumberToSize(sta->byte_offset());
     160             : 
     161             :   return FutexEmulation::Wait(isolate, array_buffer, addr, value_int32,
     162         192 :                               timeout_number);
     163             : }
     164             : 
     165             : }  // namespace internal
     166             : }  // namespace v8

Generated by: LCOV version 1.10