Flutter Engine
The Flutter Engine
typed_data.cc
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
6
7#include "include/dart_api.h"
8
9#include "vm/exceptions.h"
10#include "vm/native_entry.h"
11#include "vm/object.h"
12#include "vm/object_store.h"
13
14namespace dart {
15
16// TypedData.
17
19 GET_NON_NULL_NATIVE_ARGUMENT(TypedDataBase, array, arguments->NativeArgAt(0));
20 return Smi::New(array.Length());
21}
22
23DEFINE_NATIVE_ENTRY(TypedDataView_offsetInBytes, 0, 1) {
24 // "this" is either a _*ArrayView class or _ByteDataView.
25 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
26 ASSERT(instance.IsTypedDataView());
27 return TypedDataView::Cast(instance).offset_in_bytes();
28}
29
30DEFINE_NATIVE_ENTRY(TypedDataView_typedData, 0, 1) {
31 // "this" is either a _*ArrayView class or _ByteDataView.
32 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
33 ASSERT(instance.IsTypedDataView());
34 return TypedDataView::Cast(instance).typed_data();
35}
36
37static bool IsTypedDataUint8ArrayClassId(intptr_t cid) {
38 if (!IsTypedDataBaseClassId(cid)) return false;
39 const intptr_t internal_cid =
42 return internal_cid == kTypedDataUint8ArrayCid ||
43 internal_cid == kTypedDataUint8ClampedArrayCid;
44}
45
46DEFINE_NATIVE_ENTRY(TypedDataBase_setClampedRange, 0, 5) {
47 // This is called after bounds checking, so the numeric inputs are
48 // guaranteed to be Smis, and the length is guaranteed to be non-zero.
49 const TypedDataBase& dst =
50 TypedDataBase::CheckedHandle(zone, arguments->NativeArgAt(0));
51 const Smi& dst_start_smi =
52 Smi::CheckedHandle(zone, arguments->NativeArgAt(1));
53 const Smi& length_smi = Smi::CheckedHandle(zone, arguments->NativeArgAt(2));
54 const TypedDataBase& src =
55 TypedDataBase::CheckedHandle(zone, arguments->NativeArgAt(3));
56 const Smi& src_start_smi =
57 Smi::CheckedHandle(zone, arguments->NativeArgAt(4));
58
59 const intptr_t element_size_in_bytes = dst.ElementSizeInBytes();
60 ASSERT_EQUAL(src.ElementSizeInBytes(), element_size_in_bytes);
61
62 const intptr_t dst_start_in_bytes =
63 dst_start_smi.Value() * element_size_in_bytes;
64 const intptr_t length_in_bytes = length_smi.Value() * element_size_in_bytes;
65 const intptr_t src_start_in_bytes =
66 src_start_smi.Value() * element_size_in_bytes;
67
68#if defined(DEBUG)
69 // Verify bounds checks weren't needed.
70 ASSERT(dst_start_in_bytes >= 0);
71 ASSERT(src_start_in_bytes >= 0);
72 // The callers of this native function never call it for a zero-sized copy.
73 ASSERT(length_in_bytes > 0);
74
75 const intptr_t dst_length_in_bytes = dst.LengthInBytes();
76 // Since the length is non-zero, the start can't be the same as the end.
77 ASSERT(dst_start_in_bytes < dst_length_in_bytes);
78 ASSERT(length_in_bytes <= dst_length_in_bytes - dst_start_in_bytes);
79
80 const intptr_t src_length_in_bytes = src.LengthInBytes();
81 // Since the length is non-zero, the start can't be the same as the end.
82 ASSERT(src_start_in_bytes < src_length_in_bytes);
83 ASSERT(length_in_bytes <= src_length_in_bytes - src_start_in_bytes);
84#endif
85
86 ASSERT(IsClampedTypedDataBaseClassId(dst.ptr()->GetClassId()));
87 // The algorithm below assumes the clamped destination has uint8 elements.
88 ASSERT_EQUAL(element_size_in_bytes, 1);
89 ASSERT(IsTypedDataUint8ArrayClassId(dst.ptr()->GetClassId()));
90 // The native entry should only be called when clamping is needed. When the
91 // source has uint8 elements, a direct memory move should be used instead.
92 ASSERT(!IsTypedDataUint8ArrayClassId(src.ptr()->GetClassId()));
93
94 NoSafepointScope no_safepoint;
95 uint8_t* dst_data =
96 reinterpret_cast<uint8_t*>(dst.DataAddr(dst_start_in_bytes));
97 int8_t* src_data =
98 reinterpret_cast<int8_t*>(src.DataAddr(src_start_in_bytes));
99 for (intptr_t ix = 0; ix < length_in_bytes; ix++) {
100 int8_t v = *src_data;
101 if (v < 0) v = 0;
102 *dst_data = v;
103 src_data++;
104 dst_data++;
105 }
106
107 return Object::null();
108}
109
110// The native getter and setter functions defined here are only called if
111// unboxing doubles or SIMD values is not supported by the flow graph compiler,
112// and the provided offsets have already been range checked by the calling code.
113
114#define TYPED_DATA_GETTER(getter, object, ctor) \
115 DEFINE_NATIVE_ENTRY(TypedData_##getter, 0, 2) { \
116 GET_NON_NULL_NATIVE_ARGUMENT(TypedDataBase, array, \
117 arguments->NativeArgAt(0)); \
118 GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, \
119 arguments->NativeArgAt(1)); \
120 return object::ctor(array.getter(offsetInBytes.Value())); \
121 }
122
123#define TYPED_DATA_SETTER(setter, object, get_object_value, access_type) \
124 DEFINE_NATIVE_ENTRY(TypedData_##setter, 0, 3) { \
125 GET_NON_NULL_NATIVE_ARGUMENT(TypedDataBase, array, \
126 arguments->NativeArgAt(0)); \
127 GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, \
128 arguments->NativeArgAt(1)); \
129 GET_NON_NULL_NATIVE_ARGUMENT(object, value, arguments->NativeArgAt(2)); \
130 array.setter(offsetInBytes.Value(), \
131 static_cast<access_type>(value.get_object_value())); \
132 return Object::null(); \
133 }
134
135#define TYPED_DATA_NATIVES(type_name, object, ctor, get_object_value, \
136 access_type) \
137 TYPED_DATA_GETTER(Get##type_name, object, ctor) \
138 TYPED_DATA_SETTER(Set##type_name, object, get_object_value, access_type)
139
140TYPED_DATA_NATIVES(Float32, Double, New, value, float)
141TYPED_DATA_NATIVES(Float64, Double, New, value, double)
142TYPED_DATA_NATIVES(Float32x4, Float32x4, New, value, simd128_value_t)
143TYPED_DATA_NATIVES(Int32x4, Int32x4, New, value, simd128_value_t)
144TYPED_DATA_NATIVES(Float64x2, Float64x2, New, value, simd128_value_t)
145
146} // namespace dart
#define ASSERT_EQUAL(expected, actual)
Definition: assert.h:309
static ObjectPtr null()
Definition: object.h:433
static SmiPtr New(intptr_t value)
Definition: object.h:10006
intptr_t Value() const
Definition: object.h:9990
#define ASSERT(E)
VkInstance instance
Definition: main.cc:48
uint8_t value
Definition: dart_vm.cc:33
const int kNumTypedDataCidRemainders
Definition: class_id.h:265
bool IsTypedDataBaseClassId(intptr_t index)
Definition: class_id.h:429
@ TypedDataBase_length
Definition: il_test.cc:1250
const int kTypedDataCidRemainderInternal
Definition: class_id.h:261
static bool IsTypedDataUint8ArrayClassId(intptr_t cid)
Definition: typed_data.cc:37
bool IsClampedTypedDataBaseClassId(intptr_t index)
Definition: class_id.h:461
static const ClassId kFirstTypedDataCid
Definition: class_id.h:377
const intptr_t cid
DEFINE_NATIVE_ENTRY(List_allocate, 0, 2)
Definition: array.cc:13
dst
Definition: cp.py:12
#define GET_NON_NULL_NATIVE_ARGUMENT(type, name, value)
Definition: native_entry.h:74
#define TYPED_DATA_NATIVES(type_name, object, ctor, get_object_value, access_type)
Definition: typed_data.cc:135