/* * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ecmascript/ic/ic_runtime_stub-inl.h" #include "ecmascript/interpreter/slow_runtime_stub.h" #include "ecmascript/base/builtins_base.h" #include "ecmascript/ic/ic_handler.h" #include "ecmascript/global_env.h" #include "ecmascript/js_array.h" #include "ecmascript/js_object.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/object_operator.h" #include "ecmascript/tests/test_helper.h" using namespace panda::ecmascript; using namespace panda::ecmascript::base; namespace panda::test { using InlinedPropsBit = HandlerBase::InlinedPropsBit; using OffsetBit = HandlerBase::OffsetBit; using KindBit = HandlerBase::KindBit; using IsJSArrayBit = HandlerBase::IsJSArrayBit; using HandlerKind = HandlerBase::HandlerKind; using AccessorBit = HandlerBase::AccessorBit; class ICRuntimeStubTest : public testing::Test { public: static void SetUpTestCase() { GTEST_LOG_(INFO) << "SetUpTestCase"; } static void TearDownTestCase() { GTEST_LOG_(INFO) << "TearDownCase"; } void SetUp() override { TestHelper::CreateEcmaVMWithScope(instance, thread, scope); } void TearDown() override { TestHelper::DestroyEcmaVMWithScope(instance, scope); } EcmaVM *instance {nullptr}; EcmaHandleScope *scope {nullptr}; JSThread *thread {nullptr}; }; HWTEST_F_L0(ICRuntimeStubTest, LoadGlobalICByName) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objFun = env->GetArrayFunction(); JSHandle handleValue(thread, JSTaggedValue(2)); JSHandle globalValue(factory->NewJSObjectByConstructor(JSHandle(objFun), objFun)); JSHandle handleBoxValue = factory->NewPropertyBox(handleValue); JSHandle propKey(factory->NewFromASCII("x")); uint32_t arrayLength = 2U; JSHandle handleTaggedArray = factory->NewTaggedArray(arrayLength); handleTaggedArray->Set(thread, 0, handleBoxValue.GetTaggedValue()); handleTaggedArray->Set(thread, 1, JSTaggedValue::Undefined()); JSHandle handleProfileTypeInfo = JSHandle::Cast(handleTaggedArray); // ProfileTypeInfo get value is HeapObject and then call LoadGlobal function to load JSTaggedValue resultValue1 = ICRuntimeStub::LoadGlobalICByName(thread, *handleProfileTypeInfo, JSTaggedValue::Undefined(), JSTaggedValue::Undefined(), 0, true); EXPECT_EQ(resultValue1.GetInt(), 2); // the globalValue is jsobject then call loadMiss function can find global variable from global record firstly // so need store global record. SlowRuntimeStub::StGlobalRecord(thread, propKey.GetTaggedValue(), handleValue.GetTaggedValue(), false); JSTaggedValue resultValue2 = ICRuntimeStub::LoadGlobalICByName(thread, *handleProfileTypeInfo, globalValue.GetTaggedValue(), propKey.GetTaggedValue(), 1, true); EXPECT_EQ(resultValue2.GetInt(), 2); EXPECT_TRUE(handleProfileTypeInfo->Get(1).IsPropertyBox()); } HWTEST_F_L0(ICRuntimeStubTest, StoreGlobalICByName) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objFun = env->GetArrayFunction(); JSHandle handleBoxValue = factory->NewPropertyBox(JSHandle(thread, JSTaggedValue::Undefined())); JSHandle propKey(factory->NewFromASCII("x")); JSHandle globalValue(factory->NewJSObjectByConstructor(JSHandle(objFun), objFun)); JSTaggedValue handleValue(2); uint32_t arrayLength = 2U; // 2 means ProfileTypeInfo length JSHandle handleTaggedArray = factory->NewTaggedArray(arrayLength); handleTaggedArray->Set(thread, 0, handleBoxValue.GetTaggedValue()); handleTaggedArray->Set(thread, 1, JSTaggedValue::Undefined()); JSHandle handleProfileTypeInfo = JSHandle::Cast(handleTaggedArray); // ProfileTypeInfo get value is HeapObject and then call LoadGlobal function to load JSTaggedValue resultValue1 = ICRuntimeStub::StoreGlobalICByName(thread, *handleProfileTypeInfo, JSTaggedValue::Undefined(), JSTaggedValue::Undefined(), handleValue, 0, true); EXPECT_TRUE(resultValue1.IsUndefined()); EXPECT_EQ(handleBoxValue->GetValue().GetInt(), 2); // the globalValue is jsobject then call storeMiss function can find global variable from global record firstly // so need store global record. SlowRuntimeStub::StGlobalRecord(thread, propKey.GetTaggedValue(), handleBoxValue.GetTaggedValue(), false); JSTaggedValue resultValue2 = ICRuntimeStub::StoreGlobalICByName(thread, *handleProfileTypeInfo, globalValue.GetTaggedValue(), propKey.GetTaggedValue(), handleValue, 1, true); EXPECT_TRUE(resultValue2.IsUndefined()); EXPECT_TRUE(handleProfileTypeInfo->Get(1).IsPropertyBox()); } HWTEST_F_L0(ICRuntimeStubTest, CheckPolyHClass) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle handleValue(thread, JSTaggedValue::Undefined()); JSHandle handlePropertyBox = factory->NewPropertyBox(handleValue); JSHandle handleEmptyStr = factory->GetEmptyString(); JSHandle handleCacheArray = factory->NewTaggedArray(5); // 5 : 5 array length JSHandle objFun = env->GetArrayFunction(); JSHandle handleObj(factory->NewJSObjectByConstructor(JSHandle(objFun), objFun)); TaggedObject *handleTaggedObj = handleObj->GetTaggedObject(); JSTaggedValue handleTaggedObjVal(handleTaggedObj); handleTaggedObjVal.CreateWeakRef(); TaggedObject *handleWeakObj = TaggedObject::Cast(handleTaggedObjVal.GetWeakReferent()); JSHClass *handleObjClass = static_cast(handleWeakObj); handleCacheArray->Set(thread, 0, JSTaggedValue::Undefined()); // 0 : 0 set value in zero handleCacheArray->Set(thread, 1, JSTaggedValue::Undefined()); // 1 : 1 set value in one handleCacheArray->Set(thread, 2, handleTaggedObjVal); // 2 : 2 set weakvalue in two handleCacheArray->Set(thread, 3, handlePropertyBox.GetTaggedValue()); // 3 : 3 set value in three handleCacheArray->Set(thread, 4, handleEmptyStr.GetTaggedValue()); // 4 : 4 set value in four JSTaggedValue handleWeakCacheValue(handleCacheArray.GetTaggedValue()); JSTaggedValue resultValue = ICRuntimeStub::CheckPolyHClass(handleWeakCacheValue, handleObjClass); EXPECT_TRUE(resultValue.IsPropertyBox()); } HWTEST_F_L0(ICRuntimeStubTest, StoreICAndLoadIC_ByName) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objFun = env->GetObjectFunction(); JSHandle handleObj(factory->NewJSObjectByConstructor(JSHandle(objFun), objFun)); JSHandle handleKey(factory->NewFromASCII("key")); JSHandle handleValue(thread, JSTaggedValue(1)); JSHandle handleStoreVal(thread, JSTaggedValue(2)); uint32_t arrayLength = 1U; JSHandle handleTaggedArray = factory->NewTaggedArray(arrayLength); JSHandle handleProfileTypeInfo = JSHandle::Cast(handleTaggedArray); // test receiver is jsobject and ProfileTypeInfo get value is hole in slotId. ICRuntimeStub::StoreICByName(thread, *handleProfileTypeInfo, handleObj.GetTaggedValue(), handleKey.GetTaggedValue(), handleStoreVal.GetTaggedValue(), 0); JSTaggedValue resultValue = ICRuntimeStub::LoadICByName(thread, *handleProfileTypeInfo, handleObj.GetTaggedValue(), handleKey.GetTaggedValue(), 0); EXPECT_EQ(resultValue.GetInt(), 2); } HWTEST_F_L0(ICRuntimeStubTest, StoreICAndLoadIC_ByValue) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle typeArrayFun = env->GetInt8ArrayFunction(); JSHandle handleTypeArrReceiver = JSHandle::Cast( factory->NewJSObjectByConstructor(JSHandle(typeArrayFun), typeArrayFun)); JSHandle handleKey(factory->NewFromASCII("key")); JSHandle handleStoreVal(factory->NewFromASCII("1")); uint32_t arrayLength = 2U; // 2 means ProfileTypeInfo length JSHandle handleTaggedArray = factory->NewTaggedArray(arrayLength); JSHandle handleProfileTypeInfo = JSHandle::Cast(handleTaggedArray); // test receiver is typedArray ICRuntimeStub::StoreICByValue(thread, *handleProfileTypeInfo, handleTypeArrReceiver.GetTaggedValue(), handleKey.GetTaggedValue(), handleStoreVal.GetTaggedValue(), 0); JSTaggedValue resultValue = ICRuntimeStub::LoadICByValue(thread, *handleProfileTypeInfo, handleTypeArrReceiver.GetTaggedValue(), handleKey.GetTaggedValue(), 0); EXPECT_TRUE(resultValue.IsString()); JSHandle handleEcmaStrTo(JSHandle(thread, resultValue)); EXPECT_STREQ("1", EcmaStringAccessor(handleEcmaStrTo).ToCString().c_str()); } HWTEST_F_L0(ICRuntimeStubTest, TryStoreICAndLoadIC_ByName) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objFun = env->GetObjectFunction(); JSHandle handleObj = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); JSTaggedValue handleFirstObjClassVal(handleObj->GetClass()); TaggedObject *handleTaggedObject = handleFirstObjClassVal.GetWeakReferentUnChecked(); JSHClass *handleNewObjClass = static_cast(handleTaggedObject); JSHandle handleNewObj = factory->NewJSObject(JSHandle(thread, handleNewObjClass)); JSHandle handleArr = factory->NewTaggedArray(1); handleArr->Set(thread, 0, JSTaggedValue::Undefined()); JSHandle handleBoxValue(thread, JSTaggedValue::Undefined()); JSHandle handlerPropertyBoxVal(factory->NewPropertyBox(handleBoxValue)); JSTaggedValue handleFirstArrVal(handleArr.GetTaggedValue()); JSTaggedValue handleSecondPropertyBoxVal = handlerPropertyBoxVal.GetTaggedValue(); JSTaggedValue handleReceiver = handleNewObj.GetTaggedValue(); JSTaggedValue handleStoreVal(2); // fistValue GetWeakReferentUnChecked is equal the receiver class ICRuntimeStub::TryStoreICByName(thread, handleReceiver, handleFirstObjClassVal, handleSecondPropertyBoxVal, handleStoreVal); JSTaggedValue resultValue1 = ICRuntimeStub::TryLoadICByName(thread, handleReceiver, handleFirstObjClassVal, handleSecondPropertyBoxVal); EXPECT_EQ(resultValue1.GetInt(), handleStoreVal.GetInt()); // fistValue GetWeakReferent is not equal the receiver class ICRuntimeStub::TryStoreICByName(thread, handleObj.GetTaggedValue(), handleFirstArrVal, handleSecondPropertyBoxVal, handleStoreVal); JSTaggedValue resultValue2 = ICRuntimeStub::TryLoadICByName(thread, handleObj.GetTaggedValue(), handleFirstArrVal, handleSecondPropertyBoxVal); EXPECT_TRUE(resultValue2.IsHole()); // receiver is number int a = 32; JSHandle numReceiver(thread, JSTaggedValue(a)); JSHandle receiver = JSHandle::Cast(factory->NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_NUMBER, numReceiver)); JSHandle hclass(thread, receiver->GetTaggedObject()->GetClass()); JSHandle key = thread->GlobalConstants()->GetHandledValueOfString(); ObjectOperator op(thread, numReceiver, key); JSHandle handlerValue = PrototypeHandler::LoadPrototype(thread, op, hclass); JSTaggedValue resultValue3 = ICRuntimeStub::TryLoadICByName(thread, numReceiver.GetTaggedValue(), hclass.GetTaggedValue(), handlerValue.GetTaggedValue()); EXPECT_EQ(op.GetValue(), resultValue3); } HWTEST_F_L0(ICRuntimeStubTest, TryStoreICAndLoadIC_ByValue1) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objFun = env->GetObjectFunction(); JSHandle handleObj = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); JSTaggedValue handleObjClassVal(handleObj->GetClass()); TaggedObject *handleTaggedObject = handleObjClassVal.GetWeakReferentUnChecked(); JSHClass *handleNewObjClass = static_cast(handleTaggedObject); JSHandle handleNewObj = factory->NewJSObject(JSHandle(thread, handleNewObjClass)); JSHandle handleTaggedArray = factory->NewTaggedArray(1); handleNewObj->SetElements(thread, handleTaggedArray.GetTaggedValue()); uint32_t handler = 0U; KindBit::Set(HandlerKind::ELEMENT, &handler); JSTaggedValue handleFirstVal(handleTaggedObject); JSTaggedValue handleSecondHandlerVal(handler); JSTaggedValue handleReceiver = handleNewObj.GetTaggedValue(); JSTaggedValue handleStoreVal(2); // fistValue GetWeakReferentUnChecked is equal the receiver class ICRuntimeStub::TryStoreICByValue(thread, handleReceiver, JSTaggedValue(0), handleFirstVal, handleSecondHandlerVal, handleStoreVal); JSTaggedValue resultValue = ICRuntimeStub::TryLoadICByValue(thread, handleReceiver, JSTaggedValue(0), handleFirstVal, handleSecondHandlerVal); EXPECT_EQ(resultValue.GetInt(), handleStoreVal.GetInt()); } HWTEST_F_L0(ICRuntimeStubTest, TryStoreICAndLoadIC_ByValue2) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objFun = env->GetObjectFunction(); JSHandle handleObj = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); JSTaggedValue handleObjClassVal(handleObj->GetClass()); handleObjClassVal.CreateWeakRef(); TaggedObject *handleTaggedObject = TaggedObject::Cast(handleObjClassVal.GetWeakReferent()); JSHClass *handleNewObjClass = static_cast(handleTaggedObject); JSHandle handleTypeArr = factory->NewTaggedArray(1); JSHandle handleNewObj = factory->NewJSObject(JSHandle(thread, handleNewObjClass)); handleNewObj->SetProperties(thread, handleTypeArr.GetTaggedValue()); uint32_t handler = 0U; KindBit::Set(HandlerKind::FIELD, &handler); JSHandle handleSecondValArr = factory->NewTaggedArray(2); handleSecondValArr->Set(thread, 0, handleObjClassVal); handleSecondValArr->Set(thread, 1, JSTaggedValue(handler)); JSTaggedValue handleReceiver = handleNewObj.GetTaggedValue(); JSTaggedValue handleSecondArrVal = handleSecondValArr.GetTaggedValue(); JSTaggedValue handleStoreVal(2); // fistvalue is equal the key value. ICRuntimeStub::TryStoreICByValue(thread, handleReceiver, JSTaggedValue(0), JSTaggedValue(0), handleSecondArrVal, handleStoreVal); JSTaggedValue resultValue = ICRuntimeStub::TryLoadICByValue(thread, handleReceiver, JSTaggedValue(0), JSTaggedValue(0), handleSecondArrVal); EXPECT_EQ(resultValue.GetInt(), handleStoreVal.GetInt()); } JSTaggedValue TestSetter(EcmaRuntimeCallInfo *argv) { // 2 : 2 arg value if (argv->GetArgsNumber() == 1 && argv->GetCallArg(0).GetTaggedValue() == JSTaggedValue(2)) { JSThread *thread = argv->GetThread(); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle obj(BuiltinsBase::GetThis(argv)); JSHandle keyHandle(factory->NewFromASCII("key")); JSHandle valueHandle(thread, JSTaggedValue(2)); // 2 : 2 property value JSObject::SetProperty(thread, JSHandle(obj), keyHandle, valueHandle); return JSTaggedValue(JSTaggedValue::True()); } return JSTaggedValue(JSTaggedValue::False()); } HWTEST_F_L0(ICRuntimeStubTest, StoreICWithHandler) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objFun = env->GetObjectFunction(); JSHandle keyHandle(factory->NewFromASCII("key")); JSHandle boxHandler = factory->NewPropertyBox(keyHandle); JSHandle setter = factory->NewJSFunction(env, reinterpret_cast(TestSetter)); JSHandle handleAccessor = factory->NewAccessorData(); handleAccessor->SetSetter(thread, setter.GetTaggedValue()); uint32_t handler = 0U; uint32_t bitOffset = 1U; OffsetBit::Set(bitOffset, &handler); AccessorBit::Set(true, &handler); uint32_t arrayLength = bitOffset + 1U; JSHandle handleHolder = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); JSHandle handleTaggedArr = factory->NewTaggedArray(arrayLength); handleTaggedArr->Set(thread, bitOffset, handleAccessor.GetTaggedValue()); handleHolder->SetProperties(thread, handleTaggedArr.GetTaggedValue()); JSHandle handleReceiver = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); // handler is Init and HandlerBase Is Accessor,then call CallSetter function. JSTaggedValue resultValue1 = ICRuntimeStub::StoreICWithHandler(thread, handleReceiver.GetTaggedValue(), handleHolder.GetTaggedValue(), JSTaggedValue(2), JSTaggedValue(handler)); EXPECT_TRUE(resultValue1.IsUndefined()); EXPECT_EQ(JSObject::GetProperty(thread, JSHandle(handleReceiver), keyHandle).GetValue()->GetInt(), 2); // handler is PropertyBox and then call StoreGlobal function. JSTaggedValue resultValue2 = ICRuntimeStub::StoreICWithHandler(thread, handleReceiver.GetTaggedValue(), handleHolder.GetTaggedValue(), JSTaggedValue(2), boxHandler.GetTaggedValue()); EXPECT_TRUE(resultValue2.IsUndefined()); EXPECT_EQ(ICRuntimeStub::LoadGlobal(boxHandler.GetTaggedValue()).GetInt(), 2); // HandlerBase Is NonExist and This situation is not judged. KindBit::Set(HandlerKind::NON_EXIST, &handler); JSTaggedValue resultValue3 = ICRuntimeStub::StoreICWithHandler(thread, handleReceiver.GetTaggedValue(), handleHolder.GetTaggedValue(), JSTaggedValue(2), JSTaggedValue(handler)); EXPECT_TRUE(resultValue3.IsUndefined()); } JSTaggedValue TestGetter(EcmaRuntimeCallInfo *argv) { auto thread = argv->GetThread(); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle obj(BuiltinsBase::GetThis(argv)); JSHandle keyHandle(factory->NewFromASCII("key")); JSTaggedValue value = JSObject::GetProperty(thread, JSHandle(obj), keyHandle).GetValue().GetTaggedValue(); return JSTaggedValue(value.GetInt()); } HWTEST_F_L0(ICRuntimeStubTest, LoadICWithHandler) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objFun = env->GetObjectFunction(); JSHandle keyHandle(factory->NewFromASCII("key")); JSHandle valueHandle(thread, JSTaggedValue(1)); JSHandle boxHandler = factory->NewPropertyBox(keyHandle); JSHandle getter = factory->NewJSFunction(env, reinterpret_cast(TestGetter)); JSHandle handleAccessor = factory->NewAccessorData(); handleAccessor->SetGetter(thread, getter.GetTaggedValue()); uint32_t handler = 0U; uint32_t bitOffset = 1U; OffsetBit::Set(bitOffset, &handler); AccessorBit::Set(true, &handler); uint32_t arrayLength = bitOffset + 1U; JSHandle handleHolder = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); JSHandle handleTaggedArr = factory->NewTaggedArray(arrayLength); handleTaggedArr->Set(thread, bitOffset, handleAccessor.GetTaggedValue()); handleHolder->SetProperties(thread, handleTaggedArr.GetTaggedValue()); JSHandle handleReceiver = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); JSObject::SetProperty(thread, JSHandle(handleReceiver), keyHandle, valueHandle); // handler is Init and HandlerBase Is Accessor,then call CallGetter function. JSTaggedValue resultValue1 = ICRuntimeStub::LoadICWithHandler(thread, handleReceiver.GetTaggedValue(), handleHolder.GetTaggedValue(), JSTaggedValue(handler)); EXPECT_EQ(resultValue1.GetInt(), 1); // HandlerBase Is NonExist and This situation is not judged. KindBit::Set(HandlerKind::NON_EXIST, &handler); JSTaggedValue resultValue3 = ICRuntimeStub::LoadICWithHandler(thread, handleReceiver.GetTaggedValue(), handleHolder.GetTaggedValue(), JSTaggedValue(handler)); EXPECT_TRUE(resultValue3.IsUndefined()); // handler is PropertyBox and then call LoadGlobal function. JSTaggedValue resultValue4 = ICRuntimeStub::LoadICWithHandler(thread, handleReceiver.GetTaggedValue(), handleHolder.GetTaggedValue(), boxHandler.GetTaggedValue()); EXPECT_TRUE(resultValue4.IsString()); } HWTEST_F_L0(ICRuntimeStubTest, Prototype_StoreAndLoad) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objFun = env->GetObjectFunction(); JSHandle cellValue = factory->NewProtoChangeMarker(); EXPECT_TRUE(!cellValue->GetHasChanged()); uint32_t handler = 0U; uint32_t bitOffset = 1U; OffsetBit::Set(bitOffset, &handler); KindBit::Set(HandlerKind::FIELD, &handler); // test filed uint32_t arrayLength = bitOffset + 1U; JSHandle handleObj = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); JSHandle handleTaggedArr = factory->NewTaggedArray(arrayLength); handleObj->SetProperties(thread, handleTaggedArr.GetTaggedValue()); JSHandle handleProtoHandler = factory->NewPrototypeHandler(); handleProtoHandler->SetProtoCell(thread, cellValue.GetTaggedValue()); handleProtoHandler->SetHandlerInfo(thread, JSTaggedValue(handler)); handleProtoHandler->SetHolder(thread, handleObj.GetTaggedValue()); // test storePrototype function JSTaggedValue resultValue1 = ICRuntimeStub::StorePrototype(thread, handleObj.GetTaggedValue(), JSTaggedValue(1), handleProtoHandler.GetTaggedValue()); EXPECT_TRUE(resultValue1.IsUndefined()); // test loadPrototype function JSTaggedValue resultValue2 = ICRuntimeStub::LoadPrototype(thread, handleObj.GetTaggedValue(), handleProtoHandler.GetTaggedValue()); EXPECT_EQ(ICRuntimeStub::LoadFromField(*handleObj, handler).GetInt(), resultValue2.GetInt()); } HWTEST_F_L0(ICRuntimeStubTest, StoreWithTransition_In_Filed) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objFun = env->GetObjectFunction(); JSHandle arrFun = env->GetArrayFunction(); JSHandle handleObj = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); JSHandle originHClass(thread, handleObj->GetJSHClass()); JSHandle handleArrObj = factory->NewJSObjectByConstructor(JSHandle(arrFun), arrFun); auto hclass = handleArrObj->SynchronizedGetClass(); uint32_t handler = 0U; uint32_t bitOffset = 1U; OffsetBit::Set(bitOffset, &handler); KindBit::Set(HandlerKind::FIELD, &handler); uint32_t arrayLength = bitOffset + 1U; JSHandle handleTaggedArr = factory->NewTaggedArray(arrayLength); handleObj->SetProperties(thread, handleTaggedArr.GetTaggedValue()); JSHandle handleTranHandler = factory->NewTransitionHandler(); handleTranHandler->SetTransitionHClass(thread, JSTaggedValue(hclass)); handleTranHandler->SetHandlerInfo(thread, JSTaggedValue(handler)); // test handler is InlinedProps and store in filed InlinedPropsBit::Set(true, &handler); ICRuntimeStub::StoreWithTransition(thread, *handleObj, JSTaggedValue(2), handleTranHandler.GetTaggedValue()); auto resultArray = TaggedArray::Cast(handleObj->GetProperties().GetTaggedObject()); EXPECT_EQ(resultArray->Get(bitOffset).GetInt(), 2); handleObj->SynchronizedSetClass(thread, *originHClass); } HWTEST_F_L0(ICRuntimeStubTest, Field_StoreAndLoad) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objFun = env->GetObjectFunction(); uint32_t handler = 0U; uint32_t bitOffset = 2U; OffsetBit::Set(bitOffset, &handler); uint32_t arrayLength = bitOffset + 1U; JSHandle handleTaggedArr = factory->NewTaggedArray(arrayLength); handleTaggedArr->Set(thread, bitOffset, JSTaggedValue::Undefined()); JSHandle handleObj = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); handleObj->SetProperties(thread, handleTaggedArr.GetTaggedValue()); // test handler is not InlinedProps ICRuntimeStub::StoreField(thread, *handleObj, JSTaggedValue(3), handler); JSTaggedValue resultValue1 = ICRuntimeStub::LoadFromField(*handleObj, handler); EXPECT_EQ(resultValue1.GetInt(), 3); // test handler is InlinedProps InlinedPropsBit::Set(true, &handler); ICRuntimeStub::StoreField(thread, *handleObj, JSTaggedValue(2), handler); JSTaggedValue resultValue = ICRuntimeStub::LoadFromField(*handleObj, handler); EXPECT_EQ(resultValue.GetInt(), 2); } HWTEST_F_L0(ICRuntimeStubTest, Global_StoreAndLoad) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle handleUndefinedVal(thread, JSTaggedValue::Undefined()); JSHandle handlerValue = factory->NewPropertyBox(handleUndefinedVal); JSTaggedValue resultValue1 = ICRuntimeStub::StoreGlobal(thread, JSTaggedValue(2), handlerValue.GetTaggedValue()); EXPECT_TRUE(resultValue1.IsUndefined()); JSTaggedValue resultValue2 = ICRuntimeStub::LoadGlobal(handlerValue.GetTaggedValue()); EXPECT_EQ(resultValue2.GetInt(), 2); handlerValue->Clear(thread); JSTaggedValue resultValue3 = ICRuntimeStub::StoreGlobal(thread, JSTaggedValue(3), handlerValue.GetTaggedValue()); EXPECT_TRUE(resultValue3.IsHole()); JSTaggedValue resultValue4 = ICRuntimeStub::LoadGlobal(handlerValue.GetTaggedValue()); EXPECT_TRUE(resultValue4.IsHole()); } HWTEST_F_L0(ICRuntimeStubTest, Element_StoreAndLoad) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle lengthKey = thread->GlobalConstants()->GetHandledLengthString(); JSTaggedValue hanldeIntKey(4); uint32_t handlerInfo = 0U; KindBit::Set(HandlerKind::ELEMENT, &handlerInfo); IsJSArrayBit::Set(true, &handlerInfo); uint32_t arrayLength = 3U; JSArray *handleArr = JSArray::ArrayCreate(thread, JSTaggedNumber(arrayLength)).GetObject(); JSHandle handleArrObj(thread, handleArr); JSHandle handleTaggedArr = factory->NewTaggedArray(arrayLength); handleArrObj->SetProperties(thread, handleTaggedArr.GetTaggedValue()); JSTaggedValue resultValue = ICRuntimeStub::StoreElement(thread, *handleArrObj, hanldeIntKey, JSTaggedValue(3), JSTaggedValue(handlerInfo)); EXPECT_TRUE(resultValue.IsUndefined()); EXPECT_EQ(ICRuntimeStub::LoadElement(*handleArrObj, hanldeIntKey).GetInt(), 3); EXPECT_EQ(JSObject::GetProperty(thread, handleArrObj, lengthKey).GetValue()->GetInt(), 5); EXPECT_TRUE(ICRuntimeStub::LoadElement(*handleArrObj, JSTaggedValue(2)).IsHole()); } HWTEST_F_L0(ICRuntimeStubTest, TryToElementsIndex) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSTaggedValue hanldeIntKey1(0); JSTaggedValue hanldeIntKey2(1); JSTaggedValue handleDoubleKey1(1.00); JSTaggedValue handleDoubleKey2(1.11); JSHandle handleStrKey1(factory->NewFromASCII("1234")); JSHandle handleStrKey2(factory->NewFromASCII("xy")); EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(hanldeIntKey1), 0); EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(hanldeIntKey2), 1); EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(handleDoubleKey1), 1); EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(handleDoubleKey2), -1); EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(handleStrKey1.GetTaggedValue()), 1234); EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(handleStrKey2.GetTaggedValue()), -1); } } // namespace panda::test