• 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/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