• 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/bytecode_circuit_builder.h"
17 #include "ecmascript/compiler/circuit.h"
18 #include "ecmascript/compiler/ecma_opcode_des.h"
19 #include "ecmascript/compiler/gate_accessor.h"
20 #include "ecmascript/platform/map.h"
21 
22 namespace panda::ecmascript::kungfu {
Circuit(NativeAreaAllocator * allocator,bool isArch64)23 Circuit::Circuit(NativeAreaAllocator* allocator, bool isArch64) :
24     circuitSize_(0), gateCount_(0), time_(1),
25     isArch64_(isArch64), chunk_(allocator),
26     root_(Circuit::NullGate()), metaBuilder_(chunk())
27 #ifndef NDEBUG
28     , allGates_(chunk())
29 #endif
30 {
31     space_ = panda::ecmascript::PageMap(CIRCUIT_SPACE, PAGE_PROT_READWRITE).GetMem();
32     InitRoot();
33 }
34 
~Circuit()35 Circuit::~Circuit()
36 {
37     panda::ecmascript::PageUnmap(MemMap(space_, CIRCUIT_SPACE));
38 }
39 
InitRoot()40 void Circuit::InitRoot()
41 {
42     root_ = NewGate(metaBuilder_.CircuitRoot(), MachineType::NOVALUE, {}, GateType::Empty());
43     NewGate(metaBuilder_.StateEntry(), MachineType::NOVALUE, { root_ }, GateType::Empty());
44     NewGate(metaBuilder_.DependEntry(), MachineType::NOVALUE, { root_ }, GateType::Empty());
45     NewGate(metaBuilder_.ReturnList(), MachineType::NOVALUE, { root_ }, GateType::Empty());
46     NewGate(metaBuilder_.ArgList(), MachineType::NOVALUE, { root_ }, GateType::Empty());
47 }
48 
AllocateSpace(size_t gateSize)49 uint8_t *Circuit::AllocateSpace(size_t gateSize)
50 {
51     circuitSize_ += gateSize;
52     if (circuitSize_ > CIRCUIT_SPACE) {
53         return nullptr;  // abort compilation
54     }
55     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
56     return GetDataPtr(circuitSize_ - gateSize);
57 }
58 
AllocateGateSpace(size_t numIns)59 Gate *Circuit::AllocateGateSpace(size_t numIns)
60 {
61     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
62     return reinterpret_cast<Gate *>(AllocateSpace(Gate::GetGateSize(numIns)) + Gate::GetOutListSize(numIns));
63 }
64 
65 // NOLINTNEXTLINE(modernize-avoid-c-arrays)
NewGate(const GateMetaData * meta,MachineType machineType,size_t numIns,const GateRef inList[],GateType type)66 GateRef Circuit::NewGate(const GateMetaData *meta, MachineType machineType,
67     size_t numIns, const GateRef inList[], GateType type)
68 {
69 #ifndef NDEBUG
70     if (numIns != meta->GetNumIns()) {
71         LOG_COMPILER(ERROR) << "Invalid input list!"
72                             << " op=" << meta->GetOpCode()
73                             << " expected_num_in=" << meta->GetNumIns() << " actual_num_in=" << numIns;
74         UNREACHABLE();
75     }
76 #endif
77     std::vector<Gate *> inPtrList(numIns);
78     auto gateSpace = AllocateGateSpace(numIns);
79     for (size_t idx = 0; idx < numIns; idx++) {
80         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
81         inPtrList[idx] = (inList[idx] == Circuit::NullGate()) ? nullptr : LoadGatePtr(inList[idx]);
82     }
83     auto newGate = new (gateSpace) Gate(meta, gateCount_++, inPtrList.data(), machineType, type);
84 #ifndef NDEBUG
85     allGates_.push_back(GetGateRef(newGate));
86 #endif
87     return GetGateRef(newGate);
88 }
89 
NewGate(const GateMetaData * meta,const std::vector<GateRef> & inList)90 GateRef Circuit::NewGate(const GateMetaData *meta, const std::vector<GateRef> &inList)
91 {
92     return NewGate(meta, MachineType::NOVALUE, inList.size(), inList.data(), GateType::Empty());
93 }
94 
NewGate(const GateMetaData * meta,MachineType machineType,const std::initializer_list<GateRef> & args,GateType type)95 GateRef Circuit::NewGate(const GateMetaData *meta, MachineType machineType,
96     const std::initializer_list<GateRef>& args, GateType type)
97 {
98     return NewGate(meta, machineType, args.size(), args.begin(), type);
99 }
100 
NewGate(const GateMetaData * meta,MachineType machineType,GateType type)101 GateRef Circuit::NewGate(const GateMetaData *meta, MachineType machineType, GateType type)
102 {
103     return NewGate(meta, machineType, {}, type);
104 }
105 
PrintAllGates() const106 void Circuit::PrintAllGates() const
107 {
108     std::vector<GateRef> gateList;
109     GetAllGates(gateList);
110     for (const auto &gate : gateList) {
111         LoadGatePtrConst(gate)->Print();
112     }
113 }
114 
PrintAllGatesWithBytecode() const115 void Circuit::PrintAllGatesWithBytecode() const
116 {
117     std::vector<GateRef> gateList;
118     GetAllGates(gateList);
119     for (const auto &gate : gateList) {
120         if (GetOpCode(gate) == OpCode::JS_BYTECODE) {
121             const Gate *gatePtr = LoadGatePtrConst(gate);
122             auto opcode =  gatePtr->GetJSBytecodeMetaData()->GetByteCodeOpcode();
123             std::string bytecodeStr = GetEcmaOpcodeStr(opcode);
124             LoadGatePtrConst(gate)->PrintByteCode(bytecodeStr);
125         } else {
126             LoadGatePtrConst(gate)->Print();
127         }
128     }
129 }
130 
GetAllGates(std::vector<GateRef> & gateList) const131 void Circuit::GetAllGates(std::vector<GateRef>& gateList) const
132 {
133     gateList.clear();
134     for (size_t out = 0; out < circuitSize_;
135         out += Gate::GetGateSize(reinterpret_cast<const Out *>(LoadGatePtrConst(GateRef(out)))->GetIndex() + 1)) {
136         auto gatePtr = reinterpret_cast<const Out *>(LoadGatePtrConst(GateRef(out)))->GetGateConst();
137         if (!gatePtr->GetMetaData()->IsNop()) {
138             gateList.push_back(GetGateRef(gatePtr));
139         }
140     }
141 }
142 
GetGateRef(const Gate * gate) const143 GateRef Circuit::GetGateRef(const Gate *gate) const
144 {
145     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
146     return static_cast<GateRef>(reinterpret_cast<const uint8_t *>(gate) - GetDataPtrConst(0));
147 }
148 
LoadGatePtr(GateRef shift)149 Gate *Circuit::LoadGatePtr(GateRef shift)
150 {
151     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
152     return reinterpret_cast<Gate *>(GetDataPtr(shift));
153 }
154 
LoadGatePtrConst(GateRef shift) const155 const Gate *Circuit::LoadGatePtrConst(GateRef shift) const
156 {
157     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
158     return reinterpret_cast<const Gate *>(GetDataPtrConst(shift));
159 }
160 
161 
162 
AdvanceTime() const163 void Circuit::AdvanceTime() const
164 {
165     auto &curTime = const_cast<TimeStamp &>(time_);
166     curTime++;
167     if (curTime == 0) {
168         curTime = 1;
169         ResetAllGateTimeStamps();
170     }
171 }
172 
ResetAllGateTimeStamps() const173 void Circuit::ResetAllGateTimeStamps() const
174 {
175     std::vector<GateRef> gateList;
176     GetAllGates(gateList);
177     for (auto &gate : gateList) {
178         const_cast<Gate *>(LoadGatePtrConst(gate))->SetMark(MarkCode::NO_MARK, 0);
179     }
180 }
181 
GetTime() const182 TimeStamp Circuit::GetTime() const
183 {
184     return time_;
185 }
186 
GetMark(GateRef gate) const187 MarkCode Circuit::GetMark(GateRef gate) const
188 {
189     return LoadGatePtrConst(gate)->GetMark(GetTime());
190 }
191 
SetMark(GateRef gate,MarkCode mark) const192 void Circuit::SetMark(GateRef gate, MarkCode mark) const
193 {
194     const_cast<Gate *>(LoadGatePtrConst(gate))->SetMark(mark, GetTime());
195 }
196 
Verify(GateRef gate) const197 void Circuit::Verify(GateRef gate) const
198 {
199     LoadGatePtrConst(gate)->Verify(IsArch64());
200 }
201 
NullGate()202 GateRef Circuit::NullGate()
203 {
204     return Gate::InvalidGateRef;
205 }
206 
IsLoopHead(GateRef gate) const207 bool Circuit::IsLoopHead(GateRef gate) const
208 {
209     if (gate != NullGate()) {
210         const Gate *curGate = LoadGatePtrConst(gate);
211         return curGate->GetMetaData()->IsLoopHead();
212     }
213     return false;
214 }
215 
IsControlCase(GateRef gate) const216 bool Circuit::IsControlCase(GateRef gate) const
217 {
218     if (gate != NullGate()) {
219         const Gate *curGate = LoadGatePtrConst(gate);
220         return curGate->GetMetaData()->IsControlCase();
221     }
222     return false;
223 }
224 
IsSelector(GateRef gate) const225 bool Circuit::IsSelector(GateRef gate) const
226 {
227     if (gate != NullGate()) {
228         const Gate *curGate = LoadGatePtrConst(gate);
229         return curGate->GetOpCode() == OpCode::VALUE_SELECTOR;
230     }
231     return false;
232 }
233 
GetIn(GateRef gate,size_t idx) const234 GateRef Circuit::GetIn(GateRef gate, size_t idx) const
235 {
236     ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
237     if (IsInGateNull(gate, idx)) {
238         return NullGate();
239     }
240     const Gate *curGate = LoadGatePtrConst(gate);
241     return GetGateRef(curGate->GetInGateConst(idx));
242 }
243 
IsInGateNull(GateRef gate,size_t idx) const244 bool Circuit::IsInGateNull(GateRef gate, size_t idx) const
245 {
246     const Gate *curGate = LoadGatePtrConst(gate);
247     return curGate->GetInConst(idx)->IsGateNull();
248 }
249 
IsFirstOutNull(GateRef gate) const250 bool Circuit::IsFirstOutNull(GateRef gate) const
251 {
252     const Gate *curGate = LoadGatePtrConst(gate);
253     return curGate->IsFirstOutNull();
254 }
255 
GetOutVector(GateRef gate) const256 std::vector<GateRef> Circuit::GetOutVector(GateRef gate) const
257 {
258     std::vector<GateRef> result;
259     const Gate *curGate = LoadGatePtrConst(gate);
260     if (!curGate->IsFirstOutNull()) {
261         const Out *curOut = curGate->GetFirstOutConst();
262         result.push_back(GetGateRef(curOut->GetGateConst()));
263         while (!curOut->IsNextOutNull()) {
264             curOut = curOut->GetNextOutConst();
265             result.push_back(GetGateRef(curOut->GetGateConst()));
266         }
267     }
268     return result;
269 }
270 
NewIn(GateRef gate,size_t idx,GateRef in)271 void Circuit::NewIn(GateRef gate, size_t idx, GateRef in)
272 {
273 #ifndef NDEBUG
274     ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
275     ASSERT(Circuit::IsInGateNull(gate, idx));
276 #endif
277     LoadGatePtr(gate)->NewIn(idx, LoadGatePtr(in));
278 }
279 
ModifyIn(GateRef gate,size_t idx,GateRef in)280 void Circuit::ModifyIn(GateRef gate, size_t idx, GateRef in)
281 {
282 #ifndef NDEBUG
283     ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
284     ASSERT(!Circuit::IsInGateNull(gate, idx) || (GetOpCode(gate) == OpCode::SAVE_REGISTER));
285 #endif
286     LoadGatePtr(gate)->ModifyIn(idx, LoadGatePtr(in));
287 }
288 
DeleteIn(GateRef gate,size_t idx)289 void Circuit::DeleteIn(GateRef gate, size_t idx)
290 {
291     ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
292     ASSERT(!Circuit::IsInGateNull(gate, idx));
293     LoadGatePtr(gate)->DeleteIn(idx);
294 }
295 
DeleteGate(GateRef gate)296 void Circuit::DeleteGate(GateRef gate)
297 {
298     LoadGatePtr(gate)->DeleteGate();
299     LoadGatePtr(gate)->SetMetaData(Nop());
300 }
301 
DecreaseIn(GateRef gate,size_t idx)302 void Circuit::DecreaseIn(GateRef gate, size_t idx)
303 {
304     auto numIns = LoadGatePtrConst(gate)->GetNumIns();
305     for (size_t i = idx; i < numIns - 1; i++) {
306         ModifyIn(gate, i, GetIn(gate, i + 1));
307     }
308     DeleteIn(gate, numIns - 1);
309     GateMetaData *meta = const_cast<GateMetaData *>(
310             LoadGatePtr(gate)->GetMetaData());
311     if (meta->GetKind() == GateMetaData::Kind::MUTABLE_WITH_SIZE) {
312         meta->DecreaseIn(idx);
313     } else {
314         meta = metaBuilder_.NewGateMetaData(meta);
315         meta->DecreaseIn(idx);
316         LoadGatePtr(gate)->SetMetaData(meta);
317     }
318 }
319 
SetGateType(GateRef gate,GateType type)320 void Circuit::SetGateType(GateRef gate, GateType type)
321 {
322     LoadGatePtr(gate)->SetGateType(type);
323 }
324 
SetMachineType(GateRef gate,MachineType machineType)325 void Circuit::SetMachineType(GateRef gate, MachineType machineType)
326 {
327     LoadGatePtr(gate)->SetMachineType(machineType);
328 }
329 
GetGateType(GateRef gate) const330 GateType Circuit::GetGateType(GateRef gate) const
331 {
332     return LoadGatePtrConst(gate)->GetGateType();
333 }
334 
GetMachineType(GateRef gate) const335 MachineType Circuit::GetMachineType(GateRef gate) const
336 {
337     return LoadGatePtrConst(gate)->GetMachineType();
338 }
339 
GetOpCode(GateRef gate) const340 OpCode Circuit::GetOpCode(GateRef gate) const
341 {
342     return LoadGatePtrConst(gate)->GetOpCode();
343 }
344 
GetId(GateRef gate) const345 GateId Circuit::GetId(GateRef gate) const
346 {
347     return LoadGatePtrConst(gate)->GetId();
348 }
349 
Print(GateRef gate) const350 void Circuit::Print(GateRef gate) const
351 {
352     LoadGatePtrConst(gate)->Print();
353 }
354 
GetCircuitDataSize() const355 size_t Circuit::GetCircuitDataSize() const
356 {
357     return circuitSize_;
358 }
359 
GetSpaceDataStartPtrConst() const360 const void *Circuit::GetSpaceDataStartPtrConst() const
361 {
362     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
363     return GetDataPtrConst(0);
364 }
365 
GetSpaceDataEndPtrConst() const366 const void *Circuit::GetSpaceDataEndPtrConst() const
367 {
368     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
369     return GetDataPtrConst(circuitSize_);
370 }
371 
GetDataPtrConst(size_t offset) const372 const uint8_t *Circuit::GetDataPtrConst(size_t offset) const
373 {
374     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
375     return static_cast<uint8_t *>(space_) + offset;
376 }
377 
GetDataPtr(size_t offset)378 uint8_t *Circuit::GetDataPtr(size_t offset)
379 {
380     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
381     return static_cast<uint8_t *>(space_) + offset;
382 }
383 
GetFrameType() const384 panda::ecmascript::FrameType Circuit::GetFrameType() const
385 {
386     return frameType_;
387 }
388 
SetFrameType(panda::ecmascript::FrameType type)389 void Circuit::SetFrameType(panda::ecmascript::FrameType type)
390 {
391     frameType_ = type;
392 }
393 
GetConstantGate(MachineType machineType,uint64_t value,GateType type)394 GateRef Circuit::GetConstantGate(MachineType machineType, uint64_t value,
395                                  GateType type)
396 {
397     auto search = constantCache_.find({machineType, value, type});
398     if (search != constantCache_.end()) {
399         return constantCache_.at({machineType, value, type});
400     }
401     auto gate = NewGate(metaBuilder_.Constant(value), machineType, type);
402     constantCache_[{machineType, value, type}] = gate;
403     return gate;
404 }
405 
NewArg(MachineType machineType,size_t index,GateType type,GateRef argRoot)406 GateRef Circuit::NewArg(MachineType machineType, size_t index,
407                         GateType type, GateRef argRoot)
408 {
409     return NewGate(metaBuilder_.Arg(index), machineType, { argRoot }, type);
410 }
411 
GetConstantDataGate(uint64_t value,GateType type)412 GateRef Circuit::GetConstantDataGate(uint64_t value, GateType type)
413 {
414     auto search = constantDataCache_.find(value);
415     if (search != constantDataCache_.end()) {
416         return constantDataCache_.at(value);
417     }
418     auto gate = NewGate(metaBuilder_.ConstData(value), MachineType::ARCH, type);
419     constantDataCache_[value] = gate;
420     return gate;
421 }
422 
GetGateCount() const423 size_t Circuit::GetGateCount() const
424 {
425     return gateCount_;
426 }
427 
GetStateRoot() const428 GateRef Circuit::GetStateRoot() const
429 {
430     const GateAccessor acc(const_cast<Circuit*>(this));
431     return acc.GetStateRoot();
432 }
433 
GetDependRoot() const434 GateRef Circuit::GetDependRoot() const
435 {
436     const GateAccessor acc(const_cast<Circuit*>(this));
437     return acc.GetDependRoot();
438 }
439 
GetArgRoot() const440 GateRef Circuit::GetArgRoot() const
441 {
442     const GateAccessor acc(const_cast<Circuit*>(this));
443     return acc.GetArgRoot();
444 }
445 
GetReturnRoot() const446 GateRef Circuit::GetReturnRoot() const
447 {
448     const GateAccessor acc(const_cast<Circuit*>(this));
449     return acc.GetReturnRoot();
450 }
451 }  // namespace panda::ecmascript::kungfu
452