V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
wasm-external-refs.cc
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/utils.h"
14 #include "src/v8memory.h"
15 #include "src/wasm/wasm-external-refs.h"
16 
17 namespace v8 {
18 namespace internal {
19 namespace wasm {
20 
21 void f32_trunc_wrapper(Address data) {
22  WriteUnalignedValue<float>(data, truncf(ReadUnalignedValue<float>(data)));
23 }
24 
25 void f32_floor_wrapper(Address data) {
26  WriteUnalignedValue<float>(data, floorf(ReadUnalignedValue<float>(data)));
27 }
28 
29 void f32_ceil_wrapper(Address data) {
30  WriteUnalignedValue<float>(data, ceilf(ReadUnalignedValue<float>(data)));
31 }
32 
33 void f32_nearest_int_wrapper(Address data) {
34  WriteUnalignedValue<float>(data, nearbyintf(ReadUnalignedValue<float>(data)));
35 }
36 
37 void f64_trunc_wrapper(Address data) {
38  WriteUnalignedValue<double>(data, trunc(ReadUnalignedValue<double>(data)));
39 }
40 
41 void f64_floor_wrapper(Address data) {
42  WriteUnalignedValue<double>(data, floor(ReadUnalignedValue<double>(data)));
43 }
44 
45 void f64_ceil_wrapper(Address data) {
46  WriteUnalignedValue<double>(data, ceil(ReadUnalignedValue<double>(data)));
47 }
48 
49 void f64_nearest_int_wrapper(Address data) {
50  WriteUnalignedValue<double>(data,
51  nearbyint(ReadUnalignedValue<double>(data)));
52 }
53 
54 void int64_to_float32_wrapper(Address data) {
55  int64_t input = ReadUnalignedValue<int64_t>(data);
56  WriteUnalignedValue<float>(data, static_cast<float>(input));
57 }
58 
59 void uint64_to_float32_wrapper(Address data) {
60  uint64_t input = ReadUnalignedValue<uint64_t>(data);
61  float result = static_cast<float>(input);
62 
63 #if V8_CC_MSVC
64  // With MSVC we use static_cast<float>(uint32_t) instead of
65  // static_cast<float>(uint64_t) to achieve round-to-nearest-ties-even
66  // semantics. The idea is to calculate
67  // static_cast<float>(high_word) * 2^32 + static_cast<float>(low_word). To
68  // achieve proper rounding in all cases we have to adjust the high_word
69  // with a "rounding bit" sometimes. The rounding bit is stored in the LSB of
70  // the high_word if the low_word may affect the rounding of the high_word.
71  uint32_t low_word = static_cast<uint32_t>(input & 0xFFFFFFFF);
72  uint32_t high_word = static_cast<uint32_t>(input >> 32);
73 
74  float shift = static_cast<float>(1ull << 32);
75  // If the MSB of the high_word is set, then we make space for a rounding bit.
76  if (high_word < 0x80000000) {
77  high_word <<= 1;
78  shift = static_cast<float>(1ull << 31);
79  }
80 
81  if ((high_word & 0xFE000000) && low_word) {
82  // Set the rounding bit.
83  high_word |= 1;
84  }
85 
86  result = static_cast<float>(high_word);
87  result *= shift;
88  result += static_cast<float>(low_word);
89 #endif
90 
91  WriteUnalignedValue<float>(data, result);
92 }
93 
94 void int64_to_float64_wrapper(Address data) {
95  int64_t input = ReadUnalignedValue<int64_t>(data);
96  WriteUnalignedValue<double>(data, static_cast<double>(input));
97 }
98 
99 void uint64_to_float64_wrapper(Address data) {
100  uint64_t input = ReadUnalignedValue<uint64_t>(data);
101  double result = static_cast<double>(input);
102 
103 #if V8_CC_MSVC
104  // With MSVC we use static_cast<double>(uint32_t) instead of
105  // static_cast<double>(uint64_t) to achieve round-to-nearest-ties-even
106  // semantics. The idea is to calculate
107  // static_cast<double>(high_word) * 2^32 + static_cast<double>(low_word).
108  uint32_t low_word = static_cast<uint32_t>(input & 0xFFFFFFFF);
109  uint32_t high_word = static_cast<uint32_t>(input >> 32);
110 
111  double shift = static_cast<double>(1ull << 32);
112 
113  result = static_cast<double>(high_word);
114  result *= shift;
115  result += static_cast<double>(low_word);
116 #endif
117 
118  WriteUnalignedValue<double>(data, result);
119 }
120 
121 int32_t float32_to_int64_wrapper(Address data) {
122  // We use "<" here to check the upper bound because of rounding problems: With
123  // "<=" some inputs would be considered within int64 range which are actually
124  // not within int64 range.
125  float input = ReadUnalignedValue<float>(data);
126  if (input >= static_cast<float>(std::numeric_limits<int64_t>::min()) &&
127  input < static_cast<float>(std::numeric_limits<int64_t>::max())) {
128  WriteUnalignedValue<int64_t>(data, static_cast<int64_t>(input));
129  return 1;
130  }
131  return 0;
132 }
133 
134 int32_t float32_to_uint64_wrapper(Address data) {
135  float input = ReadUnalignedValue<float>(data);
136  // We use "<" here to check the upper bound because of rounding problems: With
137  // "<=" some inputs would be considered within uint64 range which are actually
138  // not within uint64 range.
139  if (input > -1.0 &&
140  input < static_cast<float>(std::numeric_limits<uint64_t>::max())) {
141  WriteUnalignedValue<uint64_t>(data, static_cast<uint64_t>(input));
142  return 1;
143  }
144  return 0;
145 }
146 
147 int32_t float64_to_int64_wrapper(Address data) {
148  // We use "<" here to check the upper bound because of rounding problems: With
149  // "<=" some inputs would be considered within int64 range which are actually
150  // not within int64 range.
151  double input = ReadUnalignedValue<double>(data);
152  if (input >= static_cast<double>(std::numeric_limits<int64_t>::min()) &&
153  input < static_cast<double>(std::numeric_limits<int64_t>::max())) {
154  WriteUnalignedValue<int64_t>(data, static_cast<int64_t>(input));
155  return 1;
156  }
157  return 0;
158 }
159 
160 int32_t float64_to_uint64_wrapper(Address data) {
161  // We use "<" here to check the upper bound because of rounding problems: With
162  // "<=" some inputs would be considered within uint64 range which are actually
163  // not within uint64 range.
164  double input = ReadUnalignedValue<double>(data);
165  if (input > -1.0 &&
166  input < static_cast<double>(std::numeric_limits<uint64_t>::max())) {
167  WriteUnalignedValue<uint64_t>(data, static_cast<uint64_t>(input));
168  return 1;
169  }
170  return 0;
171 }
172 
173 int32_t int64_div_wrapper(Address data) {
174  int64_t dividend = ReadUnalignedValue<int64_t>(data);
175  int64_t divisor = ReadUnalignedValue<int64_t>(data + sizeof(dividend));
176  if (divisor == 0) {
177  return 0;
178  }
179  if (divisor == -1 && dividend == std::numeric_limits<int64_t>::min()) {
180  return -1;
181  }
182  WriteUnalignedValue<int64_t>(data, dividend / divisor);
183  return 1;
184 }
185 
186 int32_t int64_mod_wrapper(Address data) {
187  int64_t dividend = ReadUnalignedValue<int64_t>(data);
188  int64_t divisor = ReadUnalignedValue<int64_t>(data + sizeof(dividend));
189  if (divisor == 0) {
190  return 0;
191  }
192  WriteUnalignedValue<int64_t>(data, dividend % divisor);
193  return 1;
194 }
195 
196 int32_t uint64_div_wrapper(Address data) {
197  uint64_t dividend = ReadUnalignedValue<uint64_t>(data);
198  uint64_t divisor = ReadUnalignedValue<uint64_t>(data + sizeof(dividend));
199  if (divisor == 0) {
200  return 0;
201  }
202  WriteUnalignedValue<uint64_t>(data, dividend / divisor);
203  return 1;
204 }
205 
206 int32_t uint64_mod_wrapper(Address data) {
207  uint64_t dividend = ReadUnalignedValue<uint64_t>(data);
208  uint64_t divisor = ReadUnalignedValue<uint64_t>(data + sizeof(dividend));
209  if (divisor == 0) {
210  return 0;
211  }
212  WriteUnalignedValue<uint64_t>(data, dividend % divisor);
213  return 1;
214 }
215 
216 uint32_t word32_ctz_wrapper(Address data) {
217  return base::bits::CountTrailingZeros(ReadUnalignedValue<uint32_t>(data));
218 }
219 
220 uint32_t word64_ctz_wrapper(Address data) {
221  return base::bits::CountTrailingZeros(ReadUnalignedValue<uint64_t>(data));
222 }
223 
224 uint32_t word32_popcnt_wrapper(Address data) {
225  return base::bits::CountPopulation(ReadUnalignedValue<uint32_t>(data));
226 }
227 
228 uint32_t word64_popcnt_wrapper(Address data) {
229  return base::bits::CountPopulation(ReadUnalignedValue<uint64_t>(data));
230 }
231 
232 uint32_t word32_rol_wrapper(Address data) {
233  uint32_t input = ReadUnalignedValue<uint32_t>(data);
234  uint32_t shift = ReadUnalignedValue<uint32_t>(data + sizeof(input)) & 31;
235  return (input << shift) | (input >> (32 - shift));
236 }
237 
238 uint32_t word32_ror_wrapper(Address data) {
239  uint32_t input = ReadUnalignedValue<uint32_t>(data);
240  uint32_t shift = ReadUnalignedValue<uint32_t>(data + sizeof(input)) & 31;
241  return (input >> shift) | (input << (32 - shift));
242 }
243 
244 void float64_pow_wrapper(Address data) {
245  double x = ReadUnalignedValue<double>(data);
246  double y = ReadUnalignedValue<double>(data + sizeof(x));
247  WriteUnalignedValue<double>(data, Pow(x, y));
248 }
249 
250 static WasmTrapCallbackForTesting wasm_trap_callback_for_testing = nullptr;
251 
252 void set_trap_callback_for_testing(WasmTrapCallbackForTesting callback) {
253  wasm_trap_callback_for_testing = callback;
254 }
255 
256 void call_trap_callback_for_testing() {
257  if (wasm_trap_callback_for_testing) {
258  wasm_trap_callback_for_testing();
259  }
260 }
261 
262 } // namespace wasm
263 } // namespace internal
264 } // namespace v8
Definition: libplatform.h:13