• 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 
17 #include "ecmascript/compiler/bytecode_info_collector.h"
18 #include "ecmascript/compiler/bytecodes.h"
19 #include "ecmascript/compiler/pass.h"
20 #include "ecmascript/compiler/compilation_driver.h"
21 #include "ecmascript/ecma_handle_scope.h"
22 #include "ecmascript/jspandafile/js_pandafile_manager.h"
23 #include "ecmascript/jspandafile/panda_file_translator.h"
24 #include "ecmascript/snapshot/mem/snapshot.h"
25 #include "ecmascript/ts_types/ts_manager.h"
26 
27 namespace panda::ecmascript::kungfu {
28 
Compile(const std::string & fileName,AOTFileGenerator & generator)29 bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generator)
30 {
31     [[maybe_unused]] EcmaHandleScope handleScope(vm_->GetJSThread());
32     JSPandaFile *jsPandaFile = CreateAndVerifyJSPandaFile(fileName.c_str());
33     if (jsPandaFile == nullptr) {
34         LOG_COMPILER(ERROR) << "Cannot execute panda file '" << fileName << "'";
35         return false;
36     }
37 
38     if (!profilerLoader_.LoadAndVerify(jsPandaFile->GetChecksum())) {
39         LOG_COMPILER(ERROR) << "Load and verify profiler failure";
40         return false;
41     }
42     bool enableCollectLiteralInfo = EnableTypeInfer() &&
43         (profilerLoader_.IsLoaded() || vm_->GetTSManager()->AssertTypes());
44     BytecodeInfoCollector bcInfoCollector(vm_, jsPandaFile, maxAotMethodSize_,
45         enableCollectLiteralInfo);
46 
47     if (!IsReleasedPandaFile(jsPandaFile)) {
48         LOG_COMPILER(ERROR) << "The input panda file [" << fileName
49                             << "] of AOT Compiler is debuggable version, do not use for performance test!";
50     }
51 
52     ResolveModule(jsPandaFile, fileName);
53     auto aotModule = new LLVMModule(fileName, triple_);
54     auto aotModuleAssembler = new LLVMAssembler(aotModule->GetModule(),
55                                                 LOptions(optLevel_, true, relocMode_));
56 
57     CompilationConfig cmpCfg(triple_, false, log_->IsTraceBC(), vm_->GetJSOptions().GetOptCodeProfiler());
58     Bytecodes bytecodes;
59     auto &bytecodeInfo = bcInfoCollector.GetBytecodeInfo();
60     auto lexEnvManager = LexEnvManager(bytecodeInfo);
61 
62     CompilationDriver cmpDriver(jsPandaFile, profilerLoader_, bytecodeInfo);
63     // ts type system
64     TSManager *tsManager = vm_->GetTSManager();
65     tsManager->SetCompilationDriver(&cmpDriver);
66     PassInfo info(tsManager, &bytecodes, &lexEnvManager, &cmpCfg, log_,
67         jsPandaFile, &bcInfoCollector, aotModule);
68 
69     cmpDriver.Run([this, &fileName, &info]
70         (const CString recordName, const std::string &methodName, MethodLiteral *methodLiteral,
71          uint32_t methodOffset, const MethodPcInfo &methodPCInfo, size_t methodInfoIndex) {
72         auto jsPandaFile = info.GetJSPandaFile();
73         auto cmpCfg = info.GetCompilerConfig();
74         auto tsManager = info.GetTSManager();
75         // note: TSManager need to set current constantpool before all pass
76         tsManager->SetCurConstantPool(jsPandaFile, methodOffset);
77 
78         log_->SetMethodLog(fileName, recordName, methodName, logList_);
79 
80         std::string fullName = methodName + "@" + fileName;
81         bool enableMethodLog = log_->GetEnableMethodLog();
82         if (enableMethodLog) {
83             LOG_COMPILER(INFO) << "\033[34m" << "aot method [" << fullName << "] log:" << "\033[0m";
84         }
85 
86         bool hasTypes = jsPandaFile->HasTSTypes(recordName);
87         if (UNLIKELY(!hasTypes)) {
88             LOG_COMPILER(INFO) << "record: " << recordName << " has no types";
89         }
90 
91         Circuit circuit(vm_->GetNativeAreaAllocator(), cmpCfg->Is64Bit());
92         BytecodeCircuitBuilder builder(jsPandaFile, methodLiteral, methodPCInfo, tsManager, &circuit,
93                                        info.GetByteCodes(), hasTypes, enableMethodLog && log_->OutputCIR(),
94                                        EnableTypeLowering(), fullName, recordName);
95         {
96             TimeScope timeScope("BytecodeToCircuit", methodName, methodOffset, log_);
97             builder.BytecodeToCircuit();
98         }
99 
100         PassData data(&builder, &circuit, &info, log_, fullName,
101                       methodInfoIndex, hasTypes, recordName,
102                       methodLiteral, methodOffset, vm_->GetNativeAreaAllocator());
103         PassRunner<PassData> pipeline(&data);
104         if (EnableTypeInfer()) {
105             pipeline.RunPass<TypeInferPass>();
106         }
107         pipeline.RunPass<AsyncFunctionLoweringPass>();
108         if (EnableTypeLowering()) {
109             pipeline.RunPass<TSTypeLoweringPass>();
110             pipeline.RunPass<EarlyEliminationPass>();
111             pipeline.RunPass<TypeLoweringPass>();
112         }
113         pipeline.RunPass<SlowPathLoweringPass>();
114         pipeline.RunPass<VerifierPass>();
115         pipeline.RunPass<SchedulingPass>();
116         pipeline.RunPass<LLVMIRGenPass>();
117     });
118     LOG_COMPILER(INFO) << bytecodeInfo.GetSkippedMethodSize() << " methods in "
119                        << fileName << " have been skipped";
120     generator.AddModule(aotModule, aotModuleAssembler, &bcInfoCollector);
121     return true;
122 }
123 
CreateAndVerifyJSPandaFile(const CString & fileName)124 JSPandaFile *PassManager::CreateAndVerifyJSPandaFile(const CString &fileName)
125 {
126     JSPandaFileManager *jsPandaFileManager = JSPandaFileManager::GetInstance();
127     JSPandaFile *jsPandaFile = jsPandaFileManager->OpenJSPandaFile(fileName);
128     if (jsPandaFile == nullptr) {
129         LOG_ECMA(ERROR) << "open file " << fileName << " error";
130         return nullptr;
131     }
132 
133     if (!jsPandaFile->IsNewVersion()) {
134         LOG_COMPILER(ERROR) << "AOT only support panda file with new ISA, while the '" <<
135             fileName << "' file is the old version";
136         return nullptr;
137     }
138 
139     JSPandaFileManager::GetInstance()->InsertJSPandaFile(jsPandaFile);
140     return jsPandaFile;
141 }
142 
IsReleasedPandaFile(const JSPandaFile * jsPandaFile) const143 bool PassManager::IsReleasedPandaFile(const JSPandaFile *jsPandaFile) const
144 {
145     MethodLiteral* methodLiteral = jsPandaFile->GetMethodLiterals();
146     if (methodLiteral == nullptr) {
147         LOG_COMPILER(ERROR) << "There is no mehtod literal in " << jsPandaFile->GetJSPandaFileDesc();
148         return false;
149     }
150 
151     panda_file::File::EntityId methodId = methodLiteral->GetMethodId();
152     DebugInfoExtractor *debugInfoExtractor = JSPandaFileManager::GetInstance()->GetJSPtExtractor(jsPandaFile);
153     LocalVariableTable lvt = debugInfoExtractor->GetLocalVariableTable(methodId);
154     return lvt.empty();
155 }
156 
ResolveModule(const JSPandaFile * jsPandaFile,const std::string & fileName)157 void PassManager::ResolveModule(const JSPandaFile *jsPandaFile, const std::string &fileName)
158 {
159     const auto &recordInfo = jsPandaFile->GetJSRecordInfo();
160     ModuleManager *moduleManager = vm_->GetModuleManager();
161     JSThread *thread = vm_->GetJSThread();
162     for (auto info: recordInfo) {
163         auto recordName = info.first;
164         if (jsPandaFile->IsModule(thread, recordName)) {
165             ASSERT(!thread->HasPendingException());
166             moduleManager->HostResolveImportedModuleWithMerge(fileName.c_str(), recordName);
167         }
168     }
169 }
170 } // namespace panda::ecmascript::kungfu
171