1/*
2 * Copyright (c) 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#include "ecmascript/ic/ic_runtime_stub-inl.h"
17#include "ecmascript/interpreter/slow_runtime_stub.h"
18#include "ecmascript/base/builtins_base.h"
19#include "ecmascript/ic/ic_handler.h"
20#include "ecmascript/global_env.h"
21#include "ecmascript/js_array.h"
22#include "ecmascript/js_object.h"
23#include "ecmascript/js_tagged_value.h"
24#include "ecmascript/object_operator.h"
25#include "ecmascript/tests/test_helper.h"
26
27using namespace panda::ecmascript;
28using namespace panda::ecmascript::base;
29
30namespace panda::test {
31using InlinedPropsBit = HandlerBase::InlinedPropsBit;
32using OffsetBit = HandlerBase::OffsetBit;
33using KindBit = HandlerBase::KindBit;
34using IsJSArrayBit = HandlerBase::IsJSArrayBit;
35using HandlerKind = HandlerBase::HandlerKind;
36using AccessorBit = HandlerBase::AccessorBit;
37class ICRuntimeStubTest : public testing::Test {
38public:
39    static void SetUpTestCase()
40    {
41        GTEST_LOG_(INFO) << "SetUpTestCase";
42    }
43
44    static void TearDownTestCase()
45    {
46        GTEST_LOG_(INFO) << "TearDownCase";
47    }
48
49    void SetUp() override
50    {
51        TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
52    }
53
54    void TearDown() override
55    {
56        TestHelper::DestroyEcmaVMWithScope(instance, scope);
57    }
58
59    EcmaVM *instance {nullptr};
60    EcmaHandleScope *scope {nullptr};
61    JSThread *thread {nullptr};
62};
63
64HWTEST_F_L0(ICRuntimeStubTest, LoadGlobalICByName)
65{
66    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
67    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
68    JSHandle<JSTaggedValue> objFun = env->GetArrayFunction();
69
70    JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(2));
71    JSHandle<JSTaggedValue> globalValue(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
72    JSHandle<PropertyBox> handleBoxValue = factory->NewPropertyBox(handleValue);
73    JSHandle<JSTaggedValue> propKey(factory->NewFromASCII("x"));
74
75    uint32_t arrayLength = 2U;
76    JSHandle<TaggedArray> handleTaggedArray = factory->NewTaggedArray(arrayLength);
77    handleTaggedArray->Set(thread, 0, handleBoxValue.GetTaggedValue());
78    handleTaggedArray->Set(thread, 1, JSTaggedValue::Undefined());
79    JSHandle<ProfileTypeInfo> handleProfileTypeInfo = JSHandle<ProfileTypeInfo>::Cast(handleTaggedArray);
80    // ProfileTypeInfo get value is HeapObject and then call LoadGlobal function to load
81    JSTaggedValue resultValue1 =
82        ICRuntimeStub::LoadGlobalICByName(thread, *handleProfileTypeInfo,
83                                          JSTaggedValue::Undefined(), JSTaggedValue::Undefined(), 0, true);
84    EXPECT_EQ(resultValue1.GetInt(), 2);
85    // the globalValue is jsobject then call loadMiss function can find global variable from global record firstly
86    // so need store global record.
87    SlowRuntimeStub::StGlobalRecord(thread, propKey.GetTaggedValue(), handleValue.GetTaggedValue(), false);
88    JSTaggedValue resultValue2 =
89        ICRuntimeStub::LoadGlobalICByName(thread, *handleProfileTypeInfo,
90                                          globalValue.GetTaggedValue(), propKey.GetTaggedValue(), 1, true);
91    EXPECT_EQ(resultValue2.GetInt(), 2);
92    EXPECT_TRUE(handleProfileTypeInfo->Get(1).IsPropertyBox());
93}
94
95HWTEST_F_L0(ICRuntimeStubTest, StoreGlobalICByName)
96{
97    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
98    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
99    JSHandle<JSTaggedValue> objFun = env->GetArrayFunction();
100    JSHandle<PropertyBox> handleBoxValue =
101        factory->NewPropertyBox(JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
102    JSHandle<JSTaggedValue> propKey(factory->NewFromASCII("x"));
103    JSHandle<JSTaggedValue> globalValue(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
104    JSTaggedValue handleValue(2);
105
106    uint32_t arrayLength = 2U; // 2 means ProfileTypeInfo length
107    JSHandle<TaggedArray> handleTaggedArray = factory->NewTaggedArray(arrayLength);
108    handleTaggedArray->Set(thread, 0, handleBoxValue.GetTaggedValue());
109    handleTaggedArray->Set(thread, 1, JSTaggedValue::Undefined());
110    JSHandle<ProfileTypeInfo> handleProfileTypeInfo = JSHandle<ProfileTypeInfo>::Cast(handleTaggedArray);
111    // ProfileTypeInfo get value is HeapObject and then call LoadGlobal function to load
112    JSTaggedValue resultValue1 =
113        ICRuntimeStub::StoreGlobalICByName(thread, *handleProfileTypeInfo, JSTaggedValue::Undefined(),
114                                           JSTaggedValue::Undefined(), handleValue, 0, true);
115    EXPECT_TRUE(resultValue1.IsUndefined());
116    EXPECT_EQ(handleBoxValue->GetValue().GetInt(), 2);
117    // the globalValue is jsobject then call storeMiss function can find global variable from global record firstly
118    // so need store global record.
119    SlowRuntimeStub::StGlobalRecord(thread, propKey.GetTaggedValue(), handleBoxValue.GetTaggedValue(), false);
120    JSTaggedValue resultValue2 =
121        ICRuntimeStub::StoreGlobalICByName(thread, *handleProfileTypeInfo, globalValue.GetTaggedValue(),
122                                           propKey.GetTaggedValue(), handleValue, 1, true);
123    EXPECT_TRUE(resultValue2.IsUndefined());
124    EXPECT_TRUE(handleProfileTypeInfo->Get(1).IsPropertyBox());
125}
126
127HWTEST_F_L0(ICRuntimeStubTest, CheckPolyHClass)
128{
129    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
130    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
131    JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue::Undefined());
132    JSHandle<PropertyBox> handlePropertyBox = factory->NewPropertyBox(handleValue);
133    JSHandle<EcmaString> handleEmptyStr = factory->GetEmptyString();
134    JSHandle<TaggedArray> handleCacheArray = factory->NewTaggedArray(5); // 5 : 5 array length
135
136    JSHandle<JSTaggedValue> objFun = env->GetArrayFunction();
137    JSHandle<JSTaggedValue> handleObj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
138    TaggedObject *handleTaggedObj = handleObj->GetTaggedObject();
139    JSTaggedValue handleTaggedObjVal(handleTaggedObj);
140    handleTaggedObjVal.CreateWeakRef();
141    TaggedObject *handleWeakObj = TaggedObject::Cast(handleTaggedObjVal.GetWeakReferent());
142    JSHClass *handleObjClass = static_cast<JSHClass *>(handleWeakObj);
143
144    handleCacheArray->Set(thread, 0, JSTaggedValue::Undefined()); // 0 : 0 set value in zero
145    handleCacheArray->Set(thread, 1, JSTaggedValue::Undefined()); // 1 : 1 set value in one
146    handleCacheArray->Set(thread, 2, handleTaggedObjVal); // 2 : 2 set weakvalue in two
147    handleCacheArray->Set(thread, 3, handlePropertyBox.GetTaggedValue()); // 3 : 3 set value in three
148    handleCacheArray->Set(thread, 4, handleEmptyStr.GetTaggedValue()); // 4 : 4 set value in four
149    JSTaggedValue handleWeakCacheValue(handleCacheArray.GetTaggedValue());
150
151    JSTaggedValue resultValue = ICRuntimeStub::CheckPolyHClass(handleWeakCacheValue, handleObjClass);
152    EXPECT_TRUE(resultValue.IsPropertyBox());
153}
154
155HWTEST_F_L0(ICRuntimeStubTest, StoreICAndLoadIC_ByName)
156{
157    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
158    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
159
160    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
161    JSHandle<JSTaggedValue> handleObj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
162    JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
163    JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(1));
164    JSHandle<JSTaggedValue> handleStoreVal(thread, JSTaggedValue(2));
165
166    uint32_t arrayLength = 1U;
167    JSHandle<TaggedArray> handleTaggedArray = factory->NewTaggedArray(arrayLength);
168    JSHandle<ProfileTypeInfo> handleProfileTypeInfo = JSHandle<ProfileTypeInfo>::Cast(handleTaggedArray);
169
170    // test receiver is jsobject and ProfileTypeInfo get value is hole in slotId.
171    ICRuntimeStub::StoreICByName(thread, *handleProfileTypeInfo, handleObj.GetTaggedValue(),
172                                 handleKey.GetTaggedValue(), handleStoreVal.GetTaggedValue(), 0);
173    JSTaggedValue resultValue =
174        ICRuntimeStub::LoadICByName(thread, *handleProfileTypeInfo, handleObj.GetTaggedValue(),
175                                    handleKey.GetTaggedValue(), 0);
176    EXPECT_EQ(resultValue.GetInt(), 2);
177}
178
179HWTEST_F_L0(ICRuntimeStubTest, StoreICAndLoadIC_ByValue)
180{
181    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
182    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
183
184    JSHandle<JSTaggedValue> typeArrayFun = env->GetInt8ArrayFunction();
185    JSHandle<JSTypedArray> handleTypeArrReceiver = JSHandle<JSTypedArray>::Cast(
186        factory->NewJSObjectByConstructor(JSHandle<JSFunction>(typeArrayFun), typeArrayFun));
187    JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
188    JSHandle<JSTaggedValue> handleStoreVal(factory->NewFromASCII("1"));
189
190    uint32_t arrayLength = 2U; // 2 means ProfileTypeInfo length
191    JSHandle<TaggedArray> handleTaggedArray = factory->NewTaggedArray(arrayLength);
192    JSHandle<ProfileTypeInfo> handleProfileTypeInfo = JSHandle<ProfileTypeInfo>::Cast(handleTaggedArray);
193    // test receiver is typedArray
194    ICRuntimeStub::StoreICByValue(thread, *handleProfileTypeInfo, handleTypeArrReceiver.GetTaggedValue(),
195                                 handleKey.GetTaggedValue(), handleStoreVal.GetTaggedValue(), 0);
196    JSTaggedValue resultValue =
197        ICRuntimeStub::LoadICByValue(thread, *handleProfileTypeInfo, handleTypeArrReceiver.GetTaggedValue(),
198                                     handleKey.GetTaggedValue(), 0);
199    EXPECT_TRUE(resultValue.IsString());
200    JSHandle<EcmaString> handleEcmaStrTo(JSHandle<JSTaggedValue>(thread, resultValue));
201    EXPECT_STREQ("1", EcmaStringAccessor(handleEcmaStrTo).ToCString().c_str());
202}
203
204HWTEST_F_L0(ICRuntimeStubTest, TryStoreICAndLoadIC_ByName)
205{
206    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
207    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
208
209    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
210    JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
211    JSTaggedValue handleFirstObjClassVal(handleObj->GetClass());
212    TaggedObject *handleTaggedObject = handleFirstObjClassVal.GetWeakReferentUnChecked();
213    JSHClass *handleNewObjClass = static_cast<JSHClass *>(handleTaggedObject);
214    JSHandle<JSObject> handleNewObj = factory->NewJSObject(JSHandle<JSHClass>(thread, handleNewObjClass));
215
216    JSHandle<TaggedArray> handleArr = factory->NewTaggedArray(1);
217    handleArr->Set(thread, 0, JSTaggedValue::Undefined());
218    JSHandle<JSTaggedValue> handleBoxValue(thread, JSTaggedValue::Undefined());
219    JSHandle<JSTaggedValue> handlerPropertyBoxVal(factory->NewPropertyBox(handleBoxValue));
220
221    JSTaggedValue handleFirstArrVal(handleArr.GetTaggedValue());
222    JSTaggedValue handleSecondPropertyBoxVal = handlerPropertyBoxVal.GetTaggedValue();
223    JSTaggedValue handleReceiver = handleNewObj.GetTaggedValue();
224    JSTaggedValue handleStoreVal(2);
225
226    // fistValue GetWeakReferentUnChecked is equal the receiver class
227    ICRuntimeStub::TryStoreICByName(thread, handleReceiver, handleFirstObjClassVal,
228                                                            handleSecondPropertyBoxVal, handleStoreVal);
229    JSTaggedValue resultValue1 = ICRuntimeStub::TryLoadICByName(thread, handleReceiver, handleFirstObjClassVal,
230                                                                handleSecondPropertyBoxVal);
231    EXPECT_EQ(resultValue1.GetInt(), handleStoreVal.GetInt());
232    // fistValue GetWeakReferent is not equal the receiver class
233    ICRuntimeStub::TryStoreICByName(thread, handleObj.GetTaggedValue(), handleFirstArrVal,
234                                                            handleSecondPropertyBoxVal, handleStoreVal);
235    JSTaggedValue resultValue2 = ICRuntimeStub::TryLoadICByName(thread, handleObj.GetTaggedValue(),
236                                                                handleFirstArrVal, handleSecondPropertyBoxVal);
237    EXPECT_TRUE(resultValue2.IsHole());
238    // receiver is number
239    int a = 32;
240    JSHandle<JSTaggedValue> numReceiver(thread, JSTaggedValue(a));
241    JSHandle<JSTaggedValue> receiver =
242        JSHandle<JSTaggedValue>::Cast(factory->NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_NUMBER, numReceiver));
243    JSHandle<JSHClass> hclass(thread, receiver->GetTaggedObject()->GetClass());
244    JSHandle<JSTaggedValue> key = thread->GlobalConstants()->GetHandledValueOfString();
245    ObjectOperator op(thread, numReceiver, key);
246    JSHandle<JSTaggedValue> handlerValue = PrototypeHandler::LoadPrototype(thread, op, hclass);
247    JSTaggedValue resultValue3 = ICRuntimeStub::TryLoadICByName(thread, numReceiver.GetTaggedValue(),
248        hclass.GetTaggedValue(), handlerValue.GetTaggedValue());
249    EXPECT_EQ(op.GetValue(), resultValue3);
250}
251
252HWTEST_F_L0(ICRuntimeStubTest, TryStoreICAndLoadIC_ByValue1)
253{
254    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
255    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
256
257    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
258    JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
259    JSTaggedValue handleObjClassVal(handleObj->GetClass());
260    TaggedObject *handleTaggedObject = handleObjClassVal.GetWeakReferentUnChecked();
261    JSHClass *handleNewObjClass = static_cast<JSHClass *>(handleTaggedObject);
262
263    JSHandle<JSObject> handleNewObj = factory->NewJSObject(JSHandle<JSHClass>(thread, handleNewObjClass));
264    JSHandle<TaggedArray> handleTaggedArray = factory->NewTaggedArray(1);
265    handleNewObj->SetElements(thread, handleTaggedArray.GetTaggedValue());
266
267    uint32_t handler = 0U;
268    KindBit::Set<uint32_t>(HandlerKind::ELEMENT, &handler);
269    JSTaggedValue handleFirstVal(handleTaggedObject);
270    JSTaggedValue handleSecondHandlerVal(handler);
271    JSTaggedValue handleReceiver = handleNewObj.GetTaggedValue();
272    JSTaggedValue handleStoreVal(2);
273
274    // fistValue GetWeakReferentUnChecked is equal the receiver class
275    ICRuntimeStub::TryStoreICByValue(thread, handleReceiver, JSTaggedValue(0),
276                                     handleFirstVal, handleSecondHandlerVal, handleStoreVal);
277    JSTaggedValue resultValue = ICRuntimeStub::TryLoadICByValue(thread, handleReceiver, JSTaggedValue(0),
278                                                                handleFirstVal, handleSecondHandlerVal);
279    EXPECT_EQ(resultValue.GetInt(), handleStoreVal.GetInt());
280}
281
282HWTEST_F_L0(ICRuntimeStubTest, TryStoreICAndLoadIC_ByValue2)
283{
284    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
285    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
286
287    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
288    JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
289    JSTaggedValue handleObjClassVal(handleObj->GetClass());
290    handleObjClassVal.CreateWeakRef();
291    TaggedObject *handleTaggedObject = TaggedObject::Cast(handleObjClassVal.GetWeakReferent());
292    JSHClass *handleNewObjClass = static_cast<JSHClass *>(handleTaggedObject);
293    JSHandle<TaggedArray> handleTypeArr = factory->NewTaggedArray(1);
294    JSHandle<JSObject> handleNewObj = factory->NewJSObject(JSHandle<JSHClass>(thread, handleNewObjClass));
295    handleNewObj->SetProperties(thread, handleTypeArr.GetTaggedValue());
296
297    uint32_t handler = 0U;
298    KindBit::Set<uint32_t>(HandlerKind::FIELD, &handler);
299    JSHandle<TaggedArray> handleSecondValArr = factory->NewTaggedArray(2);
300    handleSecondValArr->Set(thread, 0, handleObjClassVal);
301    handleSecondValArr->Set(thread, 1, JSTaggedValue(handler));
302    JSTaggedValue handleReceiver = handleNewObj.GetTaggedValue();
303    JSTaggedValue handleSecondArrVal = handleSecondValArr.GetTaggedValue();
304    JSTaggedValue handleStoreVal(2);
305
306    // fistvalue is equal the key value.
307    ICRuntimeStub::TryStoreICByValue(thread, handleReceiver, JSTaggedValue(0),
308                                     JSTaggedValue(0), handleSecondArrVal, handleStoreVal);
309    JSTaggedValue resultValue = ICRuntimeStub::TryLoadICByValue(thread, handleReceiver, JSTaggedValue(0),
310                                                                JSTaggedValue(0), handleSecondArrVal);
311    EXPECT_EQ(resultValue.GetInt(), handleStoreVal.GetInt());
312}
313
314JSTaggedValue TestSetter(EcmaRuntimeCallInfo *argv)
315{
316    // 2 : 2 arg value
317    if (argv->GetArgsNumber() == 1 && argv->GetCallArg(0).GetTaggedValue() == JSTaggedValue(2)) {
318        JSThread *thread = argv->GetThread();
319        ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
320        JSHandle<JSObject> obj(BuiltinsBase::GetThis(argv));
321        JSHandle<JSTaggedValue> keyHandle(factory->NewFromASCII("key"));
322        JSHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue(2)); // 2 : 2 property value
323        JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), keyHandle, valueHandle);
324        return JSTaggedValue(JSTaggedValue::True());
325    }
326    return JSTaggedValue(JSTaggedValue::False());
327}
328
329HWTEST_F_L0(ICRuntimeStubTest, StoreICWithHandler)
330{
331    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
332    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
333    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
334
335    JSHandle<JSTaggedValue> keyHandle(factory->NewFromASCII("key"));
336    JSHandle<PropertyBox> boxHandler = factory->NewPropertyBox(keyHandle);
337    JSHandle<JSFunction> setter = factory->NewJSFunction(env, reinterpret_cast<void *>(TestSetter));
338    JSHandle<AccessorData> handleAccessor = factory->NewAccessorData();
339    handleAccessor->SetSetter(thread, setter.GetTaggedValue());
340
341    uint32_t handler = 0U;
342    uint32_t bitOffset = 1U;
343    OffsetBit::Set<uint32_t>(bitOffset, &handler);
344    AccessorBit::Set<uint32_t>(true, &handler);
345
346    uint32_t arrayLength = bitOffset + 1U;
347    JSHandle<JSObject> handleHolder = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
348    JSHandle<TaggedArray> handleTaggedArr = factory->NewTaggedArray(arrayLength);
349    handleTaggedArr->Set(thread, bitOffset, handleAccessor.GetTaggedValue());
350    handleHolder->SetProperties(thread, handleTaggedArr.GetTaggedValue());
351    JSHandle<JSObject> handleReceiver = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
352
353    // handler is Init and HandlerBase Is Accessor,then call CallSetter function.
354    JSTaggedValue resultValue1 =
355        ICRuntimeStub::StoreICWithHandler(thread, handleReceiver.GetTaggedValue(),
356                                          handleHolder.GetTaggedValue(), JSTaggedValue(2), JSTaggedValue(handler));
357    EXPECT_TRUE(resultValue1.IsUndefined());
358    EXPECT_EQ(JSObject::GetProperty(thread,
359                                    JSHandle<JSTaggedValue>(handleReceiver), keyHandle).GetValue()->GetInt(), 2);
360    // handler is PropertyBox and then call StoreGlobal function.
361    JSTaggedValue resultValue2 =
362        ICRuntimeStub::StoreICWithHandler(thread, handleReceiver.GetTaggedValue(),
363                                          handleHolder.GetTaggedValue(), JSTaggedValue(2), boxHandler.GetTaggedValue());
364    EXPECT_TRUE(resultValue2.IsUndefined());
365    EXPECT_EQ(ICRuntimeStub::LoadGlobal(boxHandler.GetTaggedValue()).GetInt(), 2);
366    // HandlerBase Is NonExist and This situation is not judged.
367    KindBit::Set<uint32_t>(HandlerKind::NON_EXIST, &handler);
368    JSTaggedValue resultValue3 =
369        ICRuntimeStub::StoreICWithHandler(thread, handleReceiver.GetTaggedValue(),
370                                          handleHolder.GetTaggedValue(), JSTaggedValue(2), JSTaggedValue(handler));
371    EXPECT_TRUE(resultValue3.IsUndefined());
372}
373
374JSTaggedValue TestGetter(EcmaRuntimeCallInfo *argv)
375{
376    auto thread = argv->GetThread();
377    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
378    JSHandle<JSObject> obj(BuiltinsBase::GetThis(argv));
379    JSHandle<JSTaggedValue> keyHandle(factory->NewFromASCII("key"));
380    JSTaggedValue value =
381        JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), keyHandle).GetValue().GetTaggedValue();
382
383    return JSTaggedValue(value.GetInt());
384}
385
386HWTEST_F_L0(ICRuntimeStubTest, LoadICWithHandler)
387{
388    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
389    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
390    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
391
392    JSHandle<JSTaggedValue> keyHandle(factory->NewFromASCII("key"));
393    JSHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue(1));
394    JSHandle<PropertyBox> boxHandler = factory->NewPropertyBox(keyHandle);
395    JSHandle<JSFunction> getter = factory->NewJSFunction(env, reinterpret_cast<void *>(TestGetter));
396    JSHandle<AccessorData> handleAccessor = factory->NewAccessorData();
397    handleAccessor->SetGetter(thread, getter.GetTaggedValue());
398
399    uint32_t handler = 0U;
400    uint32_t bitOffset = 1U;
401    OffsetBit::Set<uint32_t>(bitOffset, &handler);
402    AccessorBit::Set<uint32_t>(true, &handler);
403
404    uint32_t arrayLength = bitOffset + 1U;
405    JSHandle<JSObject> handleHolder = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
406    JSHandle<TaggedArray> handleTaggedArr = factory->NewTaggedArray(arrayLength);
407    handleTaggedArr->Set(thread, bitOffset, handleAccessor.GetTaggedValue());
408    handleHolder->SetProperties(thread, handleTaggedArr.GetTaggedValue());
409    JSHandle<JSObject> handleReceiver = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
410    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handleReceiver), keyHandle, valueHandle);
411    // handler is Init and HandlerBase Is Accessor,then call CallGetter function.
412    JSTaggedValue resultValue1 =
413        ICRuntimeStub::LoadICWithHandler(thread, handleReceiver.GetTaggedValue(),
414                                         handleHolder.GetTaggedValue(), JSTaggedValue(handler));
415    EXPECT_EQ(resultValue1.GetInt(), 1);
416    // HandlerBase Is NonExist and This situation is not judged.
417    KindBit::Set<uint32_t>(HandlerKind::NON_EXIST, &handler);
418    JSTaggedValue resultValue3 =
419        ICRuntimeStub::LoadICWithHandler(thread, handleReceiver.GetTaggedValue(),
420                                         handleHolder.GetTaggedValue(), JSTaggedValue(handler));
421    EXPECT_TRUE(resultValue3.IsUndefined());
422    // handler is PropertyBox and then call LoadGlobal function.
423    JSTaggedValue resultValue4 =
424        ICRuntimeStub::LoadICWithHandler(thread, handleReceiver.GetTaggedValue(),
425                                         handleHolder.GetTaggedValue(), boxHandler.GetTaggedValue());
426    EXPECT_TRUE(resultValue4.IsString());
427}
428
429HWTEST_F_L0(ICRuntimeStubTest, Prototype_StoreAndLoad)
430{
431    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
432    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
433    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
434
435    JSHandle<ProtoChangeMarker> cellValue = factory->NewProtoChangeMarker();
436    EXPECT_TRUE(!cellValue->GetHasChanged());
437
438    uint32_t handler = 0U;
439    uint32_t bitOffset = 1U;
440    OffsetBit::Set<uint32_t>(bitOffset, &handler);
441    KindBit::Set<uint32_t>(HandlerKind::FIELD, &handler); // test filed
442
443    uint32_t arrayLength = bitOffset + 1U;
444    JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
445    JSHandle<TaggedArray> handleTaggedArr = factory->NewTaggedArray(arrayLength);
446    handleObj->SetProperties(thread, handleTaggedArr.GetTaggedValue());
447
448    JSHandle<PrototypeHandler> handleProtoHandler = factory->NewPrototypeHandler();
449    handleProtoHandler->SetProtoCell(thread, cellValue.GetTaggedValue());
450    handleProtoHandler->SetHandlerInfo(thread, JSTaggedValue(handler));
451    handleProtoHandler->SetHolder(thread, handleObj.GetTaggedValue());
452    // test storePrototype function
453    JSTaggedValue resultValue1 = ICRuntimeStub::StorePrototype(thread, handleObj.GetTaggedValue(),
454                                                              JSTaggedValue(1), handleProtoHandler.GetTaggedValue());
455    EXPECT_TRUE(resultValue1.IsUndefined());
456    // test loadPrototype function
457    JSTaggedValue resultValue2 =
458        ICRuntimeStub::LoadPrototype(thread, handleObj.GetTaggedValue(), handleProtoHandler.GetTaggedValue());
459    EXPECT_EQ(ICRuntimeStub::LoadFromField(*handleObj, handler).GetInt(), resultValue2.GetInt());
460}
461
462HWTEST_F_L0(ICRuntimeStubTest, StoreWithTransition_In_Filed)
463{
464    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
465    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
466    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
467    JSHandle<JSTaggedValue> arrFun = env->GetArrayFunction();
468    JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
469    JSHandle<JSHClass> originHClass(thread, handleObj->GetJSHClass());
470    JSHandle<JSObject> handleArrObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(arrFun), arrFun);
471    auto hclass = handleArrObj->SynchronizedGetClass();
472
473    uint32_t handler = 0U;
474    uint32_t bitOffset = 1U;
475    OffsetBit::Set<uint32_t>(bitOffset, &handler);
476    KindBit::Set<uint32_t>(HandlerKind::FIELD, &handler);
477
478    uint32_t arrayLength = bitOffset + 1U;
479    JSHandle<TaggedArray> handleTaggedArr = factory->NewTaggedArray(arrayLength);
480    handleObj->SetProperties(thread, handleTaggedArr.GetTaggedValue());
481
482    JSHandle<TransitionHandler> handleTranHandler = factory->NewTransitionHandler();
483    handleTranHandler->SetTransitionHClass(thread, JSTaggedValue(hclass));
484    handleTranHandler->SetHandlerInfo(thread, JSTaggedValue(handler));
485
486    // test handler is InlinedProps and store in filed
487    InlinedPropsBit::Set<uint32_t>(true, &handler);
488    ICRuntimeStub::StoreWithTransition(thread, *handleObj, JSTaggedValue(2), handleTranHandler.GetTaggedValue());
489    auto resultArray = TaggedArray::Cast(handleObj->GetProperties().GetTaggedObject());
490    EXPECT_EQ(resultArray->Get(bitOffset).GetInt(), 2);
491    handleObj->SynchronizedSetClass(thread, *originHClass);
492}
493
494HWTEST_F_L0(ICRuntimeStubTest, Field_StoreAndLoad)
495{
496    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
497    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
498    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
499
500    uint32_t handler = 0U;
501    uint32_t bitOffset = 2U;
502    OffsetBit::Set<uint32_t>(bitOffset, &handler);
503
504    uint32_t arrayLength = bitOffset + 1U;
505    JSHandle<TaggedArray> handleTaggedArr = factory->NewTaggedArray(arrayLength);
506    handleTaggedArr->Set(thread, bitOffset, JSTaggedValue::Undefined());
507
508    JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
509    handleObj->SetProperties(thread, handleTaggedArr.GetTaggedValue());
510    // test handler is not InlinedProps
511    ICRuntimeStub::StoreField(thread, *handleObj, JSTaggedValue(3), handler);
512    JSTaggedValue resultValue1 = ICRuntimeStub::LoadFromField(*handleObj, handler);
513    EXPECT_EQ(resultValue1.GetInt(), 3);
514    // test handler is InlinedProps
515    InlinedPropsBit::Set<uint32_t>(true, &handler);
516    ICRuntimeStub::StoreField(thread, *handleObj, JSTaggedValue(2), handler);
517    JSTaggedValue resultValue = ICRuntimeStub::LoadFromField(*handleObj, handler);
518    EXPECT_EQ(resultValue.GetInt(), 2);
519}
520
521HWTEST_F_L0(ICRuntimeStubTest, Global_StoreAndLoad)
522{
523    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
524    JSHandle<JSTaggedValue> handleUndefinedVal(thread, JSTaggedValue::Undefined());
525    JSHandle<PropertyBox> handlerValue = factory->NewPropertyBox(handleUndefinedVal);
526
527    JSTaggedValue resultValue1 = ICRuntimeStub::StoreGlobal(thread, JSTaggedValue(2), handlerValue.GetTaggedValue());
528    EXPECT_TRUE(resultValue1.IsUndefined());
529    JSTaggedValue resultValue2 = ICRuntimeStub::LoadGlobal(handlerValue.GetTaggedValue());
530    EXPECT_EQ(resultValue2.GetInt(), 2);
531
532    handlerValue->Clear(thread);
533    JSTaggedValue resultValue3 = ICRuntimeStub::StoreGlobal(thread, JSTaggedValue(3), handlerValue.GetTaggedValue());
534    EXPECT_TRUE(resultValue3.IsHole());
535
536    JSTaggedValue resultValue4 = ICRuntimeStub::LoadGlobal(handlerValue.GetTaggedValue());
537    EXPECT_TRUE(resultValue4.IsHole());
538}
539
540HWTEST_F_L0(ICRuntimeStubTest, Element_StoreAndLoad)
541{
542    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
543    JSHandle<JSTaggedValue> lengthKey = thread->GlobalConstants()->GetHandledLengthString();
544    JSTaggedValue hanldeIntKey(4);
545
546    uint32_t handlerInfo = 0U;
547    KindBit::Set<uint32_t>(HandlerKind::ELEMENT, &handlerInfo);
548    IsJSArrayBit::Set<uint32_t>(true, &handlerInfo);
549
550    uint32_t arrayLength = 3U;
551    JSArray *handleArr = JSArray::ArrayCreate(thread, JSTaggedNumber(arrayLength)).GetObject<JSArray>();
552    JSHandle<JSObject> handleArrObj(thread, handleArr);
553    JSHandle<TaggedArray> handleTaggedArr = factory->NewTaggedArray(arrayLength);
554    handleArrObj->SetProperties(thread, handleTaggedArr.GetTaggedValue());
555
556    JSTaggedValue resultValue =
557        ICRuntimeStub::StoreElement(thread, *handleArrObj, hanldeIntKey, JSTaggedValue(3), JSTaggedValue(handlerInfo));
558
559    EXPECT_TRUE(resultValue.IsUndefined());
560    EXPECT_EQ(ICRuntimeStub::LoadElement(*handleArrObj, hanldeIntKey).GetInt(), 3);
561    EXPECT_EQ(JSObject::GetProperty(thread, handleArrObj, lengthKey).GetValue()->GetInt(), 5);
562    EXPECT_TRUE(ICRuntimeStub::LoadElement(*handleArrObj, JSTaggedValue(2)).IsHole());
563}
564
565HWTEST_F_L0(ICRuntimeStubTest, TryToElementsIndex)
566{
567    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
568
569    JSTaggedValue hanldeIntKey1(0);
570    JSTaggedValue hanldeIntKey2(1);
571    JSTaggedValue handleDoubleKey1(1.00);
572    JSTaggedValue handleDoubleKey2(1.11);
573    JSHandle<JSTaggedValue> handleStrKey1(factory->NewFromASCII("1234"));
574    JSHandle<JSTaggedValue> handleStrKey2(factory->NewFromASCII("xy"));
575
576    EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(hanldeIntKey1), 0);
577    EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(hanldeIntKey2), 1);
578    EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(handleDoubleKey1), 1);
579    EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(handleDoubleKey2), -1);
580    EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(handleStrKey1.GetTaggedValue()), 1234);
581    EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(handleStrKey2.GetTaggedValue()), -1);
582}
583} // namespace panda::test
584