* 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<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> objFun = env->GetArrayFunction();
JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(2));
JSHandle<JSTaggedValue> globalValue(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
JSHandle<PropertyBox> handleBoxValue = factory->NewPropertyBox(handleValue);
JSHandle<JSTaggedValue> propKey(factory->NewFromASCII("x"));
uint32_t arrayLength = 2U;
JSHandle<ProfileTypeInfo> handleProfileTypeInfo = factory->NewProfileTypeInfo(arrayLength);
handleProfileTypeInfo->Set(thread, 0, handleBoxValue.GetTaggedValue());
JSTaggedValue resultValue1 =
ICRuntimeStub::LoadGlobalICByName(thread, *handleProfileTypeInfo,
JSTaggedValue::Undefined(), JSTaggedValue::Undefined(), 0, true);
EXPECT_EQ(resultValue1.GetInt(), 2);
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(thread, 1).IsPropertyBox());
}
HWTEST_F_L0(ICRuntimeStubTest, StoreGlobalICByName)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> objFun = env->GetArrayFunction();
JSHandle<PropertyBox> handleBoxValue =
factory->NewPropertyBox(JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
JSHandle<JSTaggedValue> propKey(factory->NewFromASCII("x"));
JSHandle<JSTaggedValue> globalValue(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
JSTaggedValue handleValue(2);
uint32_t arrayLength = 2U;
JSHandle<ProfileTypeInfo> handleProfileTypeInfo = factory->NewProfileTypeInfo(arrayLength);
handleProfileTypeInfo->Set(thread, 0, handleBoxValue.GetTaggedValue());
JSTaggedValue resultValue1 =
ICRuntimeStub::StoreGlobalICByName(thread, *handleProfileTypeInfo, JSTaggedValue::Undefined(),
JSTaggedValue::Undefined(), handleValue, 0, true);
EXPECT_TRUE(resultValue1.IsUndefined());
EXPECT_EQ(handleBoxValue->GetValue(thread).GetInt(), 2);
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(thread, 1).IsPropertyBox());
}
HWTEST_F_L0(ICRuntimeStubTest, CheckPolyHClass)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue::Undefined());
JSHandle<PropertyBox> handlePropertyBox = factory->NewPropertyBox(handleValue);
JSHandle<EcmaString> handleEmptyStr = factory->GetEmptyString();
JSHandle<TaggedArray> handleCacheArray = factory->NewTaggedArray(6);
JSHandle<JSTaggedValue> objFun = env->GetArrayFunction();
JSHandle<JSTaggedValue> handleObj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
TaggedObject *handleTaggedObj = handleObj->GetTaggedObject();
JSTaggedValue handleTaggedObjVal(handleTaggedObj);
handleTaggedObjVal.CreateWeakRef();
TaggedObject *handleWeakObj = TaggedObject::Cast(handleTaggedObjVal.GetWeakReferent());
JSHClass *handleObjClass = static_cast<JSHClass *>(handleWeakObj);
handleCacheArray->Set(thread, 0, JSTaggedValue::Undefined());
handleCacheArray->Set(thread, 1, JSTaggedValue::Undefined());
handleCacheArray->Set(thread, 2, handleTaggedObjVal);
handleCacheArray->Set(thread, 3, handlePropertyBox.GetTaggedValue());
handleCacheArray->Set(thread, 4, JSTaggedValue::Undefined());
handleCacheArray->Set(thread, 5, handleEmptyStr.GetTaggedValue());
JSTaggedValue handleWeakCacheValue(handleCacheArray.GetTaggedValue());
JSTaggedValue resultValue = ICRuntimeStub::CheckPolyHClass(thread, handleWeakCacheValue, handleObjClass);
EXPECT_TRUE(resultValue.IsPropertyBox());
}
HWTEST_F_L0(ICRuntimeStubTest, StoreICAndLoadIC_ByName)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
JSHandle<JSTaggedValue> handleObj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(1));
JSHandle<JSTaggedValue> handleStoreVal(thread, JSTaggedValue(2));
uint32_t arrayLength = 2U;
JSHandle<ProfileTypeInfo> handleProfileTypeInfo = factory->NewProfileTypeInfo(arrayLength);
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<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> typedArrayFun = env->GetInt8ArrayFunction();
JSHandle<JSTypedArray> handleTypeArrReceiver = JSHandle<JSTypedArray>::Cast(
factory->NewJSObjectByConstructor(JSHandle<JSFunction>(typedArrayFun), typedArrayFun));
JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
JSHandle<JSTaggedValue> handleStoreVal(factory->NewFromASCII("1"));
uint32_t arrayLength = 2U;
JSHandle<ProfileTypeInfo> handleProfileTypeInfo = factory->NewProfileTypeInfo(arrayLength);
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<EcmaString> handleEcmaStrTo(JSHandle<JSTaggedValue>(thread, resultValue));
EXPECT_STREQ("1", EcmaStringAccessor(handleEcmaStrTo).ToCString(thread).c_str());
}
HWTEST_F_L0(ICRuntimeStubTest, TryStoreICAndLoadIC_ByName)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
JSTaggedValue handleFirstObjClassVal(handleObj->GetClass());
TaggedObject *handleTaggedObject = handleFirstObjClassVal.GetWeakReferentUnChecked();
JSHClass *handleNewObjClass = static_cast<JSHClass *>(handleTaggedObject);
JSHandle<JSObject> handleNewObj = factory->NewJSObject(JSHandle<JSHClass>(thread, handleNewObjClass));
JSHandle<TaggedArray> handleArr = factory->NewTaggedArray(2);
handleArr->Set(thread, 0, JSTaggedValue::Undefined());
JSHandle<JSTaggedValue> handleBoxValue(thread, JSTaggedValue::Undefined());
JSHandle<JSTaggedValue> handlerPropertyBoxVal(factory->NewPropertyBox(handleBoxValue));
JSTaggedValue handleFirstArrVal(handleArr.GetTaggedValue());
JSTaggedValue handleSecondPropertyBoxVal = handlerPropertyBoxVal.GetTaggedValue();
JSTaggedValue handleReceiver = handleNewObj.GetTaggedValue();
JSTaggedValue handleStoreVal(2);
ICRuntimeStub::TryStoreICByName(thread, handleReceiver, handleFirstObjClassVal,
handleSecondPropertyBoxVal, handleStoreVal);
JSTaggedValue resultValue1 = ICRuntimeStub::TryLoadICByName(thread, handleReceiver, handleFirstObjClassVal,
handleSecondPropertyBoxVal);
EXPECT_EQ(resultValue1.GetInt(), handleStoreVal.GetInt());
ICRuntimeStub::TryStoreICByName(thread, handleObj.GetTaggedValue(), handleFirstArrVal,
handleSecondPropertyBoxVal, handleStoreVal);
JSTaggedValue resultValue2 = ICRuntimeStub::TryLoadICByName(thread, handleObj.GetTaggedValue(),
handleFirstArrVal, handleSecondPropertyBoxVal);
EXPECT_TRUE(resultValue2.IsHole());
int a = 32;
JSHandle<JSTaggedValue> numReceiver(thread, JSTaggedValue(a));
JSHandle<JSTaggedValue> receiver =
JSHandle<JSTaggedValue>::Cast(factory->NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_NUMBER, numReceiver));
JSHandle<JSHClass> hclass(thread, receiver->GetTaggedObject()->GetClass());
JSHandle<JSTaggedValue> key = thread->GlobalConstants()->GetHandledValueOfString();
ObjectOperator op(thread, numReceiver, key);
JSHandle<JSTaggedValue> 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<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
JSTaggedValue handleObjClassVal(handleObj->GetClass());
TaggedObject *handleTaggedObject = handleObjClassVal.GetWeakReferentUnChecked();
JSHClass *handleNewObjClass = static_cast<JSHClass *>(handleTaggedObject);
JSHandle<JSObject> handleNewObj = factory->NewJSObject(JSHandle<JSHClass>(thread, handleNewObjClass));
JSHandle<TaggedArray> handleTaggedArray = factory->NewTaggedArray(1);
handleNewObj->SetElements(thread, handleTaggedArray.GetTaggedValue());
uint32_t handler = 0U;
KindBit::Set<uint32_t>(HandlerKind::ELEMENT, &handler);
JSTaggedValue handleFirstVal(handleTaggedObject);
JSTaggedValue handleSecondHandlerVal(handler);
JSTaggedValue handleReceiver = handleNewObj.GetTaggedValue();
JSTaggedValue handleStoreVal(2);
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<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
JSTaggedValue handleObjClassVal(handleObj->GetClass());
handleObjClassVal.CreateWeakRef();
TaggedObject *handleTaggedObject = TaggedObject::Cast(handleObjClassVal.GetWeakReferent());
JSHClass *handleNewObjClass = static_cast<JSHClass *>(handleTaggedObject);
JSHandle<TaggedArray> handleTypeArr = factory->NewTaggedArray(1);
JSHandle<JSObject> handleNewObj = factory->NewJSObject(JSHandle<JSHClass>(thread, handleNewObjClass));
handleNewObj->SetProperties(thread, handleTypeArr.GetTaggedValue());
uint32_t handler = 0U;
KindBit::Set<uint32_t>(HandlerKind::FIELD, &handler);
JSHandle<TaggedArray> 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);
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)
{
if (argv->GetArgsNumber() == 1 && argv->GetCallArg(0).GetTaggedValue() == JSTaggedValue(2)) {
JSThread *thread = argv->GetThread();
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSObject> obj(BuiltinsBase::GetThis(argv));
JSHandle<JSTaggedValue> keyHandle(factory->NewFromASCII("key"));
JSHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue(2));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), keyHandle, valueHandle);
return JSTaggedValue(JSTaggedValue::True());
}
return JSTaggedValue(JSTaggedValue::False());
}
HWTEST_F_L0(ICRuntimeStubTest, StoreICWithHandler)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
JSHandle<JSTaggedValue> keyHandle(factory->NewFromASCII("key"));
JSHandle<PropertyBox> boxHandler = factory->NewPropertyBox(keyHandle);
JSHandle<JSFunction> setter = factory->NewJSFunction(env, reinterpret_cast<void *>(TestSetter));
JSHandle<AccessorData> handleAccessor = factory->NewAccessorData();
handleAccessor->SetSetter(thread, setter.GetTaggedValue());
uint32_t handler = 0U;
uint32_t bitOffset = 1U;
OffsetBit::Set<uint32_t>(bitOffset, &handler);
AccessorBit::Set<uint32_t>(true, &handler);
uint32_t arrayLength = bitOffset + 1U;
JSHandle<JSObject> handleHolder = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
JSHandle<TaggedArray> handleTaggedArr = factory->NewTaggedArray(arrayLength);
handleTaggedArr->Set(thread, bitOffset, handleAccessor.GetTaggedValue());
handleHolder->SetProperties(thread, handleTaggedArr.GetTaggedValue());
JSHandle<JSObject> handleReceiver = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
JSTaggedValue resultValue1 =
ICRuntimeStub::StoreICWithHandler(thread, handleReceiver.GetTaggedValue(),
handleHolder.GetTaggedValue(), JSTaggedValue(2), JSTaggedValue(handler));
EXPECT_TRUE(resultValue1.IsUndefined());
EXPECT_EQ(JSObject::GetProperty(thread,
JSHandle<JSTaggedValue>(handleReceiver), keyHandle).GetValue()->GetInt(), 2);
JSTaggedValue resultValue2 =
ICRuntimeStub::StoreICWithHandler(thread, handleReceiver.GetTaggedValue(),
handleHolder.GetTaggedValue(), JSTaggedValue(2), boxHandler.GetTaggedValue());
EXPECT_TRUE(resultValue2.IsUndefined());
EXPECT_EQ(ICRuntimeStub::LoadGlobal(thread, boxHandler.GetTaggedValue()).GetInt(), 2);
KindBit::Set<uint32_t>(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<JSObject> obj(BuiltinsBase::GetThis(argv));
JSHandle<JSTaggedValue> keyHandle(factory->NewFromASCII("key"));
JSTaggedValue value =
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), keyHandle).GetValue().GetTaggedValue();
return JSTaggedValue(value.GetInt());
}
HWTEST_F_L0(ICRuntimeStubTest, LoadICWithHandler)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
JSHandle<JSTaggedValue> keyHandle(factory->NewFromASCII("key"));
JSHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue(1));
JSHandle<PropertyBox> boxHandler = factory->NewPropertyBox(keyHandle);
JSHandle<JSFunction> getter = factory->NewJSFunction(env, reinterpret_cast<void *>(TestGetter));
JSHandle<AccessorData> handleAccessor = factory->NewAccessorData();
handleAccessor->SetGetter(thread, getter.GetTaggedValue());
uint32_t handler = 0U;
uint32_t bitOffset = 1U;
OffsetBit::Set<uint32_t>(bitOffset, &handler);
AccessorBit::Set<uint32_t>(true, &handler);
uint32_t arrayLength = bitOffset + 1U;
JSHandle<JSObject> handleHolder = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
JSHandle<TaggedArray> handleTaggedArr = factory->NewTaggedArray(arrayLength);
handleTaggedArr->Set(thread, bitOffset, handleAccessor.GetTaggedValue());
handleHolder->SetProperties(thread, handleTaggedArr.GetTaggedValue());
JSHandle<JSObject> handleReceiver = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handleReceiver), keyHandle, valueHandle);
JSTaggedValue resultValue1 =
ICRuntimeStub::LoadICWithHandler(thread, handleReceiver.GetTaggedValue(),
handleHolder.GetTaggedValue(), JSTaggedValue(handler));
EXPECT_EQ(resultValue1.GetInt(), 1);
KindBit::Set<uint32_t>(HandlerKind::NON_EXIST, &handler);
JSTaggedValue resultValue3 =
ICRuntimeStub::LoadICWithHandler(thread, handleReceiver.GetTaggedValue(),
handleHolder.GetTaggedValue(), JSTaggedValue(handler));
EXPECT_TRUE(resultValue3.IsUndefined());
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<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
JSHandle<ProtoChangeMarker> cellValue = factory->NewProtoChangeMarker();
EXPECT_TRUE(!cellValue->GetHasChanged());
uint32_t handler = 0U;
uint32_t bitOffset = 1U;
OffsetBit::Set<uint32_t>(bitOffset, &handler);
KindBit::Set<uint32_t>(HandlerKind::FIELD, &handler);
uint32_t arrayLength = bitOffset + 1U;
JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
JSHandle<TaggedArray> handleTaggedArr = factory->NewTaggedArray(arrayLength);
handleObj->SetProperties(thread, handleTaggedArr.GetTaggedValue());
JSHandle<PrototypeHandler> handleProtoHandler = factory->NewPrototypeHandler();
handleProtoHandler->SetProtoCell(thread, cellValue.GetTaggedValue());
handleProtoHandler->SetHandlerInfo(thread, JSTaggedValue(handler));
handleProtoHandler->SetHolder(thread, handleObj.GetTaggedValue());
JSTaggedValue resultValue1 = ICRuntimeStub::StorePrototype(thread, handleObj.GetTaggedValue(),
JSTaggedValue(1), handleProtoHandler.GetTaggedValue());
EXPECT_TRUE(resultValue1.IsUndefined());
JSTaggedValue resultValue2 =
ICRuntimeStub::LoadPrototype(thread, handleObj.GetTaggedValue(), handleProtoHandler.GetTaggedValue());
EXPECT_EQ(ICRuntimeStub::LoadFromField(thread, *handleObj, handler).GetInt(), resultValue2.GetInt());
}
HWTEST_F_L0(ICRuntimeStubTest, StoreWithTransition_In_Filed)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
JSHandle<JSTaggedValue> arrFun = env->GetArrayFunction();
JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
JSHandle<JSHClass> originHClass(thread, handleObj->GetJSHClass());
JSHandle<JSObject> handleArrObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(arrFun), arrFun);
auto hclass = handleArrObj->SynchronizedGetClass();
uint32_t handler = 0U;
uint32_t bitOffset = 1U;
OffsetBit::Set<uint32_t>(bitOffset, &handler);
KindBit::Set<uint32_t>(HandlerKind::FIELD, &handler);
uint32_t arrayLength = bitOffset + 1U;
JSHandle<TaggedArray> handleTaggedArr = factory->NewTaggedArray(arrayLength);
handleObj->SetProperties(thread, handleTaggedArr.GetTaggedValue());
JSHandle<TransitionHandler> handleTranHandler = factory->NewTransitionHandler();
handleTranHandler->SetTransitionHClass(thread, JSTaggedValue(hclass));
handleTranHandler->SetHandlerInfo(thread, JSTaggedValue(handler));
InlinedPropsBit::Set<uint32_t>(true, &handler);
ICRuntimeStub::StoreWithTransition(thread, *handleObj, JSTaggedValue(2), handleTranHandler.GetTaggedValue());
auto resultArray = TaggedArray::Cast(handleObj->GetProperties(thread).GetTaggedObject());
EXPECT_EQ(resultArray->Get(thread, bitOffset).GetInt(), 2);
handleObj->SynchronizedTransitionClass(thread, *originHClass);
}
HWTEST_F_L0(ICRuntimeStubTest, Field_StoreAndLoad)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
uint32_t handler = 0U;
uint32_t bitOffset = 2U;
OffsetBit::Set<uint32_t>(bitOffset, &handler);
uint32_t arrayLength = bitOffset + 1U;
JSHandle<TaggedArray> handleTaggedArr = factory->NewTaggedArray(arrayLength);
handleTaggedArr->Set(thread, bitOffset, JSTaggedValue::Undefined());
JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
handleObj->SetProperties(thread, handleTaggedArr.GetTaggedValue());
ICRuntimeStub::StoreField(thread, *handleObj, JSTaggedValue(3), handler);
JSTaggedValue resultValue1 = ICRuntimeStub::LoadFromField(thread, *handleObj, handler);
EXPECT_EQ(resultValue1.GetInt(), 3);
InlinedPropsBit::Set<uint32_t>(true, &handler);
ICRuntimeStub::StoreField(thread, *handleObj, JSTaggedValue(2), handler);
JSTaggedValue resultValue = ICRuntimeStub::LoadFromField(thread, *handleObj, handler);
EXPECT_EQ(resultValue.GetInt(), 2);
}
HWTEST_F_L0(ICRuntimeStubTest, Global_StoreAndLoad)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSTaggedValue> handleUndefinedVal(thread, JSTaggedValue::Undefined());
JSHandle<PropertyBox> handlerValue = factory->NewPropertyBox(handleUndefinedVal);
JSTaggedValue resultValue1 = ICRuntimeStub::StoreGlobal(thread, JSTaggedValue(2), handlerValue.GetTaggedValue());
EXPECT_TRUE(resultValue1.IsUndefined());
JSTaggedValue resultValue2 = ICRuntimeStub::LoadGlobal(thread, 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(thread, handlerValue.GetTaggedValue());
EXPECT_TRUE(resultValue4.IsHole());
}
HWTEST_F_L0(ICRuntimeStubTest, Element_StoreAndLoad)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSTaggedValue> lengthKey = thread->GlobalConstants()->GetHandledLengthString();
JSTaggedValue handleIntKey(4);
uint32_t handlerInfo = 0U;
KindBit::Set<uint32_t>(HandlerKind::ELEMENT, &handlerInfo);
IsJSArrayBit::Set<uint32_t>(true, &handlerInfo);
uint32_t arrayLength = 3U;
JSArray *handleArr = JSArray::ArrayCreate(thread, JSTaggedNumber(arrayLength)).GetObject<JSArray>();
JSHandle<JSObject> handleArrObj(thread, handleArr);
JSHandle<TaggedArray> handleTaggedArr = factory->NewTaggedArray(arrayLength);
handleArrObj->SetProperties(thread, handleTaggedArr.GetTaggedValue());
JSTaggedValue resultValue =
ICRuntimeStub::StoreElement(thread, *handleArrObj, handleIntKey, JSTaggedValue(3), JSTaggedValue(handlerInfo));
EXPECT_TRUE(resultValue.IsUndefined());
EXPECT_EQ(ICRuntimeStub::LoadElement(thread, *handleArrObj, handleIntKey).GetInt(), 3);
EXPECT_EQ(JSObject::GetProperty(thread, handleArrObj, lengthKey).GetValue()->GetInt(), 5);
EXPECT_TRUE(ICRuntimeStub::LoadElement(thread, *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<JSTaggedValue> handleStrKey1(factory->NewFromASCII("1234"));
JSHandle<JSTaggedValue> handleStrKey2(factory->NewFromASCII("xy"));
EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(thread, hanldeIntKey1), 0);
EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(thread, hanldeIntKey2), 1);
EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(thread, handleDoubleKey1), 1);
EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(thread, handleDoubleKey2), -1);
EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(thread, handleStrKey1.GetTaggedValue()), 1234);
EXPECT_EQ(ICRuntimeStub::TryToElementsIndex(thread, handleStrKey2.GetTaggedValue()), -1);
}
}