• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/ic/ic_handler.h"
17 #include "ecmascript/ic/proto_change_details.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/js_array.h"
20 #include "ecmascript/js_hclass.h"
21 #include "ecmascript/js_object-inl.h"
22 #include "ecmascript/object_operator.h"
23 #include "ecmascript/tests/test_helper.h"
24 
25 using namespace panda::ecmascript;
26 
27 namespace panda::test {
28 using HandlerKind = ecmascript::HandlerBase::HandlerKind;
29 class ICHandlerTest : public testing::Test {
30 public:
SetUpTestCase()31     static void SetUpTestCase()
32     {
33         GTEST_LOG_(INFO) << "SetUpTestCase";
34     }
35 
TearDownTestCase()36     static void TearDownTestCase()
37     {
38         GTEST_LOG_(INFO) << "TearDownCase";
39     }
40 
SetUp()41     void SetUp() override
42     {
43         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
44     }
45 
TearDown()46     void TearDown() override
47     {
48         TestHelper::DestroyEcmaVMWithScope(instance, scope);
49     }
50 
51     EcmaVM *instance {nullptr};
52     EcmaHandleScope *scope {nullptr};
53     JSThread *thread {nullptr};
54 };
55 
56 /**
57  * @tc.name: LoadElement
58  * @tc.desc: Call "LoadElement" function,check whether the Element is loaded successfully by checking returned value.
59  * @tc.type: FUNC
60  * @tc.require:
61  */
HWTEST_F_L0(ICHandlerTest,LoadElement)62 HWTEST_F_L0(ICHandlerTest, LoadElement)
63 {
64     JSTaggedValue result = LoadHandler::LoadElement(thread).GetTaggedValue();
65     EXPECT_TRUE(HandlerBase::IsElement(result.GetInt()));
66     EXPECT_EQ(HandlerBase::GetKind(result.GetInt()), HandlerKind::ELEMENT);
67 }
68 
69 /**
70  * @tc.name: LoadProperty
71  * @tc.desc: Call "LoadProperty" function,check whether the Property is loaded successfully by checking returned value.
72  * @tc.type: FUNC
73  * @tc.require:
74  */
HWTEST_F_L0(ICHandlerTest,LoadProperty)75 HWTEST_F_L0(ICHandlerTest, LoadProperty)
76 {
77     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
78     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
79 
80     JSHandle<JSTaggedValue> objFun = env->GetArrayFunction();
81     JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(1));
82     JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
83     int index = 1;
84     PropertyAttributes handleAttriButes(2);
85     handleAttriButes.SetIsInlinedProps(true);
86     // test op is not Found
87     ObjectOperator handleOp1(thread, handleKey);
88     JSHandle<JSTaggedValue> handlerInfo1 = LoadHandler::LoadProperty(thread, handleOp1);
89     EXPECT_TRUE(HandlerBase::IsNonExist(handlerInfo1->GetInt()));
90     EXPECT_EQ(HandlerBase::GetKind(handlerInfo1->GetInt()), HandlerKind::NON_EXIST);
91     // test op is Found and FastMode
92     JSHandle<JSTaggedValue> handleHolder(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
93     ObjectOperator handleOp2(thread, handleHolder, handleKey);
94     handleOp2.SetFastMode(true);
95     handleOp2.SetIndex(index);
96     JSHandle<JSTaggedValue> handlerInfo2 = LoadHandler::LoadProperty(thread, handleOp2);
97     EXPECT_EQ(HandlerBase::GetOffset(handlerInfo2->GetInt()), 1);
98     // test op is Found and InlinedProps
99     handleOp2.SetAttr(handleAttriButes);
100     JSHandle<JSTaggedValue> handlerInfo3 = LoadHandler::LoadProperty(thread, handleOp2);
101     EXPECT_EQ(HandlerBase::GetKind(handlerInfo3->GetInt()), HandlerKind::FIELD);
102     EXPECT_EQ(HandlerBase::GetOffset(handlerInfo3->GetInt()), 5);
103     EXPECT_TRUE(HandlerBase::IsInlinedProps(handlerInfo3->GetInt()));
104 }
105 
106 /**
107  * @tc.name: StoreElement
108  * @tc.desc: Call "StoreElement" function,check whether the Element is stored successfully by checking returned value.
109  * @tc.type: FUNC
110  * @tc.require:
111  */
HWTEST_F_L0(ICHandlerTest,StoreElement)112 HWTEST_F_L0(ICHandlerTest, StoreElement)
113 {
114     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
115 
116     JSArray *handleArr = JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetObject<JSArray>();
117     JSHandle<JSTaggedValue> handleReceiver1(thread, handleArr);
118     JSHandle<JSTaggedValue> handleReceiver2(factory->NewJSArray());
119     JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(1));
120 
121     JSHandle<JSTaggedValue> handlerInfo1 = StoreHandler::StoreElement(thread, handleReceiver1);
122     JSHandle<JSTaggedValue> handlerInfo2 = StoreHandler::StoreElement(thread, handleReceiver2);
123     JSHandle<JSTaggedValue> handlerInfo3 = StoreHandler::StoreElement(thread, handleValue);
124 
125     EXPECT_EQ(HandlerBase::GetKind(handlerInfo1->GetInt()), HandlerKind::ELEMENT);
126     EXPECT_EQ(HandlerBase::GetKind(handlerInfo2->GetInt()), HandlerKind::ELEMENT);
127     EXPECT_EQ(HandlerBase::GetKind(handlerInfo3->GetInt()), HandlerKind::ELEMENT);
128 
129     EXPECT_TRUE(HandlerBase::IsJSArray(handlerInfo1->GetInt()));
130     EXPECT_TRUE(HandlerBase::IsJSArray(handlerInfo2->GetInt()));
131     EXPECT_FALSE(HandlerBase::IsJSArray(handlerInfo3->GetInt()));
132 }
133 
134 /**
135  * @tc.name: StoreProperty
136  * @tc.desc: Call "StoreProperty" function,check whether the Property is stored successfully by checking returned value.
137  *           according to the ObjectOperation object,the stored Property is different,the stored ObjectOperation object
138  *           is Found.
139  * @tc.type: FUNC
140  * @tc.require:
141  */
HWTEST_F_L0(ICHandlerTest,StoreProperty)142 HWTEST_F_L0(ICHandlerTest, StoreProperty)
143 {
144     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
145     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
146 
147     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
148     JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(1));
149     JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
150     int index = 2;
151     PropertyAttributes handleAttriButes(2);
152     handleAttriButes.SetIsInlinedProps(true);
153 
154     JSHandle<PropertyBox> cellHandle = factory->NewPropertyBox(handleKey);
155     ObjectOperator handleOp1(thread, handleKey);
156     handleOp1.SetValue(cellHandle.GetTaggedValue());
157     // test op value is PropertyBox
158     JSHandle<JSTaggedValue> handlerInfo1 = StoreHandler::StoreProperty(thread, handleOp1);
159     EXPECT_TRUE(handlerInfo1->IsPropertyBox());
160     // test op is FastMode/Found and not AccessorDescriptor
161     JSHandle<JSTaggedValue> handleReceiver(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
162     ObjectOperator handleOp2(thread, handleReceiver, handleKey);
163     handleOp2.SetFastMode(true);
164     handleOp2.SetIndex(index);
165     JSHandle<JSTaggedValue> handlerInfo2 = StoreHandler::StoreProperty(thread, handleOp2);
166     EXPECT_EQ(HandlerBase::GetOffset(handlerInfo2->GetInt()), 2);
167     EXPECT_FALSE(HandlerBase::IsAccessor(handlerInfo2->GetInt()));
168     // test op is InlinedProps/Found and not AccessorDescriptor
169     handleOp2.SetAttr(handleAttriButes);
170     JSHandle<JSTaggedValue> handlerInfo3 = StoreHandler::StoreProperty(thread, handleOp2);
171     EXPECT_EQ(HandlerBase::GetKind(handlerInfo3->GetInt()), HandlerKind::FIELD);
172     EXPECT_EQ(HandlerBase::GetOffset(handlerInfo3->GetInt()), 6);
173     EXPECT_TRUE(HandlerBase::IsInlinedProps(handlerInfo3->GetInt()));
174 }
175 
176 /**
177  * @tc.name: StoreTransition
178  * @tc.desc: Call "StoreTransition" function,check whether the Transition is stored successfully by checking
179  *           returned value.
180  * @tc.type: FUNC
181  * @tc.require:
182  */
HWTEST_F_L0(ICHandlerTest,StoreTransition)183 HWTEST_F_L0(ICHandlerTest, StoreTransition)
184 {
185     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
186     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
187     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
188     JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(1));
189     JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
190 
191     JSHandle<PropertyBox> cellHandle = factory->NewPropertyBox(handleKey);
192     JSHandle<JSTaggedValue> handleHolder(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
193 
194     ObjectOperator handleOp(thread, handleHolder, handleKey);
195     handleOp.SetValue(cellHandle.GetTaggedValue());
196 
197     JSHandle<JSTaggedValue> handlerValue = TransitionHandler::StoreTransition(thread, handleOp);
198     JSHandle<TransitionHandler> handler = JSHandle<TransitionHandler>::Cast(handlerValue);
199     EXPECT_TRUE(handler->GetHandlerInfo().IsPropertyBox());
200     EXPECT_TRUE(handler->GetTransitionHClass().IsHeapObject());
201 }
202 
203 /**
204  * @tc.name: LoadPrototype
205  * @tc.desc: Call "LoadPrototype" function,check whether the Prototype is loaded successfully by checking returned value
206  *           according to the ObjectOperation object,the stored Property is different.
207  * @tc.type: FUNC
208  * @tc.require:
209  */
HWTEST_F_L0(ICHandlerTest,LoadPrototype)210 HWTEST_F_L0(ICHandlerTest, LoadPrototype)
211 {
212     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
213 
214     JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
215     JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(3));
216 
217     JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
218     JSHandle<JSObject> handleObj1 = JSObject::ObjectCreate(thread, nullHandle);
219     JSHandle<JSObject> handleObj2 = JSObject::ObjectCreate(thread, handleObj1);
220 
221     JSHandle<JSHClass> obj1Class(thread, handleObj1->GetJSHClass());
222     JSHandle<JSHClass> obj2Class(thread, handleObj2->GetJSHClass());
223 
224     ObjectOperator handleOp1(thread, handleKey, OperatorType::OWN);
225     ObjectOperator handleOp2(thread, handleKey, OperatorType::OWN);
226     handleOp1.SetFastMode(true);
227     handleOp2.SetFastMode(true);
228     handleOp2.SetIndex(2);
229     // test op is not Found and hclass has no Prototype
230     JSHandle<JSTaggedValue> handlerValue1 = LoadHandler::LoadProperty(thread, handleOp1);
231     EXPECT_TRUE(HandlerBase::IsNonExist(handlerValue1->GetInt()));
232     // test op is Found and hclass has Prototype
233     JSHandle<JSTaggedValue> handlerValue2 = PrototypeHandler::LoadPrototype(thread, handleOp2, obj2Class);
234     JSHandle<PrototypeHandler> handler2 = JSHandle<PrototypeHandler>::Cast(handlerValue2);
235     JSHandle<JSTaggedValue> handlerInfo2(thread, handler2->GetHandlerInfo());
236     EXPECT_EQ(HandlerBase::GetOffset(handlerInfo2->GetInt()), 2);
237     JSHandle<JSTaggedValue> resultMarker(thread, handler2->GetProtoCell());
238     EXPECT_TRUE(resultMarker->IsProtoChangeMarker());
239     EXPECT_TRUE(handler2->GetHolder().IsJSGlobalObject());
240 }
241 
242 /**
243  * @tc.name: StorePrototype
244  * @tc.desc: Call StorePrototype function,check whether the Prototype is stored successfully by checking returned value
245  *           according to the ObjectOperation object,the stored Property is different.the stored ObjectOperation object
246  *           must be Found.
247  * @tc.type: FUNC
248  * @tc.require:
249  */
HWTEST_F_L0(ICHandlerTest,StorePrototype)250 HWTEST_F_L0(ICHandlerTest, StorePrototype)
251 {
252     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
253 
254     JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
255     JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(3));
256 
257     JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
258     JSHandle<JSObject> nullObj = JSObject::ObjectCreate(thread, nullHandle);
259     JSHandle<JSObject> handleObj = JSObject::ObjectCreate(thread, nullObj);
260 
261     JSHandle<JSHClass> objClass(thread, handleObj->GetJSHClass());
262 
263     ObjectOperator handleOp(thread, handleKey, OperatorType::OWN);
264     handleOp.SetFastMode(true);
265     handleOp.SetIndex(2);
266     // test hclass has Prototype
267     JSHandle<JSTaggedValue> handlerValue = PrototypeHandler::StorePrototype(thread, handleOp, objClass);
268     JSHandle<PrototypeHandler> handler = JSHandle<PrototypeHandler>::Cast(handlerValue);
269     JSHandle<JSTaggedValue> handlerInfo(thread, handler->GetHandlerInfo());
270     EXPECT_EQ(HandlerBase::GetOffset(handlerInfo->GetInt()), 2);
271     JSHandle<JSTaggedValue> resultMarker(thread, handler->GetProtoCell());
272     EXPECT_TRUE(resultMarker->IsProtoChangeMarker());
273     EXPECT_TRUE(handler->GetHolder().IsJSGlobalObject());
274 }
275 } // namespace panda::test
276