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/compiler/gate.h"
17 #include "ecmascript/compiler/gate_meta_data.h"
18 #include "ecmascript/compiler/gate_meta_data_builder.h"
19
20 namespace panda::ecmascript::kungfu {
MachineTypeToStr(MachineType machineType)21 std::string MachineTypeToStr(MachineType machineType)
22 {
23 switch (machineType) {
24 case NOVALUE:
25 return "NOVALUE";
26 case ANYVALUE:
27 return "ANYVALUE";
28 case I1:
29 return "I1";
30 case I8:
31 return "I8";
32 case I16:
33 return "I16";
34 case I32:
35 return "I32";
36 case I64:
37 return "I64";
38 case F32:
39 return "F32";
40 case F64:
41 return "F64";
42 default:
43 return "???";
44 }
45 }
46
Str(OpCode opcode)47 std::string GateMetaData::Str(OpCode opcode)
48 {
49 const std::map<OpCode, const char *> strMap = {
50 #define GATE_NAME_MAP(NAME, OP, R, S, D, V) { OpCode::OP, #OP },
51 IMMUTABLE_META_DATA_CACHE_LIST(GATE_NAME_MAP)
52 GATE_META_DATA_LIST_WITH_SIZE(GATE_NAME_MAP)
53 GATE_META_DATA_LIST_WITH_ONE_PARAMETER(GATE_NAME_MAP)
54 #undef GATE_NAME_MAP
55 #define GATE_NAME_MAP(OP) { OpCode::OP, #OP },
56 GATE_OPCODE_LIST(GATE_NAME_MAP)
57 #undef GATE_NAME_MAP
58 };
59 if (strMap.count(opcode) > 0) {
60 return strMap.at(opcode);
61 }
62 return "OP-" + std::to_string(static_cast<uint8_t>(opcode));
63 }
64
IsRoot() const65 bool GateMetaData::IsRoot() const
66 {
67 return (opcode_ == OpCode::CIRCUIT_ROOT) || (opcode_ == OpCode::STATE_ENTRY) ||
68 (opcode_ == OpCode::DEPEND_ENTRY) || (opcode_ == OpCode::RETURN_LIST) ||
69 (opcode_ == OpCode::ARG_LIST);
70 }
71
IsProlog() const72 bool GateMetaData::IsProlog() const
73 {
74 return (opcode_ == OpCode::ARG);
75 }
76
IsFixed() const77 bool GateMetaData::IsFixed() const
78 {
79 return (opcode_ == OpCode::VALUE_SELECTOR) || (opcode_ == OpCode::DEPEND_SELECTOR) ||
80 (opcode_ == OpCode::DEPEND_RELAY);
81 }
82
IsSchedulable() const83 bool GateMetaData::IsSchedulable() const
84 {
85 return (opcode_ != OpCode::NOP) && (!IsProlog()) && (!IsRoot()) &&
86 (!IsFixed()) && (GetStateCount() == 0);
87 }
88
IsState() const89 bool GateMetaData::IsState() const
90 {
91 return (opcode_ != OpCode::NOP) && (!IsProlog()) && (!IsRoot()) &&
92 (!IsFixed()) && (GetStateCount() > 0);
93 }
94
IsGeneralState() const95 bool GateMetaData::IsGeneralState() const
96 {
97 return ((opcode_ == OpCode::IF_TRUE) || (opcode_ == OpCode::IF_FALSE) ||
98 (opcode_ == OpCode::JS_BYTECODE) || (opcode_ == OpCode::IF_SUCCESS) ||
99 (opcode_ == OpCode::IF_EXCEPTION) || (opcode_ == OpCode::SWITCH_CASE) ||
100 (opcode_ == OpCode::DEFAULT_CASE) || (opcode_ == OpCode::MERGE) ||
101 (opcode_ == OpCode::LOOP_BEGIN) || (opcode_ == OpCode::ORDINARY_BLOCK) ||
102 (opcode_ == OpCode::STATE_ENTRY) || (opcode_ == OpCode::TYPED_BINARY_OP) ||
103 (opcode_ == OpCode::TYPE_CONVERT) || (opcode_ == OpCode::TYPED_UNARY_OP) ||
104 (opcode_ == OpCode::TO_LENGTH) || (opcode_ == OpCode::HEAP_ALLOC) ||
105 (opcode_ == OpCode::LOAD_ELEMENT) || (opcode_ == OpCode::LOAD_PROPERTY) ||
106 (opcode_ == OpCode::STORE_ELEMENT) || (opcode_ == OpCode::STORE_PROPERTY) ||
107 (opcode_ == OpCode::TYPED_CALL)) || (opcode_ == OpCode::DEOPT_CHECK);
108 }
109
IsTerminalState() const110 bool GateMetaData::IsTerminalState() const
111 {
112 return ((opcode_ == OpCode::RETURN) || (opcode_ == OpCode::THROW) ||
113 (opcode_ == OpCode::RETURN_VOID));
114 }
115
IsCFGMerge() const116 bool GateMetaData::IsCFGMerge() const
117 {
118 return (opcode_ == OpCode::MERGE) || (opcode_ == OpCode::LOOP_BEGIN);
119 }
120
IsControlCase() const121 bool GateMetaData::IsControlCase() const
122 {
123 ASSERT(HasFlag(GateFlags::CONTROL));
124 return (opcode_ == OpCode::IF_BRANCH) || (opcode_ == OpCode::SWITCH_BRANCH) ||
125 (opcode_ == OpCode::IF_TRUE) || (opcode_ == OpCode::IF_FALSE) ||
126 (opcode_ == OpCode::IF_SUCCESS) || (opcode_ == OpCode::IF_EXCEPTION) ||
127 (opcode_ == OpCode::SWITCH_CASE) || (opcode_ == OpCode::DEFAULT_CASE);
128 }
129
IsLoopHead() const130 bool GateMetaData::IsLoopHead() const
131 {
132 return (opcode_ == OpCode::LOOP_BEGIN);
133 }
134
IsNop() const135 bool GateMetaData::IsNop() const
136 {
137 return (opcode_ == OpCode::NOP);
138 }
139
IsConstant() const140 bool GateMetaData::IsConstant() const
141 {
142 return (opcode_ == OpCode::CONSTANT || opcode_ == OpCode::CONST_DATA);
143 }
144
IsDependSelector() const145 bool GateMetaData::IsDependSelector() const
146 {
147 return (opcode_ == OpCode::DEPEND_SELECTOR);
148 }
149
IsTypedOperator() const150 bool GateMetaData::IsTypedOperator() const
151 {
152 return (opcode_ == OpCode::TYPED_BINARY_OP) || (opcode_ == OpCode::TYPE_CONVERT) ||
153 (opcode_ == OpCode::TYPED_UNARY_OP);
154 }
155
IsCheckWithTwoIns() const156 bool GateMetaData::IsCheckWithTwoIns() const
157 {
158 return (opcode_ == OpCode::OBJECT_TYPE_CHECK) ||
159 (opcode_ == OpCode::INDEX_CHECK) ||
160 (opcode_ == OpCode::TYPED_CALL_CHECK);
161 }
162
IsCheckWithOneIn() const163 bool GateMetaData::IsCheckWithOneIn() const
164 {
165 return (opcode_ == OpCode::PRIMITIVE_TYPE_CHECK) ||
166 (opcode_ == OpCode::INT32_OVERFLOW_CHECK) ||
167 (opcode_ == OpCode::ARRAY_CHECK) ||
168 (opcode_ == OpCode::STABLE_ARRAY_CHECK) ||
169 (opcode_ == OpCode::TYPED_ARRAY_CHECK);
170 }
171
GateMetaBuilder(Chunk * chunk)172 GateMetaBuilder::GateMetaBuilder(Chunk* chunk)
173 : cache_(), chunk_(chunk) {}
174
175 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
176 const GateMetaData* GateMetaBuilder::NAME() \
177 { \
178 return &cache_.cached##NAME##_; \
179 }
180 IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_META)
181 #undef DECLARE_GATE_META
182
183 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
184 const GateMetaData* GateMetaBuilder::NAME(size_t value) \
185 { \
186 switch (value) { \
187 case GateMetaDataChache::ONE_VALUE: \
188 return &cache_.cached##NAME##1_; \
189 case GateMetaDataChache::TWO_VALUE: \
190 return &cache_.cached##NAME##2_; \
191 case GateMetaDataChache::THREE_VALUE: \
192 return &cache_.cached##NAME##3_; \
193 case GateMetaDataChache::FOUR_VALUE: \
194 return &cache_.cached##NAME##4_; \
195 case GateMetaDataChache::FIVE_VALUE: \
196 return &cache_.cached##NAME##5_; \
197 default: \
198 break; \
199 } \
200 auto meta = new (chunk_) GateMetaData(OpCode::OP, R, S, D, V); \
201 meta->SetKind(GateMetaData::Kind::MUTABLE_WITH_SIZE); \
202 return meta; \
203 }
GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_META)204 GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_META)
205 #undef DECLARE_GATE_META
206
207 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
208 const GateMetaData* GateMetaBuilder::NAME(uint64_t value) \
209 { \
210 switch (value) { \
211 case GateMetaDataChache::ONE_VALUE: \
212 return &cache_.cached##NAME##1_; \
213 case GateMetaDataChache::TWO_VALUE: \
214 return &cache_.cached##NAME##2_; \
215 case GateMetaDataChache::THREE_VALUE: \
216 return &cache_.cached##NAME##3_; \
217 case GateMetaDataChache::FOUR_VALUE: \
218 return &cache_.cached##NAME##4_; \
219 case GateMetaDataChache::FIVE_VALUE: \
220 return &cache_.cached##NAME##5_; \
221 default: \
222 break; \
223 } \
224 auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, V, value); \
225 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \
226 return meta; \
227 }
228 GATE_META_DATA_LIST_WITH_VALUE(DECLARE_GATE_META)
229 #undef DECLARE_GATE_META
230
231 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
232 const GateMetaData* GateMetaBuilder::NAME(uint64_t value) \
233 { \
234 auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, V, value); \
235 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \
236 return meta; \
237 }
238 GATE_META_DATA_LIST_WITH_GATE_TYPE(DECLARE_GATE_META)
239 #undef DECLARE_GATE_META
240
241 const GateMetaData* GateMetaBuilder::Arg(uint64_t value)
242 {
243 switch (value) {
244 #define DECLARE_CACHED_VALUE_CASE(VALUE) \
245 case VALUE: { \
246 return &cache_.cachedArg##VALUE##_; \
247 }
248 CACHED_ARG_LIST(DECLARE_CACHED_VALUE_CASE)
249 #undef DECLARE_CACHED_VALUE_CASE
250 default:
251 break;
252 }
253
254 auto meta = new (chunk_) OneParameterMetaData(OpCode::ARG, GateFlags::HAS_ROOT, 0, 0, 0, value);
255 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER);
256 return meta;
257 }
258 } // namespace panda::ecmascript::kungfu
259