• 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/object_operator.h"
25 #include "ecmascript/tests/test_helper.h"
26 
27 using namespace panda::ecmascript;
28 using namespace panda::ecmascript::base;
29 
30 namespace panda::test {
31 using InlinedPropsBit = HandlerBase::InlinedPropsBit;
32 using OffsetBit = HandlerBase::OffsetBit;
33 using KindBit = HandlerBase::KindBit;
34 using IsJSArrayBit = HandlerBase::IsJSArrayBit;
35 using HandlerKind = HandlerBase::HandlerKind;
36 using AccessorBit = HandlerBase::AccessorBit;
37 class ICRuntimeStubTest : public testing::Test {
38 public:
SetUpTestCase()39     static void SetUpTestCase()
40     {
41         GTEST_LOG_(INFO) << "SetUpTestCase";
42     }
43 
TearDownTestCase()44     static void TearDownTestCase()
45     {
46         GTEST_LOG_(INFO) << "TearDownCase";
47     }
48 
SetUp()49     void SetUp() override
50     {
51         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
52     }
53 
TearDown()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 
HWTEST_F_L0(ICRuntimeStubTest,LoadGlobalICByName)64 HWTEST_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 
HWTEST_F_L0(ICRuntimeStubTest,StoreGlobalICByName)95 HWTEST_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 
HWTEST_F_L0(ICRuntimeStubTest,CheckPolyHClass)127 HWTEST_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 
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 = 2U;
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     // 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 
HWTEST_F_L0(ICRuntimeStubTest,TryStoreICAndLoadIC_ByValue1)252 HWTEST_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 
HWTEST_F_L0(ICRuntimeStubTest,TryStoreICAndLoadIC_ByValue2)282 HWTEST_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 
TestSetter(EcmaRuntimeCallInfo * argv)314 JSTaggedValue 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 
HWTEST_F_L0(ICRuntimeStubTest,StoreICWithHandler)329 HWTEST_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 
TestGetter(EcmaRuntimeCallInfo * argv)374 JSTaggedValue 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 
HWTEST_F_L0(ICRuntimeStubTest,LoadICWithHandler)386 HWTEST_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 
HWTEST_F_L0(ICRuntimeStubTest,Prototype_StoreAndLoad)429 HWTEST_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 
HWTEST_F_L0(ICRuntimeStubTest,StoreWithTransition_In_Filed)462 HWTEST_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 
HWTEST_F_L0(ICRuntimeStubTest,Field_StoreAndLoad)494 HWTEST_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 
HWTEST_F_L0(ICRuntimeStubTest,Global_StoreAndLoad)521 HWTEST_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 
HWTEST_F_L0(ICRuntimeStubTest,Element_StoreAndLoad)540 HWTEST_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(thread, *handleArrObj, hanldeIntKey).GetInt(), 3);
561     EXPECT_EQ(JSObject::GetProperty(thread, handleArrObj, lengthKey).GetValue()->GetInt(), 5);
562     EXPECT_TRUE(ICRuntimeStub::LoadElement(thread, *handleArrObj, JSTaggedValue(2)).IsHole());
563 }
564 
HWTEST_F_L0(ICRuntimeStubTest,TryToElementsIndex)565 HWTEST_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