• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #ifndef ECMASCRIPT_COMPILER_FRAME_STATE_H
17 #define ECMASCRIPT_COMPILER_FRAME_STATE_H
18 
19 #include "ecmascript/compiler/argument_accessor.h"
20 #include "ecmascript/compiler/base/bit_set.h"
21 #include "ecmascript/compiler/circuit.h"
22 #include "ecmascript/compiler/gate.h"
23 #include "ecmascript/compiler/gate_accessor.h"
24 #include "ecmascript/jspandafile/method_literal.h"
25 
26 namespace panda::ecmascript::kungfu {
27 class BytecodeCircuitBuilder;
28 struct BytecodeRegion;
29 
30 class FrameStateInfo {
31 public:
FrameStateInfo(size_t numVregs)32     explicit FrameStateInfo(size_t numVregs) : values_(numVregs), liveout_(numVregs) {}
33 
SetValuesAt(size_t index,GateRef gate)34     void SetValuesAt(size_t index, GateRef gate)
35     {
36         ASSERT(index < values_.size());
37         values_[index] = gate;
38     }
39 
SetBit(size_t index)40     void SetBit(size_t index)
41     {
42         liveout_.SetBit(index);
43     }
44 
ClearBit(size_t index)45     void ClearBit(size_t index)
46     {
47         liveout_.ClearBit(index);
48     }
49 
ValuesAt(size_t index)50     GateRef ValuesAt(size_t index) const
51     {
52         ASSERT(index < values_.size());
53         return values_[index];
54     }
55 
CopyFrom(FrameStateInfo * other)56     void CopyFrom(FrameStateInfo *other)
57     {
58         values_.assign(other->values_.begin(), other->values_.end());
59         liveout_.CopyFrom(other->liveout_);
60     }
61 
MergeLiveout(FrameStateInfo * other)62     bool MergeLiveout(FrameStateInfo *other)
63     {
64         return liveout_.UnionWithChanged(other->liveout_);
65     }
66 private:
67     // [numVRegs_] [extra args] [numArgs_] [accumulator]
68     std::vector<GateRef> values_ {};
69     BitSet liveout_;
70 };
71 
72 class FrameStateBuilder {
73 public:
74     FrameStateBuilder(BytecodeCircuitBuilder *builder,
75         Circuit *circuit, const MethodLiteral *literal);
76     ~FrameStateBuilder();
77 
78     void BuildFrameState();
79 private:
ValuesAt(size_t index)80     GateRef ValuesAt(size_t index) const
81     {
82         return liveOutResult_->ValuesAt(index);
83     }
84 
ValuesAtAccumulator()85     GateRef ValuesAtAccumulator() const
86     {
87         return ValuesAt(accumulatorIndex_);
88     }
UpdateVirtualRegister(size_t index,GateRef gate)89     void UpdateVirtualRegister(size_t index, GateRef gate)
90     {
91         liveOutResult_->SetValuesAt(index, gate);
92         if (gate == Circuit::NullGate()) {
93             liveOutResult_->ClearBit(index);
94         } else {
95             liveOutResult_->SetBit(index);
96         }
97     }
UpdateAccumulator(GateRef gate)98     void UpdateAccumulator(GateRef gate)
99     {
100         UpdateVirtualRegister(accumulatorIndex_, gate);
101     }
102     void BindStateSplit(GateRef gate, size_t pcOffset, FrameStateInfo *stateInfo);
103     void BindStateSplit(size_t size);
104     void UpdateVirtualRegister(size_t id, size_t index, GateRef gate);
105     GateRef FrameState(size_t pcOffset, FrameStateInfo *stateInfo);
106 
107     FrameStateInfo *CreateEmptyStateInfo();
108     void BuildPostOrderList(size_t size);
109     bool ComputeLiveOut(size_t bbId);
110     void ComputeLiveState();
111     void ComputeLiveOutBC(uint32_t index, const BytecodeInfo &bytecodeInfo);
112     bool MergeIntoPredBC(uint32_t predPc);
113     bool MergeIntoPredBB(BytecodeRegion *bb, BytecodeRegion *predBb);
GetOrOCreateBCEndStateInfo(uint32_t bcIndex)114     FrameStateInfo *GetOrOCreateBCEndStateInfo(uint32_t bcIndex)
115     {
116         auto currentInfo = bcEndStateInfos_[bcIndex];
117         if (currentInfo == nullptr) {
118             currentInfo = CreateEmptyStateInfo();
119             bcEndStateInfos_[bcIndex] = currentInfo;
120         }
121         return currentInfo;
122     }
GetBBBeginStateInfo(size_t bbId)123     FrameStateInfo *GetBBBeginStateInfo(size_t bbId) const
124     {
125         return bbBeginStateInfos_.at(bbId);
126     }
127     void UpdateVirtualRegistersOfSuspend(GateRef gate);
128     void UpdateVirtualRegistersOfResume(GateRef gate);
129     void SaveBBBeginStateInfo(size_t bbId);
130     FrameStateInfo *GetCurrentFrameInfo(BytecodeRegion &bb, uint32_t bcId);
131     GateRef GetPhiComponent(BytecodeRegion *bb, BytecodeRegion *predBb, GateRef phi);
132 
133     BytecodeCircuitBuilder *builder_{nullptr};
134     FrameStateInfo *liveOutResult_{nullptr};
135     size_t numVregs_ {0};
136     size_t accumulatorIndex_ {0};
137     Circuit *circuit_ {nullptr};
138     GateAccessor gateAcc_;
139     ArgumentAccessor argAcc_;
140     std::vector<FrameStateInfo *> bcEndStateInfos_;
141     std::vector<FrameStateInfo *> bbBeginStateInfos_;
142     std::vector<size_t> postOrderList_;
143 };
144 }  // panda::ecmascript::kungfu
145 #endif  // ECMASCRIPT_COMPILER_FRAME_STATE_H