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