• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 
18 namespace panda::ecmascript::kungfu {
CheckNullInput() const19 void Gate::CheckNullInput() const
20 {
21     const auto numIns = GetNumIns();
22     for (size_t idx = 0; idx < numIns; idx++) {
23         if (IsInGateNull(idx)) {
24             CheckFailed("In list contains null", idx);
25         }
26     }
27 }
28 
CheckFailed(std::string errorString,size_t highlightIdx) const29 void Gate::CheckFailed(std::string errorString, size_t highlightIdx) const
30 {
31     LOG_COMPILER(ERROR) << "[Verifier][Error] Gate level input list schema verify failed";
32     Print("", true, highlightIdx);
33     LOG_COMPILER(FATAL) << "Note: " << errorString;
34 }
35 
CheckInputOpcode(size_t idx,OpCode expected) const36 void Gate::CheckInputOpcode(size_t idx, OpCode expected) const
37 {
38     OpCode actual = GetInGateConst(idx)->GetOpCode();
39     if (actual != expected) {
40         CheckFailed("State input does not match (expected:" + GateMetaData::Str(expected)
41             + " actual:" + GateMetaData::Str(actual) + ")", idx);
42     }
43 }
44 
CheckInputMachineType(size_t idx,MachineType expected,bool isArch64) const45 void Gate::CheckInputMachineType(size_t idx, MachineType expected, bool isArch64) const
46 {
47     MachineType actual = GetInGateConst(idx)->GetMachineType();
48     if (expected == MachineType::FLEX) {
49         expected = GetMachineType();
50     }
51     if (expected == MachineType::ARCH) {
52         expected = isArch64 ? MachineType::I64 : MachineType::I32;
53     }
54     if (actual == MachineType::ARCH) {
55         actual = isArch64 ? MachineType::I64 : MachineType::I32;
56     }
57     if (actual != expected) {
58         CheckFailed("Value input does not match (expected:"
59             + MachineTypeToStr(expected) + " actual:" + MachineTypeToStr(actual) + ")", idx);
60     }
61 }
62 
CheckGeneralState(size_t idx) const63 void Gate::CheckGeneralState(size_t idx) const
64 {
65     auto gatePtr = GetInGateConst(idx);
66     OpCode actual = gatePtr->GetOpCode();
67     if (!gatePtr->meta_->IsGeneralState()) {
68         CheckFailed("State input does not match (expected:<General State> actual:"
69             + GateMetaData::Str(actual) + ")", idx);
70     }
71 }
72 
CheckStateInput() const73 void Gate::CheckStateInput() const
74 {
75     size_t stateStart = 0;
76     size_t stateEnd = GetStateCount();
77     for (size_t idx = stateStart; idx < stateEnd; idx++) {
78         bool needCheck = true;
79         switch (GetOpCode()) {
80             case OpCode::IF_TRUE:
81             case OpCode::IF_FALSE:
82                 ASSERT(idx == stateStart);
83                 CheckInputOpcode(idx, OpCode::IF_BRANCH);
84                 needCheck = false;
85                 break;
86             case OpCode::SWITCH_CASE:
87             case OpCode::DEFAULT_CASE:
88                 ASSERT(idx == stateStart);
89                 CheckInputOpcode(idx, OpCode::SWITCH_BRANCH);
90                 needCheck = false;
91                 break;
92             case OpCode::LOOP_BEGIN:
93                 if (idx == stateStart + 1) { // 1: idx 1
94                     CheckInputOpcode(idx, OpCode::LOOP_BACK);
95                     needCheck = false;
96                 }
97                 break;
98             default:
99                 break;
100         }
101         if (needCheck) {
102             CheckGeneralState(idx);
103         }
104     }
105 }
106 
CheckValueInput(bool isArch64) const107 void Gate::CheckValueInput(bool isArch64) const
108 {
109     size_t valueStart = GetInValueStarts();
110     size_t valueEnd = valueStart + GetInValueCount();
111     for (size_t idx = valueStart; idx < valueEnd; idx++) {
112         switch (GetOpCode()) {
113             case OpCode::IF_BRANCH:
114                 ASSERT(idx == valueStart);
115                 CheckInputMachineType(idx, MachineType::I1, isArch64);
116                 break;
117             case OpCode::VALUE_SELECTOR:
118             case OpCode::ADD:
119             case OpCode::SUB:
120             case OpCode::MUL:
121             case OpCode::EXP:
122             case OpCode::SDIV:
123             case OpCode::SMOD:
124             case OpCode::UDIV:
125             case OpCode::UMOD:
126             case OpCode::FDIV:
127             case OpCode::FMOD:
128             case OpCode::AND:
129             case OpCode::XOR:
130             case OpCode::OR:
131             case OpCode::LSL:
132             case OpCode::LSR:
133             case OpCode::ASR:
134                 CheckInputMachineType(idx, MachineType::FLEX, isArch64);
135                 break;
136             case OpCode::REV:
137                 ASSERT(idx == valueStart);
138                 CheckInputMachineType(idx, MachineType::I1, isArch64);
139                 break;
140             case OpCode::LOAD:
141                 ASSERT(idx == valueStart);
142                 CheckInputMachineType(idx, MachineType::ARCH, isArch64);
143                 break;
144             case OpCode::STORE:
145                 if (idx == valueStart + 1) { // 1: idx 1
146                     CheckInputMachineType(idx, MachineType::ARCH, isArch64);
147                 }
148                 break;
149             case OpCode::HEAP_ALLOC:
150             case OpCode::TAGGED_TO_INT64:
151             case OpCode::INT64_TO_TAGGED:
152                 ASSERT(idx == valueStart);
153                 CheckInputMachineType(valueStart, MachineType::I64, isArch64);
154                 break;
155             case OpCode::OBJECT_TYPE_CHECK:
156             case OpCode::LOAD_ELEMENT:
157             case OpCode::STORE_ELEMENT:
158                 if (idx == valueStart + 1) { // 1: idx 1
159                     CheckInputMachineType(idx, MachineType::I64, isArch64);
160                 }
161                 break;
162             default:
163                 break;
164         }
165     }
166 }
167 
CheckDependInput() const168 void Gate::CheckDependInput() const
169 {
170     size_t dependStart = GetStateCount();
171     size_t dependEnd = dependStart + GetDependCount();
172     for (size_t idx = dependStart; idx < dependEnd; idx++) {
173         if (GetInGateConst(idx)->GetDependCount() == 0 &&
174             GetInGateConst(idx)->GetOpCode() != OpCode::DEPEND_ENTRY) {
175             CheckFailed("Depend input is side-effect free", idx);
176         }
177     }
178 }
179 
CheckRootInput() const180 void Gate::CheckRootInput() const
181 {
182     size_t rootStart = GetInValueStarts() + GetInValueCount();
183     if (meta_->HasRoot()) {
184         switch (GetOpCode()) {
185             case OpCode::STATE_ENTRY:
186             case OpCode::DEPEND_ENTRY:
187             case OpCode::RETURN_LIST:
188             case OpCode::ARG_LIST:
189                 CheckInputOpcode(rootStart, OpCode::CIRCUIT_ROOT);
190                 break;
191             case OpCode::ARG:
192                 CheckInputOpcode(rootStart, OpCode::ARG_LIST);
193                 break;
194             case OpCode::RETURN:
195             case OpCode::RETURN_VOID:
196                 CheckInputOpcode(rootStart, OpCode::RETURN_LIST);
197                 break;
198             default:
199                 break;
200         }
201     }
202 }
203 
CheckFrameStateInput() const204 void Gate::CheckFrameStateInput() const
205 {
206     size_t frameStateStart = GetInFrameStateStarts();
207     if (meta_->HasFrameState()) {
208         CheckInputOpcode(frameStateStart, OpCode::FRAME_STATE);
209     }
210 }
211 
CheckStateOutput() const212 void Gate::CheckStateOutput() const
213 {
214     if (GetMetaData()->IsState()) {
215         size_t cnt = 0;
216         const Gate *curGate = this;
217         if (!curGate->IsFirstOutNull()) {
218             const Out *curOut = curGate->GetFirstOutConst();
219             if (curOut->IsStateEdge() && curOut->GetGateConst()->GetMetaData()->IsState()) {
220                 cnt++;
221             }
222             while (!curOut->IsNextOutNull()) {
223                 curOut = curOut->GetNextOutConst();
224                 if (curOut->IsStateEdge() && curOut->GetGateConst()->GetMetaData()->IsState()) {
225                     cnt++;
226                 }
227             }
228         }
229         size_t expected = 0;
230         bool needCheck = true;
231         if (GetMetaData()->IsTerminalState()) {
232             expected = 0;
233         } else if (GetOpCode() == OpCode::IF_BRANCH || GetOpCode() == OpCode::JS_BYTECODE) {
234             expected = 2; // 2: expected number of state out branches
235         } else if (GetOpCode() == OpCode::SWITCH_BRANCH) {
236             needCheck = false;
237         } else {
238             expected = 1;
239         }
240         if (needCheck && cnt != expected) {
241             curGate->Print();
242             CheckFailed("Number of state out branches is not valid (expected:" + std::to_string(expected) +
243                 " actual:" + std::to_string(cnt) + ")", -1);
244         }
245     }
246 }
247 
CheckBranchOutput() const248 void Gate::CheckBranchOutput() const
249 {
250     std::map<std::pair<OpCode, BitField>, size_t> setOfOps;
251     if (GetOpCode() == OpCode::IF_BRANCH || GetOpCode() == OpCode::SWITCH_BRANCH) {
252         size_t cnt = 0;
253         const Gate *curGate = this;
254         if (!curGate->IsFirstOutNull()) {
255             const Out *curOut = curGate->GetFirstOutConst();
256             if (curOut->GetGateConst()->GetMetaData()->IsState() && curOut->IsStateEdge()) {
257                 ASSERT(!curOut->GetGateConst()->GetMetaData()->IsFixed());
258                 setOfOps[{curOut->GetGateConst()->GetOpCode(), curOut->GetGateConst()->GetStateCount()}]++;
259                 cnt++;
260             }
261             while (!curOut->IsNextOutNull()) {
262                 curOut = curOut->GetNextOutConst();
263                 if (curOut->GetGateConst()->GetMetaData()->IsState() && curOut->IsStateEdge()) {
264                     ASSERT(!curOut->GetGateConst()->GetMetaData()->IsFixed());
265                     setOfOps[{curOut->GetGateConst()->GetOpCode(), curOut->GetGateConst()->GetStateCount()}]++;
266                     cnt++;
267                 }
268             }
269         }
270         if (setOfOps.size() != cnt) {
271             CheckFailed("Duplicate state out branches", -1);
272         }
273     }
274 }
275 
CheckNOP() const276 void Gate::CheckNOP() const
277 {
278     if (GetOpCode() == OpCode::NOP) {
279         if (!IsFirstOutNull()) {
280             CheckFailed("NOP gate used by other gates", -1);
281         }
282     }
283 }
284 
CheckSelector() const285 void Gate::CheckSelector() const
286 {
287     if (GetOpCode() == OpCode::VALUE_SELECTOR || GetOpCode() == OpCode::DEPEND_SELECTOR) {
288         auto stateOp = GetInGateConst(0)->GetOpCode();
289         if (stateOp == OpCode::MERGE || stateOp == OpCode::LOOP_BEGIN) {
290             if (GetInGateConst(0)->GetNumIns() != GetNumIns() - 1) {
291                 if (GetOpCode() == OpCode::DEPEND_SELECTOR) {
292                     CheckFailed("Number of depend flows does not match control flows (expected:" +
293                             std::to_string(GetInGateConst(0)->GetNumIns()) +
294                             " actual:" + std::to_string(GetNumIns() - 1) + ")",
295                         -1);
296                 } else {
297                     CheckFailed("Number of data flows does not match control flows (expected:" +
298                             std::to_string(GetInGateConst(0)->GetNumIns()) +
299                             " actual:" + std::to_string(GetNumIns() - 1) + ")",
300                         -1);
301                 }
302             }
303         } else {
304             CheckFailed(
305                 "State input does not match (expected:[MERGE|LOOP_BEGIN] actual:" +
306                 GateMetaData::Str(stateOp) + ")", 0);
307         }
308     }
309 }
310 
CheckRelay() const311 void Gate::CheckRelay() const
312 {
313     if (GetOpCode() == OpCode::DEPEND_RELAY) {
314         auto stateOp = GetInGateConst(0)->GetOpCode();
315         if (!(stateOp == OpCode::IF_TRUE || stateOp == OpCode::IF_FALSE || stateOp == OpCode::SWITCH_CASE ||
316             stateOp == OpCode::DEFAULT_CASE || stateOp == OpCode::IF_SUCCESS || stateOp == OpCode::IF_EXCEPTION ||
317             stateOp == OpCode::ORDINARY_BLOCK)) {
318             CheckFailed("State input does not match ("
319                 "expected:[IF_TRUE|IF_FALSE|SWITCH_CASE|DEFAULT_CASE|IF_SUCCESS|IF_EXCEPTION|ORDINARY_BLOCK] actual:" +
320                  GateMetaData::Str(stateOp) + ")", 0);
321         }
322     }
323 }
324 
Verify(bool isArch64) const325 void Gate::Verify(bool isArch64) const
326 {
327     CheckNullInput();
328     CheckStateInput();
329     CheckValueInput(isArch64);
330     CheckDependInput();
331     CheckFrameStateInput();
332     CheckRootInput();
333     CheckStateOutput();
334     CheckBranchOutput();
335     CheckNOP();
336     CheckSelector();
337     CheckRelay();
338 }
339 
SetNextOut(const Out * ptr)340 void Out::SetNextOut(const Out *ptr)
341 {
342     nextOut_ =
343         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
344         static_cast<GateRef>((reinterpret_cast<const uint8_t *>(ptr)) - (reinterpret_cast<const uint8_t *>(this)));
345 }
346 
GetNextOut()347 Out *Out::GetNextOut()
348 {
349     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
350     return reinterpret_cast<Out *>((reinterpret_cast<uint8_t *>(this)) + nextOut_);
351 }
352 
GetNextOutConst() const353 const Out *Out::GetNextOutConst() const
354 {
355     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
356     return reinterpret_cast<const Out *>((reinterpret_cast<const uint8_t *>(this)) + nextOut_);
357 }
358 
SetPrevOut(const Out * ptr)359 void Out::SetPrevOut(const Out *ptr)
360 {
361     prevOut_ =
362         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
363         static_cast<GateRef>((reinterpret_cast<const uint8_t *>(ptr)) - (reinterpret_cast<const uint8_t *>(this)));
364 }
365 
GetPrevOut()366 Out *Out::GetPrevOut()
367 {
368     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
369     return reinterpret_cast<Out *>((reinterpret_cast<uint8_t *>(this)) + prevOut_);
370 }
371 
GetPrevOutConst() const372 const Out *Out::GetPrevOutConst() const
373 {
374     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
375     return reinterpret_cast<const Out *>((reinterpret_cast<const uint8_t *>(this)) + prevOut_);
376 }
377 
SetIndex(OutIdx idx)378 void Out::SetIndex(OutIdx idx)
379 {
380     idx_ = idx;
381 }
382 
GetIndex() const383 OutIdx Out::GetIndex() const
384 {
385     return idx_;
386 }
387 
GetGate()388 Gate *Out::GetGate()
389 {
390     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
391     return reinterpret_cast<Gate *>(&this[idx_ + 1]);
392 }
393 
GetGateConst() const394 const Gate *Out::GetGateConst() const
395 {
396     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
397     return reinterpret_cast<const Gate *>(&this[idx_ + 1]);
398 }
399 
SetPrevOutNull()400 void Out::SetPrevOutNull()
401 {
402     prevOut_ = 0;
403 }
404 
IsPrevOutNull() const405 bool Out::IsPrevOutNull() const
406 {
407     return prevOut_ == 0;
408 }
409 
SetNextOutNull()410 void Out::SetNextOutNull()
411 {
412     nextOut_ = 0;
413 }
414 
IsNextOutNull() const415 bool Out::IsNextOutNull() const
416 {
417     return nextOut_ == 0;
418 }
419 
IsStateEdge() const420 bool Out::IsStateEdge() const
421 {
422     return idx_ < GetGateConst()->GetStateCount();
423 }
424 
SetGate(const Gate * ptr)425 void In::SetGate(const Gate *ptr)
426 {
427     gatePtr_ =
428         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
429         static_cast<GateRef>((reinterpret_cast<const uint8_t *>(ptr)) - (reinterpret_cast<const uint8_t *>(this)));
430 }
431 
GetGate()432 Gate *In::GetGate()
433 {
434     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
435     return reinterpret_cast<Gate *>((reinterpret_cast<uint8_t *>(this)) + gatePtr_);
436 }
437 
GetGateConst() const438 const Gate *In::GetGateConst() const
439 {
440     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
441     return reinterpret_cast<const Gate *>((reinterpret_cast<const uint8_t *>(this)) + gatePtr_);
442 }
443 
SetGateNull()444 void In::SetGateNull()
445 {
446     gatePtr_ = Gate::InvalidGateRef;
447 }
448 
IsGateNull() const449 bool In::IsGateNull() const
450 {
451     return gatePtr_ == Gate::InvalidGateRef;
452 }
453 
454 // NOLINTNEXTLINE(modernize-avoid-c-arrays)
Gate(const GateMetaData * meta,GateId id,Gate * inList[],MachineType machineType,GateType type)455 Gate::Gate(const GateMetaData* meta, GateId id, Gate *inList[], MachineType machineType, GateType type)
456     : meta_(meta), id_(id), type_(type), machineType_(machineType)
457 {
458     auto numIns = GetNumIns();
459     if (numIns == 0) {
460         auto curOut = GetOut(0);
461         curOut->SetIndex(0);
462         return;
463     }
464     for (size_t idx = 0; idx < numIns; idx++) {
465         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
466         auto in = inList[idx];
467         if (in == nullptr) {
468             GetIn(idx)->SetGateNull();
469         } else {
470             NewIn(idx, in);
471         }
472         auto curOut = GetOut(idx);
473         curOut->SetIndex(idx);
474     }
475 }
476 
NewIn(size_t idx,Gate * in)477 void Gate::NewIn(size_t idx, Gate *in)
478 {
479     GetIn(idx)->SetGate(in);
480     auto curOut = GetOut(idx);
481     if (in->IsFirstOutNull()) {
482         curOut->SetNextOutNull();
483     } else {
484         curOut->SetNextOut(in->GetFirstOut());
485         in->GetFirstOut()->SetPrevOut(curOut);
486     }
487     curOut->SetPrevOutNull();
488     in->SetFirstOut(curOut);
489 }
490 
ModifyIn(size_t idx,Gate * in)491 void Gate::ModifyIn(size_t idx, Gate *in)
492 {
493     DeleteIn(idx);
494     NewIn(idx, in);
495 }
496 
DeleteIn(size_t idx)497 void Gate::DeleteIn(size_t idx)
498 {
499     if (!GetOut(idx)->IsNextOutNull() && !GetOut(idx)->IsPrevOutNull()) {
500         GetOut(idx)->GetPrevOut()->SetNextOut(GetOut(idx)->GetNextOut());
501         GetOut(idx)->GetNextOut()->SetPrevOut(GetOut(idx)->GetPrevOut());
502     } else if (GetOut(idx)->IsNextOutNull() && !GetOut(idx)->IsPrevOutNull()) {
503         GetOut(idx)->GetPrevOut()->SetNextOutNull();
504     } else if (!GetOut(idx)->IsNextOutNull()) {  // then GetOut(idx)->IsPrevOutNull() is true
505         GetIn(idx)->GetGate()->SetFirstOut(GetOut(idx)->GetNextOut());
506         GetOut(idx)->GetNextOut()->SetPrevOutNull();
507     } else {  // only this out now
508         GetIn(idx)->GetGate()->SetFirstOutNull();
509     }
510     GetIn(idx)->SetGateNull();
511 }
512 
DeleteGate()513 void Gate::DeleteGate()
514 {
515     auto numIns = GetNumIns();
516     for (size_t idx = 0; idx < numIns; idx++) {
517         DeleteIn(idx);
518     }
519 }
520 
GetOut(size_t idx)521 Out *Gate::GetOut(size_t idx)
522 {
523     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
524     return &reinterpret_cast<Out *>(this)[-1 - idx];
525 }
526 
GetOutConst(size_t idx) const527 const Out *Gate::GetOutConst(size_t idx) const
528 {
529     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
530     return &reinterpret_cast<const Out *>(this)[-1 - idx];
531 }
532 
GetFirstOut()533 Out *Gate::GetFirstOut()
534 {
535     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
536     return reinterpret_cast<Out *>((reinterpret_cast<uint8_t *>(this)) + firstOut_);
537 }
538 
GetFirstOutConst() const539 const Out *Gate::GetFirstOutConst() const
540 {
541     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
542     return reinterpret_cast<const Out *>((reinterpret_cast<const uint8_t *>(this)) + firstOut_);
543 }
544 
SetFirstOutNull()545 void Gate::SetFirstOutNull()
546 {
547     firstOut_ = 0;
548 }
549 
IsFirstOutNull() const550 bool Gate::IsFirstOutNull() const
551 {
552     return firstOut_ == 0;
553 }
554 
SetFirstOut(const Out * firstOut)555 void Gate::SetFirstOut(const Out *firstOut)
556 {
557     firstOut_ =
558         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
559         static_cast<GateRef>(reinterpret_cast<const uint8_t *>(firstOut) - reinterpret_cast<const uint8_t *>(this));
560 }
561 
GetIn(size_t idx)562 In *Gate::GetIn(size_t idx)
563 {
564 #ifndef NDEBUG
565     if (idx >= GetNumIns()) {
566         LOG_COMPILER(INFO) << std::dec << "Gate In access out-of-bound! (idx=" << idx << ")";
567         Print();
568         ASSERT(false);
569     }
570 #endif
571     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
572     return &reinterpret_cast<In *>(this + 1)[idx];
573 }
574 
GetInConst(size_t idx) const575 const In *Gate::GetInConst(size_t idx) const
576 {
577 #ifndef NDEBUG
578     if (idx >= GetNumIns()) {
579         LOG_COMPILER(INFO) << std::dec << "Gate In access out-of-bound! (idx=" << idx << ")";
580         Print();
581         ASSERT(false);
582     }
583 #endif
584     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
585     return &reinterpret_cast<const In *>(this + 1)[idx];
586 }
587 
GetInGate(size_t idx)588 Gate *Gate::GetInGate(size_t idx)
589 {
590     return GetIn(idx)->GetGate();
591 }
592 
GetInGateConst(size_t idx) const593 const Gate *Gate::GetInGateConst(size_t idx) const
594 {
595     return GetInConst(idx)->GetGateConst();
596 }
597 
IsInGateNull(size_t idx) const598 bool Gate::IsInGateNull(size_t idx) const
599 {
600     return GetInConst(idx)->IsGateNull();
601 }
602 
GetId() const603 GateId Gate::GetId() const
604 {
605     return id_;
606 }
607 
GetOpCode() const608 OpCode Gate::GetOpCode() const
609 {
610     return meta_->GetOpCode();
611 }
612 
GetNumIns() const613 size_t Gate::GetNumIns() const
614 {
615     return meta_->GetNumIns();
616 }
617 
GetInValueStarts() const618 size_t Gate::GetInValueStarts() const
619 {
620     return meta_->GetInValueStarts();
621 }
622 
GetInFrameStateStarts() const623 size_t Gate::GetInFrameStateStarts() const
624 {
625     return meta_->GetInFrameStateStarts();
626 }
627 
GetStateCount() const628 size_t Gate::GetStateCount() const
629 {
630     return meta_->GetStateCount();
631 }
632 
GetDependCount() const633 size_t Gate::GetDependCount() const
634 {
635     return meta_->GetDependCount();
636 }
637 
GetInValueCount() const638 size_t Gate::GetInValueCount() const
639 {
640     return meta_->GetInValueCount();
641 }
642 
GetInFrameStateCount() const643 size_t Gate::GetInFrameStateCount() const
644 {
645     return meta_->GetInFrameStateCount();
646 }
647 
GetRootCount() const648 size_t Gate::GetRootCount() const
649 {
650     return meta_->GetRootCount();
651 }
652 
MachineTypeStr(MachineType machineType) const653 std::string Gate::MachineTypeStr(MachineType machineType) const
654 {
655     const std::map<MachineType, const char *> strMap = {
656         {NOVALUE, "NOVALUE"},
657         {ANYVALUE, "ANYVALUE"},
658         {ARCH, "ARCH"},
659         {FLEX, "FLEX"},
660         {I1, "I1"},
661         {I8, "I8"},
662         {I16, "I16"},
663         {I32, "I32"},
664         {I64, "I64"},
665         {F32, "F32"},
666         {F64, "F64"},
667     };
668     if (strMap.count(machineType) > 0) {
669         return strMap.at(machineType);
670     }
671     return "MachineType-" + std::to_string(machineType);
672 }
673 
GateTypeStr(GateType gateType) const674 std::string Gate::GateTypeStr(GateType gateType) const
675 {
676     static const std::map<GateType, const char *> strMap = {
677         {GateType::NJSValue(), "NJS_VALUE"},
678         {GateType::TaggedValue(), "TAGGED_VALUE"},
679         {GateType::TaggedPointer(), "TAGGED_POINTER"},
680         {GateType::TaggedNPointer(), "TAGGED_NPOINTER"},
681         {GateType::Empty(), "EMPTY"},
682         {GateType::AnyType(), "ANY_TYPE"},
683     };
684 
685     std::string name = "";
686     if (strMap.count(gateType) > 0) {
687         name = strMap.at(gateType);
688     }
689     GlobalTSTypeRef r = gateType.GetGTRef();
690     uint32_t m = r.GetModuleId();
691     uint32_t l = r.GetLocalId();
692     return name + std::string("-GT(M=") + std::to_string(m) +
693            std::string(", L=") + std::to_string(l) + std::string(")");
694 }
695 
Print(std::string bytecode,bool inListPreview,size_t highlightIdx) const696 void Gate::Print(std::string bytecode, bool inListPreview, size_t highlightIdx) const
697 {
698     auto opcode = GetOpCode();
699     if (opcode != OpCode::NOP) {
700         std::string log("{\"id\":" + std::to_string(id_) + ", \"op\":\"" + GateMetaData::Str(opcode) + "\", ");
701         log += ((bytecode.compare("") == 0) ? "" : "\"bytecode\":\"") + bytecode;
702         log += ((bytecode.compare("") == 0) ? "" : "\", ");
703         log += "\"MType\":\"" + MachineTypeStr(GetMachineType()) + ", ";
704         log += "bitfield=" + std::to_string(TryGetValue()) + ", ";
705         log += "type=" + GateTypeStr(type_) + ", ";
706         log += "stamp=" + std::to_string(static_cast<uint32_t>(stamp_)) + ", ";
707         log += "mark=" + std::to_string(static_cast<uint32_t>(mark_)) + ", ";
708         log += "\",\"in\":[";
709 
710         size_t idx = 0;
711         auto stateSize = GetStateCount();
712         auto dependSize = GetDependCount();
713         auto valueSize = GetInValueCount();
714         auto frameStateSize = GetInFrameStateCount();
715         auto rootSize = GetRootCount();
716         size_t start = 0;
717         size_t end = stateSize;
718         idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log);
719         end += dependSize;
720         start += stateSize;
721         idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log);
722         end += valueSize;
723         start += dependSize;
724         idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log);
725         end += frameStateSize;
726         start += valueSize;
727         idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log);
728         end += rootSize;
729         start += frameStateSize;
730         idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log, true);
731 
732         log += "], \"out\":[";
733 
734         if (!IsFirstOutNull()) {
735             const Out *curOut = GetFirstOutConst();
736             opcode = curOut->GetGateConst()->GetOpCode();
737             log += std::to_string(curOut->GetGateConst()->GetId()) +
738                     (inListPreview ? std::string(":" + GateMetaData::Str(opcode)) : std::string(""));
739 
740             while (!curOut->IsNextOutNull()) {
741                 curOut = curOut->GetNextOutConst();
742                 log += ", " +  std::to_string(curOut->GetGateConst()->GetId()) +
743                        (inListPreview ? std::string(":" + GateMetaData::Str(opcode))
744                                        : std::string(""));
745             }
746         }
747         log += "]},";
748         LOG_COMPILER(INFO) << std::dec << log;
749     }
750 }
751 
ShortPrint(std::string bytecode,bool inListPreview,size_t highlightIdx) const752 void Gate::ShortPrint(std::string bytecode, bool inListPreview, size_t highlightIdx) const
753 {
754     auto opcode = GetOpCode();
755     if (opcode != OpCode::NOP) {
756         std::string log("(\"id\"=" + std::to_string(id_) + ", \"op\"=\"" + GateMetaData::Str(opcode) + "\", ");
757         log += ((bytecode.compare("") == 0) ? "" : "bytecode=") + bytecode;
758         log += ((bytecode.compare("") == 0) ? "" : ", ");
759         log += "\"MType\"=\"" + MachineTypeStr(GetMachineType()) + ", ";
760         log += "bitfield=" + std::to_string(TryGetValue()) + ", ";
761         log += "type=" + GateTypeStr(type_) + ", ";
762         log += "\", in=[";
763 
764         size_t idx = 0;
765         auto stateSize = GetStateCount();
766         auto dependSize = GetDependCount();
767         auto valueSize = GetInValueCount();
768         auto frameStateSize = GetInFrameStateCount();
769         auto rootSize = GetRootCount();
770         size_t start = 0;
771         size_t end = stateSize;
772         idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log);
773         end += dependSize;
774         start += stateSize;
775         idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log);
776         end += valueSize;
777         start += dependSize;
778         idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log);
779         end += frameStateSize;
780         start += valueSize;
781         idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log);
782         end += rootSize;
783         start += frameStateSize;
784         idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log, true);
785 
786         log += "], out=[";
787 
788         if (!IsFirstOutNull()) {
789             const Out *curOut = GetFirstOutConst();
790             opcode = curOut->GetGateConst()->GetOpCode();
791             log += std::to_string(curOut->GetGateConst()->GetId()) +
792                    (inListPreview ? std::string(":" + GateMetaData::Str(opcode)) : std::string(""));
793 
794             while (!curOut->IsNextOutNull()) {
795                 curOut = curOut->GetNextOutConst();
796                 log += ", " +  std::to_string(curOut->GetGateConst()->GetId()) +
797                        (inListPreview ? std::string(":" + GateMetaData::Str(opcode))
798                                       : std::string(""));
799             }
800         }
801         log += "])";
802         LOG_COMPILER(INFO) << std::dec << log;
803     }
804 }
805 
PrintInGate(size_t numIns,size_t idx,size_t size,bool inListPreview,size_t highlightIdx,std::string & log,bool isEnd) const806 size_t Gate::PrintInGate(size_t numIns, size_t idx, size_t size, bool inListPreview, size_t highlightIdx,
807                          std::string &log, bool isEnd) const
808 {
809     log += "[";
810     for (; idx < numIns; idx++) {
811         log += ((idx == size) ? "" : ", ");
812         log += ((idx == highlightIdx) ? "\033[4;31m" : "");
813         log += ((IsInGateNull(idx)
814                 ? "N"
815                 : (std::to_string(GetInGateConst(idx)->GetId()) +
816                     (inListPreview ? std::string(":" + GateMetaData::Str(GetInGateConst(idx)->GetOpCode()))
817                                    : std::string("")))));
818         log += ((idx == highlightIdx) ? "\033[0m" : "");
819     }
820     log += "]";
821     log += ((isEnd) ? "" : ", ");
822     return idx;
823 }
824 
PrintByteCode(std::string bytecode) const825 void Gate::PrintByteCode(std::string bytecode) const
826 {
827     Print(bytecode);
828 }
829 
GetMark(TimeStamp stamp) const830 MarkCode Gate::GetMark(TimeStamp stamp) const
831 {
832     return (stamp_ == stamp) ? mark_ : MarkCode::NO_MARK;
833 }
834 
SetMark(MarkCode mark,TimeStamp stamp)835 void Gate::SetMark(MarkCode mark, TimeStamp stamp)
836 {
837     stamp_ = stamp;
838     mark_ = mark;
839 }
840 }  // namespace panda::ecmascript::kungfu
841