• 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/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