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 |