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
28namespace panda::test {
29class MetaDataEqualTests : public testing::Test {};
30
31using ecmascript::kungfu::Circuit;
32using ecmascript::kungfu::CircuitBuilder;
33using ecmascript::kungfu::EcmaOpcode;
34using ecmascript::kungfu::ElementsKind;
35using ecmascript::kungfu::Environment;
36using ecmascript::kungfu::GateAccessor;
37using ecmascript::kungfu::GateMetaData;
38using ecmascript::kungfu::GateType;
39using ecmascript::kungfu::JSBytecodeMetaData;
40using ecmascript::kungfu::MachineType;
41using ecmascript::kungfu::PGOTypeRef;
42using ecmascript::kungfu::PGOSampleType;
43using ecmascript::kungfu::TypedBinOp;
44using ecmascript::kungfu::TypedCallTargetCheckOp;
45using ecmascript::kungfu::ParamType;
46using ecmascript::kungfu::TypedCallTargetCheckAccessor;
47
48HWTEST_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
71HWTEST_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
112HWTEST_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
129HWTEST_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
174HWTEST_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