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