| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 #include "vm/bootstrap_natives.h" | |
| 6 | |
| 7 #include "include/dart_api.h" | |
| 8 | |
| 9 #include "vm/bigint_operations.h" | |
| 10 #include "vm/exceptions.h" | |
| 11 #include "vm/native_entry.h" | |
| 12 #include "vm/object.h" | |
| 13 | |
| 14 namespace dart { | |
| 15 | |
| 16 // TypedData. | |
| 17 | |
| 18 // Checks to see if offset_in_bytes is in the range. | |
| 19 static bool RangeCheck(intptr_t offset_in_bytes, intptr_t length_in_bytes) { | |
| 20 return ((offset_in_bytes >= 0) && | |
| 21 (length_in_bytes > 0) && | |
| 22 (offset_in_bytes < length_in_bytes)); | |
| 23 } | |
| 24 | |
| 25 | |
| 26 // Checks to see if offsetInBytes + num_bytes is in the range. | |
| 27 static void SetRangeCheck(intptr_t offset_in_bytes, | |
| 28 intptr_t num_bytes, | |
| 29 intptr_t length_in_bytes, | |
| 30 intptr_t element_size_in_bytes) { | |
| 31 if (!Utils::RangeCheck(offset_in_bytes, num_bytes, length_in_bytes)) { | |
| 32 const String& error = String::Handle(String::NewFormatted( | |
| 33 "index (%"Pd") must be in the range [0..%"Pd")", | |
| 34 (offset_in_bytes / element_size_in_bytes), | |
| 35 (length_in_bytes / element_size_in_bytes))); | |
| 36 const Array& args = Array::Handle(Array::New(1)); | |
| 37 args.SetAt(0, error); | |
| 38 Exceptions::ThrowByType(Exceptions::kRange, args); | |
| 39 } | |
| 40 } | |
| 41 | |
| 42 | |
| 43 // Checks to see if a length will not result in an OOM error. | |
| 44 static void LengthCheck(intptr_t len, intptr_t max) { | |
| 45 ASSERT(len >= 0); | |
| 46 if (len > max) { | |
| 47 const String& error = String::Handle(String::NewFormatted( | |
| 48 "insufficient memory to allocate a TypedData object of length (%"Pd")", | |
| 49 len)); | |
| 50 const Array& args = Array::Handle(Array::New(1)); | |
| 51 args.SetAt(0, error); | |
| 52 Exceptions::ThrowByType(Exceptions::kOutOfMemory, args); | |
| 53 } | |
| 54 } | |
| 55 | |
| 56 | |
| 57 static void PeerFinalizer(Dart_Handle handle, void* peer) { | |
| 58 Dart_DeletePersistentHandle(handle); | |
| 59 OS::AlignedFree(peer); | |
| 60 } | |
| 61 | |
| 62 | |
| 63 DEFINE_NATIVE_ENTRY(TypedData_length, 1) { | |
| 64 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); | |
| 65 if (instance.IsTypedData()) { | |
| 66 const TypedData& array = TypedData::Cast(instance); | |
| 67 return Smi::New(array.Length()); | |
| 68 } | |
| 69 if (instance.IsExternalTypedData()) { | |
| 70 const ExternalTypedData& array = ExternalTypedData::Cast(instance); | |
| 71 return Smi::New(array.Length()); | |
| 72 } | |
| 73 const String& error = String::Handle(String::NewFormatted( | |
| 74 "Expected a TypedData object but found %s", instance.ToCString())); | |
| 75 const Array& args = Array::Handle(Array::New(1)); | |
| 76 args.SetAt(0, error); | |
| 77 Exceptions::ThrowByType(Exceptions::kArgument, args); | |
| 78 return Integer::null(); | |
| 79 } | |
| 80 | |
| 81 template <typename DstType, typename SrcType> | |
| 82 static RawBool* CopyData(const Instance& dst, const Instance& src, | |
| 83 const Smi& dst_start, const Smi& src_start, | |
| 84 const Smi& length) { | |
| 85 const DstType& dst_array = DstType::Cast(dst); | |
| 86 const SrcType& src_array = SrcType::Cast(src); | |
| 87 intptr_t element_size_in_bytes = dst_array.ElementSizeInBytes(); | |
| 88 intptr_t dst_offset_in_bytes = dst_start.Value() * element_size_in_bytes; | |
| 89 intptr_t src_offset_in_bytes = src_start.Value() * element_size_in_bytes; | |
| 90 intptr_t length_in_bytes = length.Value() * element_size_in_bytes; | |
| 91 if (dst_array.ElementType() != src_array.ElementType()) { | |
| 92 return Bool::False().raw(); | |
| 93 } | |
| 94 SetRangeCheck(src_offset_in_bytes, | |
| 95 length_in_bytes, | |
| 96 src_array.LengthInBytes(), | |
| 97 element_size_in_bytes); | |
| 98 SetRangeCheck(dst_offset_in_bytes, | |
| 99 length_in_bytes, | |
| 100 dst_array.LengthInBytes(), | |
| 101 element_size_in_bytes); | |
| 102 TypedData::Copy<DstType, SrcType>(dst_array, dst_offset_in_bytes, | |
| 103 src_array, src_offset_in_bytes, | |
| 104 length_in_bytes); | |
| 105 return Bool::True().raw(); | |
| 106 } | |
| 107 | |
| 108 DEFINE_NATIVE_ENTRY(TypedData_setRange, 5) { | |
| 109 GET_NON_NULL_NATIVE_ARGUMENT(Instance, dst, arguments->NativeArgAt(0)); | |
| 110 GET_NON_NULL_NATIVE_ARGUMENT(Smi, dst_start, arguments->NativeArgAt(1)); | |
| 111 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(2)); | |
| 112 GET_NON_NULL_NATIVE_ARGUMENT(Instance, src, arguments->NativeArgAt(3)); | |
| 113 GET_NON_NULL_NATIVE_ARGUMENT(Smi, src_start, arguments->NativeArgAt(4)); | |
| 114 | |
| 115 if (length.Value() < 0) { | |
| 116 const String& error = String::Handle(String::NewFormatted( | |
| 117 "length (%"Pd") must be non-negative", length.Value())); | |
| 118 const Array& args = Array::Handle(Array::New(1)); | |
| 119 args.SetAt(0, error); | |
| 120 Exceptions::ThrowByType(Exceptions::kArgument, args); | |
| 121 } | |
| 122 if (dst.IsTypedData()) { | |
| 123 if (src.IsTypedData()) { | |
| 124 return CopyData<TypedData, TypedData>( | |
| 125 dst, src, dst_start, src_start, length); | |
| 126 } else if (src.IsExternalTypedData()) { | |
| 127 return CopyData<TypedData, ExternalTypedData>( | |
| 128 dst, src, dst_start, src_start, length); | |
| 129 } | |
| 130 } else if (dst.IsExternalTypedData()) { | |
| 131 if (src.IsTypedData()) { | |
| 132 return CopyData<ExternalTypedData, TypedData>( | |
| 133 dst, src, dst_start, src_start, length); | |
| 134 } else if (src.IsExternalTypedData()) { | |
| 135 return CopyData<ExternalTypedData, ExternalTypedData>( | |
| 136 dst, src, dst_start, src_start, length); | |
| 137 } | |
| 138 } | |
| 139 return Bool::False().raw(); | |
| 140 } | |
| 141 | |
| 142 | |
| 143 // We check the length parameter against a possible maximum length for the | |
| 144 // array based on available physical addressable memory on the system. The | |
| 145 // maximum possible length is a scaled value of kSmiMax which is set up based | |
| 146 // on whether the underlying architecture is 32-bit or 64-bit. | |
| 147 #define TYPED_DATA_NEW(name) \ | |
| 148 DEFINE_NATIVE_ENTRY(TypedData_##name##_new, 1) { \ | |
| 149 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0)); \ | |
| 150 intptr_t cid = kTypedData##name##Cid; \ | |
| 151 intptr_t len = length.Value(); \ | |
| 152 intptr_t max = TypedData::MaxElements(cid); \ | |
| 153 LengthCheck(len, max); \ | |
| 154 return TypedData::New(cid, len); \ | |
| 155 } \ | |
| 156 | |
| 157 | |
| 158 // We check the length parameter against a possible maximum length for the | |
| 159 // array based on available physical addressable memory on the system. The | |
| 160 // maximum possible length is a scaled value of kSmiMax which is set up based | |
| 161 // on whether the underlying architecture is 32-bit or 64-bit. | |
| 162 #define EXT_TYPED_DATA_NEW(name) \ | |
| 163 DEFINE_NATIVE_ENTRY(ExternalTypedData_##name##_new, 1) { \ | |
| 164 const int kAlignment = 16; \ | |
| 165 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0)); \ | |
| 166 intptr_t cid = kExternalTypedData##name##Cid; \ | |
| 167 intptr_t len = length.Value(); \ | |
| 168 intptr_t max = ExternalTypedData::MaxElements(cid); \ | |
| 169 LengthCheck(len, max); \ | |
| 170 intptr_t len_bytes = len * ExternalTypedData::ElementSizeInBytes(cid); \ | |
| 171 uint8_t* data = OS::AllocateAlignedArray<uint8_t>(len_bytes, kAlignment); \ | |
| 172 const ExternalTypedData& obj = \ | |
| 173 ExternalTypedData::Handle(ExternalTypedData::New(cid, data, len)); \ | |
| 174 obj.AddFinalizer(data, PeerFinalizer); \ | |
| 175 return obj.raw(); \ | |
| 176 } \ | |
| 177 | |
| 178 | |
| 179 #define TYPED_DATA_NEW_NATIVE(name) \ | |
| 180 TYPED_DATA_NEW(name) \ | |
| 181 EXT_TYPED_DATA_NEW(name) \ | |
| 182 | |
| 183 | |
| 184 CLASS_LIST_TYPED_DATA(TYPED_DATA_NEW_NATIVE) | |
| 185 | |
| 186 #define TYPED_DATA_GETTER(getter, object) \ | |
| 187 DEFINE_NATIVE_ENTRY(TypedData_##getter, 2) { \ | |
| 188 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ | |
| 189 GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ | |
| 190 if (instance.IsTypedData()) { \ | |
| 191 const TypedData& array = TypedData::Cast(instance); \ | |
| 192 ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ | |
| 193 return object::New(array.getter(offsetInBytes.Value())); \ | |
| 194 } \ | |
| 195 if (instance.IsExternalTypedData()) { \ | |
| 196 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ | |
| 197 ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ | |
| 198 return object::New(array.getter(offsetInBytes.Value())); \ | |
| 199 } \ | |
| 200 const String& error = String::Handle(String::NewFormatted( \ | |
| 201 "Expected a TypedData object but found %s", instance.ToCString())); \ | |
| 202 const Array& args = Array::Handle(Array::New(1)); \ | |
| 203 args.SetAt(0, error); \ | |
| 204 Exceptions::ThrowByType(Exceptions::kArgument, args); \ | |
| 205 return object::null(); \ | |
| 206 } \ | |
| 207 | |
| 208 | |
| 209 #define TYPED_DATA_SETTER(setter, object, get_object_value) \ | |
| 210 DEFINE_NATIVE_ENTRY(TypedData_##setter, 3) { \ | |
| 211 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ | |
| 212 GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ | |
| 213 GET_NON_NULL_NATIVE_ARGUMENT(object, value, arguments->NativeArgAt(2)); \ | |
| 214 if (instance.IsTypedData()) { \ | |
| 215 const TypedData& array = TypedData::Cast(instance); \ | |
| 216 ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ | |
| 217 array.setter(offsetInBytes.Value(), value.get_object_value()); \ | |
| 218 } else if (instance.IsExternalTypedData()) { \ | |
| 219 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ | |
| 220 ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ | |
| 221 array.setter(offsetInBytes.Value(), value.get_object_value()); \ | |
| 222 } else { \ | |
| 223 const String& error = String::Handle(String::NewFormatted( \ | |
| 224 "Expected a TypedData object but found %s", instance.ToCString())); \ | |
| 225 const Array& args = Array::Handle(Array::New(1)); \ | |
| 226 args.SetAt(0, error); \ | |
| 227 Exceptions::ThrowByType(Exceptions::kArgument, args); \ | |
| 228 } \ | |
| 229 return Object::null(); \ | |
| 230 } | |
| 231 | |
| 232 | |
| 233 #define TYPED_DATA_UINT64_GETTER(getter, object) \ | |
| 234 DEFINE_NATIVE_ENTRY(TypedData_##getter, 2) { \ | |
| 235 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ | |
| 236 GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ | |
| 237 uint64_t value = 0; \ | |
| 238 if (instance.IsTypedData()) { \ | |
| 239 const TypedData& array = TypedData::Cast(instance); \ | |
| 240 ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ | |
| 241 value = array.getter(offsetInBytes.Value()); \ | |
| 242 } else if (instance.IsExternalTypedData()) { \ | |
| 243 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ | |
| 244 ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ | |
| 245 value = array.getter(offsetInBytes.Value()); \ | |
| 246 } else { \ | |
| 247 const String& error = String::Handle(String::NewFormatted( \ | |
| 248 "Expected a TypedData object but found %s", instance.ToCString())); \ | |
| 249 const Array& args = Array::Handle(Array::New(1)); \ | |
| 250 args.SetAt(0, error); \ | |
| 251 Exceptions::ThrowByType(Exceptions::kArgument, args); \ | |
| 252 } \ | |
| 253 Integer& result = Integer::Handle(); \ | |
| 254 if (value > static_cast<uint64_t>(Mint::kMaxValue)) { \ | |
| 255 result = BigintOperations::NewFromUint64(value); \ | |
| 256 } else if (value > static_cast<uint64_t>(Smi::kMaxValue)) { \ | |
| 257 result = Mint::New(value); \ | |
| 258 } else { \ | |
| 259 result = Smi::New(value); \ | |
| 260 } \ | |
| 261 return result.raw(); \ | |
| 262 } \ | |
| 263 | |
| 264 | |
| 265 // TODO(asiva): Consider truncating the bigint value if it does not fit into | |
| 266 // a uint64_t value (see ASSERT(BigintOperations::FitsIntoUint64(bigint))). | |
| 267 #define TYPED_DATA_UINT64_SETTER(setter, object) \ | |
| 268 DEFINE_NATIVE_ENTRY(TypedData_##setter, 3) { \ | |
| 269 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ | |
| 270 GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ | |
| 271 GET_NON_NULL_NATIVE_ARGUMENT(object, value, arguments->NativeArgAt(2)); \ | |
| 272 uint64_t object_value; \ | |
| 273 if (value.IsBigint()) { \ | |
| 274 const Bigint& bigint = Bigint::Cast(value); \ | |
| 275 ASSERT(BigintOperations::FitsIntoUint64(bigint)); \ | |
| 276 object_value = BigintOperations::AbsToUint64(bigint); \ | |
| 277 } else { \ | |
| 278 ASSERT(value.IsMint() || value.IsSmi()); \ | |
| 279 object_value = value.AsInt64Value(); \ | |
| 280 } \ | |
| 281 if (instance.IsTypedData()) { \ | |
| 282 const TypedData& array = TypedData::Cast(instance); \ | |
| 283 ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ | |
| 284 array.setter(offsetInBytes.Value(), object_value); \ | |
| 285 } else if (instance.IsExternalTypedData()) { \ | |
| 286 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ | |
| 287 ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ | |
| 288 array.setter(offsetInBytes.Value(), object_value); \ | |
| 289 } else { \ | |
| 290 const String& error = String::Handle(String::NewFormatted( \ | |
| 291 "Expected a TypedData object but found %s", instance.ToCString())); \ | |
| 292 const Array& args = Array::Handle(Array::New(1)); \ | |
| 293 args.SetAt(0, error); \ | |
| 294 Exceptions::ThrowByType(Exceptions::kArgument, args); \ | |
| 295 } \ | |
| 296 return Object::null(); \ | |
| 297 } | |
| 298 | |
| 299 | |
| 300 #define TYPED_DATA_NATIVES(getter, setter, object, get_object_value) \ | |
| 301 TYPED_DATA_GETTER(getter, object) \ | |
| 302 TYPED_DATA_SETTER(setter, object, get_object_value) \ | |
| 303 | |
| 304 | |
| 305 #define TYPED_DATA_UINT64_NATIVES(getter, setter, object) \ | |
| 306 TYPED_DATA_UINT64_GETTER(getter, object) \ | |
| 307 TYPED_DATA_UINT64_SETTER(setter, object) \ | |
| 308 | |
| 309 | |
| 310 TYPED_DATA_NATIVES(GetInt8, SetInt8, Smi, Value) | |
| 311 TYPED_DATA_NATIVES(GetUint8, SetUint8, Smi, Value) | |
| 312 TYPED_DATA_NATIVES(GetInt16, SetInt16, Smi, Value) | |
| 313 TYPED_DATA_NATIVES(GetUint16, SetUint16, Smi, Value) | |
| 314 TYPED_DATA_NATIVES(GetInt32, SetInt32, Integer, AsInt64Value) | |
| 315 TYPED_DATA_NATIVES(GetUint32, SetUint32, Integer, AsInt64Value) | |
| 316 TYPED_DATA_NATIVES(GetInt64, SetInt64, Integer, AsInt64Value) | |
| 317 TYPED_DATA_UINT64_NATIVES(GetUint64, SetUint64, Integer) | |
| 318 TYPED_DATA_NATIVES(GetFloat32, SetFloat32, Double, value) | |
| 319 TYPED_DATA_NATIVES(GetFloat64, SetFloat64, Double, value) | |
| 320 TYPED_DATA_NATIVES(GetFloat32x4, SetFloat32x4, Float32x4, value) | |
| 321 | |
| 322 | |
| 323 DEFINE_NATIVE_ENTRY(ByteData_ToEndianInt16, 2) { | |
| 324 GET_NON_NULL_NATIVE_ARGUMENT(Smi, host_value, arguments->NativeArgAt(0)); | |
| 325 GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); | |
| 326 int16_t value = host_value.Value(); | |
| 327 if (little_endian.value()) { | |
| 328 value = Utils::HostToLittleEndian16(value); | |
| 329 } else { | |
| 330 value = Utils::HostToBigEndian16(value); | |
| 331 } | |
| 332 return Smi::New(value); | |
| 333 } | |
| 334 | |
| 335 | |
| 336 DEFINE_NATIVE_ENTRY(ByteData_ToEndianUint16, 2) { | |
| 337 GET_NON_NULL_NATIVE_ARGUMENT(Smi, host_value, arguments->NativeArgAt(0)); | |
| 338 GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); | |
| 339 uint16_t value = host_value.Value(); | |
| 340 if (little_endian.value()) { | |
| 341 return Smi::New(Utils::HostToLittleEndian16(value)); | |
| 342 } | |
| 343 return Smi::New(Utils::HostToBigEndian16(value)); | |
| 344 } | |
| 345 | |
| 346 | |
| 347 DEFINE_NATIVE_ENTRY(ByteData_ToEndianInt32, 2) { | |
| 348 GET_NON_NULL_NATIVE_ARGUMENT(Integer, host_value, arguments->NativeArgAt(0)); | |
| 349 GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); | |
| 350 ASSERT(host_value.AsInt64Value() <= kMaxInt32); | |
| 351 int32_t value = host_value.AsInt64Value(); | |
| 352 if (little_endian.value()) { | |
| 353 value = Utils::HostToLittleEndian32(value); | |
| 354 } else { | |
| 355 value = Utils::HostToBigEndian32(value); | |
| 356 } | |
| 357 return Integer::New(value); | |
| 358 } | |
| 359 | |
| 360 | |
| 361 DEFINE_NATIVE_ENTRY(ByteData_ToEndianUint32, 2) { | |
| 362 GET_NON_NULL_NATIVE_ARGUMENT(Integer, host_value, arguments->NativeArgAt(0)); | |
| 363 GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); | |
| 364 ASSERT(host_value.AsInt64Value() <= kMaxUint32); | |
| 365 uint32_t value = host_value.AsInt64Value(); | |
| 366 if (little_endian.value()) { | |
| 367 value = Utils::HostToLittleEndian32(value); | |
| 368 } else { | |
| 369 value = Utils::HostToBigEndian32(value); | |
| 370 } | |
| 371 return Integer::New(value); | |
| 372 } | |
| 373 | |
| 374 | |
| 375 DEFINE_NATIVE_ENTRY(ByteData_ToEndianInt64, 2) { | |
| 376 GET_NON_NULL_NATIVE_ARGUMENT(Integer, host_value, arguments->NativeArgAt(0)); | |
| 377 GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); | |
| 378 int64_t value = host_value.AsInt64Value(); | |
| 379 if (little_endian.value()) { | |
| 380 value = Utils::HostToLittleEndian64(value); | |
| 381 } else { | |
| 382 value = Utils::HostToBigEndian64(value); | |
| 383 } | |
| 384 return Integer::New(value); | |
| 385 } | |
| 386 | |
| 387 | |
| 388 DEFINE_NATIVE_ENTRY(ByteData_ToEndianUint64, 2) { | |
| 389 GET_NON_NULL_NATIVE_ARGUMENT(Integer, host_value, arguments->NativeArgAt(0)); | |
| 390 GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); | |
| 391 uint64_t value; | |
| 392 if (host_value.IsBigint()) { | |
| 393 const Bigint& bigint = Bigint::Cast(host_value); | |
| 394 ASSERT(BigintOperations::FitsIntoUint64(bigint)); | |
| 395 value = BigintOperations::AbsToUint64(bigint); | |
| 396 } else { | |
| 397 ASSERT(host_value.IsMint() || host_value.IsSmi()); | |
| 398 value = host_value.AsInt64Value(); | |
| 399 } | |
| 400 if (little_endian.value()) { | |
| 401 value = Utils::HostToLittleEndian64(value); | |
| 402 } else { | |
| 403 value = Utils::HostToBigEndian64(value); | |
| 404 } | |
| 405 if (value > static_cast<uint64_t>(Mint::kMaxValue)) { | |
| 406 return BigintOperations::NewFromUint64(value); | |
| 407 } else if (value > static_cast<uint64_t>(Smi::kMaxValue)) { | |
| 408 return Mint::New(value); | |
| 409 } | |
| 410 return Smi::New(value); | |
| 411 } | |
| 412 | |
| 413 | |
| 414 DEFINE_NATIVE_ENTRY(ByteData_ToEndianFloat32, 2) { | |
| 415 GET_NON_NULL_NATIVE_ARGUMENT(Double, host_value, arguments->NativeArgAt(0)); | |
| 416 GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); | |
| 417 float value = host_value.value(); | |
| 418 if (little_endian.value()) { | |
| 419 value = bit_cast<float>( | |
| 420 Utils::HostToLittleEndian32(bit_cast<uint32_t>(value))); | |
| 421 } else { | |
| 422 value = bit_cast<float>( | |
| 423 Utils::HostToBigEndian32(bit_cast<uint32_t>(value))); | |
| 424 } | |
| 425 return Double::New(value); | |
| 426 } | |
| 427 | |
| 428 | |
| 429 DEFINE_NATIVE_ENTRY(ByteData_ToEndianFloat64, 2) { | |
| 430 GET_NON_NULL_NATIVE_ARGUMENT(Double, host_value, arguments->NativeArgAt(0)); | |
| 431 GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); | |
| 432 double value = host_value.value(); | |
| 433 if (little_endian.value()) { | |
| 434 value = bit_cast<double>( | |
| 435 Utils::HostToLittleEndian64(bit_cast<uint64_t>(value))); | |
| 436 } else { | |
| 437 value = bit_cast<double>( | |
| 438 Utils::HostToBigEndian64(bit_cast<uint64_t>(value))); | |
| 439 } | |
| 440 return Double::New(value); | |
| 441 } | |
| 442 | |
| 443 } // namespace dart | |
| OLD | NEW |