Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(299)

Side by Side Diff: runtime/lib/typed_data.cc

Issue 189443004: Fix performance of setRange by avoiding going to Lists.copy (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/lib/typed_data.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « no previous file | runtime/lib/typed_data.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698