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