OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/bootstrap_natives.h" | 5 #include "vm/bootstrap_natives.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 | 8 |
9 #include "vm/exceptions.h" | 9 #include "vm/exceptions.h" |
10 #include "vm/native_entry.h" | 10 #include "vm/native_entry.h" |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 } \ | 195 } \ |
196 | 196 |
197 | 197 |
198 #define TYPED_DATA_NEW_NATIVE(name) \ | 198 #define TYPED_DATA_NEW_NATIVE(name) \ |
199 TYPED_DATA_NEW(name) \ | 199 TYPED_DATA_NEW(name) \ |
200 EXT_TYPED_DATA_NEW(name) \ | 200 EXT_TYPED_DATA_NEW(name) \ |
201 | 201 |
202 | 202 |
203 CLASS_LIST_TYPED_DATA(TYPED_DATA_NEW_NATIVE) | 203 CLASS_LIST_TYPED_DATA(TYPED_DATA_NEW_NATIVE) |
204 | 204 |
205 #define TYPED_DATA_GETTER(getter, object, access_size) \ | 205 #define TYPED_DATA_GETTER(getter, object, ctor, access_size) \ |
206 DEFINE_NATIVE_ENTRY(TypedData_##getter, 2) { \ | 206 DEFINE_NATIVE_ENTRY(TypedData_##getter, 2) { \ |
207 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ | 207 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ |
208 GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ | 208 GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ |
209 if (instance.IsTypedData()) { \ | 209 if (instance.IsTypedData()) { \ |
210 const TypedData& array = TypedData::Cast(instance); \ | 210 const TypedData& array = TypedData::Cast(instance); \ |
211 RangeCheck(offsetInBytes.Value(), access_size, \ | 211 RangeCheck(offsetInBytes.Value(), access_size, \ |
212 array.LengthInBytes(), access_size); \ | 212 array.LengthInBytes(), access_size); \ |
213 return object::New(array.getter(offsetInBytes.Value())); \ | 213 return object::ctor(array.getter(offsetInBytes.Value())); \ |
214 } \ | 214 } \ |
215 if (instance.IsExternalTypedData()) { \ | 215 if (instance.IsExternalTypedData()) { \ |
216 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ | 216 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ |
217 RangeCheck(offsetInBytes.Value(), access_size, \ | 217 RangeCheck(offsetInBytes.Value(), access_size, \ |
218 array.LengthInBytes(), access_size); \ | 218 array.LengthInBytes(), access_size); \ |
219 return object::New(array.getter(offsetInBytes.Value())); \ | 219 return object::ctor(array.getter(offsetInBytes.Value())); \ |
220 } \ | 220 } \ |
221 const String& error = String::Handle(String::NewFormatted( \ | 221 const String& error = String::Handle(String::NewFormatted( \ |
222 "Expected a TypedData object but found %s", instance.ToCString())); \ | 222 "Expected a TypedData object but found %s", instance.ToCString())); \ |
223 Exceptions::ThrowArgumentError(error); \ | 223 Exceptions::ThrowArgumentError(error); \ |
224 return object::null(); \ | 224 return object::null(); \ |
225 } \ | 225 } \ |
226 | 226 |
227 | 227 |
228 #define TYPED_DATA_SETTER(setter, \ | 228 #define TYPED_DATA_SETTER(setter, \ |
229 object, \ | 229 object, \ |
(...skipping 17 matching lines...) Expand all Loading... |
247 array.setter(offsetInBytes.Value(), \ | 247 array.setter(offsetInBytes.Value(), \ |
248 static_cast<access_type>(value.get_object_value())); \ | 248 static_cast<access_type>(value.get_object_value())); \ |
249 } else { \ | 249 } else { \ |
250 const String& error = String::Handle(String::NewFormatted( \ | 250 const String& error = String::Handle(String::NewFormatted( \ |
251 "Expected a TypedData object but found %s", instance.ToCString())); \ | 251 "Expected a TypedData object but found %s", instance.ToCString())); \ |
252 Exceptions::ThrowArgumentError(error); \ | 252 Exceptions::ThrowArgumentError(error); \ |
253 } \ | 253 } \ |
254 return Object::null(); \ | 254 return Object::null(); \ |
255 } | 255 } |
256 | 256 |
257 | 257 #define TYPED_DATA_NATIVES(type_name, \ |
258 #define TYPED_DATA_UINT64_GETTER(getter, object) \ | |
259 DEFINE_NATIVE_ENTRY(TypedData_##getter, 2) { \ | |
260 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ | |
261 GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ | |
262 uint64_t value = 0; \ | |
263 if (instance.IsTypedData()) { \ | |
264 const TypedData& array = TypedData::Cast(instance); \ | |
265 RangeCheck(offsetInBytes.Value(), 8, array.LengthInBytes(), 8); \ | |
266 value = array.getter(offsetInBytes.Value()); \ | |
267 } else if (instance.IsExternalTypedData()) { \ | |
268 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ | |
269 RangeCheck(offsetInBytes.Value(), 8, array.LengthInBytes(), 8); \ | |
270 value = array.getter(offsetInBytes.Value()); \ | |
271 } else { \ | |
272 const String& error = String::Handle(String::NewFormatted( \ | |
273 "Expected a TypedData object but found %s", instance.ToCString())); \ | |
274 Exceptions::ThrowArgumentError(error); \ | |
275 } \ | |
276 return Integer::NewFromUint64(value); \ | |
277 } \ | |
278 | |
279 | |
280 // TODO(asiva): Consider truncating the bigint value if it does not fit into | |
281 // a uint64_t value (see ASSERT(BigintOperations::FitsIntoUint64(bigint))). | |
282 // TODO(regis): Shouldn't we throw an argument error if the bigint is too large | |
283 // instead of assert faulting or truncating the bigint as suggested? | |
284 #define TYPED_DATA_UINT64_SETTER(setter, object) \ | |
285 DEFINE_NATIVE_ENTRY(TypedData_##setter, 3) { \ | |
286 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ | |
287 GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ | |
288 GET_NON_NULL_NATIVE_ARGUMENT(object, value, arguments->NativeArgAt(2)); \ | |
289 uint64_t object_value; \ | |
290 if (value.IsBigint()) { \ | |
291 const Bigint& bigint = Bigint::Cast(value); \ | |
292 ASSERT(bigint.FitsIntoUint64()); \ | |
293 object_value = bigint.AsUint64Value(); \ | |
294 } else { \ | |
295 ASSERT(value.IsMint() || value.IsSmi()); \ | |
296 object_value = value.AsInt64Value(); \ | |
297 } \ | |
298 if (instance.IsTypedData()) { \ | |
299 const TypedData& array = TypedData::Cast(instance); \ | |
300 RangeCheck(offsetInBytes.Value(), 8, array.LengthInBytes(), 8); \ | |
301 array.setter(offsetInBytes.Value(), object_value); \ | |
302 } else if (instance.IsExternalTypedData()) { \ | |
303 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ | |
304 RangeCheck(offsetInBytes.Value(), 8, array.LengthInBytes(), 8); \ | |
305 array.setter(offsetInBytes.Value(), object_value); \ | |
306 } else { \ | |
307 const String& error = String::Handle(String::NewFormatted( \ | |
308 "Expected a TypedData object but found %s", instance.ToCString())); \ | |
309 Exceptions::ThrowArgumentError(error); \ | |
310 } \ | |
311 return Object::null(); \ | |
312 } | |
313 | |
314 | |
315 #define TYPED_DATA_NATIVES(getter, \ | |
316 setter, \ | |
317 object, \ | 258 object, \ |
| 259 ctor, \ |
318 get_object_value, \ | 260 get_object_value, \ |
319 access_size, \ | 261 access_size, \ |
320 access_type) \ | 262 access_type) \ |
321 TYPED_DATA_GETTER(getter, object, access_size) \ | 263 TYPED_DATA_GETTER(Get##type_name, object, ctor, access_size) \ |
322 TYPED_DATA_SETTER(setter, object, get_object_value, access_size, access_type)\ | 264 TYPED_DATA_SETTER(Set##type_name, object, \ |
| 265 get_object_value, access_size, access_type) \ |
323 | 266 |
324 | 267 TYPED_DATA_NATIVES(Int8, Integer, New, AsTruncatedUint32Value, 1, int8_t) |
325 #define TYPED_DATA_UINT64_NATIVES(getter, setter, object) \ | 268 TYPED_DATA_NATIVES(Uint8, Integer, New, AsTruncatedUint32Value, 1, uint8_t) |
326 TYPED_DATA_UINT64_GETTER(getter, object) \ | 269 TYPED_DATA_NATIVES(Int16, Integer, New, AsTruncatedUint32Value, 2, int16_t) |
327 TYPED_DATA_UINT64_SETTER(setter, object) \ | 270 TYPED_DATA_NATIVES(Uint16, Integer, New, AsTruncatedUint32Value, 2, uint16_t) |
328 | 271 TYPED_DATA_NATIVES(Int32, Integer, New, AsTruncatedUint32Value, 4, int32_t) |
329 | 272 TYPED_DATA_NATIVES(Uint32, Integer, New, AsTruncatedUint32Value, 4, uint32_t) |
330 TYPED_DATA_NATIVES(GetInt8, SetInt8, Smi, Value, 1, int8_t) | 273 TYPED_DATA_NATIVES(Int64, Integer, New, AsTruncatedInt64Value, 8, int64_t) |
331 TYPED_DATA_NATIVES(GetUint8, SetUint8, Smi, Value, 1, uint8_t) | |
332 TYPED_DATA_NATIVES(GetInt16, SetInt16, Smi, Value, 2, int16_t) | |
333 TYPED_DATA_NATIVES(GetUint16, SetUint16, Smi, Value, 2, uint16_t) | |
334 TYPED_DATA_NATIVES(GetInt32, SetInt32, Integer, AsInt64Value, 4, int32_t) | |
335 TYPED_DATA_NATIVES(GetUint32, SetUint32, Integer, AsInt64Value, 4, uint32_t) | |
336 TYPED_DATA_NATIVES(GetInt64, SetInt64, Integer, AsInt64Value, 8, int64_t) | |
337 TYPED_DATA_UINT64_NATIVES(GetUint64, SetUint64, Integer) | |
338 TYPED_DATA_NATIVES(GetFloat32, SetFloat32, Double, value, 4, float) | |
339 TYPED_DATA_NATIVES(GetFloat64, SetFloat64, Double, value, 8, double) | |
340 TYPED_DATA_NATIVES( | 274 TYPED_DATA_NATIVES( |
341 GetFloat32x4, SetFloat32x4, Float32x4, value, 16, simd128_value_t) | 275 Uint64, Integer, NewFromUint64, AsTruncatedInt64Value, 8, uint64_t) |
342 TYPED_DATA_NATIVES(GetInt32x4, SetInt32x4, Int32x4, value, 16, simd128_value_t) | 276 TYPED_DATA_NATIVES(Float32, Double, New, value, 4, float) |
343 TYPED_DATA_NATIVES( | 277 TYPED_DATA_NATIVES(Float64, Double, New, value, 8, double) |
344 GetFloat64x2, SetFloat64x2, Float64x2, value, 16, simd128_value_t) | 278 TYPED_DATA_NATIVES(Float32x4, Float32x4, New, value, 16, simd128_value_t) |
| 279 TYPED_DATA_NATIVES(Int32x4, Int32x4, New, value, 16, simd128_value_t) |
| 280 TYPED_DATA_NATIVES(Float64x2, Float64x2, New, value, 16, simd128_value_t) |
345 | 281 |
346 | 282 |
347 DEFINE_NATIVE_ENTRY(ByteData_ToEndianInt16, 2) { | 283 DEFINE_NATIVE_ENTRY(ByteData_ToEndianInt16, 2) { |
348 GET_NON_NULL_NATIVE_ARGUMENT(Smi, host_value, arguments->NativeArgAt(0)); | 284 GET_NON_NULL_NATIVE_ARGUMENT(Smi, host_value, arguments->NativeArgAt(0)); |
349 GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); | 285 GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); |
350 int16_t value = host_value.Value(); | 286 int16_t value = host_value.Value(); |
351 if (little_endian.value()) { | 287 if (little_endian.value()) { |
352 value = Utils::HostToLittleEndian16(value); | 288 value = Utils::HostToLittleEndian16(value); |
353 } else { | 289 } else { |
354 value = Utils::HostToBigEndian16(value); | 290 value = Utils::HostToBigEndian16(value); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 value = bit_cast<double>( | 390 value = bit_cast<double>( |
455 Utils::HostToLittleEndian64(bit_cast<uint64_t>(value))); | 391 Utils::HostToLittleEndian64(bit_cast<uint64_t>(value))); |
456 } else { | 392 } else { |
457 value = bit_cast<double>( | 393 value = bit_cast<double>( |
458 Utils::HostToBigEndian64(bit_cast<uint64_t>(value))); | 394 Utils::HostToBigEndian64(bit_cast<uint64_t>(value))); |
459 } | 395 } |
460 return Double::New(value); | 396 return Double::New(value); |
461 } | 397 } |
462 | 398 |
463 } // namespace dart | 399 } // namespace dart |
OLD | NEW |