• 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(Chunk * chunk,size_t numVregs)32     explicit FrameStateInfo(Chunk* chunk, size_t numVregs)
33         : values_(numVregs, chunk), liveout_(chunk, numVregs) {}
34 
SetValuesAt(size_t index,GateRef gate)35     void SetValuesAt(size_t index, GateRef gate)
36     {
37         ASSERT(index < values_.size());
38         values_[index] = gate;
39     }
40 
SetBit(size_t index)41     void SetBit(size_t index)
42     {
43         liveout_.SetBit(index);
44     }
45 
ClearBit(size_t index)46     void ClearBit(size_t index)
47     {
48         liveout_.ClearBit(index);
49     }
50 
ValuesAt(size_t index)51     GateRef ValuesAt(size_t index) const
52     {
53         ASSERT(index < values_.size());
54         return values_[index];
55     }
56 
CopyFrom(FrameStateInfo * other)57     void CopyFrom(FrameStateInfo *other)
58     {
59         values_.assign(other->values_.begin(), other->values_.end());
60         liveout_.CopyFrom(other->liveout_);
61     }
62 
MergeLiveout(FrameStateInfo * other)63     bool MergeLiveout(FrameStateInfo *other)
64     {
65         return liveout_.UnionWithChanged(other->liveout_);
66     }
67 private:
68     // [numVRegs_] [extra args] [numArgs_] [accumulator]
69     ChunkVector<GateRef> values_;
70     BitSet liveout_;
71 };
72 
73 class FrameStateBuilder {
74 public:
75     FrameStateBuilder(BytecodeCircuitBuilder *builder,
76         Circuit *circuit, const MethodLiteral *literal);
77     ~FrameStateBuilder();
78 
79     void BuildFrameState();
80 private:
81     static constexpr size_t FIXED_ARGS = 2; // ac & env
ValuesAt(size_t index)82     GateRef ValuesAt(size_t index) const
83     {
84         return liveOutResult_->ValuesAt(index);
85     }
86 
ValuesAtAccumulator()87     GateRef ValuesAtAccumulator() const
88     {
89         return ValuesAt(accumulatorIndex_);
90     }
UpdateVirtualRegister(size_t index,GateRef gate)91     void UpdateVirtualRegister(size_t index, GateRef gate)
92     {
93         liveOutResult_->SetValuesAt(index, gate);
94         if (gate == Circuit::NullGate()) {
95             liveOutResult_->ClearBit(index);
96         } else {
97             liveOutResult_->SetBit(index);
98         }
99     }
UpdateAccumulator(GateRef gate)100     void UpdateAccumulator(GateRef gate)
101     {
102         UpdateVirtualRegister(accumulatorIndex_, gate);
103     }
104     void BindStateSplit(GateRef state, GateRef depend, GateRef frameState);
105     void BindStateSplit(GateRef gate, GateRef frameState);
106     void BindBBStateSplit();
107     void UpdateVirtualRegister(size_t id, size_t index, GateRef gate);
108     GateRef BuildFrameStateGate(size_t pcOffset, GateRef frameValues, FrameStateOutput output);
109     GateRef BuildFrameValues(FrameStateInfo *stateInfo);
110 
111     FrameStateInfo *CreateEmptyStateInfo();
112     void BuildPostOrderList(size_t size);
113     bool ComputeLiveOut(size_t bbId);
114     void ComputeLiveState();
115     void ComputeLiveOutBC(uint32_t index, const BytecodeInfo &bytecodeInfo, size_t bbId);
116     bool IsAsyncResolveOrSusp(const BytecodeInfo &bytecodeInfo);
117     bool MergeIntoPredBC(uint32_t predPc, size_t diff);
118     bool MergeIntoPredBB(BytecodeRegion *bb, BytecodeRegion *predBb);
119     size_t LoopExitCount(BytecodeRegion *bb, BytecodeRegion *bbNext);
120     GateRef TryGetLoopExitValue(GateRef value, size_t diff);
GetOrOCreateBCEndStateInfo(uint32_t bcIndex)121     FrameStateInfo *GetOrOCreateBCEndStateInfo(uint32_t bcIndex)
122     {
123         auto currentInfo = bcEndStateInfos_[bcIndex];
124         if (currentInfo == nullptr) {
125             currentInfo = CreateEmptyStateInfo();
126             bcEndStateInfos_[bcIndex] = currentInfo;
127         }
128         return currentInfo;
129     }
GetEntryBBBeginStateInfo()130     FrameStateInfo *GetEntryBBBeginStateInfo()
131     {
132         auto entry = CreateEmptyStateInfo();
133         auto first = bbBeginStateInfos_.at(1);  // 1: first block
134         for (size_t i = 0; i < numVregs_; ++i) {
135             auto value = first->ValuesAt(i);
136             if (value == Circuit::NullGate()) {
137                 continue;
138             }
139             if (gateAcc_.IsValueSelector(value)) {
140                 value = gateAcc_.GetValueIn(value);
141             }
142             entry->SetValuesAt(i, value);
143         }
144         return entry;
145     }
GetBBBeginStateInfo(size_t bbId)146     FrameStateInfo *GetBBBeginStateInfo(size_t bbId)
147     {
148         if (bbId == 0) {    // 0: entry block
149             return GetEntryBBBeginStateInfo();
150         }
151         return bbBeginStateInfos_.at(bbId);
152     }
153     void UpdateVirtualRegistersOfSuspend(GateRef gate);
154     void UpdateVirtualRegistersOfResume(GateRef gate);
155     void SaveBBBeginStateInfo(size_t bbId);
156     FrameStateInfo *GetFrameInfoBefore(BytecodeRegion &bb, uint32_t bcId);
157     FrameStateInfo *GetFrameInfoAfter(uint32_t bcId);
158     GateRef GetPreBBInput(BytecodeRegion *bb, BytecodeRegion *predBb, GateRef gate);
159     GateRef GetPhiComponent(BytecodeRegion *bb, BytecodeRegion *predBb, GateRef phi);
160     void BuildFrameState(BytecodeRegion& bb, const BytecodeInfo &bytecodeInfo, size_t index);
161     void BuildStateSplitAfter(size_t index, BytecodeRegion& bb);
162     void BuildStateSplitBefore(BytecodeRegion& bb, size_t index);
163     bool ShouldInsertFrameStateBefore(BytecodeRegion& bb, size_t index);
164     void BuildCallFrameState(size_t index, BytecodeRegion& bb);
165     size_t GetNearestNextIndex(size_t index, BytecodeRegion& bb) const;
166 
167     BytecodeCircuitBuilder *builder_{nullptr};
168     FrameStateInfo *liveOutResult_{nullptr};
169     size_t numVregs_ {0};
170     size_t accumulatorIndex_ {0};
171     Circuit *circuit_ {nullptr};
172     GateAccessor gateAcc_;
173     ChunkVector<FrameStateInfo *> bcEndStateInfos_;
174     ChunkVector<FrameStateInfo *> bbBeginStateInfos_;
175     ChunkVector<size_t> postOrderList_;
176 };
177 }  // panda::ecmascript::kungfu
178 #endif  // ECMASCRIPT_COMPILER_FRAME_STATE_H
179