• 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 #ifndef ECMASCRIPT_COMPILER_PASS_H
17 #define ECMASCRIPT_COMPILER_PASS_H
18 
19 #include "ecmascript/compiler/aot_compilation_env.h"
20 #include "ecmascript/compiler/jit_compilation_env.h"
21 #include "ecmascript/compiler/async_function_lowering.h"
22 #include "ecmascript/compiler/bytecode_circuit_builder.h"
23 #include "ecmascript/compiler/codegen/llvm/llvm_codegen.h"
24 #include "ecmascript/compiler/combined_pass_visitor.h"
25 #include "ecmascript/compiler/compiler_log.h"
26 #include "ecmascript/compiler/constant_folding.h"
27 #include "ecmascript/compiler/dead_code_elimination.h"
28 #include "ecmascript/compiler/early_elimination.h"
29 #include "ecmascript/compiler/escape_analysis.h"
30 #include "ecmascript/compiler/escape_analysis_editor.h"
31 #include "ecmascript/compiler/graph_editor.h"
32 #include "ecmascript/compiler/graph_linearizer.h"
33 #include "ecmascript/compiler/induction_variable_analysis.h"
34 #include "ecmascript/compiler/later_elimination.h"
35 #include "ecmascript/compiler/mcr_lowering.h"
36 #include "ecmascript/compiler/lexical_env_specialization_pass.h"
37 #include "ecmascript/compiler/loop_analysis.h"
38 #include "ecmascript/compiler/loop_peeling.h"
39 #include "ecmascript/compiler/native_inline_lowering.h"
40 #include "ecmascript/compiler/ntype_bytecode_lowering.h"
41 #include "ecmascript/compiler/ntype_hcr_lowering.h"
42 #include "ecmascript/compiler/number_speculative_runner.h"
43 #include "ecmascript/compiler/post_schedule.h"
44 #include "ecmascript/compiler/precompile_checker.h"
45 #include "ecmascript/compiler/scheduler.h"
46 #include "ecmascript/compiler/string_builder_optimizer.h"
47 #include "ecmascript/compiler/slowpath_lowering.h"
48 #include "ecmascript/compiler/state_split_linearizer.h"
49 #include "ecmascript/compiler/ts_inline_lowering.h"
50 #include "ecmascript/compiler/typed_bytecode_lowering.h"
51 #include "ecmascript/compiler/ts_hcr_opt_pass.h"
52 #include "ecmascript/compiler/type_inference/pgo_type_infer.h"
53 #include "ecmascript/compiler/typed_hcr_lowering.h"
54 #include "ecmascript/compiler/typed_native_inline_lowering.h"
55 #include "ecmascript/compiler/useless_gate_elimination.h"
56 #include "ecmascript/compiler/value_numbering.h"
57 #include "ecmascript/compiler/instruction_combine.h"
58 #include "ecmascript/compiler/verifier.h"
59 #include "ecmascript/js_runtime_options.h"
60 
61 #ifdef COMPILE_MAPLE
62 #include "ecmascript/compiler/codegen/maple/litecg_codegen.h"
63 #include "litecg.h"
64 #include "lmir_builder.h"
65 #endif
66 
67 namespace panda::ecmascript::kungfu {
68 class PassContext;
69 
70 class PassData {
71 public:
72     PassData(BytecodeCircuitBuilder *builder, Circuit *circuit, PassContext *ctx, CompilerLog *log,
73              std::string methodName, MethodInfo *methodInfo = nullptr,
74              const CString &recordName = "", MethodLiteral *methodLiteral = nullptr,
75              uint32_t methodOffset = 0, CallMethodFlagMap *callMethodFlagMap = nullptr,
76              const CVector<AbcFileInfo> &fileInfos = CVector<AbcFileInfo>{}, NativeAreaAllocator *allocator = nullptr,
77              PGOProfilerDecoder *decoder = nullptr, PassOptions *passOptions = nullptr,
78              std::string optBCRange = "")
builder_(builder)79         : builder_(builder), circuit_(circuit), ctx_(ctx), log_(log), methodName_(methodName),
80           methodInfo_(methodInfo), recordName_(recordName), methodLiteral_(methodLiteral),
81           methodOffset_(methodOffset), callMethodFlagMap_(callMethodFlagMap), fileInfos_(fileInfos),
82           allocator_(allocator), decoder_(decoder), passOptions_(passOptions),
83           optBCRange_(optBCRange)
84     {
85     }
86 
87     virtual ~PassData() = default;
88 
GetConstScheduleResult()89     const ControlFlowGraph &GetConstScheduleResult() const
90     {
91         return cfg_;
92     }
93 
GetCfg()94     ControlFlowGraph &GetCfg()
95     {
96         return cfg_;
97     }
98 
GetCircuit()99     virtual Circuit* GetCircuit() const
100     {
101         return circuit_;
102     }
103 
GetBuilder()104     BytecodeCircuitBuilder* GetBuilder() const
105     {
106         return builder_;
107     }
108 
GetPassContext()109     PassContext* GetPassContext() const
110     {
111         return ctx_;
112     }
113 
GetCompilerConfig()114     CompilationConfig* GetCompilerConfig() const
115     {
116         return ctx_->GetCompilerConfig();
117     }
118 
GetPTManager()119     PGOTypeManager* GetPTManager() const
120     {
121         return ctx_->GetPTManager();
122     }
123 
GetJSPandaFile()124     const JSPandaFile *GetJSPandaFile() const
125     {
126         return ctx_->GetJSPandaFile();
127     }
128 
GetAotModule()129     IRModule* GetAotModule() const
130     {
131         return ctx_->GetAOTModule();
132     }
133 
GetLog()134     CompilerLog* GetLog() const
135     {
136         return log_;
137     }
138 
GetMethodName()139     const std::string& GetMethodName() const
140     {
141         return methodName_;
142     }
143 
GetMethodLiteral()144     const MethodLiteral* GetMethodLiteral() const
145     {
146         return methodLiteral_;
147     }
148 
GetMethodOffset()149     uint32_t GetMethodOffset() const
150     {
151         return methodOffset_;
152     }
153 
GetMethodInfo()154     MethodInfo* GetMethodInfo() const
155     {
156         return methodInfo_;
157     }
158 
GetMethodInfoIndex()159     size_t GetMethodInfoIndex() const
160     {
161         return methodInfo_->GetMethodInfoIndex();
162     }
163 
GetRecordName()164     const CString &GetRecordName() const
165     {
166         return recordName_;
167     }
168 
GetNativeAreaAllocator()169     NativeAreaAllocator* GetNativeAreaAllocator() const
170     {
171         return allocator_;
172     }
173 
GetPGOProfilerDecoder()174     PGOProfilerDecoder *GetPGOProfilerDecoder() const
175     {
176         return decoder_;
177     }
178 
GetPassOptions()179     PassOptions *GetPassOptions() const
180     {
181         return passOptions_;
182     }
183 
GetOptBCRange()184     std::string GetOptBCRange() const
185     {
186         return optBCRange_;
187     }
188 
GetCallMethodFlagMap()189     CallMethodFlagMap *GetCallMethodFlagMap()
190     {
191         return callMethodFlagMap_;
192     }
193 
GetFileInfos()194     const CVector<AbcFileInfo> &GetFileInfos() const
195     {
196         return fileInfos_;
197     }
198 
AbortCompilation()199     void AbortCompilation()
200     {
201         ctx_->GetBytecodeInfo().AddSkippedMethod(methodOffset_);
202         methodInfo_->SetIsCompiled(false);
203     }
204 
205 private:
206     BytecodeCircuitBuilder *builder_ {nullptr};
207     Circuit *circuit_ {nullptr};
208     ControlFlowGraph cfg_;
209     PassContext *ctx_ {nullptr};
210     CompilerLog *log_ {nullptr};
211     std::string methodName_;
212     MethodInfo *methodInfo_ {nullptr};
213     const CString &recordName_;
214     MethodLiteral *methodLiteral_ {nullptr};
215     uint32_t methodOffset_;
216     CallMethodFlagMap *callMethodFlagMap_ {nullptr};
217     const CVector<AbcFileInfo> &fileInfos_;
218     NativeAreaAllocator *allocator_ {nullptr};
219     PGOProfilerDecoder *decoder_ {nullptr};
220     PassOptions *passOptions_ {nullptr};
221     std::string optBCRange_;
222 };
223 
224 template<typename T1>
225 class PassRunner {
226 public:
PassRunner(T1 * data)227     explicit PassRunner(T1* data) : data_(data) {}
228     virtual ~PassRunner() = default;
229     template<typename T2, typename... Args>
RunPass(Args...args)230     bool RunPass(Args... args)
231     {
232         T2 pass;
233         return pass.Run(data_, std::forward<Args>(args)...);
234     }
235 
236 private:
237     T1* data_;
238 };
239 
240 class PreCompileCheckPass {
241 public:
Run(PassData * data)242     bool Run(PassData* data)
243     {
244         TimeScope timescope("PreCompileCheckPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
245         bool enableLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType();
246         PreCompileChecker preCompileChecker(data, data->GetCircuit(), data->GetMethodName(), enableLog);
247         if (!preCompileChecker.Run()) {
248             data->AbortCompilation();
249             return false;
250         }
251         return true;
252     }
253 };
254 
255 class PGOTypeInferPass {
256 public:
Run(PassData * data)257     bool Run(PassData* data)
258     {
259         TimeScope timescope("PGOTypeInferPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
260         bool enableLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType();
261         Chunk chunk(data->GetNativeAreaAllocator());
262         PGOTypeInfer pgoTypeInfer(data->GetCircuit(), data->GetBuilder(), data->GetMethodName(), &chunk, enableLog);
263         pgoTypeInfer.Run();
264         return true;
265     }
266 };
267 
268 class EscapeAnalysisPass {
269 public:
Run(PassData * data)270     bool Run(PassData *data)
271     {
272         PassOptions *passOptions = data->GetPassOptions();
273         if (!passOptions->EnableEscapeAnalysis()) {
274             return false;
275         }
276         TimeScope timescope("EscapeAnalysisPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
277         bool enableLog = data->GetLog()->EnableMethodCIRLog();
278         JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions();
279         Chunk chunk(data->GetNativeAreaAllocator());
280         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
281         EscapeAnalysis escapeAnalysis(data->GetCircuit(), &visitor, &chunk, runtimeOption.GetTraceEscapeAnalysis());
282         visitor.AddPass(&escapeAnalysis);
283         visitor.VisitGraph();
284         CombinedPassVisitor Editvisitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
285         EscapeAnalysisEditor escapeAnalysisEditor(data->GetCircuit(), &visitor, &chunk,
286                                                   &escapeAnalysis, runtimeOption.GetTraceEscapeAnalysis());
287         Editvisitor.AddPass(&escapeAnalysisEditor);
288         Editvisitor.VisitGraph();
289         visitor.PrintLog("escape Analysis");
290         return true;
291     }
292 };
293 
294 class InductionVariableAnalysisPass {
295 public:
Run(PassData * data)296     bool Run(PassData *data)
297     {
298         PassOptions *passOptions = data->GetPassOptions();
299         if (!passOptions->EnableInductionVariableAnalysis()) {
300             return false;
301         }
302         TimeScope timescope("InductionVariableAnalysisPass", data->GetMethodName(),
303                             data->GetMethodOffset(), data->GetLog());
304         bool enableLog = data->GetLog()->EnableMethodCIRLog();
305         JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions();
306         Chunk chunk(data->GetNativeAreaAllocator());
307         InductionVariableAnalysis inductionVariableAnalysis(data->GetCircuit(), data->GetPassContext(), enableLog,
308                                                             data->GetMethodName(), &chunk,
309                                                             runtimeOption.GetTraceInductionVariableAnalysis());
310         inductionVariableAnalysis.Run();
311         return true;
312     }
313 };
314 
315 class TypeBytecodeLoweringPass {
316 public:
Run(PassData * data)317     bool Run(PassData* data)
318     {
319         PassOptions *passOptions = data->GetPassOptions();
320         if (!passOptions->EnableTypeLowering()) {
321             return false;
322         }
323         TimeScope timescope("TypeBytecodeLoweringPass", data->GetMethodName(),
324             data->GetMethodOffset(), data->GetLog());
325         bool enableLog = data->GetLog()->EnableMethodCIRLog();
326         bool enableTypeLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType();
327         Chunk chunk(data->GetNativeAreaAllocator());
328         TypedBytecodeLowering lowering(data->GetCircuit(), data->GetPassContext(), &chunk,
329                                       enableLog,
330                                       enableTypeLog,
331                                       data->GetMethodName(),
332                                       passOptions->EnableLoweringBuiltin(),
333                                       passOptions->EnableMergePoly(),
334                                       passOptions->EnableLazyDeopt(),
335                                       data->GetRecordName(),
336                                       data->GetCallMethodFlagMap(),
337                                       data->GetPGOProfilerDecoder(),
338                                       data->GetOptBCRange(),
339                                       data->GetMethodLiteral());
340         lowering.RunTypedBytecodeLowering();
341         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
342         DeadCodeElimination deadCodeElimination(data->GetCircuit(), &visitor, &chunk);
343         TSHCROptPass optimization(data->GetCircuit(), &visitor, &chunk, data->GetPassContext(), enableLog,
344                                   data->GetMethodName());
345 
346         visitor.AddPass(&optimization);
347         visitor.AddPass(&deadCodeElimination);
348         visitor.VisitGraph();
349         visitor.PrintLog("TSHCROptPass");
350         return true;
351     }
352 };
353 
354 class NTypeBytecodeLoweringPass {
355 public:
Run(PassData * data)356     bool Run(PassData* data)
357     {
358         PassOptions *passOptions = data->GetPassOptions();
359         if (!passOptions->EnableTypeLowering()) {
360             return false;
361         }
362         TimeScope timescope("NTypeBytecodeLoweringPass", data->GetMethodName(),
363             data->GetMethodOffset(), data->GetLog());
364         bool enableLog = data->GetLog()->EnableMethodCIRLog();
365         NTypeBytecodeLowering lowering(data->GetCircuit(), data->GetPassContext(), enableLog,
366                                        passOptions->EnableLazyDeopt(), data->GetMethodName(), data->GetRecordName());
367         lowering.RunNTypeBytecodeLowering();
368         Chunk chunk(data->GetNativeAreaAllocator());
369         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
370         DeadCodeElimination deadCodeElimination(data->GetCircuit(), &visitor, &chunk);
371         visitor.AddPass(&deadCodeElimination);
372         visitor.VisitGraph();
373         return true;
374     }
375 };
376 
377 class StringOptimizationPass {
378 public:
Run(PassData * data)379     bool Run(PassData* data)
380     {
381         PassOptions *passOptions = data->GetPassOptions();
382         if (!passOptions->EnableOptString()) {
383             return false;
384         }
385         TimeScope timescope("StringOptimizationPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
386         bool enableLog = data->GetLog()->EnableMethodCIRLog();
387         Chunk chunk(data->GetNativeAreaAllocator());
388         StringBuilderOptimizer stringBuilder(data->GetCircuit(),
389                                              enableLog,
390                                              data->GetMethodName(),
391                                              data->GetCompilerConfig(),
392                                              &chunk);
393         stringBuilder.Run();
394         return true;
395     }
396 };
397 
398 class TypeHCRLoweringPass {
399 public:
Run(PassData * data)400     bool Run(PassData* data)
401     {
402         PassOptions *passOptions = data->GetPassOptions();
403         if (!passOptions->EnableTypeLowering()) {
404             return false;
405         }
406         {
407             TimeScope timescope("TypeHCRLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
408             bool enableLog = data->GetLog()->EnableMethodCIRLog();
409             Chunk chunk(data->GetNativeAreaAllocator());
410             CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
411             TypedHCRLowering lowering(data->GetCircuit(),
412                                     data->GetPassContext()->GetCompilationEnv(),
413                                     &visitor,
414                                     data->GetCompilerConfig(),
415                                     &chunk,
416                                     passOptions->EnableLoweringBuiltin());
417             visitor.AddPass(&lowering);
418             visitor.VisitGraph();
419             visitor.PrintLog("TypedHCRLowering");
420         }
421 
422         {
423             TimeScope timescope("TypedNativeInlineLoweringPass", data->GetMethodName(), data->GetMethodOffset(),
424                                 data->GetLog());
425             bool enableLog = data->GetLog()->EnableMethodCIRLog();
426             Chunk chunk(data->GetNativeAreaAllocator());
427             CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
428             TypedNativeInlineLowering lowering(data->GetCircuit(),
429                                                &visitor,
430                                                data->GetPassContext(),
431                                                data->GetCompilerConfig(),
432                                                &chunk);
433             visitor.AddPass(&lowering);
434             visitor.VisitGraph();
435             visitor.PrintLog("TypedNativeInlineLowering");
436         }
437 
438         return true;
439     }
440 };
441 
442 class NTypeHCRLoweringPass {
443 public:
Run(PassData * data)444     bool Run(PassData* data)
445     {
446         PassOptions *passOptions = data->GetPassOptions();
447         if (!passOptions->EnableTypeLowering()) {
448             return false;
449         }
450         TimeScope timescope("NTypeHCRLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
451         bool enableLog = data->GetLog()->EnableMethodCIRLog();
452         Chunk chunk(data->GetNativeAreaAllocator());
453         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
454         JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions();
455         NTypeHCRLowering lowering(data->GetCircuit(), &visitor, data->GetPassContext(),
456             data->GetRecordName(), data->GetMethodLiteral(), runtimeOption.IsCompilerEnablePgoSpace(), &chunk);
457         visitor.AddPass(&lowering);
458         visitor.VisitGraph();
459         visitor.PrintLog("NTypeHCRLowering");
460         return true;
461     }
462 };
463 
464 class LCRLoweringPass {
465 public:
Run(PassData * data)466     bool Run(PassData* data)
467     {
468         PassOptions *passOptions = data->GetPassOptions();
469         if (!passOptions->EnableTypeLowering()) {
470             return false;
471         }
472         TimeScope timescope("LCRLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
473         bool enableLog = data->GetLog()->EnableMethodCIRLog();
474         Chunk chunk(data->GetNativeAreaAllocator());
475         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
476         MCRLowering lowering(data->GetPassContext()->GetCompilationEnv(), data->GetCircuit(), &visitor,
477                              data->GetCompilerConfig(), &chunk);
478         visitor.AddPass(&lowering);
479         visitor.VisitGraph();
480         visitor.PrintLog("MCRLowering");
481         return true;
482     }
483 };
484 
485 class TSInlineLoweringPass {
486 public:
Run(PassData * data)487     bool Run(PassData* data)
488     {
489         PassOptions *passOptions = data->GetPassOptions();
490         if (!passOptions->EnableOptInlining() || !passOptions->EnableTypeLowering()) {
491             return false;
492         }
493         TimeScope timescope("TSInlineLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
494         bool enableLog = data->GetLog()->EnableMethodCIRLog();
495         TSInlineLowering inlining(data->GetCircuit(), data->GetPassContext(), enableLog, data->GetMethodName(),
496                                   data->GetNativeAreaAllocator(), passOptions, data->GetMethodOffset(),
497                                   data->GetCallMethodFlagMap());
498         inlining.RunTSInlineLowering();
499         Chunk chunk(data->GetNativeAreaAllocator());
500         if (passOptions->EnableLexenvSpecialization()) {
501             {
502                 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
503                 GetEnvSpecializationPass getEnvSpecializationPass(data->GetCircuit(), &visitor, &chunk);
504                 visitor.AddPass(&getEnvSpecializationPass);
505                 visitor.VisitGraph();
506                 visitor.PrintLog("getEnvSpecializationPass");
507             }
508             {
509                 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
510                 LexicalEnvSpecializationPass lexicalEnvSpecializationPass(data->GetCircuit(), &visitor, &chunk,
511                                                                           enableLog);
512                 visitor.AddPass(&lexicalEnvSpecializationPass);
513                 visitor.VisitGraph();
514                 visitor.PrintLog("lexicalEnvSpecialization");
515                 lexicalEnvSpecializationPass.PrintSpecializeId();
516             }
517         }
518 
519         if (passOptions->EnableInlineNative()) {
520             NativeInlineLowering nativeInline(data->GetCircuit(), data->GetCompilerConfig(), data->GetPassContext(),
521                                               enableLog, data->GetMethodName(), &chunk);
522             nativeInline.RunNativeInlineLowering();
523             CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
524             DeadCodeElimination deadCodeElimination(data->GetCircuit(), &visitor, &chunk);
525             TSHCROptPass optimization(data->GetCircuit(), &visitor, &chunk, data->GetPassContext(), enableLog,
526                                     data->GetMethodName());
527 
528             visitor.AddPass(&optimization);
529             visitor.AddPass(&deadCodeElimination);
530             visitor.VisitGraph();
531             visitor.PrintLog("TSHCROptPass");
532         }
533         return true;
534     }
535 };
536 
537 class SlowPathLoweringPass {
538 public:
Run(PassData * data)539     bool Run(PassData* data)
540     {
541         TimeScope timescope("SlowPathLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
542         bool enableLog = data->GetLog()->EnableMethodCIRLog();
543         SlowPathLowering lowering(data->GetCircuit(), data->GetCompilerConfig(), data->GetPassContext(),
544                                   data->GetMethodLiteral(), enableLog, data->GetMethodName(), data->GetRecordName());
545         lowering.CallRuntimeLowering();
546         return true;
547     }
548 };
549 
550 class RunFlowCyclesVerifierPass {
551 public:
Run(PassData * data)552     bool Run(PassData* data)
553     {
554         TimeScope timescope("FlowCyclesVerifierPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
555         bool hasFlowCycle = Verifier::RunFlowCyclesFind(data->GetCircuit());
556         if (hasFlowCycle) {
557             LOG_FULL(FATAL) << "FlowCyclesVerifierPass fail";
558             UNREACHABLE();
559         }
560         return !hasFlowCycle;
561     }
562 };
563 
564 class VerifierPass {
565 public:
Run(PassData * data)566     bool Run(PassData* data)
567     {
568         TimeScope timescope("VerifierPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
569         bool enableLog = data->GetLog()->EnableMethodCIRLog();
570         bool isQualified = Verifier::Run(data->GetCircuit(), data->GetMethodName(), enableLog);
571         if (!isQualified) {
572             LOG_FULL(FATAL) << "VerifierPass fail";
573             UNREACHABLE();
574         }
575         return isQualified;
576     }
577 };
578 
579 class NumberSpeculativePass {
580 public:
Run(PassData * data)581     bool Run(PassData* data)
582     {
583         PassOptions *passOptions = data->GetPassOptions();
584         if (!passOptions->EnableTypeLowering()) {
585             return false;
586         }
587         TimeScope timescope("NumberSpeculativePass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
588         Chunk chunk(data->GetNativeAreaAllocator());
589         bool enableLog = data->GetLog()->EnableMethodCIRLog();
590         bool enableArrayBoundsCheckElimination = passOptions->EnableArrayBoundsCheckElimination();
591         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
592         NumberSpeculativeRunner(data->GetCircuit(), data->GetCompilerConfig(), enableLog,
593                                 enableArrayBoundsCheckElimination, data->GetMethodName(), &chunk).Run();
594         return true;
595     }
596 };
597 
598 class ConstantFoldingPass {
599 public:
Run(PassData * data)600     bool Run(PassData* data)
601     {
602         PassOptions *passOptions = data->GetPassOptions();
603         if (!passOptions->EnableOptConstantFolding()) {
604             return false;
605         }
606         TimeScope timescope("ConstantFoldingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
607         Chunk chunk(data->GetNativeAreaAllocator());
608         bool enableLog = data->GetLog()->EnableMethodCIRLog();
609         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
610         ConstantFolding constantFolding(data->GetCircuit(), &visitor, data->GetCompilerConfig(), enableLog,
611                                         data->GetMethodName(), &chunk);
612         visitor.AddPass(&constantFolding);
613         visitor.VisitGraph();
614         constantFolding.Print();
615         return true;
616     }
617 };
618 
619 class LoopOptimizationPass {
620 public:
Run(PassData * data)621     bool Run(PassData* data)
622     {
623         TimeScope timescope("LoopOptimizationPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
624         Chunk chunk(data->GetNativeAreaAllocator());
625         LoopAnalysis loopAnalysis(data->GetBuilder(), data->GetCircuit(), &chunk);
626         loopAnalysis.Run();
627         bool enableLog = data->GetLog()->EnableMethodCIRLog();
628         for (auto loopInfo : loopAnalysis.GetLoopTree()) {
629             loopAnalysis.CollectLoopBody(loopInfo);
630             if (enableLog) {
631                 loopAnalysis.PrintLoop(loopInfo);
632             }
633             if (data->GetPassOptions()->EnableOptLoopPeeling()) {
634                 LoopPeeling(data->GetBuilder(), data->GetCircuit(), enableLog,
635                             data->GetMethodName(), &chunk, loopInfo).Peel();
636             }
637         }
638         loopAnalysis.LoopExitElimination();
639         return true;
640     }
641 };
642 
643 class RedundantPhiEliminationPass {
644 public:
Run(PassData * data)645     bool Run(PassData* data)
646     {
647         TimeScope timescope("RedundantPhiEliminationPass", data->GetMethodName(),
648             data->GetMethodOffset(), data->GetLog());
649         bool enableLog = data->GetLog()->EnableMethodCIRLog();
650         GraphEditor::EliminateRedundantPhi(data->GetCircuit(), enableLog, data->GetMethodName());
651         return true;
652     }
653 };
654 
655 class EarlyEliminationPass {
656 public:
Run(PassData * data)657     bool Run(PassData* data)
658     {
659         PassOptions *passOptions = data->GetPassOptions();
660         if (!passOptions->EnableTypeLowering() || !passOptions->EnableEarlyElimination()) {
661             return false;
662         }
663         TimeScope timescope("EarlyEliminationPass", data->GetMethodName(),
664                             data->GetMethodOffset(), data->GetLog());
665         bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog();
666         Chunk chunk(data->GetNativeAreaAllocator());
667         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
668         JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions();
669         EarlyElimination earlyElimination(data->GetCircuit(), &visitor, &chunk,
670             runtimeOption.IsEnableMemoryAnalysis(), runtimeOption.IsEnableFrameStateElimination());
671         visitor.AddPass(&earlyElimination);
672         visitor.VisitGraph();
673         visitor.PrintLog("early elimination");
674         return true;
675     }
676 };
677 
678 class LaterEliminationPass {
679 public:
Run(PassData * data)680     bool Run(PassData* data)
681     {
682         PassOptions *passOptions = data->GetPassOptions();
683         if (!passOptions->EnableTypeLowering() || !passOptions->EnableLaterElimination()) {
684             return false;
685         }
686         TimeScope timescope("LaterEliminationPass", data->GetMethodName(),
687                             data->GetMethodOffset(), data->GetLog());
688         bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog();
689         Chunk chunk(data->GetNativeAreaAllocator());
690         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
691         LaterElimination laterElimination(data->GetCircuit(), &visitor, &chunk);
692         visitor.AddPass(&laterElimination);
693         visitor.VisitGraph();
694         visitor.PrintLog("later elimination");
695         return true;
696     }
697 };
698 
699 class UselessGateEliminationPass {
700 public:
Run(PassData * data)701     bool Run(PassData* data)
702     {
703         TimeScope timescope("UselessGateEliminationPass", data->GetMethodName(),
704                             data->GetMethodOffset(), data->GetLog());
705         bool enableLog = data->GetLog()->EnableMethodCIRLog();
706         UselessGateElimination uselessGateElimination(data->GetCircuit(), enableLog, data->GetMethodName());
707         uselessGateElimination.Run();
708         return true;
709     }
710 };
711 
712 class ValueNumberingPass {
713 public:
Run(PassData * data)714     bool Run(PassData* data)
715     {
716         PassOptions *passOptions = data->GetPassOptions();
717         if (!passOptions->EnableTypeLowering() || !passOptions->EnableValueNumbering()) {
718             return false;
719         }
720         JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions();
721         TimeScope timescope("ValueNumberingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
722         Chunk chunk(data->GetNativeAreaAllocator());
723         bool enableLog = data->GetLog()->EnableMethodCIRLog();
724         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
725         ValueNumbering valueNumbering(data->GetCircuit(), &visitor, &chunk,
726                                       runtimeOption.IsEnableNewValueNumbering(),
727                                       runtimeOption.GetTraceValueNumbering());
728         visitor.AddPass(&valueNumbering);
729         visitor.VisitGraph();
730         visitor.PrintLog("value numbering");
731         return true;
732     }
733 };
734 
735 class InstructionCombinePass {
736 public:
Run(PassData * data)737     bool Run(PassData *data)
738     {
739         JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions();
740         if (runtimeOption.IsEnableInstrcutionCombine()) {
741             TimeScope timescope("InstructionCombinePass", data->GetMethodName(), data->GetMethodOffset(),
742                                 data->GetLog());
743             Chunk chunk(data->GetNativeAreaAllocator());
744             bool enableLog = data->GetLog()->EnableMethodCIRLog();
745             CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
746             InstructionCombine instructionCombine(data->GetCircuit(), &visitor, &chunk,
747                                                   runtimeOption.GetTraceInstructionCombine());
748             visitor.AddPass(&instructionCombine);
749             visitor.VisitGraph();
750             visitor.PrintLog("Instruction Combine");
751         }
752         return true;
753     }
754 };
755 
756 class SchedulingPass {
757 public:
Run(PassData * data,bool isStwCopyStub)758     bool Run(PassData* data, bool isStwCopyStub)
759     {
760         TimeScope timescope("SchedulingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
761         bool enableLog = data->GetLog()->EnableMethodCIRLog();
762         Scheduler::Run(data->GetCircuit(), data->GetCfg(), data->GetMethodName(), enableLog);
763         Chunk chunk(data->GetNativeAreaAllocator());
764         CompilationEnv *env = nullptr;
765         if (data->GetPassContext() != nullptr) {
766             env = data->GetPassContext()->GetCompilationEnv();
767         }
768         if (isStwCopyStub) {
769 #if ENABLE_NEXT_OPTIMIZATION
770             PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, env, true, isStwCopyStub)
771                 .Run(data->GetCfg());
772 #else
773             PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, env, false, isStwCopyStub)
774                 .Run(data->GetCfg());
775 #endif
776         } else {
777             PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, env, false, isStwCopyStub)
778                 .Run(data->GetCfg());
779         }
780         return true;
781     }
782 };
783 
784 class StateSplitLinearizerPass {
785 public:
Run(PassData * data)786     bool Run(PassData* data)
787     {
788         PassOptions *passOptions = data->GetPassOptions();
789         if (!passOptions->EnableTypeLowering()) {
790             return false;
791         }
792         TimeScope timescope("StateSplitLinearizerPass", data->GetMethodName(),
793                             data->GetMethodOffset(), data->GetLog());
794         Chunk chunk(data->GetNativeAreaAllocator());
795         bool enableLog = data->GetLog()->EnableMethodCIRLog();
796         StateSplitLinearizer(data->GetPassContext()->GetCompilationEnv(), data->GetCircuit(), nullptr,
797                              data->GetCompilerConfig(), enableLog, data->GetMethodName(), &chunk)
798             .Run();
799         return true;
800     }
801 };
802 
803 class GraphLinearizerPass {
804 public:
Run(PassData * data,bool isStwCopyStub)805     bool Run(PassData* data, bool isStwCopyStub)
806     {
807         TimeScope timescope("GraphLinearizerPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
808         Chunk chunk(data->GetNativeAreaAllocator());
809         bool enableLog = data->GetLog()->EnableMethodCIRLog();
810         bool licm = data->GetPassOptions()->EnableOptLoopInvariantCodeMotion();
811         bool liteCG = data->GetPassContext()->GetCompilationEnv()->GetJSOptions().IsCompilerEnableLiteCG();
812         bool enableStoreBarrier = data->GetPassContext()->GetCompilationEnv()->GetJSOptions().IsStoreBarrierOpt();
813         GraphLinearizer(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, false, licm, liteCG)
814             .Run(data->GetCfg());
815         PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk,
816                      data->GetPassContext()->GetCompilationEnv(), enableStoreBarrier, isStwCopyStub)
817                      .Run(data->GetCfg());
818         return true;
819     }
820 };
821 
822 class CGIRGenPass {
823 public:
CreateCodeGen(IRModule * module,bool enableLog)824     void CreateCodeGen(IRModule *module, bool enableLog)
825     {
826 #ifdef COMPILE_MAPLE
827         if (module->GetModuleKind() == MODULE_LLVM) {
828             cgImpl_ = std::make_unique<LLVMIRGeneratorImpl>(static_cast<LLVMModule*>(module), enableLog);
829         } else {
830             cgImpl_ = std::make_unique<LiteCGIRGeneratorImpl>(static_cast<LMIRModule*>(module), enableLog);
831         }
832 #else
833         cgImpl_ = std::make_unique<LLVMIRGeneratorImpl>(static_cast<LLVMModule*>(module), enableLog);
834 #endif
835     }
Run(PassData * data)836     bool Run(PassData *data)
837     {
838         auto module = data->GetAotModule();
839         TimeScope timescope("CGIRGenPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
840         bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog();
841         PassOptions *passOptions = data->GetPassOptions();
842         bool enableOptInlining = passOptions->EnableOptInlining() && passOptions->EnableTypeLowering();
843         bool enableOptBranchProfiling = passOptions->EnableOptBranchProfiling();
844         CreateCodeGen(module, enableLog);
845         CodeGenerator codegen(cgImpl_, data->GetMethodName());
846         codegen.Run(data->GetCircuit(), data->GetConstScheduleResult(), data->GetCompilerConfig(),
847                     data->GetMethodLiteral(), data->GetJSPandaFile(), data->GetCircuit()->GetFrameType(),
848                     enableOptInlining, enableOptBranchProfiling);
849         return true;
850     }
851 private:
852     std::unique_ptr<CodeGeneratorImpl> cgImpl_ {nullptr};
853 };
854 
855 class AsyncFunctionLoweringPass {
856 public:
Run(PassData * data)857     bool Run(PassData* data)
858     {
859         TimeScope timescope("AsyncFunctionLoweringPass", data->GetMethodName(),
860                             data->GetMethodOffset(), data->GetLog());
861         bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog();
862         AsyncFunctionLowering lowering(data->GetBuilder(), data->GetCircuit(), data->GetCompilerConfig(),
863                                        enableLog, data->GetMethodName());
864         if (lowering.IsAsyncRelated()) {
865             lowering.ProcessAll();
866         }
867         return true;
868     }
869 
870 private:
IsFunctionMain(PassData * data)871     bool IsFunctionMain(PassData* data)
872     {
873         auto methodName = data->GetMethodName();
874         auto pos = methodName.find(JSPandaFile::ENTRY_FUNCTION_NAME);
875         if (pos != std::string::npos) {
876             return true;
877         }
878         return false;
879     }
880 };
881 } // namespace panda::ecmascript::kungfu
882 #endif
883