LCOV - code coverage report
Current view: top level - src/builtins - builtins-sharedarraybuffer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 63 67 94.0 %
Date: 2019-01-20 Functions: 13 17 76.5 %

          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-inl.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/futex-emulation.h"
      14             : #include "src/globals.h"
      15             : #include "src/heap/factory.h"
      16             : #include "src/objects-inl.h"
      17             : #include "src/objects/js-array-buffer-inl.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : 
      22             : // See builtins-arraybuffer.cc for implementations of
      23             : // SharedArrayBuffer.prototye.byteLength and SharedArrayBuffer.prototype.slice
      24             : 
      25             : inline bool AtomicIsLockFree(uint32_t size) {
      26        9072 :   return size == 1 || size == 2 || size == 4;
      27             : }
      28             : 
      29             : // ES #sec-atomics.islockfree
      30       36288 : BUILTIN(AtomicsIsLockFree) {
      31             :   HandleScope scope(isolate);
      32             :   Handle<Object> size = args.atOrUndefined(isolate, 1);
      33       18144 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, size,
      34             :                                      Object::ToNumber(isolate, size));
      35       27216 :   return *isolate->factory()->ToBoolean(AtomicIsLockFree(size->Number()));
      36             : }
      37             : 
      38             : // ES #sec-validatesharedintegertypedarray
      39        1184 : V8_WARN_UNUSED_RESULT MaybeHandle<JSTypedArray> ValidateSharedIntegerTypedArray(
      40             :     Isolate* isolate, Handle<Object> object, bool only_int32 = false) {
      41        2368 :   if (object->IsJSTypedArray()) {
      42        1184 :     Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(object);
      43        2367 :     if (typed_array->GetBuffer()->is_shared()) {
      44        1021 :       if (only_int32) {
      45        1021 :         if (typed_array->type() == kExternalInt32Array) return typed_array;
      46             :       } else {
      47           0 :         if (typed_array->type() != kExternalFloat32Array &&
      48           0 :             typed_array->type() != kExternalFloat64Array &&
      49           0 :             typed_array->type() != kExternalUint8ClampedArray)
      50           0 :           return typed_array;
      51             :       }
      52             :     }
      53             :   }
      54             : 
      55         306 :   THROW_NEW_ERROR(
      56             :       isolate,
      57             :       NewTypeError(only_int32 ? MessageTemplate::kNotInt32SharedTypedArray
      58             :                               : MessageTemplate::kNotIntegerSharedTypedArray,
      59             :                    object),
      60             :       JSTypedArray);
      61             : }
      62             : 
      63             : // ES #sec-validateatomicaccess
      64             : // ValidateAtomicAccess( typedArray, requestIndex )
      65         877 : V8_WARN_UNUSED_RESULT Maybe<size_t> ValidateAtomicAccess(
      66             :     Isolate* isolate, Handle<JSTypedArray> typed_array,
      67             :     Handle<Object> request_index) {
      68             :   Handle<Object> access_index_obj;
      69        1754 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
      70             :       isolate, access_index_obj,
      71             :       Object::ToIndex(isolate, request_index,
      72             :                       MessageTemplate::kInvalidAtomicAccessIndex),
      73             :       Nothing<size_t>());
      74             : 
      75             :   size_t access_index;
      76        2524 :   if (!TryNumberToSize(*access_index_obj, &access_index) ||
      77        3366 :       typed_array->WasDetached() ||
      78         842 :       access_index >= typed_array->length_value()) {
      79             :     isolate->Throw(*isolate->factory()->NewRangeError(
      80         216 :         MessageTemplate::kInvalidAtomicAccessIndex));
      81             :     return Nothing<size_t>();
      82             :   }
      83             :   return Just<size_t>(access_index);
      84             : }
      85             : 
      86             : namespace {
      87         532 : MaybeHandle<Object> AtomicsWake(Isolate* isolate, Handle<Object> array,
      88             :                                 Handle<Object> index, Handle<Object> count) {
      89             :   Handle<JSTypedArray> sta;
      90        1064 :   ASSIGN_RETURN_ON_EXCEPTION(
      91             :       isolate, sta, ValidateSharedIntegerTypedArray(isolate, array, true),
      92             :       Object);
      93             : 
      94         379 :   Maybe<size_t> maybe_index = ValidateAtomicAccess(isolate, sta, index);
      95         379 :   MAYBE_RETURN_NULL(maybe_index);
      96             :   size_t i = maybe_index.FromJust();
      97             : 
      98             :   uint32_t c;
      99         614 :   if (count->IsUndefined(isolate)) {
     100             :     c = kMaxUInt32;
     101             :   } else {
     102         594 :     ASSIGN_RETURN_ON_EXCEPTION(isolate, count,
     103             :                                Object::ToInteger(isolate, count), Object);
     104         297 :     double count_double = count->Number();
     105         297 :     if (count_double < 0)
     106             :       count_double = 0;
     107         297 :     else if (count_double > kMaxUInt32)
     108             :       count_double = kMaxUInt32;
     109         297 :     c = static_cast<uint32_t>(count_double);
     110             :   }
     111             : 
     112         307 :   Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
     113         614 :   size_t addr = (i << 2) + sta->byte_offset();
     114             : 
     115         614 :   return Handle<Object>(FutexEmulation::Wake(array_buffer, addr, c), isolate);
     116             : }
     117             : 
     118             : }  // namespace
     119             : 
     120             : // ES #sec-atomics.wake
     121             : // Atomics.wake( typedArray, index, count )
     122        1748 : BUILTIN(AtomicsWake) {
     123             :   HandleScope scope(isolate);
     124         437 :   Handle<Object> array = args.atOrUndefined(isolate, 1);
     125         437 :   Handle<Object> index = args.atOrUndefined(isolate, 2);
     126         437 :   Handle<Object> count = args.atOrUndefined(isolate, 3);
     127             : 
     128         437 :   isolate->CountUsage(v8::Isolate::UseCounterFeature::kAtomicsWake);
     129        1099 :   RETURN_RESULT_OR_FAILURE(isolate, AtomicsWake(isolate, array, index, count));
     130             : }
     131             : 
     132             : // ES #sec-atomics.notify
     133             : // Atomics.notify( typedArray, index, count )
     134         380 : BUILTIN(AtomicsNotify) {
     135             :   HandleScope scope(isolate);
     136          95 :   Handle<Object> array = args.atOrUndefined(isolate, 1);
     137          95 :   Handle<Object> index = args.atOrUndefined(isolate, 2);
     138          95 :   Handle<Object> count = args.atOrUndefined(isolate, 3);
     139             : 
     140          95 :   isolate->CountUsage(v8::Isolate::UseCounterFeature::kAtomicsNotify);
     141         190 :   RETURN_RESULT_OR_FAILURE(isolate, AtomicsWake(isolate, array, index, count));
     142             : }
     143             : 
     144             : // ES #sec-atomics.wait
     145             : // Atomics.wait( typedArray, index, value, timeout )
     146        3034 : BUILTIN(AtomicsWait) {
     147             :   HandleScope scope(isolate);
     148         652 :   Handle<Object> array = args.atOrUndefined(isolate, 1);
     149         652 :   Handle<Object> index = args.atOrUndefined(isolate, 2);
     150             :   Handle<Object> value = args.atOrUndefined(isolate, 3);
     151             :   Handle<Object> timeout = args.atOrUndefined(isolate, 4);
     152             : 
     153             :   Handle<JSTypedArray> sta;
     154        1456 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     155             :       isolate, sta, ValidateSharedIntegerTypedArray(isolate, array, true));
     156             : 
     157         498 :   Maybe<size_t> maybe_index = ValidateAtomicAccess(isolate, sta, index);
     158         571 :   if (maybe_index.IsNothing()) return ReadOnlyRoots(isolate).exception();
     159             :   size_t i = maybe_index.FromJust();
     160             : 
     161         853 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
     162             :                                      Object::ToInt32(isolate, value));
     163         426 :   int32_t value_int32 = NumberToInt32(*value);
     164             : 
     165             :   double timeout_number;
     166         852 :   if (timeout->IsUndefined(isolate)) {
     167         269 :     timeout_number = ReadOnlyRoots(isolate).infinity_value()->Number();
     168             :   } else {
     169         316 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, timeout,
     170             :                                        Object::ToNumber(isolate, timeout));
     171         158 :     timeout_number = timeout->Number();
     172         158 :     if (std::isnan(timeout_number))
     173          54 :       timeout_number = ReadOnlyRoots(isolate).infinity_value()->Number();
     174         104 :     else if (timeout_number < 0)
     175             :       timeout_number = 0;
     176             :   }
     177             : 
     178         427 :   if (!isolate->allow_atomics_wait()) {
     179          18 :     THROW_NEW_ERROR_RETURN_FAILURE(
     180             :         isolate, NewTypeError(MessageTemplate::kAtomicsWaitNotAllowed));
     181             :   }
     182             : 
     183         418 :   Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
     184         834 :   size_t addr = (i << 2) + sta->byte_offset();
     185             : 
     186             :   return FutexEmulation::WaitJs(isolate, array_buffer, addr, value_int32,
     187         417 :                                 timeout_number);
     188             : }
     189             : 
     190             : }  // namespace internal
     191      183867 : }  // namespace v8

Generated by: LCOV version 1.10