| 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 const String& error = String::Handle(String::NewFormatted( | 64 const String& error = String::Handle(String::NewFormatted( |
| 65 "Expected a TypedData object but found %s", instance.ToCString())); | 65 "Expected a TypedData object but found %s", instance.ToCString())); |
| 66 Exceptions::ThrowArgumentError(error); | 66 Exceptions::ThrowArgumentError(error); |
| 67 return Integer::null(); | 67 return Integer::null(); |
| 68 } | 68 } |
| 69 | 69 |
| 70 | 70 |
| 71 template <typename DstType, typename SrcType> | 71 template <typename DstType, typename SrcType> |
| 72 static RawBool* CopyData(const Instance& dst, const Instance& src, | 72 static RawBool* CopyData(const Instance& dst, const Instance& src, |
| 73 const Smi& dst_start, const Smi& src_start, | 73 const Smi& dst_start, const Smi& src_start, |
| 74 const Smi& length) { | 74 const Smi& length, |
| 75 bool clamped) { |
| 75 const DstType& dst_array = DstType::Cast(dst); | 76 const DstType& dst_array = DstType::Cast(dst); |
| 76 const SrcType& src_array = SrcType::Cast(src); | 77 const SrcType& src_array = SrcType::Cast(src); |
| 77 const intptr_t dst_offset_in_bytes = dst_start.Value(); | 78 const intptr_t dst_offset_in_bytes = dst_start.Value(); |
| 78 const intptr_t src_offset_in_bytes = src_start.Value(); | 79 const intptr_t src_offset_in_bytes = src_start.Value(); |
| 79 const intptr_t length_in_bytes = length.Value(); | 80 const intptr_t length_in_bytes = length.Value(); |
| 80 if (dst_array.ElementType() != src_array.ElementType()) { | |
| 81 return Bool::False().raw(); | |
| 82 } | |
| 83 ASSERT(Utils::RangeCheck( | 81 ASSERT(Utils::RangeCheck( |
| 84 src_offset_in_bytes, length_in_bytes, src_array.LengthInBytes())); | 82 src_offset_in_bytes, length_in_bytes, src_array.LengthInBytes())); |
| 85 ASSERT(Utils::RangeCheck( | 83 ASSERT(Utils::RangeCheck( |
| 86 dst_offset_in_bytes, length_in_bytes, dst_array.LengthInBytes())); | 84 dst_offset_in_bytes, length_in_bytes, dst_array.LengthInBytes())); |
| 87 TypedData::Copy<DstType, SrcType>(dst_array, dst_offset_in_bytes, | 85 if (clamped) { |
| 88 src_array, src_offset_in_bytes, | 86 TypedData::ClampedCopy<DstType, SrcType>(dst_array, dst_offset_in_bytes, |
| 89 length_in_bytes); | 87 src_array, src_offset_in_bytes, |
| 88 length_in_bytes); |
| 89 } else { |
| 90 TypedData::Copy<DstType, SrcType>(dst_array, dst_offset_in_bytes, |
| 91 src_array, src_offset_in_bytes, |
| 92 length_in_bytes); |
| 93 } |
| 90 return Bool::True().raw(); | 94 return Bool::True().raw(); |
| 91 } | 95 } |
| 92 | 96 |
| 93 DEFINE_NATIVE_ENTRY(TypedData_setRange, 5) { | 97 |
| 94 GET_NON_NULL_NATIVE_ARGUMENT(Instance, dst, arguments->NativeArgAt(0)); | 98 static bool IsClamped(intptr_t cid) { |
| 95 GET_NON_NULL_NATIVE_ARGUMENT(Smi, dst_start, arguments->NativeArgAt(1)); | 99 switch (cid) { |
| 96 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(2)); | 100 case kTypedDataUint8ClampedArrayCid: |
| 97 GET_NON_NULL_NATIVE_ARGUMENT(Instance, src, arguments->NativeArgAt(3)); | 101 case kExternalTypedDataUint8ClampedArrayCid: |
| 98 GET_NON_NULL_NATIVE_ARGUMENT(Smi, src_start, arguments->NativeArgAt(4)); | 102 case kTypedDataUint8ClampedArrayViewCid: |
| 103 return true; |
| 104 default: |
| 105 return false; |
| 106 } |
| 107 } |
| 108 |
| 109 |
| 110 static bool IsUint8(intptr_t cid) { |
| 111 switch (cid) { |
| 112 case kTypedDataUint8ClampedArrayCid: |
| 113 case kExternalTypedDataUint8ClampedArrayCid: |
| 114 case kTypedDataUint8ClampedArrayViewCid: |
| 115 case kTypedDataUint8ArrayCid: |
| 116 case kExternalTypedDataUint8ArrayCid: |
| 117 case kTypedDataUint8ArrayViewCid: |
| 118 return true; |
| 119 default: |
| 120 return false; |
| 121 } |
| 122 } |
| 123 |
| 124 |
| 125 DEFINE_NATIVE_ENTRY(TypedData_setRange, 7) { |
| 126 const Instance& dst = Instance::CheckedHandle(arguments->NativeArgAt(0)); |
| 127 const Smi& dst_start = Smi::CheckedHandle(arguments->NativeArgAt(1)); |
| 128 const Smi& length = Smi::CheckedHandle(arguments->NativeArgAt(2)); |
| 129 const Instance& src = Instance::CheckedHandle(arguments->NativeArgAt(3)); |
| 130 const Smi& src_start = Smi::CheckedHandle(arguments->NativeArgAt(4)); |
| 131 const Smi& to_cid_smi = Smi::CheckedHandle(arguments->NativeArgAt(5)); |
| 132 const Smi& from_cid_smi = Smi::CheckedHandle(arguments->NativeArgAt(6)); |
| 99 | 133 |
| 100 if (length.Value() < 0) { | 134 if (length.Value() < 0) { |
| 101 const String& error = String::Handle(String::NewFormatted( | 135 const String& error = String::Handle(String::NewFormatted( |
| 102 "length (%" Pd ") must be non-negative", length.Value())); | 136 "length (%" Pd ") must be non-negative", length.Value())); |
| 103 Exceptions::ThrowArgumentError(error); | 137 Exceptions::ThrowArgumentError(error); |
| 104 } | 138 } |
| 139 const intptr_t to_cid = to_cid_smi.Value(); |
| 140 const intptr_t from_cid = from_cid_smi.Value(); |
| 141 |
| 142 const bool needs_clamping = IsClamped(to_cid) && !IsUint8(from_cid); |
| 105 if (dst.IsTypedData()) { | 143 if (dst.IsTypedData()) { |
| 106 if (src.IsTypedData()) { | 144 if (src.IsTypedData()) { |
| 107 return CopyData<TypedData, TypedData>( | 145 return CopyData<TypedData, TypedData>( |
| 108 dst, src, dst_start, src_start, length); | 146 dst, src, dst_start, src_start, length, needs_clamping); |
| 109 } else if (src.IsExternalTypedData()) { | 147 } else if (src.IsExternalTypedData()) { |
| 110 return CopyData<TypedData, ExternalTypedData>( | 148 return CopyData<TypedData, ExternalTypedData>( |
| 111 dst, src, dst_start, src_start, length); | 149 dst, src, dst_start, src_start, length, needs_clamping); |
| 112 } | 150 } |
| 113 } else if (dst.IsExternalTypedData()) { | 151 } else if (dst.IsExternalTypedData()) { |
| 114 if (src.IsTypedData()) { | 152 if (src.IsTypedData()) { |
| 115 return CopyData<ExternalTypedData, TypedData>( | 153 return CopyData<ExternalTypedData, TypedData>( |
| 116 dst, src, dst_start, src_start, length); | 154 dst, src, dst_start, src_start, length, needs_clamping); |
| 117 } else if (src.IsExternalTypedData()) { | 155 } else if (src.IsExternalTypedData()) { |
| 118 return CopyData<ExternalTypedData, ExternalTypedData>( | 156 return CopyData<ExternalTypedData, ExternalTypedData>( |
| 119 dst, src, dst_start, src_start, length); | 157 dst, src, dst_start, src_start, length, needs_clamping); |
| 120 } | 158 } |
| 121 } | 159 } |
| 122 UNREACHABLE(); | 160 UNREACHABLE(); |
| 123 return Bool::False().raw(); | 161 return Bool::False().raw(); |
| 124 } | 162 } |
| 125 | 163 |
| 164 |
| 126 // We check the length parameter against a possible maximum length for the | 165 // We check the length parameter against a possible maximum length for the |
| 127 // array based on available physical addressable memory on the system. The | 166 // array based on available physical addressable memory on the system. The |
| 128 // maximum possible length is a scaled value of kSmiMax which is set up based | 167 // maximum possible length is a scaled value of kSmiMax which is set up based |
| 129 // on whether the underlying architecture is 32-bit or 64-bit. | 168 // on whether the underlying architecture is 32-bit or 64-bit. |
| 130 #define TYPED_DATA_NEW(name) \ | 169 #define TYPED_DATA_NEW(name) \ |
| 131 DEFINE_NATIVE_ENTRY(TypedData_##name##_new, 1) { \ | 170 DEFINE_NATIVE_ENTRY(TypedData_##name##_new, 1) { \ |
| 132 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0)); \ | 171 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0)); \ |
| 133 intptr_t cid = kTypedData##name##Cid; \ | 172 intptr_t cid = kTypedData##name##Cid; \ |
| 134 intptr_t len = length.Value(); \ | 173 intptr_t len = length.Value(); \ |
| 135 intptr_t max = TypedData::MaxElements(cid); \ | 174 intptr_t max = TypedData::MaxElements(cid); \ |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 value = bit_cast<double>( | 455 value = bit_cast<double>( |
| 417 Utils::HostToLittleEndian64(bit_cast<uint64_t>(value))); | 456 Utils::HostToLittleEndian64(bit_cast<uint64_t>(value))); |
| 418 } else { | 457 } else { |
| 419 value = bit_cast<double>( | 458 value = bit_cast<double>( |
| 420 Utils::HostToBigEndian64(bit_cast<uint64_t>(value))); | 459 Utils::HostToBigEndian64(bit_cast<uint64_t>(value))); |
| 421 } | 460 } |
| 422 return Double::New(value); | 461 return Double::New(value); |
| 423 } | 462 } |
| 424 | 463 |
| 425 } // namespace dart | 464 } // namespace dart |
| OLD | NEW |