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