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