OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <math.h> | 5 #include <math.h> |
6 #include <stdint.h> | 6 #include <stdint.h> |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 #include <limits> | 8 #include <limits> |
9 | 9 |
10 #include "include/v8config.h" | 10 #include "include/v8config.h" |
(...skipping 24 matching lines...) Expand all Loading... |
35 | 35 |
36 void f64_ceil_wrapper(double* param) { | 36 void f64_ceil_wrapper(double* param) { |
37 WriteDoubleValue(param, ceil(ReadDoubleValue(param))); | 37 WriteDoubleValue(param, ceil(ReadDoubleValue(param))); |
38 } | 38 } |
39 | 39 |
40 void f64_nearest_int_wrapper(double* param) { | 40 void f64_nearest_int_wrapper(double* param) { |
41 WriteDoubleValue(param, nearbyint(ReadDoubleValue(param))); | 41 WriteDoubleValue(param, nearbyint(ReadDoubleValue(param))); |
42 } | 42 } |
43 | 43 |
44 void int64_to_float32_wrapper(int64_t* input, float* output) { | 44 void int64_to_float32_wrapper(int64_t* input, float* output) { |
45 *output = static_cast<float>(*input); | 45 *output = static_cast<float>(ReadUnalignedValue<int64_t>(input)); |
46 } | 46 } |
47 | 47 |
48 void uint64_to_float32_wrapper(uint64_t* input, float* output) { | 48 void uint64_to_float32_wrapper(uint64_t* input, float* output) { |
49 #if V8_CC_MSVC | 49 #if V8_CC_MSVC |
50 // With MSVC we use static_cast<float>(uint32_t) instead of | 50 // With MSVC we use static_cast<float>(uint32_t) instead of |
51 // static_cast<float>(uint64_t) to achieve round-to-nearest-ties-even | 51 // static_cast<float>(uint64_t) to achieve round-to-nearest-ties-even |
52 // semantics. The idea is to calculate | 52 // semantics. The idea is to calculate |
53 // static_cast<float>(high_word) * 2^32 + static_cast<float>(low_word). To | 53 // static_cast<float>(high_word) * 2^32 + static_cast<float>(low_word). To |
54 // achieve proper rounding in all cases we have to adjust the high_word | 54 // achieve proper rounding in all cases we have to adjust the high_word |
55 // with a "rounding bit" sometimes. The rounding bit is stored in the LSB of | 55 // with a "rounding bit" sometimes. The rounding bit is stored in the LSB of |
(...skipping 12 matching lines...) Expand all Loading... |
68 // Set the rounding bit. | 68 // Set the rounding bit. |
69 high_word |= 1; | 69 high_word |= 1; |
70 } | 70 } |
71 | 71 |
72 float result = static_cast<float>(high_word); | 72 float result = static_cast<float>(high_word); |
73 result *= shift; | 73 result *= shift; |
74 result += static_cast<float>(low_word); | 74 result += static_cast<float>(low_word); |
75 *output = result; | 75 *output = result; |
76 | 76 |
77 #else | 77 #else |
78 *output = static_cast<float>(*input); | 78 *output = static_cast<float>(ReadUnalignedValue<uint64_t>(input)); |
79 #endif | 79 #endif |
80 } | 80 } |
81 | 81 |
82 void int64_to_float64_wrapper(int64_t* input, double* output) { | 82 void int64_to_float64_wrapper(int64_t* input, double* output) { |
83 *output = static_cast<double>(*input); | 83 WriteDoubleValue(output, |
| 84 static_cast<double>(ReadUnalignedValue<int64_t>(input))); |
84 } | 85 } |
85 | 86 |
86 void uint64_to_float64_wrapper(uint64_t* input, double* output) { | 87 void uint64_to_float64_wrapper(uint64_t* input, double* output) { |
87 #if V8_CC_MSVC | 88 #if V8_CC_MSVC |
88 // With MSVC we use static_cast<double>(uint32_t) instead of | 89 // With MSVC we use static_cast<double>(uint32_t) instead of |
89 // static_cast<double>(uint64_t) to achieve round-to-nearest-ties-even | 90 // static_cast<double>(uint64_t) to achieve round-to-nearest-ties-even |
90 // semantics. The idea is to calculate | 91 // semantics. The idea is to calculate |
91 // static_cast<double>(high_word) * 2^32 + static_cast<double>(low_word). | 92 // static_cast<double>(high_word) * 2^32 + static_cast<double>(low_word). |
92 uint32_t low_word = static_cast<uint32_t>(*input & 0xffffffff); | 93 uint32_t low_word = static_cast<uint32_t>(*input & 0xffffffff); |
93 uint32_t high_word = static_cast<uint32_t>(*input >> 32); | 94 uint32_t high_word = static_cast<uint32_t>(*input >> 32); |
94 | 95 |
95 double shift = static_cast<double>(1ull << 32); | 96 double shift = static_cast<double>(1ull << 32); |
96 | 97 |
97 double result = static_cast<double>(high_word); | 98 double result = static_cast<double>(high_word); |
98 result *= shift; | 99 result *= shift; |
99 result += static_cast<double>(low_word); | 100 result += static_cast<double>(low_word); |
100 *output = result; | 101 *output = result; |
101 | 102 |
102 #else | 103 #else |
103 *output = static_cast<double>(*input); | 104 WriteDoubleValue(output, |
| 105 static_cast<double>(ReadUnalignedValue<uint64_t>(input))); |
104 #endif | 106 #endif |
105 } | 107 } |
106 | 108 |
107 int32_t float32_to_int64_wrapper(float* input, int64_t* output) { | 109 int32_t float32_to_int64_wrapper(float* input, int64_t* output) { |
108 // We use "<" here to check the upper bound because of rounding problems: With | 110 // We use "<" here to check the upper bound because of rounding problems: With |
109 // "<=" some inputs would be considered within int64 range which are actually | 111 // "<=" some inputs would be considered within int64 range which are actually |
110 // not within int64 range. | 112 // not within int64 range. |
111 if (*input >= static_cast<float>(std::numeric_limits<int64_t>::min()) && | 113 if (*input >= static_cast<float>(std::numeric_limits<int64_t>::min()) && |
112 *input < static_cast<float>(std::numeric_limits<int64_t>::max())) { | 114 *input < static_cast<float>(std::numeric_limits<int64_t>::max())) { |
113 *output = static_cast<int64_t>(*input); | 115 WriteUnalignedValue<int64_t>(output, static_cast<int64_t>(*input)); |
114 return 1; | 116 return 1; |
115 } | 117 } |
116 return 0; | 118 return 0; |
117 } | 119 } |
118 | 120 |
119 int32_t float32_to_uint64_wrapper(float* input, uint64_t* output) { | 121 int32_t float32_to_uint64_wrapper(float* input, uint64_t* output) { |
120 // We use "<" here to check the upper bound because of rounding problems: With | 122 // We use "<" here to check the upper bound because of rounding problems: With |
121 // "<=" some inputs would be considered within uint64 range which are actually | 123 // "<=" some inputs would be considered within uint64 range which are actually |
122 // not within uint64 range. | 124 // not within uint64 range. |
123 if (*input > -1.0 && | 125 if (*input > -1.0 && |
124 *input < static_cast<float>(std::numeric_limits<uint64_t>::max())) { | 126 *input < static_cast<float>(std::numeric_limits<uint64_t>::max())) { |
125 *output = static_cast<uint64_t>(*input); | 127 WriteUnalignedValue<uint64_t>(output, static_cast<uint64_t>(*input)); |
126 return 1; | 128 return 1; |
127 } | 129 } |
128 return 0; | 130 return 0; |
129 } | 131 } |
130 | 132 |
131 int32_t float64_to_int64_wrapper(double* input, int64_t* output) { | 133 int32_t float64_to_int64_wrapper(double* input, int64_t* output) { |
132 // We use "<" here to check the upper bound because of rounding problems: With | 134 // We use "<" here to check the upper bound because of rounding problems: With |
133 // "<=" some inputs would be considered within int64 range which are actually | 135 // "<=" some inputs would be considered within int64 range which are actually |
134 // not within int64 range. | 136 // not within int64 range. |
135 if (*input >= static_cast<double>(std::numeric_limits<int64_t>::min()) && | 137 double input_val = ReadDoubleValue(input); |
136 *input < static_cast<double>(std::numeric_limits<int64_t>::max())) { | 138 if (input_val >= static_cast<double>(std::numeric_limits<int64_t>::min()) && |
137 *output = static_cast<int64_t>(*input); | 139 input_val < static_cast<double>(std::numeric_limits<int64_t>::max())) { |
| 140 WriteUnalignedValue<int64_t>(output, static_cast<int64_t>(input_val)); |
138 return 1; | 141 return 1; |
139 } | 142 } |
140 return 0; | 143 return 0; |
141 } | 144 } |
142 | 145 |
143 int32_t float64_to_uint64_wrapper(double* input, uint64_t* output) { | 146 int32_t float64_to_uint64_wrapper(double* input, uint64_t* output) { |
144 // We use "<" here to check the upper bound because of rounding problems: With | 147 // We use "<" here to check the upper bound because of rounding problems: With |
145 // "<=" some inputs would be considered within uint64 range which are actually | 148 // "<=" some inputs would be considered within uint64 range which are actually |
146 // not within uint64 range. | 149 // not within uint64 range. |
147 if (*input > -1.0 && | 150 double input_val = ReadDoubleValue(input); |
148 *input < static_cast<double>(std::numeric_limits<uint64_t>::max())) { | 151 if (input_val > -1.0 && |
149 *output = static_cast<uint64_t>(*input); | 152 input_val < static_cast<double>(std::numeric_limits<uint64_t>::max())) { |
| 153 WriteUnalignedValue<uint64_t>(output, static_cast<uint64_t>(input_val)); |
150 return 1; | 154 return 1; |
151 } | 155 } |
152 return 0; | 156 return 0; |
153 } | 157 } |
154 | 158 |
155 int32_t int64_div_wrapper(int64_t* dst, int64_t* src) { | 159 int32_t int64_div_wrapper(int64_t* dst, int64_t* src) { |
156 if (*src == 0) { | 160 int64_t src_val = ReadUnalignedValue<int64_t>(src); |
| 161 int64_t dst_val = ReadUnalignedValue<int64_t>(dst); |
| 162 if (src_val == 0) { |
157 return 0; | 163 return 0; |
158 } | 164 } |
159 if (*src == -1 && *dst == std::numeric_limits<int64_t>::min()) { | 165 if (src_val == -1 && dst_val == std::numeric_limits<int64_t>::min()) { |
160 return -1; | 166 return -1; |
161 } | 167 } |
162 *dst /= *src; | 168 WriteUnalignedValue<int64_t>(dst, dst_val / src_val); |
163 return 1; | 169 return 1; |
164 } | 170 } |
165 | 171 |
166 int32_t int64_mod_wrapper(int64_t* dst, int64_t* src) { | 172 int32_t int64_mod_wrapper(int64_t* dst, int64_t* src) { |
167 if (*src == 0) { | 173 int64_t src_val = ReadUnalignedValue<int64_t>(src); |
| 174 int64_t dst_val = ReadUnalignedValue<int64_t>(dst); |
| 175 if (src_val == 0) { |
168 return 0; | 176 return 0; |
169 } | 177 } |
170 *dst %= *src; | 178 WriteUnalignedValue<int64_t>(dst, dst_val % src_val); |
171 return 1; | 179 return 1; |
172 } | 180 } |
173 | 181 |
174 int32_t uint64_div_wrapper(uint64_t* dst, uint64_t* src) { | 182 int32_t uint64_div_wrapper(uint64_t* dst, uint64_t* src) { |
175 if (*src == 0) { | 183 uint64_t src_val = ReadUnalignedValue<uint64_t>(src); |
| 184 uint64_t dst_val = ReadUnalignedValue<uint64_t>(dst); |
| 185 if (src_val == 0) { |
176 return 0; | 186 return 0; |
177 } | 187 } |
178 *dst /= *src; | 188 WriteUnalignedValue<uint64_t>(dst, dst_val / src_val); |
179 return 1; | 189 return 1; |
180 } | 190 } |
181 | 191 |
182 int32_t uint64_mod_wrapper(uint64_t* dst, uint64_t* src) { | 192 int32_t uint64_mod_wrapper(uint64_t* dst, uint64_t* src) { |
183 if (*src == 0) { | 193 uint64_t src_val = ReadUnalignedValue<uint64_t>(src); |
| 194 uint64_t dst_val = ReadUnalignedValue<uint64_t>(dst); |
| 195 if (src_val == 0) { |
184 return 0; | 196 return 0; |
185 } | 197 } |
186 *dst %= *src; | 198 WriteUnalignedValue<uint64_t>(dst, dst_val % src_val); |
187 return 1; | 199 return 1; |
188 } | 200 } |
189 | 201 |
190 uint32_t word32_ctz_wrapper(uint32_t* input) { | 202 uint32_t word32_ctz_wrapper(uint32_t* input) { |
191 return static_cast<uint32_t>(base::bits::CountTrailingZeros32(*input)); | 203 return static_cast<uint32_t>(base::bits::CountTrailingZeros32(*input)); |
192 } | 204 } |
193 | 205 |
194 uint32_t word64_ctz_wrapper(uint64_t* input) { | 206 uint32_t word64_ctz_wrapper(uint64_t* input) { |
195 return static_cast<uint32_t>(base::bits::CountTrailingZeros64(*input)); | 207 return static_cast<uint32_t>( |
| 208 base::bits::CountTrailingZeros64(ReadUnalignedValue<uint64_t>(input))); |
196 } | 209 } |
197 | 210 |
198 uint32_t word32_popcnt_wrapper(uint32_t* input) { | 211 uint32_t word32_popcnt_wrapper(uint32_t* input) { |
199 return static_cast<uint32_t>(base::bits::CountPopulation(*input)); | 212 return static_cast<uint32_t>(base::bits::CountPopulation(*input)); |
200 } | 213 } |
201 | 214 |
202 uint32_t word64_popcnt_wrapper(uint64_t* input) { | 215 uint32_t word64_popcnt_wrapper(uint64_t* input) { |
203 return static_cast<uint32_t>(base::bits::CountPopulation(*input)); | 216 return static_cast<uint32_t>( |
| 217 base::bits::CountPopulation(ReadUnalignedValue<uint64_t>(input))); |
204 } | 218 } |
205 | 219 |
206 void float64_pow_wrapper(double* param0, double* param1) { | 220 void float64_pow_wrapper(double* param0, double* param1) { |
207 double x = ReadDoubleValue(param0); | 221 double x = ReadDoubleValue(param0); |
208 double y = ReadDoubleValue(param1); | 222 double y = ReadDoubleValue(param1); |
209 WriteDoubleValue(param0, Pow(x, y)); | 223 WriteDoubleValue(param0, Pow(x, y)); |
210 } | 224 } |
211 | 225 |
212 static WasmTrapCallbackForTesting wasm_trap_callback_for_testing = nullptr; | 226 static WasmTrapCallbackForTesting wasm_trap_callback_for_testing = nullptr; |
213 | 227 |
214 void set_trap_callback_for_testing(WasmTrapCallbackForTesting callback) { | 228 void set_trap_callback_for_testing(WasmTrapCallbackForTesting callback) { |
215 wasm_trap_callback_for_testing = callback; | 229 wasm_trap_callback_for_testing = callback; |
216 } | 230 } |
217 | 231 |
218 void call_trap_callback_for_testing() { | 232 void call_trap_callback_for_testing() { |
219 if (wasm_trap_callback_for_testing) { | 233 if (wasm_trap_callback_for_testing) { |
220 wasm_trap_callback_for_testing(); | 234 wasm_trap_callback_for_testing(); |
221 } | 235 } |
222 } | 236 } |
223 | 237 |
224 } // namespace wasm | 238 } // namespace wasm |
225 } // namespace internal | 239 } // namespace internal |
226 } // namespace v8 | 240 } // namespace v8 |
OLD | NEW |