1 /*
2  * Copyright (c) 2023 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 #include "ecmascript/compiler/gate_accessor.h"
16 #include "ecmascript/compiler/share_opcodes.h"
17 #include "ecmascript/compiler/verifier.h"
18 #include "ecmascript/compiler/typed_bytecode_lowering.h"
19 #include "ecmascript/compiler/typed_hcr_lowering.h"
20 #include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
21 #include "ecmascript/elements.h"
22 #include "ecmascript/mem/concurrent_marker.h"
23 #include "ecmascript/mem/native_area_allocator.h"
24 #include "ecmascript/tests/test_helper.h"
25 #include "gtest/gtest.h"
26 #include <cstddef>
27 
28 namespace panda::test {
29 class MetaDataEqualTests : public testing::Test {};
30 
31 using ecmascript::kungfu::Circuit;
32 using ecmascript::kungfu::CircuitBuilder;
33 using ecmascript::kungfu::EcmaOpcode;
34 using ecmascript::kungfu::ElementsKind;
35 using ecmascript::kungfu::Environment;
36 using ecmascript::kungfu::GateAccessor;
37 using ecmascript::kungfu::GateMetaData;
38 using ecmascript::kungfu::GateType;
39 using ecmascript::kungfu::JSBytecodeMetaData;
40 using ecmascript::kungfu::MachineType;
41 using ecmascript::kungfu::PGOTypeRef;
42 using ecmascript::kungfu::PGOSampleType;
43 using ecmascript::kungfu::TypedBinOp;
44 using ecmascript::kungfu::TypedCallTargetCheckOp;
45 using ecmascript::kungfu::ParamType;
46 using ecmascript::kungfu::TypedCallTargetCheckAccessor;
47 
HWTEST_F_L0(MetaDataEqualTests, StringMetaDataEqualTest)48 HWTEST_F_L0(MetaDataEqualTests, StringMetaDataEqualTest)
49 {
50     // construct a circuit
51     ecmascript::NativeAreaAllocator allocator;
52     Circuit circuit(&allocator);
53     ecmascript::Chunk chunk(&allocator);
54     GateAccessor acc(&circuit);
55     CircuitBuilder builder(&circuit);
56     Environment env(0, &builder);
57     builder.SetEnvironment(&env);
58 
59     auto stringGate1 = circuit.GetConstantStringGate(MachineType::ARCH, "test1", GateType::NJSValue());
60 
61 
62     auto stringGate2 = circuit.GetConstantStringGate(MachineType::ARCH, "test2", GateType::NJSValue());
63 
64     EXPECT_FALSE(acc.MetaDataValueEqu(stringGate1, stringGate2));
65 
66     auto stringGate3 = circuit.GetConstantStringGate(MachineType::ARCH, "test1", GateType::NJSValue());
67 
68     EXPECT_TRUE(acc.MetaDataValueEqu(stringGate1, stringGate3));
69 }
70 
HWTEST_F_L0(MetaDataEqualTests, ConstantMetaDataEqualTest)71 HWTEST_F_L0(MetaDataEqualTests, ConstantMetaDataEqualTest)
72 {
73     // construct a circuit
74     ecmascript::NativeAreaAllocator allocator;
75     Circuit circuit(&allocator);
76     ecmascript::Chunk chunk(&allocator);
77     GateAccessor acc(&circuit);
78     CircuitBuilder builder(&circuit);
79     Environment env(0, &builder);
80     builder.SetEnvironment(&env);
81 
82 
83     auto constantValue1 = circuit.GetConstantGate(MachineType::I64, 2, GateType::NJSValue());
84 
85     auto constantValue2 = circuit.GetConstantGate(MachineType::I64, 2, GateType::NJSValue());
86 
87     EXPECT_TRUE(acc.MetaDataValueEqu(constantValue1, constantValue2));
88 
89     auto constantValue3 = circuit.GetConstantGate(MachineType::I64, 2, GateType::NJSValue());
90 
91     auto constantValue4 = circuit.GetConstantGate(MachineType::I64, 3, GateType::NJSValue());
92 
93     EXPECT_FALSE(acc.MetaDataValueEqu(constantValue3, constantValue4));
94 
95 
96     // MetaData is equal, but Gate is not equal
97     auto constantValue5 = circuit.GetConstantGate(MachineType::I64, 2, GateType::NJSValue());
98 
99     auto constantValue6 = circuit.GetConstantGate(MachineType::I32, 2, GateType::NJSValue());
100 
101     EXPECT_TRUE(acc.MetaDataValueEqu(constantValue5, constantValue6));
102 
103     // MetaData is equal, but Gate is not equal
104     auto ConstGateNJSValue2 = circuit.GetConstantGate(MachineType::I64, 2, GateType::NJSValue());
105 
106     auto ConstGateUndefined =
107         circuit.GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_UNDEFINED, GateType::UndefinedType());
108 
109     EXPECT_TRUE(acc.MetaDataValueEqu(ConstGateNJSValue2, ConstGateUndefined));
110 }
111 
HWTEST_F_L0(MetaDataEqualTests, TypeErrorMetaDataEqualTest)112 HWTEST_F_L0(MetaDataEqualTests, TypeErrorMetaDataEqualTest)
113 {
114     // construct a circuit
115     ecmascript::NativeAreaAllocator allocator;
116     Circuit circuit(&allocator);
117     ecmascript::Chunk chunk(&allocator);
118     GateAccessor acc(&circuit);
119     CircuitBuilder builder(&circuit);
120     Environment env(0, &builder);
121     builder.SetEnvironment(&env);
122 
123     auto constantValue1 = circuit.GetConstantGate(MachineType::I64, 2, GateType::NJSValue());
124     auto stringGate1 = circuit.GetConstantStringGate(MachineType::ARCH, "test1", GateType::NJSValue());
125     EXPECT_FALSE(acc.MetaDataValueEqu(constantValue1, stringGate1));
126     EXPECT_FALSE(acc.MetaDataValueEqu(stringGate1, constantValue1));
127 }
128 
HWTEST_F_L0(MetaDataEqualTests, HCRMetaDataEqualTest)129 HWTEST_F_L0(MetaDataEqualTests, HCRMetaDataEqualTest)
130 {
131     // construct a circuit
132     ecmascript::NativeAreaAllocator allocator;
133     Circuit circuit(&allocator);
134     ecmascript::Chunk chunk(&allocator);
135     GateAccessor acc(&circuit);
136     CircuitBuilder builder(&circuit);
137     Environment env(0, &builder);
138     builder.SetEnvironment(&env);
139 
140     // JSBytecodeMetaData
141     auto meta = circuit.JSBytecode(0, 0, EcmaOpcode::JEQZ_IMM8, 0, 0, true, false);
142     auto gate =
143         circuit.NewGate(meta, MachineType::I64, {Circuit::NullGate(), Circuit::NullGate()}, GateType::AnyType());
144     auto meta2 = circuit.JSBytecode(0, 0, EcmaOpcode::JEQZ_IMM8, 0, 0, true, false);
145     auto gate2 =
146         circuit.NewGate(meta2, MachineType::I64, {Circuit::NullGate(), Circuit::NullGate()}, GateType::AnyType());
147 
148     EXPECT_TRUE(acc.MetaDataValueEqu(gate, gate2));
149 
150     static_cast<JSBytecodeMetaData *>(const_cast<GateMetaData *>(meta))->SetElementsKind(ElementsKind::NUMBER);
151     static_cast<JSBytecodeMetaData *>(const_cast<GateMetaData *>(meta2))->SetElementsKind(ElementsKind::NUMBER);
152     EXPECT_TRUE(acc.MetaDataValueEqu(gate, gate2));
153 
154     PGOSampleType type = PGOSampleType::CreateProfileType(0, 0);
155     PGOSampleType type2 = PGOSampleType::CreateProfileType(0, 0);
156     static_cast<JSBytecodeMetaData *>(const_cast<GateMetaData *>(meta))
157         ->SetType(PGOTypeRef(static_cast<const PGOSampleType *>(&type)));
158     static_cast<JSBytecodeMetaData *>(const_cast<GateMetaData *>(meta2))
159         ->SetType(PGOTypeRef(static_cast<const PGOSampleType *>(&type2)));
160     EXPECT_FALSE(acc.MetaDataValueEqu(gate, gate2));
161 
162     PGOSampleType type3 = PGOSampleType::CreateProfileType(0, 1);
163     static_cast<JSBytecodeMetaData *>(const_cast<GateMetaData *>(meta))
164         ->SetType(PGOTypeRef(static_cast<const PGOSampleType *>(&type)));
165     static_cast<JSBytecodeMetaData *>(const_cast<GateMetaData *>(meta2))
166         ->SetType(PGOTypeRef(static_cast<const PGOSampleType *>(&type3)));
167     EXPECT_FALSE(acc.MetaDataValueEqu(gate, gate2));
168 
169     static_cast<JSBytecodeMetaData *>(const_cast<GateMetaData *>(meta))->SetElementsKind(ElementsKind::NUMBER);
170     static_cast<JSBytecodeMetaData *>(const_cast<GateMetaData *>(meta2))->SetElementsKind(ElementsKind::HOLE_NUMBER);
171     EXPECT_FALSE(acc.MetaDataValueEqu(gate, gate2));
172 }
173 
HWTEST_F_L0(MetaDataEqualTests, MCRMetaDataEqualTest)174 HWTEST_F_L0(MetaDataEqualTests, MCRMetaDataEqualTest)
175 {
176     // construct a circuit
177     ecmascript::NativeAreaAllocator allocator;
178     Circuit circuit(&allocator);
179     ecmascript::Chunk chunk(&allocator);
180     GateAccessor acc(&circuit);
181     CircuitBuilder builder(&circuit);
182     Environment env(0, &builder);
183     builder.SetEnvironment(&env);
184 
185     // TypedCallMetaData
186     auto callGate =
187         circuit.NewGate(circuit.TypedCall(0, 0, true), MachineType::I64,
188                         {Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate()}, GateType::AnyType());
189 
190     auto callGate2 =
191         circuit.NewGate(circuit.TypedCall(0, 0, true), MachineType::I64,
192                         {Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate()}, GateType::AnyType());
193 
194     EXPECT_TRUE(acc.MetaDataValueEqu(callGate, callGate2));
195     EXPECT_TRUE(acc.MetaDataValueEqu(callGate2, callGate));
196 
197     // TypedCallTargetCheckMetaData
198     auto callGate3 =
199         circuit.NewGate(circuit.TypedCallTargetCheckOp(
200             TypedCallTargetCheckAccessor::ToValue(TypedCallTargetCheckOp::JSCALLTHIS_FAST)), MachineType::I64,
201             {Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate()},
202             GateType::AnyType());
203     auto callGate4 =
204         circuit.NewGate(circuit.TypedCallTargetCheckOp(
205             TypedCallTargetCheckAccessor::ToValue(TypedCallTargetCheckOp::JSCALLTHIS_FAST)), MachineType::I64,
206             {Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate()},
207             GateType::AnyType());
208 
209     EXPECT_TRUE(acc.MetaDataValueEqu(callGate3, callGate4));
210     EXPECT_TRUE(acc.MetaDataValueEqu(callGate4, callGate3));
211 
212     // TypedBinaryMetaData
213     uint64_t valueForType5 = ecmascript::kungfu::TypedBinaryAccessor::ToValue(ParamType::IntType(),
214                                                                               TypedBinOp::TYPED_ADD);
215     auto callGate5 = circuit.NewGate(
216         circuit.TypedBinaryOp(valueForType5),
217         MachineType::I64, { Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate() },
218         GateType::AnyType());
219 
220     // TypedBinaryMetaData
221     uint64_t valueForType6 = ecmascript::kungfu::TypedBinaryAccessor::ToValue(ParamType::IntType(),
222                                                                               TypedBinOp::TYPED_ADD);
223     auto callGate6 = circuit.NewGate(
224         circuit.TypedBinaryOp(valueForType6),
225         MachineType::I64, { Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate() },
226         GateType::AnyType());
227 
228     EXPECT_TRUE(acc.MetaDataValueEqu(callGate5, callGate6));
229     EXPECT_TRUE(acc.MetaDataValueEqu(callGate6, callGate5));
230 }
231 
232 
233 } // namespace panda::test
234