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 27using namespace panda::ecmascript; 28using namespace panda::ecmascript::base; 29 30namespace panda::test { 31using InlinedPropsBit = HandlerBase::InlinedPropsBit; 32using OffsetBit = HandlerBase::OffsetBit; 33using KindBit = HandlerBase::KindBit; 34using IsJSArrayBit = HandlerBase::IsJSArrayBit; 35using HandlerKind = HandlerBase::HandlerKind; 36using AccessorBit = HandlerBase::AccessorBit; 37class ICRuntimeStubTest : public testing::Test { 38public: 39 static void SetUpTestCase() 40 { 41 GTEST_LOG_(INFO) << "SetUpTestCase"; 42 } 43 44 static void TearDownTestCase() 45 { 46 GTEST_LOG_(INFO) << "TearDownCase"; 47 } 48 49 void SetUp() override 50 { 51 TestHelper::CreateEcmaVMWithScope(instance, thread, scope); 52 } 53 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 64HWTEST_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 95HWTEST_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 127HWTEST_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 155HWTEST_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 179HWTEST_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 204HWTEST_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 252HWTEST_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 282HWTEST_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 314JSTaggedValue 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 329HWTEST_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 374JSTaggedValue 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 386HWTEST_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 429HWTEST_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 462HWTEST_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 494HWTEST_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 521HWTEST_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 540HWTEST_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(*handleArrObj, hanldeIntKey).GetInt(), 3); 561 EXPECT_EQ(JSObject::GetProperty(thread, handleArrObj, lengthKey).GetValue()->GetInt(), 5); 562 EXPECT_TRUE(ICRuntimeStub::LoadElement(*handleArrObj, JSTaggedValue(2)).IsHole()); 563} 564 565HWTEST_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