mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-30 13:40:51 +00:00
Add type coverage statistics and partial compilation strategy based on coverage
1.Type infer will record gates which should be inferred and gates which are still any type after infer 2.Methods whose type coverage is lower than threshold will be stopped after type infer issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I6BPRC Signed-off-by: lijincheng <lijincheng13@huawei.com>
This commit is contained in:
parent
95c3bf8b8e
commit
1da20bdc7f
@ -196,25 +196,63 @@ public:
|
||||
|
||||
bool IsPGO() const
|
||||
{
|
||||
return isPgoMarked_;
|
||||
return CompileStateBit::PGOBit::Decode(compileState_.value_);
|
||||
}
|
||||
|
||||
void SetIsPGO(bool pgoMark)
|
||||
{
|
||||
isPgoMarked_ = pgoMark;
|
||||
CompileStateBit::PGOBit::Set<uint8_t>(pgoMark, &compileState_.value_);
|
||||
}
|
||||
|
||||
bool IsCompiled() const
|
||||
{
|
||||
return isCompiled_;
|
||||
return CompileStateBit::CompiledBit::Decode(compileState_.value_);
|
||||
}
|
||||
|
||||
void SetIsCompiled(bool isCompiled)
|
||||
{
|
||||
isCompiled_ = isCompiled;
|
||||
CompileStateBit::CompiledBit::Set<uint8_t>(isCompiled, &compileState_.value_);
|
||||
}
|
||||
|
||||
bool IsTypeInferAbort() const
|
||||
{
|
||||
return CompileStateBit::TypeInferAbortBit::Decode(compileState_.value_);
|
||||
}
|
||||
|
||||
void SetTypeInferAbort(bool halfCompiled)
|
||||
{
|
||||
CompileStateBit::TypeInferAbortBit::Set<uint8_t>(halfCompiled, &compileState_.value_);
|
||||
}
|
||||
|
||||
bool IsResolvedMethod() const
|
||||
{
|
||||
return CompileStateBit::ResolvedMethodBit::Decode(compileState_.value_);
|
||||
}
|
||||
|
||||
void SetResolvedMethod(bool isDeoptResolveNeed)
|
||||
{
|
||||
CompileStateBit::ResolvedMethodBit::Set<uint8_t>(isDeoptResolveNeed, &compileState_.value_);
|
||||
}
|
||||
|
||||
private:
|
||||
class CompileStateBit {
|
||||
public:
|
||||
explicit CompileStateBit(uint8_t value) : value_(value) {}
|
||||
CompileStateBit() = default;
|
||||
~CompileStateBit() = default;
|
||||
DEFAULT_COPY_SEMANTIC(CompileStateBit);
|
||||
DEFAULT_MOVE_SEMANTIC(CompileStateBit);
|
||||
|
||||
static constexpr size_t BOOL_FLAG_BIT_LENGTH = 1;
|
||||
using PGOBit = panda::BitField<bool, 0, BOOL_FLAG_BIT_LENGTH>;
|
||||
using CompiledBit = PGOBit::NextField<bool, BOOL_FLAG_BIT_LENGTH>;
|
||||
using TypeInferAbortBit = CompiledBit::NextField<bool, BOOL_FLAG_BIT_LENGTH>;
|
||||
using ResolvedMethodBit = TypeInferAbortBit::NextField<bool, BOOL_FLAG_BIT_LENGTH>;
|
||||
|
||||
private:
|
||||
uint8_t value_ {0};
|
||||
friend class MethodInfo;
|
||||
};
|
||||
// used to record the index of the current MethodInfo to speed up the lookup of lexEnv
|
||||
uint32_t methodInfoIndex_ { 0 };
|
||||
// used to obtain MethodPcInfo from the vector methodPcInfos of struct BCInfo
|
||||
@ -224,8 +262,7 @@ private:
|
||||
uint32_t outerMethodOffset_ { MethodInfo::DEFAULT_OUTMETHOD_OFFSET };
|
||||
uint32_t numOfLexVars_ { 0 };
|
||||
LexicalEnvStatus status_ { LexicalEnvStatus::VIRTUAL_LEXENV };
|
||||
bool isPgoMarked_ {false};
|
||||
bool isCompiled_ {false};
|
||||
CompileStateBit compileState_ { 0 };
|
||||
};
|
||||
|
||||
|
||||
|
@ -38,7 +38,9 @@ public:
|
||||
|
||||
void UpdateCompileQueue(const CString &recordName, EntityId resolvedMethod)
|
||||
{
|
||||
if (pfLoader_.Match(recordName, resolvedMethod)) {
|
||||
const auto &methodList = bytecodeInfo_.GetMethodList();
|
||||
auto &resolvedMethodInfo = methodList.at(resolvedMethod.GetOffset());
|
||||
if (pfLoader_.Match(recordName, resolvedMethod) && !resolvedMethodInfo.IsTypeInferAbort()) {
|
||||
return;
|
||||
}
|
||||
// update profile and update compile queue
|
||||
@ -88,7 +90,12 @@ public:
|
||||
if (!methodInfo.IsCompiled()) {
|
||||
methodInfo.SetIsCompiled(true);
|
||||
cb(bytecodeInfo_.GetRecordName(index), methodName, methodLiteral, compilingMethod,
|
||||
methodPcInfo, methodInfo.GetMethodInfoIndex());
|
||||
methodPcInfo, methodInfo);
|
||||
} else if (NeedSecondaryCompile(methodInfo)) {
|
||||
// if a method used to be not full compiled but now it's a deopt resolved method
|
||||
// it should be full compiled again
|
||||
cb(bytecodeInfo_.GetRecordName(index), methodName, methodLiteral, compilingMethod,
|
||||
methodPcInfo, methodInfo);
|
||||
}
|
||||
}
|
||||
auto &innerMethods = methodInfo.GetInnerMethods();
|
||||
@ -106,6 +113,9 @@ public:
|
||||
return;
|
||||
}
|
||||
uint32_t resolvedMethod = bytecodeInfo_.GetDefineMethod(classLiteralOffset);
|
||||
auto &methodList = bytecodeInfo_.GetMethodList();
|
||||
auto &methodInfo = methodList.at(resolvedMethod);
|
||||
methodInfo.SetResolvedMethod(true);
|
||||
panda_file::File::EntityId resolvedMethodId(resolvedMethod);
|
||||
UpdateCompileQueue(recordName, resolvedMethodId);
|
||||
}
|
||||
@ -114,6 +124,11 @@ private:
|
||||
|
||||
void InitializeCompileQueue();
|
||||
|
||||
bool NeedSecondaryCompile(const MethodInfo &methodInfo) const
|
||||
{
|
||||
return methodInfo.IsTypeInferAbort() && methodInfo.IsResolvedMethod();
|
||||
}
|
||||
|
||||
void SearchForCompilation(const std::unordered_set<EntityId> &methodSet, std::unordered_set<EntityId> &newMethodSet,
|
||||
uint32_t mainMethodOffset, bool needUpdateCompile)
|
||||
{
|
||||
@ -132,7 +147,7 @@ private:
|
||||
auto &methodInfo = methodList.at(methodOffset);
|
||||
auto outMethodOffset = methodInfo.GetOutMethodOffset();
|
||||
// if current method has already been marked as PGO, stop searching upper layer of the define chain
|
||||
if (methodInfo.IsPGO()) {
|
||||
if (methodInfo.IsPGO() && !methodInfo.IsTypeInferAbort()) {
|
||||
return;
|
||||
}
|
||||
// we need to collect these new-marked PGO methods to update PGO profile
|
||||
@ -152,6 +167,7 @@ private:
|
||||
auto outMethodInfo = methodList.at(outMethodOffset);
|
||||
if (outMethodInfo.IsPGO()) {
|
||||
compileQueue_.push(methodOffset);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// if current searched method is an un-marked main method, just push it to compile queue
|
||||
|
@ -34,7 +34,7 @@ CompilerLog::CompilerLog(const std::string &logOpt, bool TraceBC)
|
||||
traceBc_ = TraceBC;
|
||||
}
|
||||
|
||||
void CompilerLog::SetMethodLog(const std::string &fileName, const CString& recordName,
|
||||
void CompilerLog::SetMethodLog(const std::string &fileName,
|
||||
const std::string &methodName, AotMethodLogList *logList)
|
||||
{
|
||||
bool enableMethodLog = !NoneMethod();
|
||||
@ -42,7 +42,6 @@ void CompilerLog::SetMethodLog(const std::string &fileName, const CString& recor
|
||||
enableMethodLog = logList->IncludesMethod(fileName, methodName);
|
||||
}
|
||||
SetEnableMethodLog(enableMethodLog);
|
||||
AddCompiledMethod(methodName, recordName);
|
||||
}
|
||||
|
||||
bool MethodLogList::IncludesMethod(const std::string &methodName) const
|
||||
|
@ -102,8 +102,9 @@ public:
|
||||
return GetEnableMethodLog() && OutputCIR();
|
||||
}
|
||||
|
||||
void SetMethodLog(const std::string &fileName, const CString& recordName,
|
||||
void SetMethodLog(const std::string &fileName,
|
||||
const std::string &methodName, AotMethodLogList *logList);
|
||||
void AddCompiledMethod(const std::string& name, const CString& recordName);
|
||||
void Print() const;
|
||||
void AddMethodTime(const std::string& name, uint32_t id, double time);
|
||||
void AddPassTime(const std::string& name, double time);
|
||||
@ -125,7 +126,6 @@ private:
|
||||
void PrintMethodTime() const;
|
||||
void PrintTime() const;
|
||||
void PrintCompiledMethod() const;
|
||||
void AddCompiledMethod(const std::string& name, const CString& recordName);
|
||||
|
||||
int idx_ {0};
|
||||
bool allMethod_ {false};
|
||||
|
@ -36,12 +36,12 @@ class PassInfo;
|
||||
class PassData {
|
||||
public:
|
||||
PassData(BytecodeCircuitBuilder *builder, Circuit *circuit, PassInfo *info, CompilerLog *log,
|
||||
std::string methodName, size_t methodInfoIndex = 0, bool hasTypes = false,
|
||||
std::string methodName, MethodInfo *methodInfo = nullptr, bool hasTypes = false,
|
||||
const CString &recordName = "", MethodLiteral *methodLiteral = nullptr,
|
||||
uint32_t methodOffset = 0, NativeAreaAllocator *allocator = nullptr)
|
||||
: builder_(builder), circuit_(circuit), info_(info), log_(log), methodName_(methodName),
|
||||
methodInfoIndex_(methodInfoIndex), hasTypes_(hasTypes), recordName_(recordName),
|
||||
methodLiteral_(methodLiteral), methodOffset_(methodOffset), allocator_(allocator)
|
||||
methodInfo_(methodInfo), hasTypes_(hasTypes), recordName_(recordName), methodLiteral_(methodLiteral),
|
||||
methodOffset_(methodOffset), allocator_(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
@ -112,9 +112,14 @@ public:
|
||||
return methodOffset_;
|
||||
}
|
||||
|
||||
MethodInfo* GetMethodInfo() const
|
||||
{
|
||||
return methodInfo_;
|
||||
}
|
||||
|
||||
size_t GetMethodInfoIndex() const
|
||||
{
|
||||
return methodInfoIndex_;
|
||||
return methodInfo_->GetMethodInfoIndex();
|
||||
}
|
||||
|
||||
bool HasTypes() const
|
||||
@ -132,6 +137,31 @@ public:
|
||||
return allocator_;
|
||||
}
|
||||
|
||||
bool IsTypeAbort() const
|
||||
{
|
||||
if (hasTypes_) {
|
||||
// A ts method which has low type percent and not marked as a resolved method
|
||||
// should be skipped from full compilation.
|
||||
if (methodInfo_->IsTypeInferAbort() && !methodInfo_->IsResolvedMethod()) {
|
||||
info_->GetBytecodeInfo().AddSkippedMethod(methodOffset_);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// For js method, type infer pass will be skipped and it don't have a type percent.
|
||||
// If we set an non zero type threshold, js method will be skipped from full compilation.
|
||||
// The default Type threshold is -1.
|
||||
if (info_->GetTSManager()->GetTypeThreshold() >= 0) {
|
||||
info_->GetBytecodeInfo().AddSkippedMethod(methodOffset_);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// when a method will be full compiled, we should confirm its TypeInferAbortBit to be false
|
||||
// maybe it used to be true in the first round of compilation.
|
||||
methodInfo_->SetTypeInferAbort(false);
|
||||
log_->AddCompiledMethod(methodName_, recordName_);
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
BytecodeCircuitBuilder *builder_ {nullptr};
|
||||
Circuit *circuit_ {nullptr};
|
||||
@ -139,7 +169,7 @@ private:
|
||||
PassInfo *info_ {nullptr};
|
||||
CompilerLog *log_ {nullptr};
|
||||
std::string methodName_;
|
||||
size_t methodInfoIndex_;
|
||||
MethodInfo *methodInfo_ {nullptr};
|
||||
bool hasTypes_;
|
||||
const CString &recordName_;
|
||||
MethodLiteral *methodLiteral_ {nullptr};
|
||||
@ -171,7 +201,7 @@ public:
|
||||
if (data->HasTypes()) {
|
||||
bool enableLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType();
|
||||
TypeInfer typeInfer(data->GetBuilder(), data->GetCircuit(), data->GetInfo(), data->GetMethodInfoIndex(),
|
||||
enableLog, data->GetMethodName(), data->GetRecordName());
|
||||
enableLog, data->GetMethodName(), data->GetRecordName(), data->GetMethodInfo());
|
||||
typeInfer.TraverseCircuit();
|
||||
}
|
||||
return true;
|
||||
|
@ -68,14 +68,14 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat
|
||||
|
||||
cmpDriver.Run([this, &fileName, &info]
|
||||
(const CString recordName, const std::string &methodName, MethodLiteral *methodLiteral,
|
||||
uint32_t methodOffset, const MethodPcInfo &methodPCInfo, size_t methodInfoIndex) {
|
||||
uint32_t methodOffset, const MethodPcInfo &methodPCInfo, MethodInfo &methodInfo) {
|
||||
auto jsPandaFile = info.GetJSPandaFile();
|
||||
auto cmpCfg = info.GetCompilerConfig();
|
||||
auto tsManager = info.GetTSManager();
|
||||
// note: TSManager need to set current constantpool before all pass
|
||||
tsManager->SetCurConstantPool(jsPandaFile, methodOffset);
|
||||
|
||||
log_->SetMethodLog(fileName, recordName, methodName, logList_);
|
||||
log_->SetMethodLog(fileName, methodName, logList_);
|
||||
|
||||
std::string fullName = methodName + "@" + fileName;
|
||||
bool enableMethodLog = log_->GetEnableMethodLog();
|
||||
@ -99,12 +99,15 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat
|
||||
}
|
||||
|
||||
PassData data(&builder, &circuit, &info, log_, fullName,
|
||||
methodInfoIndex, hasTypes, recordName,
|
||||
&methodInfo, hasTypes, recordName,
|
||||
methodLiteral, methodOffset, vm_->GetNativeAreaAllocator());
|
||||
PassRunner<PassData> pipeline(&data);
|
||||
if (EnableTypeInfer()) {
|
||||
pipeline.RunPass<TypeInferPass>();
|
||||
}
|
||||
if (data.IsTypeAbort()) {
|
||||
return;
|
||||
}
|
||||
pipeline.RunPass<AsyncFunctionLoweringPass>();
|
||||
if (EnableTypeLowering()) {
|
||||
pipeline.RunPass<TSTypeLoweringPass>();
|
||||
|
@ -104,7 +104,8 @@ public:
|
||||
CompilerLog *log, AotMethodLogList *logList, size_t maxAotMethodSize, bool enableTypeLowering,
|
||||
const std::string &profIn, uint32_t hotnessThreshold)
|
||||
: vm_(vm), entry_(entry), triple_(triple), optLevel_(optLevel), relocMode_(relocMode), log_(log),
|
||||
logList_(logList), maxAotMethodSize_(maxAotMethodSize), enableTypeLowering_(enableTypeLowering),
|
||||
logList_(logList), maxAotMethodSize_(maxAotMethodSize),
|
||||
enableTypeLowering_(enableTypeLowering),
|
||||
enableTypeInfer_(enableTypeLowering || vm_->GetTSManager()->AssertTypes()),
|
||||
profilerLoader_(profIn, hotnessThreshold) {};
|
||||
PassManager() = default;
|
||||
|
@ -162,7 +162,7 @@ void TSInlineLowering::InlineCall(MethodInfo &methodInfo, MethodPcInfo &methodPC
|
||||
}
|
||||
|
||||
PassData data(&builder, circuit_, info_, log, fullName,
|
||||
methodInfo.GetMethodInfoIndex(), hasTyps, recordName,
|
||||
&methodInfo, hasTyps, recordName,
|
||||
method, method->GetMethodId().GetOffset());
|
||||
PassRunner<PassData> pipeline(&data);
|
||||
pipeline.RunPass<TypeInferPass>();
|
||||
|
@ -42,6 +42,8 @@ void TypeInfer::TraverseCircuit()
|
||||
PrintAllByteCodesTypes();
|
||||
}
|
||||
|
||||
VerifyTypePercent();
|
||||
|
||||
if (tsManager_->AssertTypes()) {
|
||||
Verify();
|
||||
}
|
||||
@ -113,7 +115,7 @@ void TypeInfer::UpdateQueueForLoopPhi()
|
||||
bool TypeInfer::UpdateType(GateRef gate, const GateType type, bool savePreType)
|
||||
{
|
||||
GateType preType = gateAccessor_.GetGateType(gate);
|
||||
|
||||
needInferGates_.insert(gate);
|
||||
// When the type after type inference is any and you want to save previous type, it wolud not update.
|
||||
if (savePreType && type.IsAnyType()) {
|
||||
return false;
|
||||
@ -159,7 +161,8 @@ bool TypeInfer::ShouldInfer(const GateRef gate) const
|
||||
* panda::ecmascript::kungfu::LexEnv which are created during the building of IR. So in the type inference,
|
||||
* newlexenv is ignored.
|
||||
*/
|
||||
if (opcode != OpCode::CONSTANT && opcode != OpCode::RETURN && opcode != OpCode::JS_BYTECODE) {
|
||||
if (opcode != OpCode::CONSTANT && opcode != OpCode::CONST_DATA &&
|
||||
opcode != OpCode::RETURN && opcode != OpCode::JS_BYTECODE) {
|
||||
return false;
|
||||
}
|
||||
if (jsgateToBytecode_.find(gate) == jsgateToBytecode_.end()) {
|
||||
@ -587,7 +590,7 @@ bool TypeInfer::InferLdObjByIndex(GateRef gate)
|
||||
auto type = GetPropType(inValueType, key);
|
||||
return UpdateType(gate, type);
|
||||
}
|
||||
return false;
|
||||
return UpdateType(gate, GateType::AnyType());
|
||||
}
|
||||
|
||||
bool TypeInfer::SetStGlobalBcType(GateRef gate, bool hasIC)
|
||||
@ -627,7 +630,7 @@ bool TypeInfer::InferLdGlobalVar(GateRef gate)
|
||||
if (iter != stringIdToGateType_.end()) {
|
||||
return UpdateType(gate, iter->second);
|
||||
}
|
||||
return false;
|
||||
return UpdateType(gate, GateType::AnyType());
|
||||
}
|
||||
|
||||
bool TypeInfer::InferReturnUndefined(GateRef gate)
|
||||
@ -649,7 +652,7 @@ bool TypeInfer::InferLdObjByName(GateRef gate)
|
||||
ASSERT(gateAccessor_.GetNumValueIn(gate) == 3);
|
||||
auto objType = gateAccessor_.GetGateType(gateAccessor_.GetValueIn(gate, 2)); // 2: the third parameter is receiver
|
||||
if (objType.IsAnyType()) {
|
||||
return false;
|
||||
return UpdateType(gate, GateType::AnyType());
|
||||
}
|
||||
|
||||
if (ShouldConvertToBuiltinArray(objType)) {
|
||||
@ -669,7 +672,7 @@ bool TypeInfer::InferLdObjByName(GateRef gate)
|
||||
uint16_t index = gateAccessor_.GetConstDataId(gateAccessor_.GetValueIn(gate, 1)).GetId();
|
||||
return GetObjPropWithName(gate, objType, index);
|
||||
}
|
||||
return false;
|
||||
return UpdateType(gate, GateType::AnyType());
|
||||
}
|
||||
|
||||
bool TypeInfer::InferNewObject(GateRef gate)
|
||||
@ -683,7 +686,7 @@ bool TypeInfer::InferNewObject(GateRef gate)
|
||||
return UpdateType(gate, classInstanceType);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return UpdateType(gate, GateType::AnyType());
|
||||
}
|
||||
|
||||
bool TypeInfer::InferLdStr(GateRef gate)
|
||||
@ -755,7 +758,7 @@ bool TypeInfer::InferCallFunction(GateRef gate)
|
||||
// For simplicity, calling and constructing are considered equivalent.
|
||||
return UpdateType(gate, tsManager_->CreateClassInstanceType(funcType));
|
||||
}
|
||||
return false;
|
||||
return UpdateType(gate, GateType::AnyType());
|
||||
}
|
||||
|
||||
bool TypeInfer::InferLdObjByValue(GateRef gate)
|
||||
@ -780,7 +783,7 @@ bool TypeInfer::InferLdObjByValue(GateRef gate)
|
||||
return GetObjPropWithName(gate, objType, index);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return UpdateType(gate, GateType::AnyType());
|
||||
}
|
||||
|
||||
bool TypeInfer::InferGetNextPropName(GateRef gate)
|
||||
@ -805,7 +808,7 @@ bool TypeInfer::InferSuperCall(GateRef gate)
|
||||
auto classInstanceType = tsManager_->CreateClassInstanceType(classType);
|
||||
return UpdateType(gate, classInstanceType);
|
||||
}
|
||||
return false;
|
||||
return UpdateType(gate, GateType::AnyType());
|
||||
}
|
||||
|
||||
bool TypeInfer::InferSuperPropertyByName(GateRef gate)
|
||||
@ -827,7 +830,7 @@ bool TypeInfer::InferSuperPropertyByValue(GateRef gate)
|
||||
|
||||
return GetSuperProp(gate, index, false);
|
||||
}
|
||||
return false;
|
||||
return UpdateType(gate, GateType::AnyType());
|
||||
}
|
||||
|
||||
bool TypeInfer::GetSuperProp(GateRef gate, uint64_t index, bool isString)
|
||||
@ -852,7 +855,7 @@ bool TypeInfer::GetSuperProp(GateRef gate, uint64_t index, bool isString)
|
||||
}
|
||||
return UpdateType(gate, type);
|
||||
}
|
||||
return false;
|
||||
return UpdateType(gate, GateType::AnyType());
|
||||
}
|
||||
|
||||
bool TypeInfer::InferGetIterator(GateRef gate)
|
||||
@ -866,7 +869,7 @@ bool TypeInfer::InferGetIterator(GateRef gate)
|
||||
} else if (inValueType.IsStringType()) {
|
||||
elementGt.SetType(GateType::StringType().Value());
|
||||
} else {
|
||||
return false;
|
||||
return UpdateType(gate, GateType::AnyType());
|
||||
}
|
||||
GlobalTSTypeRef iteratorInstanceType = tsManager_->GetOrCreateTSIteratorInstanceType(
|
||||
TSRuntimeType::ITERATOR, elementGt);
|
||||
@ -883,7 +886,7 @@ bool TypeInfer::InferTryLdGlobalByName(GateRef gate)
|
||||
if (iter != stringIdToGateType_.end()) {
|
||||
return UpdateType(gate, iter->second);
|
||||
}
|
||||
return false;
|
||||
return UpdateType(gate, GateType::AnyType());
|
||||
}
|
||||
|
||||
bool TypeInfer::InferLdLexVarDyn(GateRef gate)
|
||||
@ -1168,4 +1171,31 @@ std::string TypeInfer::CollectGateTypeLogInfo(GateRef gate, DebugInfoExtractor *
|
||||
log += "\n[compiler] ";
|
||||
return log;
|
||||
}
|
||||
|
||||
void TypeInfer::VerifyTypePercent()
|
||||
{
|
||||
shouldInferNum_ = needInferGates_.size();
|
||||
for (auto gate : needInferGates_) {
|
||||
if (!gateAccessor_.GetGateType(gate).IsAnyType()) {
|
||||
normalInferNum_++;
|
||||
}
|
||||
}
|
||||
double rate = (double)normalInferNum_ / (double)shouldInferNum_;
|
||||
auto typeThreshold = tsManager_->GetTypeThreshold();
|
||||
if (rate <= typeThreshold) {
|
||||
methodInfo_->SetTypeInferAbort(true);
|
||||
}
|
||||
if (IsLogEnabled()) {
|
||||
LOG_COMPILER(INFO) << "";
|
||||
LOG_COMPILER(INFO) << "[TypeCoverage] print method type coverage: \n"
|
||||
<< "[compiler] [TypeCoverage] [ShouldInferedGate]: " << shouldInferNum_
|
||||
<< " || [NormalInferedGate]: " << normalInferNum_ << "\n"
|
||||
<< "[compiler] [TypeCoverage] [TypeCoverage Percentage]: "
|
||||
<< std::fixed << std::setprecision(PERCENT_LENS) << rate * HUNDRED_TIME << "%";
|
||||
if (rate <= typeThreshold) {
|
||||
LOG_COMPILER(INFO) << "[TypeCoverage] TypeCoverage Percentage is lower than threshold: ["
|
||||
<< typeThreshold << "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -37,13 +37,15 @@ class TypeInfer {
|
||||
public:
|
||||
TypeInfer(BytecodeCircuitBuilder *builder, Circuit *circuit,
|
||||
PassInfo *info, size_t methodId, bool enableLog,
|
||||
const std::string& name, const CString &recordName)
|
||||
const std::string &name, const CString &recordName,
|
||||
MethodInfo *methodInfo)
|
||||
: builder_(builder), circuit_(circuit),
|
||||
gateAccessor_(circuit),
|
||||
tsManager_(info->GetTSManager()),
|
||||
lexEnvManager_(info->GetLexEnvManager()),
|
||||
methodId_(methodId), enableLog_(enableLog),
|
||||
methodName_(name), recordName_(recordName),
|
||||
methodInfo_(methodInfo),
|
||||
inQueue_(circuit_->GetGateCount(), true)
|
||||
{
|
||||
}
|
||||
@ -66,6 +68,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr int PERCENT_LENS = 2;
|
||||
static constexpr int HUNDRED_TIME = 100;
|
||||
|
||||
// savePreType: save the previous type, which is true by default
|
||||
bool UpdateType(GateRef gate, const GateType type, bool savePreType = true);
|
||||
bool UpdateType(GateRef gate, const GlobalTSTypeRef &typeRef, bool savePreType = true);
|
||||
@ -148,6 +153,7 @@ private:
|
||||
|
||||
void PrintAllByteCodesTypes() const;
|
||||
void Verify() const;
|
||||
void VerifyTypePercent();
|
||||
void TypeCheck(GateRef gate) const;
|
||||
void FilterAnyTypeGates() const;
|
||||
|
||||
@ -177,7 +183,11 @@ private:
|
||||
std::unordered_map<GateRef, uint32_t> jsgateToBytecode_ {};
|
||||
std::map<GateRef, InferState> loopPhiState_ {};
|
||||
const CString &recordName_;
|
||||
size_t shouldInferNum_ {0};
|
||||
size_t normalInferNum_ {0};
|
||||
MethodInfo *methodInfo_ {nullptr};
|
||||
std::vector<bool> inQueue_;
|
||||
std::unordered_set<GateRef> needInferGates_ {};
|
||||
std::queue<GateRef> pendingQueue_ {};
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -60,6 +60,7 @@ const std::string PUBLIC_API HELP_OPTION_MSG =
|
||||
" Default: 'none'\n"
|
||||
"--compiler-log-methods: Specific method list for compiler log, only used when compiler-log."
|
||||
"Default: 'none'\n"
|
||||
"--compiler-type-threshold: enable to skip methods whose type coverage is no more than threshold.. Default: -1\n"
|
||||
"--compiler-log-snapshot: Enable to print snapshot information. Default: 'false'\n"
|
||||
"--compiler-log-time: Enable to print pass compiler time. Default: 'false'\n"
|
||||
"--enable-ark-tools: Enable ark tools to debug. Default: 'false'\n"
|
||||
@ -133,6 +134,7 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
|
||||
{"compiler-log-methods", required_argument, nullptr, OPTION_COMPILER_LOG_METHODS},
|
||||
{"compiler-log-snapshot", required_argument, nullptr, OPTION_COMPILER_LOG_SNAPSHOT},
|
||||
{"compiler-log-time", required_argument, nullptr, OPTION_COMPILER_LOG_TIME},
|
||||
{"compiler-type-threshold", required_argument, nullptr, OPTION_COMPILER_TYPE_THRESHOLD},
|
||||
{"enable-ark-tools", required_argument, nullptr, OPTION_ENABLE_ARK_TOOLS},
|
||||
{"trace-bc", required_argument, nullptr, OPTION_TRACE_BC},
|
||||
{"trace-deopt", required_argument, nullptr, OPTION_TRACE_DEOPT},
|
||||
@ -183,6 +185,7 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
|
||||
uint32_t argUint32 = 0;
|
||||
int argInt = 0;
|
||||
bool argBool = false;
|
||||
double argDouble = 0.0;
|
||||
static std::string COLON = ":";
|
||||
|
||||
if (argc <= 1) {
|
||||
@ -404,6 +407,14 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPTION_COMPILER_TYPE_THRESHOLD:
|
||||
ret = ParseDoubleParam("compiler-type-threshold", &argDouble);
|
||||
if (ret) {
|
||||
SetTypeThreshold(argDouble);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPTION_MAX_NONMOVABLE_SPACE_CAPACITY:
|
||||
ret = ParseUint32Param("maxNonmovableSpaceCapacity", &argUint32);
|
||||
if (ret) {
|
||||
@ -544,7 +555,18 @@ bool JSRuntimeOptions::ParseBoolParam(bool* argBool)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSRuntimeOptions::ParseIntParam(const std::string &option, int* argInt)
|
||||
bool JSRuntimeOptions::ParseDoubleParam(const std::string &option, double *argDouble)
|
||||
{
|
||||
*argDouble = std::stod(optarg, nullptr);
|
||||
if (errno == ERANGE) {
|
||||
std::cerr << "getopt: \"" << option << "\" argument has invalid parameter value \""
|
||||
<< optarg <<"\"\n" << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSRuntimeOptions::ParseIntParam(const std::string &option, int *argInt)
|
||||
{
|
||||
if (StartsWith(optarg, "0x")) {
|
||||
const int HEX = 16;
|
||||
@ -554,7 +576,7 @@ bool JSRuntimeOptions::ParseIntParam(const std::string &option, int* argInt)
|
||||
}
|
||||
|
||||
if (errno == ERANGE) {
|
||||
std::cerr << "getopt: \"" << option <<"\" argument has invalid parameter value \""
|
||||
std::cerr << "getopt: \"" << option << "\" argument has invalid parameter value \""
|
||||
<< optarg <<"\"\n" << std::endl;
|
||||
return false;
|
||||
}
|
||||
@ -572,7 +594,7 @@ bool JSRuntimeOptions::ParseUint32Param(const std::string &option, uint32_t *arg
|
||||
}
|
||||
|
||||
if (errno == ERANGE) {
|
||||
std::cerr << "getopt: \"" << option <<"\" argument has invalid parameter value \""
|
||||
std::cerr << "getopt: \"" << option << "\" argument has invalid parameter value \""
|
||||
<< optarg <<"\"\n" << std::endl;
|
||||
return false;
|
||||
}
|
||||
@ -590,7 +612,7 @@ bool JSRuntimeOptions::ParseUint64Param(const std::string &option, uint64_t *arg
|
||||
}
|
||||
|
||||
if (errno == ERANGE) {
|
||||
std::cerr << "getopt: \"" << option <<"\" argument has invalid parameter value \""
|
||||
std::cerr << "getopt: \"" << option << "\" argument has invalid parameter value \""
|
||||
<< optarg <<"\"\n" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
@ -82,6 +82,7 @@ enum CommandValues {
|
||||
OPTION_STARTUP_TIME,
|
||||
OPTION_COMPILER_LOG_OPT,
|
||||
OPTION_COMPILER_LOG_METHODS,
|
||||
OPTION_COMPILER_TYPE_THRESHOLD,
|
||||
OPTION_ENABLE_RUNTIME_STAT,
|
||||
OPTION_ASSERT_TYPES,
|
||||
OPTION_PRINT_ANY_TYPES,
|
||||
@ -749,6 +750,16 @@ public:
|
||||
maxAotMethodSize_ = value;
|
||||
}
|
||||
|
||||
double GetTypeThreshold() const
|
||||
{
|
||||
return typeThreshold_;
|
||||
}
|
||||
|
||||
void SetTypeThreshold(double threshold)
|
||||
{
|
||||
typeThreshold_ = threshold;
|
||||
}
|
||||
|
||||
std::string GetEntryPoint() const
|
||||
{
|
||||
return entryPoint_;
|
||||
@ -870,6 +881,7 @@ private:
|
||||
}
|
||||
|
||||
bool ParseBoolParam(bool* argBool);
|
||||
bool ParseDoubleParam(const std::string &option, double* argDouble);
|
||||
bool ParseIntParam(const std::string &option, int* argInt);
|
||||
bool ParseUint32Param(const std::string &option, uint32_t *argUInt32);
|
||||
bool ParseUint64Param(const std::string &option, uint64_t *argUInt64);
|
||||
@ -915,6 +927,7 @@ private:
|
||||
arg_list_t logComponents_ {{"all"}};
|
||||
bool enableAOT_ {false};
|
||||
uint32_t maxAotMethodSize_ {32_KB};
|
||||
double typeThreshold_ {-1};
|
||||
std::string entryPoint_ {"_GLOBAL::func_main_0"};
|
||||
bool mergeAbc_ {false};
|
||||
bool enableTypeLowering_ {true};
|
||||
|
@ -23,7 +23,8 @@
|
||||
namespace panda::ecmascript {
|
||||
TSManager::TSManager(EcmaVM *vm) : vm_(vm), thread_(vm_->GetJSThread()), factory_(vm_->GetFactory()),
|
||||
assertTypes_(vm_->GetJSOptions().AssertTypes()),
|
||||
printAnyTypes_(vm_->GetJSOptions().PrintAnyTypes())
|
||||
printAnyTypes_(vm_->GetJSOptions().PrintAnyTypes()),
|
||||
typeThreshold_(vm_->GetJSOptions().GetTypeThreshold())
|
||||
{
|
||||
JSHandle<TSModuleTable> mTable = factory_->NewTSModuleTable(TSModuleTable::DEFAULT_TABLE_CAPACITY);
|
||||
SetTSModuleTable(mTable);
|
||||
|
@ -352,6 +352,11 @@ public:
|
||||
return printAnyTypes_;
|
||||
}
|
||||
|
||||
double PUBLIC_API GetTypeThreshold() const
|
||||
{
|
||||
return typeThreshold_;
|
||||
}
|
||||
|
||||
bool IsBuiltinsDTSEnabled() const
|
||||
{
|
||||
return vm_->GetJSOptions().WasSetBuiltinsDTS();
|
||||
@ -730,6 +735,7 @@ private:
|
||||
std::map<GlobalTSTypeRef, IHClassData> gtIhcMap_ {};
|
||||
bool assertTypes_ {false};
|
||||
bool printAnyTypes_ {false};
|
||||
double typeThreshold_ {-1};
|
||||
|
||||
// when the passmanager iterates each method, the curCP_ and curCPID_ should be updated
|
||||
// so that subsequent passes (type_infer, ts_type_lowering) can obtain the correct constpool.
|
||||
|
Loading…
Reference in New Issue
Block a user