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

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

Issue 12544015: Implement 'dart:typeddata' directly in the VM instead of using 'dart:scalarlist' (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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/typeddata.dart » ('j') | runtime/vm/object.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include "vm/bootstrap_natives.h"
6
7 #include "include/dart_api.h"
8
9 #include "vm/bigint_operations.h"
10 #include "vm/exceptions.h"
11 #include "vm/native_entry.h"
12 #include "vm/object.h"
13
14 namespace dart {
15
16 // TypedData.
17
18 // Checks to see if offsetInBytes is in the range.
19 static bool RangeCheck(intptr_t offsetInBytes, intptr_t lengthInBytes) {
20 return ((offsetInBytes >= 0) &&
21 (lengthInBytes > 0) &&
22 (offsetInBytes < lengthInBytes));
23 }
24
25
26 // Checks to see if a length will not result in an OOM error.
27 static void LengthCheck(intptr_t len, intptr_t max) {
28 ASSERT(len >= 0);
29 if (len > max) {
30 const String& error = String::Handle(String::NewFormatted(
31 "insufficient memory to allocate a TypedData object of length (%"Pd")",
32 len));
33 const Array& args = Array::Handle(Array::New(1));
34 args.SetAt(0, error);
35 Exceptions::ThrowByType(Exceptions::kOutOfMemory, args);
36 }
37 }
38
39
40 static void PeerFinalizer(Dart_Handle handle, void* peer) {
41 Dart_DeletePersistentHandle(handle);
42 OS::AlignedFree(peer);
43 }
44
45
46 DEFINE_NATIVE_ENTRY(TypedData_length, 1) {
47 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
48 if (instance.IsTypedData()) {
49 const TypedData& array = TypedData::Cast(instance);
50 return Smi::New(array.Length());
51 }
52 ASSERT(instance.IsExternalTypedData());
Ivan Posva 2013/03/07 08:53:31 I am not sure the ASSERT here is good enough. As t
siva 2013/03/07 21:47:43 Changed the ASSERT to thrown an ArgumentError exce
53 const ExternalTypedData& array = ExternalTypedData::Cast(instance);
54 return Smi::New(array.Length());
55 }
56
57
58 #define TYPED_DATA_NEW(name) \
59 DEFINE_NATIVE_ENTRY(TypedData_##name##_new, 1) { \
60 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0)); \
61 intptr_t cid = kTypedData##name##Cid; \
62 intptr_t len = length.Value(); \
63 intptr_t max = (kSmiMax / TypedData::ElementSizeInBytes(cid)); \
Ivan Posva 2013/03/07 08:53:31 Please comment why you have this restriction here.
siva 2013/03/07 21:47:43 Done.
64 LengthCheck(len, max); \
65 return TypedData::New(cid, len); \
66 } \
67
68
69 #define EXT_TYPED_DATA_NEW(name) \
70 DEFINE_NATIVE_ENTRY(ExternalTypedData_##name##_new, 1) { \
71 const int kAlignment = 16; \
72 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0)); \
73 intptr_t cid = kExternalTypedData##name##Cid; \
74 intptr_t len = length.Value(); \
75 intptr_t max = (kSmiMax / ExternalTypedData::ElementSizeInBytes(cid)); \
Ivan Posva 2013/03/07 08:53:31 ditto
siva 2013/03/07 21:47:43 Done.
76 LengthCheck(len, max); \
77 intptr_t len_bytes = len * ExternalTypedData::ElementSizeInBytes(cid); \
78 uint8_t* data = OS::AllocateAlignedArray<uint8_t>(len_bytes, kAlignment); \
79 const ExternalTypedData& obj = \
80 ExternalTypedData::Handle(ExternalTypedData::New(cid, data, len)); \
81 obj.AddFinalizer(data, PeerFinalizer); \
82 return obj.raw(); \
83 } \
84
85
86 #define TYPED_DATA_NEW_NATIVE(name) \
87 TYPED_DATA_NEW(name) \
88 EXT_TYPED_DATA_NEW(name) \
89
90
91 CLASS_LIST_TYPED_DATA(TYPED_DATA_NEW_NATIVE)
92
93
94 #define TYPED_DATA_GETTER(getter, object) \
95 DEFINE_NATIVE_ENTRY(TypedData_##getter, 2) { \
96 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \
97 GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1)); \
98 if (instance.IsTypedData()) { \
99 const TypedData& array = TypedData::Cast(instance); \
100 intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
101 ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
102 return object::New(array.getter(offsetInBytes)); \
103 } \
104 ASSERT(instance.IsExternalTypedData()); \
Ivan Posva 2013/03/07 08:53:31 ditto
siva 2013/03/07 21:47:43 Done.
105 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \
106 intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
107 ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
108 return object::New(array.getter(offsetInBytes)); \
109 } \
110
111
112 #define TYPED_DATA_SETTER(setter, object, get_object_value) \
113 DEFINE_NATIVE_ENTRY(TypedData_##setter, 3) { \
114 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \
115 GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1)); \
116 GET_NON_NULL_NATIVE_ARGUMENT(object, value, arguments->NativeArgAt(2)); \
117 if (instance.IsTypedData()) { \
118 const TypedData& array = TypedData::Cast(instance); \
119 intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
120 ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
121 array.setter(offsetInBytes, value.get_object_value()); \
122 } else { \
123 ASSERT(instance.IsExternalTypedData()); \
Ivan Posva 2013/03/07 08:53:31 ditto
siva 2013/03/07 21:47:43 Done.
124 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \
125 intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
126 ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
127 array.setter(offsetInBytes, value.get_object_value()); \
128 } \
129 return Object::null(); \
130 }
131
132
133 #define TYPED_DATA_UINT64_GETTER(getter, object) \
134 DEFINE_NATIVE_ENTRY(TypedData_##getter, 2) { \
135 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \
136 GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1)); \
137 uint64_t value = 0; \
138 if (instance.IsTypedData()) { \
139 const TypedData& array = TypedData::Cast(instance); \
140 intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
141 ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
142 value = array.getter(offsetInBytes); \
143 } else { \
144 ASSERT(instance.IsExternalTypedData()); \
Ivan Posva 2013/03/07 08:53:31 ditto
siva 2013/03/07 21:47:43 Done.
145 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \
146 intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
147 ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
148 value = array.getter(offsetInBytes); \
149 } \
150 Integer& result = Integer::Handle(); \
151 if (value > static_cast<uint64_t>(Mint::kMaxValue)) { \
152 result = BigintOperations::NewFromUint64(value); \
153 } else if (value > static_cast<uint64_t>(Smi::kMaxValue)) { \
154 result = Mint::New(value); \
155 } else { \
156 result = Smi::New(value); \
157 } \
158 return result.raw(); \
159 } \
160
161
162 #define TYPED_DATA_UINT64_SETTER(setter, object) \
163 DEFINE_NATIVE_ENTRY(TypedData_##setter, 3) { \
164 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \
165 GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1)); \
166 GET_NON_NULL_NATIVE_ARGUMENT(object, value, arguments->NativeArgAt(2)); \
167 uint64_t object_value; \
168 if (value.IsBigint()) { \
169 const Bigint& bigint = Bigint::Cast(value); \
170 ASSERT(BigintOperations::FitsIntoUint64(bigint)); \
Ivan Posva 2013/03/07 08:53:31 This assert is strange here. Shouldn't this just t
siva 2013/03/07 21:47:43 I don't see a truncate operation in our current bi
171 object_value = BigintOperations::AbsToUint64(bigint); \
172 } else { \
173 ASSERT(value.IsMint() || value.IsSmi()); \
174 object_value = value.AsInt64Value(); \
175 } \
176 if (instance.IsTypedData()) { \
177 const TypedData& array = TypedData::Cast(instance); \
178 intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
179 ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
180 array.setter(offsetInBytes, object_value); \
181 } else { \
182 ASSERT(instance.IsExternalTypedData()); \
Ivan Posva 2013/03/07 08:53:31 ditto
siva 2013/03/07 21:47:43 Done.
183 const ExternalTypedData& array = ExternalTypedData::Cast(instance); \
184 intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
185 ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
186 array.setter(offsetInBytes, object_value); \
187 } \
188 return Object::null(); \
189 }
190
191
192 #define TYPED_DATA_NATIVES(name, getter, setter, object, get_object_value) \
193 TYPED_DATA_GETTER(getter, object) \
194 TYPED_DATA_SETTER(setter, object, get_object_value) \
195
196
197 #define TYPED_DATA_UINT64_NATIVES(name, getter, setter, object) \
198 TYPED_DATA_UINT64_GETTER(getter, object) \
199 TYPED_DATA_UINT64_SETTER(setter, object) \
200
201
202 TYPED_DATA_NATIVES(Int8Array, GetInt8, SetInt8, Smi, Value)
203 TYPED_DATA_NATIVES(Uint8Array, GetUint8, SetUint8, Smi, Value)
204 TYPED_DATA_NATIVES(Int16Array, GetInt16, SetInt16, Smi, Value)
205 TYPED_DATA_NATIVES(Uint16Array, GetUint16, SetUint16, Smi, Value)
206 TYPED_DATA_NATIVES(Int32Array, GetInt32, SetInt32, Integer, AsInt64Value)
207 TYPED_DATA_NATIVES(Uint32Array, GetUint32, SetUint32, Integer, AsInt64Value)
208 TYPED_DATA_NATIVES(Int64Array, GetInt64, SetInt64, Integer, AsInt64Value)
209 TYPED_DATA_UINT64_NATIVES(Uint64Array, GetUint64, SetUint64, Integer)
210 TYPED_DATA_NATIVES(Float32Array, GetFloat32, SetFloat32, Double, value)
211 TYPED_DATA_NATIVES(Float64Array, GetFloat64, SetFloat64, Double, value)
212
213 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/lib/typeddata.dart » ('j') | runtime/vm/object.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698