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 16#include "ecmascript/compiler/gate.h" 17#include "ecmascript/compiler/share_gate_meta_data.h" 18#include "ecmascript/compiler/gate_meta_data_builder.h" 19 20namespace panda::ecmascript::kungfu { 21 22std::string GateMetaData::Str(OpCode opcode) 23{ 24 const std::map<OpCode, const char *> strMap = { 25#define GATE_NAME_MAP(NAME, OP, R, S, D, V) { OpCode::OP, #OP }, 26 IMMUTABLE_META_DATA_CACHE_LIST(GATE_NAME_MAP) 27 GATE_META_DATA_LIST_WITH_BOOL(GATE_NAME_MAP) 28 GATE_META_DATA_LIST_WITH_BOOL_VALUE_IN(GATE_NAME_MAP) 29 GATE_META_DATA_LIST_WITH_SIZE(GATE_NAME_MAP) 30 GATE_META_DATA_LIST_WITH_ONE_PARAMETER(GATE_NAME_MAP) 31 GATE_META_DATA_LIST_WITH_PC_OFFSET(GATE_NAME_MAP) 32 GATE_META_DATA_LIST_FOR_CALL(GATE_NAME_MAP) 33 GATE_META_DATA_LIST_FOR_NEW(GATE_NAME_MAP) 34 GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(GATE_NAME_MAP) 35#undef GATE_NAME_MAP 36#define GATE_NAME_MAP(OP) { OpCode::OP, #OP }, 37 GATE_OPCODE_LIST(GATE_NAME_MAP) 38#undef GATE_NAME_MAP 39 }; 40 if (strMap.count(opcode) > 0) { 41 return strMap.at(opcode); 42 } 43 return "OP-" + std::to_string(static_cast<uint8_t>(opcode)); 44} 45 46bool GateMetaData::IsRoot() const 47{ 48 switch (opcode_) { 49 case OpCode::CIRCUIT_ROOT: 50 case OpCode::DEPEND_ENTRY: 51 case OpCode::ARG_LIST: 52 case OpCode::STATE_ENTRY: 53 case OpCode::RETURN_LIST: 54 return true; 55 default: 56 return false; 57 } 58} 59 60bool GateMetaData::IsProlog() const 61{ 62 return (opcode_ == OpCode::ARG || opcode_ == OpCode::INITVREG); 63} 64 65bool GateMetaData::IsFixed() const 66{ 67 switch (opcode_) { 68 case OpCode::VALUE_SELECTOR: 69 case OpCode::DEPEND_SELECTOR: 70 case OpCode::DEPEND_RELAY: 71 case OpCode::LOOP_EXIT_DEPEND: 72 case OpCode::LOOP_EXIT_VALUE: 73 return true; 74 default: 75 return false; 76 } 77} 78 79bool GateMetaData::IsSchedulable() const 80{ 81 ASSERT(!IsNop()); 82#ifndef NDEBUG 83 if (GetStateCount() == 0) { 84 ASSERT(!IsFixed()); 85 } 86#endif 87 return (!IsProlog()) && (!IsRoot()) && (GetStateCount() == 0); 88} 89 90bool GateMetaData::IsState() const 91{ 92 ASSERT(!IsNop()); 93#ifndef NDEBUG 94 if (GetStateCount() > 0) { 95 ASSERT(!IsProlog()); 96 ASSERT(!IsRoot()); 97 } 98#endif 99 return (!IsVirtualState()) && (!IsFixed()) && (GetStateCount() > 0); 100} 101 102bool GateMetaData::IsGeneralState() const 103{ 104 switch (opcode_) { 105 case OpCode::IF_BRANCH: 106 case OpCode::SWITCH_BRANCH: 107 case OpCode::IF_TRUE: 108 case OpCode::IF_FALSE: 109 case OpCode::IF_SUCCESS: 110 case OpCode::IF_EXCEPTION: 111 case OpCode::SWITCH_CASE: 112 case OpCode::DEFAULT_CASE: 113 case OpCode::MERGE: 114 case OpCode::LOOP_BEGIN: 115 case OpCode::LOOP_BACK: 116 case OpCode::LOOP_EXIT: 117 case OpCode::ORDINARY_BLOCK: 118 case OpCode::STATE_ENTRY: 119 case OpCode::DEOPT_CHECK: 120 case OpCode::RETURN: 121 case OpCode::RETURN_VOID: 122 return true; 123 default: 124 return false; 125 } 126} 127 128bool GateMetaData::IsTerminalState() const 129{ 130 switch (opcode_) { 131 case OpCode::RETURN: 132 case OpCode::THROW: 133 case OpCode::RETURN_VOID: 134 case OpCode::GET_EXCEPTION: 135 case OpCode::STATE_SPLIT: 136 return true; 137 default: 138 return false; 139 } 140} 141 142bool GateMetaData::IsVirtualState() const 143{ 144 switch (opcode_) { 145 case OpCode::GET_EXCEPTION: 146 case OpCode::STATE_SPLIT: 147 return true; 148 default: 149 return false; 150 } 151} 152 153bool GateMetaData::IsCFGMerge() const 154{ 155 return (opcode_ == OpCode::MERGE) || (opcode_ == OpCode::LOOP_BEGIN); 156} 157 158bool GateMetaData::IsControlCase() const 159{ 160 ASSERT(HasFlag(GateFlags::CONTROL)); 161 // should add relay 162 switch (opcode_) { 163 case OpCode::IF_BRANCH: 164 case OpCode::SWITCH_BRANCH: 165 case OpCode::IF_TRUE: 166 case OpCode::IF_FALSE: 167 case OpCode::SWITCH_CASE: 168 case OpCode::DEFAULT_CASE: 169 return true; 170 default: 171 return false; 172 } 173} 174 175bool GateMetaData::IsIfOrSwitchRelated() const 176{ 177 switch (opcode_) { 178 case OpCode::IF_TRUE: 179 case OpCode::IF_FALSE: 180 case OpCode::SWITCH_CASE: 181 case OpCode::DEFAULT_CASE: 182 case OpCode::IF_SUCCESS: 183 case OpCode::IF_EXCEPTION: 184 return true; 185 default: 186 return false; 187 } 188} 189 190bool GateMetaData::IsLoopHead() const 191{ 192 return (opcode_ == OpCode::LOOP_BEGIN); 193} 194 195bool GateMetaData::IsNop() const 196{ 197 return (opcode_ == OpCode::NOP || opcode_ == OpCode::DEAD); 198} 199 200bool GateMetaData::IsDead() const 201{ 202 return opcode_ == OpCode::DEAD; 203} 204 205bool GateMetaData::IsConstant() const 206{ 207 return (opcode_ == OpCode::CONSTANT); 208} 209 210bool GateMetaData::IsDependSelector() const 211{ 212 return (opcode_ == OpCode::DEPEND_SELECTOR); 213} 214 215GateMetaBuilder::GateMetaBuilder(Chunk* chunk) 216 : cache_(), chunk_(chunk) {} 217 218#define DECLARE_GATE_META(NAME, OP, R, S, D, V) \ 219const GateMetaData* GateMetaBuilder::NAME() \ 220{ \ 221 return &cache_.cached##NAME##_; \ 222} 223IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_META) 224#undef DECLARE_GATE_META 225 226#define DECLARE_GATE_META(NAME, OP, R, S, D, V) \ 227const GateMetaData* GateMetaBuilder::NAME(bool value) \ 228{ \ 229 auto meta = new (chunk_) BoolMetaData(OpCode::OP, R, S, D, V, value); \ 230 return meta; \ 231} 232GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_META) 233#undef DECLARE_GATE_META 234 235#define DECLARE_GATE_META_WITH_BOOL_VALUE_IN(NAME, OP, R, S, D, V) \ 236const GateMetaData* GateMetaBuilder::NAME(size_t value, bool flag) \ 237{ \ 238 auto meta = new (chunk_) BoolMetaData(OpCode::OP, R, S, D, V, flag); \ 239 return meta; \ 240} 241GATE_META_DATA_LIST_WITH_BOOL_VALUE_IN(DECLARE_GATE_META_WITH_BOOL_VALUE_IN) 242#undef DECLARE_GATE_META_WITH_BOOL_VALUE_IN 243 244#define DECLARE_GATE_META(NAME, OP, R, S, D, V) \ 245const GateMetaData* GateMetaBuilder::NAME(size_t value) \ 246{ \ 247 switch (value) { \ 248 case GateMetaDataChache::ONE_VALUE: \ 249 return &cache_.cached##NAME##1_; \ 250 case GateMetaDataChache::TWO_VALUE: \ 251 return &cache_.cached##NAME##2_; \ 252 case GateMetaDataChache::THREE_VALUE: \ 253 return &cache_.cached##NAME##3_; \ 254 case GateMetaDataChache::FOUR_VALUE: \ 255 return &cache_.cached##NAME##4_; \ 256 case GateMetaDataChache::FIVE_VALUE: \ 257 return &cache_.cached##NAME##5_; \ 258 default: \ 259 break; \ 260 } \ 261 auto meta = new (chunk_) GateMetaData(OpCode::OP, R, S, D, V); \ 262 meta->SetKind(GateMetaData::Kind::MUTABLE_WITH_SIZE); \ 263 return meta; \ 264} 265GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_META) 266#undef DECLARE_GATE_META 267 268#define DECLARE_GATE_META(NAME, OP, R, S, D, V) \ 269const GateMetaData* GateMetaBuilder::NAME(uint64_t value) \ 270{ \ 271 switch (value) { \ 272 case GateMetaDataChache::ONE_VALUE: \ 273 return &cache_.cached##NAME##1_; \ 274 case GateMetaDataChache::TWO_VALUE: \ 275 return &cache_.cached##NAME##2_; \ 276 case GateMetaDataChache::THREE_VALUE: \ 277 return &cache_.cached##NAME##3_; \ 278 case GateMetaDataChache::FOUR_VALUE: \ 279 return &cache_.cached##NAME##4_; \ 280 case GateMetaDataChache::FIVE_VALUE: \ 281 return &cache_.cached##NAME##5_; \ 282 default: \ 283 break; \ 284 } \ 285 auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, V, value); \ 286 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \ 287 return meta; \ 288} 289GATE_META_DATA_LIST_WITH_VALUE(DECLARE_GATE_META) 290#undef DECLARE_GATE_META 291 292#define DECLARE_GATE_META(NAME, OP, R, S, D, V) \ 293const GateMetaData* GateMetaBuilder::NAME(uint64_t value) \ 294{ \ 295 auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, V, value); \ 296 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \ 297 return meta; \ 298} 299GATE_META_DATA_LIST_WITH_GATE_TYPE(DECLARE_GATE_META) 300#undef DECLARE_GATE_META 301 302#define DECLARE_GATE_META(NAME, OP, R, S, D, V) \ 303const GateMetaData* GateMetaBuilder::NAME(uint64_t value, uint64_t pcOffset) \ 304{ \ 305 auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, value, pcOffset); \ 306 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \ 307 return meta; \ 308} 309GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_META) 310#undef DECLARE_GATE_META 311 312#define DECLARE_GATE_META_FOR_CALL(NAME, OP, R, S, D, V) \ 313const GateMetaData* GateMetaBuilder::NAME(uint64_t value, uint64_t pcOffset, bool noGC) \ 314{ \ 315 auto meta = new (chunk_) TypedCallMetaData(OpCode::OP, R, S, D, value, pcOffset, noGC); \ 316 meta->SetKind(GateMetaData::Kind::TYPED_CALL); \ 317 return meta; \ 318} 319GATE_META_DATA_LIST_FOR_CALL(DECLARE_GATE_META_FOR_CALL) 320#undef DECLARE_GATE_META_FOR_CALL 321 322#define DECLARE_GATE_META_FOR_NEW(NAME, OP, R, S, D, V) \ 323const GateMetaData* GateMetaBuilder::NAME(uint64_t value, uint64_t pcOffset, \ 324 bool isFastCall) \ 325{ \ 326 auto meta = new (chunk_) NewConstructMetaData(OpCode::OP, R, S, D, value, \ 327 pcOffset, isFastCall); \ 328 meta->SetKind(GateMetaData::Kind::CALL_NEW); \ 329 return meta; \ 330} 331GATE_META_DATA_LIST_FOR_NEW(DECLARE_GATE_META_FOR_NEW) 332#undef DECLARE_GATE_META_FOR_NEW 333 334#define DECLARE_GATE_META(NAME, OP, R, S, D, V) \ 335const GateMetaData* GateMetaBuilder::NAME(uint64_t pcOffset) const \ 336{ \ 337 auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, V, pcOffset); \ 338 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \ 339 return meta; \ 340} 341GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(DECLARE_GATE_META) 342#undef DECLARE_GATE_META 343 344const GateMetaData* GateMetaBuilder::Arg(uint64_t value) 345{ 346 switch (value) { 347#define DECLARE_CACHED_VALUE_CASE(VALUE) \ 348 case VALUE: { \ 349 return &cache_.cachedArg##VALUE##_; \ 350 } 351CACHED_ARG_LIST(DECLARE_CACHED_VALUE_CASE) 352#undef DECLARE_CACHED_VALUE_CASE 353 default: 354 break; 355 } 356 357 auto meta = new (chunk_) OneParameterMetaData(OpCode::ARG, GateFlags::HAS_ROOT, 0, 0, 0, value); 358 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); 359 return meta; 360} 361 362const GateMetaData* GateMetaBuilder::InitVreg(uint64_t value) 363{ 364 auto meta = new (chunk_) OneParameterMetaData(OpCode::INITVREG, GateFlags::HAS_ROOT, 0, 0, 0, value); 365 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); 366 return meta; 367} 368} // namespace panda::ecmascript::kungfu 369