Fast copy between TypedData and ExternalTypedData
Until now, copying data from TypedData to TypedData and from ExternalTypedData to ExternalTypedData was fast. But copying between TypedData and ExternalTypedData was not handled in a fast way. Review URL: https://codereview.chromium.org//14296006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@21791 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
+41
-29
@@ -78,25 +78,32 @@ DEFINE_NATIVE_ENTRY(TypedData_length, 1) {
|
||||
return Integer::null();
|
||||
}
|
||||
|
||||
|
||||
#define COPY_DATA(type, dst, src) \
|
||||
const type& dst_array = type::Cast(dst); \
|
||||
const type& src_array = type::Cast(src); \
|
||||
intptr_t element_size_in_bytes = dst_array.ElementSizeInBytes(); \
|
||||
intptr_t length_in_bytes = length.Value() * element_size_in_bytes; \
|
||||
intptr_t src_offset_in_bytes = src_start.Value() * element_size_in_bytes; \
|
||||
intptr_t dst_offset_in_bytes = dst_start.Value() * element_size_in_bytes; \
|
||||
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); \
|
||||
type::Copy(dst_array, dst_offset_in_bytes, \
|
||||
src_array, src_offset_in_bytes, \
|
||||
length_in_bytes);
|
||||
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));
|
||||
@@ -112,17 +119,22 @@ DEFINE_NATIVE_ENTRY(TypedData_setRange, 5) {
|
||||
args.SetAt(0, error);
|
||||
Exceptions::ThrowByType(Exceptions::kArgument, args);
|
||||
}
|
||||
if ((dst.IsTypedData() || dst.IsExternalTypedData()) &&
|
||||
(dst.clazz() == src.clazz())) {
|
||||
if (dst.IsTypedData()) {
|
||||
ASSERT(src.IsTypedData());
|
||||
COPY_DATA(TypedData, dst, src);
|
||||
} else {
|
||||
ASSERT(src.IsExternalTypedData());
|
||||
ASSERT(dst.IsExternalTypedData());
|
||||
COPY_DATA(ExternalTypedData, dst, src);
|
||||
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::True().raw();
|
||||
}
|
||||
return Bool::False().raw();
|
||||
}
|
||||
|
||||
@@ -12689,28 +12689,6 @@ const intptr_t TypedData::element_size[] = {
|
||||
};
|
||||
|
||||
|
||||
void TypedData::Copy(const TypedData& dst,
|
||||
intptr_t dst_offset_in_bytes,
|
||||
const TypedData& src,
|
||||
intptr_t src_offset_in_bytes,
|
||||
intptr_t length_in_bytes) {
|
||||
ASSERT(Utils::RangeCheck(src_offset_in_bytes,
|
||||
length_in_bytes,
|
||||
src.LengthInBytes()));
|
||||
ASSERT(Utils::RangeCheck(dst_offset_in_bytes,
|
||||
length_in_bytes,
|
||||
dst.LengthInBytes()));
|
||||
{
|
||||
NoGCScope no_gc;
|
||||
if (length_in_bytes > 0) {
|
||||
memmove(dst.DataAddr(dst_offset_in_bytes),
|
||||
src.DataAddr(src_offset_in_bytes),
|
||||
length_in_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RawTypedData* TypedData::New(intptr_t class_id,
|
||||
intptr_t len,
|
||||
Heap::Space space) {
|
||||
@@ -12748,28 +12726,6 @@ FinalizablePersistentHandle* ExternalTypedData::AddFinalizer(
|
||||
}
|
||||
|
||||
|
||||
void ExternalTypedData::Copy(const ExternalTypedData& dst,
|
||||
intptr_t dst_offset_in_bytes,
|
||||
const ExternalTypedData& src,
|
||||
intptr_t src_offset_in_bytes,
|
||||
intptr_t length_in_bytes) {
|
||||
ASSERT(Utils::RangeCheck(src_offset_in_bytes,
|
||||
length_in_bytes,
|
||||
src.LengthInBytes()));
|
||||
ASSERT(Utils::RangeCheck(dst_offset_in_bytes,
|
||||
length_in_bytes,
|
||||
dst.LengthInBytes()));
|
||||
{
|
||||
NoGCScope no_gc;
|
||||
if (length_in_bytes > 0) {
|
||||
memmove(dst.DataAddr(dst_offset_in_bytes),
|
||||
src.DataAddr(src_offset_in_bytes),
|
||||
length_in_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RawExternalTypedData* ExternalTypedData::New(intptr_t class_id,
|
||||
uint8_t* data,
|
||||
intptr_t len,
|
||||
|
||||
+45
-13
@@ -5043,6 +5043,12 @@ class TypedData : public Instance {
|
||||
return ElementSizeInBytes(cid);
|
||||
}
|
||||
|
||||
|
||||
TypeDataElementType ElementType() const {
|
||||
intptr_t cid = raw()->GetClassId();
|
||||
return ElementType(cid);
|
||||
}
|
||||
|
||||
intptr_t LengthInBytes() const {
|
||||
intptr_t cid = raw()->GetClassId();
|
||||
return (ElementSizeInBytes(cid) * Length());
|
||||
@@ -5092,7 +5098,13 @@ class TypedData : public Instance {
|
||||
|
||||
static intptr_t ElementSizeInBytes(intptr_t class_id) {
|
||||
ASSERT(RawObject::IsTypedDataClassId(class_id));
|
||||
return element_size[class_id - kTypedDataInt8ArrayCid];
|
||||
return element_size[ElementType(class_id)];
|
||||
}
|
||||
|
||||
static TypeDataElementType ElementType(intptr_t class_id) {
|
||||
ASSERT(RawObject::IsTypedDataClassId(class_id));
|
||||
return static_cast<TypeDataElementType>(
|
||||
class_id - kTypedDataInt8ArrayCid);
|
||||
}
|
||||
|
||||
static intptr_t MaxElements(intptr_t class_id) {
|
||||
@@ -5104,11 +5116,26 @@ class TypedData : public Instance {
|
||||
intptr_t len,
|
||||
Heap::Space space = Heap::kNew);
|
||||
|
||||
static void Copy(const TypedData& dst,
|
||||
intptr_t dst_offset_in_bytes,
|
||||
const TypedData& src,
|
||||
intptr_t src_offset_in_bytes,
|
||||
intptr_t length_in_bytes);
|
||||
template <typename DstType, typename SrcType>
|
||||
static void Copy(const DstType& dst, intptr_t dst_offset_in_bytes,
|
||||
const SrcType& src, intptr_t src_offset_in_bytes,
|
||||
intptr_t length_in_bytes) {
|
||||
ASSERT(dst.ElementType() == src.ElementType());
|
||||
ASSERT(Utils::RangeCheck(src_offset_in_bytes,
|
||||
length_in_bytes,
|
||||
src.LengthInBytes()));
|
||||
ASSERT(Utils::RangeCheck(dst_offset_in_bytes,
|
||||
length_in_bytes,
|
||||
dst.LengthInBytes()));
|
||||
{
|
||||
NoGCScope no_gc;
|
||||
if (length_in_bytes > 0) {
|
||||
memmove(dst.DataAddr(dst_offset_in_bytes),
|
||||
src.DataAddr(src_offset_in_bytes),
|
||||
length_in_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsTypedData(const Instance& obj) {
|
||||
ASSERT(!obj.IsNull());
|
||||
@@ -5143,6 +5170,11 @@ class ExternalTypedData : public Instance {
|
||||
return ElementSizeInBytes(cid);
|
||||
}
|
||||
|
||||
TypeDataElementType ElementType() const {
|
||||
intptr_t cid = raw()->GetClassId();
|
||||
return ElementType(cid);
|
||||
}
|
||||
|
||||
intptr_t LengthInBytes() const {
|
||||
intptr_t cid = raw()->GetClassId();
|
||||
return (ElementSizeInBytes(cid) * Length());
|
||||
@@ -5193,7 +5225,13 @@ class ExternalTypedData : public Instance {
|
||||
|
||||
static intptr_t ElementSizeInBytes(intptr_t class_id) {
|
||||
ASSERT(RawObject::IsExternalTypedDataClassId(class_id));
|
||||
return TypedData::element_size[class_id - kExternalTypedDataInt8ArrayCid];
|
||||
return TypedData::element_size[ElementType(class_id)];
|
||||
}
|
||||
|
||||
static TypeDataElementType ElementType(intptr_t class_id) {
|
||||
ASSERT(RawObject::IsExternalTypedDataClassId(class_id));
|
||||
return static_cast<TypeDataElementType>(
|
||||
class_id - kExternalTypedDataInt8ArrayCid);
|
||||
}
|
||||
|
||||
static intptr_t MaxElements(intptr_t class_id) {
|
||||
@@ -5206,12 +5244,6 @@ class ExternalTypedData : public Instance {
|
||||
intptr_t len,
|
||||
Heap::Space space = Heap::kNew);
|
||||
|
||||
static void Copy(const ExternalTypedData& dst,
|
||||
intptr_t dst_offset_in_bytes,
|
||||
const ExternalTypedData& src,
|
||||
intptr_t src_offset_in_bytes,
|
||||
intptr_t length_in_bytes);
|
||||
|
||||
static bool IsExternalTypedData(const Instance& obj) {
|
||||
ASSERT(!obj.IsNull());
|
||||
intptr_t cid = obj.raw()->GetClassId();
|
||||
|
||||
@@ -172,6 +172,12 @@ enum {
|
||||
kSmiTagShift = 1,
|
||||
};
|
||||
|
||||
enum TypeDataElementType {
|
||||
#define V(name) k##name##Element,
|
||||
CLASS_LIST_TYPED_DATA(V)
|
||||
#undef V
|
||||
};
|
||||
|
||||
#define SNAPSHOT_WRITER_SUPPORT() \
|
||||
void WriteTo( \
|
||||
SnapshotWriter* writer, intptr_t object_id, Snapshot::Kind kind); \
|
||||
|
||||
Reference in New Issue
Block a user