LCOV - code coverage report
Current view: top level - src/builtins - builtins-sharedarraybuffer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 58 62 93.5 %
Date: 2019-04-17 Functions: 12 16 75.0 %

          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(double size) {
      26        9072 :   return size == 1 || size == 2 || size == 4;
      27             : }
      28             : 
      29             : // ES #sec-atomics.islockfree
      30       45360 : 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       18144 :   return *isolate->factory()->ToBoolean(AtomicIsLockFree(size->Number()));
      36             : }
      37             : 
      38             : // ES #sec-validatesharedintegertypedarray
      39        1164 : V8_WARN_UNUSED_RESULT MaybeHandle<JSTypedArray> ValidateSharedIntegerTypedArray(
      40             :     Isolate* isolate, Handle<Object> object, bool only_int32 = false) {
      41        1164 :   if (object->IsJSTypedArray()) {
      42             :     Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(object);
      43        2328 :     if (typed_array->GetBuffer()->is_shared()) {
      44        1001 :       if (only_int32) {
      45        1001 :         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         613 :   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         858 : 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        1716 :   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        1644 :   if (!TryNumberToSize(*access_index_obj, &access_index) ||
      77        1644 :       typed_array->WasDetached() || access_index >= typed_array->length()) {
      78         216 :     isolate->Throw(*isolate->factory()->NewRangeError(
      79         216 :         MessageTemplate::kInvalidAtomicAccessIndex));
      80             :     return Nothing<size_t>();
      81             :   }
      82             :   return Just<size_t>(access_index);
      83             : }
      84             : 
      85             : namespace {
      86         524 : MaybeHandle<Object> AtomicsWake(Isolate* isolate, Handle<Object> array,
      87             :                                 Handle<Object> index, Handle<Object> count) {
      88             :   Handle<JSTypedArray> sta;
      89        1048 :   ASSIGN_RETURN_ON_EXCEPTION(
      90             :       isolate, sta, ValidateSharedIntegerTypedArray(isolate, array, true),
      91             :       Object);
      92             : 
      93         371 :   Maybe<size_t> maybe_index = ValidateAtomicAccess(isolate, sta, index);
      94         371 :   MAYBE_RETURN_NULL(maybe_index);
      95             :   size_t i = maybe_index.FromJust();
      96             : 
      97             :   uint32_t c;
      98         299 :   if (count->IsUndefined(isolate)) {
      99             :     c = kMaxUInt32;
     100             :   } else {
     101         289 :     ASSIGN_RETURN_ON_EXCEPTION(isolate, count,
     102             :                                Object::ToInteger(isolate, count), Object);
     103             :     double count_double = count->Number();
     104         289 :     if (count_double < 0)
     105             :       count_double = 0;
     106         289 :     else if (count_double > kMaxUInt32)
     107             :       count_double = kMaxUInt32;
     108         289 :     c = static_cast<uint32_t>(count_double);
     109             :   }
     110             : 
     111         299 :   Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
     112         598 :   size_t addr = (i << 2) + sta->byte_offset();
     113             : 
     114         598 :   return Handle<Object>(FutexEmulation::Wake(array_buffer, addr, c), isolate);
     115             : }
     116             : 
     117             : }  // namespace
     118             : 
     119             : // ES #sec-atomics.wake
     120             : // Atomics.wake( typedArray, index, count )
     121        2145 : BUILTIN(AtomicsWake) {
     122             :   HandleScope scope(isolate);
     123         429 :   Handle<Object> array = args.atOrUndefined(isolate, 1);
     124         429 :   Handle<Object> index = args.atOrUndefined(isolate, 2);
     125         429 :   Handle<Object> count = args.atOrUndefined(isolate, 3);
     126             : 
     127         429 :   isolate->CountUsage(v8::Isolate::UseCounterFeature::kAtomicsWake);
     128        1083 :   RETURN_RESULT_OR_FAILURE(isolate, AtomicsWake(isolate, array, index, count));
     129             : }
     130             : 
     131             : // ES #sec-atomics.notify
     132             : // Atomics.notify( typedArray, index, count )
     133         475 : BUILTIN(AtomicsNotify) {
     134             :   HandleScope scope(isolate);
     135          95 :   Handle<Object> array = args.atOrUndefined(isolate, 1);
     136          95 :   Handle<Object> index = args.atOrUndefined(isolate, 2);
     137          95 :   Handle<Object> count = args.atOrUndefined(isolate, 3);
     138             : 
     139          95 :   isolate->CountUsage(v8::Isolate::UseCounterFeature::kAtomicsNotify);
     140         190 :   RETURN_RESULT_OR_FAILURE(isolate, AtomicsWake(isolate, array, index, count));
     141             : }
     142             : 
     143             : // ES #sec-atomics.wait
     144             : // Atomics.wait( typedArray, index, value, timeout )
     145        3200 : BUILTIN(AtomicsWait) {
     146             :   HandleScope scope(isolate);
     147         640 :   Handle<Object> array = args.atOrUndefined(isolate, 1);
     148         640 :   Handle<Object> index = args.atOrUndefined(isolate, 2);
     149             :   Handle<Object> value = args.atOrUndefined(isolate, 3);
     150             :   Handle<Object> timeout = args.atOrUndefined(isolate, 4);
     151             : 
     152             :   Handle<JSTypedArray> sta;
     153        1433 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     154             :       isolate, sta, ValidateSharedIntegerTypedArray(isolate, array, true));
     155             : 
     156         487 :   Maybe<size_t> maybe_index = ValidateAtomicAccess(isolate, sta, index);
     157         559 :   if (maybe_index.IsNothing()) return ReadOnlyRoots(isolate).exception();
     158             :   size_t i = maybe_index.FromJust();
     159             : 
     160         415 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
     161             :                                      Object::ToInt32(isolate, value));
     162         415 :   int32_t value_int32 = NumberToInt32(*value);
     163             : 
     164             :   double timeout_number;
     165         415 :   if (timeout->IsUndefined(isolate)) {
     166             :     timeout_number = ReadOnlyRoots(isolate).infinity_value()->Number();
     167             :   } else {
     168         316 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, timeout,
     169             :                                        Object::ToNumber(isolate, timeout));
     170             :     timeout_number = timeout->Number();
     171         158 :     if (std::isnan(timeout_number))
     172             :       timeout_number = ReadOnlyRoots(isolate).infinity_value()->Number();
     173         104 :     else if (timeout_number < 0)
     174             :       timeout_number = 0;
     175             :   }
     176             : 
     177         415 :   if (!isolate->allow_atomics_wait()) {
     178          18 :     THROW_NEW_ERROR_RETURN_FAILURE(
     179             :         isolate, NewTypeError(MessageTemplate::kAtomicsWaitNotAllowed));
     180             :   }
     181             : 
     182         406 :   Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
     183         810 :   size_t addr = (i << 2) + sta->byte_offset();
     184             : 
     185             :   return FutexEmulation::WaitJs(isolate, array_buffer, addr, value_int32,
     186         405 :                                 timeout_number);
     187             : }
     188             : 
     189             : }  // namespace internal
     190      122004 : }  // namespace v8

Generated by: LCOV version 1.10