• 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 #include "ecmascript/compiler/pass_manager.h"
16 #include "ecmascript/compiler/bytecodes.h"
17 #include "ecmascript/compiler/pass.h"
18 #include "ecmascript/compiler/compilation_driver.h"
19 #include "ecmascript/ecma_handle_scope.h"
20 #include "ecmascript/jspandafile/js_pandafile_manager.h"
21 #include "ecmascript/jspandafile/panda_file_translator.h"
22 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
23 #include "ecmascript/snapshot/mem/snapshot.h"
24 #include "ecmascript/ts_types/ts_manager.h"
25 
26 namespace panda::ecmascript::kungfu {
ShouldCollect() const27 bool PassManager::ShouldCollect() const
28 {
29     return passOptions_->EnableTypeInfer() &&
30         (profilerDecoder_.IsLoaded() || vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->AssertTypes() ||
31          log_->OutputType());
32 }
33 
Compile(JSPandaFile * jsPandaFile,const std::string & fileName,AOTFileGenerator & gen)34 bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName, AOTFileGenerator &gen)
35 {
36     [[maybe_unused]] EcmaHandleScope handleScope(vm_->GetJSThread());
37 
38     if (jsPandaFile == nullptr) {
39         LOG_COMPILER(ERROR) << "Cannot execute panda file '" << fileName << "'";
40         return false;
41     }
42 
43     if (!PGOProfilerManager::MergeApFiles(jsPandaFile->GetChecksum(), profilerDecoder_)) {
44         LOG_COMPILER(ERROR) << "Load and verify profiler failure";
45         return false;
46     }
47 
48     ResolveModule(jsPandaFile, fileName);
49     BytecodeInfoCollector collector(vm_, jsPandaFile, profilerDecoder_, maxAotMethodSize_, ShouldCollect());
50 
51     // Checking released/debuggable pandafile uses method literals, which are initialized in BytecodeInfoCollector,
52     // should after it.
53     if (!IsReleasedPandaFile(jsPandaFile)) {
54         LOG_COMPILER(ERROR) << "The input panda file [" << fileName
55                             << "] of AOT Compiler is debuggable version, do not use for performance test!";
56     }
57 
58     LOptions lOptions(optLevel_, FPFlag::RESERVE_FP, relocMode_);
59     CompilationDriver cmpDriver(profilerDecoder_,
60                                 &collector,
61                                 vm_->GetJSOptions().GetCompilerSelectMethods(),
62                                 vm_->GetJSOptions().GetCompilerSkipMethods(),
63                                 &gen,
64                                 fileName,
65                                 triple_,
66                                 &lOptions,
67                                 log_,
68                                 log_->OutputASM(),
69                                 maxMethodsInModule_);
70 
71     cmpDriver.Run([this, &fileName, &collector](const CString recordName,
72                                                 const std::string &methodName,
73                                                 MethodLiteral *methodLiteral,
74                                                 uint32_t methodOffset,
75                                                 const MethodPcInfo &methodPCInfo,
76                                                 MethodInfo &methodInfo,
77                                                 Module *m) {
78         PassContext ctx(triple_, log_, &collector, m->GetModule(), &profilerDecoder_);
79         auto jsPandaFile = ctx.GetJSPandaFile();
80         auto cmpCfg = ctx.GetCompilerConfig();
81         auto tsManager = ctx.GetTSManager();
82         auto module = m->GetModule();
83         // note: TSManager need to set current constantpool before all pass
84         tsManager->SetCurConstantPool(jsPandaFile, methodOffset);
85         log_->SetMethodLog(fileName, methodName, logList_);
86 
87         std::string fullName = module->GetFuncName(methodLiteral, jsPandaFile);
88         bool enableMethodLog = log_->GetEnableMethodLog();
89         if (enableMethodLog) {
90             LOG_COMPILER(INFO) << "\033[34m" << "aot method [" << fullName
91                                << "] recordName [" << recordName << "] log:" << "\033[0m";
92         }
93         bool hasTypes = jsPandaFile->HasTSTypes(recordName);
94         if (UNLIKELY(!hasTypes)) {
95             LOG_COMPILER(INFO) << "record: " << recordName << " has no types";
96         }
97 
98         Circuit circuit(vm_->GetNativeAreaAllocator(), ctx.GetAOTModule()->GetDebugInfo(),
99                         fullName.c_str(), cmpCfg->Is64Bit());
100         circuit.SetFrameType(FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
101 
102         PGOProfilerDecoder *decoder = passOptions_->EnableOptPGOType() ? &profilerDecoder_ : nullptr;
103 
104         BytecodeCircuitBuilder builder(jsPandaFile, methodLiteral, methodPCInfo, tsManager, &circuit,
105                                        ctx.GetByteCodes(), hasTypes, enableMethodLog && log_->OutputCIR(),
106                                        passOptions_->EnableTypeLowering(), fullName, recordName, decoder, false,
107                                        passOptions_->EnableOptTrackField());
108         {
109             TimeScope timeScope("BytecodeToCircuit", methodName, methodOffset, log_);
110             builder.BytecodeToCircuit();
111         }
112 
113         PassData data(&builder, &circuit, &ctx, log_, fullName, &methodInfo, hasTypes, recordName,
114                       methodLiteral, methodOffset, vm_->GetNativeAreaAllocator(), decoder, passOptions_);
115 
116         PassRunner<PassData> pipeline(&data);
117         if (builder.EnableLoopOptimization()) {
118             pipeline.RunPass<LoopOptimizationPass>();
119         }
120         pipeline.RunPass<TypeInferPass>();
121         if (data.IsTypeAbort()) {
122             data.AbortCompilation();
123             return;
124         }
125         pipeline.RunPass<PGOTypeInferPass>();
126         pipeline.RunPass<TSClassAnalysisPass>();
127         pipeline.RunPass<TSInlineLoweringPass>();
128         pipeline.RunPass<AsyncFunctionLoweringPass>();
129         pipeline.RunPass<TSHCRLoweringPass>();
130         pipeline.RunPass<NTypeHCRLoweringPass>();
131         if (data.IsTypeAbort()) {
132             data.AbortCompilation();
133             return;
134         }
135         pipeline.RunPass<EarlyEliminationPass>();
136         pipeline.RunPass<NumberSpeculativePass>();
137         pipeline.RunPass<LaterEliminationPass>();
138         pipeline.RunPass<ValueNumberingPass>();
139         pipeline.RunPass<StateSplitLinearizerPass>();
140         pipeline.RunPass<NTypeMCRLoweringPass>();
141         pipeline.RunPass<TypeMCRLoweringPass>();
142         pipeline.RunPass<LaterEliminationPass>();
143         pipeline.RunPass<EarlyEliminationPass>();
144         pipeline.RunPass<LCRLoweringPass>();
145         pipeline.RunPass<SlowPathLoweringPass>();
146         pipeline.RunPass<VerifierPass>();
147         pipeline.RunPass<GraphLinearizerPass>();
148         pipeline.RunPass<LLVMIRGenPass>();
149     });
150 
151     ProcessConstantPool(&collector);
152     return true;
153 }
154 
ProcessConstantPool(BytecodeInfoCollector * collector)155 void PassManager::ProcessConstantPool(BytecodeInfoCollector *collector)
156 {
157     LOG_COMPILER(INFO) << collector->GetBytecodeInfo().GetSkippedMethodSize()
158                        << " methods have been skipped";
159     vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->ProcessSnapshotConstantPool(collector);
160 }
161 
IsReleasedPandaFile(const JSPandaFile * jsPandaFile) const162 bool PassManager::IsReleasedPandaFile(const JSPandaFile *jsPandaFile) const
163 {
164     MethodLiteral* methodLiteral = jsPandaFile->GetMethodLiterals();
165     if (methodLiteral == nullptr) {
166         LOG_COMPILER(ERROR) << "There is no mehtod literal in " << jsPandaFile->GetJSPandaFileDesc();
167         return false;
168     }
169 
170     panda_file::File::EntityId methodId = methodLiteral->GetMethodId();
171     ASSERT(methodId.IsValid());
172     DebugInfoExtractor *debugInfoExtractor = JSPandaFileManager::GetInstance()->GetJSPtExtractor(jsPandaFile);
173     LocalVariableTable lvt = debugInfoExtractor->GetLocalVariableTable(methodId);
174     return lvt.empty();
175 }
176 
ResolveModule(const JSPandaFile * jsPandaFile,const std::string & fileName)177 void PassManager::ResolveModule(const JSPandaFile *jsPandaFile, const std::string &fileName)
178 {
179     const auto &recordInfo = jsPandaFile->GetJSRecordInfo();
180     JSThread *thread = vm_->GetJSThread();
181     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
182     [[maybe_unused]] EcmaHandleScope scope(thread);
183     for (auto info: recordInfo) {
184         if (jsPandaFile->IsModule(info.second)) {
185             auto recordName = info.first;
186             JSHandle<JSTaggedValue> moduleRecord = moduleManager->HostResolveImportedModuleWithMerge(fileName.c_str(),
187                 recordName);
188             SourceTextModule::Instantiate(thread, moduleRecord);
189         }
190     }
191 }
192 } // namespace panda::ecmascript::kungfu
193