• 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 "dynamicContext.h"
17 
18 #include <compiler/core/pandagen.h>
19 #include <compiler/base/catchTable.h>
20 #include <ir/expressions/identifier.h>
21 #include <ir/statements/tryStatement.h>
22 #include <ir/statements/blockStatement.h>
23 #include <ir/statements/labelledStatement.h>
24 
25 namespace panda::es2panda::compiler {
DynamicContext(PandaGen * pg,LabelTarget target)26 DynamicContext::DynamicContext(PandaGen *pg, LabelTarget target) : pg_(pg), target_(target), prev_(pg_->dynamicContext_)
27 {
28     pg_->dynamicContext_ = this;
29 }
30 
~DynamicContext()31 DynamicContext::~DynamicContext()
32 {
33     pg_->dynamicContext_ = prev_;
34 }
35 
LabelContext(PandaGen * pg,const ir::LabelledStatement * labelledStmt)36 LabelContext::LabelContext(PandaGen *pg, const ir::LabelledStatement *labelledStmt)
37     : DynamicContext(pg, LabelTarget(labelledStmt->Ident()->Name())), labelledStmt_(labelledStmt)
38 {
39     if (!labelledStmt->Body()->IsBlockStatement() && !labelledStmt->Body()->IsIfStatement()) {
40         return;
41     }
42 
43     label_ = pg->AllocLabel();
44     target_.SetBreakTarget(label_);
45 }
46 
~LabelContext()47 LabelContext::~LabelContext()
48 {
49     if (!label_) {
50         return;
51     }
52 
53     pg_->SetLabel(labelledStmt_, label_);
54 }
55 
LexEnvContext(LoopEnvScope * envScope,PandaGen * pg,LabelTarget target)56 LexEnvContext::LexEnvContext(LoopEnvScope *envScope, PandaGen *pg, LabelTarget target)
57     : DynamicContext(pg, target), envScope_(envScope)
58 {
59     if (!envScope_->HasEnv()) {
60         return;
61     }
62 
63     catchTable_ = pg_->CreateCatchTable();
64     const auto &labelSet = catchTable_->LabelSet();
65     const auto *node = envScope_->Scope()->Node();
66 
67     pg_->SetLabel(node, labelSet.TryBegin());
68 }
69 
~LexEnvContext()70 LexEnvContext::~LexEnvContext()
71 {
72     if (!envScope_->HasEnv()) {
73         return;
74     }
75 
76     const auto &labelSet = catchTable_->LabelSet();
77     const auto *node = envScope_->Scope()->Node();
78 
79     pg_->SetLabel(node, labelSet.TryEnd());
80     pg_->Branch(node, labelSet.CatchEnd());
81 
82     pg_->SetLabel(node, labelSet.CatchBegin());
83     pg_->PopLexEnv(node);
84     pg_->EmitThrow(node);
85     pg_->SetLabel(node, labelSet.CatchEnd());
86     pg_->PopLexEnv(node);
87 }
88 
HasTryCatch() const89 bool LexEnvContext::HasTryCatch() const
90 {
91     return envScope_->HasEnv();
92 }
93 
AbortContext(ControlFlowChange cfc,const util::StringView & targetLabel)94 void LexEnvContext::AbortContext([[maybe_unused]] ControlFlowChange cfc,
95                                  [[maybe_unused]] const util::StringView &targetLabel)
96 {
97     if (!envScope_->HasEnv()) {
98         return;
99     }
100 
101     const auto *node = envScope_->Scope()->Node();
102     if (node->IsForUpdateStatement() || node->IsDoWhileStatement()) {
103         return;
104     }
105 
106     pg_->PopLexEnv(node);
107 }
108 
IteratorContext(PandaGen * pg,const Iterator & iterator,LabelTarget target)109 IteratorContext::IteratorContext(PandaGen *pg, const Iterator &iterator, LabelTarget target)
110     : DynamicContext(pg, target), iterator_(iterator), catchTable_(pg->CreateCatchTable())
111 {
112     const auto &labelSet = catchTable_->LabelSet();
113     pg_->SetLabel(iterator_.Node(), labelSet.TryBegin());
114 }
115 
~IteratorContext()116 IteratorContext::~IteratorContext()
117 {
118     const auto &labelSet = catchTable_->LabelSet();
119     const auto *node = iterator_.Node();
120 
121     pg_->SetLabel(node, labelSet.TryEnd());
122     pg_->Branch(node, labelSet.CatchEnd());
123 
124     pg_->SetLabel(node, labelSet.CatchBegin());
125     iterator_.Close(true);
126     pg_->SetLabel(node, labelSet.CatchEnd());
127 }
128 
AbortContext(ControlFlowChange cfc,const util::StringView & targetLabel)129 void IteratorContext::AbortContext([[maybe_unused]] ControlFlowChange cfc,
130                                    [[maybe_unused]] const util::StringView &targetLabel)
131 {
132     if (cfc == ControlFlowChange::CONTINUE && target_.ContinueLabel() == targetLabel) {
133         return;
134     }
135 
136     iterator_.Close(false);
137 }
138 
DestructuringIteratorContext(PandaGen * pg,const DestructuringIterator & iterator)139 DestructuringIteratorContext::DestructuringIteratorContext(PandaGen *pg, const DestructuringIterator &iterator)
140     : DynamicContext(pg, {}), iterator_(iterator), catchTable_(pg->CreateCatchTable())
141 {
142     const auto &labelSet = catchTable_->LabelSet();
143     pg_->SetLabel(iterator_.Node(), labelSet.TryBegin());
144 }
145 
~DestructuringIteratorContext()146 DestructuringIteratorContext::~DestructuringIteratorContext()
147 {
148     const auto &labelSet = catchTable_->LabelSet();
149     const auto *node = iterator_.Node();
150 
151     pg_->SetLabel(node, labelSet.TryEnd());
152 
153     // Normal completion
154     pg_->LoadAccumulator(node, iterator_.Done());
155     pg_->BranchIfTrue(node, labelSet.CatchEnd());
156     iterator_.Close(false);
157 
158     pg_->Branch(node, labelSet.CatchEnd());
159 
160     Label *end = pg_->AllocLabel();
161     pg_->SetLabel(node, labelSet.CatchBegin());
162     pg_->StoreAccumulator(node, iterator_.Result());
163     pg_->LoadAccumulator(node, iterator_.Done());
164 
165     pg_->BranchIfTrue(node, end);
166     pg_->LoadAccumulator(node, iterator_.Result());
167     iterator_.Close(true);
168     pg_->SetLabel(node, end);
169     pg_->LoadAccumulator(node, iterator_.Result());
170     pg_->EmitThrow(node);
171     pg_->SetLabel(node, labelSet.CatchEnd());
172 }
173 
AbortContext(ControlFlowChange cfc,const util::StringView & targetLabel)174 void DestructuringIteratorContext::AbortContext(ControlFlowChange cfc, const util::StringView &targetLabel)
175 {
176     if (cfc == ControlFlowChange::CONTINUE && target_.ContinueLabel() == targetLabel) {
177         return;
178     }
179 
180     iterator_.Close(false);
181 }
182 
InitFinalizer()183 void TryContext::InitFinalizer()
184 {
185     ASSERT(tryStmt_);
186 
187     if (!hasFinalizer_ || !tryStmt_->FinallyBlock()) {
188         return;
189     }
190 
191     finalizerRun_ = pg_->AllocReg();
192     pg_->StoreConst(tryStmt_, finalizerRun_, Constant::JS_UNDEFINED);
193 }
194 
InitCatchTable()195 void TryContext::InitCatchTable()
196 {
197     catchTable_ = pg_->CreateCatchTable();
198 }
199 
LabelSet() const200 const TryLabelSet &TryContext::LabelSet() const
201 {
202     return catchTable_->LabelSet();
203 }
204 
HasFinalizer() const205 bool TryContext::HasFinalizer() const
206 {
207     return hasFinalizer_;
208 }
209 
EmitFinalizer()210 void TryContext::EmitFinalizer()
211 {
212     if (!hasFinalizer_ || inFinalizer_ || !tryStmt_->FinallyBlock()) {
213         return;
214     }
215 
216     inFinalizer_ = true;
217     tryStmt_->FinallyBlock()->Compile(pg_);
218     inFinalizer_ = false;
219 }
220 
AbortContext(ControlFlowChange cfc,const util::StringView & targetLabel)221 void TryContext::AbortContext([[maybe_unused]] ControlFlowChange cfc,
222                               [[maybe_unused]] const util::StringView &targetLabel)
223 {
224     EmitFinalizer();
225 }
226 }  // namespace panda::es2panda::compiler
227