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