Index: runtime/lib/typeddata.cc |
diff --git a/runtime/lib/typeddata.cc b/runtime/lib/typeddata.cc |
deleted file mode 100644 |
index 4a47d7123d6bc348aea504ef925ee2e9e594fd31..0000000000000000000000000000000000000000 |
--- a/runtime/lib/typeddata.cc |
+++ /dev/null |
@@ -1,443 +0,0 @@ |
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-#include "vm/bootstrap_natives.h" |
- |
-#include "include/dart_api.h" |
- |
-#include "vm/bigint_operations.h" |
-#include "vm/exceptions.h" |
-#include "vm/native_entry.h" |
-#include "vm/object.h" |
- |
-namespace dart { |
- |
-// TypedData. |
- |
-// Checks to see if offset_in_bytes is in the range. |
-static bool RangeCheck(intptr_t offset_in_bytes, intptr_t length_in_bytes) { |
- return ((offset_in_bytes >= 0) && |
- (length_in_bytes > 0) && |
- (offset_in_bytes < length_in_bytes)); |
-} |
- |
- |
-// Checks to see if offsetInBytes + num_bytes is in the range. |
-static void SetRangeCheck(intptr_t offset_in_bytes, |
- intptr_t num_bytes, |
- intptr_t length_in_bytes, |
- intptr_t element_size_in_bytes) { |
- if (!Utils::RangeCheck(offset_in_bytes, num_bytes, length_in_bytes)) { |
- const String& error = String::Handle(String::NewFormatted( |
- "index (%"Pd") must be in the range [0..%"Pd")", |
- (offset_in_bytes / element_size_in_bytes), |
- (length_in_bytes / element_size_in_bytes))); |
- const Array& args = Array::Handle(Array::New(1)); |
- args.SetAt(0, error); |
- Exceptions::ThrowByType(Exceptions::kRange, args); |
- } |
-} |
- |
- |
-// Checks to see if a length will not result in an OOM error. |
-static void LengthCheck(intptr_t len, intptr_t max) { |
- ASSERT(len >= 0); |
- if (len > max) { |
- const String& error = String::Handle(String::NewFormatted( |
- "insufficient memory to allocate a TypedData object of length (%"Pd")", |
- len)); |
- const Array& args = Array::Handle(Array::New(1)); |
- args.SetAt(0, error); |
- Exceptions::ThrowByType(Exceptions::kOutOfMemory, args); |
- } |
-} |
- |
- |
-static void PeerFinalizer(Dart_Handle handle, void* peer) { |
- Dart_DeletePersistentHandle(handle); |
- OS::AlignedFree(peer); |
-} |
- |
- |
-DEFINE_NATIVE_ENTRY(TypedData_length, 1) { |
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); |
- if (instance.IsTypedData()) { |
- const TypedData& array = TypedData::Cast(instance); |
- return Smi::New(array.Length()); |
- } |
- if (instance.IsExternalTypedData()) { |
- const ExternalTypedData& array = ExternalTypedData::Cast(instance); |
- return Smi::New(array.Length()); |
- } |
- const String& error = String::Handle(String::NewFormatted( |
- "Expected a TypedData object but found %s", instance.ToCString())); |
- const Array& args = Array::Handle(Array::New(1)); |
- args.SetAt(0, error); |
- Exceptions::ThrowByType(Exceptions::kArgument, args); |
- return Integer::null(); |
-} |
- |
-template <typename DstType, typename SrcType> |
-static RawBool* CopyData(const Instance& dst, const Instance& src, |
- const Smi& dst_start, const Smi& src_start, |
- const Smi& length) { |
- const DstType& dst_array = DstType::Cast(dst); |
- const SrcType& src_array = SrcType::Cast(src); |
- intptr_t element_size_in_bytes = dst_array.ElementSizeInBytes(); |
- intptr_t dst_offset_in_bytes = dst_start.Value() * element_size_in_bytes; |
- intptr_t src_offset_in_bytes = src_start.Value() * element_size_in_bytes; |
- intptr_t length_in_bytes = length.Value() * element_size_in_bytes; |
- if (dst_array.ElementType() != src_array.ElementType()) { |
- return Bool::False().raw(); |
- } |
- SetRangeCheck(src_offset_in_bytes, |
- length_in_bytes, |
- src_array.LengthInBytes(), |
- element_size_in_bytes); |
- SetRangeCheck(dst_offset_in_bytes, |
- length_in_bytes, |
- dst_array.LengthInBytes(), |
- element_size_in_bytes); |
- TypedData::Copy<DstType, SrcType>(dst_array, dst_offset_in_bytes, |
- src_array, src_offset_in_bytes, |
- length_in_bytes); |
- return Bool::True().raw(); |
-} |
- |
-DEFINE_NATIVE_ENTRY(TypedData_setRange, 5) { |
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, dst, arguments->NativeArgAt(0)); |
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, dst_start, arguments->NativeArgAt(1)); |
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(2)); |
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, src, arguments->NativeArgAt(3)); |
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, src_start, arguments->NativeArgAt(4)); |
- |
- if (length.Value() < 0) { |
- const String& error = String::Handle(String::NewFormatted( |
- "length (%"Pd") must be non-negative", length.Value())); |
- const Array& args = Array::Handle(Array::New(1)); |
- args.SetAt(0, error); |
- Exceptions::ThrowByType(Exceptions::kArgument, args); |
- } |
- if (dst.IsTypedData()) { |
- if (src.IsTypedData()) { |
- return CopyData<TypedData, TypedData>( |
- dst, src, dst_start, src_start, length); |
- } else if (src.IsExternalTypedData()) { |
- return CopyData<TypedData, ExternalTypedData>( |
- dst, src, dst_start, src_start, length); |
- } |
- } else if (dst.IsExternalTypedData()) { |
- if (src.IsTypedData()) { |
- return CopyData<ExternalTypedData, TypedData>( |
- dst, src, dst_start, src_start, length); |
- } else if (src.IsExternalTypedData()) { |
- return CopyData<ExternalTypedData, ExternalTypedData>( |
- dst, src, dst_start, src_start, length); |
- } |
- } |
- return Bool::False().raw(); |
-} |
- |
- |
-// We check the length parameter against a possible maximum length for the |
-// array based on available physical addressable memory on the system. The |
-// maximum possible length is a scaled value of kSmiMax which is set up based |
-// on whether the underlying architecture is 32-bit or 64-bit. |
-#define TYPED_DATA_NEW(name) \ |
-DEFINE_NATIVE_ENTRY(TypedData_##name##_new, 1) { \ |
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0)); \ |
- intptr_t cid = kTypedData##name##Cid; \ |
- intptr_t len = length.Value(); \ |
- intptr_t max = TypedData::MaxElements(cid); \ |
- LengthCheck(len, max); \ |
- return TypedData::New(cid, len); \ |
-} \ |
- |
- |
-// We check the length parameter against a possible maximum length for the |
-// array based on available physical addressable memory on the system. The |
-// maximum possible length is a scaled value of kSmiMax which is set up based |
-// on whether the underlying architecture is 32-bit or 64-bit. |
-#define EXT_TYPED_DATA_NEW(name) \ |
-DEFINE_NATIVE_ENTRY(ExternalTypedData_##name##_new, 1) { \ |
- const int kAlignment = 16; \ |
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0)); \ |
- intptr_t cid = kExternalTypedData##name##Cid; \ |
- intptr_t len = length.Value(); \ |
- intptr_t max = ExternalTypedData::MaxElements(cid); \ |
- LengthCheck(len, max); \ |
- intptr_t len_bytes = len * ExternalTypedData::ElementSizeInBytes(cid); \ |
- uint8_t* data = OS::AllocateAlignedArray<uint8_t>(len_bytes, kAlignment); \ |
- const ExternalTypedData& obj = \ |
- ExternalTypedData::Handle(ExternalTypedData::New(cid, data, len)); \ |
- obj.AddFinalizer(data, PeerFinalizer); \ |
- return obj.raw(); \ |
-} \ |
- |
- |
-#define TYPED_DATA_NEW_NATIVE(name) \ |
- TYPED_DATA_NEW(name) \ |
- EXT_TYPED_DATA_NEW(name) \ |
- |
- |
-CLASS_LIST_TYPED_DATA(TYPED_DATA_NEW_NATIVE) |
- |
-#define TYPED_DATA_GETTER(getter, object) \ |
-DEFINE_NATIVE_ENTRY(TypedData_##getter, 2) { \ |
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ |
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ |
- if (instance.IsTypedData()) { \ |
- const TypedData& array = TypedData::Cast(instance); \ |
- ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ |
- return object::New(array.getter(offsetInBytes.Value())); \ |
- } \ |
- if (instance.IsExternalTypedData()) { \ |
- const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ |
- ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ |
- return object::New(array.getter(offsetInBytes.Value())); \ |
- } \ |
- const String& error = String::Handle(String::NewFormatted( \ |
- "Expected a TypedData object but found %s", instance.ToCString())); \ |
- const Array& args = Array::Handle(Array::New(1)); \ |
- args.SetAt(0, error); \ |
- Exceptions::ThrowByType(Exceptions::kArgument, args); \ |
- return object::null(); \ |
-} \ |
- |
- |
-#define TYPED_DATA_SETTER(setter, object, get_object_value) \ |
-DEFINE_NATIVE_ENTRY(TypedData_##setter, 3) { \ |
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ |
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ |
- GET_NON_NULL_NATIVE_ARGUMENT(object, value, arguments->NativeArgAt(2)); \ |
- if (instance.IsTypedData()) { \ |
- const TypedData& array = TypedData::Cast(instance); \ |
- ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ |
- array.setter(offsetInBytes.Value(), value.get_object_value()); \ |
- } else if (instance.IsExternalTypedData()) { \ |
- const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ |
- ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ |
- array.setter(offsetInBytes.Value(), value.get_object_value()); \ |
- } else { \ |
- const String& error = String::Handle(String::NewFormatted( \ |
- "Expected a TypedData object but found %s", instance.ToCString())); \ |
- const Array& args = Array::Handle(Array::New(1)); \ |
- args.SetAt(0, error); \ |
- Exceptions::ThrowByType(Exceptions::kArgument, args); \ |
- } \ |
- return Object::null(); \ |
-} |
- |
- |
-#define TYPED_DATA_UINT64_GETTER(getter, object) \ |
-DEFINE_NATIVE_ENTRY(TypedData_##getter, 2) { \ |
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ |
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ |
- uint64_t value = 0; \ |
- if (instance.IsTypedData()) { \ |
- const TypedData& array = TypedData::Cast(instance); \ |
- ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ |
- value = array.getter(offsetInBytes.Value()); \ |
- } else if (instance.IsExternalTypedData()) { \ |
- const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ |
- ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ |
- value = array.getter(offsetInBytes.Value()); \ |
- } else { \ |
- const String& error = String::Handle(String::NewFormatted( \ |
- "Expected a TypedData object but found %s", instance.ToCString())); \ |
- const Array& args = Array::Handle(Array::New(1)); \ |
- args.SetAt(0, error); \ |
- Exceptions::ThrowByType(Exceptions::kArgument, args); \ |
- } \ |
- Integer& result = Integer::Handle(); \ |
- if (value > static_cast<uint64_t>(Mint::kMaxValue)) { \ |
- result = BigintOperations::NewFromUint64(value); \ |
- } else if (value > static_cast<uint64_t>(Smi::kMaxValue)) { \ |
- result = Mint::New(value); \ |
- } else { \ |
- result = Smi::New(value); \ |
- } \ |
- return result.raw(); \ |
-} \ |
- |
- |
-// TODO(asiva): Consider truncating the bigint value if it does not fit into |
-// a uint64_t value (see ASSERT(BigintOperations::FitsIntoUint64(bigint))). |
-#define TYPED_DATA_UINT64_SETTER(setter, object) \ |
-DEFINE_NATIVE_ENTRY(TypedData_##setter, 3) { \ |
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \ |
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \ |
- GET_NON_NULL_NATIVE_ARGUMENT(object, value, arguments->NativeArgAt(2)); \ |
- uint64_t object_value; \ |
- if (value.IsBigint()) { \ |
- const Bigint& bigint = Bigint::Cast(value); \ |
- ASSERT(BigintOperations::FitsIntoUint64(bigint)); \ |
- object_value = BigintOperations::AbsToUint64(bigint); \ |
- } else { \ |
- ASSERT(value.IsMint() || value.IsSmi()); \ |
- object_value = value.AsInt64Value(); \ |
- } \ |
- if (instance.IsTypedData()) { \ |
- const TypedData& array = TypedData::Cast(instance); \ |
- ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ |
- array.setter(offsetInBytes.Value(), object_value); \ |
- } else if (instance.IsExternalTypedData()) { \ |
- const ExternalTypedData& array = ExternalTypedData::Cast(instance); \ |
- ASSERT(RangeCheck(offsetInBytes.Value(), array.LengthInBytes())); \ |
- array.setter(offsetInBytes.Value(), object_value); \ |
- } else { \ |
- const String& error = String::Handle(String::NewFormatted( \ |
- "Expected a TypedData object but found %s", instance.ToCString())); \ |
- const Array& args = Array::Handle(Array::New(1)); \ |
- args.SetAt(0, error); \ |
- Exceptions::ThrowByType(Exceptions::kArgument, args); \ |
- } \ |
- return Object::null(); \ |
-} |
- |
- |
-#define TYPED_DATA_NATIVES(getter, setter, object, get_object_value) \ |
- TYPED_DATA_GETTER(getter, object) \ |
- TYPED_DATA_SETTER(setter, object, get_object_value) \ |
- |
- |
-#define TYPED_DATA_UINT64_NATIVES(getter, setter, object) \ |
- TYPED_DATA_UINT64_GETTER(getter, object) \ |
- TYPED_DATA_UINT64_SETTER(setter, object) \ |
- |
- |
-TYPED_DATA_NATIVES(GetInt8, SetInt8, Smi, Value) |
-TYPED_DATA_NATIVES(GetUint8, SetUint8, Smi, Value) |
-TYPED_DATA_NATIVES(GetInt16, SetInt16, Smi, Value) |
-TYPED_DATA_NATIVES(GetUint16, SetUint16, Smi, Value) |
-TYPED_DATA_NATIVES(GetInt32, SetInt32, Integer, AsInt64Value) |
-TYPED_DATA_NATIVES(GetUint32, SetUint32, Integer, AsInt64Value) |
-TYPED_DATA_NATIVES(GetInt64, SetInt64, Integer, AsInt64Value) |
-TYPED_DATA_UINT64_NATIVES(GetUint64, SetUint64, Integer) |
-TYPED_DATA_NATIVES(GetFloat32, SetFloat32, Double, value) |
-TYPED_DATA_NATIVES(GetFloat64, SetFloat64, Double, value) |
-TYPED_DATA_NATIVES(GetFloat32x4, SetFloat32x4, Float32x4, value) |
- |
- |
-DEFINE_NATIVE_ENTRY(ByteData_ToEndianInt16, 2) { |
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, host_value, arguments->NativeArgAt(0)); |
- GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); |
- int16_t value = host_value.Value(); |
- if (little_endian.value()) { |
- value = Utils::HostToLittleEndian16(value); |
- } else { |
- value = Utils::HostToBigEndian16(value); |
- } |
- return Smi::New(value); |
-} |
- |
- |
-DEFINE_NATIVE_ENTRY(ByteData_ToEndianUint16, 2) { |
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, host_value, arguments->NativeArgAt(0)); |
- GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); |
- uint16_t value = host_value.Value(); |
- if (little_endian.value()) { |
- return Smi::New(Utils::HostToLittleEndian16(value)); |
- } |
- return Smi::New(Utils::HostToBigEndian16(value)); |
-} |
- |
- |
-DEFINE_NATIVE_ENTRY(ByteData_ToEndianInt32, 2) { |
- GET_NON_NULL_NATIVE_ARGUMENT(Integer, host_value, arguments->NativeArgAt(0)); |
- GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); |
- ASSERT(host_value.AsInt64Value() <= kMaxInt32); |
- int32_t value = host_value.AsInt64Value(); |
- if (little_endian.value()) { |
- value = Utils::HostToLittleEndian32(value); |
- } else { |
- value = Utils::HostToBigEndian32(value); |
- } |
- return Integer::New(value); |
-} |
- |
- |
-DEFINE_NATIVE_ENTRY(ByteData_ToEndianUint32, 2) { |
- GET_NON_NULL_NATIVE_ARGUMENT(Integer, host_value, arguments->NativeArgAt(0)); |
- GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); |
- ASSERT(host_value.AsInt64Value() <= kMaxUint32); |
- uint32_t value = host_value.AsInt64Value(); |
- if (little_endian.value()) { |
- value = Utils::HostToLittleEndian32(value); |
- } else { |
- value = Utils::HostToBigEndian32(value); |
- } |
- return Integer::New(value); |
-} |
- |
- |
-DEFINE_NATIVE_ENTRY(ByteData_ToEndianInt64, 2) { |
- GET_NON_NULL_NATIVE_ARGUMENT(Integer, host_value, arguments->NativeArgAt(0)); |
- GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); |
- int64_t value = host_value.AsInt64Value(); |
- if (little_endian.value()) { |
- value = Utils::HostToLittleEndian64(value); |
- } else { |
- value = Utils::HostToBigEndian64(value); |
- } |
- return Integer::New(value); |
-} |
- |
- |
-DEFINE_NATIVE_ENTRY(ByteData_ToEndianUint64, 2) { |
- GET_NON_NULL_NATIVE_ARGUMENT(Integer, host_value, arguments->NativeArgAt(0)); |
- GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); |
- uint64_t value; |
- if (host_value.IsBigint()) { |
- const Bigint& bigint = Bigint::Cast(host_value); |
- ASSERT(BigintOperations::FitsIntoUint64(bigint)); |
- value = BigintOperations::AbsToUint64(bigint); |
- } else { |
- ASSERT(host_value.IsMint() || host_value.IsSmi()); |
- value = host_value.AsInt64Value(); |
- } |
- if (little_endian.value()) { |
- value = Utils::HostToLittleEndian64(value); |
- } else { |
- value = Utils::HostToBigEndian64(value); |
- } |
- if (value > static_cast<uint64_t>(Mint::kMaxValue)) { |
- return BigintOperations::NewFromUint64(value); |
- } else if (value > static_cast<uint64_t>(Smi::kMaxValue)) { |
- return Mint::New(value); |
- } |
- return Smi::New(value); |
-} |
- |
- |
-DEFINE_NATIVE_ENTRY(ByteData_ToEndianFloat32, 2) { |
- GET_NON_NULL_NATIVE_ARGUMENT(Double, host_value, arguments->NativeArgAt(0)); |
- GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); |
- float value = host_value.value(); |
- if (little_endian.value()) { |
- value = bit_cast<float>( |
- Utils::HostToLittleEndian32(bit_cast<uint32_t>(value))); |
- } else { |
- value = bit_cast<float>( |
- Utils::HostToBigEndian32(bit_cast<uint32_t>(value))); |
- } |
- return Double::New(value); |
-} |
- |
- |
-DEFINE_NATIVE_ENTRY(ByteData_ToEndianFloat64, 2) { |
- GET_NON_NULL_NATIVE_ARGUMENT(Double, host_value, arguments->NativeArgAt(0)); |
- GET_NON_NULL_NATIVE_ARGUMENT(Bool, little_endian, arguments->NativeArgAt(1)); |
- double value = host_value.value(); |
- if (little_endian.value()) { |
- value = bit_cast<double>( |
- Utils::HostToLittleEndian64(bit_cast<uint64_t>(value))); |
- } else { |
- value = bit_cast<double>( |
- Utils::HostToBigEndian64(bit_cast<uint64_t>(value))); |
- } |
- return Double::New(value); |
-} |
- |
-} // namespace dart |