1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef ECMASCRIPT_BASE_TYPED_ARRAY_HELPER_INL_H
17 #define ECMASCRIPT_BASE_TYPED_ARRAY_HELPER_INL_H
18
19 #include "ecmascript/builtins/builtins_arraybuffer.h"
20 #include "ecmascript/base/builtins_base.h"
21 #include "ecmascript/base/error_helper.h"
22 #include "ecmascript/base/error_type.h"
23 #include "ecmascript/base/typed_array_helper.h"
24 #include "ecmascript/ecma_macros.h"
25 #include "ecmascript/ecma_vm.h"
26 #include "ecmascript/global_env.h"
27 #include "ecmascript/ic/proto_change_details.h"
28 #include "ecmascript/js_array_iterator.h"
29 #include "ecmascript/js_arraybuffer.h"
30 #include "ecmascript/js_hclass.h"
31 #include "ecmascript/js_object.h"
32 #include "ecmascript/js_tagged_value.h"
33 #include "ecmascript/js_tagged_value-inl.h"
34 #include "ecmascript/object_factory.h"
35
36 namespace panda::ecmascript::base {
37
38 #define GET_ONHEAP_HCLASS_FROM_TYPE(Type) \
39 JSHandle<JSHClass> TypedArrayHelper::GetOnHeapHclass##Type(JSThread *thread, JSHClass* objHclass) \
40 { \
41 JSHandle<JSHClass> result; \
42 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); \
43 if (*JSHandle<JSHClass>(env->Get##Type##RootHclass()) == (objHclass)) { \
44 return JSHandle<JSHClass>(env->Get##Type##RootHclassOnHeap()); \
45 } \
46 result = JSHClass::Clone((thread), JSHandle<JSHClass>((thread), (objHclass))); \
47 result->SetIsOnHeap(true); \
48 return result; \
49 }
50
51 TYPED_ARRAY_TYPES(GET_ONHEAP_HCLASS_FROM_TYPE)
52 #undef GET_ONHEAP_HCLASS_FROM_TYPE
53
54 #define GET_NOT_ONHEAP_HCLASS_FROM_TYPE(Type) \
55 JSHandle<JSHClass> TypedArrayHelper::GetNotOnHeapHclass##Type(JSThread *thread, JSHClass* objHclass) \
56 { \
57 JSHandle<JSHClass> result; \
58 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); \
59 if (*JSHandle<JSHClass>(env->Get##Type##RootHclassOnHeap()) == (objHclass)) { \
60 return JSHandle<JSHClass>(env->Get##Type##RootHclass()); \
61 } \
62 result = JSHClass::Clone((thread), JSHandle<JSHClass>((thread), (objHclass))); \
63 result->SetIsOnHeap(false); \
64 return result; \
65 }
66
TYPED_ARRAY_TYPES(GET_NOT_ONHEAP_HCLASS_FROM_TYPE)67 TYPED_ARRAY_TYPES(GET_NOT_ONHEAP_HCLASS_FROM_TYPE)
68 #undef GET_NOT_ONHEAP_HCLASS_FROM_TYPE
69
70 DataViewType TypedArrayHelper::GetType(const JSHandle<JSTypedArray> &obj)
71 {
72 JSType type = obj->GetJSHClass()->GetObjectType();
73 return GetType(type);
74 }
75
GetType(JSType type)76 DataViewType TypedArrayHelper::GetType(JSType type)
77 {
78 switch (type) {
79 case JSType::JS_INT8_ARRAY:
80 return DataViewType::INT8;
81 case JSType::JS_UINT8_ARRAY:
82 return DataViewType::UINT8;
83 case JSType::JS_UINT8_CLAMPED_ARRAY:
84 return DataViewType::UINT8_CLAMPED;
85 case JSType::JS_INT16_ARRAY:
86 return DataViewType::INT16;
87 case JSType::JS_UINT16_ARRAY:
88 return DataViewType::UINT16;
89 case JSType::JS_INT32_ARRAY:
90 return DataViewType::INT32;
91 case JSType::JS_UINT32_ARRAY:
92 return DataViewType::UINT32;
93 case JSType::JS_FLOAT32_ARRAY:
94 return DataViewType::FLOAT32;
95 case JSType::JS_FLOAT64_ARRAY:
96 return DataViewType::FLOAT64;
97 case JSType::JS_BIGINT64_ARRAY:
98 return DataViewType::BIGINT64;
99 default:
100 return DataViewType::BIGUINT64;
101 }
102 }
103
GetElementSize(const JSHandle<JSTypedArray> & obj)104 uint32_t TypedArrayHelper::GetElementSize(const JSHandle<JSTypedArray> &obj)
105 {
106 JSType type = obj->GetJSHClass()->GetObjectType();
107 return GetElementSize(type);
108 }
109
GetElementSize(JSType type)110 uint32_t TypedArrayHelper::GetElementSize(JSType type)
111 {
112 switch (type) {
113 case JSType::JS_INT8_ARRAY:
114 case JSType::JS_UINT8_ARRAY:
115 case JSType::JS_UINT8_CLAMPED_ARRAY:
116 return ElementSize::ONE;
117 case JSType::JS_INT16_ARRAY:
118 case JSType::JS_UINT16_ARRAY:
119 return ElementSize::TWO;
120 case JSType::JS_INT32_ARRAY:
121 case JSType::JS_UINT32_ARRAY:
122 case JSType::JS_FLOAT32_ARRAY:
123 return ElementSize::FOUR;
124 default:
125 return ElementSize::EIGHT;
126 }
127 }
128
GetConstructor(JSThread * thread,const JSHandle<JSTaggedValue> & obj)129 JSHandle<JSTaggedValue> TypedArrayHelper::GetConstructor(JSThread *thread, const JSHandle<JSTaggedValue> &obj)
130 {
131 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
132 JSType type = obj->GetTaggedObject()->GetClass()->GetObjectType();
133 switch (type) {
134 case JSType::JS_INT8_ARRAY:
135 return env->GetInt8ArrayFunction();
136 case JSType::JS_UINT8_ARRAY:
137 return env->GetUint8ArrayFunction();
138 case JSType::JS_UINT8_CLAMPED_ARRAY:
139 return env->GetUint8ClampedArrayFunction();
140 case JSType::JS_INT16_ARRAY:
141 return env->GetInt16ArrayFunction();
142 case JSType::JS_UINT16_ARRAY:
143 return env->GetUint16ArrayFunction();
144 case JSType::JS_INT32_ARRAY:
145 return env->GetInt32ArrayFunction();
146 case JSType::JS_UINT32_ARRAY:
147 return env->GetUint32ArrayFunction();
148 case JSType::JS_FLOAT32_ARRAY:
149 return env->GetFloat32ArrayFunction();
150 case JSType::JS_FLOAT64_ARRAY:
151 return env->GetFloat64ArrayFunction();
152 case JSType::JS_BIGINT64_ARRAY:
153 return env->GetBigInt64ArrayFunction();
154 default:
155 return env->GetBigUint64ArrayFunction();
156 }
157 }
158
GetConstructorFromType(JSThread * thread,const DataViewType arrayType)159 JSHandle<JSFunction> TypedArrayHelper::GetConstructorFromType(JSThread *thread, const DataViewType arrayType)
160 {
161 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
162 switch (arrayType) {
163 case DataViewType::INT8:
164 return JSHandle<JSFunction>(env->GetInt8ArrayFunction());
165 case DataViewType::UINT8:
166 return JSHandle<JSFunction>(env->GetUint8ArrayFunction());
167 case DataViewType::UINT8_CLAMPED:
168 return JSHandle<JSFunction>(env->GetUint8ClampedArrayFunction());
169 case DataViewType::INT16:
170 return JSHandle<JSFunction>(env->GetInt16ArrayFunction());
171 case DataViewType::UINT16:
172 return JSHandle<JSFunction>(env->GetUint16ArrayFunction());
173 case DataViewType::INT32:
174 return JSHandle<JSFunction>(env->GetInt32ArrayFunction());
175 case DataViewType::UINT32:
176 return JSHandle<JSFunction>(env->GetUint32ArrayFunction());
177 case DataViewType::FLOAT32:
178 return JSHandle<JSFunction>(env->GetFloat32ArrayFunction());
179 case DataViewType::FLOAT64:
180 return JSHandle<JSFunction>(env->GetFloat64ArrayFunction());
181 case DataViewType::BIGINT64:
182 return JSHandle<JSFunction>(env->GetBigInt64ArrayFunction());
183 default:
184 break;
185 }
186 return JSHandle<JSFunction>(env->GetBigUint64ArrayFunction());
187 }
188
GetConstructorNameFromType(JSThread * thread,const DataViewType arrayType)189 JSHandle<JSTaggedValue> TypedArrayHelper::GetConstructorNameFromType(JSThread *thread, const DataViewType arrayType)
190 {
191 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
192 switch (arrayType) {
193 case DataViewType::INT8:
194 return globalConst->GetHandledInt8ArrayString();
195 case DataViewType::UINT8:
196 return globalConst->GetHandledUint8ArrayString();
197 case DataViewType::UINT8_CLAMPED:
198 return globalConst->GetHandledUint8ClampedArrayString();
199 case DataViewType::INT16:
200 return globalConst->GetHandledInt16ArrayString();
201 case DataViewType::UINT16:
202 return globalConst->GetHandledUint16ArrayString();
203 case DataViewType::INT32:
204 return globalConst->GetHandledInt32ArrayString();
205 case DataViewType::UINT32:
206 return globalConst->GetHandledUint32ArrayString();
207 case DataViewType::FLOAT32:
208 return globalConst->GetHandledFloat32ArrayString();
209 case DataViewType::FLOAT64:
210 return globalConst->GetHandledFloat64ArrayString();
211 case DataViewType::BIGINT64:
212 return globalConst->GetHandledBigInt64ArrayString();
213 default:
214 break;
215 }
216 return globalConst->GetHandledBigInt64ArrayString();
217 }
218
GetOnHeapHclassFromType(JSThread * thread,const JSHandle<JSTypedArray> & obj,const DataViewType arrayType)219 JSHandle<JSHClass> TypedArrayHelper::GetOnHeapHclassFromType(
220 JSThread *thread, const JSHandle<JSTypedArray> &obj, const DataViewType arrayType)
221 {
222 JSHClass* objHclass = JSHandle<TaggedObject>(obj)->GetClass();
223 ASSERT_PRINT(!objHclass->IsOnHeapFromBitField(), "must be not on heap");
224 switch (arrayType) {
225 case DataViewType::INT8:
226 return TypedArrayHelper::GetOnHeapHclassInt8Array(thread, objHclass);
227 case DataViewType::UINT8:
228 return TypedArrayHelper::GetOnHeapHclassUint8Array(thread, objHclass);
229 case DataViewType::UINT8_CLAMPED:
230 return TypedArrayHelper::GetOnHeapHclassUint8ClampedArray(thread, objHclass);
231 case DataViewType::INT16:
232 return TypedArrayHelper::GetOnHeapHclassInt16Array(thread, objHclass);
233 case DataViewType::UINT16:
234 return TypedArrayHelper::GetOnHeapHclassUint16Array(thread, objHclass);
235 case DataViewType::INT32:
236 return TypedArrayHelper::GetOnHeapHclassInt32Array(thread, objHclass);
237 case DataViewType::UINT32:
238 return TypedArrayHelper::GetOnHeapHclassUint32Array(thread, objHclass);
239 case DataViewType::FLOAT32:
240 return TypedArrayHelper::GetOnHeapHclassFloat32Array(thread, objHclass);
241 case DataViewType::FLOAT64:
242 return TypedArrayHelper::GetOnHeapHclassFloat64Array(thread, objHclass);
243 case DataViewType::BIGINT64:
244 return TypedArrayHelper::GetOnHeapHclassBigInt64Array(thread, objHclass);
245 default:
246 break;
247 }
248 return TypedArrayHelper::GetOnHeapHclassBigUint64Array(thread, objHclass);
249 }
250
GetNotOnHeapHclassFromType(JSThread * thread,const JSHandle<JSTypedArray> & obj,const DataViewType arrayType)251 JSHandle<JSHClass> TypedArrayHelper::GetNotOnHeapHclassFromType(
252 JSThread *thread, const JSHandle<JSTypedArray> &obj, const DataViewType arrayType)
253 {
254 JSHClass* objHclass = JSHandle<TaggedObject>(obj)->GetClass();
255 ASSERT_PRINT(objHclass->IsOnHeapFromBitField(), "must be on heap");
256 switch (arrayType) {
257 case DataViewType::INT8:
258 return TypedArrayHelper::GetNotOnHeapHclassInt8Array(thread, objHclass);
259 case DataViewType::UINT8:
260 return TypedArrayHelper::GetNotOnHeapHclassUint8Array(thread, objHclass);
261 case DataViewType::UINT8_CLAMPED:
262 return TypedArrayHelper::GetNotOnHeapHclassUint8ClampedArray(thread, objHclass);
263 case DataViewType::INT16:
264 return TypedArrayHelper::GetNotOnHeapHclassInt16Array(thread, objHclass);
265 case DataViewType::UINT16:
266 return TypedArrayHelper::GetNotOnHeapHclassUint16Array(thread, objHclass);
267 case DataViewType::INT32:
268 return TypedArrayHelper::GetNotOnHeapHclassInt32Array(thread, objHclass);
269 case DataViewType::UINT32:
270 return TypedArrayHelper::GetOnHeapHclassUint32Array(thread, objHclass);
271 case DataViewType::FLOAT32:
272 return TypedArrayHelper::GetNotOnHeapHclassFloat32Array(thread, objHclass);
273 case DataViewType::FLOAT64:
274 return TypedArrayHelper::GetNotOnHeapHclassFloat64Array(thread, objHclass);
275 case DataViewType::BIGINT64:
276 return TypedArrayHelper::GetNotOnHeapHclassBigInt64Array(thread, objHclass);
277 default:
278 break;
279 }
280 return TypedArrayHelper::GetNotOnHeapHclassBigUint64Array(thread, objHclass);
281 }
282
GetSizeFromType(const DataViewType arrayType)283 uint32_t TypedArrayHelper::GetSizeFromType(const DataViewType arrayType)
284 {
285 if (arrayType == DataViewType::INT8 ||
286 arrayType == DataViewType::UINT8 ||
287 arrayType == DataViewType::UINT8_CLAMPED) {
288 return ElementSize::ONE;
289 }
290
291 if (arrayType == DataViewType::INT16 ||
292 arrayType == DataViewType::UINT16) {
293 return ElementSize::TWO;
294 }
295
296 if (arrayType == DataViewType::FLOAT32 ||
297 arrayType == DataViewType::UINT32 ||
298 arrayType == DataViewType::INT32) {
299 return ElementSize::FOUR;
300 }
301
302 return ElementSize::EIGHT;
303 }
304
IsAccessorHasChanged(const JSHandle<JSTaggedValue> & obj)305 bool TypedArrayHelper::IsAccessorHasChanged(const JSHandle<JSTaggedValue> &obj)
306 {
307 if (obj->IsHeapObject()) {
308 JSTaggedValue markerValue = obj->GetTaggedObject()->GetClass()->GetProtoChangeMarker();
309 if (markerValue.IsProtoChangeMarker()) {
310 return ProtoChangeMarker::Cast(markerValue.GetTaggedObject())->GetAccessorHasChanged();
311 }
312 }
313 return false;
314 }
315 } // namespace panda::ecmascript::base
316 #endif // ECMASCRIPT_BASE_TYPED_ARRAY_HELPER_INL_H
317