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:
zoumujia 2024-08-31 14:53:09 +08:00
parent 2dc30245ec
commit 5398c8555d
20 changed files with 618 additions and 69 deletions

View File

@ -14,17 +14,18 @@
*/ */
#include "ecmascript/compiler/aot_compiler_preprocessor.h" #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/pgo_type/pgo_type_parser.h"
#include "ecmascript/compiler/pass_manager.h"
#include "ecmascript/jspandafile/program_object.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_shared_module_manager.h"
#include "ecmascript/module/js_module_manager.h" #include "ecmascript/module/js_module_manager.h"
#include "ecmascript/ohos/ohos_pgo_processor.h" #include "ecmascript/ohos/ohos_pgo_processor.h"
#include "ecmascript/ohos/ohos_pkg_args.h" #include "ecmascript/ohos/ohos_pkg_args.h"
namespace panda::ecmascript::kungfu { namespace panda::ecmascript::kungfu {
namespace {
constexpr int32_t DEFAULT_OPT_LEVEL = 3; // 3: default opt level
} // namespace
using PGOProfilerManager = pgo::PGOProfilerManager; using PGOProfilerManager = pgo::PGOProfilerManager;
CompilationOptions::CompilationOptions(JSRuntimeOptions &runtimeOptions) CompilationOptions::CompilationOptions(JSRuntimeOptions &runtimeOptions)
@ -49,6 +50,7 @@ CompilationOptions::CompilationOptions(JSRuntimeOptions &runtimeOptions)
isEnableArrayBoundsCheckElimination_ = runtimeOptions.IsEnableArrayBoundsCheckElimination(); isEnableArrayBoundsCheckElimination_ = runtimeOptions.IsEnableArrayBoundsCheckElimination();
isEnableTypeLowering_ = runtimeOptions.IsEnableTypeLowering(); isEnableTypeLowering_ = runtimeOptions.IsEnableTypeLowering();
isEnableEarlyElimination_ = runtimeOptions.IsEnableEarlyElimination(); isEnableEarlyElimination_ = runtimeOptions.IsEnableEarlyElimination();
isEnableEmptyCatchFunction_ = runtimeOptions.IsEnableEmptyCatchFunction();
isEnableLaterElimination_ = runtimeOptions.IsEnableLaterElimination(); isEnableLaterElimination_ = runtimeOptions.IsEnableLaterElimination();
isEnableValueNumbering_ = runtimeOptions.IsEnableValueNumbering(); isEnableValueNumbering_ = runtimeOptions.IsEnableValueNumbering();
isEnableOptInlining_ = runtimeOptions.IsEnableOptInlining(); isEnableOptInlining_ = runtimeOptions.IsEnableOptInlining();
@ -67,7 +69,6 @@ CompilationOptions::CompilationOptions(JSRuntimeOptions &runtimeOptions)
isEnableInductionVariableAnalysis_ = runtimeOptions.IsEnableInductionVariableAnalysis(); isEnableInductionVariableAnalysis_ = runtimeOptions.IsEnableInductionVariableAnalysis();
isEnableVerifierPass_ = !runtimeOptions.IsTargetCompilerMode(); isEnableVerifierPass_ = !runtimeOptions.IsTargetCompilerMode();
isEnableBaselinePgo_ = runtimeOptions.IsEnableBaselinePgo(); isEnableBaselinePgo_ = runtimeOptions.IsEnableBaselinePgo();
std::string optionSelectMethods = runtimeOptions.GetCompilerSelectMethods(); std::string optionSelectMethods = runtimeOptions.GetCompilerSelectMethods();
std::string optionSkipMethods = runtimeOptions.GetCompilerSkipMethods(); std::string optionSkipMethods = runtimeOptions.GetCompilerSkipMethods();
if (!optionSelectMethods.empty() && !optionSkipMethods.empty()) { if (!optionSelectMethods.empty() && !optionSkipMethods.empty()) {
@ -145,6 +146,18 @@ void AotCompilerPreprocessor::HandleTargetModeInfo(CompilationOptions &cOptions)
cOptions.optLevel_ = DEFAULT_OPT_LEVEL; 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) bool AotCompilerPreprocessor::HandlePandaFileNames(const int argc, const char **argv)
{ {
if (runtimeOptions_.GetCompilerPkgJsonInfo().empty() || pkgsArgs_.empty()) { if (runtimeOptions_.GetCompilerPkgJsonInfo().empty() || pkgsArgs_.empty()) {
@ -174,9 +187,78 @@ void AotCompilerPreprocessor::Process(CompilationOptions &cOptions)
GenerateBytecodeInfoCollectors(cOptions); GenerateBytecodeInfoCollectors(cOptions);
GeneratePGOTypes(); GeneratePGOTypes();
SnapshotInitialize(); SnapshotInitialize();
DoPreAnalysis(cOptions);
GenerateMethodMap(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() uint32_t AotCompilerPreprocessor::GenerateAbcFileInfos()
{ {
size_t size = pandaFileNames_.size(); size_t size = pandaFileNames_.size();
@ -357,6 +439,15 @@ bool AotCompilerPreprocessor::IsSkipMethod(const JSPandaFile *jsPandaFile, const
return FilterOption(cOptions.optionSkipMethods_, ConvertToStdString(recordName), methodName); 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; 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 std::string AotCompilerPreprocessor::GetMainPkgArgsAppSignature() const
{ {
return GetMainPkgArgs() == nullptr ? "" : GetMainPkgArgs()->GetAppSignature(); return GetMainPkgArgs() == nullptr ? "" : GetMainPkgArgs()->GetAppSignature();

View File

@ -75,6 +75,7 @@ struct CompilationOptions {
bool isEnableLaterElimination_ {true}; bool isEnableLaterElimination_ {true};
bool isEnableValueNumbering_ {true}; bool isEnableValueNumbering_ {true};
bool isEnableOptInlining_ {true}; bool isEnableOptInlining_ {true};
bool isEnableEmptyCatchFunction_ {false};
bool isEnableOptString_ {true}; bool isEnableOptString_ {true};
bool isEnableOptPGOType_ {true}; bool isEnableOptPGOType_ {true};
bool isEnableOptTrackField_ {true}; bool isEnableOptTrackField_ {true};
@ -114,6 +115,13 @@ public:
void AOTInitialize(); 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); void Process(CompilationOptions &cOptions);
uint32_t GenerateAbcFileInfos(); uint32_t GenerateAbcFileInfos();
@ -136,6 +144,10 @@ public:
void GenerateMethodMap(CompilationOptions &cOptions); 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) void SetIsFastCall(CString fileDesc, uint32_t methodOffset, bool isFastCall)
{ {
callMethodFlagMap_.SetIsFastCall(fileDesc, methodOffset, isFastCall); callMethodFlagMap_.SetIsFastCall(fileDesc, methodOffset, isFastCall);
@ -226,6 +238,8 @@ private:
CVector<std::unique_ptr<BytecodeInfoCollector>> bcInfoCollectors_; CVector<std::unique_ptr<BytecodeInfoCollector>> bcInfoCollectors_;
CallMethodFlagMap callMethodFlagMap_; CallMethodFlagMap callMethodFlagMap_;
AOTCompilationEnv aotCompilationEnv_; AOTCompilationEnv aotCompilationEnv_;
CVector<std::string> emptyCatchBBMethods_;
CVector<std::string> irreducibleMethods_;
friend class OhosPkgArgs; friend class OhosPkgArgs;
}; };
} // namespace panda::ecmascript::kungfu } // namespace panda::ecmascript::kungfu

View File

@ -15,12 +15,16 @@
#include "ecmascript/compiler/bytecode_circuit_builder.h" #include "ecmascript/compiler/bytecode_circuit_builder.h"
#include <algorithm>
#include <cstddef>
#include "ecmascript/base/number_helper.h" #include "ecmascript/base/number_helper.h"
#include "ecmascript/compiler/gate_accessor.h" #include "ecmascript/compiler/gate_accessor.h"
#include "ecmascript/deoptimizer/deoptimizer.h" #include "ecmascript/deoptimizer/deoptimizer.h"
#include "ecmascript/interpreter/interpreter-inl.h" #include "ecmascript/interpreter/interpreter-inl.h"
#include "libpandafile/bytecode_instruction-inl.h" #include "libpandafile/bytecode_instruction-inl.h"
namespace panda::ecmascript::kungfu { namespace panda::ecmascript::kungfu {
void BytecodeCircuitBuilder::BytecodeToCircuit() 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() void BytecodeCircuitBuilder::BuildEntryBlock()
{ {
BytecodeRegion &entryBlock = RegionAt(0); BytecodeRegion &entryBlock = RegionAt(0);
@ -156,23 +315,9 @@ void BytecodeCircuitBuilder::BuildEntryBlock()
entryBlock.bytecodeIterator_.Reset(this, 0, BytecodeIterator::INVALID_INDEX); entryBlock.bytecodeIterator_.Reset(this, 0, BytecodeIterator::INVALID_INDEX);
} }
void BytecodeCircuitBuilder::BuildRegions(const ExceptionInfo &byteCodeException) void BytecodeCircuitBuilder::BuildBasicBlock()
{ {
auto &items = regionsInfo_.GetBlockItems(); 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; size_t blockId = 1;
for (const auto &item : items) { for (const auto &item : items) {
auto &curBlock = GetBasicBlockById(blockId); auto &curBlock = GetBasicBlockById(blockId);
@ -194,6 +339,25 @@ void BytecodeCircuitBuilder::BuildRegions(const ExceptionInfo &byteCodeException
auto &lastBlock = RegionAt(blockId - 1); // 1: last block auto &lastBlock = RegionAt(blockId - 1); // 1: last block
lastBlock.end = GetLastBcIndex(); lastBlock.end = GetLastBcIndex();
lastBlock.bytecodeIterator_.Reset(this, lastBlock.start, lastBlock.end); 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(); auto &splitItems = regionsInfo_.GetSplitItems();
for (const auto &item : splitItems) { for (const auto &item : splitItems) {
@ -213,7 +377,10 @@ void BytecodeCircuitBuilder::BuildRegions(const ExceptionInfo &byteCodeException
CollectTryPredsInfo(); CollectTryPredsInfo();
} }
RemoveUnreachableRegion(); RemoveUnreachableRegion();
if (IsLogEnabled()) { if (NeedIrreducibleLoopCheck()) {
ReducibilityCheck();
}
if (IsLogEnabled() && !IsPreAnalysis()) {
PrintGraph(std::string("Update CFG [" + methodName_ + "]").c_str()); PrintGraph(std::string("Update CFG [" + methodName_ + "]").c_str());
} }
BuildCircuit(); BuildCircuit();
@ -227,6 +394,7 @@ void BytecodeCircuitBuilder::UpdateEmptyCatchBB()
if (it != candidateEmptyCatch_.end()) { if (it != candidateEmptyCatch_.end()) {
if (it->second) { if (it->second) {
bb.IsEmptyCatchBB = true; bb.IsEmptyCatchBB = true;
hasEmptyCatchBB_ = true;
} }
} }
} }
@ -1039,12 +1207,18 @@ void BytecodeCircuitBuilder::BuildCircuit()
// create osr arg gates array // create osr arg gates array
BuildOSRArgs(); BuildOSRArgs();
frameStateBuilder_.DoBytecodeAnalysis(); frameStateBuilder_.DoBytecodeAnalysis();
if (TerminateAnalysis()) {
return;
}
// build states sub-circuit of osr block // build states sub-circuit of osr block
BuildOsrCircuit(); BuildOsrCircuit();
} else { } else {
// create arg gates array // create arg gates array
BuildCircuitArgs(); BuildCircuitArgs();
frameStateBuilder_.DoBytecodeAnalysis(); frameStateBuilder_.DoBytecodeAnalysis();
if (TerminateAnalysis()) {
return;
}
// build states sub-circuit of each block // build states sub-circuit of each block
BuildSubCircuit(); BuildSubCircuit();
} }

View File

@ -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 bool IsOSR() const
{ {
return osrOffset_ != MachineCode::INVALID_OSR_OFFSET; return osrOffset_ != MachineCode::INVALID_OSR_OFFSET;
@ -584,10 +629,26 @@ public:
void ComputeNumOfLoopBack(); 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: private:
void CollectTryCatchBlockInfo(ExceptionInfo &Exception); void CollectTryCatchBlockInfo(ExceptionInfo &Exception);
void BuildCatchBlocks(const ExceptionInfo &Exception); void BuildCatchBlocks(const ExceptionInfo &Exception);
void BuildEntryBlock(); void BuildEntryBlock();
void BuildBasicBlock();
void BuildRegions(const ExceptionInfo &Exception); void BuildRegions(const ExceptionInfo &Exception);
// build circuit // build circuit
void BuildCircuitArgs(); void BuildCircuitArgs();
@ -621,6 +682,13 @@ private:
void BuildRegionInfo(); void BuildRegionInfo();
void BuildFrameArgs(); void BuildFrameArgs();
void RemoveIfInRpoList(BytecodeRegion *bb); 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) BytecodeRegion &RegionAt(size_t i)
{ {
@ -654,8 +722,15 @@ private:
size_t numOfLiveBB_ {0}; size_t numOfLiveBB_ {0};
bool isInline_ {false}; bool isInline_ {false};
uint32_t methodId_ {0}; uint32_t methodId_ {0};
bool preAnalysis_ {false};
std::set<const BytecodeRegion *> catchBBOfOSRLoop_{}; std::set<const BytecodeRegion *> catchBBOfOSRLoop_{};
std::map<uint32_t, bool> candidateEmptyCatch_ {}; 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 } // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H #endif // ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H

View File

@ -149,13 +149,13 @@ public:
Module *GetModule(); Module *GetModule();
template <class Callback> template <class Callback>
void CompileMethod(const JSPandaFile *jsPandaFile, MethodLiteral *methodLiteral, bool CompileMethod(const JSPandaFile *jsPandaFile, MethodLiteral *methodLiteral,
JSHandle<ProfileTypeInfo> &profileTypeInfo, const uint8_t *pcStart, JSHandle<ProfileTypeInfo> &profileTypeInfo, const uint8_t *pcStart,
const panda_file::File::Header *header, ApEntityId abcId, const Callback &cb) const panda_file::File::Header *header, ApEntityId abcId, const Callback &cb)
{ {
SetCurrentCompilationFile(); SetCurrentCompilationFile();
if (methodLiteral == nullptr) { if (methodLiteral == nullptr) {
return; return false;
} }
const std::string methodName(MethodLiteral::GetMethodName(jsPandaFile, methodLiteral->GetMethodId())); const std::string methodName(MethodLiteral::GetMethodName(jsPandaFile, methodLiteral->GetMethodId()));
@ -168,7 +168,7 @@ public:
bytecodeInfo_.EraseSkippedMethod(methodOffset); bytecodeInfo_.EraseSkippedMethod(methodOffset);
Module *module = GetModule(); 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); methodOffset, methodPcInfo, methodInfo, module, pcStart, header, abcId);
} }
}; };

View File

@ -943,6 +943,9 @@ public:
void Run() void Run()
{ {
ComputeLoopBack(); ComputeLoopBack();
if (bcBuilder_->TerminateAnalysis()) {
return;
}
TryClearDeadBlock(); TryClearDeadBlock();
bcBuilder_->ComputeNumOfLoopBack(); bcBuilder_->ComputeNumOfLoopBack();
frameBuilder_->numLoops_ = numLoops_; 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() void ComputeLoopBack()
{ {
auto size = bcBuilder_->GetBasicBlockCount(); auto size = bcBuilder_->GetBasicBlockCount();
@ -1015,6 +1031,10 @@ public:
frameBuilder_->rpoList_.push_front(bbId); frameBuilder_->rpoList_.push_front(bbId);
} }
} }
if (bcBuilder_->NeedIrreducibleLoopCheck()) {
CheckDominance();
}
} }
void TryClearDeadBlock() void TryClearDeadBlock()
@ -1340,7 +1360,7 @@ void FrameStateBuilder::ComputeLoopInfo()
{ {
BlockLoopAnalysis loopAnalysis(this, circuit_->chunk()); BlockLoopAnalysis loopAnalysis(this, circuit_->chunk());
loopAnalysis.Run(); loopAnalysis.Run();
if (numLoops_ != 0) { if (numLoops_ != 0 && !bcBuilder_->HasIrreducibleLoop()) {
ChunkVector<GateRef>& headerGates = bcBuilder_->GetLoopHeaderGates(); ChunkVector<GateRef>& headerGates = bcBuilder_->GetLoopHeaderGates();
headerGates.resize(numLoops_, Circuit::NullGate()); headerGates.resize(numLoops_, Circuit::NullGate());
} }

View File

@ -73,7 +73,7 @@ public:
virtual ModuleKind GetModuleKind() const = 0; 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: private:
DebugInfo *debugInfo_ {nullptr}; DebugInfo *debugInfo_ {nullptr};

View File

@ -71,7 +71,7 @@ bool JitPassManager::Compile(JSHandle<ProfileTypeInfo> &profileTypeInfo,
log_, log_,
log_->OutputASM(), log_->OutputASM(),
maxMethodsInModule_); maxMethodsInModule_);
cmpDriver_->CompileMethod(jsPandaFile, methodLiteral, profileTypeInfo, pcStart, header, abcId, return cmpDriver_->CompileMethod(jsPandaFile, methodLiteral, profileTypeInfo, pcStart, header, abcId,
[this, &fileName, &osrOffset] ( [this, &fileName, &osrOffset] (
const CString &recordName, const CString &recordName,
const std::string &methodName, const std::string &methodName,
@ -83,7 +83,7 @@ bool JitPassManager::Compile(JSHandle<ProfileTypeInfo> &profileTypeInfo,
Module *m, Module *m,
const uint8_t *pcStart, const uint8_t *pcStart,
const panda_file::File::Header *header, const panda_file::File::Header *header,
ApEntityId abcId) { ApEntityId abcId) -> bool {
if (compilationEnv_->GetJSOptions().GetTraceJIT()) { if (compilationEnv_->GetJSOptions().GetTraceJIT()) {
LOG_COMPILER(INFO) << "JIT Compile Method Start: " << methodName << ", " << methodOffset << "\n"; LOG_COMPILER(INFO) << "JIT Compile Method Start: " << methodName << ", " << methodOffset << "\n";
} }
@ -130,7 +130,16 @@ bool JitPassManager::Compile(JSHandle<ProfileTypeInfo> &profileTypeInfo,
builder_->SetOsrOffset(osrOffset); builder_->SetOsrOffset(osrOffset);
{ {
TimeScope timeScope("BytecodeToCircuit", methodName, methodOffset, log_); TimeScope timeScope("BytecodeToCircuit", methodName, methodOffset, log_);
builder_->SetJitCompile();
builder_->BytecodeToCircuit(); 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; CallMethodFlagMap methodFlagMap;
@ -192,8 +201,8 @@ bool JitPassManager::Compile(JSHandle<ProfileTypeInfo> &profileTypeInfo,
pipeline.RunPass<VerifierPass>(); pipeline.RunPass<VerifierPass>();
} }
pipeline.RunPass<GraphLinearizerPass>(); pipeline.RunPass<GraphLinearizerPass>();
});
return true; return true;
});
} }
bool JitPassManager::RunCg() bool JitPassManager::RunCg()
@ -261,7 +270,6 @@ bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName,
LOG_COMPILER(ERROR) << "The input panda file [" << fileName LOG_COMPILER(ERROR) << "The input panda file [" << fileName
<< "] of AOT Compiler is debuggable version, do not use for performance test!"; << "] of AOT Compiler is debuggable version, do not use for performance test!";
} }
LOptions lOptions(optLevel_, FPFlag::RESERVE_FP, relocMode_); LOptions lOptions(optLevel_, FPFlag::RESERVE_FP, relocMode_);
CompilationDriver cmpDriver(profilerDecoder_, CompilationDriver cmpDriver(profilerDecoder_,
&collector, &collector,

View File

@ -466,7 +466,6 @@ bool JitTask::AsyncTask::AllocFromFortAndCopy()
bool JitTask::AsyncTask::Run([[maybe_unused]] uint32_t threadIndex) bool JitTask::AsyncTask::Run([[maybe_unused]] uint32_t threadIndex)
{ {
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "AsyncTask::Run");
if (IsTerminate() || !jitTask_->GetHostThread()->GetEcmaVM()->IsInitialized()) { if (IsTerminate() || !jitTask_->GetHostThread()->GetEcmaVM()->IsInitialized()) {
return false; return false;
} }
@ -474,15 +473,8 @@ bool JitTask::AsyncTask::Run([[maybe_unused]] uint32_t threadIndex)
CString info = "compile method:" + jitTask_->GetMethodName(); CString info = "compile method:" + jitTask_->GetMethodName();
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, ConvertToStdString("JIT::Compile:" + info)); ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, ConvertToStdString("JIT::Compile:" + info));
// JitCompileMode ASYNC
// check init ok
jitTask_->SetRunState(RunState::RUNNING);
JSThread *compilerThread = jitTask_->GetCompilerThread(); AsyncTaskRunScope asyncTaskRunScope(jitTask_.get());
ASSERT(compilerThread->IsJitThread());
JitThread *jitThread = static_cast<JitThread*>(compilerThread);
JitVM *jitvm = jitThread->GetJitVM();
jitvm->SetHostVM(jitTask_->GetHostThread());
if (jitTask_->GetJsFunction().GetAddress() == 0) { if (jitTask_->GetJsFunction().GetAddress() == 0) {
// for unit test // for unit test
@ -510,8 +502,23 @@ bool JitTask::AsyncTask::Run([[maybe_unused]] uint32_t threadIndex)
JitDfx::GetInstance()->RecordSpentTimeAndPrintStatsLogInJitThread(compilerTime, jitTask_->methodName_, JitDfx::GetInstance()->RecordSpentTimeAndPrintStatsLogInJitThread(compilerTime, jitTask_->methodName_,
jitTask_->compilerTier_ == CompilerTier::BASELINE, jitTask_->mainThreadCompileTime_); jitTask_->compilerTier_ == CompilerTier::BASELINE, jitTask_->mainThreadCompileTime_);
} }
jitvm->ReSetHostVM();
jitTask_->SetRunStateFinish();
return true; 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 } // namespace panda::ecmascript

View File

@ -270,6 +270,15 @@ public:
private: private:
ARK_INLINE bool CopyCodeToFort(); ARK_INLINE bool CopyCodeToFort();
std::shared_ptr<JitTask> jitTask_ { nullptr }; std::shared_ptr<JitTask> jitTask_ { nullptr };
class AsyncTaskRunScope {
public:
AsyncTaskRunScope(JitTask *jitTask);
~AsyncTaskRunScope();
private:
JitTask *jitTask_ { nullptr };
JitVM *jitvm_ { nullptr };
};
}; };
private: private:
void SustainingJSHandles(); void SustainingJSHandles();

View File

@ -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-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-string: Enable string optimization pass for aot compiler. Default: 'true'\n"
"--compiler-opt-value-numbering: Enable ValueNumbering 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-inlining: Enable inlining function for aot compiler: Default: 'true'\n"
"--compiler-opt-pgotype: Enable pgo type 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" "--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-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-new-value-numbering", required_argument, nullptr, OPTION_COMPILER_OPT_NEW_VALUE_NUMBERING},
{"compiler-opt-inlining", required_argument, nullptr, OPTION_COMPILER_OPT_INLINING}, {"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-pgotype", required_argument, nullptr, OPTION_COMPILER_OPT_PGOTYPE},
{"compiler-opt-track-field", required_argument, nullptr, OPTION_COMPILER_OPT_TRACK_FIELD}, {"compiler-opt-track-field", required_argument, nullptr, OPTION_COMPILER_OPT_TRACK_FIELD},
{"entry-point", required_argument, nullptr, OPTION_ENTRY_POINT}, {"entry-point", required_argument, nullptr, OPTION_ENTRY_POINT},
@ -850,6 +852,14 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
return false; return false;
} }
break; break;
case OPTION_COMPILER_EMPTY_CATCH_FUNCTION:
ret = ParseBoolParam(&argBool);
if (ret) {
SetEnableEmptyCatchFunction(argBool);
} else {
return false;
}
break;
case OPTION_COMPILER_OPT_INSTRUCTIONE_COMBINE: case OPTION_COMPILER_OPT_INSTRUCTIONE_COMBINE:
ret = ParseBoolParam(&argBool); ret = ParseBoolParam(&argBool);
if (ret) { if (ret) {

View File

@ -26,6 +26,11 @@
#include "ecmascript/mem/mem_common.h" #include "ecmascript/mem/mem_common.h"
#include "libpandabase/os/file.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 {
namespace panda::ecmascript { namespace panda::ecmascript {
using arg_list_t = std::vector<std::string>; using arg_list_t = std::vector<std::string>;
@ -210,6 +215,7 @@ enum CommandValues {
OPTION_COMPILER_OPT_STRING, OPTION_COMPILER_OPT_STRING,
OPTION_OPEN_ARK_TOOLS, OPTION_OPEN_ARK_TOOLS,
OPTION_COMPILER_OPT_FRAME_STATE_ELIMINATION, 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_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 static_assert(OPTION_SPLIT_TWO == 128); // add new option at the bottom, DO NOT modify this value
@ -1344,6 +1350,16 @@ public:
enableOptInlining_ = value; enableOptInlining_ = value;
} }
void SetEnableEmptyCatchFunction(bool value)
{
enableEmptyCatchFunction_ = value;
}
bool IsEnableEmptyCatchFunction() const
{
return enableEmptyCatchFunction_;
}
bool IsEnableOptInlining() const bool IsEnableOptInlining() const
{ {
return enableOptInlining_; return enableOptInlining_;
@ -1937,7 +1953,6 @@ public:
static constexpr int32_t MAX_APP_COMPILE_METHOD_SIZE = 4_KB; static constexpr int32_t MAX_APP_COMPILE_METHOD_SIZE = 4_KB;
private: private:
static constexpr int32_t DEFAULT_OPT_LEVEL = 3; // 3: default opt level
static bool StartsWith(const std::string& haystack, const std::string& needle) static bool StartsWith(const std::string& haystack, const std::string& needle)
{ {
@ -2033,6 +2048,7 @@ private:
bool enableInstrcutionCombine {true}; bool enableInstrcutionCombine {true};
bool enableNewValueNumbering_ {true}; bool enableNewValueNumbering_ {true};
bool enableOptInlining_ {true}; bool enableOptInlining_ {true};
bool enableEmptyCatchFunction_ {false};
bool enableOptPGOType_ {true}; bool enableOptPGOType_ {true};
bool enableFastJIT_ {false}; bool enableFastJIT_ {false};
bool enableAPPJIT_ {false}; bool enableAPPJIT_ {false};

View File

@ -13,3 +13,4 @@
Test Success Test Success
true true
false

View File

@ -13,3 +13,4 @@
Test Success Test Success
false false
false

View File

@ -29,3 +29,19 @@ function f3() {
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));

View File

@ -15,6 +15,7 @@ group("ark_jit_ts_test") {
testonly = true testonly = true
test_list = [ test_list = [
"create_arguments", "create_arguments",
"try_catch_empty",
"ldobjbyname", "ldobjbyname",
"for_loop", "for_loop",
"typed_array", "typed_array",

View 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 = []
}

View 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

View 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);

View File

@ -1220,7 +1220,7 @@ template("host_aot_js_test_action") {
script = "//arkcompiler/ets_runtime/script/run_ark_executable.py" script = "//arkcompiler/ets_runtime/script/run_ark_executable.py"
_aot_compile_options_ = " --aot-file=" + rebase_path(_test_aot_arg_) + _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) { if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
_aot_compile_options_ += " --compiler-pgo-profiler-path=" + _aot_compile_options_ += " --compiler-pgo-profiler-path=" +
@ -1493,7 +1493,8 @@ template("host_aot_js_test_action") {
" --compiler-opt-type-lowering=false" + " --compiler-opt-type-lowering=false" +
" --compiler-opt-inlining=false" + " --compiler-opt-inlining=false" +
" --compiler-opt-loop-peeling=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) { if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
_aot_compile_options_ += " --compiler-pgo-profiler-path=" + _aot_compile_options_ += " --compiler-pgo-profiler-path=" +
@ -1749,7 +1750,8 @@ template("host_aot_js_test_action") {
" --compiler-opt-inlining=false" + " --compiler-opt-inlining=false" +
" --compiler-opt-loop-peeling=false" + " --compiler-opt-loop-peeling=false" +
" --compiler-enable-litecg=true" + " --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) { if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
_aot_compile_options_ += " --compiler-pgo-profiler-path=" + _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" script = "//arkcompiler/ets_runtime/script/run_ark_executable.py"
_aot_compile_options_ = " --aot-file=" + rebase_path(_test_aot_arg_) + _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) { if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
_aot_compile_options_ += " --compiler-pgo-profiler-path=" + _aot_compile_options_ += " --compiler-pgo-profiler-path=" +
@ -2530,7 +2532,9 @@ template("host_aot_test_action") {
_aot_compile_options_ = _aot_compile_options_ =
" --aot-file=" + rebase_path(_test_aot_arg_) + " --log-level=" + " --aot-file=" + rebase_path(_test_aot_arg_) + " --log-level=" +
_test_aot_log_level + " --log-components=compiler" + _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) { if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
_aot_compile_options_ += _aot_compile_options_ +=
@ -2627,7 +2631,10 @@ template("host_aot_test_action") {
" --aot-file=" + rebase_path(_test_aot_arg_slowpath_) + " --aot-file=" + rebase_path(_test_aot_arg_slowpath_) +
" --log-level=" + _test_aot_log_level + " --log-components=compiler" + " --log-level=" + _test_aot_log_level + " --log-components=compiler" +
" --compiler-opt-type-lowering=false" + " --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) && if (defined(invoker.is_enable_trace_deopt) &&
invoker.is_enable_trace_deopt) { invoker.is_enable_trace_deopt) {
_aot_compile_options_ += " --compiler-trace-deopt=true" _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" + " --log-level=" + _test_aot_log_level + " --log-components=compiler" +
" --compiler-opt-inlining=false" + " --compiler-opt-inlining=false" +
" --compiler-opt-loop-peeling=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) { if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
_aot_compile_options_ += _aot_compile_options_ +=
@ -3047,7 +3055,8 @@ template("host_aot_test_action") {
" --compiler-opt-type-lowering=false" + " --compiler-opt-type-lowering=false" +
" --compiler-opt-inlining=false" + " --compiler-opt-inlining=false" +
" --compiler-opt-loop-peeling=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) && if (defined(invoker.is_enable_trace_deopt) &&
invoker.is_enable_trace_deopt) { invoker.is_enable_trace_deopt) {
_aot_compile_options_ += " --compiler-trace-deopt=true" _aot_compile_options_ += " --compiler-trace-deopt=true"
@ -3356,7 +3365,8 @@ template("host_aot_test_action") {
" --compiler-opt-inlining=false" + " --compiler-opt-inlining=false" +
" --compiler-opt-loop-peeling=false" + " --compiler-opt-loop-peeling=false" +
" --compiler-enable-litecg=true" + " --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) { if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
_aot_compile_options_ += _aot_compile_options_ +=
@ -3458,7 +3468,8 @@ template("host_aot_test_action") {
" --compiler-opt-inlining=false" + " --compiler-opt-inlining=false" +
" --compiler-opt-loop-peeling=false" + " --compiler-opt-loop-peeling=false" +
" --compiler-enable-litecg=true" + " --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) && if (defined(invoker.is_enable_trace_deopt) &&
invoker.is_enable_trace_deopt) { invoker.is_enable_trace_deopt) {
_aot_compile_options_ += " --compiler-trace-deopt=true" _aot_compile_options_ += " --compiler-trace-deopt=true"
@ -3872,7 +3883,9 @@ template("host_aot_assert_test_action") {
_aot_compile_options_ = _aot_compile_options_ =
" --aot-file=" + rebase_path(_test_aot_arg_) + " --log-level=" + " --aot-file=" + rebase_path(_test_aot_arg_) + " --log-level=" +
_test_aot_log_level + " --log-components=compiler" + _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) { if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
_aot_compile_options_ += " --compiler-pgo-profiler-path=" + _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_) + " --aot-file=" + rebase_path(_test_aot_arg_slowpath_) +
" --log-level=" + _test_aot_log_level + " --log-components=compiler" + " --log-level=" + _test_aot_log_level + " --log-components=compiler" +
" --compiler-opt-type-lowering=false" + " --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)) { if (defined(invoker.aot_log_option)) {
_aot_compile_options_ += 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" script = "//arkcompiler/ets_runtime/script/run_ark_executable.py"
_aot_compile_options_ = " --compiler-opt-type-lowering=false" + _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 # Pgo Option
_aot_compile_options_ += " --compiler-pgo-profiler-path=" + _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" script = "//arkcompiler/ets_runtime/script/run_ark_executable.py"
_aot_compile_options_ = _aot_compile_options_ = " --compiler-opt-type-lowering=false" +
" --compiler-opt-type-lowering=false" + " --compiler-opt-loop-peeling=false" +
" --compiler-opt-loop-peeling=false" + " --compiler-enable-litecg=true" " --compiler-enable-litecg=true" +
" --compiler-empty-catch-function=true"
# Pgo Option # Pgo Option
_aot_compile_options_ += " --compiler-pgo-profiler-path=" + _aot_compile_options_ += " --compiler-pgo-profiler-path=" +