mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-06 23:54:03 +00:00
Add irreducible loop check
1.skip empty catch bb for aot and jit 2.add irreducible loop check Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IANMXK Signed-off-by: zoumujia <zoumujia0920@163.com>
This commit is contained in:
parent
2dc30245ec
commit
5398c8555d
@ -14,17 +14,18 @@
|
||||
*/
|
||||
#include "ecmascript/compiler/aot_compiler_preprocessor.h"
|
||||
|
||||
#include "ecmascript/compiler/bytecode_circuit_builder.h"
|
||||
#include "ecmascript/compiler/pgo_type/pgo_type_parser.h"
|
||||
#include "ecmascript/compiler/pass_manager.h"
|
||||
#include "ecmascript/jspandafile/program_object.h"
|
||||
#include "ecmascript/js_runtime_options.h"
|
||||
#include "ecmascript/module/js_shared_module_manager.h"
|
||||
#include "ecmascript/module/js_module_manager.h"
|
||||
#include "ecmascript/ohos/ohos_pgo_processor.h"
|
||||
#include "ecmascript/ohos/ohos_pkg_args.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
namespace {
|
||||
constexpr int32_t DEFAULT_OPT_LEVEL = 3; // 3: default opt level
|
||||
} // namespace
|
||||
|
||||
using PGOProfilerManager = pgo::PGOProfilerManager;
|
||||
|
||||
CompilationOptions::CompilationOptions(JSRuntimeOptions &runtimeOptions)
|
||||
@ -49,6 +50,7 @@ CompilationOptions::CompilationOptions(JSRuntimeOptions &runtimeOptions)
|
||||
isEnableArrayBoundsCheckElimination_ = runtimeOptions.IsEnableArrayBoundsCheckElimination();
|
||||
isEnableTypeLowering_ = runtimeOptions.IsEnableTypeLowering();
|
||||
isEnableEarlyElimination_ = runtimeOptions.IsEnableEarlyElimination();
|
||||
isEnableEmptyCatchFunction_ = runtimeOptions.IsEnableEmptyCatchFunction();
|
||||
isEnableLaterElimination_ = runtimeOptions.IsEnableLaterElimination();
|
||||
isEnableValueNumbering_ = runtimeOptions.IsEnableValueNumbering();
|
||||
isEnableOptInlining_ = runtimeOptions.IsEnableOptInlining();
|
||||
@ -67,7 +69,6 @@ CompilationOptions::CompilationOptions(JSRuntimeOptions &runtimeOptions)
|
||||
isEnableInductionVariableAnalysis_ = runtimeOptions.IsEnableInductionVariableAnalysis();
|
||||
isEnableVerifierPass_ = !runtimeOptions.IsTargetCompilerMode();
|
||||
isEnableBaselinePgo_ = runtimeOptions.IsEnableBaselinePgo();
|
||||
|
||||
std::string optionSelectMethods = runtimeOptions.GetCompilerSelectMethods();
|
||||
std::string optionSkipMethods = runtimeOptions.GetCompilerSkipMethods();
|
||||
if (!optionSelectMethods.empty() && !optionSkipMethods.empty()) {
|
||||
@ -145,6 +146,18 @@ void AotCompilerPreprocessor::HandleTargetModeInfo(CompilationOptions &cOptions)
|
||||
cOptions.optLevel_ = DEFAULT_OPT_LEVEL;
|
||||
}
|
||||
|
||||
bool AotCompilerPreprocessor::MethodHasTryCatch(const JSPandaFile *jsPandaFile,
|
||||
const MethodLiteral *methodLiteral) const
|
||||
{
|
||||
if (jsPandaFile == nullptr || methodLiteral == nullptr) {
|
||||
return false;
|
||||
}
|
||||
auto pf = jsPandaFile->GetPandaFile();
|
||||
panda_file::MethodDataAccessor mda(*pf, methodLiteral->GetMethodId());
|
||||
panda_file::CodeDataAccessor cda(*pf, mda.GetCodeId().value());
|
||||
return cda.GetTriesSize() != 0;
|
||||
}
|
||||
|
||||
bool AotCompilerPreprocessor::HandlePandaFileNames(const int argc, const char **argv)
|
||||
{
|
||||
if (runtimeOptions_.GetCompilerPkgJsonInfo().empty() || pkgsArgs_.empty()) {
|
||||
@ -174,9 +187,78 @@ void AotCompilerPreprocessor::Process(CompilationOptions &cOptions)
|
||||
GenerateBytecodeInfoCollectors(cOptions);
|
||||
GeneratePGOTypes();
|
||||
SnapshotInitialize();
|
||||
DoPreAnalysis(cOptions);
|
||||
GenerateMethodMap(cOptions);
|
||||
}
|
||||
|
||||
void AotCompilerPreprocessor::DoPreAnalysis(CompilationOptions &cOptions)
|
||||
{
|
||||
for (uint32_t i = 0 ; i < fileInfos_.size(); ++i) {
|
||||
JSPandaFile *jsPandaFile = fileInfos_[i].jsPandaFile_.get();
|
||||
auto &collector = *bcInfoCollectors_[i];
|
||||
AnalyzeGraphs(jsPandaFile, collector, cOptions);
|
||||
}
|
||||
}
|
||||
|
||||
void AotCompilerPreprocessor::AnalyzeGraphs(JSPandaFile *jsPandaFile,
|
||||
BytecodeInfoCollector &collector, CompilationOptions &cOptions)
|
||||
{
|
||||
if (jsPandaFile == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto &bytecodeInfo = collector.GetBytecodeInfo();
|
||||
auto &methodPcInfos = bytecodeInfo.GetMethodPcInfos();
|
||||
for (auto &[methodId, methodInfo] : bytecodeInfo.GetMethodList()) {
|
||||
auto methodLiteral = jsPandaFile->FindMethodLiteral(methodId);
|
||||
auto &methodPcInfo = methodPcInfos[methodInfo.GetMethodPcInfoIndex()];
|
||||
if (MethodHasTryCatch(jsPandaFile, methodLiteral)) {
|
||||
AnalyzeGraph(bytecodeInfo, cOptions, collector, methodLiteral, methodPcInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AotCompilerPreprocessor::AnalyzeGraph(BCInfo &bytecodeInfo, CompilationOptions &cOptions,
|
||||
BytecodeInfoCollector &collector, MethodLiteral *methodLiteral,
|
||||
MethodPcInfo &methodPCInfo)
|
||||
{
|
||||
if (methodLiteral == nullptr) {
|
||||
return;
|
||||
}
|
||||
AotMethodLogList logList(cOptions.logMethodsList_);
|
||||
AOTCompilationEnv aotCompilationEnv(vm_);
|
||||
CompilerLog log(cOptions.logOption_);
|
||||
AOTFileGenerator generator(&log, &logList, &aotCompilationEnv, cOptions.triple_, false);
|
||||
PGOProfilerDecoder profilerDecoder;
|
||||
LOptions lOptions = LOptions(DEFAULT_OPT_LEVEL, FPFlag::RESERVE_FP, DEFAULT_REL_MODE);
|
||||
Module *m = generator.AddModule("", cOptions.triple_, lOptions, false);
|
||||
PassContext ctx(cOptions.triple_, &log, &collector, m->GetModule(), &profilerDecoder);
|
||||
auto jsPandaFile = ctx.GetJSPandaFile();
|
||||
auto cmpCfg = ctx.GetCompilerConfig();
|
||||
auto module = m->GetModule();
|
||||
std::string fullName = module->GetFuncName(methodLiteral, jsPandaFile);
|
||||
|
||||
Circuit circuit(vm_->GetNativeAreaAllocator(), ctx.GetAOTModule()->GetDebugInfo(),
|
||||
fullName.c_str(), cmpCfg->Is64Bit(), FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
|
||||
|
||||
PGOProfilerDecoder *decoder = cOptions.isEnableOptPGOType_ ? &profilerDecoder : nullptr;
|
||||
|
||||
BytecodeCircuitBuilder builder(jsPandaFile, methodLiteral, methodPCInfo, &circuit,
|
||||
ctx.GetByteCodes(), false,
|
||||
cOptions.isEnableTypeLowering_,
|
||||
fullName, bytecodeInfo.GetRecordNameWithIndex(0), decoder, false);
|
||||
{
|
||||
builder.SetPreAnalysis();
|
||||
builder.BytecodeToCircuit();
|
||||
if (builder.HasEmptyCatchBB()) {
|
||||
emptyCatchBBMethods_.push_back(fullName);
|
||||
}
|
||||
if (builder.HasIrreducibleLoop()) {
|
||||
irreducibleMethods_.push_back(fullName);
|
||||
}
|
||||
}
|
||||
m->DestroyModule();
|
||||
}
|
||||
|
||||
uint32_t AotCompilerPreprocessor::GenerateAbcFileInfos()
|
||||
{
|
||||
size_t size = pandaFileNames_.size();
|
||||
@ -357,6 +439,15 @@ bool AotCompilerPreprocessor::IsSkipMethod(const JSPandaFile *jsPandaFile, const
|
||||
return FilterOption(cOptions.optionSkipMethods_, ConvertToStdString(recordName), methodName);
|
||||
}
|
||||
|
||||
std::string fullName = IRModule::GetFuncName(methodLiteral, jsPandaFile);
|
||||
if (HasSkipMethod(irreducibleMethods_, fullName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (HasSkipMethod(emptyCatchBBMethods_, fullName) && !cOptions.isEnableEmptyCatchFunction_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -390,6 +481,12 @@ void AotCompilerPreprocessor::GenerateMethodMap(CompilationOptions &cOptions)
|
||||
}
|
||||
}
|
||||
|
||||
bool AotCompilerPreprocessor::HasSkipMethod(const CVector<std::string> &methodList,
|
||||
const std::string &methodName) const
|
||||
{
|
||||
return std::find(methodList.begin(), methodList.end(), methodName) != methodList.end();
|
||||
}
|
||||
|
||||
std::string AotCompilerPreprocessor::GetMainPkgArgsAppSignature() const
|
||||
{
|
||||
return GetMainPkgArgs() == nullptr ? "" : GetMainPkgArgs()->GetAppSignature();
|
||||
|
@ -75,6 +75,7 @@ struct CompilationOptions {
|
||||
bool isEnableLaterElimination_ {true};
|
||||
bool isEnableValueNumbering_ {true};
|
||||
bool isEnableOptInlining_ {true};
|
||||
bool isEnableEmptyCatchFunction_ {false};
|
||||
bool isEnableOptString_ {true};
|
||||
bool isEnableOptPGOType_ {true};
|
||||
bool isEnableOptTrackField_ {true};
|
||||
@ -114,6 +115,13 @@ public:
|
||||
|
||||
void AOTInitialize();
|
||||
|
||||
void DoPreAnalysis(CompilationOptions &cOptions);
|
||||
|
||||
void AnalyzeGraphs(JSPandaFile *jsPandaFile, BytecodeInfoCollector &collector, CompilationOptions &cOptions);
|
||||
|
||||
void AnalyzeGraph(BCInfo &bytecodeInfo, CompilationOptions &cOptions, BytecodeInfoCollector &collector,
|
||||
MethodLiteral *methodLiteral, MethodPcInfo &methodPCInfo);
|
||||
|
||||
void Process(CompilationOptions &cOptions);
|
||||
|
||||
uint32_t GenerateAbcFileInfos();
|
||||
@ -136,6 +144,10 @@ public:
|
||||
|
||||
void GenerateMethodMap(CompilationOptions &cOptions);
|
||||
|
||||
bool MethodHasTryCatch(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral) const;
|
||||
|
||||
bool HasSkipMethod(const CVector<std::string> &methodList, const std::string &methodName) const;
|
||||
|
||||
void SetIsFastCall(CString fileDesc, uint32_t methodOffset, bool isFastCall)
|
||||
{
|
||||
callMethodFlagMap_.SetIsFastCall(fileDesc, methodOffset, isFastCall);
|
||||
@ -226,6 +238,8 @@ private:
|
||||
CVector<std::unique_ptr<BytecodeInfoCollector>> bcInfoCollectors_;
|
||||
CallMethodFlagMap callMethodFlagMap_;
|
||||
AOTCompilationEnv aotCompilationEnv_;
|
||||
CVector<std::string> emptyCatchBBMethods_;
|
||||
CVector<std::string> irreducibleMethods_;
|
||||
friend class OhosPkgArgs;
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -15,12 +15,16 @@
|
||||
|
||||
#include "ecmascript/compiler/bytecode_circuit_builder.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
#include "ecmascript/deoptimizer/deoptimizer.h"
|
||||
#include "ecmascript/interpreter/interpreter-inl.h"
|
||||
#include "libpandafile/bytecode_instruction-inl.h"
|
||||
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
void BytecodeCircuitBuilder::BytecodeToCircuit()
|
||||
{
|
||||
@ -147,6 +151,161 @@ void BytecodeCircuitBuilder::CollectTryCatchBlockInfo(ExceptionInfo &byteCodeExc
|
||||
});
|
||||
}
|
||||
|
||||
bool BytecodeCircuitBuilder::IsAncestor(size_t nodeA, size_t nodeB)
|
||||
{
|
||||
return timeIn_[bbIdToDfsTimestamp_[nodeA]] <= timeIn_[bbIdToDfsTimestamp_[nodeB]] &&
|
||||
timeOut_[bbIdToDfsTimestamp_[nodeA]] >= timeOut_[bbIdToDfsTimestamp_[nodeB]];
|
||||
}
|
||||
|
||||
void BytecodeCircuitBuilder::PerformDFS(const std::vector<size_t> &immDom, size_t listSize)
|
||||
{
|
||||
std::vector<std::vector<size_t>> sonList(listSize);
|
||||
for (size_t idx = 1; idx < immDom.size(); idx++) {
|
||||
sonList[immDom[idx]].push_back(idx);
|
||||
}
|
||||
|
||||
{
|
||||
size_t timestamp = 0;
|
||||
struct DFSState {
|
||||
size_t cur;
|
||||
std::vector<size_t> &succList;
|
||||
size_t idx;
|
||||
};
|
||||
std::stack<DFSState> dfsStack;
|
||||
size_t root = 0;
|
||||
dfsStack.push({root, sonList[root], 0});
|
||||
timeIn_[root] = timestamp++;
|
||||
while (!dfsStack.empty()) {
|
||||
auto &curState = dfsStack.top();
|
||||
auto &cur = curState.cur;
|
||||
auto &succList = curState.succList;
|
||||
auto &idx = curState.idx;
|
||||
if (idx == succList.size()) {
|
||||
timeOut_[cur] = timestamp++;
|
||||
dfsStack.pop();
|
||||
continue;
|
||||
}
|
||||
const auto &succ = succList[idx];
|
||||
dfsStack.push({succ, sonList[succ], 0});
|
||||
timeIn_[succ] = timestamp++;
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BytecodeCircuitBuilder::ReducibilityCheck()
|
||||
{
|
||||
std::vector<size_t> basicBlockList;
|
||||
std::vector<size_t> immDom;
|
||||
std::unordered_map<size_t, size_t> bbDfsTimestampToIdx;
|
||||
ComputeDominatorTree(basicBlockList, immDom, bbDfsTimestampToIdx);
|
||||
timeIn_.resize(basicBlockList.size());
|
||||
timeOut_.resize(basicBlockList.size());
|
||||
PerformDFS(immDom, basicBlockList.size());
|
||||
}
|
||||
|
||||
void BytecodeCircuitBuilder::ComputeImmediateDominators(const std::vector<size_t> &basicBlockList,
|
||||
std::unordered_map<size_t, size_t> &dfsFatherIdx,
|
||||
std::vector<size_t> &immDom,
|
||||
std::unordered_map<size_t, size_t> &bbDfsTimestampToIdx)
|
||||
{
|
||||
std::vector<size_t> semiDom(basicBlockList.size());
|
||||
std::vector<std::vector<size_t> > semiDomTree(basicBlockList.size());
|
||||
{
|
||||
std::vector<size_t> parent(basicBlockList.size());
|
||||
std::iota(parent.begin(), parent.end(), 0);
|
||||
std::vector<size_t> minIdx(basicBlockList.size());
|
||||
std::function<size_t(size_t)> unionFind = [&] (size_t idx) -> size_t {
|
||||
if (parent[idx] == idx) return idx;
|
||||
size_t unionFindSetRoot = unionFind(parent[idx]);
|
||||
if (semiDom[minIdx[idx]] > semiDom[minIdx[parent[idx]]]) {
|
||||
minIdx[idx] = minIdx[parent[idx]];
|
||||
}
|
||||
return parent[idx] = unionFindSetRoot;
|
||||
};
|
||||
auto merge = [&] (size_t fatherIdx, size_t sonIdx) -> void {
|
||||
size_t parentFatherIdx = unionFind(fatherIdx);
|
||||
size_t parentSonIdx = unionFind(sonIdx);
|
||||
parent[parentSonIdx] = parentFatherIdx;
|
||||
};
|
||||
auto calculateSemiDom = [&](size_t idx, const ChunkVector<BytecodeRegion *> &blocks) {
|
||||
for (const auto &preBlock : blocks) {
|
||||
if (bbDfsTimestampToIdx[preBlock->id] < idx) {
|
||||
semiDom[idx] = std::min(semiDom[idx], bbDfsTimestampToIdx[preBlock->id]);
|
||||
} else {
|
||||
unionFind(bbDfsTimestampToIdx[preBlock->id]);
|
||||
semiDom[idx] = std::min(semiDom[idx], semiDom[minIdx[bbDfsTimestampToIdx[preBlock->id]]]);
|
||||
}
|
||||
}
|
||||
};
|
||||
std::iota(semiDom.begin(), semiDom.end(), 0);
|
||||
semiDom[0] = semiDom.size();
|
||||
for (size_t idx = basicBlockList.size() - 1; idx >= 1; idx--) {
|
||||
calculateSemiDom(idx, graph_[basicBlockList[idx]]->preds);
|
||||
if (!graph_[basicBlockList[idx]]->trys.empty()) {
|
||||
calculateSemiDom(idx, graph_[basicBlockList[idx]]->trys);
|
||||
}
|
||||
for (const auto &succDomIdx : semiDomTree[idx]) {
|
||||
unionFind(succDomIdx);
|
||||
if (idx == semiDom[minIdx[succDomIdx]]) {
|
||||
immDom[succDomIdx] = idx;
|
||||
} else {
|
||||
immDom[succDomIdx] = minIdx[succDomIdx];
|
||||
}
|
||||
}
|
||||
minIdx[idx] = idx;
|
||||
merge(dfsFatherIdx[basicBlockList[idx]], idx);
|
||||
semiDomTree[semiDom[idx]].emplace_back(idx);
|
||||
}
|
||||
for (size_t idx = 1; idx < basicBlockList.size(); idx++) {
|
||||
if (immDom[idx] != semiDom[idx]) {
|
||||
immDom[idx] = immDom[immDom[idx]];
|
||||
}
|
||||
}
|
||||
semiDom[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeCircuitBuilder::ComputeDominatorTree(std::vector<size_t> &basicBlockList, std::vector<size_t> &immDom,
|
||||
std::unordered_map<size_t, size_t> &bbDfsTimestampToIdx)
|
||||
{
|
||||
std::unordered_map<size_t, size_t> dfsFatherIdx;
|
||||
size_t timestamp = 0;
|
||||
std::deque<size_t> pendingList;
|
||||
std::vector<size_t> visited(graph_.size(), 0);
|
||||
auto basicBlockId = graph_[0]->id;
|
||||
visited[graph_[0]->id] = 1;
|
||||
pendingList.emplace_back(basicBlockId);
|
||||
|
||||
auto visitConnectedBlocks = [&](const ChunkVector<BytecodeRegion *> &succs, size_t curBlockId) {
|
||||
for (const auto &succBlock : succs) {
|
||||
if (visited[succBlock->id] == 0) {
|
||||
visited[succBlock->id] = 1;
|
||||
pendingList.emplace_back(succBlock->id);
|
||||
dfsFatherIdx[succBlock->id] = bbIdToDfsTimestamp_[curBlockId];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
while (!pendingList.empty()) {
|
||||
size_t curBlockId = pendingList.back();
|
||||
pendingList.pop_back();
|
||||
basicBlockList.emplace_back(curBlockId);
|
||||
bbIdToDfsTimestamp_[curBlockId] = timestamp++;
|
||||
visitConnectedBlocks(graph_[curBlockId]->succs, curBlockId);
|
||||
if (!graph_[curBlockId]->catches.empty()) {
|
||||
visitConnectedBlocks(graph_[curBlockId]->catches, curBlockId);
|
||||
}
|
||||
}
|
||||
for (size_t idx = 0; idx < basicBlockList.size(); idx++) {
|
||||
bbDfsTimestampToIdx[basicBlockList[idx]] = idx;
|
||||
}
|
||||
|
||||
immDom.resize(basicBlockList.size());
|
||||
ComputeImmediateDominators(basicBlockList, dfsFatherIdx, immDom, bbDfsTimestampToIdx);
|
||||
}
|
||||
|
||||
void BytecodeCircuitBuilder::BuildEntryBlock()
|
||||
{
|
||||
BytecodeRegion &entryBlock = RegionAt(0);
|
||||
@ -156,23 +315,9 @@ void BytecodeCircuitBuilder::BuildEntryBlock()
|
||||
entryBlock.bytecodeIterator_.Reset(this, 0, BytecodeIterator::INVALID_INDEX);
|
||||
}
|
||||
|
||||
void BytecodeCircuitBuilder::BuildRegions(const ExceptionInfo &byteCodeException)
|
||||
void BytecodeCircuitBuilder::BuildBasicBlock()
|
||||
{
|
||||
auto &items = regionsInfo_.GetBlockItems();
|
||||
auto blockSize = items.size();
|
||||
|
||||
// 1 : entry block. if the loop head is in the first bb block, the variables used in the head cannot correctly
|
||||
// generate Phi nodes through the dominator-tree algorithm, resulting in an infinite loop. Therefore, an empty
|
||||
// BB block is generated as an entry block
|
||||
graph_.resize(blockSize + 1, nullptr);
|
||||
for (size_t i = 0; i < graph_.size(); i++) {
|
||||
graph_[i] = circuit_->chunk()->New<BytecodeRegion>(circuit_->chunk());
|
||||
}
|
||||
|
||||
// build entry block
|
||||
BuildEntryBlock();
|
||||
|
||||
// build basic block
|
||||
size_t blockId = 1;
|
||||
for (const auto &item : items) {
|
||||
auto &curBlock = GetBasicBlockById(blockId);
|
||||
@ -194,6 +339,25 @@ void BytecodeCircuitBuilder::BuildRegions(const ExceptionInfo &byteCodeException
|
||||
auto &lastBlock = RegionAt(blockId - 1); // 1: last block
|
||||
lastBlock.end = GetLastBcIndex();
|
||||
lastBlock.bytecodeIterator_.Reset(this, lastBlock.start, lastBlock.end);
|
||||
}
|
||||
|
||||
void BytecodeCircuitBuilder::BuildRegions(const ExceptionInfo &byteCodeException)
|
||||
{
|
||||
auto blockSize = regionsInfo_.GetBlockItems().size();
|
||||
|
||||
// 1 : entry block. if the loop head is in the first bb block, the variables used in the head cannot correctly
|
||||
// generate Phi nodes through the dominator-tree algorithm, resulting in an infinite loop. Therefore, an empty
|
||||
// BB block is generated as an entry block
|
||||
graph_.resize(blockSize + 1, nullptr);
|
||||
for (size_t i = 0; i < graph_.size(); i++) {
|
||||
graph_[i] = circuit_->chunk()->New<BytecodeRegion>(circuit_->chunk());
|
||||
}
|
||||
|
||||
// build entry block
|
||||
BuildEntryBlock();
|
||||
|
||||
// build basic block
|
||||
BuildBasicBlock();
|
||||
|
||||
auto &splitItems = regionsInfo_.GetSplitItems();
|
||||
for (const auto &item : splitItems) {
|
||||
@ -213,7 +377,10 @@ void BytecodeCircuitBuilder::BuildRegions(const ExceptionInfo &byteCodeException
|
||||
CollectTryPredsInfo();
|
||||
}
|
||||
RemoveUnreachableRegion();
|
||||
if (IsLogEnabled()) {
|
||||
if (NeedIrreducibleLoopCheck()) {
|
||||
ReducibilityCheck();
|
||||
}
|
||||
if (IsLogEnabled() && !IsPreAnalysis()) {
|
||||
PrintGraph(std::string("Update CFG [" + methodName_ + "]").c_str());
|
||||
}
|
||||
BuildCircuit();
|
||||
@ -227,6 +394,7 @@ void BytecodeCircuitBuilder::UpdateEmptyCatchBB()
|
||||
if (it != candidateEmptyCatch_.end()) {
|
||||
if (it->second) {
|
||||
bb.IsEmptyCatchBB = true;
|
||||
hasEmptyCatchBB_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1039,12 +1207,18 @@ void BytecodeCircuitBuilder::BuildCircuit()
|
||||
// create osr arg gates array
|
||||
BuildOSRArgs();
|
||||
frameStateBuilder_.DoBytecodeAnalysis();
|
||||
if (TerminateAnalysis()) {
|
||||
return;
|
||||
}
|
||||
// build states sub-circuit of osr block
|
||||
BuildOsrCircuit();
|
||||
} else {
|
||||
// create arg gates array
|
||||
BuildCircuitArgs();
|
||||
frameStateBuilder_.DoBytecodeAnalysis();
|
||||
if (TerminateAnalysis()) {
|
||||
return;
|
||||
}
|
||||
// build states sub-circuit of each block
|
||||
BuildSubCircuit();
|
||||
}
|
||||
|
@ -572,6 +572,51 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void SetIrreducibleLoop()
|
||||
{
|
||||
isIrreducible_ = true;
|
||||
}
|
||||
|
||||
bool HasIrreducibleLoop() const
|
||||
{
|
||||
return isIrreducible_;
|
||||
}
|
||||
|
||||
void SetJitCompile()
|
||||
{
|
||||
isJitCompile_ = true;
|
||||
}
|
||||
|
||||
bool IsJitCompile() const
|
||||
{
|
||||
return isJitCompile_;
|
||||
}
|
||||
|
||||
void SetPreAnalysis()
|
||||
{
|
||||
preAnalysis_ = true;
|
||||
}
|
||||
|
||||
bool IsPreAnalysis() const
|
||||
{
|
||||
return preAnalysis_;
|
||||
}
|
||||
|
||||
bool HasEmptyCatchBB() const
|
||||
{
|
||||
return hasEmptyCatchBB_;
|
||||
}
|
||||
|
||||
bool NeedIrreducibleLoopCheck() const
|
||||
{
|
||||
return IsPreAnalysis() || IsJitCompile();
|
||||
}
|
||||
|
||||
bool TerminateAnalysis() const
|
||||
{
|
||||
return IsPreAnalysis() || HasIrreducibleLoop();
|
||||
}
|
||||
|
||||
bool IsOSR() const
|
||||
{
|
||||
return osrOffset_ != MachineCode::INVALID_OSR_OFFSET;
|
||||
@ -584,10 +629,26 @@ public:
|
||||
|
||||
void ComputeNumOfLoopBack();
|
||||
|
||||
enum class MarkState : uint8_t {
|
||||
UNVISITED = 0,
|
||||
ON_STACK,
|
||||
PENDING,
|
||||
VISITED,
|
||||
VISITED1,
|
||||
UNVISITED1 = VISITED
|
||||
};
|
||||
|
||||
struct VisitedInfo {
|
||||
size_t needVisitIndex;
|
||||
bool isVisitedCatchBlock = false;
|
||||
};
|
||||
bool IsAncestor(size_t nodeA, size_t nodeB);
|
||||
|
||||
private:
|
||||
void CollectTryCatchBlockInfo(ExceptionInfo &Exception);
|
||||
void BuildCatchBlocks(const ExceptionInfo &Exception);
|
||||
void BuildEntryBlock();
|
||||
void BuildBasicBlock();
|
||||
void BuildRegions(const ExceptionInfo &Exception);
|
||||
// build circuit
|
||||
void BuildCircuitArgs();
|
||||
@ -621,6 +682,13 @@ private:
|
||||
void BuildRegionInfo();
|
||||
void BuildFrameArgs();
|
||||
void RemoveIfInRpoList(BytecodeRegion *bb);
|
||||
void PerformDFS(const std::vector<size_t> &immDom, size_t listSize);
|
||||
void ReducibilityCheck();
|
||||
void ComputeImmediateDominators(const std::vector<size_t> &basicBlockList,
|
||||
std::unordered_map<size_t, size_t> &dfsFatherIdx, std::vector<size_t> &immDom,
|
||||
std::unordered_map<size_t, size_t> &bbDfsTimestampToIdx);
|
||||
void ComputeDominatorTree(std::vector<size_t> &basicBlockList, std::vector<size_t> &immDom,
|
||||
std::unordered_map<size_t, size_t> &bbDfsTimestampToIdx);
|
||||
|
||||
BytecodeRegion &RegionAt(size_t i)
|
||||
{
|
||||
@ -654,8 +722,15 @@ private:
|
||||
size_t numOfLiveBB_ {0};
|
||||
bool isInline_ {false};
|
||||
uint32_t methodId_ {0};
|
||||
bool preAnalysis_ {false};
|
||||
std::set<const BytecodeRegion *> catchBBOfOSRLoop_{};
|
||||
std::map<uint32_t, bool> candidateEmptyCatch_ {};
|
||||
bool hasEmptyCatchBB_ {false};
|
||||
bool isIrreducible_ {false};
|
||||
bool isJitCompile_ {false};
|
||||
CVector<size_t> timeIn_ {};
|
||||
CVector<size_t> timeOut_ {};
|
||||
std::unordered_map<size_t, size_t> bbIdToDfsTimestamp_ {};
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H
|
||||
|
@ -149,13 +149,13 @@ public:
|
||||
Module *GetModule();
|
||||
|
||||
template <class Callback>
|
||||
void CompileMethod(const JSPandaFile *jsPandaFile, MethodLiteral *methodLiteral,
|
||||
bool CompileMethod(const JSPandaFile *jsPandaFile, MethodLiteral *methodLiteral,
|
||||
JSHandle<ProfileTypeInfo> &profileTypeInfo, const uint8_t *pcStart,
|
||||
const panda_file::File::Header *header, ApEntityId abcId, const Callback &cb)
|
||||
{
|
||||
SetCurrentCompilationFile();
|
||||
if (methodLiteral == nullptr) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
const std::string methodName(MethodLiteral::GetMethodName(jsPandaFile, methodLiteral->GetMethodId()));
|
||||
|
||||
@ -168,7 +168,7 @@ public:
|
||||
bytecodeInfo_.EraseSkippedMethod(methodOffset);
|
||||
|
||||
Module *module = GetModule();
|
||||
cb(bytecodeInfo_.GetRecordNameWithIndex(0), methodName, methodLiteral, profileTypeInfo,
|
||||
return cb(bytecodeInfo_.GetRecordNameWithIndex(0), methodName, methodLiteral, profileTypeInfo,
|
||||
methodOffset, methodPcInfo, methodInfo, module, pcStart, header, abcId);
|
||||
}
|
||||
};
|
||||
|
@ -943,6 +943,9 @@ public:
|
||||
void Run()
|
||||
{
|
||||
ComputeLoopBack();
|
||||
if (bcBuilder_->TerminateAnalysis()) {
|
||||
return;
|
||||
}
|
||||
TryClearDeadBlock();
|
||||
bcBuilder_->ComputeNumOfLoopBack();
|
||||
frameBuilder_->numLoops_ = numLoops_;
|
||||
@ -967,6 +970,19 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void CheckDominance()
|
||||
{
|
||||
for (size_t i = 0; i < loopbacks_.size(); i++) {
|
||||
auto loopBackinfo = loopbacks_[i];
|
||||
bool isDom = bcBuilder_->IsAncestor(loopBackinfo.toId, loopBackinfo.fromId);
|
||||
if (!isDom) {
|
||||
bcBuilder_->SetIrreducibleLoop();
|
||||
LOG_COMPILER(INFO) << "CFG is not reducible. Compilation aborted.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ComputeLoopBack()
|
||||
{
|
||||
auto size = bcBuilder_->GetBasicBlockCount();
|
||||
@ -1015,6 +1031,10 @@ public:
|
||||
frameBuilder_->rpoList_.push_front(bbId);
|
||||
}
|
||||
}
|
||||
|
||||
if (bcBuilder_->NeedIrreducibleLoopCheck()) {
|
||||
CheckDominance();
|
||||
}
|
||||
}
|
||||
|
||||
void TryClearDeadBlock()
|
||||
@ -1340,7 +1360,7 @@ void FrameStateBuilder::ComputeLoopInfo()
|
||||
{
|
||||
BlockLoopAnalysis loopAnalysis(this, circuit_->chunk());
|
||||
loopAnalysis.Run();
|
||||
if (numLoops_ != 0) {
|
||||
if (numLoops_ != 0 && !bcBuilder_->HasIrreducibleLoop()) {
|
||||
ChunkVector<GateRef>& headerGates = bcBuilder_->GetLoopHeaderGates();
|
||||
headerGates.resize(numLoops_, Circuit::NullGate());
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
|
||||
virtual ModuleKind GetModuleKind() const = 0;
|
||||
|
||||
std::string GetFuncName(const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile);
|
||||
static std::string GetFuncName(const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile);
|
||||
|
||||
private:
|
||||
DebugInfo *debugInfo_ {nullptr};
|
||||
|
@ -71,19 +71,19 @@ bool JitPassManager::Compile(JSHandle<ProfileTypeInfo> &profileTypeInfo,
|
||||
log_,
|
||||
log_->OutputASM(),
|
||||
maxMethodsInModule_);
|
||||
cmpDriver_->CompileMethod(jsPandaFile, methodLiteral, profileTypeInfo, pcStart, header, abcId,
|
||||
[this, &fileName, &osrOffset] (
|
||||
const CString &recordName,
|
||||
const std::string &methodName,
|
||||
MethodLiteral *methodLiteral,
|
||||
JSHandle<ProfileTypeInfo> &profileTypeInfo,
|
||||
uint32_t methodOffset,
|
||||
const MethodPcInfo &methodPCInfo,
|
||||
MethodInfo &methodInfo,
|
||||
Module *m,
|
||||
const uint8_t *pcStart,
|
||||
const panda_file::File::Header *header,
|
||||
ApEntityId abcId) {
|
||||
return cmpDriver_->CompileMethod(jsPandaFile, methodLiteral, profileTypeInfo, pcStart, header, abcId,
|
||||
[this, &fileName, &osrOffset] (
|
||||
const CString &recordName,
|
||||
const std::string &methodName,
|
||||
MethodLiteral *methodLiteral,
|
||||
JSHandle<ProfileTypeInfo> &profileTypeInfo,
|
||||
uint32_t methodOffset,
|
||||
const MethodPcInfo &methodPCInfo,
|
||||
MethodInfo &methodInfo,
|
||||
Module *m,
|
||||
const uint8_t *pcStart,
|
||||
const panda_file::File::Header *header,
|
||||
ApEntityId abcId) -> bool {
|
||||
if (compilationEnv_->GetJSOptions().GetTraceJIT()) {
|
||||
LOG_COMPILER(INFO) << "JIT Compile Method Start: " << methodName << ", " << methodOffset << "\n";
|
||||
}
|
||||
@ -130,7 +130,16 @@ bool JitPassManager::Compile(JSHandle<ProfileTypeInfo> &profileTypeInfo,
|
||||
builder_->SetOsrOffset(osrOffset);
|
||||
{
|
||||
TimeScope timeScope("BytecodeToCircuit", methodName, methodOffset, log_);
|
||||
builder_->SetJitCompile();
|
||||
builder_->BytecodeToCircuit();
|
||||
if (builder_->HasIrreducibleLoop()) {
|
||||
LOG_JIT(DEBUG) << "compile fail as has irreducible loop:" << methodName;
|
||||
return false;
|
||||
}
|
||||
if (builder_->HasEmptyCatchBB() && compilationEnv_->GetJSOptions().IsEnableAPPJIT()) {
|
||||
LOG_JIT(DEBUG) << "compile fail as has empty catch bb:" << methodName;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CallMethodFlagMap methodFlagMap;
|
||||
@ -192,8 +201,8 @@ bool JitPassManager::Compile(JSHandle<ProfileTypeInfo> &profileTypeInfo,
|
||||
pipeline.RunPass<VerifierPass>();
|
||||
}
|
||||
pipeline.RunPass<GraphLinearizerPass>();
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JitPassManager::RunCg()
|
||||
@ -261,7 +270,6 @@ bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName,
|
||||
LOG_COMPILER(ERROR) << "The input panda file [" << fileName
|
||||
<< "] of AOT Compiler is debuggable version, do not use for performance test!";
|
||||
}
|
||||
|
||||
LOptions lOptions(optLevel_, FPFlag::RESERVE_FP, relocMode_);
|
||||
CompilationDriver cmpDriver(profilerDecoder_,
|
||||
&collector,
|
||||
|
@ -466,7 +466,6 @@ bool JitTask::AsyncTask::AllocFromFortAndCopy()
|
||||
|
||||
bool JitTask::AsyncTask::Run([[maybe_unused]] uint32_t threadIndex)
|
||||
{
|
||||
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "AsyncTask::Run");
|
||||
if (IsTerminate() || !jitTask_->GetHostThread()->GetEcmaVM()->IsInitialized()) {
|
||||
return false;
|
||||
}
|
||||
@ -474,15 +473,8 @@ bool JitTask::AsyncTask::Run([[maybe_unused]] uint32_t threadIndex)
|
||||
|
||||
CString info = "compile method:" + jitTask_->GetMethodName();
|
||||
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, ConvertToStdString("JIT::Compile:" + info));
|
||||
// JitCompileMode ASYNC
|
||||
// check init ok
|
||||
jitTask_->SetRunState(RunState::RUNNING);
|
||||
|
||||
JSThread *compilerThread = jitTask_->GetCompilerThread();
|
||||
ASSERT(compilerThread->IsJitThread());
|
||||
JitThread *jitThread = static_cast<JitThread*>(compilerThread);
|
||||
JitVM *jitvm = jitThread->GetJitVM();
|
||||
jitvm->SetHostVM(jitTask_->GetHostThread());
|
||||
AsyncTaskRunScope asyncTaskRunScope(jitTask_.get());
|
||||
|
||||
if (jitTask_->GetJsFunction().GetAddress() == 0) {
|
||||
// for unit test
|
||||
@ -510,8 +502,23 @@ bool JitTask::AsyncTask::Run([[maybe_unused]] uint32_t threadIndex)
|
||||
JitDfx::GetInstance()->RecordSpentTimeAndPrintStatsLogInJitThread(compilerTime, jitTask_->methodName_,
|
||||
jitTask_->compilerTier_ == CompilerTier::BASELINE, jitTask_->mainThreadCompileTime_);
|
||||
}
|
||||
jitvm->ReSetHostVM();
|
||||
jitTask_->SetRunStateFinish();
|
||||
return true;
|
||||
}
|
||||
|
||||
JitTask::AsyncTask::AsyncTaskRunScope::AsyncTaskRunScope(JitTask *jitTask)
|
||||
{
|
||||
jitTask_ = jitTask;
|
||||
jitTask_->SetRunState(RunState::RUNNING);
|
||||
JSThread *compilerThread = jitTask_->GetCompilerThread();
|
||||
ASSERT(compilerThread->IsJitThread());
|
||||
JitThread *jitThread = static_cast<JitThread*>(compilerThread);
|
||||
jitvm_ = jitThread->GetJitVM();
|
||||
jitvm_->SetHostVM(jitTask_->GetHostThread());
|
||||
}
|
||||
|
||||
JitTask::AsyncTask::AsyncTaskRunScope::~AsyncTaskRunScope()
|
||||
{
|
||||
jitvm_->ReSetHostVM();
|
||||
jitTask_->SetRunStateFinish();
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -270,6 +270,15 @@ public:
|
||||
private:
|
||||
ARK_INLINE bool CopyCodeToFort();
|
||||
std::shared_ptr<JitTask> jitTask_ { nullptr };
|
||||
|
||||
class AsyncTaskRunScope {
|
||||
public:
|
||||
AsyncTaskRunScope(JitTask *jitTask);
|
||||
~AsyncTaskRunScope();
|
||||
private:
|
||||
JitTask *jitTask_ { nullptr };
|
||||
JitVM *jitvm_ { nullptr };
|
||||
};
|
||||
};
|
||||
private:
|
||||
void SustainingJSHandles();
|
||||
|
@ -89,6 +89,7 @@ const std::string PUBLIC_API HELP_OPTION_MSG =
|
||||
"--compiler-opt-later-elimination: Enable LaterElimination for aot compiler. Default: 'true'\n"
|
||||
"--compiler-opt-string: Enable string optimization pass for aot compiler. Default: 'true'\n"
|
||||
"--compiler-opt-value-numbering: Enable ValueNumbering for aot compiler. Default: 'true'\n"
|
||||
"--compiler-empty-catch-function: Enable function with empty-catch for aot compiler: Default: 'false'\n"
|
||||
"--compiler-opt-inlining: Enable inlining function for aot compiler: Default: 'true'\n"
|
||||
"--compiler-opt-pgotype: Enable pgo type for aot compiler: Default: 'true'\n"
|
||||
"--compiler-opt-track-field: Enable track field for aot compiler: Default: 'false'\n"
|
||||
@ -242,6 +243,7 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
|
||||
{"compiler-opt-value-numbering", required_argument, nullptr, OPTION_COMPILER_OPT_VALUE_NUMBERING},
|
||||
{"compiler-opt-new-value-numbering", required_argument, nullptr, OPTION_COMPILER_OPT_NEW_VALUE_NUMBERING},
|
||||
{"compiler-opt-inlining", required_argument, nullptr, OPTION_COMPILER_OPT_INLINING},
|
||||
{"compiler-empty-catch-function", required_argument, nullptr, OPTION_COMPILER_EMPTY_CATCH_FUNCTION},
|
||||
{"compiler-opt-pgotype", required_argument, nullptr, OPTION_COMPILER_OPT_PGOTYPE},
|
||||
{"compiler-opt-track-field", required_argument, nullptr, OPTION_COMPILER_OPT_TRACK_FIELD},
|
||||
{"entry-point", required_argument, nullptr, OPTION_ENTRY_POINT},
|
||||
@ -850,6 +852,14 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPTION_COMPILER_EMPTY_CATCH_FUNCTION:
|
||||
ret = ParseBoolParam(&argBool);
|
||||
if (ret) {
|
||||
SetEnableEmptyCatchFunction(argBool);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPTION_COMPILER_OPT_INSTRUCTIONE_COMBINE:
|
||||
ret = ParseBoolParam(&argBool);
|
||||
if (ret) {
|
||||
|
@ -26,6 +26,11 @@
|
||||
#include "ecmascript/mem/mem_common.h"
|
||||
#include "libpandabase/os/file.h"
|
||||
|
||||
namespace {
|
||||
constexpr size_t DEFAULT_OPT_LEVEL = 3; // 3: default opt level
|
||||
constexpr size_t DEFAULT_REL_MODE = 2;
|
||||
} // namespace
|
||||
|
||||
// namespace panda {
|
||||
namespace panda::ecmascript {
|
||||
using arg_list_t = std::vector<std::string>;
|
||||
@ -210,6 +215,7 @@ enum CommandValues {
|
||||
OPTION_COMPILER_OPT_STRING,
|
||||
OPTION_OPEN_ARK_TOOLS,
|
||||
OPTION_COMPILER_OPT_FRAME_STATE_ELIMINATION,
|
||||
OPTION_COMPILER_EMPTY_CATCH_FUNCTION
|
||||
};
|
||||
static_assert(OPTION_SPLIT_ONE == 64); // add new option at the bottom, DO NOT modify this value
|
||||
static_assert(OPTION_SPLIT_TWO == 128); // add new option at the bottom, DO NOT modify this value
|
||||
@ -1344,6 +1350,16 @@ public:
|
||||
enableOptInlining_ = value;
|
||||
}
|
||||
|
||||
void SetEnableEmptyCatchFunction(bool value)
|
||||
{
|
||||
enableEmptyCatchFunction_ = value;
|
||||
}
|
||||
|
||||
bool IsEnableEmptyCatchFunction() const
|
||||
{
|
||||
return enableEmptyCatchFunction_;
|
||||
}
|
||||
|
||||
bool IsEnableOptInlining() const
|
||||
{
|
||||
return enableOptInlining_;
|
||||
@ -1937,7 +1953,6 @@ public:
|
||||
static constexpr int32_t MAX_APP_COMPILE_METHOD_SIZE = 4_KB;
|
||||
|
||||
private:
|
||||
static constexpr int32_t DEFAULT_OPT_LEVEL = 3; // 3: default opt level
|
||||
|
||||
static bool StartsWith(const std::string& haystack, const std::string& needle)
|
||||
{
|
||||
@ -2033,6 +2048,7 @@ private:
|
||||
bool enableInstrcutionCombine {true};
|
||||
bool enableNewValueNumbering_ {true};
|
||||
bool enableOptInlining_ {true};
|
||||
bool enableEmptyCatchFunction_ {false};
|
||||
bool enableOptPGOType_ {true};
|
||||
bool enableFastJIT_ {false};
|
||||
bool enableAPPJIT_ {false};
|
||||
|
@ -13,3 +13,4 @@
|
||||
|
||||
Test Success
|
||||
true
|
||||
false
|
@ -13,3 +13,4 @@
|
||||
|
||||
Test Success
|
||||
false
|
||||
false
|
@ -28,4 +28,20 @@ function f3() {
|
||||
}
|
||||
|
||||
f3()
|
||||
print(ArkTools.isAOTCompiled(f3));
|
||||
print(ArkTools.isAOTCompiled(f3));
|
||||
|
||||
function f4() {
|
||||
let v3 = 3;
|
||||
for (let i44 = 0; i44 < 5; i44++) {
|
||||
let v53 = 0;
|
||||
do {
|
||||
i44 = v3;
|
||||
try {
|
||||
i44.o(375);
|
||||
} catch (e) {}
|
||||
v53++;
|
||||
} while (v53 < 2)
|
||||
v3++;
|
||||
}
|
||||
}
|
||||
print(ArkTools.isAOTCompiled(f4));
|
@ -15,6 +15,7 @@ group("ark_jit_ts_test") {
|
||||
testonly = true
|
||||
test_list = [
|
||||
"create_arguments",
|
||||
"try_catch_empty",
|
||||
"ldobjbyname",
|
||||
"for_loop",
|
||||
"typed_array",
|
||||
|
18
test/jittest/try_catch_empty/BUILD.gn
Normal file
18
test/jittest/try_catch_empty/BUILD.gn
Normal file
@ -0,0 +1,18 @@
|
||||
# Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//arkcompiler/ets_runtime/test/test_helper.gni")
|
||||
|
||||
host_jit_test_action("try_catch_empty") {
|
||||
deps = []
|
||||
}
|
15
test/jittest/try_catch_empty/expect_output.txt
Normal file
15
test/jittest/try_catch_empty/expect_output.txt
Normal file
@ -0,0 +1,15 @@
|
||||
# Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
true
|
||||
130
|
50
test/jittest/try_catch_empty/try_catch_empty.ts
Normal file
50
test/jittest/try_catch_empty/try_catch_empty.ts
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
var i = 0;
|
||||
|
||||
function SmallFunc() {
|
||||
try {
|
||||
i += 10;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
function EmptyCatch() {
|
||||
try {
|
||||
i += 10;
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function CallSmallFunc() {
|
||||
SmallFunc();
|
||||
try {
|
||||
i += 10;
|
||||
} catch (e) {
|
||||
i += 10;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
EmptyCatch();
|
||||
CallSmallFunc();
|
||||
ArkTools.jitCompileAsync(EmptyCatch);
|
||||
ArkTools.jitCompileAsync(CallSmallFunc);
|
||||
var ret = ArkTools.waitJitCompileFinish(CallSmallFunc);
|
||||
for (let j = 0; j < 10; j++) {
|
||||
EmptyCatch()
|
||||
}
|
||||
print(ret);
|
||||
print(i);
|
@ -1220,7 +1220,7 @@ template("host_aot_js_test_action") {
|
||||
script = "//arkcompiler/ets_runtime/script/run_ark_executable.py"
|
||||
|
||||
_aot_compile_options_ = " --aot-file=" + rebase_path(_test_aot_arg_) +
|
||||
" --log-level=" + _test_aot_log_level + " --log-components=compiler --compiler-opt-type-lowering=false --compiler-opt-inlining=false" + " --compiler-opt-loop-peeling=false"
|
||||
" --log-level=" + _test_aot_log_level + " --log-components=compiler --compiler-opt-type-lowering=false --compiler-opt-inlining=false" + " --compiler-opt-loop-peeling=false" + " --compiler-empty-catch-function=true"
|
||||
|
||||
if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
|
||||
_aot_compile_options_ += " --compiler-pgo-profiler-path=" +
|
||||
@ -1493,7 +1493,8 @@ template("host_aot_js_test_action") {
|
||||
" --compiler-opt-type-lowering=false" +
|
||||
" --compiler-opt-inlining=false" +
|
||||
" --compiler-opt-loop-peeling=false" +
|
||||
" --compiler-enable-litecg=true"
|
||||
" --compiler-enable-litecg=true" +
|
||||
" --compiler-empty-catch-function=true"
|
||||
|
||||
if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
|
||||
_aot_compile_options_ += " --compiler-pgo-profiler-path=" +
|
||||
@ -1749,7 +1750,8 @@ template("host_aot_js_test_action") {
|
||||
" --compiler-opt-inlining=false" +
|
||||
" --compiler-opt-loop-peeling=false" +
|
||||
" --compiler-enable-litecg=true" +
|
||||
" --compiler-target-triple=aarch64-unknown-linux-gnu"
|
||||
" --compiler-target-triple=aarch64-unknown-linux-gnu" +
|
||||
" --compiler-empty-catch-function=true"
|
||||
|
||||
if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
|
||||
_aot_compile_options_ += " --compiler-pgo-profiler-path=" +
|
||||
@ -2104,7 +2106,7 @@ template("host_aot_js_assert_test_action") {
|
||||
script = "//arkcompiler/ets_runtime/script/run_ark_executable.py"
|
||||
|
||||
_aot_compile_options_ = " --aot-file=" + rebase_path(_test_aot_arg_) +
|
||||
" --log-level=" + _test_aot_log_level + " --log-components=compiler --compiler-opt-type-lowering=false --compiler-opt-inlining=false" + " --compiler-opt-loop-peeling=false"
|
||||
" --log-level=" + _test_aot_log_level + " --log-components=compiler --compiler-opt-type-lowering=false --compiler-opt-inlining=false" + " --compiler-opt-loop-peeling=false" + " --compiler-empty-catch-function=true"
|
||||
|
||||
if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
|
||||
_aot_compile_options_ += " --compiler-pgo-profiler-path=" +
|
||||
@ -2530,7 +2532,9 @@ template("host_aot_test_action") {
|
||||
_aot_compile_options_ =
|
||||
" --aot-file=" + rebase_path(_test_aot_arg_) + " --log-level=" +
|
||||
_test_aot_log_level + " --log-components=compiler" +
|
||||
" --compiler-opt-inlining=false" + " --compiler-opt-loop-peeling=false"
|
||||
" --compiler-opt-inlining=false" +
|
||||
" --compiler-opt-loop-peeling=false" +
|
||||
" --compiler-empty-catch-function=true"
|
||||
|
||||
if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
|
||||
_aot_compile_options_ +=
|
||||
@ -2627,7 +2631,10 @@ template("host_aot_test_action") {
|
||||
" --aot-file=" + rebase_path(_test_aot_arg_slowpath_) +
|
||||
" --log-level=" + _test_aot_log_level + " --log-components=compiler" +
|
||||
" --compiler-opt-type-lowering=false" +
|
||||
" --compiler-opt-inlining=false" + " --compiler-opt-loop-peeling=false"
|
||||
" --compiler-opt-inlining=false" +
|
||||
" --compiler-opt-loop-peeling=false" +
|
||||
" --compiler-empty-catch-function=true"
|
||||
|
||||
if (defined(invoker.is_enable_trace_deopt) &&
|
||||
invoker.is_enable_trace_deopt) {
|
||||
_aot_compile_options_ += " --compiler-trace-deopt=true"
|
||||
@ -2946,7 +2953,8 @@ template("host_aot_test_action") {
|
||||
" --log-level=" + _test_aot_log_level + " --log-components=compiler" +
|
||||
" --compiler-opt-inlining=false" +
|
||||
" --compiler-opt-loop-peeling=false" +
|
||||
" --compiler-enable-litecg=true"
|
||||
" --compiler-enable-litecg=true" +
|
||||
" --compiler-empty-catch-function=true"
|
||||
|
||||
if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
|
||||
_aot_compile_options_ +=
|
||||
@ -3047,7 +3055,8 @@ template("host_aot_test_action") {
|
||||
" --compiler-opt-type-lowering=false" +
|
||||
" --compiler-opt-inlining=false" +
|
||||
" --compiler-opt-loop-peeling=false" +
|
||||
" --compiler-enable-litecg=true"
|
||||
" --compiler-enable-litecg=true" +
|
||||
" --compiler-empty-catch-function=true"
|
||||
if (defined(invoker.is_enable_trace_deopt) &&
|
||||
invoker.is_enable_trace_deopt) {
|
||||
_aot_compile_options_ += " --compiler-trace-deopt=true"
|
||||
@ -3356,7 +3365,8 @@ template("host_aot_test_action") {
|
||||
" --compiler-opt-inlining=false" +
|
||||
" --compiler-opt-loop-peeling=false" +
|
||||
" --compiler-enable-litecg=true" +
|
||||
" --compiler-target-triple=aarch64-unknown-linux-gnu"
|
||||
" --compiler-target-triple=aarch64-unknown-linux-gnu" +
|
||||
" --compiler-empty-catch-function=true"
|
||||
|
||||
if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
|
||||
_aot_compile_options_ +=
|
||||
@ -3458,7 +3468,8 @@ template("host_aot_test_action") {
|
||||
" --compiler-opt-inlining=false" +
|
||||
" --compiler-opt-loop-peeling=false" +
|
||||
" --compiler-enable-litecg=true" +
|
||||
" --compiler-target-triple=aarch64-unknown-linux-gnu"
|
||||
" --compiler-target-triple=aarch64-unknown-linux-gnu" +
|
||||
" --compiler-empty-catch-function=true"
|
||||
if (defined(invoker.is_enable_trace_deopt) &&
|
||||
invoker.is_enable_trace_deopt) {
|
||||
_aot_compile_options_ += " --compiler-trace-deopt=true"
|
||||
@ -3872,7 +3883,9 @@ template("host_aot_assert_test_action") {
|
||||
_aot_compile_options_ =
|
||||
" --aot-file=" + rebase_path(_test_aot_arg_) + " --log-level=" +
|
||||
_test_aot_log_level + " --log-components=compiler" +
|
||||
" --compiler-opt-inlining=false" + " --compiler-opt-loop-peeling=false"
|
||||
" --compiler-opt-inlining=false" +
|
||||
" --compiler-opt-loop-peeling=false" +
|
||||
" --compiler-empty-catch-function=true"
|
||||
|
||||
if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
|
||||
_aot_compile_options_ += " --compiler-pgo-profiler-path=" +
|
||||
@ -3971,7 +3984,9 @@ template("host_aot_assert_test_action") {
|
||||
" --aot-file=" + rebase_path(_test_aot_arg_slowpath_) +
|
||||
" --log-level=" + _test_aot_log_level + " --log-components=compiler" +
|
||||
" --compiler-opt-type-lowering=false" +
|
||||
" --compiler-opt-inlining=false" + " --compiler-opt-loop-peeling=false"
|
||||
" --compiler-opt-inlining=false" +
|
||||
" --compiler-opt-loop-peeling=false" +
|
||||
" --compiler-empty-catch-function=true"
|
||||
|
||||
if (defined(invoker.aot_log_option)) {
|
||||
_aot_compile_options_ += invoker.aot_log_option
|
||||
@ -4367,7 +4382,8 @@ template("host_pgotypeinfer_test_action") {
|
||||
script = "//arkcompiler/ets_runtime/script/run_ark_executable.py"
|
||||
|
||||
_aot_compile_options_ = " --compiler-opt-type-lowering=false" +
|
||||
" --compiler-opt-loop-peeling=false"
|
||||
" --compiler-opt-loop-peeling=false" +
|
||||
" --compiler-empty-catch-function=true"
|
||||
|
||||
# Pgo Option
|
||||
_aot_compile_options_ += " --compiler-pgo-profiler-path=" +
|
||||
@ -4414,9 +4430,10 @@ template("host_pgotypeinfer_test_action") {
|
||||
|
||||
script = "//arkcompiler/ets_runtime/script/run_ark_executable.py"
|
||||
|
||||
_aot_compile_options_ =
|
||||
" --compiler-opt-type-lowering=false" +
|
||||
" --compiler-opt-loop-peeling=false" + " --compiler-enable-litecg=true"
|
||||
_aot_compile_options_ = " --compiler-opt-type-lowering=false" +
|
||||
" --compiler-opt-loop-peeling=false" +
|
||||
" --compiler-enable-litecg=true" +
|
||||
" --compiler-empty-catch-function=true"
|
||||
|
||||
# Pgo Option
|
||||
_aot_compile_options_ += " --compiler-pgo-profiler-path=" +
|
||||
|
Loading…
Reference in New Issue
Block a user