| 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/bigint_operations.h" | 9 #include "vm/bigint_operations.h" |
| 10 #include "vm/exceptions.h" | 10 #include "vm/exceptions.h" |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 } | 31 } |
| 32 } | 32 } |
| 33 | 33 |
| 34 | 34 |
| 35 // Checks to see if a length will not result in an OOM error. | 35 // Checks to see if a length will not result in an OOM error. |
| 36 static void LengthCheck(intptr_t len, intptr_t max) { | 36 static void LengthCheck(intptr_t len, intptr_t max) { |
| 37 if (len < 0 || len > max) { | 37 if (len < 0 || len > max) { |
| 38 const String& error = String::Handle(String::NewFormatted( | 38 const String& error = String::Handle(String::NewFormatted( |
| 39 "Length (%" Pd ") of object must be in range [0..%" Pd "]", | 39 "Length (%" Pd ") of object must be in range [0..%" Pd "]", |
| 40 len, max)); | 40 len, max)); |
| 41 const Array& args = Array::Handle(Array::New(1)); | 41 Exceptions::ThrowArgumentError(error); |
| 42 args.SetAt(0, error); | |
| 43 Exceptions::ThrowByType(Exceptions::kArgument, args); | |
| 44 } | 42 } |
| 45 } | 43 } |
| 46 | 44 |
| 47 | 45 |
| 48 static void PeerFinalizer(Dart_WeakPersistentHandle handle, void* peer) { | 46 static void PeerFinalizer(Dart_WeakPersistentHandle handle, void* peer) { |
| 49 Dart_DeleteWeakPersistentHandle(handle); | 47 Dart_DeleteWeakPersistentHandle(handle); |
| 50 OS::AlignedFree(peer); | 48 OS::AlignedFree(peer); |
| 51 } | 49 } |
| 52 | 50 |
| 53 | 51 |
| 54 DEFINE_NATIVE_ENTRY(TypedData_length, 1) { | 52 DEFINE_NATIVE_ENTRY(TypedData_length, 1) { |
| 55 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); | 53 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); |
| 56 if (instance.IsTypedData()) { | 54 if (instance.IsTypedData()) { |
| 57 const TypedData& array = TypedData::Cast(instance); | 55 const TypedData& array = TypedData::Cast(instance); |
| 58 return Smi::New(array.Length()); | 56 return Smi::New(array.Length()); |
| 59 } | 57 } |
| 60 if (instance.IsExternalTypedData()) { | 58 if (instance.IsExternalTypedData()) { |
| 61 const ExternalTypedData& array = ExternalTypedData::Cast(instance); | 59 const ExternalTypedData& array = ExternalTypedData::Cast(instance); |
| 62 return Smi::New(array.Length()); | 60 return Smi::New(array.Length()); |
| 63 } | 61 } |
| 64 const String& error = String::Handle(String::NewFormatted( | 62 const String& error = String::Handle(String::NewFormatted( |
| 65 "Expected a TypedData object but found %s", instance.ToCString())); | 63 "Expected a TypedData object but found %s", instance.ToCString())); |
| 66 const Array& args = Array::Handle(Array::New(1)); | 64 Exceptions::ThrowArgumentError(error); |
| 67 args.SetAt(0, error); | |
| 68 Exceptions::ThrowByType(Exceptions::kArgument, args); | |
| 69 return Integer::null(); | 65 return Integer::null(); |
| 70 } | 66 } |
| 71 | 67 |
| 72 template <typename DstType, typename SrcType> | 68 template <typename DstType, typename SrcType> |
| 73 static RawBool* CopyData(const Instance& dst, const Instance& src, | 69 static RawBool* CopyData(const Instance& dst, const Instance& src, |
| 74 const Smi& dst_start, const Smi& src_start, | 70 const Smi& dst_start, const Smi& src_start, |
| 75 const Smi& length) { | 71 const Smi& length) { |
| 76 const DstType& dst_array = DstType::Cast(dst); | 72 const DstType& dst_array = DstType::Cast(dst); |
| 77 const SrcType& src_array = SrcType::Cast(src); | 73 const SrcType& src_array = SrcType::Cast(src); |
| 78 intptr_t element_size_in_bytes = dst_array.ElementSizeInBytes(); | 74 intptr_t element_size_in_bytes = dst_array.ElementSizeInBytes(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 100 DEFINE_NATIVE_ENTRY(TypedData_setRange, 5) { | 96 DEFINE_NATIVE_ENTRY(TypedData_setRange, 5) { |
| 101 GET_NON_NULL_NATIVE_ARGUMENT(Instance, dst, arguments->NativeArgAt(0)); | 97 GET_NON_NULL_NATIVE_ARGUMENT(Instance, dst, arguments->NativeArgAt(0)); |
| 102 GET_NON_NULL_NATIVE_ARGUMENT(Smi, dst_start, arguments->NativeArgAt(1)); | 98 GET_NON_NULL_NATIVE_ARGUMENT(Smi, dst_start, arguments->NativeArgAt(1)); |
| 103 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(2)); | 99 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(2)); |
| 104 GET_NON_NULL_NATIVE_ARGUMENT(Instance, src, arguments->NativeArgAt(3)); | 100 GET_NON_NULL_NATIVE_ARGUMENT(Instance, src, arguments->NativeArgAt(3)); |
| 105 GET_NON_NULL_NATIVE_ARGUMENT(Smi, src_start, arguments->NativeArgAt(4)); | 101 GET_NON_NULL_NATIVE_ARGUMENT(Smi, src_start, arguments->NativeArgAt(4)); |
| 106 | 102 |
| 107 if (length.Value() < 0) { | 103 if (length.Value() < 0) { |
| 108 const String& error = String::Handle(String::NewFormatted( | 104 const String& error = String::Handle(String::NewFormatted( |
| 109 "length (%" Pd ") must be non-negative", length.Value())); | 105 "length (%" Pd ") must be non-negative", length.Value())); |
| 110 const Array& args = Array::Handle(Array::New(1)); | 106 Exceptions::ThrowArgumentError(error); |
| 111 args.SetAt(0, error); | |
| 112 Exceptions::ThrowByType(Exceptions::kArgument, args); | |
| 113 } | 107 } |
| 114 if (dst.IsTypedData()) { | 108 if (dst.IsTypedData()) { |
| 115 if (src.IsTypedData()) { | 109 if (src.IsTypedData()) { |
| 116 return CopyData<TypedData, TypedData>( | 110 return CopyData<TypedData, TypedData>( |
| 117 dst, src, dst_start, src_start, length); | 111 dst, src, dst_start, src_start, length); |
| 118 } else if (src.IsExternalTypedData()) { | 112 } else if (src.IsExternalTypedData()) { |
| 119 return CopyData<TypedData, ExternalTypedData>( | 113 return CopyData<TypedData, ExternalTypedData>( |
| 120 dst, src, dst_start, src_start, length); | 114 dst, src, dst_start, src_start, length); |
| 121 } | 115 } |
| 122 } else if (dst.IsExternalTypedData()) { | 116 } else if (dst.IsExternalTypedData()) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 return object::New(array.getter(offsetInBytes.Value())); \ | 180 return object::New(array.getter(offsetInBytes.Value())); \ |
| 187 } \ | 181 } \ |
| 188 if (instance.IsExternalTypedData()) { \ | 182 if (instance.IsExternalTypedData()) { \ |
| 189 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ | 183 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ |
| 190 RangeCheck(offsetInBytes.Value(), access_size, \ | 184 RangeCheck(offsetInBytes.Value(), access_size, \ |
| 191 array.LengthInBytes(), access_size); \ | 185 array.LengthInBytes(), access_size); \ |
| 192 return object::New(array.getter(offsetInBytes.Value())); \ | 186 return object::New(array.getter(offsetInBytes.Value())); \ |
| 193 } \ | 187 } \ |
| 194 const String& error = String::Handle(String::NewFormatted( \ | 188 const String& error = String::Handle(String::NewFormatted( \ |
| 195 "Expected a TypedData object but found %s", instance.ToCString())); \ | 189 "Expected a TypedData object but found %s", instance.ToCString())); \ |
| 196 const Array& args = Array::Handle(Array::New(1)); \ | 190 Exceptions::ThrowArgumentError(error); \ |
| 197 args.SetAt(0, error); \ | |
| 198 Exceptions::ThrowByType(Exceptions::kArgument, args); \ | |
| 199 return object::null(); \ | 191 return object::null(); \ |
| 200 } \ | 192 } \ |
| 201 | 193 |
| 202 | 194 |
| 203 #define TYPED_DATA_SETTER(setter, object, get_object_value, access_size) \ | 195 #define TYPED_DATA_SETTER(setter, object, get_object_value, access_size) \ |
| 204 DEFINE_NATIVE_ENTRY(TypedData_##setter, 3) { \ | 196 DEFINE_NATIVE_ENTRY(TypedData_##setter, 3) { \ |
| 205 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ | 197 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ |
| 206 GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ | 198 GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ |
| 207 GET_NON_NULL_NATIVE_ARGUMENT(object, value, arguments->NativeArgAt(2)); \ | 199 GET_NON_NULL_NATIVE_ARGUMENT(object, value, arguments->NativeArgAt(2)); \ |
| 208 if (instance.IsTypedData()) { \ | 200 if (instance.IsTypedData()) { \ |
| 209 const TypedData& array = TypedData::Cast(instance); \ | 201 const TypedData& array = TypedData::Cast(instance); \ |
| 210 RangeCheck(offsetInBytes.Value(), access_size, \ | 202 RangeCheck(offsetInBytes.Value(), access_size, \ |
| 211 array.LengthInBytes(), access_size); \ | 203 array.LengthInBytes(), access_size); \ |
| 212 array.setter(offsetInBytes.Value(), value.get_object_value()); \ | 204 array.setter(offsetInBytes.Value(), value.get_object_value()); \ |
| 213 } else if (instance.IsExternalTypedData()) { \ | 205 } else if (instance.IsExternalTypedData()) { \ |
| 214 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ | 206 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ |
| 215 RangeCheck(offsetInBytes.Value(), access_size, \ | 207 RangeCheck(offsetInBytes.Value(), access_size, \ |
| 216 array.LengthInBytes(), access_size); \ | 208 array.LengthInBytes(), access_size); \ |
| 217 array.setter(offsetInBytes.Value(), value.get_object_value()); \ | 209 array.setter(offsetInBytes.Value(), value.get_object_value()); \ |
| 218 } else { \ | 210 } else { \ |
| 219 const String& error = String::Handle(String::NewFormatted( \ | 211 const String& error = String::Handle(String::NewFormatted( \ |
| 220 "Expected a TypedData object but found %s", instance.ToCString())); \ | 212 "Expected a TypedData object but found %s", instance.ToCString())); \ |
| 221 const Array& args = Array::Handle(Array::New(1)); \ | 213 Exceptions::ThrowArgumentError(error); \ |
| 222 args.SetAt(0, error); \ | |
| 223 Exceptions::ThrowByType(Exceptions::kArgument, args); \ | |
| 224 } \ | 214 } \ |
| 225 return Object::null(); \ | 215 return Object::null(); \ |
| 226 } | 216 } |
| 227 | 217 |
| 228 | 218 |
| 229 #define TYPED_DATA_UINT64_GETTER(getter, object) \ | 219 #define TYPED_DATA_UINT64_GETTER(getter, object) \ |
| 230 DEFINE_NATIVE_ENTRY(TypedData_##getter, 2) { \ | 220 DEFINE_NATIVE_ENTRY(TypedData_##getter, 2) { \ |
| 231 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ | 221 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ |
| 232 GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ | 222 GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ |
| 233 uint64_t value = 0; \ | 223 uint64_t value = 0; \ |
| 234 if (instance.IsTypedData()) { \ | 224 if (instance.IsTypedData()) { \ |
| 235 const TypedData& array = TypedData::Cast(instance); \ | 225 const TypedData& array = TypedData::Cast(instance); \ |
| 236 RangeCheck(offsetInBytes.Value(), 8, array.LengthInBytes(), 8); \ | 226 RangeCheck(offsetInBytes.Value(), 8, array.LengthInBytes(), 8); \ |
| 237 value = array.getter(offsetInBytes.Value()); \ | 227 value = array.getter(offsetInBytes.Value()); \ |
| 238 } else if (instance.IsExternalTypedData()) { \ | 228 } else if (instance.IsExternalTypedData()) { \ |
| 239 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ | 229 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ |
| 240 RangeCheck(offsetInBytes.Value(), 8, array.LengthInBytes(), 8); \ | 230 RangeCheck(offsetInBytes.Value(), 8, array.LengthInBytes(), 8); \ |
| 241 value = array.getter(offsetInBytes.Value()); \ | 231 value = array.getter(offsetInBytes.Value()); \ |
| 242 } else { \ | 232 } else { \ |
| 243 const String& error = String::Handle(String::NewFormatted( \ | 233 const String& error = String::Handle(String::NewFormatted( \ |
| 244 "Expected a TypedData object but found %s", instance.ToCString())); \ | 234 "Expected a TypedData object but found %s", instance.ToCString())); \ |
| 245 const Array& args = Array::Handle(Array::New(1)); \ | 235 Exceptions::ThrowArgumentError(error); \ |
| 246 args.SetAt(0, error); \ | |
| 247 Exceptions::ThrowByType(Exceptions::kArgument, args); \ | |
| 248 } \ | 236 } \ |
| 249 return Integer::NewFromUint64(value); \ | 237 return Integer::NewFromUint64(value); \ |
| 250 } \ | 238 } \ |
| 251 | 239 |
| 252 | 240 |
| 253 // TODO(asiva): Consider truncating the bigint value if it does not fit into | 241 // TODO(asiva): Consider truncating the bigint value if it does not fit into |
| 254 // a uint64_t value (see ASSERT(BigintOperations::FitsIntoUint64(bigint))). | 242 // a uint64_t value (see ASSERT(BigintOperations::FitsIntoUint64(bigint))). |
| 255 #define TYPED_DATA_UINT64_SETTER(setter, object) \ | 243 #define TYPED_DATA_UINT64_SETTER(setter, object) \ |
| 256 DEFINE_NATIVE_ENTRY(TypedData_##setter, 3) { \ | 244 DEFINE_NATIVE_ENTRY(TypedData_##setter, 3) { \ |
| 257 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ | 245 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ |
| (...skipping 12 matching lines...) Expand all Loading... |
| 270 const TypedData& array = TypedData::Cast(instance); \ | 258 const TypedData& array = TypedData::Cast(instance); \ |
| 271 RangeCheck(offsetInBytes.Value(), 8, array.LengthInBytes(), 8); \ | 259 RangeCheck(offsetInBytes.Value(), 8, array.LengthInBytes(), 8); \ |
| 272 array.setter(offsetInBytes.Value(), object_value); \ | 260 array.setter(offsetInBytes.Value(), object_value); \ |
| 273 } else if (instance.IsExternalTypedData()) { \ | 261 } else if (instance.IsExternalTypedData()) { \ |
| 274 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ | 262 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ |
| 275 RangeCheck(offsetInBytes.Value(), 8, array.LengthInBytes(), 8); \ | 263 RangeCheck(offsetInBytes.Value(), 8, array.LengthInBytes(), 8); \ |
| 276 array.setter(offsetInBytes.Value(), object_value); \ | 264 array.setter(offsetInBytes.Value(), object_value); \ |
| 277 } else { \ | 265 } else { \ |
| 278 const String& error = String::Handle(String::NewFormatted( \ | 266 const String& error = String::Handle(String::NewFormatted( \ |
| 279 "Expected a TypedData object but found %s", instance.ToCString())); \ | 267 "Expected a TypedData object but found %s", instance.ToCString())); \ |
| 280 const Array& args = Array::Handle(Array::New(1)); \ | 268 Exceptions::ThrowArgumentError(error); \ |
| 281 args.SetAt(0, error); \ | |
| 282 Exceptions::ThrowByType(Exceptions::kArgument, args); \ | |
| 283 } \ | 269 } \ |
| 284 return Object::null(); \ | 270 return Object::null(); \ |
| 285 } | 271 } |
| 286 | 272 |
| 287 | 273 |
| 288 #define TYPED_DATA_NATIVES(getter, \ | 274 #define TYPED_DATA_NATIVES(getter, \ |
| 289 setter, \ | 275 setter, \ |
| 290 object, \ | 276 object, \ |
| 291 get_object_value, \ | 277 get_object_value, \ |
| 292 access_size) \ | 278 access_size) \ |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 value = bit_cast<double>( | 407 value = bit_cast<double>( |
| 422 Utils::HostToLittleEndian64(bit_cast<uint64_t>(value))); | 408 Utils::HostToLittleEndian64(bit_cast<uint64_t>(value))); |
| 423 } else { | 409 } else { |
| 424 value = bit_cast<double>( | 410 value = bit_cast<double>( |
| 425 Utils::HostToBigEndian64(bit_cast<uint64_t>(value))); | 411 Utils::HostToBigEndian64(bit_cast<uint64_t>(value))); |
| 426 } | 412 } |
| 427 return Double::New(value); | 413 return Double::New(value); |
| 428 } | 414 } |
| 429 | 415 |
| 430 } // namespace dart | 416 } // namespace dart |
| OLD | NEW |