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/circuit.h"
17 #include "ecmascript/compiler/compiler_macros.h"
18 #include "ecmascript/compiler/bytecode_circuit_builder.h"
19
20 namespace panda::ecmascript::kungfu {
Circuit()21 Circuit::Circuit() : space_(), circuitSize_(0), gateCount_(0), time_(1), dataSection_()
22 {
23 NewGate(OpCode(OpCode::CIRCUIT_ROOT), 0, {}, GateType::EMPTY); // circuit root
24 auto circuitRoot = Circuit::GetCircuitRoot(OpCode(OpCode::CIRCUIT_ROOT));
25 NewGate(OpCode(OpCode::STATE_ENTRY), 0, {circuitRoot}, GateType::EMPTY);
26 NewGate(OpCode(OpCode::DEPEND_ENTRY), 0, {circuitRoot}, GateType::EMPTY);
27 NewGate(OpCode(OpCode::FRAMESTATE_ENTRY), 0, {circuitRoot}, GateType::EMPTY);
28 NewGate(OpCode(OpCode::RETURN_LIST), 0, {circuitRoot}, GateType::EMPTY);
29 NewGate(OpCode(OpCode::THROW_LIST), 0, {circuitRoot}, GateType::EMPTY);
30 NewGate(OpCode(OpCode::CONSTANT_LIST), 0, {circuitRoot}, GateType::EMPTY);
31 NewGate(OpCode(OpCode::ALLOCA_LIST), 0, {circuitRoot}, GateType::EMPTY);
32 NewGate(OpCode(OpCode::ARG_LIST), 0, {circuitRoot}, GateType::EMPTY);
33 }
34
AllocateSpace(size_t gateSize)35 uint8_t *Circuit::AllocateSpace(size_t gateSize)
36 {
37 circuitSize_ += gateSize;
38 if (UNLIKELY(GetSpaceDataSize() == 0)) {
39 SetSpaceDataSize(INITIAL_SPACE);
40 }
41 while (UNLIKELY(GetSpaceDataSize() < circuitSize_)) {
42 SetSpaceDataSize(GetSpaceDataSize() * SCALE_RATE);
43 }
44 if (UNLIKELY(GetSpaceDataSize() > MAX_SPACE)) {
45 return nullptr; // abort compilation
46 }
47 if (UNLIKELY(GetSpaceDataStartPtrConst() == nullptr)) {
48 return nullptr; // abort compilation
49 }
50 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
51 return GetDataPtr(circuitSize_ - gateSize);
52 }
53
AllocateGateSpace(size_t numIns)54 Gate *Circuit::AllocateGateSpace(size_t numIns)
55 {
56 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
57 return reinterpret_cast<Gate *>(AllocateSpace(Gate::GetGateSize(numIns)) + Gate::GetOutListSize(numIns));
58 }
59
60 // NOLINTNEXTLINE(modernize-avoid-c-arrays)
NewGate(OpCode opcode,MachineType bitValue,BitField bitfield,size_t numIns,const GateRef inList[],GateType type,MarkCode mark)61 GateRef Circuit::NewGate(OpCode opcode, MachineType bitValue, BitField bitfield, size_t numIns, const GateRef inList[],
62 GateType type, MarkCode mark)
63 {
64 #ifndef NDEBUG
65 if (numIns != opcode.GetOpCodeNumIns(bitfield)) {
66 std::cerr << "Invalid input list!"
67 << " op=" << opcode.Str() << " bitfield=" << bitfield
68 << " expected_num_in=" << opcode.GetOpCodeNumIns(bitfield) << " actual_num_in=" << numIns
69 << std::endl;
70 UNREACHABLE();
71 }
72 #endif
73 std::vector<Gate *> inPtrList(numIns);
74 auto gateSpace = AllocateGateSpace(numIns);
75 for (size_t idx = 0; idx < numIns; idx++) {
76 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
77 inPtrList[idx] = (inList[idx] == Circuit::NullGate()) ? nullptr : LoadGatePtr(inList[idx]);
78 }
79 ASSERT(opcode.GetMachineType() == MachineType::FLEX);
80 auto newGate = new (gateSpace) Gate(gateCount_, opcode, bitValue, bitfield, inPtrList.data(), type, mark);
81 gateCount_++;
82 return SaveGatePtr(newGate);
83 }
84
NewGate(OpCode opcode,MachineType bitValue,BitField bitfield,const std::vector<GateRef> & inList,GateType type,MarkCode mark)85 GateRef Circuit::NewGate(OpCode opcode, MachineType bitValue, BitField bitfield, const std::vector<GateRef> &inList,
86 GateType type, MarkCode mark)
87 {
88 return NewGate(opcode, bitValue, bitfield, inList.size(), inList.data(), type, mark);
89 }
90
91 // NOLINTNEXTLINE(modernize-avoid-c-arrays)
NewGate(OpCode opcode,BitField bitfield,size_t numIns,const GateRef inList[],GateType type,MarkCode mark)92 GateRef Circuit::NewGate(OpCode opcode, BitField bitfield, size_t numIns, const GateRef inList[], GateType type,
93 MarkCode mark)
94 {
95 #ifndef NDEBUG
96 if (numIns != opcode.GetOpCodeNumIns(bitfield)) {
97 std::cerr << "Invalid input list!"
98 << " op=" << opcode.Str() << " bitfield=" << bitfield
99 << " expected_num_in=" << opcode.GetOpCodeNumIns(bitfield) << " actual_num_in=" << numIns
100 << std::endl;
101 UNREACHABLE();
102 }
103 #endif
104 std::vector<Gate *> inPtrList(numIns);
105 auto gateSpace = AllocateGateSpace(numIns);
106 for (size_t idx = 0; idx < numIns; idx++) {
107 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
108 inPtrList[idx] = (inList[idx] == Circuit::NullGate()) ? nullptr : LoadGatePtr(inList[idx]);
109 }
110 ASSERT(opcode.GetMachineType() != MachineType::FLEX);
111 auto newGate = new (gateSpace) Gate(gateCount_, opcode, opcode.GetMachineType(), bitfield, inPtrList.data(), type,
112 mark);
113 gateCount_++;
114 return SaveGatePtr(newGate);
115 }
116
NewGate(OpCode opcode,BitField bitfield,const std::vector<GateRef> & inList,GateType type,MarkCode mark)117 GateRef Circuit::NewGate(OpCode opcode, BitField bitfield, const std::vector<GateRef> &inList, GateType type,
118 MarkCode mark)
119 {
120 return NewGate(opcode, bitfield, inList.size(), inList.data(), type, mark);
121 }
122
PrintAllGates() const123 void Circuit::PrintAllGates() const
124 {
125 const auto &gateList = GetAllGates();
126 for (const auto &gate : gateList) {
127 LoadGatePtrConst(gate)->Print();
128 }
129 }
130
PrintAllGates(BytecodeCircuitBuilder & builder) const131 void Circuit::PrintAllGates(BytecodeCircuitBuilder &builder) const
132 {
133 const auto &gateList = GetAllGates();
134 for (const auto &gate : gateList) {
135 auto item = builder.GetGateToBytecode().find(gate);
136 if (item != builder.GetGateToBytecode().end()) {
137 std::string bytecodeStr = builder.GetBytecodeStr(gate);
138 LoadGatePtrConst(gate)->PrintByteCode(bytecodeStr);
139 } else {
140 LoadGatePtrConst(gate)->Print();
141 }
142 }
143 }
144
GetAllGates() const145 std::vector<GateRef> Circuit::GetAllGates() const
146 {
147 std::vector<GateRef> gateList;
148 gateList.push_back(0);
149 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
150 for (size_t out = sizeof(Gate); out < circuitSize_;
151 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
152 out += Gate::GetGateSize(reinterpret_cast<const Out *>(LoadGatePtrConst(GateRef(out)))->GetIndex() + 1)) {
153 gateList.push_back(SaveGatePtr(reinterpret_cast<const Out *>(LoadGatePtrConst(GateRef(out)))->GetGateConst()));
154 }
155 return gateList;
156 }
157
SaveGatePtr(const Gate * gate) const158 GateRef Circuit::SaveGatePtr(const Gate *gate) const
159 {
160 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
161 return static_cast<GateRef>(reinterpret_cast<const uint8_t *>(gate) - GetDataPtrConst(0));
162 }
163
LoadGatePtr(GateRef shift)164 Gate *Circuit::LoadGatePtr(GateRef shift)
165 {
166 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
167 return reinterpret_cast<Gate *>(GetDataPtr(shift));
168 }
169
LoadGatePtrConst(GateRef shift) const170 const Gate *Circuit::LoadGatePtrConst(GateRef shift) const
171 {
172 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
173 return reinterpret_cast<const Gate *>(GetDataPtrConst(shift));
174 }
175
GetCircuitRoot(OpCode opcode)176 GateRef Circuit::GetCircuitRoot(OpCode opcode)
177 {
178 switch (opcode) {
179 case OpCode::CIRCUIT_ROOT:
180 return sizeof(In) * 0 + sizeof(Out) * 0 + sizeof(Gate) * 0; // 0 0 0: offset of circuit root
181 case OpCode::STATE_ENTRY:
182 return sizeof(In) * 0 + sizeof(Out) * 1 + sizeof(Gate) * 1; // 0 1 1: offset of state entry
183 case OpCode::DEPEND_ENTRY:
184 return sizeof(In) * 1 + sizeof(Out) * 2 + sizeof(Gate) * 2; // 1 2 2: offset of depend entry
185 case OpCode::FRAMESTATE_ENTRY:
186 return sizeof(In) * 2 + sizeof(Out) * 3 + sizeof(Gate) * 3; // 2 3 3: offset of framestate entry
187 case OpCode::RETURN_LIST:
188 return sizeof(In) * 3 + sizeof(Out) * 4 + sizeof(Gate) * 4; // 3 4 4: offset of return list
189 case OpCode::THROW_LIST:
190 return sizeof(In) * 4 + sizeof(Out) * 5 + sizeof(Gate) * 5; // 4 5 5: offset of throw list
191 case OpCode::CONSTANT_LIST:
192 return sizeof(In) * 5 + sizeof(Out) * 6 + sizeof(Gate) * 6; // 5 6 6: offset of constant list
193 case OpCode::ALLOCA_LIST:
194 return sizeof(In) * 6 + sizeof(Out) * 7 + sizeof(Gate) * 7; // 6 7 7: offset of alloca list
195 case OpCode::ARG_LIST:
196 return sizeof(In) * 7 + sizeof(Out) * 8 + sizeof(Gate) * 8; // 7 8 8: offset of arg list
197 default:
198 UNREACHABLE();
199 }
200 }
201
~Circuit()202 Circuit::~Circuit() {}
203
AdvanceTime() const204 void Circuit::AdvanceTime() const
205 {
206 auto &curTime = const_cast<TimeStamp &>(time_);
207 curTime++;
208 if (curTime == 0) {
209 curTime = 1;
210 ResetAllGateTimeStamps();
211 }
212 }
213
ResetAllGateTimeStamps() const214 void Circuit::ResetAllGateTimeStamps() const
215 {
216 const auto &gateList = GetAllGates();
217 for (auto &gate : gateList) {
218 const_cast<Gate *>(LoadGatePtrConst(gate))->SetMark(MarkCode::NO_MARK, 0);
219 }
220 }
221
GetTime() const222 TimeStamp Circuit::GetTime() const
223 {
224 return time_;
225 }
226
GetMark(GateRef gate) const227 MarkCode Circuit::GetMark(GateRef gate) const
228 {
229 return LoadGatePtrConst(gate)->GetMark(GetTime());
230 }
231
SetMark(GateRef gate,MarkCode mark) const232 void Circuit::SetMark(GateRef gate, MarkCode mark) const
233 {
234 const_cast<Gate *>(LoadGatePtrConst(gate))->SetMark(mark, GetTime());
235 }
236
Verify(GateRef gate) const237 bool Circuit::Verify(GateRef gate) const
238 {
239 return LoadGatePtrConst(gate)->Verify();
240 }
241
NullGate()242 GateRef Circuit::NullGate()
243 {
244 return -1;
245 }
246
IsLoopHead(GateRef gate) const247 bool Circuit::IsLoopHead(GateRef gate) const
248 {
249 if (gate != NullGate()) {
250 const Gate *curGate = LoadGatePtrConst(gate);
251 return curGate->GetOpCode().IsLoopHead();
252 }
253 return false;
254 }
255
IsControlCase(GateRef gate) const256 bool Circuit::IsControlCase(GateRef gate) const
257 {
258 if (gate != NullGate()) {
259 const Gate *curGate = LoadGatePtrConst(gate);
260 return curGate->GetOpCode().IsControlCase();
261 }
262 return false;
263 }
264
IsSelector(GateRef gate) const265 bool Circuit::IsSelector(GateRef gate) const
266 {
267 if (gate != NullGate()) {
268 const Gate *curGate = LoadGatePtrConst(gate);
269 return curGate->GetOpCode() == OpCode::VALUE_SELECTOR;
270 }
271 return false;
272 }
273
GetInVector(GateRef gate) const274 std::vector<GateRef> Circuit::GetInVector(GateRef gate) const
275 {
276 std::vector<GateRef> result;
277 const Gate *curGate = LoadGatePtrConst(gate);
278 for (size_t idx = 0; idx < curGate->GetNumIns(); idx++) {
279 result.push_back(SaveGatePtr(curGate->GetInGateConst(idx)));
280 }
281 return result;
282 }
283
GetIn(GateRef gate,size_t idx) const284 GateRef Circuit::GetIn(GateRef gate, size_t idx) const
285 {
286 ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
287 const Gate *curGate = LoadGatePtrConst(gate);
288 return SaveGatePtr(curGate->GetInGateConst(idx));
289 }
290
IsInGateNull(GateRef gate,size_t idx) const291 bool Circuit::IsInGateNull(GateRef gate, size_t idx) const
292 {
293 const Gate *curGate = LoadGatePtrConst(gate);
294 return curGate->GetInConst(idx)->IsGateNull();
295 }
296
IsFirstOutNull(GateRef gate) const297 bool Circuit::IsFirstOutNull(GateRef gate) const
298 {
299 const Gate *curGate = LoadGatePtrConst(gate);
300 return curGate->IsFirstOutNull();
301 }
302
GetOutVector(GateRef gate) const303 std::vector<GateRef> Circuit::GetOutVector(GateRef gate) const
304 {
305 std::vector<GateRef> result;
306 const Gate *curGate = LoadGatePtrConst(gate);
307 if (!curGate->IsFirstOutNull()) {
308 const Out *curOut = curGate->GetFirstOutConst();
309 result.push_back(SaveGatePtr(curOut->GetGateConst()));
310 while (!curOut->IsNextOutNull()) {
311 curOut = curOut->GetNextOutConst();
312 result.push_back(SaveGatePtr(curOut->GetGateConst()));
313 }
314 }
315 return result;
316 }
317
NewIn(GateRef gate,size_t idx,GateRef in)318 void Circuit::NewIn(GateRef gate, size_t idx, GateRef in)
319 {
320 #ifndef NDEBUG
321 ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
322 ASSERT(Circuit::IsInGateNull(gate, idx));
323 #endif
324 LoadGatePtr(gate)->NewIn(idx, LoadGatePtr(in));
325 }
326
ModifyIn(GateRef gate,size_t idx,GateRef in)327 void Circuit::ModifyIn(GateRef gate, size_t idx, GateRef in)
328 {
329 #ifndef NDEBUG
330 ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
331 ASSERT(!Circuit::IsInGateNull(gate, idx));
332 #endif
333 LoadGatePtr(gate)->ModifyIn(idx, LoadGatePtr(in));
334 }
335
DeleteIn(GateRef gate,size_t idx)336 void Circuit::DeleteIn(GateRef gate, size_t idx)
337 {
338 ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
339 ASSERT(!Circuit::IsInGateNull(gate, idx));
340 LoadGatePtr(gate)->DeleteIn(idx);
341 }
342
DeleteGate(GateRef gate)343 void Circuit::DeleteGate(GateRef gate)
344 {
345 LoadGatePtr(gate)->DeleteGate();
346 }
347
SetOpCode(GateRef gate,OpCode opcode)348 void Circuit::SetOpCode(GateRef gate, OpCode opcode)
349 {
350 LoadGatePtr(gate)->SetOpCode(opcode);
351 }
352
SetGateType(GateRef gate,GateType type)353 void Circuit::SetGateType(GateRef gate, GateType type)
354 {
355 LoadGatePtr(gate)->SetGateType(type);
356 }
357
SetMachineType(GateRef gate,MachineType machineType)358 void Circuit::SetMachineType(GateRef gate, MachineType machineType)
359 {
360 LoadGatePtr(gate)->SetMachineType(machineType);
361 }
362
GetGateType(GateRef gate) const363 GateType Circuit::GetGateType(GateRef gate) const
364 {
365 return LoadGatePtrConst(gate)->GetGateType();
366 }
367
GetMachineType(GateRef gate) const368 MachineType Circuit::GetMachineType(GateRef gate) const
369 {
370 return LoadGatePtrConst(gate)->GetMachineType();
371 }
372
GetOpCode(GateRef gate) const373 OpCode Circuit::GetOpCode(GateRef gate) const
374 {
375 return LoadGatePtrConst(gate)->GetOpCode();
376 }
377
GetId(GateRef gate) const378 GateId Circuit::GetId(GateRef gate) const
379 {
380 return LoadGatePtrConst(gate)->GetId();
381 }
382
GetBitField(GateRef gate) const383 BitField Circuit::GetBitField(GateRef gate) const
384 {
385 return LoadGatePtrConst(gate)->GetBitField();
386 }
387
Print(GateRef gate) const388 void Circuit::Print(GateRef gate) const
389 {
390 LoadGatePtrConst(gate)->Print();
391 }
392
GetDataSection() const393 std::vector<uint8_t> Circuit::GetDataSection() const
394 {
395 return dataSection_;
396 }
397
SetDataSection(const std::vector<uint8_t> & data)398 void Circuit::SetDataSection(const std::vector<uint8_t> &data)
399 {
400 dataSection_ = data;
401 }
402
GetCircuitDataSize() const403 size_t Circuit::GetCircuitDataSize() const
404 {
405 return circuitSize_;
406 }
407
GetSpaceDataStartPtrConst() const408 const void *Circuit::GetSpaceDataStartPtrConst() const
409 {
410 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
411 return GetDataPtrConst(0);
412 }
413
GetSpaceDataEndPtrConst() const414 const void *Circuit::GetSpaceDataEndPtrConst() const
415 {
416 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
417 return GetDataPtrConst(circuitSize_);
418 }
419
GetDataPtrConst(size_t offset) const420 const uint8_t *Circuit::GetDataPtrConst(size_t offset) const
421 {
422 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
423 return space_.data() + offset;
424 }
425
GetDataPtr(size_t offset)426 uint8_t *Circuit::GetDataPtr(size_t offset)
427 {
428 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
429 return space_.data() + offset;
430 }
431
GetSpaceDataSize() const432 size_t Circuit::GetSpaceDataSize() const
433 {
434 return space_.size();
435 }
436
SetSpaceDataSize(size_t sz)437 void Circuit::SetSpaceDataSize(size_t sz)
438 {
439 return space_.resize(sz);
440 }
441
GetFrameType() const442 panda::ecmascript::FrameType Circuit::GetFrameType() const
443 {
444 return frameType_;
445 }
446
SetFrameType(panda::ecmascript::FrameType type)447 void Circuit::SetFrameType(panda::ecmascript::FrameType type)
448 {
449 frameType_ = type;
450 }
451 } // namespace panda::ecmascript::kungfu
452