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 "include/dart_api.h" | 5 #include "include/dart_api.h" |
6 #include "include/dart_mirrors_api.h" | 6 #include "include/dart_mirrors_api.h" |
7 #include "include/dart_native_api.h" | 7 #include "include/dart_native_api.h" |
8 | 8 |
9 #include "platform/assert.h" | 9 #include "platform/assert.h" |
10 #include "vm/bigint_operations.h" | 10 #include "vm/bigint_operations.h" |
(...skipping 2118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2129 } \ | 2129 } \ |
2130 const Integer& integer = Integer::Cast(element); \ | 2130 const Integer& integer = Integer::Cast(element); \ |
2131 native_array[i] = static_cast<uint8_t>(integer.AsInt64Value() & 0xff); \ | 2131 native_array[i] = static_cast<uint8_t>(integer.AsInt64Value() & 0xff); \ |
2132 ASSERT(integer.AsInt64Value() <= 0xff); \ | 2132 ASSERT(integer.AsInt64Value() <= 0xff); \ |
2133 } \ | 2133 } \ |
2134 return Api::Success(); \ | 2134 return Api::Success(); \ |
2135 } \ | 2135 } \ |
2136 return Api::NewError("Invalid length passed in to access array elements"); \ | 2136 return Api::NewError("Invalid length passed in to access array elements"); \ |
2137 | 2137 |
2138 | 2138 |
2139 static Dart_Handle CopyBytes(const TypedData& array, | |
2140 intptr_t offset, | |
2141 uint8_t* native_array, | |
2142 intptr_t length) { | |
2143 ASSERT(array.IsTypedData()); | |
2144 ASSERT(array.ElementSizeInBytes() == 1); | |
2145 if (!Utils::RangeCheck(offset, length, array.Length())) { | |
2146 return Api::NewError("Invalid length passed in to access list elements"); | |
2147 } | |
2148 NoGCScope no_gc; | |
2149 memmove(native_array, | |
2150 reinterpret_cast<uint8_t*>(array.DataAddr(offset)), | |
2151 length); | |
2152 return Api::Success(); | |
2153 } | |
2154 | |
2155 | |
2139 DART_EXPORT Dart_Handle Dart_ListGetAsBytes(Dart_Handle list, | 2156 DART_EXPORT Dart_Handle Dart_ListGetAsBytes(Dart_Handle list, |
2140 intptr_t offset, | 2157 intptr_t offset, |
2141 uint8_t* native_array, | 2158 uint8_t* native_array, |
2142 intptr_t length) { | 2159 intptr_t length) { |
2143 Isolate* isolate = Isolate::Current(); | 2160 Isolate* isolate = Isolate::Current(); |
2144 DARTSCOPE(isolate); | 2161 DARTSCOPE(isolate); |
2145 const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(list)); | 2162 const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(list)); |
2146 if (obj.IsTypedData()) { | 2163 if (obj.IsTypedData()) { |
2147 const TypedData& array = TypedData::Cast(obj); | 2164 const TypedData& array = TypedData::Cast(obj); |
2148 if (array.ElementSizeInBytes() == 1) { | 2165 if (array.ElementSizeInBytes() == 1) { |
2149 if (Utils::RangeCheck(offset, length, array.Length())) { | 2166 return CopyBytes(array, offset, native_array, length); |
2150 NoGCScope no_gc; | 2167 } |
2151 memmove(native_array, | 2168 } |
2152 reinterpret_cast<uint8_t*>(array.DataAddr(offset)), | 2169 if (RawObject::IsTypedDataViewClassId(obj.GetClassId())) { |
2153 length); | 2170 const Instance& view = Instance::Cast(obj); |
2154 return Api::Success(); | 2171 if (TypedDataView::ElementSizeInBytes(view) == 1) { |
2172 intptr_t view_length = Smi::Value(TypedDataView::Length(view)); | |
2173 if (!Utils::RangeCheck(offset, length, view_length)) { | |
2174 return Api::NewError( | |
2175 "Invalid length passed in to access list elements"); | |
2155 } | 2176 } |
2156 return Api::NewError("Invalid length passed in to access list elements"); | 2177 const Instance& data = Instance::Handle(TypedDataView::Data(view)); |
2178 intptr_t data_offset = | |
2179 Smi::Value(TypedDataView::OffsetInBytes(view)) + offset; | |
siva
2013/08/01 16:29:31
This data_offset computation can be moved inside t
Florian Schneider
2013/08/02 11:07:33
Done.
| |
2180 if (data.IsTypedData()) { | |
2181 const TypedData& array = TypedData::Cast(data); | |
2182 if (array.ElementSizeInBytes() == 1) { | |
2183 return CopyBytes(array, data_offset, native_array, length); | |
siva
2013/08/01 16:29:31
We end up doing the range check twice in this case
Florian Schneider
2013/08/02 11:07:33
Agree. The second range check is redundant becaus
| |
2184 } | |
2185 } | |
2157 } | 2186 } |
2158 } | 2187 } |
2159 if (obj.IsArray()) { | 2188 if (obj.IsArray()) { |
2160 GET_LIST_ELEMENT_AS_BYTES(isolate, | 2189 GET_LIST_ELEMENT_AS_BYTES(isolate, |
2161 Array, | 2190 Array, |
2162 obj, | 2191 obj, |
2163 native_array, | 2192 native_array, |
2164 offset, | 2193 offset, |
2165 length); | 2194 length); |
2166 } | 2195 } |
(...skipping 19 matching lines...) Expand all Loading... | |
2186 Array::Handle(ArgumentsDescriptor::New(kNumArgs))); | 2215 Array::Handle(ArgumentsDescriptor::New(kNumArgs))); |
2187 const Function& function = Function::Handle( | 2216 const Function& function = Function::Handle( |
2188 isolate, | 2217 isolate, |
2189 Resolver::ResolveDynamic(instance, Symbols::IndexToken(), args_desc)); | 2218 Resolver::ResolveDynamic(instance, Symbols::IndexToken(), args_desc)); |
2190 if (!function.IsNull()) { | 2219 if (!function.IsNull()) { |
2191 Object& result = Object::Handle(isolate); | 2220 Object& result = Object::Handle(isolate); |
2192 Integer& intobj = Integer::Handle(isolate); | 2221 Integer& intobj = Integer::Handle(isolate); |
2193 const Array& args = Array::Handle(isolate, Array::New(kNumArgs)); | 2222 const Array& args = Array::Handle(isolate, Array::New(kNumArgs)); |
2194 args.SetAt(0, instance); // Set up the receiver as the first argument. | 2223 args.SetAt(0, instance); // Set up the receiver as the first argument. |
2195 for (int i = 0; i < length; i++) { | 2224 for (int i = 0; i < length; i++) { |
2225 HandleScope handle_scope(isolate); | |
siva
2013/08/01 16:29:31
Could you use HANDLESCOPE(isolate); here to be con
Florian Schneider
2013/08/02 11:07:33
Done.
| |
2196 intobj = Integer::New(offset + i); | 2226 intobj = Integer::New(offset + i); |
2197 args.SetAt(1, intobj); | 2227 args.SetAt(1, intobj); |
2198 result = DartEntry::InvokeFunction(function, args); | 2228 result = DartEntry::InvokeFunction(function, args); |
2199 if (result.IsError()) { | 2229 if (result.IsError()) { |
2200 return Api::NewHandle(isolate, result.raw()); | 2230 return Api::NewHandle(isolate, result.raw()); |
2201 } | 2231 } |
2202 if (!result.IsInteger()) { | 2232 if (!result.IsInteger()) { |
2203 return Api::NewError("%s expects the argument 'list' to be " | 2233 return Api::NewError("%s expects the argument 'list' to be " |
2204 "a List of int", CURRENT_FUNC); | 2234 "a List of int", CURRENT_FUNC); |
2205 } | 2235 } |
(...skipping 1903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4109 } | 4139 } |
4110 { | 4140 { |
4111 NoGCScope no_gc; | 4141 NoGCScope no_gc; |
4112 RawObject* raw_obj = obj.raw(); | 4142 RawObject* raw_obj = obj.raw(); |
4113 isolate->heap()->SetPeer(raw_obj, peer); | 4143 isolate->heap()->SetPeer(raw_obj, peer); |
4114 } | 4144 } |
4115 return Api::Success(); | 4145 return Api::Success(); |
4116 } | 4146 } |
4117 | 4147 |
4118 } // namespace dart | 4148 } // namespace dart |
OLD | NEW |