1 /**
2 * Copyright (c) 2021-2024 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 #include "ets_coroutine.h"
17 #include "ets_vm.h"
18 #include "intrinsics.h"
19 #include "mem/vm_handle.h"
20 #include "plugins/ets/runtime/types/ets_object.h"
21 #include "plugins/ets/runtime/types/ets_string.h"
22 #include "plugins/ets/runtime/types/ets_box_primitive-inl.h"
23 #include "plugins/ets/runtime/ets_panda_file_items.h"
24 #include "types/ets_array.h"
25 #include "types/ets_box_primitive.h"
26 #include "types/ets_class.h"
27 #include "types/ets_method.h"
28 #include "types/ets_primitives.h"
29 #include "types/ets_type.h"
30 #include "types/ets_type_comptime_traits.h"
31 #include "types/ets_typeapi.h"
32 #include "types/ets_typeapi_field.h"
33
34 namespace ark::ets::intrinsics {
35
ValueAPISetFieldObject(EtsObject * obj,EtsLong i,EtsObject * val)36 void ValueAPISetFieldObject(EtsObject *obj, EtsLong i, EtsObject *val)
37 {
38 auto coroutine = EtsCoroutine::GetCurrent();
39 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
40 VMHandle<EtsObject> objHandle(coroutine, obj->GetCoreType());
41 VMHandle<EtsObject> valHandle(coroutine, val->GetCoreType());
42
43 auto typeClass = objHandle.GetPtr()->GetClass();
44 auto fieldObject = typeClass->GetFieldByIndex(i);
45 objHandle.GetPtr()->SetFieldObject(fieldObject, valHandle.GetPtr());
46 }
47
48 template <typename T>
SetFieldValue(EtsObject * obj,EtsLong i,T val)49 void SetFieldValue(EtsObject *obj, EtsLong i, T val)
50 {
51 auto coroutine = EtsCoroutine::GetCurrent();
52 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
53 VMHandle<EtsObject> objHandle(coroutine, obj->GetCoreType());
54
55 auto typeClass = objHandle.GetPtr()->GetClass();
56 auto fieldObject = typeClass->GetFieldByIndex(i);
57 if (fieldObject->GetType()->IsBoxed()) {
58 objHandle.GetPtr()->SetFieldObject(fieldObject, EtsBoxPrimitive<T>::Create(coroutine, val));
59 return;
60 }
61 objHandle.GetPtr()->SetFieldPrimitive<T>(fieldObject, val);
62 }
63
ValueAPISetFieldBoolean(EtsObject * obj,EtsLong i,EtsBoolean val)64 void ValueAPISetFieldBoolean(EtsObject *obj, EtsLong i, EtsBoolean val)
65 {
66 SetFieldValue(obj, i, val);
67 }
68
ValueAPISetFieldByte(EtsObject * obj,EtsLong i,EtsByte val)69 void ValueAPISetFieldByte(EtsObject *obj, EtsLong i, EtsByte val)
70 {
71 SetFieldValue(obj, i, val);
72 }
73
ValueAPISetFieldShort(EtsObject * obj,EtsLong i,EtsShort val)74 void ValueAPISetFieldShort(EtsObject *obj, EtsLong i, EtsShort val)
75 {
76 SetFieldValue(obj, i, val);
77 }
78
ValueAPISetFieldChar(EtsObject * obj,EtsLong i,EtsChar val)79 void ValueAPISetFieldChar(EtsObject *obj, EtsLong i, EtsChar val)
80 {
81 SetFieldValue(obj, i, val);
82 }
83
ValueAPISetFieldInt(EtsObject * obj,EtsLong i,EtsInt val)84 void ValueAPISetFieldInt(EtsObject *obj, EtsLong i, EtsInt val)
85 {
86 SetFieldValue(obj, i, val);
87 }
88
ValueAPISetFieldLong(EtsObject * obj,EtsLong i,EtsLong val)89 void ValueAPISetFieldLong(EtsObject *obj, EtsLong i, EtsLong val)
90 {
91 SetFieldValue(obj, i, val);
92 }
93
ValueAPISetFieldFloat(EtsObject * obj,EtsLong i,EtsFloat val)94 void ValueAPISetFieldFloat(EtsObject *obj, EtsLong i, EtsFloat val)
95 {
96 SetFieldValue(obj, i, val);
97 }
98
ValueAPISetFieldDouble(EtsObject * obj,EtsLong i,EtsDouble val)99 void ValueAPISetFieldDouble(EtsObject *obj, EtsLong i, EtsDouble val)
100 {
101 SetFieldValue(obj, i, val);
102 }
103
ValueAPISetFieldByNameObject(EtsObject * obj,EtsString * name,EtsObject * val)104 void ValueAPISetFieldByNameObject(EtsObject *obj, EtsString *name, EtsObject *val)
105 {
106 auto coroutine = EtsCoroutine::GetCurrent();
107 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
108 VMHandle<EtsObject> objHandle(coroutine, obj->GetCoreType());
109 VMHandle<EtsString> nameHandle(coroutine, name->GetCoreType());
110 VMHandle<EtsObject> valHandle(coroutine, val->GetCoreType());
111
112 auto typeClass = objHandle.GetPtr()->GetClass();
113 auto fieldObject = typeClass->GetFieldIDByName(nameHandle.GetPtr()->GetMutf8().c_str());
114 objHandle.GetPtr()->SetFieldObject(fieldObject, valHandle.GetPtr());
115 }
116
117 template <typename T>
SetFieldByNameValue(EtsObject * obj,EtsString * name,T val)118 void SetFieldByNameValue(EtsObject *obj, EtsString *name, T val)
119 {
120 auto coroutine = EtsCoroutine::GetCurrent();
121 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
122 VMHandle<EtsObject> objHandle(coroutine, obj->GetCoreType());
123 VMHandle<EtsString> nameHandle(coroutine, name->GetCoreType());
124
125 auto typeClass = objHandle.GetPtr()->GetClass();
126 auto fieldObject = typeClass->GetFieldIDByName(nameHandle.GetPtr()->GetMutf8().c_str());
127 if (fieldObject->GetType()->IsBoxed()) {
128 objHandle.GetPtr()->SetFieldObject(fieldObject, EtsBoxPrimitive<T>::Create(coroutine, val));
129 return;
130 }
131 objHandle.GetPtr()->SetFieldPrimitive<T>(fieldObject, val);
132 }
133
ValueAPISetFieldByNameBoolean(EtsObject * obj,EtsString * name,EtsBoolean val)134 void ValueAPISetFieldByNameBoolean(EtsObject *obj, EtsString *name, EtsBoolean val)
135 {
136 SetFieldByNameValue(obj, name, val);
137 }
138
ValueAPISetFieldByNameByte(EtsObject * obj,EtsString * name,EtsByte val)139 void ValueAPISetFieldByNameByte(EtsObject *obj, EtsString *name, EtsByte val)
140 {
141 SetFieldByNameValue(obj, name, val);
142 }
143
ValueAPISetFieldByNameShort(EtsObject * obj,EtsString * name,EtsShort val)144 void ValueAPISetFieldByNameShort(EtsObject *obj, EtsString *name, EtsShort val)
145 {
146 SetFieldByNameValue(obj, name, val);
147 }
148
ValueAPISetFieldByNameChar(EtsObject * obj,EtsString * name,EtsChar val)149 void ValueAPISetFieldByNameChar(EtsObject *obj, EtsString *name, EtsChar val)
150 {
151 SetFieldByNameValue(obj, name, val);
152 }
153
ValueAPISetFieldByNameInt(EtsObject * obj,EtsString * name,EtsInt val)154 void ValueAPISetFieldByNameInt(EtsObject *obj, EtsString *name, EtsInt val)
155 {
156 SetFieldByNameValue(obj, name, val);
157 }
158
ValueAPISetFieldByNameLong(EtsObject * obj,EtsString * name,EtsLong val)159 void ValueAPISetFieldByNameLong(EtsObject *obj, EtsString *name, EtsLong val)
160 {
161 SetFieldByNameValue(obj, name, val);
162 }
163
ValueAPISetFieldByNameFloat(EtsObject * obj,EtsString * name,EtsFloat val)164 void ValueAPISetFieldByNameFloat(EtsObject *obj, EtsString *name, EtsFloat val)
165 {
166 SetFieldByNameValue(obj, name, val);
167 }
168
ValueAPISetFieldByNameDouble(EtsObject * obj,EtsString * name,EtsDouble val)169 void ValueAPISetFieldByNameDouble(EtsObject *obj, EtsString *name, EtsDouble val)
170 {
171 SetFieldByNameValue(obj, name, val);
172 }
173
ValueAPIGetFieldObject(EtsObject * obj,EtsLong i)174 EtsObject *ValueAPIGetFieldObject(EtsObject *obj, EtsLong i)
175 {
176 auto coroutine = EtsCoroutine::GetCurrent();
177 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
178 VMHandle<EtsObject> objHandle(coroutine, obj->GetCoreType());
179
180 auto typeClass = objHandle.GetPtr()->GetClass();
181 auto fieldObject = typeClass->GetFieldByIndex(i);
182 return objHandle.GetPtr()->GetFieldObject(fieldObject);
183 }
184
185 template <typename T>
GetFieldValue(EtsObject * obj,EtsLong i)186 T GetFieldValue(EtsObject *obj, EtsLong i)
187 {
188 auto coroutine = EtsCoroutine::GetCurrent();
189 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
190 VMHandle<EtsObject> objHandle(coroutine, obj->GetCoreType());
191
192 auto typeClass = objHandle.GetPtr()->GetClass();
193 auto fieldObject = typeClass->GetFieldByIndex(i);
194 if (fieldObject->GetType()->IsBoxed()) {
195 return EtsBoxPrimitive<T>::FromCoreType(objHandle.GetPtr()->GetFieldObject(fieldObject))->GetValue();
196 }
197 return objHandle.GetPtr()->GetFieldPrimitive<T>(fieldObject);
198 }
199
ValueAPIGetFieldBoolean(EtsObject * obj,EtsLong i)200 EtsBoolean ValueAPIGetFieldBoolean(EtsObject *obj, EtsLong i)
201 {
202 return GetFieldValue<EtsBoolean>(obj, i);
203 }
204
ValueAPIGetFieldByte(EtsObject * obj,EtsLong i)205 EtsByte ValueAPIGetFieldByte(EtsObject *obj, EtsLong i)
206 {
207 return GetFieldValue<EtsByte>(obj, i);
208 }
209
ValueAPIGetFieldShort(EtsObject * obj,EtsLong i)210 EtsShort ValueAPIGetFieldShort(EtsObject *obj, EtsLong i)
211 {
212 return GetFieldValue<EtsShort>(obj, i);
213 }
214
ValueAPIGetFieldChar(EtsObject * obj,EtsLong i)215 EtsChar ValueAPIGetFieldChar(EtsObject *obj, EtsLong i)
216 {
217 return GetFieldValue<EtsChar>(obj, i);
218 }
219
ValueAPIGetFieldInt(EtsObject * obj,EtsLong i)220 EtsInt ValueAPIGetFieldInt(EtsObject *obj, EtsLong i)
221 {
222 return GetFieldValue<EtsInt>(obj, i);
223 }
224
ValueAPIGetFieldLong(EtsObject * obj,EtsLong i)225 EtsLong ValueAPIGetFieldLong(EtsObject *obj, EtsLong i)
226 {
227 return GetFieldValue<EtsLong>(obj, i);
228 }
229
ValueAPIGetFieldFloat(EtsObject * obj,EtsLong i)230 EtsFloat ValueAPIGetFieldFloat(EtsObject *obj, EtsLong i)
231 {
232 return GetFieldValue<EtsFloat>(obj, i);
233 }
234
ValueAPIGetFieldDouble(EtsObject * obj,EtsLong i)235 EtsDouble ValueAPIGetFieldDouble(EtsObject *obj, EtsLong i)
236 {
237 return GetFieldValue<EtsDouble>(obj, i);
238 }
239
ValueAPIGetFieldByNameObject(EtsObject * obj,EtsString * name)240 EtsObject *ValueAPIGetFieldByNameObject(EtsObject *obj, EtsString *name)
241 {
242 auto coroutine = EtsCoroutine::GetCurrent();
243 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
244 VMHandle<EtsObject> objHandle(coroutine, obj->GetCoreType());
245
246 auto typeClass = objHandle.GetPtr()->GetClass();
247 auto fieldObject = typeClass->GetFieldIDByName(name->GetMutf8().c_str());
248 return objHandle.GetPtr()->GetFieldObject(fieldObject);
249 }
250
251 template <typename T>
GetFieldByNameValue(EtsObject * obj,EtsString * name)252 T GetFieldByNameValue(EtsObject *obj, EtsString *name)
253 {
254 auto coroutine = EtsCoroutine::GetCurrent();
255 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
256 VMHandle<EtsObject> objHandle(coroutine, obj->GetCoreType());
257
258 auto typeClass = objHandle.GetPtr()->GetClass();
259 auto fieldObject = typeClass->GetFieldIDByName(name->GetMutf8().c_str());
260 if (fieldObject->GetType()->IsBoxed()) {
261 return EtsBoxPrimitive<T>::FromCoreType(objHandle.GetPtr()->GetFieldObject(fieldObject))->GetValue();
262 }
263 return objHandle.GetPtr()->GetFieldPrimitive<T>(fieldObject);
264 }
265
ValueAPIGetFieldByNameBoolean(EtsObject * obj,EtsString * name)266 EtsBoolean ValueAPIGetFieldByNameBoolean(EtsObject *obj, EtsString *name)
267 {
268 return GetFieldByNameValue<EtsBoolean>(obj, name);
269 }
270
ValueAPIGetFieldByNameByte(EtsObject * obj,EtsString * name)271 EtsByte ValueAPIGetFieldByNameByte(EtsObject *obj, EtsString *name)
272 {
273 return GetFieldByNameValue<EtsByte>(obj, name);
274 }
275
ValueAPIGetFieldByNameShort(EtsObject * obj,EtsString * name)276 EtsShort ValueAPIGetFieldByNameShort(EtsObject *obj, EtsString *name)
277 {
278 return GetFieldByNameValue<EtsShort>(obj, name);
279 }
280
ValueAPIGetFieldByNameChar(EtsObject * obj,EtsString * name)281 EtsChar ValueAPIGetFieldByNameChar(EtsObject *obj, EtsString *name)
282 {
283 return GetFieldByNameValue<EtsChar>(obj, name);
284 }
285
ValueAPIGetFieldByNameInt(EtsObject * obj,EtsString * name)286 EtsInt ValueAPIGetFieldByNameInt(EtsObject *obj, EtsString *name)
287 {
288 return GetFieldByNameValue<EtsInt>(obj, name);
289 }
290
ValueAPIGetFieldByNameLong(EtsObject * obj,EtsString * name)291 EtsLong ValueAPIGetFieldByNameLong(EtsObject *obj, EtsString *name)
292 {
293 return GetFieldByNameValue<EtsLong>(obj, name);
294 }
295
ValueAPIGetFieldByNameFloat(EtsObject * obj,EtsString * name)296 EtsFloat ValueAPIGetFieldByNameFloat(EtsObject *obj, EtsString *name)
297 {
298 return GetFieldByNameValue<EtsFloat>(obj, name);
299 }
300
ValueAPIGetFieldByNameDouble(EtsObject * obj,EtsString * name)301 EtsDouble ValueAPIGetFieldByNameDouble(EtsObject *obj, EtsString *name)
302 {
303 return GetFieldByNameValue<EtsDouble>(obj, name);
304 }
305
ValueAPIGetArrayLength(EtsObject * obj)306 EtsLong ValueAPIGetArrayLength(EtsObject *obj)
307 {
308 auto coroutine = EtsCoroutine::GetCurrent();
309 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
310 VMHandle<EtsArray> arrHandle(coroutine, obj->GetCoreType());
311 return arrHandle->GetLength();
312 }
313
ValueAPISetElementObject(EtsObject * obj,EtsLong i,EtsObject * val)314 void ValueAPISetElementObject(EtsObject *obj, EtsLong i, EtsObject *val)
315 {
316 auto coroutine = EtsCoroutine::GetCurrent();
317 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
318 VMHandle<EtsObjectArray> arrHandle(coroutine, obj->GetCoreType());
319 VMHandle<EtsObject> valHandle(coroutine, val->GetCoreType());
320
321 arrHandle.GetPtr()->Set(i, valHandle.GetPtr());
322 }
323
324 template <typename P, typename T>
SetElement(EtsObject * obj,EtsLong i,T val)325 void SetElement(EtsObject *obj, EtsLong i, T val)
326 {
327 auto coroutine = EtsCoroutine::GetCurrent();
328 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
329 auto typeClass = obj->GetClass();
330 if (!typeClass->GetComponentType()->IsBoxed()) {
331 VMHandle<P> arrHandle(coroutine, obj->GetCoreType());
332 arrHandle.GetPtr()->Set(i, val);
333 } else {
334 VMHandle<EtsObjectArray> arrHandle(coroutine, obj->GetCoreType());
335 arrHandle.GetPtr()->Set(i, EtsBoxPrimitive<T>::Create(coroutine, val));
336 }
337 }
338
ValueAPISetElementBoolean(EtsObject * obj,EtsLong i,EtsBoolean val)339 void ValueAPISetElementBoolean(EtsObject *obj, EtsLong i, EtsBoolean val)
340 {
341 SetElement<EtsBooleanArray>(obj, i, val);
342 }
343
ValueAPISetElementByte(EtsObject * obj,EtsLong i,EtsByte val)344 void ValueAPISetElementByte(EtsObject *obj, EtsLong i, EtsByte val)
345 {
346 SetElement<EtsByteArray>(obj, i, val);
347 }
348
ValueAPISetElementShort(EtsObject * obj,EtsLong i,EtsShort val)349 void ValueAPISetElementShort(EtsObject *obj, EtsLong i, EtsShort val)
350 {
351 SetElement<EtsShortArray>(obj, i, val);
352 }
353
ValueAPISetElementChar(EtsObject * obj,EtsLong i,EtsChar val)354 void ValueAPISetElementChar(EtsObject *obj, EtsLong i, EtsChar val)
355 {
356 SetElement<EtsCharArray>(obj, i, val);
357 }
358
ValueAPISetElementInt(EtsObject * obj,EtsLong i,EtsInt val)359 void ValueAPISetElementInt(EtsObject *obj, EtsLong i, EtsInt val)
360 {
361 SetElement<EtsIntArray>(obj, i, val);
362 }
363
ValueAPISetElementLong(EtsObject * obj,EtsLong i,EtsLong val)364 void ValueAPISetElementLong(EtsObject *obj, EtsLong i, EtsLong val)
365 {
366 SetElement<EtsLongArray>(obj, i, val);
367 }
368
ValueAPISetElementFloat(EtsObject * obj,EtsLong i,EtsFloat val)369 void ValueAPISetElementFloat(EtsObject *obj, EtsLong i, EtsFloat val)
370 {
371 SetElement<EtsFloatArray>(obj, i, val);
372 }
373
ValueAPISetElementDouble(EtsObject * obj,EtsLong i,EtsDouble val)374 void ValueAPISetElementDouble(EtsObject *obj, EtsLong i, EtsDouble val)
375 {
376 SetElement<EtsDoubleArray>(obj, i, val);
377 }
378
ValueAPIGetElementObject(EtsObject * obj,EtsLong i)379 EtsObject *ValueAPIGetElementObject(EtsObject *obj, EtsLong i)
380 {
381 auto coroutine = EtsCoroutine::GetCurrent();
382 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
383 VMHandle<EtsObjectArray> arrHandle(coroutine, obj->GetCoreType());
384
385 return arrHandle.GetPtr()->Get(i);
386 }
387
388 template <typename P>
GetElement(EtsObject * obj,EtsLong i)389 typename P::ValueType GetElement(EtsObject *obj, EtsLong i)
390 {
391 auto coroutine = EtsCoroutine::GetCurrent();
392 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
393 auto typeClass = obj->GetClass();
394 if (!typeClass->GetComponentType()->IsBoxed()) {
395 VMHandle<P> arrHandle(coroutine, obj->GetCoreType());
396 return arrHandle.GetPtr()->Get(i);
397 }
398 VMHandle<EtsObjectArray> arrHandle(coroutine, obj->GetCoreType());
399 auto value = EtsBoxPrimitive<typename P::ValueType>::FromCoreType(arrHandle.GetPtr()->Get(i));
400 return value->GetValue();
401 }
402
ValueAPIGetElementBoolean(EtsObject * obj,EtsLong i)403 EtsBoolean ValueAPIGetElementBoolean(EtsObject *obj, EtsLong i)
404 {
405 return GetElement<EtsBooleanArray>(obj, i);
406 }
407
ValueAPIGetElementByte(EtsObject * obj,EtsLong i)408 EtsByte ValueAPIGetElementByte(EtsObject *obj, EtsLong i)
409 {
410 return GetElement<EtsByteArray>(obj, i);
411 }
412
ValueAPIGetElementShort(EtsObject * obj,EtsLong i)413 EtsShort ValueAPIGetElementShort(EtsObject *obj, EtsLong i)
414 {
415 return GetElement<EtsShortArray>(obj, i);
416 }
417
ValueAPIGetElementChar(EtsObject * obj,EtsLong i)418 EtsChar ValueAPIGetElementChar(EtsObject *obj, EtsLong i)
419 {
420 return GetElement<EtsCharArray>(obj, i);
421 }
422
ValueAPIGetElementInt(EtsObject * obj,EtsLong i)423 EtsInt ValueAPIGetElementInt(EtsObject *obj, EtsLong i)
424 {
425 return GetElement<EtsIntArray>(obj, i);
426 }
427
ValueAPIGetElementLong(EtsObject * obj,EtsLong i)428 EtsLong ValueAPIGetElementLong(EtsObject *obj, EtsLong i)
429 {
430 return GetElement<EtsLongArray>(obj, i);
431 }
432
ValueAPIGetElementFloat(EtsObject * obj,EtsLong i)433 EtsFloat ValueAPIGetElementFloat(EtsObject *obj, EtsLong i)
434 {
435 return GetElement<EtsFloatArray>(obj, i);
436 }
437
ValueAPIGetElementDouble(EtsObject * obj,EtsLong i)438 EtsDouble ValueAPIGetElementDouble(EtsObject *obj, EtsLong i)
439 {
440 return GetElement<EtsDoubleArray>(obj, i);
441 }
442
443 } // namespace ark::ets::intrinsics
444