1/*
2 * Copyright (c) 2021 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/ecma_vm.h"
17#include "ecmascript/ic/invoke_cache.h"
18#include "ecmascript/object_factory.h"
19#include "ecmascript/tests/test_helper.h"
20
21using namespace panda::ecmascript;
22namespace panda::test {
23class ICInvokeTest : public testing::Test {
24public:
25    static void SetUpTestCase()
26    {
27        GTEST_LOG_(INFO) << "SetUpTestCase";
28    }
29
30    static void TearDownTestCase()
31    {
32        GTEST_LOG_(INFO) << "TearDownCase";
33    }
34
35    void SetUp() override
36    {
37        TestHelper::CreateEcmaVMWithScope(ecmaVm, thread, scope);
38    }
39
40    void TearDown() override
41    {
42        TestHelper::DestroyEcmaVMWithScope(ecmaVm, scope);
43    }
44
45    EcmaVM *ecmaVm = nullptr;
46    EcmaHandleScope *scope {nullptr};
47    JSThread *thread {nullptr};
48};
49
50HWTEST_F_L0(ICInvokeTest, SetMonoConstuctCacheSlot)
51{
52    auto globalEnv = ecmaVm->GetGlobalEnv();
53    auto factory = ecmaVm->GetFactory();
54    JSHandle<JSFunction> func = factory->NewJSFunction(globalEnv);
55    func.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassConstructor(true);
56
57    JSHandle<TaggedArray> array = factory->NewTaggedArray(10);
58    uint32_t slotId = 5;
59    bool setResult = InvokeCache::SetMonoConstuctCacheSlot(
60        thread, static_cast<ProfileTypeInfo *>(*array), slotId, func.GetTaggedValue(), JSTaggedValue(123));
61    ASSERT_TRUE(setResult);
62    ASSERT_EQ(array->Get(thread, slotId), func.GetTaggedValue());
63    ASSERT_EQ(array->Get(thread, slotId + 1), JSTaggedValue(123));
64}
65
66HWTEST_F_L0(ICInvokeTest, SetPolyConstuctCacheSlot)
67{
68    auto globalEnv = ecmaVm->GetGlobalEnv();
69    auto factory = ecmaVm->GetFactory();
70    JSHandle<TaggedArray> array1 = factory->NewTaggedArray(3);
71    JSHandle<TaggedArray> array2 = factory->NewTaggedArray(3);
72
73    JSHandle<JSFunction> func0 = factory->NewJSFunction(globalEnv);
74    func0.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassConstructor(true);
75    array1->Set(thread, 0, func0.GetTaggedValue());
76    array2->Set(thread, 0, JSTaggedValue(123));
77    JSHandle<JSFunction> func1 = factory->NewJSFunction(globalEnv);
78    func1.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassConstructor(true);
79    array1->Set(thread, 1, func1.GetTaggedValue());
80    array2->Set(thread, 1, JSTaggedValue(456));
81    JSHandle<JSFunction> func2 = factory->NewJSFunction(globalEnv);
82    func2.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassConstructor(true);
83    array1->Set(thread, 2, func2.GetTaggedValue());
84    array2->Set(thread, 2, JSTaggedValue(789));
85
86    JSHandle<TaggedArray> array = factory->NewTaggedArray(10);
87    uint32_t slotId = 5;
88    bool setResult = InvokeCache::SetPolyConstuctCacheSlot(
89        thread, static_cast<ProfileTypeInfo *>(*array), slotId, 3, array1.GetTaggedValue(), array2.GetTaggedValue());
90    ASSERT_TRUE(setResult);
91    JSTaggedValue slot = array->Get(thread, slotId);
92    ASSERT_TRUE(slot.IsTaggedArray());
93    JSHandle<TaggedArray> slotArray(thread, slot);
94    ASSERT_EQ(slotArray->Get(thread, 0), func0.GetTaggedValue());
95    ASSERT_EQ(slotArray->Get(thread, 1), JSTaggedValue(123));
96    ASSERT_EQ(slotArray->Get(thread, 2), func1.GetTaggedValue());
97    ASSERT_EQ(slotArray->Get(thread, 3), JSTaggedValue(456));
98    ASSERT_EQ(slotArray->Get(thread, 4), func2.GetTaggedValue());
99    ASSERT_EQ(slotArray->Get(thread, 5), JSTaggedValue(789));
100    ASSERT_EQ(array->Get(thread, slotId + 1), JSTaggedValue::Hole());
101}
102
103HWTEST_F_L0(ICInvokeTest, CheckPolyInvokeCache)
104{
105    auto globalEnv = ecmaVm->GetGlobalEnv();
106    auto factory = ecmaVm->GetFactory();
107    JSHandle<TaggedArray> array = factory->NewTaggedArray(6);
108
109    JSHandle<JSFunction> func0 = factory->NewJSFunction(globalEnv);
110    JSHandle<JSFunction> func1 = factory->NewJSFunction(globalEnv);
111    JSHandle<JSFunction> func2 = factory->NewJSFunction(globalEnv);
112    JSHandle<JSFunction> func3 = factory->NewJSFunction(globalEnv);
113    array->Set(thread, 0, func0.GetTaggedValue());
114    array->Set(thread, 1, JSTaggedValue(123));
115    array->Set(thread, 2, func1.GetTaggedValue());
116    array->Set(thread, 3, JSTaggedValue(456));
117    array->Set(thread, 4, func2.GetTaggedValue());
118    array->Set(thread, 5, JSTaggedValue(789));
119
120    JSTaggedValue testValue0 = InvokeCache::CheckPolyInvokeCache(array.GetTaggedValue(), func0.GetTaggedValue());
121    ASSERT_EQ(testValue0, JSTaggedValue(123));
122    JSTaggedValue testValue1 = InvokeCache::CheckPolyInvokeCache(array.GetTaggedValue(), func1.GetTaggedValue());
123    ASSERT_EQ(testValue1, JSTaggedValue(456));
124    JSTaggedValue testValue2 = InvokeCache::CheckPolyInvokeCache(array.GetTaggedValue(), func2.GetTaggedValue());
125    ASSERT_EQ(testValue2, JSTaggedValue(789));
126    JSTaggedValue testValue3 = InvokeCache::CheckPolyInvokeCache(array.GetTaggedValue(), func3.GetTaggedValue());
127    ASSERT_EQ(testValue3, JSTaggedValue::Hole());
128}
129} // namespace panda::test