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