LCOV - code coverage report
Current view: top level - src/wasm - wasm-external-refs.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 115 115 100.0 %
Date: 2019-04-17 Functions: 32 32 100.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 <math.h>
       6             : #include <stdint.h>
       7             : #include <stdlib.h>
       8             : #include <limits>
       9             : 
      10             : #include "include/v8config.h"
      11             : 
      12             : #include "src/base/bits.h"
      13             : #include "src/base/ieee754.h"
      14             : #include "src/memcopy.h"
      15             : #include "src/utils.h"
      16             : #include "src/v8memory.h"
      17             : #include "src/wasm/wasm-external-refs.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : namespace wasm {
      22             : 
      23         920 : void f32_trunc_wrapper(Address data) {
      24         920 :   WriteUnalignedValue<float>(data, truncf(ReadUnalignedValue<float>(data)));
      25         920 : }
      26             : 
      27         920 : void f32_floor_wrapper(Address data) {
      28         920 :   WriteUnalignedValue<float>(data, floorf(ReadUnalignedValue<float>(data)));
      29         920 : }
      30             : 
      31         920 : void f32_ceil_wrapper(Address data) {
      32             :   WriteUnalignedValue<float>(data, ceilf(ReadUnalignedValue<float>(data)));
      33         920 : }
      34             : 
      35         920 : void f32_nearest_int_wrapper(Address data) {
      36         920 :   WriteUnalignedValue<float>(data, nearbyintf(ReadUnalignedValue<float>(data)));
      37         920 : }
      38             : 
      39         392 : void f64_trunc_wrapper(Address data) {
      40         392 :   WriteUnalignedValue<double>(data, trunc(ReadUnalignedValue<double>(data)));
      41         392 : }
      42             : 
      43         392 : void f64_floor_wrapper(Address data) {
      44         392 :   WriteUnalignedValue<double>(data, floor(ReadUnalignedValue<double>(data)));
      45         392 : }
      46             : 
      47         392 : void f64_ceil_wrapper(Address data) {
      48         392 :   WriteUnalignedValue<double>(data, ceil(ReadUnalignedValue<double>(data)));
      49         392 : }
      50             : 
      51         392 : void f64_nearest_int_wrapper(Address data) {
      52         392 :   WriteUnalignedValue<double>(data,
      53             :                               nearbyint(ReadUnalignedValue<double>(data)));
      54         392 : }
      55             : 
      56         648 : void int64_to_float32_wrapper(Address data) {
      57             :   int64_t input = ReadUnalignedValue<int64_t>(data);
      58         648 :   WriteUnalignedValue<float>(data, static_cast<float>(input));
      59         648 : }
      60             : 
      61         952 : void uint64_to_float32_wrapper(Address data) {
      62             :   uint64_t input = ReadUnalignedValue<uint64_t>(data);
      63         952 :   float result = static_cast<float>(input);
      64             : 
      65             : #if V8_CC_MSVC
      66             :   // With MSVC we use static_cast<float>(uint32_t) instead of
      67             :   // static_cast<float>(uint64_t) to achieve round-to-nearest-ties-even
      68             :   // semantics. The idea is to calculate
      69             :   // static_cast<float>(high_word) * 2^32 + static_cast<float>(low_word). To
      70             :   // achieve proper rounding in all cases we have to adjust the high_word
      71             :   // with a "rounding bit" sometimes. The rounding bit is stored in the LSB of
      72             :   // the high_word if the low_word may affect the rounding of the high_word.
      73             :   uint32_t low_word = static_cast<uint32_t>(input & 0xFFFFFFFF);
      74             :   uint32_t high_word = static_cast<uint32_t>(input >> 32);
      75             : 
      76             :   float shift = static_cast<float>(1ull << 32);
      77             :   // If the MSB of the high_word is set, then we make space for a rounding bit.
      78             :   if (high_word < 0x80000000) {
      79             :     high_word <<= 1;
      80             :     shift = static_cast<float>(1ull << 31);
      81             :   }
      82             : 
      83             :   if ((high_word & 0xFE000000) && low_word) {
      84             :     // Set the rounding bit.
      85             :     high_word |= 1;
      86             :   }
      87             : 
      88             :   result = static_cast<float>(high_word);
      89             :   result *= shift;
      90             :   result += static_cast<float>(low_word);
      91             : #endif
      92             : 
      93             :   WriteUnalignedValue<float>(data, result);
      94         952 : }
      95             : 
      96         648 : void int64_to_float64_wrapper(Address data) {
      97             :   int64_t input = ReadUnalignedValue<int64_t>(data);
      98         648 :   WriteUnalignedValue<double>(data, static_cast<double>(input));
      99         648 : }
     100             : 
     101         948 : void uint64_to_float64_wrapper(Address data) {
     102             :   uint64_t input = ReadUnalignedValue<uint64_t>(data);
     103         948 :   double result = static_cast<double>(input);
     104             : 
     105             : #if V8_CC_MSVC
     106             :   // With MSVC we use static_cast<double>(uint32_t) instead of
     107             :   // static_cast<double>(uint64_t) to achieve round-to-nearest-ties-even
     108             :   // semantics. The idea is to calculate
     109             :   // static_cast<double>(high_word) * 2^32 + static_cast<double>(low_word).
     110             :   uint32_t low_word = static_cast<uint32_t>(input & 0xFFFFFFFF);
     111             :   uint32_t high_word = static_cast<uint32_t>(input >> 32);
     112             : 
     113             :   double shift = static_cast<double>(1ull << 32);
     114             : 
     115             :   result = static_cast<double>(high_word);
     116             :   result *= shift;
     117             :   result += static_cast<double>(low_word);
     118             : #endif
     119             : 
     120             :   WriteUnalignedValue<double>(data, result);
     121         948 : }
     122             : 
     123        1840 : int32_t float32_to_int64_wrapper(Address data) {
     124             :   // We use "<" here to check the upper bound because of rounding problems: With
     125             :   // "<=" some inputs would be considered within int64 range which are actually
     126             :   // not within int64 range.
     127             :   float input = ReadUnalignedValue<float>(data);
     128        1840 :   if (input >= static_cast<float>(std::numeric_limits<int64_t>::min()) &&
     129             :       input < static_cast<float>(std::numeric_limits<int64_t>::max())) {
     130        1328 :     WriteUnalignedValue<int64_t>(data, static_cast<int64_t>(input));
     131        1328 :     return 1;
     132             :   }
     133             :   return 0;
     134             : }
     135             : 
     136        1840 : int32_t float32_to_uint64_wrapper(Address data) {
     137             :   float input = ReadUnalignedValue<float>(data);
     138             :   // We use "<" here to check the upper bound because of rounding problems: With
     139             :   // "<=" some inputs would be considered within uint64 range which are actually
     140             :   // not within uint64 range.
     141        1840 :   if (input > -1.0 &&
     142             :       input < static_cast<float>(std::numeric_limits<uint64_t>::max())) {
     143         816 :     WriteUnalignedValue<uint64_t>(data, static_cast<uint64_t>(input));
     144         816 :     return 1;
     145             :   }
     146             :   return 0;
     147             : }
     148             : 
     149        1116 : int32_t float64_to_int64_wrapper(Address data) {
     150             :   // We use "<" here to check the upper bound because of rounding problems: With
     151             :   // "<=" some inputs would be considered within int64 range which are actually
     152             :   // not within int64 range.
     153             :   double input = ReadUnalignedValue<double>(data);
     154        1116 :   if (input >= static_cast<double>(std::numeric_limits<int64_t>::min()) &&
     155             :       input < static_cast<double>(std::numeric_limits<int64_t>::max())) {
     156         940 :     WriteUnalignedValue<int64_t>(data, static_cast<int64_t>(input));
     157         940 :     return 1;
     158             :   }
     159             :   return 0;
     160             : }
     161             : 
     162         784 : int32_t float64_to_uint64_wrapper(Address data) {
     163             :   // We use "<" here to check the upper bound because of rounding problems: With
     164             :   // "<=" some inputs would be considered within uint64 range which are actually
     165             :   // not within uint64 range.
     166             :   double input = ReadUnalignedValue<double>(data);
     167         784 :   if (input > -1.0 &&
     168             :       input < static_cast<double>(std::numeric_limits<uint64_t>::max())) {
     169         464 :     WriteUnalignedValue<uint64_t>(data, static_cast<uint64_t>(input));
     170         464 :     return 1;
     171             :   }
     172             :   return 0;
     173             : }
     174             : 
     175       52488 : int32_t int64_div_wrapper(Address data) {
     176             :   int64_t dividend = ReadUnalignedValue<int64_t>(data);
     177       52488 :   int64_t divisor = ReadUnalignedValue<int64_t>(data + sizeof(dividend));
     178       52488 :   if (divisor == 0) {
     179             :     return 0;
     180             :   }
     181       51192 :   if (divisor == -1 && dividend == std::numeric_limits<int64_t>::min()) {
     182             :     return -1;
     183             :   }
     184       51192 :   WriteUnalignedValue<int64_t>(data, dividend / divisor);
     185       51192 :   return 1;
     186             : }
     187             : 
     188       52488 : int32_t int64_mod_wrapper(Address data) {
     189             :   int64_t dividend = ReadUnalignedValue<int64_t>(data);
     190       52488 :   int64_t divisor = ReadUnalignedValue<int64_t>(data + sizeof(dividend));
     191       52488 :   if (divisor == 0) {
     192             :     return 0;
     193             :   }
     194       51192 :   WriteUnalignedValue<int64_t>(data, dividend % divisor);
     195       51192 :   return 1;
     196             : }
     197             : 
     198       52488 : int32_t uint64_div_wrapper(Address data) {
     199             :   uint64_t dividend = ReadUnalignedValue<uint64_t>(data);
     200       52488 :   uint64_t divisor = ReadUnalignedValue<uint64_t>(data + sizeof(dividend));
     201       52488 :   if (divisor == 0) {
     202             :     return 0;
     203             :   }
     204       51192 :   WriteUnalignedValue<uint64_t>(data, dividend / divisor);
     205       51192 :   return 1;
     206             : }
     207             : 
     208       52488 : int32_t uint64_mod_wrapper(Address data) {
     209             :   uint64_t dividend = ReadUnalignedValue<uint64_t>(data);
     210       52488 :   uint64_t divisor = ReadUnalignedValue<uint64_t>(data + sizeof(dividend));
     211       52488 :   if (divisor == 0) {
     212             :     return 0;
     213             :   }
     214       51192 :   WriteUnalignedValue<uint64_t>(data, dividend % divisor);
     215       51192 :   return 1;
     216             : }
     217             : 
     218         464 : uint32_t word32_ctz_wrapper(Address data) {
     219         464 :   return base::bits::CountTrailingZeros(ReadUnalignedValue<uint32_t>(data));
     220             : }
     221             : 
     222         648 : uint32_t word64_ctz_wrapper(Address data) {
     223         648 :   return base::bits::CountTrailingZeros(ReadUnalignedValue<uint64_t>(data));
     224             : }
     225             : 
     226         464 : uint32_t word32_popcnt_wrapper(Address data) {
     227         464 :   return base::bits::CountPopulation(ReadUnalignedValue<uint32_t>(data));
     228             : }
     229             : 
     230         648 : uint32_t word64_popcnt_wrapper(Address data) {
     231         648 :   return base::bits::CountPopulation(ReadUnalignedValue<uint64_t>(data));
     232             : }
     233             : 
     234       26912 : uint32_t word32_rol_wrapper(Address data) {
     235             :   uint32_t input = ReadUnalignedValue<uint32_t>(data);
     236       53824 :   uint32_t shift = ReadUnalignedValue<uint32_t>(data + sizeof(input)) & 31;
     237       26912 :   return (input << shift) | (input >> ((32 - shift) & 31));
     238             : }
     239             : 
     240       26912 : uint32_t word32_ror_wrapper(Address data) {
     241             :   uint32_t input = ReadUnalignedValue<uint32_t>(data);
     242       53824 :   uint32_t shift = ReadUnalignedValue<uint32_t>(data + sizeof(input)) & 31;
     243       26912 :   return (input >> shift) | (input << ((32 - shift) & 31));
     244             : }
     245             : 
     246       19243 : void float64_pow_wrapper(Address data) {
     247             :   double x = ReadUnalignedValue<double>(data);
     248       19243 :   double y = ReadUnalignedValue<double>(data + sizeof(x));
     249       19243 :   WriteUnalignedValue<double>(data, base::ieee754::pow(x, y));
     250       19243 : }
     251             : 
     252        1312 : void memory_copy_wrapper(Address dst, Address src, uint32_t size) {
     253             :   // Use explicit forward and backward copy to match the required semantics for
     254             :   // the memory.copy instruction. It is assumed that the caller of this
     255             :   // function has already performed bounds checks, so {src + size} and
     256             :   // {dst + size} should not overflow.
     257             :   DCHECK(src + size >= src && dst + size >= dst);
     258        1312 :   uint8_t* dst8 = reinterpret_cast<uint8_t*>(dst);
     259        1312 :   uint8_t* src8 = reinterpret_cast<uint8_t*>(src);
     260        1312 :   if (src < dst && src + size > dst && dst + size > src) {
     261          12 :     dst8 += size - 1;
     262          12 :     src8 += size - 1;
     263          84 :     for (; size > 0; size--) {
     264          36 :       *dst8-- = *src8--;
     265             :     }
     266             :   } else {
     267    17844372 :     for (; size > 0; size--) {
     268     8921536 :       *dst8++ = *src8++;
     269             :     }
     270             :   }
     271        1312 : }
     272             : 
     273         140 : void memory_fill_wrapper(Address dst, uint32_t value, uint32_t size) {
     274             :   // Use an explicit forward copy to match the required semantics for the
     275             :   // memory.fill instruction. It is assumed that the caller of this function
     276             :   // has already performed bounds checks, so {dst + size} should not overflow.
     277             :   DCHECK(dst + size >= dst);
     278         140 :   uint8_t* dst8 = reinterpret_cast<uint8_t*>(dst);
     279         140 :   uint8_t value8 = static_cast<uint8_t>(value);
     280     5759652 :   for (; size > 0; size--) {
     281     2879756 :     *dst8++ = value8;
     282             :   }
     283         140 : }
     284             : 
     285             : static WasmTrapCallbackForTesting wasm_trap_callback_for_testing = nullptr;
     286             : 
     287     9693368 : void set_trap_callback_for_testing(WasmTrapCallbackForTesting callback) {
     288     9693368 :   wasm_trap_callback_for_testing = callback;
     289     9693368 : }
     290             : 
     291       72760 : void call_trap_callback_for_testing() {
     292       72760 :   if (wasm_trap_callback_for_testing) {
     293       72760 :     wasm_trap_callback_for_testing();
     294             :   }
     295       72760 : }
     296             : 
     297             : }  // namespace wasm
     298             : }  // namespace internal
     299      122004 : }  // namespace v8

Generated by: LCOV version 1.10