• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.h"
17 #include "ecmascript/interpreter/slow_runtime_stub.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/object_operator.h"
20 #include "ecmascript/tests/test_helper.h"
21 
22 using namespace panda;
23 using namespace panda::ecmascript;
24 
25 namespace panda::test {
26 class ICRunTimeTest : public testing::Test {
27 public:
SetUpTestCase()28     static void SetUpTestCase()
29     {
30         GTEST_LOG_(INFO) << "SetUpTestCase";
31     }
32 
TearDownTestCase()33     static void TearDownTestCase()
34     {
35         GTEST_LOG_(INFO) << "TearDownCase";
36     }
37 
SetUp()38     void SetUp() override
39     {
40         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
41     }
42 
TearDown()43     void TearDown() override
44     {
45         TestHelper::DestroyEcmaVMWithScope(instance, scope);
46     }
47 
48     EcmaVM *instance {nullptr};
49     EcmaHandleScope *scope {nullptr};
50     JSThread *thread {nullptr};
51 };
52 
HWTEST_F_L0(ICRunTimeTest,UpdateLoadHandler)53 HWTEST_F_L0(ICRunTimeTest, UpdateLoadHandler)
54 {
55     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
56     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
57     auto globalConst = thread->GlobalConstants();
58     uint32_t arrayLength = 5;
59 
60     JSHandle<JSTaggedValue> objFun = env->GetArrayFunction();
61     JSHandle<JSTaggedValue> handleReceiver(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
62     JSHandle<JSTaggedValue> handleKeyWithElement(factory->NewFromASCII("2"));
63     JSHandle<JSTaggedValue> handleKeyWithString(factory->NewFromASCII("key"));
64     JSHandle<JSTaggedValue> handleStoreArray(factory->NewTaggedArray(2));
65     JSHandle<JSTaggedValue> undefinedVal;
66 
67     JSHandle<TaggedArray> handleTaggedArray = factory->NewTaggedArray(arrayLength);
68     for (uint32_t i = 0; i < arrayLength; i++) {
69         undefinedVal = globalConst->GetHandledUndefinedString();
70         if (i == static_cast<uint32_t>(ICKind::NamedLoadIC) || i == static_cast<uint32_t>(ICKind::LoadIC)) {
71             undefinedVal = handleStoreArray;
72         }
73         else if (i == static_cast<uint32_t>(ICKind::NamedLoadIC) + 1 ||
74                  i == static_cast<uint32_t>(ICKind::LoadIC) + 1) {
75             undefinedVal = JSHandle<JSTaggedValue>(thread, JSTaggedValue::Hole());
76         }
77         handleTaggedArray->Set(thread, i, undefinedVal.GetTaggedValue());
78     }
79     JSHandle<ProfileTypeInfo> handleProfileTypeInfo = JSHandle<ProfileTypeInfo>::Cast(handleTaggedArray);
80     // test op is Element
81     ObjectOperator handleOp1(thread, handleKeyWithElement);
82     uint32_t slotId = 2;
83     ICRuntime icRuntime(thread, handleProfileTypeInfo, slotId, ICKind::LoadIC);
84     icRuntime.UpdateLoadHandler(handleOp1, handleKeyWithElement, handleReceiver);
85     EXPECT_TRUE(handleProfileTypeInfo->Get(slotId).IsTaggedArray());
86     EXPECT_TRUE(handleProfileTypeInfo->Get(slotId + 1).IsHole());
87     // test op is not Element
88     ObjectOperator handleOp2(thread, handleKeyWithString);
89     slotId = 0;
90     ICRuntime icRuntime1(thread, handleProfileTypeInfo, slotId, ICKind::NamedLoadIC);
91     icRuntime1.UpdateLoadHandler(handleOp2, handleKeyWithString, handleReceiver);
92     EXPECT_TRUE(handleProfileTypeInfo->Get(slotId).IsTaggedArray());
93     EXPECT_TRUE(handleProfileTypeInfo->Get(slotId + 1).IsHole());
94 }
95 
HWTEST_F_L0(ICRunTimeTest,UpdateStoreHandler)96 HWTEST_F_L0(ICRunTimeTest, UpdateStoreHandler)
97 {
98     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
99     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
100     auto globalConst = thread->GlobalConstants();
101     uint32_t arrayLength = 5;
102 
103     JSHandle<JSTaggedValue> objFun = env->GetArrayFunction();
104     JSHandle<JSTaggedValue> handleReceiver(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
105     JSHandle<JSTaggedValue> handleKeyWithElement(factory->NewFromASCII("2"));
106     JSHandle<JSTaggedValue> handleKeyWithString(factory->NewFromASCII("key"));
107     JSHandle<JSTaggedValue> handleStoreArray(factory->NewTaggedArray(2));
108     JSHandle<JSTaggedValue> undefinedVal;
109 
110     JSHandle<TaggedArray> handleTaggedArray = factory->NewTaggedArray(arrayLength);
111     for (uint32_t i = 0; i < arrayLength; i++) {
112         undefinedVal = globalConst->GetHandledUndefinedString();
113         if (i == static_cast<uint32_t>(ICKind::NamedStoreIC) || i == static_cast<uint32_t>(ICKind::StoreIC)) {
114             undefinedVal = JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined());
115         }
116         else if (i == static_cast<uint32_t>(ICKind::NamedStoreIC) + 1 ||
117                  i == static_cast<uint32_t>(ICKind::StoreIC) + 1) {
118             undefinedVal = handleStoreArray;
119         }
120         handleTaggedArray->Set(thread, i, undefinedVal.GetTaggedValue());
121     }
122     JSHandle<ProfileTypeInfo> handleProfileTypeInfo = JSHandle<ProfileTypeInfo>::Cast(handleTaggedArray);
123     // test op is Element
124     uint32_t slotId = 3;
125     ObjectOperator handleOp1(thread, handleKeyWithElement);
126     handleOp1.SetIsOnPrototype(true);
127     handleOp1.SetIndex(slotId);
128     ICRuntime icRuntime(thread, handleProfileTypeInfo, slotId, ICKind::StoreIC);
129     icRuntime.UpdateReceiverHClass(JSHandle<JSTaggedValue>(thread, JSHandle<JSObject>(handleReceiver)->GetJSHClass()));
130     icRuntime.UpdateStoreHandler(handleOp1, handleKeyWithElement, handleReceiver);
131     EXPECT_TRUE(handleProfileTypeInfo->Get(slotId).IsWeak());
132     EXPECT_TRUE(handleProfileTypeInfo->Get(slotId + 1).IsPrototypeHandler());
133     // test op is Transition
134     slotId = 1;
135     ObjectOperator handleOp2(thread, handleReceiver, handleKeyWithString, OperatorType::OWN);
136     handleOp2.SetIsTransition(true);
137     handleOp2.SetFastMode(true);
138     handleOp2.SetIndex(slotId);
139     ICRuntime icRuntime1(thread, handleProfileTypeInfo, slotId, ICKind::NamedStoreIC);
140     icRuntime1.UpdateReceiverHClass(env->GetArgumentsClass());
141     icRuntime1.UpdateStoreHandler(handleOp2, handleKeyWithString, handleReceiver);
142     EXPECT_TRUE(handleProfileTypeInfo->Get(slotId).IsWeak());
143     EXPECT_TRUE(handleProfileTypeInfo->Get(slotId + 1).IsTransitionHandler());
144 }
145 
HWTEST_F_L0(ICRunTimeTest,TraceIC)146 HWTEST_F_L0(ICRunTimeTest, TraceIC)
147 {
148     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
149     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
150     uint32_t arrayLength = 5;
151     JSHandle<JSTaggedValue> objFun = env->GetArrayFunction();
152     JSHandle<JSTaggedValue> handleReceiver(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
153     JSHandle<JSTaggedValue> handleKeyWithString(factory->NewFromASCII("key"));
154     JSHandle<JSTaggedValue> handleKeyWithElement(thread, JSTaggedValue(2));
155 
156     JSHandle<TaggedArray> handleTaggedArray = factory->NewTaggedArray(arrayLength);
157     JSHandle<ProfileTypeInfo> handleProfileTypeInfo = JSHandle<ProfileTypeInfo>::Cast(handleTaggedArray);
158 
159     ICRuntime icRuntime(thread, handleProfileTypeInfo, 4, ICKind::NamedGlobalLoadIC);  // 4: means the NamedGlobalLoadIC
160     icRuntime.TraceIC(handleReceiver, handleKeyWithString);
161     icRuntime.TraceIC(handleReceiver, handleKeyWithElement);
162 }
163 
HWTEST_F_L0(ICRunTimeTest,StoreMiss)164 HWTEST_F_L0(ICRunTimeTest, StoreMiss)
165 {
166     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
167     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
168     uint32_t arrayLength = 2;
169 
170     JSHandle<JSTaggedValue> objFun = env->GetTypedArrayFunction();
171     JSHandle<JSTaggedValue> handleReceiver(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
172     JSHandle<JSTaggedValue> handleReceiver1(factory->NewJSArray());
173     JSHandle<JSTaggedValue> handleKeyWithString(factory->NewFromASCII("key"));
174     JSHandle<JSTaggedValue> handleValueWithElement(thread, JSTaggedValue(2));
175 
176     JSHandle<TaggedArray> handleTaggedArray = factory->NewTaggedArray(arrayLength);
177     JSHandle<ProfileTypeInfo> handleProfileTypeInfo = JSHandle<ProfileTypeInfo>::Cast(handleTaggedArray);
178     StoreICRuntime storeICRuntime(thread, handleProfileTypeInfo, 0, ICKind::NamedGlobalStoreIC);
179     storeICRuntime.StoreMiss(handleReceiver, handleKeyWithString, handleValueWithElement);
180     EXPECT_EQ(JSObject::GetProperty(thread, handleReceiver, handleKeyWithString).GetValue(), handleValueWithElement);
181     EXPECT_TRUE(handleProfileTypeInfo->Get(0).IsHole());
182     EXPECT_TRUE(handleProfileTypeInfo->Get(1).IsHole());
183 
184     SlowRuntimeStub::StGlobalRecord(thread, handleKeyWithString.GetTaggedValue(),
185                                     handleKeyWithString.GetTaggedValue(), false);
186     handleTaggedArray->Set(thread, 0, JSTaggedValue::Undefined());
187     storeICRuntime.StoreMiss(handleReceiver1, handleKeyWithString, handleValueWithElement);
188     EXPECT_TRUE(handleProfileTypeInfo->Get(0).IsPropertyBox());
189 }
190 
HWTEST_F_L0(ICRunTimeTest,LoadMiss)191 HWTEST_F_L0(ICRunTimeTest, LoadMiss)
192 {
193     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
194     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
195     uint32_t arrayLength = 2;
196 
197     JSHandle<JSTaggedValue> objFun = env->GetTypedArrayFunction();
198     JSHandle<JSTaggedValue> handleReceiver(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
199     JSHandle<JSTaggedValue> handleReceiver1(factory->NewJSArray());
200     JSHandle<JSTaggedValue> handleKeyWithString(factory->NewFromASCII("key"));
201     JSHandle<JSTaggedValue> handleValueWithElement(thread, JSTaggedValue(2));
202     JSObject::SetProperty(thread, handleReceiver, handleKeyWithString, handleValueWithElement);
203 
204     JSHandle<TaggedArray> handleTaggedArray = factory->NewTaggedArray(arrayLength);
205     JSHandle<ProfileTypeInfo> handleProfileTypeInfo = JSHandle<ProfileTypeInfo>::Cast(handleTaggedArray);
206     LoadICRuntime loadICRuntime(thread, handleProfileTypeInfo, 0, ICKind::NamedGlobalStoreIC);
207     EXPECT_EQ(loadICRuntime.LoadMiss(handleReceiver, handleKeyWithString), handleValueWithElement.GetTaggedValue());
208     EXPECT_TRUE(handleProfileTypeInfo->Get(0).IsHole());
209     EXPECT_TRUE(handleProfileTypeInfo->Get(1).IsHole());
210 }
211 }  // namespace panda::test
212