rebase pgo_type to master

Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I9EE0H
Signed-off-by: linxiang8 <linxiang8@huawei.com>
Change-Id: Iaaf1b480e4a6dbfaebafb5153fd9f3c3e1eefbd0
This commit is contained in:
linxiang8 2024-04-08 14:55:33 +08:00
parent 024e742dc7
commit 58abf70f8e
189 changed files with 2742 additions and 4158 deletions

View File

@ -1580,7 +1580,7 @@ void Builtins::InitializeJson(const JSHandle<GlobalEnv> &env, const JSHandle<JST
JSHandle<JSObject> jsonObject = factory_->NewJSObjectWithInit(jsonHClass);
SetFunction(env, jsonObject, "parse", Json::Parse, FunctionLength::TWO);
SetFunction(env, jsonObject, "stringify", Json::Stringify, FunctionLength::THREE, BUILTINS_STUB_ID(STRINGIFY));
SetFunction(env, jsonObject, "stringify", Json::Stringify, FunctionLength::THREE, BUILTINS_STUB_ID(JsonStringify));
PropertyDescriptor jsonDesc(thread_, JSHandle<JSTaggedValue>::Cast(jsonObject), true, false, true);
JSHandle<JSTaggedValue> jsonString(factory_->NewFromASCII("JSON"));
@ -1656,7 +1656,7 @@ void Builtins::InitializeStringIterator(const JSHandle<GlobalEnv> &env,
strIterFuncInstanceHClass.GetTaggedValue());
SetFunction(env, strIterPrototype, "next", StringIterator::Next, FunctionLength::ZERO,
BUILTINS_STUB_ID(STRING_ITERATOR_PROTO_NEXT));
BUILTINS_STUB_ID(StringIteratorProtoNext));
SetStringTagSymbol(env, strIterPrototype, "String Iterator");
env->SetStringIterator(thread_, strIterFunction);
@ -1700,7 +1700,7 @@ void Builtins::InitializeIterator(const JSHandle<GlobalEnv> &env, const JSHandle
SetFunction(env, iteratorPrototype, "next", BuiltinsIterator::Next, FunctionLength::ONE);
// Iterator.prototype.return()
SetFunction(env, iteratorPrototype, "return", BuiltinsIterator::Return, FunctionLength::ONE,
BUILTINS_STUB_ID(ITERATOR_PROTO_RETURN));
BUILTINS_STUB_ID(IteratorProtoReturn));
// Iterator.prototype.throw()
SetFunction(env, iteratorPrototype, "throw", BuiltinsIterator::Throw, FunctionLength::ONE);
// %IteratorPrototype% [ @@iterator ]
@ -1791,7 +1791,7 @@ void Builtins::InitializeSetIterator(const JSHandle<GlobalEnv> &env,
JSHandle<JSObject> setIteratorPrototype(factory_->NewJSObjectWithInit(iteratorFuncClass));
// Iterator.prototype.next()
SetFunction(env, setIteratorPrototype, "next", JSSetIterator::Next, FunctionLength::ZERO,
BUILTINS_STUB_ID(SET_ITERATOR_PROTO_NEXT));
BUILTINS_STUB_ID(SetIteratorProtoNext));
SetStringTagSymbol(env, setIteratorPrototype, "Set Iterator");
env->SetSetIteratorPrototype(thread_, setIteratorPrototype);
JSHandle<JSTaggedValue> protoValue = env->GetSetIteratorPrototype();
@ -1823,7 +1823,7 @@ void Builtins::InitializeMapIterator(const JSHandle<GlobalEnv> &env,
JSHandle<JSObject> mapIteratorPrototype(factory_->NewJSObjectWithInit(iteratorFuncClass));
// Iterator.prototype.next()
SetFunction(env, mapIteratorPrototype, "next", JSMapIterator::Next, FunctionLength::ZERO,
BUILTINS_STUB_ID(MAP_ITERATOR_PROTO_NEXT));
BUILTINS_STUB_ID(MapIteratorProtoNext));
SetStringTagSymbol(env, mapIteratorPrototype, "Map Iterator");
env->SetMapIteratorPrototype(thread_, mapIteratorPrototype);
JSHandle<JSTaggedValue> protoValue = env->GetMapIteratorPrototype();
@ -1860,7 +1860,7 @@ void Builtins::InitializeArrayIterator(const JSHandle<GlobalEnv> &env,
JSHandle<JSHClass> arrayIteratorInstanceHClass(globalConst->GetHandledJSArrayIteratorClass());
// Iterator.prototype.next()
SetFunction(env, arrayIteratorPrototype, "next", JSArrayIterator::Next, FunctionLength::ZERO,
BUILTINS_STUB_ID(ARRAY_ITERATOR_PROTO_NEXT));
BUILTINS_STUB_ID(ArrayIteratorProtoNext));
arrayIteratorInstanceHClass->SetPrototype(thread_, arrayIteratorPrototypeValue);
SetStringTagSymbol(env, arrayIteratorPrototype, "Array Iterator");
thread_->SetInitialBuiltinHClass(BuiltinTypeId::ARRAY_ITERATOR, nullptr,

View File

@ -91,7 +91,7 @@
/* Array.prototype.some ( callbackfn [ , thisArg ] ) */ \
V("some", Some, 1, ArraySome) \
/* Array.prototype.sort ( comparefn ) */ \
V("sort", Sort, 1, SORT) \
V("sort", Sort, 1, ArraySort) \
/* Array.prototype.splice ( start, deleteCount, ...items ) */ \
V("splice", Splice, 2, ArraySplice) \
/* Array.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ) */ \

View File

@ -58,7 +58,7 @@
/* String.prototype.lastIndexOf ( searchString [ , position ] ) */ \
V("lastIndexOf", LastIndexOf, 1, INVALID) \
/* String.prototype.localeCompare ( that [ , reserved1 [ , reserved2 ] ] ) */ \
V("localeCompare", LocaleCompare, 1, LocaleCompare) \
V("localeCompare", LocaleCompare, 1, StringLocaleCompare) \
/* String.prototype.match ( regexp ) */ \
V("match", Match, 1, INVALID) \
/* String.prototype.matchAll ( regexp ) */ \

View File

@ -179,9 +179,6 @@ libark_jsoptimizer_sources = [
"ts_hcr_opt_pass.cpp",
"ts_inline_lowering.cpp",
"type.cpp",
"type_inference/global_type_infer.cpp",
"type_inference/initialization_analysis.cpp",
"type_inference/method_type_infer.cpp",
"type_inference/pgo_type_infer.cpp",
"type_inference/pgo_type_infer_helper.cpp",
"type_info_accessors.cpp",

View File

@ -16,8 +16,6 @@
#include <chrono>
#include <iostream>
#include <memory>
#include <signal.h> // NOLINTNEXTLINE(modernize-deprecated-headers)
#include <vector>
#include "ecmascript/base/string_helper.h"
#include "ecmascript/checkpoint/thread_state_transition.h"
@ -26,11 +24,8 @@
#include "ecmascript/compiler/pass_manager.h"
#include "ecmascript/ecma_string.h"
#include "ecmascript/js_runtime_options.h"
#include "ecmascript/jspandafile/js_pandafile_manager.h"
#include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/log.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/module/js_module_manager.h"
#include "ecmascript/napi/include/jsnapi.h"
#include "ecmascript/ohos/ohos_pkg_args.h"
#include "ecmascript/platform/file.h"
@ -125,10 +120,11 @@ int Main(const int argc, const char **argv)
if (!cPreprocessor.GenerateAbcFileInfos()) {
return 1;
}
cPreprocessor.GenerateGlobalTypes(cOptions);
cPreprocessor.GeneratePGOTypes(cOptions);
cPreprocessor.SnapshotInitialize();
ret = cPreprocessor.GetCompilerResult();
const auto &fileInfos = cPreprocessor.GetAbcFileInfo();
cPreprocessor.GenerateMethodMap(cOptions);
PassOptions::Builder optionsBuilder;
PassOptions passOptions =
@ -164,11 +160,13 @@ int Main(const int argc, const char **argv)
cOptions.maxMethodsInModule_,
profilerDecoder,
&passOptions,
cPreprocessor.GetCallMethodFlagMap(),
fileInfos,
cOptions.optBCRange_);
bool isEnableLiteCG = runtimeOptions.IsCompilerEnableLiteCG();
AOTFileGenerator generator(&log, &logList, vm, cOptions.triple_, isEnableLiteCG);
const auto &fileInfos = cPreprocessor.GetAbcFileInfo();
CompileValidFiles(passManager, generator, ret, fileInfos);
std::string appSignature = cPreprocessor.GetMainPkgArgsAppSignature();
generator.SaveAOTFile(cOptions.outputFileName_ + AOTFileManager::FILE_EXTENSION_AN, appSignature);

View File

@ -13,6 +13,7 @@
* limitations under the License.
*/
#include "ecmascript/compiler/aot_compiler_preprocessor.h"
#include "ecmascript/compiler/pgo_type/pgo_type_parser.h"
#include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/module/js_module_manager.h"
@ -65,6 +66,50 @@ CompilationOptions::CompilationOptions(EcmaVM *vm, JSRuntimeOptions &runtimeOpti
optBCRange_ = runtimeOptions.GetOptCodeRange();
isEnableEscapeAnalysis_ = runtimeOptions.IsEnableEscapeAnalysis();
isEnableInductionVariableAnalysis_ = runtimeOptions.IsEnableInductionVariableAnalysis();
std::string optionSelectMethods = runtimeOptions.GetCompilerSelectMethods();
std::string optionSkipMethods = runtimeOptions.GetCompilerSkipMethods();
if (!optionSelectMethods.empty() && !optionSkipMethods.empty()) {
LOG_COMPILER(FATAL) <<
"--compiler-select-methods and --compiler-skip-methods should not be set at the same time";
}
if (!optionSelectMethods.empty()) {
ParseOption(optionSelectMethods, optionSelectMethods_);
}
if (!optionSkipMethods.empty()) {
ParseOption(optionSkipMethods, optionSkipMethods_);
}
}
std::vector<std::string> CompilationOptions::SplitString(const std::string &str, const char ch) const
{
std::vector<std::string> vec {};
std::istringstream sstr(str.c_str());
std::string split;
while (getline(sstr, split, ch)) {
vec.emplace_back(split);
}
return vec;
}
void CompilationOptions::ParseOption(const std::string &option,
std::map<std::string, std::vector<std::string>> &optionMap) const
{
const char colon = ':';
const char comma = ',';
std::string str = option;
size_t posColon = 0;
size_t posComma = 0;
do {
posColon = str.find_last_of(colon);
std::string methodNameList = str.substr(posColon + 1, str.size());
std::vector<std::string> methodNameVec = SplitString(methodNameList, comma);
str = str.substr(0, posColon);
posComma = str.find_last_of(comma);
std::string recordName = str.substr(posComma + 1, str.size());
str = str.substr(0, posComma);
optionMap[recordName] = methodNameVec;
} while (posComma != std::string::npos);
}
bool AotCompilerPreprocessor::HandleTargetCompilerMode(CompilationOptions &cOptions)
@ -197,45 +242,37 @@ void AotCompilerPreprocessor::ResolveModule(const JSPandaFile *jsPandaFile, cons
}
}
void AotCompilerPreprocessor::GenerateGlobalTypes(const CompilationOptions &cOptions)
void AotCompilerPreprocessor::RecordArrayElement(const CompilationOptions &cOptions)
{
for (const AbcFileInfo &fileInfo : fileInfos_) {
JSPandaFile *jsPandaFile = fileInfo.jsPandaFile_.get();
TSManager *tsManager = vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager();
PGOTypeManager *ptManager = vm_->GetJSThread()->GetCurrentEcmaContext()->GetPTManager();
ptManager->SetCurCompilationFile(jsPandaFile);
BytecodeInfoCollector collector(vm_, jsPandaFile, profilerDecoder_, cOptions.maxAotMethodSize_,
cOptions.isEnableCollectLiteralInfo_);
BCInfo &bytecodeInfo = collector.GetBytecodeInfo();
const PGOBCInfo *bcInfo = collector.GetPGOBCInfo();
const auto &methodPcInfos = bytecodeInfo.GetMethodPcInfos();
auto &methodList = bytecodeInfo.GetMethodList();
for (const auto &method : methodList) {
uint32_t methodOffset = method.first;
tsManager->SetCurConstantPool(jsPandaFile, methodOffset);
CString recordName = MethodLiteral::GetRecordName(jsPandaFile, EntityId(methodOffset));
auto methodLiteral = jsPandaFile->FindMethodLiteral(methodOffset);
auto &methodInfo = methodList.at(methodOffset);
auto &methodPcInfo = methodPcInfos[methodInfo.GetMethodPcInfoIndex()];
TypeRecorder typeRecorder(jsPandaFile, methodLiteral, tsManager, recordName, &profilerDecoder_,
methodPcInfo, collector.GetByteCodes(), cOptions.isEnableOptTrackField_);
typeRecorder.BindPgoTypeToGateType(jsPandaFile, tsManager, methodLiteral);
auto callback = [this, ptManager, methodOffset, &recordName]
(const uint32_t, const uint32_t, const uint32_t cpIdx) {
JSThread *thread = vm_->GetJSThread();
JSTaggedValue cp = ptManager->GetConstantPoolByMethodOffset(methodOffset);
JSHandle<ConstantPool> constpoolHandle(thread, cp);
JSTaggedValue unsharedCp = thread->GetCurrentEcmaContext()
->FindOrCreateUnsharedConstpool(constpoolHandle.GetTaggedValue());
ASSERT(ConstantPool::CheckUnsharedConstpool(unsharedCp));
JSTaggedValue arr = ConstantPool::GetLiteralFromCache<ConstPoolType::ARRAY_LITERAL>(
thread, unsharedCp, cpIdx, recordName);
JSHandle<JSArray> arrayHandle(thread, arr);
panda_file::File::EntityId id =
ConstantPool::GetIdFromCache(constpoolHandle.GetTaggedValue(), cpIdx);
ptManager->RecordElements(id, arrayHandle->GetElements());
};
bcInfo->IterateInfoByType(methodOffset, PGOBCInfo::Type::ARRAY_LITERAL,
[this, tsManager, ptManager, &recordName]([[maybe_unused]] const uint32_t bcIdx,
[[maybe_unused]] const uint32_t bcOffset, const uint32_t cpIdx) {
JSHandle<ConstantPool> constpoolHandle(tsManager->GetConstantPool());
JSThread *thread = vm_->GetJSThread();
JSTaggedValue unsharedCp = thread->GetCurrentEcmaContext()
->FindOrCreateUnsharedConstpool(constpoolHandle.GetTaggedValue());
ASSERT(ConstantPool::CheckUnsharedConstpool(unsharedCp));
JSTaggedValue arr =
ConstantPool::GetLiteralFromCache<ConstPoolType::ARRAY_LITERAL>(
thread, unsharedCp, cpIdx, recordName);
JSHandle<JSArray> arrayHandle(thread, arr);
panda_file::File::EntityId id =
ConstantPool::GetIdFromCache(constpoolHandle.GetTaggedValue(), cpIdx);
ptManager->RecordElements(id, arrayHandle->GetElements());
});
bcInfo->IterateInfoByType(methodOffset, PGOBCInfo::Type::ARRAY_LITERAL, callback);
}
}
}
@ -250,6 +287,7 @@ void AotCompilerPreprocessor::GeneratePGOTypes(const CompilationOptions &cOption
PGOTypeParser parser(profilerDecoder_, ptManager);
parser.CreatePGOType(collector);
}
RecordArrayElement(cOptions);
}
void AotCompilerPreprocessor::SnapshotInitialize()
@ -258,6 +296,99 @@ void AotCompilerPreprocessor::SnapshotInitialize()
ptManager->InitAOTSnapshot(fileInfos_.size());
}
void CallMethodFlagMap::SetIsFastCall(CString fileDesc, uint32_t methodOffset, bool isFastCall)
{
abcIdMethodIdToIsFastCall_[std::pair<CString, uint32_t>(fileDesc, methodOffset)] = isFastCall;
}
bool CallMethodFlagMap::IsFastCall(CString fileDesc, uint32_t methodOffset) const
{
if (!abcIdMethodIdToIsFastCall_.count(std::pair<CString, uint32_t>(fileDesc, methodOffset))) {
return false;
}
return abcIdMethodIdToIsFastCall_.at(std::pair<CString, uint32_t>(fileDesc, methodOffset));
}
void CallMethodFlagMap::SetIsAotCompile(CString fileDesc, uint32_t methodOffset, bool isAotCompile)
{
abcIdMethodIdToIsAotCompile_[std::pair<CString, uint32_t>(fileDesc, methodOffset)] = isAotCompile;
}
bool CallMethodFlagMap::IsAotCompile(CString fileDesc, uint32_t methodOffset) const
{
if (!abcIdMethodIdToIsAotCompile_.count(std::pair<CString, uint32_t>(fileDesc, methodOffset))) {
return false;
}
return abcIdMethodIdToIsAotCompile_.at(std::pair<CString, uint32_t>(fileDesc, methodOffset));
}
bool AotCompilerPreprocessor::FilterOption(const std::map<std::string, std::vector<std::string>> &optionMap,
const std::string &recordName, const std::string &methodName) const
{
if (optionMap.empty()) {
return false;
}
auto it = optionMap.find(recordName);
if (it == optionMap.end()) {
return false;
}
std::vector<std::string> vec = it->second;
return find(vec.begin(), vec.end(), methodName) != vec.end();
}
bool AotCompilerPreprocessor::IsSkipMethod(const JSPandaFile *jsPandaFile, const BCInfo &bytecodeInfo,
const CString &recordName, const MethodLiteral *methodLiteral,
const MethodPcInfo &methodPCInfo, const std::string &methodName,
CompilationOptions &cOptions) const
{
if (methodPCInfo.methodsSize > bytecodeInfo.GetMaxMethodSize() ||
!profilerDecoder_.Match(jsPandaFile, recordName, methodLiteral->GetMethodId())) {
return true;
}
if (!cOptions.optionSelectMethods_.empty()) {
return !FilterOption(cOptions.optionSelectMethods_, ConvertToStdString(recordName), methodName);
} else if (!cOptions.optionSkipMethods_.empty()) {
return FilterOption(cOptions.optionSkipMethods_, ConvertToStdString(recordName), methodName);
}
return false;
}
void AotCompilerPreprocessor::GenerateMethodMap(CompilationOptions &cOptions)
{
JSPandaFileManager *jsPandaFileManager = JSPandaFileManager::GetInstance();
jsPandaFileManager->EnumerateNonVirtualJSPandaFiles(
[this, &cOptions] (std::shared_ptr<JSPandaFile> jsPandaFilePtr) {
JSPandaFile *jsPandaFile = jsPandaFilePtr.get();
BytecodeInfoCollector collector(vm_, jsPandaFile, profilerDecoder_, cOptions.maxAotMethodSize_,
cOptions.isEnableCollectLiteralInfo_);
BCInfo &bytecodeInfo = collector.GetBytecodeInfo();
const auto &methodPcInfos = bytecodeInfo.GetMethodPcInfos();
auto &methodList = bytecodeInfo.GetMethodList();
for (auto it = methodList.begin(); it != methodList.end(); it++) {
uint32_t index = it->first;
auto &methodInfo = it->second;
auto &methodPcInfo = methodPcInfos[methodInfo.GetMethodPcInfoIndex()];
auto methodLiteral = jsPandaFile->FindMethodLiteral(index);
auto methodId = methodLiteral->GetMethodId();
const std::string methodName(MethodLiteral::GetMethodName(jsPandaFile, methodId));
bool isAotcompile = !IsSkipMethod(jsPandaFile, bytecodeInfo, MethodLiteral::GetRecordName(
jsPandaFile, EntityId(index)), methodLiteral, methodPcInfo, methodName, cOptions);
bool isFastCall = methodLiteral->IsFastCall();
CString fileDesc = jsPandaFile->GetNormalizedFileDesc();
uint32_t offset = methodId.GetOffset();
callMethodFlagMap_.SetIsAotCompile(fileDesc, offset, isAotcompile);
callMethodFlagMap_.SetIsFastCall(fileDesc, offset, isFastCall);
LOG_COMPILER(INFO) <<"!!!"<< fileDesc <<" "<< offset << " " << isAotcompile << " " << isFastCall;
}
return true;
});
}
std::string AotCompilerPreprocessor::GetMainPkgArgsAppSignature() const
{
return GetMainPkgArgs() == nullptr ? "" : GetMainPkgArgs()->GetAppSignature();

View File

@ -15,6 +15,9 @@
#ifndef ECMASCRIPT_COMPILER_AOT_COMPILER_PREPROCESSOR_H
#define ECMASCRIPT_COMPILER_AOT_COMPILER_PREPROCESSOR_H
#include "ecmascript/compiler/bytecode_info_collector.h"
#include "ecmascript/compiler/compiler_log.h"
#include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
#include "ecmascript/compiler/pass_manager.h"
#include "ecmascript/ecma_vm.h"
#include "macros.h"
@ -32,9 +35,22 @@ struct AbcFileInfo {
std::shared_ptr<JSPandaFile> jsPandaFile_;
};
class CallMethodFlagMap {
public:
CallMethodFlagMap() {}
void SetIsFastCall(CString fileDesc, uint32_t methodOffset, bool isFastCall);
bool IsFastCall(CString fileDesc, uint32_t methodOffset) const;
void SetIsAotCompile(CString fileDesc, uint32_t methodOffset, bool isAotCompile);
bool IsAotCompile(CString fileDesc, uint32_t methodOffset) const;
private:
std::map<std::pair<CString, uint32_t>, bool> abcIdMethodIdToIsFastCall_ {};
std::map<std::pair<CString, uint32_t>, bool> abcIdMethodIdToIsAotCompile_ {};
};
struct CompilationOptions {
explicit CompilationOptions(EcmaVM *vm, JSRuntimeOptions &runtimeOptions);
void ParseOption(const std::string &option, std::map<std::string, std::vector<std::string>> &optionMap) const;
std::vector<std::string> SplitString(const std::string &str, const char ch) const;
std::string triple_;
std::string outputFileName_;
size_t optLevel_;
@ -70,6 +86,8 @@ struct CompilationOptions {
bool isEnableOptBranchProfiling_;
bool isEnableEscapeAnalysis_;
bool isEnableInductionVariableAnalysis_;
std::map<std::string, std::vector<std::string>> optionSelectMethods_;
std::map<std::string, std::vector<std::string>> optionSkipMethods_;
};
class AotCompilerPreprocessor {
@ -95,12 +113,40 @@ public:
bool GenerateAbcFileInfos();
void GenerateGlobalTypes(const CompilationOptions &cOptions);
void GeneratePGOTypes(const CompilationOptions &cOptions);
void SnapshotInitialize();
bool FilterOption(const std::map<std::string, std::vector<std::string>> &optionMap,
const std::string &recordName, const std::string &methodName) const;
bool IsSkipMethod(const JSPandaFile *jsPandaFile, const BCInfo &bytecodeInfo,
const CString &recordName, const MethodLiteral *methodLiteral,
const MethodPcInfo &methodPCInfo, const std::string &methodName,
CompilationOptions &cOptions) const;
void GenerateMethodMap(CompilationOptions &cOptions);
void SetIsFastCall(CString fileDesc, uint32_t methodOffset, bool isFastCall)
{
callMethodFlagMap_.SetIsFastCall(fileDesc, methodOffset, isFastCall);
}
bool IsFastCall(CString fileDesc, uint32_t methodOffset)
{
return callMethodFlagMap_.IsFastCall(fileDesc, methodOffset);
}
void SetIsAotCompile(CString fileDesc, uint32_t methodOffset, bool isAotCompile)
{
callMethodFlagMap_.SetIsAotCompile(fileDesc, methodOffset, isAotCompile);
}
bool GetIsAotCompile(CString fileDesc, uint32_t methodOffset)
{
return callMethodFlagMap_.IsAotCompile(fileDesc, methodOffset);
}
std::string GetMainPkgArgsAppSignature() const;
bool GetCompilerResult()
@ -126,6 +172,10 @@ public:
{
return pkgsArgs_;
}
const CallMethodFlagMap *GetCallMethodFlagMap()
{
return &callMethodFlagMap_;
}
static std::string GetHelper()
{
@ -144,6 +194,8 @@ private:
void ResolveModule(const JSPandaFile *jsPandaFile, const std::string &fileName);
void RecordArrayElement(const CompilationOptions &cOptions);
EcmaVM *vm_;
JSRuntimeOptions &runtimeOptions_;
std::map<std::string, std::shared_ptr<OhosPkgArgs>> &pkgsArgs_;
@ -151,6 +203,7 @@ private:
PGOProfilerDecoder &profilerDecoder_;
arg_list_t &pandaFileNames_;
CVector<AbcFileInfo> fileInfos_;
CallMethodFlagMap callMethodFlagMap_;
friend class OhosPkgArgs;
};
} // namespace panda::ecmascript::kungfu

View File

@ -640,9 +640,7 @@ GateRef ArrayBoundsCheckElimination::PredicateCmpWithConst(GateRef left, TypedBi
GateRef ArrayBoundsCheckElimination::PredicateAdd(GateRef left, int32_t leftConst, TypedBinOp cond, GateRef right)
{
GateRef constGate = builder_.Int32(leftConst);
GateRef binaryOpGate = builder_.InsertTypedBinaryop(left, constGate, GateType::NumberType(),
GateType::NumberType(), GateType::AnyType(),
PGOTypeRef::NoneType(), TypedBinOp::TYPED_ADD);
GateRef binaryOpGate = builder_.InsertTypedBinaryop(left, constGate, TypedBinOp::TYPED_ADD);
return Predicate(binaryOpGate, cond, right);
}
@ -774,10 +772,10 @@ void ArrayBoundsCheckElimination::ProcessIf(IntegerStack &pushed, GateRegion *pa
case TypedBinOp::TYPED_EQ:
case TypedBinOp::TYPED_NOTEQ: {
if (cond == OpCode::IF_TRUE) {
op = TypedBinaryMetaData::GetRevCompareOp(op);
op = acc_.GetRevCompareOpForTypedBinOp(op);
}
AddIfCondition(pushed, x, y, op);
AddIfCondition(pushed, y, x, TypedBinaryMetaData::GetSwapCompareOp(op));
AddIfCondition(pushed, y, x, acc_.GetSwapCompareOpForTypedBinOp(op));
break;
}
default:
@ -884,16 +882,10 @@ void ArrayBoundsCheckElimination::InBlockMotion(GateLists &indexChecked, GateLis
GateRef lowerCompare = index;
if (info->min_ > 0) {
GateRef minGate = builder_.Int32(info->min_);
lowerCompare = builder_.InsertTypedBinaryop(lowerCompare, minGate,
GateType::NumberType(), GateType::NumberType(),
GateType::AnyType(), PGOTypeRef::NoneType(),
TypedBinOp::TYPED_ADD);
lowerCompare = builder_.InsertTypedBinaryop(lowerCompare, minGate, TypedBinOp::TYPED_ADD);
} else if (info->min_ < 0) {
GateRef minGate = builder_.Int32(-info->min_);
lowerCompare = builder_.InsertTypedBinaryop(lowerCompare, minGate,
GateType::NumberType(), GateType::NumberType(),
GateType::AnyType(), PGOTypeRef::NoneType(),
TypedBinOp::TYPED_SUB);
lowerCompare = builder_.InsertTypedBinaryop(lowerCompare, minGate, TypedBinOp::TYPED_SUB);
}
PredicateCmpWithConst(lowerCompare, TypedBinOp::TYPED_GREATEREQ, 0);
@ -903,16 +895,10 @@ void ArrayBoundsCheckElimination::InBlockMotion(GateLists &indexChecked, GateLis
if (info->max_ != 0) {
if (info->max_ > 0) {
GateRef maxGate = builder_.Int32(info->max_);
upperCompare = builder_.InsertTypedBinaryop(upperCompare, maxGate,
GateType::NumberType(), GateType::NumberType(),
GateType::AnyType(), PGOTypeRef::NoneType(),
TypedBinOp::TYPED_ADD);
upperCompare = builder_.InsertTypedBinaryop(upperCompare, maxGate, TypedBinOp::TYPED_ADD);
} else if (info->max_ < 0) {
GateRef maxGate = builder_.Int32(-info->max_);
upperCompare = builder_.InsertTypedBinaryop(upperCompare, maxGate,
GateType::NumberType(), GateType::NumberType(),
GateType::AnyType(), PGOTypeRef::NoneType(),
TypedBinOp::TYPED_SUB);
upperCompare = builder_.InsertTypedBinaryop(upperCompare, maxGate, TypedBinOp::TYPED_SUB);
}
}

View File

@ -15,6 +15,8 @@
#include "ecmascript/compiler/async_function_lowering.h"
#include "ecmascript/js_generator_object.h"
namespace panda::ecmascript::kungfu {
void AsyncFunctionLowering::ProcessAll()
{

View File

@ -18,9 +18,7 @@
#include "ecmascript/compiler/bytecode_circuit_builder.h"
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/circuit_builder-inl.h"
#include "ecmascript/compiler/circuit_builder.h"
#include "ecmascript/mem/chunk_containers.h"
namespace panda::ecmascript::kungfu {
class AsyncFunctionLowering {

View File

@ -152,21 +152,21 @@ namespace panda::ecmascript::kungfu {
V(MapConstructor)
#define AOT_AND_BUILTINS_STUB_LIST(V) \
V(LocaleCompare) \
V(STRING_ITERATOR_PROTO_NEXT) \
V(SORT)
V(StringLocaleCompare) \
V(StringIteratorProtoNext) \
V(ArraySort)
#define AOT_BUILTINS_STUB_LIST(V) \
V(STRINGIFY) \
V(MAP_PROTO_ITERATOR) \
V(SET_PROTO_ITERATOR) \
V(STRING_PROTO_ITERATOR) \
V(ARRAY_PROTO_ITERATOR) \
V(TYPED_ARRAY_PROTO_ITERATOR) \
V(MAP_ITERATOR_PROTO_NEXT) \
V(SET_ITERATOR_PROTO_NEXT) \
V(ARRAY_ITERATOR_PROTO_NEXT) \
V(ITERATOR_PROTO_RETURN)
V(JsonStringify) \
V(MapProtoIterator) \
V(MapIteratorProtoNext) \
V(SetProtoIterator) \
V(SetIteratorProtoNext) \
V(StringProtoIterator) \
V(ArrayProtoIterator) \
V(ArrayIteratorProtoNext) \
V(TypeArrayProtoIterator) \
V(IteratorProtoReturn)
// List of builtins which will try to be inlined in TypedNativeInlineLoweringPass
#define AOT_BUILTINS_INLINE_LIST(V) \
@ -242,8 +242,8 @@ public:
#undef DEF_STUB_ID_DYN
#undef DEF_STUB_ID
BUILTINS_CONSTRUCTOR_STUB_FIRST = BooleanConstructor,
TYPED_BUILTINS_FIRST = STRINGIFY,
TYPED_BUILTINS_LAST = ITERATOR_PROTO_RETURN,
TYPED_BUILTINS_FIRST = JsonStringify,
TYPED_BUILTINS_LAST = IteratorProtoReturn,
INVALID = 0xFF,
};
static_assert(ID::NONE == 0);
@ -281,9 +281,9 @@ public:
static bool IsTypedBuiltin(ID builtinId)
{
return (BuiltinsStubCSigns::ID::LocaleCompare == builtinId) ||
(BuiltinsStubCSigns::ID::STRING_ITERATOR_PROTO_NEXT == builtinId) ||
(BuiltinsStubCSigns::ID::SORT == builtinId) ||
return (BuiltinsStubCSigns::ID::StringLocaleCompare == builtinId) ||
(BuiltinsStubCSigns::ID::StringIteratorProtoNext == builtinId) ||
(BuiltinsStubCSigns::ID::ArraySort == builtinId) ||
((BuiltinsStubCSigns::ID::TYPED_BUILTINS_FIRST <= builtinId) &&
(builtinId <= BuiltinsStubCSigns::ID::TYPED_BUILTINS_LAST));
}
@ -311,11 +311,22 @@ public:
static bool IsTypedBuiltinCallThis0(ID builtinId)
{
switch (builtinId) {
case BuiltinsStubCSigns::ID::MAP_ITERATOR_PROTO_NEXT:
case BuiltinsStubCSigns::ID::SET_ITERATOR_PROTO_NEXT:
case BuiltinsStubCSigns::ID::STRING_ITERATOR_PROTO_NEXT:
case BuiltinsStubCSigns::ID::ARRAY_ITERATOR_PROTO_NEXT:
case BuiltinsStubCSigns::ID::ITERATOR_PROTO_RETURN:
case BuiltinsStubCSigns::ID::MapIteratorProtoNext:
case BuiltinsStubCSigns::ID::SetIteratorProtoNext:
case BuiltinsStubCSigns::ID::StringIteratorProtoNext:
case BuiltinsStubCSigns::ID::ArrayIteratorProtoNext:
case BuiltinsStubCSigns::ID::IteratorProtoReturn:
case BuiltinsStubCSigns::ID::ArraySort:
return true;
default:
return false;
}
}
static bool IsTypedBuiltinCallThis1(ID builtinId)
{
switch (builtinId) {
case BuiltinsStubCSigns::ID::JsonStringify:
return true;
default:
return false;
@ -325,7 +336,7 @@ public:
static bool IsTypedBuiltinCallThis3(ID builtinId)
{
switch (builtinId) {
case BuiltinsStubCSigns::ID::LocaleCompare:
case BuiltinsStubCSigns::ID::StringLocaleCompare:
return true;
default:
return false;
@ -401,21 +412,21 @@ public:
return ConstantIndex::MATH_FROUND_INDEX;
case BuiltinsStubCSigns::ID::MathImul:
return ConstantIndex::MATH_IMUL_INDEX;
case BuiltinsStubCSigns::ID::LocaleCompare:
case BuiltinsStubCSigns::ID::StringLocaleCompare:
return ConstantIndex::LOCALE_COMPARE_FUNCTION_INDEX;
case BuiltinsStubCSigns::ID::SORT:
case BuiltinsStubCSigns::ID::ArraySort:
return ConstantIndex::ARRAY_SORT_FUNCTION_INDEX;
case BuiltinsStubCSigns::ID::STRINGIFY:
case BuiltinsStubCSigns::ID::JsonStringify:
return ConstantIndex::JSON_STRINGIFY_FUNCTION_INDEX;
case BuiltinsStubCSigns::ID::MAP_ITERATOR_PROTO_NEXT:
case BuiltinsStubCSigns::ID::MapIteratorProtoNext:
return ConstantIndex::MAP_ITERATOR_PROTO_NEXT_INDEX;
case BuiltinsStubCSigns::ID::SET_ITERATOR_PROTO_NEXT:
case BuiltinsStubCSigns::ID::SetIteratorProtoNext:
return ConstantIndex::SET_ITERATOR_PROTO_NEXT_INDEX;
case BuiltinsStubCSigns::ID::STRING_ITERATOR_PROTO_NEXT:
case BuiltinsStubCSigns::ID::StringIteratorProtoNext:
return ConstantIndex::STRING_ITERATOR_PROTO_NEXT_INDEX;
case BuiltinsStubCSigns::ID::ARRAY_ITERATOR_PROTO_NEXT:
case BuiltinsStubCSigns::ID::ArrayIteratorProtoNext:
return ConstantIndex::ARRAY_ITERATOR_PROTO_NEXT_INDEX;
case BuiltinsStubCSigns::ID::ITERATOR_PROTO_RETURN:
case BuiltinsStubCSigns::ID::IteratorProtoReturn:
return ConstantIndex::ITERATOR_PROTO_RETURN_INDEX;
case BuiltinsStubCSigns::ID::StringFromCharCode:
return ConstantIndex::STRING_FROM_CHAR_CODE_INDEX;
@ -554,10 +565,10 @@ public:
{"imul", MathImul},
{"max", MathMax},
{"min", MathMin},
{"localeCompare", LocaleCompare},
{"next", STRING_ITERATOR_PROTO_NEXT},
{"sort", SORT},
{"stringify", STRINGIFY},
{"localeCompare", StringLocaleCompare},
{"next", StringIteratorProtoNext},
{"sort", ArraySort},
{"stringify", JsonStringify},
{"isFinite", GlobalIsFinite},
{"isNan", GlobalIsNan},
};
@ -593,6 +604,7 @@ enum class BuiltinsArgs : size_t {
#define IS_TYPED_INLINE_BUILTINS_ID(id) kungfu::BuiltinsStubCSigns::IsTypedInlineBuiltin(id)
#define IS_TYPED_BUILTINS_NUMBER_ID(id) kungfu::BuiltinsStubCSigns::IsTypedBuiltinNumber(id)
#define IS_TYPED_BUILTINS_ID_CALL_THIS0(id) kungfu::BuiltinsStubCSigns::IsTypedBuiltinCallThis0(id)
#define IS_TYPED_BUILTINS_ID_CALL_THIS1(id) kungfu::BuiltinsStubCSigns::IsTypedBuiltinCallThis1(id)
#define IS_TYPED_BUILTINS_ID_CALL_THIS3(id) kungfu::BuiltinsStubCSigns::IsTypedBuiltinCallThis3(id)
#define GET_TYPED_CONSTANT_INDEX(id) kungfu::BuiltinsStubCSigns::GetConstantIndex(id)
#define GET_TYPED_GLOBAL_ENV_INDEX(id) kungfu::BuiltinsStubCSigns::GetGlobalEnvIndex(id)

View File

@ -237,10 +237,10 @@ DECLARE_BUILTINS(stubName)
Return(*res); \
}
#define AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(V) \
V(LocaleCompare, LocaleCompare, String, Undefined()) \
V(STRING_ITERATOR_PROTO_NEXT, StringIteratorNext, String, Undefined()) \
V(SORT, Sort, Array, Undefined())
#define AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(V) \
V(StringLocaleCompare, LocaleCompare, String, Undefined()) \
V(StringIteratorProtoNext, StringIteratorNext, String, Undefined()) \
V(ArraySort, Sort, Array, Undefined())
AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(DECLARE_AOT_AND_BUILTINS_STUB_BUILDER)
#undef AOT_AND_BUILTINS_STUB_LIST

View File

@ -24,29 +24,29 @@ void BuiltinLowering::LowerTypedCallBuitin(GateRef gate)
auto idGate = acc_.GetValueIn(gate, valuesIn - 1);
auto id = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(idGate));
switch (id) {
case BUILTINS_STUB_ID(LocaleCompare):
case BUILTINS_STUB_ID(StringLocaleCompare):
LowerTypedLocaleCompare(gate);
break;
case BUILTINS_STUB_ID(SORT):
case BUILTINS_STUB_ID(ArraySort):
LowerTypedArraySort(gate);
break;
case BUILTINS_STUB_ID(STRINGIFY):
case BUILTINS_STUB_ID(JsonStringify):
LowerTypedStringify(gate);
break;
case BUILTINS_STUB_ID(MAP_PROTO_ITERATOR):
case BUILTINS_STUB_ID(SET_PROTO_ITERATOR):
case BUILTINS_STUB_ID(STRING_PROTO_ITERATOR):
case BUILTINS_STUB_ID(ARRAY_PROTO_ITERATOR):
case BUILTINS_STUB_ID(TYPED_ARRAY_PROTO_ITERATOR):
case BUILTINS_STUB_ID(MapProtoIterator):
case BUILTINS_STUB_ID(SetProtoIterator):
case BUILTINS_STUB_ID(StringProtoIterator):
case BUILTINS_STUB_ID(ArrayProtoIterator):
case BUILTINS_STUB_ID(TypeArrayProtoIterator):
LowerBuiltinIterator(gate, id);
break;
case BUILTINS_STUB_ID(MAP_ITERATOR_PROTO_NEXT):
case BUILTINS_STUB_ID(SET_ITERATOR_PROTO_NEXT):
case BUILTINS_STUB_ID(STRING_ITERATOR_PROTO_NEXT):
case BUILTINS_STUB_ID(ARRAY_ITERATOR_PROTO_NEXT):
case BUILTINS_STUB_ID(MapIteratorProtoNext):
case BUILTINS_STUB_ID(SetIteratorProtoNext):
case BUILTINS_STUB_ID(StringIteratorProtoNext):
case BUILTINS_STUB_ID(ArrayIteratorProtoNext):
LowerIteratorNext(gate, id);
break;
case BUILTINS_STUB_ID(ITERATOR_PROTO_RETURN):
case BUILTINS_STUB_ID(IteratorProtoReturn):
LowerIteratorReturn(gate, id);
break;
case BUILTINS_STUB_ID(NumberConstructor):
@ -187,11 +187,11 @@ GateRef BuiltinLowering::LowerCallTargetCheck(Environment *env, GateRef gate)
GateRef idGate = acc_.GetValueIn(gate, 1);
BuiltinsStubCSigns::ID id = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(idGate));
switch (id) {
case BuiltinsStubCSigns::ID::MAP_PROTO_ITERATOR:
case BuiltinsStubCSigns::ID::SET_PROTO_ITERATOR:
case BuiltinsStubCSigns::ID::STRING_PROTO_ITERATOR:
case BuiltinsStubCSigns::ID::ARRAY_PROTO_ITERATOR:
case BuiltinsStubCSigns::ID::TYPED_ARRAY_PROTO_ITERATOR: {
case BuiltinsStubCSigns::ID::MapProtoIterator:
case BuiltinsStubCSigns::ID::SetProtoIterator:
case BuiltinsStubCSigns::ID::StringProtoIterator:
case BuiltinsStubCSigns::ID::ArrayProtoIterator:
case BuiltinsStubCSigns::ID::TypeArrayProtoIterator: {
return LowerCallTargetCheckWithDetector(gate, id);
}
case BuiltinsStubCSigns::ID::NumberConstructor: {
@ -224,27 +224,27 @@ GateRef BuiltinLowering::LowerCallTargetCheckWithDetector(GateRef gate, Builtins
JSType expectType = JSType::INVALID;
uint8_t detectorIndex = 0;
switch (id) {
case BuiltinsStubCSigns::ID::MAP_PROTO_ITERATOR: {
case BuiltinsStubCSigns::ID::MapProtoIterator: {
expectType = JSType::JS_MAP;
detectorIndex = GlobalEnv::MAP_ITERATOR_DETECTOR_INDEX;
break;
}
case BuiltinsStubCSigns::ID::SET_PROTO_ITERATOR: {
case BuiltinsStubCSigns::ID::SetProtoIterator: {
expectType = JSType::JS_SET;
detectorIndex = GlobalEnv::SET_ITERATOR_DETECTOR_INDEX;
break;
}
case BuiltinsStubCSigns::ID::STRING_PROTO_ITERATOR: {
case BuiltinsStubCSigns::ID::StringProtoIterator: {
expectType = JSType::STRING_FIRST;
detectorIndex = GlobalEnv::STRING_ITERATOR_DETECTOR_INDEX;
break;
}
case BuiltinsStubCSigns::ID::ARRAY_PROTO_ITERATOR: {
case BuiltinsStubCSigns::ID::ArrayProtoIterator: {
expectType = JSType::JS_ARRAY;
detectorIndex = GlobalEnv::ARRAY_ITERATOR_DETECTOR_INDEX;
break;
}
case BuiltinsStubCSigns::ID::TYPED_ARRAY_PROTO_ITERATOR: {
case BuiltinsStubCSigns::ID::TypeArrayProtoIterator: {
expectType = JSType::JS_TYPED_ARRAY_FIRST;
detectorIndex = GlobalEnv::TYPED_ARRAY_ITERATOR_DETECTOR_INDEX;
break;
@ -272,19 +272,19 @@ GateRef BuiltinLowering::CheckPara(GateRef gate, GateRef funcCheck)
return funcCheck;
}
switch (id) {
case BuiltinsStubCSigns::ID::LocaleCompare:
case BuiltinsStubCSigns::ID::SORT:
case BuiltinsStubCSigns::ID::STRINGIFY:
case BuiltinsStubCSigns::ID::MAP_PROTO_ITERATOR:
case BuiltinsStubCSigns::ID::SET_PROTO_ITERATOR:
case BuiltinsStubCSigns::ID::STRING_PROTO_ITERATOR:
case BuiltinsStubCSigns::ID::ARRAY_PROTO_ITERATOR:
case BuiltinsStubCSigns::ID::TYPED_ARRAY_PROTO_ITERATOR:
case BuiltinsStubCSigns::ID::MAP_ITERATOR_PROTO_NEXT:
case BuiltinsStubCSigns::ID::SET_ITERATOR_PROTO_NEXT:
case BuiltinsStubCSigns::ID::STRING_ITERATOR_PROTO_NEXT:
case BuiltinsStubCSigns::ID::ARRAY_ITERATOR_PROTO_NEXT:
case BuiltinsStubCSigns::ID::ITERATOR_PROTO_RETURN:
case BuiltinsStubCSigns::ID::StringLocaleCompare:
case BuiltinsStubCSigns::ID::ArraySort:
case BuiltinsStubCSigns::ID::JsonStringify:
case BuiltinsStubCSigns::ID::MapProtoIterator:
case BuiltinsStubCSigns::ID::SetProtoIterator:
case BuiltinsStubCSigns::ID::StringProtoIterator:
case BuiltinsStubCSigns::ID::ArrayProtoIterator:
case BuiltinsStubCSigns::ID::TypeArrayProtoIterator:
case BuiltinsStubCSigns::ID::MapIteratorProtoNext:
case BuiltinsStubCSigns::ID::SetIteratorProtoNext:
case BuiltinsStubCSigns::ID::StringIteratorProtoNext:
case BuiltinsStubCSigns::ID::ArrayIteratorProtoNext:
case BuiltinsStubCSigns::ID::IteratorProtoReturn:
case BuiltinsStubCSigns::ID::NumberConstructor:
// Don't need check para
return funcCheck;
@ -311,23 +311,23 @@ void BuiltinLowering::LowerBuiltinIterator(GateRef gate, BuiltinsStubCSigns::ID
GateRef obj = acc_.GetValueIn(gate, 0);
GateRef result = Circuit::NullGate();
switch (id) {
case BUILTINS_STUB_ID(MAP_PROTO_ITERATOR): {
case BUILTINS_STUB_ID(MapProtoIterator): {
result = builder_.CallStub(glue, gate, CommonStubCSigns::CreateJSMapIterator, { glue, obj });
break;
}
case BUILTINS_STUB_ID(SET_PROTO_ITERATOR): {
case BUILTINS_STUB_ID(SetProtoIterator): {
result = builder_.CallStub(glue, gate, CommonStubCSigns::CreateJSSetIterator, { glue, obj });
break;
}
case BUILTINS_STUB_ID(STRING_PROTO_ITERATOR): {
case BUILTINS_STUB_ID(StringProtoIterator): {
result = LowerCallRuntime(glue, gate, RTSTUB_ID(CreateStringIterator), { obj }, true);
break;
}
case BUILTINS_STUB_ID(ARRAY_PROTO_ITERATOR): {
case BUILTINS_STUB_ID(ArrayProtoIterator): {
result = LowerCallRuntime(glue, gate, RTSTUB_ID(NewJSArrayIterator), { obj }, true);
break;
}
case BUILTINS_STUB_ID(TYPED_ARRAY_PROTO_ITERATOR): {
case BUILTINS_STUB_ID(TypeArrayProtoIterator): {
result = LowerCallRuntime(glue, gate, RTSTUB_ID(NewJSTypedArrayIterator), { obj }, true);
break;
}
@ -343,19 +343,19 @@ void BuiltinLowering::LowerIteratorNext(GateRef gate, BuiltinsStubCSigns::ID id)
GateRef thisObj = acc_.GetValueIn(gate, 0);
GateRef result = Circuit::NullGate();
switch (id) {
case BUILTINS_STUB_ID(MAP_ITERATOR_PROTO_NEXT): {
case BUILTINS_STUB_ID(MapIteratorProtoNext): {
result = LowerCallRuntime(glue, gate, RTSTUB_ID(MapIteratorNext), { thisObj }, true);
break;
}
case BUILTINS_STUB_ID(SET_ITERATOR_PROTO_NEXT): {
case BUILTINS_STUB_ID(SetIteratorProtoNext): {
result = LowerCallRuntime(glue, gate, RTSTUB_ID(SetIteratorNext), { thisObj }, true);
break;
}
case BUILTINS_STUB_ID(STRING_ITERATOR_PROTO_NEXT): {
case BUILTINS_STUB_ID(StringIteratorProtoNext): {
result = LowerCallRuntime(glue, gate, RTSTUB_ID(StringIteratorNext), { thisObj }, true);
break;
}
case BUILTINS_STUB_ID(ARRAY_ITERATOR_PROTO_NEXT): {
case BUILTINS_STUB_ID(ArrayIteratorProtoNext): {
result = LowerCallRuntime(glue, gate, RTSTUB_ID(ArrayIteratorNext), { thisObj }, true);
break;
}
@ -371,7 +371,7 @@ void BuiltinLowering::LowerIteratorReturn(GateRef gate, BuiltinsStubCSigns::ID i
GateRef thisObj = acc_.GetValueIn(gate, 0);
GateRef result = Circuit::NullGate();
switch (id) {
case BUILTINS_STUB_ID(ITERATOR_PROTO_RETURN): {
case BUILTINS_STUB_ID(IteratorProtoReturn): {
result = LowerCallRuntime(glue, gate, RTSTUB_ID(IteratorReturn), { thisObj }, true);
break;
}

View File

@ -387,10 +387,6 @@ void BytecodeCircuitBuilder::BuildCircuitArgs()
}
}
argAcc_.CollectArgs();
if (HasTypes()) {
argAcc_.FillArgsGateType(&typeRecorder_);
}
BuildFrameArgs();
}
@ -741,7 +737,7 @@ void BytecodeCircuitBuilder::NewByteCode(BytecodeRegion &bb)
// handle return.dyn and returnundefined bytecodes
gate = NewReturn(bb);
} else if (bytecodeInfo.IsMov()) {
frameStateBuilder_.UpdateMoveValues(bytecodeInfo, iterator.Index());
frameStateBuilder_.UpdateMoveValues(bytecodeInfo);
} else if (!bytecodeInfo.IsDiscarded()) {
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();

View File

@ -17,27 +17,20 @@
#define ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H
#include <algorithm>
#include <numeric>
#include <tuple>
#include <utility>
#include <vector>
#include <variant>
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/compiler/bytecode_info_collector.h"
#include "ecmascript/compiler/bytecodes.h"
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/compiler_log.h"
#include "ecmascript/compiler/ecma_opcode_des.h"
#include "ecmascript/compiler/frame_states.h"
#include "ecmascript/compiler/loop_analysis.h"
#include "ecmascript/compiler/pgo_type/pgo_type_recorder.h"
#include "ecmascript/compiler/type_recorder.h"
#include "ecmascript/interpreter/interpreter-inl.h"
#include "ecmascript/jspandafile/js_pandafile.h"
#include "ecmascript/jspandafile/method_literal.h"
#include "ecmascript/compiler/compiler_log.h"
#include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
namespace panda::ecmascript::kungfu {
struct ExceptionItem {
@ -216,23 +209,18 @@ public:
BytecodeCircuitBuilder(const JSPandaFile *jsPandaFile,
const MethodLiteral *methodLiteral,
const MethodPcInfo &methodPCInfo,
TSManager *tsManager,
Circuit *circuit,
Bytecodes *bytecodes,
bool hasTypes,
bool enableLog,
bool enableTypeLowering,
std::string name,
const CString &recordName,
PGOProfilerDecoder *decoder,
bool isInline,
bool enableOptTrackField)
: tsManager_(tsManager), circuit_(circuit), graph_(circuit->chunk()), file_(jsPandaFile),
bool isInline)
: circuit_(circuit), graph_(circuit->chunk()), file_(jsPandaFile),
method_(methodLiteral), gateAcc_(circuit), argAcc_(circuit, method_),
typeRecorder_(jsPandaFile, method_, tsManager, recordName, decoder, methodPCInfo, bytecodes,
enableOptTrackField),
pgoTypeRecorder_(*decoder, jsPandaFile, method_->GetMethodId().GetOffset()),
hasTypes_(hasTypes), enableLog_(enableLog), enableTypeLowering_(enableTypeLowering),
enableLog_(enableLog), enableTypeLowering_(enableTypeLowering),
pcOffsets_(methodPCInfo.pcOffsets),
frameStateBuilder_(this, circuit, methodLiteral),
methodName_(name), recordName_(recordName),
@ -337,11 +325,6 @@ public:
suspendAndResumeGates_.emplace_back(gate);
};
inline bool HasTypes() const
{
return hasTypes_;
}
template <class Callback>
void EnumerateBlock(BytecodeRegion &bb, const Callback &cb)
{
@ -517,16 +500,6 @@ public:
return bbId == 1;
}
TSManager *GetTSManager() const
{
return tsManager_;
}
const TypeRecorder *GetTypeRecorder() const
{
return &typeRecorder_;
}
const PGOTypeRecorder *GetPGOTypeRecorder() const
{
return &pgoTypeRecorder_;
@ -630,7 +603,6 @@ private:
return *graph_[i];
}
TSManager *tsManager_;
Circuit *circuit_;
std::vector<std::vector<GateRef>> byteCodeToJSGates_;
std::unordered_map<GateRef, size_t> jsGatesToByteCode_;
@ -639,10 +611,8 @@ private:
const MethodLiteral *method_ {nullptr};
GateAccessor gateAcc_;
ArgumentAccessor argAcc_;
TypeRecorder typeRecorder_;
PGOTypeRecorder pgoTypeRecorder_;
int32_t osrOffset_ {MachineCode::INVALID_OSR_OFFSET};
bool hasTypes_ {false};
bool enableLog_ {false};
bool enableTypeLowering_ {false};
std::vector<GateRef> suspendAndResumeGates_ {};

View File

@ -184,16 +184,6 @@ public:
return metaBuilder_.JSBytecode(valuesIn, methodId, opcode, pcOffset, bcIndex, flags);
}
const GateMetaData* TypedBinaryOp(uint64_t value, TypedBinOp binOp, PGOTypeRef type)
{
return metaBuilder_.TypedBinaryOp(value, binOp, type);
}
const GateMetaData* TypedCallTargetCheckOp(uint32_t numIns, uint64_t value, TypedCallTargetCheckOp checkOp)
{
return metaBuilder_.TypedCallTargetCheckOp(numIns, value, checkOp);
}
GateRef DeadGate()
{
if (dead_ == NullGate()) {

View File

@ -498,33 +498,33 @@ public:
GateRef FlattenTreeStringCheck(GateRef gate);
GateRef HClassStableArrayCheck(GateRef gate, GateRef frameState, ArrayMetaDataAccessor accessor);
GateRef ArrayGuardianCheck(GateRef frameState);
GateRef TypedArrayCheck(GateRef gate, GateType type, TypedArrayMetaDateAccessor::Mode mode,
GateRef TypedArrayCheck(GateRef gate, ParamType paramType, TypedArrayMetaDateAccessor::Mode mode,
OnHeapMode onHeap = OnHeapMode::NONE);
GateRef LoadTypedArrayLength(GateRef gate, GateType type, OnHeapMode onHeap = OnHeapMode::NONE);
GateRef LoadTypedArrayLength(GateRef gate, ParamType paramType, OnHeapMode onHeap = OnHeapMode::NONE);
GateRef RangeGuard(GateRef gate, uint32_t left, uint32_t right);
GateRef BuiltinPrototypeHClassCheck(GateRef gate, BuiltinTypeId type, ElementsKind kind,
bool isPrototypeOfPrototype);
GateRef OrdinaryHasInstanceCheck(GateRef target, GateRef jsFunc, std::vector<GateRef> &expectedHCIndexes);
GateRef IndexCheck(GateRef gate, GateRef index);
GateRef ObjectTypeCheck(GateType type, bool isHeapObject, GateRef gate, GateRef hclassIndex,
GateRef ObjectTypeCheck(bool isHeapObject, GateRef gate, GateRef hclassIndex,
GateRef frameState = Gate::InvalidGateRef);
GateRef TryPrimitiveTypeCheck(GateType type, GateRef gate);
GateRef CallTargetCheck(GateRef gate, GateRef function, GateRef id, const char* comment = nullptr);
GateRef CallTargetCheck(GateRef gate, GateRef function, GateRef id, std::vector<GateRef> params,
const char* comment = nullptr);
GateRef JSCallTargetFromDefineFuncCheck(GateType type, GateRef func, GateRef gate);
GateRef JSCallTargetFromDefineFuncCheck(GateRef func, GateRef gate);
template<TypedCallTargetCheckOp Op>
GateRef JSCallTargetTypeCheck(GateType type, GateRef func, GateRef methodIndex, GateRef gate);
GateRef JSCallTargetTypeCheck(GateRef func, GateRef methodIndex, GateRef gate);
template<TypedCallTargetCheckOp Op>
GateRef JSCallThisTargetTypeCheck(GateType type, GateRef func, GateRef gate);
GateRef JSCallThisTargetTypeCheck(GateRef func, GateRef gate);
template<TypedCallTargetCheckOp Op>
inline GateRef JSNoGCCallThisTargetTypeCheck(GateType type, GateRef func, GateRef methodId, GateRef gate);
GateRef TypeOfCheck(GateRef gate, GateType type);
GateRef TypedTypeOf(GateType type);
inline GateRef JSNoGCCallThisTargetTypeCheck(GateRef func, GateRef methodId, GateRef gate);
GateRef TypeOfCheck(GateRef gate, ParamType paramType);
GateRef TypedTypeOf(ParamType paramType);
GateRef TypedCallOperator(GateRef hirGate, MachineType type, const std::vector<GateRef>& inList, bool isSideEffect);
inline GateRef TypedCallBuiltin(GateRef hirGate, const std::vector<GateRef> &args,
BuiltinsStubCSigns::ID id, bool isSideEffect);
GateRef TypeConvert(MachineType type, GateType typeFrom, GateType typeTo, const std::vector<GateRef>& inList);
GateRef TypeConvert(MachineType type, ParamType typeFrom, GateType typeTo, const std::vector<GateRef>& inList);
GateRef Int32CheckRightIsZero(GateRef right);
GateRef RemainderIsNegativeZero(GateRef left, GateRef right);
GateRef Float64CheckRightIsZero(GateRef right);
@ -544,20 +544,18 @@ public:
GateRef InsertTypedArrayCheck(GateType type, GateRef array);
GateRef ArrayConstructorCheck(GateRef gate);
GateRef ObjectConstructorCheck(GateRef gate);
GateRef InsertTypedBinaryop(GateRef left, GateRef right, GateType leftType, GateType rightType,
GateType gateType, PGOTypeRef pgoType, TypedBinOp op);
GateRef InsertTypedBinaryop(GateRef left, GateRef right, TypedBinOp op);
GateRef InsertRangeCheckPredicate(GateRef left, TypedBinOp cond, GateRef right);
GateRef TypedConditionJump(MachineType type, TypedJumpOp jumpOp, uint32_t weight, GateType typeVal,
GateRef TypedConditionJump(MachineType type, TypedJumpOp jumpOp, uint32_t weight, ParamType paramType,
const std::vector<GateRef>& inList);
GateRef TypedNewAllocateThis(GateRef ctor, GateRef hclassIndex, GateRef frameState);
GateRef TypedSuperAllocateThis(GateRef superCtor, GateRef newTarget, GateRef frameState);
template<TypedBinOp Op>
inline GateRef TypedBinaryOp(GateRef x, GateRef y, GateType xType, GateType yType, GateType gateType,
PGOTypeRef pgoType);
inline GateRef TypedBinaryOp(GateRef x, GateRef y, ParamType paramType);
template<TypedUnOp Op>
inline GateRef TypedUnaryOp(GateRef x, GateType xType, GateType gateType);
inline GateRef TypedUnaryOp(GateRef x, ParamType paramType);
template<TypedJumpOp Op>
inline GateRef TypedConditionJump(GateRef x, GateType xType, uint32_t weight);
inline GateRef TypedConditionJump(GateRef x, ParamType paramType, uint32_t weight);
GateRef Convert(GateRef gate, ValueType src, ValueType dst);
GateRef ConvertBoolToTaggedBoolean(GateRef gate);
GateRef ConvertTaggedBooleanToBool(GateRef gate);
@ -606,7 +604,7 @@ public:
GateRef StartAllocate();
GateRef FinishAllocate(GateRef value);
inline GateRef PrimitiveToNumber(GateRef x, VariableType type);
inline GateRef PrimitiveToNumber(GateRef x, ParamType paramType);
inline GateRef GetValueFromTaggedArray(GateRef array, GateRef index);
inline GateRef GetValueFromTaggedArray(VariableType valType, GateRef array, GateRef index);
inline GateRef GetValueFromJSArrayWithElementsKind(VariableType type, GateRef array, GateRef index);

View File

@ -257,10 +257,10 @@ bool CompilationDriver::FilterOption(const std::map<std::string, std::vector<std
return find(vec.begin(), vec.end(), methodName) != vec.end();
}
void CompilationDriver::SetCurrentConstantPool(uint32_t methodOffset) const
void CompilationDriver::SetCurrentCompilationFile() const
{
PGOTypeManager *ptManager = vm_->GetJSThread()->GetCurrentEcmaContext()->GetPTManager();
ptManager->SetCurConstantPool(jsPandaFile_, methodOffset);
ptManager->SetCurCompilationFile(jsPandaFile_);
}
void CompilationDriver::StoreConstantPoolInfo() const

View File

@ -87,7 +87,6 @@ public:
MethodInfo &methodInfo)
{
Module *module = GetModule();
SetCurrentConstantPool(methodOffset);
cb(bytecodeInfo_.GetRecordName(index), methodName, methodLiteral, methodOffset,
methodPcInfo, methodInfo, module);
if (methodInfo.IsTypeInferAbort()) {
@ -102,6 +101,7 @@ public:
{
UpdatePGO();
InitializeCompileQueue();
SetCurrentCompilationFile();
uint32_t index = 0;
auto &methodList = bytecodeInfo_.GetMethodList();
const auto &methodPcInfos = bytecodeInfo_.GetMethodPcInfos();
@ -353,7 +353,7 @@ protected:
bool FilterOption(const std::map<std::string, std::vector<std::string>> &optionMap, const std::string &recordName,
const std::string &methodName) const;
void SetCurrentConstantPool(uint32_t methodOffset) const;
void SetCurrentCompilationFile() const;
void StoreConstantPoolInfo() const;

View File

@ -256,7 +256,7 @@ void PGOTypeLogList::CollectGateTypeLogInfo(GateRef gate, bool isBinOp)
const PGOSampleType *sampleType = acc_.TryGetPGOType(gate).GetPGOSampleType();
if (sampleType->IsString()) {
log_ += " [left type: string, right type: string]";
} else if (sampleType->IsNumber()) {
} else if (sampleType->HasNumber()) {
if (sampleType->IsInt()) {
log_ += " [left type: int, right type: int]";
} else {

View File

@ -349,20 +349,14 @@ bool EarlyElimination::CheckReplacement(GateRef lhs, GateRef rhs)
break;
}
case OpCode::TYPED_ARRAY_CHECK: {
if (acc_.GetTypedArrayMetaDateAccessor(lhs).GetType() !=
acc_.GetTypedArrayMetaDateAccessor(rhs).GetType()) {
if (acc_.GetTypedArrayMetaDateAccessor(lhs).GetParamType() !=
acc_.GetTypedArrayMetaDateAccessor(rhs).GetParamType()) {
return false;
}
break;
}
case OpCode::TYPE_OF_CHECK: {
if (acc_.GetParamGateType(lhs) != acc_.GetParamGateType(rhs)) {
return false;
}
break;
}
case OpCode::OBJECT_TYPE_CHECK: {
if (acc_.GetObjectTypeAccessor(lhs).GetType() != acc_.GetObjectTypeAccessor(rhs).GetType()) {
if (acc_.GetParamType(lhs) != acc_.GetParamType(rhs)) {
return false;
}
break;

View File

@ -12,17 +12,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/compiler/bytecode_circuit_builder.h"
#include "ecmascript/compiler/frame_states.h"
#include "ecmascript/ts_types/ts_manager.h"
#include <cstddef>
#include "ecmascript/compiler/bytecode_circuit_builder.h"
namespace panda::ecmascript::kungfu {
FrameStateBuilder::FrameStateBuilder(BytecodeCircuitBuilder *builder,
Circuit *circuit, const MethodLiteral *literal)
: bcBuilder_(builder),
tsManager_(builder->GetTSManager()),
typeRecorder_(builder->GetTypeRecorder()),
pgoTypeRecorder_(builder->GetPGOTypeRecorder()),
numVregs_(literal->GetNumberVRegs() + FIXED_ARGS),
accumulatorIndex_(literal->GetNumberVRegs() + 1), // 1: acc
@ -254,11 +253,8 @@ FrameContext *FrameStateBuilder::GetOrOCreateMergedContext(uint32_t bbIndex)
return context;
}
void FrameStateBuilder::FillBcInputs(const BytecodeInfo &bytecodeInfo, uint32_t bcIndex, GateRef gate)
void FrameStateBuilder::FillBcInputs(const BytecodeInfo &bytecodeInfo, GateRef gate)
{
auto type = typeRecorder_->GetType(bcIndex);
acc_.SetGateType(gate, type);
EcmaOpcode opcode = bytecodeInfo.GetOpcode();
auto pgoType = pgoTypeRecorder_->GetPGOType(acc_.TryGetPcOffset(gate));
acc_.TrySetPGOType(gate, pgoType);
@ -280,13 +276,6 @@ void FrameStateBuilder::FillBcInputs(const BytecodeInfo &bytecodeInfo, uint32_t
acc_.NewIn(gate, inIdx, defVreg);
} else {
GateRef defAcc = liveContext_->ValuesAt(accumulatorIndex_);
if (Bytecodes::IsCallOp(opcode)) {
auto oldGt = acc_.GetGateType(defAcc).GetGTRef();
GateType callTargetType = typeRecorder_->GetCallTargetType(bcIndex);
if (!tsManager_->MethodOffsetIsVaild(oldGt) && !callTargetType.IsAnyType()) {
acc_.SetGateType(defAcc, callTargetType);
}
}
acc_.NewIn(gate, inIdx, defAcc);
}
}
@ -324,7 +313,7 @@ void FrameStateBuilder::UpdateStateDepend(GateRef state, GateRef depend)
liveContext_->currentDepend_ = depend;
}
void FrameStateBuilder::UpdateMoveValues(const BytecodeInfo &bytecodeInfo, uint32_t bcId)
void FrameStateBuilder::UpdateMoveValues(const BytecodeInfo &bytecodeInfo)
{
GateRef gate = Circuit::NullGate();
if (bytecodeInfo.AccIn()) {
@ -340,13 +329,6 @@ void FrameStateBuilder::UpdateMoveValues(const BytecodeInfo &bytecodeInfo, uint3
auto vreg = bytecodeInfo.vregOut[0];
liveContext_->SetValuesAt(vreg, gate);
}
if (bcBuilder_->HasTypes()) {
GateType type = acc_.GetGateType(gate);
if (type.IsAnyType()) {
type = typeRecorder_->UpdateType(bcId, type);
acc_.SetGateType(gate, type);
}
}
}
void FrameStateBuilder::UpdateFrameValues(const BytecodeInfo &bytecodeInfo,
@ -359,7 +341,7 @@ void FrameStateBuilder::UpdateFrameValues(const BytecodeInfo &bytecodeInfo,
}
// jump gate is null
if (gate != Circuit::NullGate()) {
FillBcInputs(bytecodeInfo, bcId, gate);
FillBcInputs(bytecodeInfo, gate);
}
auto liveout = GetFrameLiveoutAfter(bcId);
// variable kill

View File

@ -16,7 +16,6 @@
#ifndef ECMASCRIPT_COMPILER_FRAME_STATE_H
#define ECMASCRIPT_COMPILER_FRAME_STATE_H
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/compiler/base/bit_set.h"
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/gate.h"
@ -115,7 +114,7 @@ public:
void AdvanceToNextBc(const BytecodeInfo &bytecodeInfo, FrameLiveOut* liveout, uint32_t bcId);
void UpdateFrameValues(const BytecodeInfo &bytecodeInfo, uint32_t bcId,
GateRef gate);
void UpdateMoveValues(const BytecodeInfo &bytecodeInfo, uint32_t bcId);
void UpdateMoveValues(const BytecodeInfo &bytecodeInfo);
void UpdateStateDepend(GateRef state, GateRef depend);
FrameLiveOut *GetOrOCreateBCEndLiveOut(uint32_t bcIndex);
FrameLiveOut *GetOrOCreateBBLiveOut(size_t bbIndex);
@ -222,7 +221,7 @@ private:
}
FrameContext *GetOrOCreateMergedContext(uint32_t bbIndex);
void FillBcInputs(const BytecodeInfo &bytecodeInfo, uint32_t bcIndex, GateRef gate);
void FillBcInputs(const BytecodeInfo &bytecodeInfo, GateRef gate);
void DumpLiveState();
size_t GetNumOfStatePreds(const BytecodeRegion &bb);
GateRef MergeValue(const BytecodeRegion &bb,
@ -254,8 +253,6 @@ private:
FrameContext *GetCachedContext();
BytecodeCircuitBuilder *bcBuilder_ {nullptr};
TSManager *tsManager_ {nullptr};
const TypeRecorder *typeRecorder_ {nullptr};
const PGOTypeRecorder *pgoTypeRecorder_ {nullptr};
FrameLiveOut *liveOutResult_ {nullptr};
FrameLiveOut *currentBBliveOut_ {nullptr};

View File

@ -782,11 +782,8 @@ std::string Gate::GateTypeStr(GateType gateType) const
if (strMap.count(gateType) > 0) {
name = strMap.at(gateType);
}
GlobalTSTypeRef r = gateType.GetGTRef();
uint32_t m = r.GetModuleId();
uint32_t l = r.GetLocalId();
return name + std::string("-GT(M=") + std::to_string(m) +
std::string(", L=") + std::to_string(l) + std::string(")");
uint32_t r = gateType.GetType();
return name + std::string("-gateType(") + std::to_string(r) + std::string(")");
}
void Gate::Print(std::string additionOp, bool inListPreview, size_t highlightIdx) const
@ -934,7 +931,8 @@ void Gate::PrintWithBytecode() const
break;
}
case OpCode::TYPED_BINARY_OP: {
bytecodeStr = GetTypedBinaryMetaData()->Str();
auto typedOp = TypedBinaryAccessor(GetOneParameterMetaData()->GetValue()).GetTypedBinOp();
bytecodeStr = GateMetaData::Str(typedOp);
break;
}
case OpCode::TYPED_UNARY_OP: {
@ -958,7 +956,8 @@ void Gate::PrintWithBytecode() const
break;
}
case OpCode::TYPED_CALLTARGETCHECK_OP: {
auto typedOp = GetTypedCallTargetCheckMetaData()->GetTypedCallTargetCheckOp();
TypedCallTargetCheckAccessor accessor(GetOneParameterMetaData()->GetValue());
auto typedOp = accessor.GetCallTargetCheckOp();
bytecodeStr = GateMetaData::Str(typedOp);
break;
}

View File

@ -227,16 +227,6 @@ public:
return OneParameterMetaData::Cast(meta_);
}
const TypedBinaryMetaData* GetTypedBinaryMetaData() const
{
return TypedBinaryMetaData::Cast(meta_);
}
const TypedCallTargetCheckMetaData* GetTypedCallTargetCheckMetaData() const
{
return TypedCallTargetCheckMetaData::Cast(meta_);
}
const StringMetaData* GetStringMetaData() const
{
ASSERT(meta_->IsStringType());

View File

@ -338,21 +338,6 @@ bool GateAccessor::TypedOpIsTypedArray(GateRef gate, TypedOpKind kind) const
}
}
GateType GateAccessor::GetReceiverType([[maybe_unused]]GateRef gate) const
{
return GateType::Empty();
}
GateType GateAccessor::GetHolderType([[maybe_unused]]GateRef gate) const
{
return GateType::Empty();
}
GateType GateAccessor::GetNewHolderType([[maybe_unused]]GateRef gate) const
{
return GateType::Empty();
}
TypedLoadOp GateAccessor::GetTypedLoadOp(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::LOAD_ELEMENT);
@ -370,8 +355,8 @@ TypedStoreOp GateAccessor::GetTypedStoreOp(GateRef gate) const
TypedCallTargetCheckOp GateAccessor::GetTypedCallTargetCheckOp(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::TYPED_CALLTARGETCHECK_OP);
Gate *gatePtr = circuit_->LoadGatePtr(gate);
return gatePtr->GetTypedCallTargetCheckMetaData()->GetTypedCallTargetCheckOp();
TypedCallTargetCheckAccessor accessor(TryGetValue(gate));
return accessor.GetCallTargetCheckOp();
}
MemoryType GateAccessor::GetMemoryType(GateRef gate) const
@ -392,52 +377,26 @@ uint32_t GateAccessor::GetHClassIndex(GateRef gate) const
TypedBinOp GateAccessor::GetTypedBinaryOp(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::TYPED_BINARY_OP);
Gate *gatePtr = circuit_->LoadGatePtr(gate);
return gatePtr->GetTypedBinaryMetaData()->GetTypedBinaryOp();
}
PGOTypeRef GateAccessor::GetTypedBinaryType(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::TYPED_BINARY_OP);
Gate *gatePtr = circuit_->LoadGatePtr(gate);
return gatePtr->GetTypedBinaryMetaData()->GetType();
TypedBinaryAccessor accessor(TryGetValue(gate));
return accessor.GetTypedBinOp();
}
bool GateAccessor::HasNumberType(GateRef gate) const
{
auto sampleType = GetTypedBinaryType(gate).GetPGOSampleType();
if (sampleType->IsNumber()) {
return true;
}
if (sampleType->IsNone()) {
GateType leftType = GetLeftType(gate);
GateType rightType = GetRightType(gate);
if (leftType.IsNumberType() && rightType.IsNumberType()) {
return true;
}
OpCode op = GetOpCode(gate);
if (op == OpCode::TYPED_BINARY_OP) {
TypedBinaryAccessor accessor(TryGetValue(gate));
return accessor.GetParamType().HasNumberType();
}
return false;
}
bool GateAccessor::HasStringType(GateRef gate) const
{
const PGOSampleType *sampleType = TryGetPGOType(gate).GetPGOSampleType();
return sampleType->IsString();
}
// Include number, undefined, null and boolean type.
bool GateAccessor::HasPrimitiveNumberType(GateRef gate) const
{
auto sampleType = GetTypedBinaryType(gate).GetPGOSampleType();
if (sampleType->IsNumber()) {
return true;
}
if (sampleType->IsNone()) {
GateType leftType = GetLeftType(gate);
GateType rightType = GetRightType(gate);
if (leftType.IsPrimitiveNumberType() && rightType.IsPrimitiveNumberType()) {
return true;
}
OpCode op = GetOpCode(gate);
if (op == OpCode::TYPED_BINARY_OP) {
TypedBinaryAccessor accessor(TryGetValue(gate));
return accessor.GetParamType().IsStringType();
}
return false;
}
@ -452,17 +411,21 @@ GlobalTSTypeRef GateAccessor::GetFuncGT(GateRef gate) const
GateType GateAccessor::GetParamGateType(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::PRIMITIVE_TYPE_CHECK ||
GetOpCode(gate) == OpCode::INDEX_CHECK ||
GetOpCode(gate) == OpCode::TYPED_CALLTARGETCHECK_OP ||
GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER ||
GetOpCode(gate) == OpCode::TYPE_OF_CHECK ||
GetOpCode(gate) == OpCode::TYPE_OF);
// NOTICE-PGO: consider to delete this function in Part3, only primitive_type_check use,
// which is generate in the retype pass
ASSERT(GetOpCode(gate) == OpCode::PRIMITIVE_TYPE_CHECK);
Gate *gatePtr = circuit_->LoadGatePtr(gate);
GateTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
return accessor.GetGateType();
}
ParamType GateAccessor::GetParamType(GateRef gate) const
{
Gate *gatePtr = circuit_->LoadGatePtr(gate);
GateTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
return accessor.GetParamType();
}
bool GateAccessor::IsConvertSupport(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::CONVERT ||
@ -490,25 +453,6 @@ ValueType GateAccessor::GetDstType(GateRef gate) const
return accessor.GetDstType();
}
GateType GateAccessor::GetLeftType(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::TYPED_UNARY_OP ||
GetOpCode(gate) == OpCode::TYPED_BINARY_OP ||
GetOpCode(gate) == OpCode::TYPE_CONVERT);
Gate *gatePtr = circuit_->LoadGatePtr(gate);
GatePairTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
return accessor.GetLeftType();
}
GateType GateAccessor::GetRightType(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::TYPED_BINARY_OP ||
GetOpCode(gate) == OpCode::TYPE_CONVERT);
Gate *gatePtr = circuit_->LoadGatePtr(gate);
GatePairTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
return accessor.GetRightType();
}
uint32_t GateAccessor::GetFirstValue(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::RANGE_GUARD);
@ -671,9 +615,6 @@ PGOTypeRef GateAccessor::TryGetPGOType(GateRef gate) const
if (op == OpCode::JS_BYTECODE) {
return gatePtr->GetJSBytecodeMetaData()->GetType();
}
if (op == OpCode::TYPED_BINARY_OP) {
return GetTypedBinaryType(gate);
}
return PGOTypeRef::NoneType();
}
@ -1998,4 +1939,46 @@ uint32_t GateAccessor::GetConstpoolId(GateRef gate) const
Gate *gatePtr = circuit_->LoadGatePtr(gate);
return gatePtr->GetOneParameterMetaData()->GetValue();
}
TypedBinOp GateAccessor::GetRevCompareOpForTypedBinOp(TypedBinOp op)
{
switch (op) {
case TypedBinOp::TYPED_LESS:
return TypedBinOp::TYPED_GREATEREQ;
case TypedBinOp::TYPED_LESSEQ:
return TypedBinOp::TYPED_GREATER;
case TypedBinOp::TYPED_GREATER:
return TypedBinOp::TYPED_LESSEQ;
case TypedBinOp::TYPED_GREATEREQ:
return TypedBinOp::TYPED_LESS;
case TypedBinOp::TYPED_EQ:
return TypedBinOp::TYPED_NOTEQ;
case TypedBinOp::TYPED_NOTEQ:
return TypedBinOp::TYPED_EQ;
default:
UNREACHABLE();
return op;
}
}
TypedBinOp GateAccessor::GetSwapCompareOpForTypedBinOp(TypedBinOp op)
{
switch (op) {
case TypedBinOp::TYPED_LESS:
return TypedBinOp::TYPED_GREATER;
case TypedBinOp::TYPED_LESSEQ:
return TypedBinOp::TYPED_GREATEREQ;
case TypedBinOp::TYPED_GREATER:
return TypedBinOp::TYPED_LESS;
case TypedBinOp::TYPED_GREATEREQ:
return TypedBinOp::TYPED_LESSEQ;
case TypedBinOp::TYPED_EQ:
return TypedBinOp::TYPED_EQ;
case TypedBinOp::TYPED_NOTEQ:
return TypedBinOp::TYPED_NOTEQ;
default:
UNREACHABLE();
return op;
}
}
} // namespace panda::ecmascript::kungfu

View File

@ -398,21 +398,17 @@ public:
void SetElementsKind(GateRef gate, ElementsKind kind);
size_t GetVirtualRegisterIndex(GateRef gate) const;
bool TypedOpIsTypedArray(GateRef gate, TypedOpKind kind) const;
GateType GetReceiverType(GateRef gate) const;
GateType GetHolderType(GateRef gate) const;
GateType GetNewHolderType(GateRef gate) const;
TypedLoadOp GetTypedLoadOp(GateRef gate) const;
TypedStoreOp GetTypedStoreOp(GateRef gate) const;
MemoryType GetMemoryType(GateRef gate) const;
uint32_t GetHClassIndex(GateRef gate) const;
TypedBinOp GetTypedBinaryOp(GateRef gate) const;
TypedCallTargetCheckOp GetTypedCallTargetCheckOp(GateRef gate) const;
PGOTypeRef GetTypedBinaryType(GateRef gate) const;
bool HasPrimitiveNumberType(GateRef gate) const;
bool HasNumberType(GateRef gate) const;
bool HasStringType(GateRef gate) const;
GlobalTSTypeRef GetFuncGT(GateRef gate) const;
GateType GetParamGateType(GateRef gate) const;
ParamType GetParamType(GateRef gate) const;
TypedUnaryAccessor GetTypedUnAccessor(GateRef gate) const;
TypedBinaryAccessor GetTypedBinaryAccessor(GateRef gate) const;
TypedJumpAccessor GetTypedJumpAccessor(GateRef gate) const;
@ -543,8 +539,6 @@ public:
void ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value);
void ReplaceGate(GateRef gate, StateDepend stateDepend, GateRef replacement);
void ReplaceGate(GateRef gate, GateRef replacement);
GateType GetLeftType(GateRef gate) const;
GateType GetRightType(GateRef gate) const;
uint32_t GetFirstValue(GateRef gate) const;
uint32_t GetSecondValue(GateRef gate) const;
GateRef GetGlueFromArgList() const;
@ -617,6 +611,9 @@ public:
void SetStoreNoBarrier(GateRef gate, bool isNoBarrier);
bool IsNoBarrier(GateRef gate) const;
TypedBinOp GetRevCompareOpForTypedBinOp(TypedBinOp op);
TypedBinOp GetSwapCompareOpForTypedBinOp(TypedBinOp op);
private:
const GateMetaData *GetMetaData(GateRef gate) const;
UseIterator ReplaceHirIfSuccess(const UseIterator &useIt, GateRef state);

View File

@ -146,16 +146,6 @@ public:
return new (chunk_) JSBytecodeMetaData(valuesIn, methodId, opcode, pcOffset, bcIndex, flags);
}
const GateMetaData* TypedBinaryOp(uint64_t value, TypedBinOp binOp, PGOTypeRef type)
{
return new (chunk_) TypedBinaryMetaData(value, binOp, type);
}
const GateMetaData* TypedCallTargetCheckOp(uint32_t numIns, uint64_t value, TypedCallTargetCheckOp checkOp)
{
return new (chunk_) TypedCallTargetCheckMetaData(numIns, value, checkOp);
}
const GateMetaData* Nop()
{
return &cachedNop_;

View File

@ -28,7 +28,7 @@
namespace panda::ecmascript::kungfu {
GateRef CircuitBuilder::ObjectTypeCheck(GateType type, bool isHeapObject, GateRef gate, GateRef hclassIndex,
GateRef CircuitBuilder::ObjectTypeCheck(bool isHeapObject, GateRef gate, GateRef hclassIndex,
GateRef frameState)
{
auto currentLabel = env_->GetCurrentLabel();
@ -37,7 +37,7 @@ GateRef CircuitBuilder::ObjectTypeCheck(GateType type, bool isHeapObject, GateRe
if (frameState == Circuit::NullGate()) {
frameState = acc_.FindNearestFrameState(currentDepend);
}
ObjectTypeAccessor accessor(type, isHeapObject);
ObjectTypeAccessor accessor(isHeapObject);
GateRef ret = GetCircuit()->NewGate(circuit_->ObjectTypeCheck(accessor.ToValue()), MachineType::I1,
{currentControl, currentDepend, gate, hclassIndex, frameState}, GateType::NJSValue());
currentLabel->SetControl(ret);
@ -180,28 +180,29 @@ GateRef CircuitBuilder::ArrayGuardianCheck(GateRef frameState)
return ret;
}
GateRef CircuitBuilder::TypedArrayCheck(GateRef gate, GateType type, TypedArrayMetaDateAccessor::Mode mode,
GateRef CircuitBuilder::TypedArrayCheck(GateRef gate, ParamType type, TypedArrayMetaDateAccessor::Mode mode,
OnHeapMode onHeap)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto frameState = acc_.FindNearestFrameState(currentDepend);
TypedArrayMetaDateAccessor accessor(type, mode, onHeap);
GateRef ret = GetCircuit()->NewGate(circuit_->TypedArrayCheck(accessor.ToValue()), MachineType::I1,
uint64_t value = TypedArrayMetaDateAccessor::ToValue(type, mode, onHeap);
GateRef ret = GetCircuit()->NewGate(circuit_->TypedArrayCheck(value), MachineType::I1,
{currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
return ret;
}
GateRef CircuitBuilder::LoadTypedArrayLength(GateRef gate, GateType type, OnHeapMode onHeap)
GateRef CircuitBuilder::LoadTypedArrayLength(GateRef gate, ParamType paramType, OnHeapMode onHeap)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
TypedArrayMetaDateAccessor accessor(type, TypedArrayMetaDateAccessor::Mode::LOAD_LENGTH, onHeap);
GateRef ret = GetCircuit()->NewGate(circuit_->LoadTypedArrayLength(accessor.ToValue()), MachineType::I64,
uint64_t value = TypedArrayMetaDateAccessor::ToValue(paramType,
TypedArrayMetaDateAccessor::Mode::LOAD_LENGTH, onHeap);
GateRef ret = GetCircuit()->NewGate(circuit_->LoadTypedArrayLength(value), MachineType::I64,
{currentControl, currentDepend, gate}, GateType::IntType());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
@ -274,25 +275,25 @@ GateRef CircuitBuilder::IndexCheck(GateRef gate, GateRef index)
return ret;
}
GateRef CircuitBuilder::TypeOfCheck(GateRef gate, GateType type)
GateRef CircuitBuilder::TypeOfCheck(GateRef gate, ParamType paramType)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto frameState = acc_.FindNearestFrameState(currentDepend);
GateRef ret = GetCircuit()->NewGate(circuit_->TypeOfCheck(static_cast<size_t>(type.Value())),
GateRef ret = GetCircuit()->NewGate(circuit_->TypeOfCheck(static_cast<uint64_t>(paramType.Value())),
MachineType::I64, {currentControl, currentDepend, gate, frameState}, GateType::IntType());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
return ret;
}
GateRef CircuitBuilder::TypedTypeOf(GateType type)
GateRef CircuitBuilder::TypedTypeOf(ParamType paramType)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
GateRef ret = GetCircuit()->NewGate(circuit_->TypeOf(static_cast<size_t>(type.Value())),
GateRef ret = GetCircuit()->NewGate(circuit_->TypeOf(static_cast<uint64_t>(paramType.Value())),
MachineType::I64, {currentControl, currentDepend}, GateType::AnyType());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
@ -582,15 +583,15 @@ GateRef CircuitBuilder::CallTargetCheck(GateRef gate, GateRef function, GateRef
return ret;
}
GateRef CircuitBuilder::JSCallTargetFromDefineFuncCheck(GateType type, GateRef func, GateRef gate)
GateRef CircuitBuilder::JSCallTargetFromDefineFuncCheck(GateRef func, GateRef gate)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto frameState = acc_.GetFrameState(gate);
GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(1, static_cast<size_t>(type.Value()),
TypedCallTargetCheckOp::JSCALL_IMMEDIATE_AFTER_FUNC_DEF),
MachineType::I1, {currentControl, currentDepend, func, frameState}, GateType::NJSValue());
uint64_t value = TypedCallTargetCheckAccessor::ToValue(TypedCallTargetCheckOp::JSCALL_IMMEDIATE_AFTER_FUNC_DEF);
GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(value), MachineType::I1,
{currentControl, currentDepend, func, IntPtr(INVALID_INDEX), frameState}, GateType::NJSValue());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
return ret;
@ -813,18 +814,18 @@ GateRef CircuitBuilder::Int32DivWithCheck(GateRef left, GateRef right)
}
GateRef CircuitBuilder::TypedConditionJump(MachineType type, TypedJumpOp jumpOp, uint32_t weight,
GateType typeVal, const std::vector<GateRef>& inList)
ParamType paramType, const std::vector<GateRef>& inList)
{
uint64_t value = TypedJumpAccessor::ToValue(typeVal, jumpOp, weight);
uint64_t value = TypedJumpAccessor::ToValue(paramType, jumpOp, weight);
return GetCircuit()->NewGate(circuit_->TypedConditionJump(value),
type, inList.size(), inList.data(), GateType::Empty());
}
GateRef CircuitBuilder::TypeConvert(MachineType type, GateType typeFrom, GateType typeTo,
GateRef CircuitBuilder::TypeConvert(MachineType type, ParamType typeFrom, GateType typeTo,
const std::vector<GateRef>& inList)
{
// merge types of valueIns before and after convertion
uint64_t operandTypes = GatePairTypeAccessor::ToValue(typeFrom, typeTo);
uint64_t operandTypes = TypeConvertAccessor::ToValue(typeFrom, typeTo);
return GetCircuit()->NewGate(circuit_->TypedConvert(operandTypes),
type, inList.size(), inList.data(), GateType::AnyType());
}
@ -1063,17 +1064,16 @@ GateType CircuitBuilder::GetGateTypeOfValueType(ValueType type)
}
}
GateRef CircuitBuilder::InsertTypedBinaryop(GateRef left, GateRef right, GateType leftType, GateType rightType,
GateType gateType, PGOTypeRef pgoType, TypedBinOp op)
GateRef CircuitBuilder::InsertTypedBinaryop(GateRef left, GateRef right, TypedBinOp op)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
uint64_t operandTypes = GatePairTypeAccessor::ToValue(leftType, rightType);
auto ret = GetCircuit()->NewGate(circuit_->TypedBinaryOp(operandTypes, op, pgoType),
uint64_t value = TypedBinaryAccessor::ToValue(ParamType::NumberType(), op);
auto ret = GetCircuit()->NewGate(circuit_->TypedBinaryOp(value),
MachineType::I64,
{currentControl, currentDepend, left, right},
gateType);
GateType::AnyType());
acc_.ReplaceInAfterInsert(currentControl, currentDepend, ret);
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
@ -1086,8 +1086,8 @@ GateRef CircuitBuilder::InsertRangeCheckPredicate(GateRef left, TypedBinOp cond,
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto frameState = acc_.FindNearestFrameState(currentDepend);
TypedBinaryAccessor accessor(GateType::IntType(), cond);
auto ret = GetCircuit()->NewGate(circuit_->RangeCheckPredicate(accessor.ToValue()),
uint64_t value = TypedBinaryAccessor::ToValue(ParamType::IntType(), cond);
auto ret = GetCircuit()->NewGate(circuit_->RangeCheckPredicate(value),
MachineType::I32,
{currentControl, currentDepend, left, right, frameState},
GateType::IntType());

View File

@ -583,29 +583,28 @@ inline GateRef CircuitBuilder::TypedCallBuiltin(GateRef hirGate, const std::vect
}
template<TypedBinOp Op>
GateRef CircuitBuilder::TypedBinaryOp(GateRef x, GateRef y, GateType xType, GateType yType, GateType gateType,
PGOTypeRef pgoType)
GateRef CircuitBuilder::TypedBinaryOp(GateRef x, GateRef y, ParamType paramType)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
uint64_t operandTypes = GatePairTypeAccessor::ToValue(xType, yType);
auto numberBinaryOp = GetCircuit()->NewGate(circuit_->TypedBinaryOp(operandTypes, Op, pgoType),
MachineType::I64, {currentControl, currentDepend, x, y}, gateType);
uint64_t value = TypedBinaryAccessor::ToValue(paramType, Op);
auto numberBinaryOp = GetCircuit()->NewGate(circuit_->TypedBinaryOp(value),
MachineType::I64, {currentControl, currentDepend, x, y}, GateType::AnyType());
currentLabel->SetControl(numberBinaryOp);
currentLabel->SetDepend(numberBinaryOp);
return numberBinaryOp;
}
template<TypedCallTargetCheckOp Op>
GateRef CircuitBuilder::JSNoGCCallThisTargetTypeCheck(GateType type, GateRef func, GateRef methodId, GateRef gate)
GateRef CircuitBuilder::JSNoGCCallThisTargetTypeCheck(GateRef func, GateRef methodId, GateRef gate)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto frameState = acc_.GetFrameState(gate);
GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(CircuitBuilder::GATE_TWO_VALUESIN,
static_cast<size_t>(type.Value()), Op), MachineType::I1,
uint64_t value = TypedCallTargetCheckAccessor::ToValue(Op);
GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(value), MachineType::I1,
{currentControl, currentDepend, func, methodId, frameState}, GateType::NJSValue());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
@ -613,14 +612,14 @@ GateRef CircuitBuilder::JSNoGCCallThisTargetTypeCheck(GateType type, GateRef fun
}
template<TypedCallTargetCheckOp Op>
GateRef CircuitBuilder::JSCallTargetTypeCheck(GateType type, GateRef func, GateRef methodIndex, GateRef gate)
GateRef CircuitBuilder::JSCallTargetTypeCheck(GateRef func, GateRef methodIndex, GateRef gate)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto frameState = acc_.GetFrameState(gate);
GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(CircuitBuilder::GATE_TWO_VALUESIN,
static_cast<size_t>(type.Value()), Op), MachineType::I1,
uint64_t value = TypedCallTargetCheckAccessor::ToValue(Op);
GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(value), MachineType::I1,
{currentControl, currentDepend, func, methodIndex, frameState}, GateType::NJSValue());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
@ -628,41 +627,42 @@ GateRef CircuitBuilder::JSCallTargetTypeCheck(GateType type, GateRef func, GateR
}
template<TypedCallTargetCheckOp Op>
GateRef CircuitBuilder::JSCallThisTargetTypeCheck(GateType type, GateRef func, GateRef gate)
GateRef CircuitBuilder::JSCallThisTargetTypeCheck(GateRef func, GateRef gate)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto frameState = acc_.GetFrameState(gate);
GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(1, static_cast<size_t>(type.Value()), Op),
MachineType::I1, {currentControl, currentDepend, func, frameState}, GateType::NJSValue());
uint64_t value = TypedCallTargetCheckAccessor::ToValue(Op);
GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(value), MachineType::I1,
{currentControl, currentDepend, func, IntPtr(INVALID_INDEX), frameState}, GateType::NJSValue());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
return ret;
}
template<TypedUnOp Op>
GateRef CircuitBuilder::TypedUnaryOp(GateRef x, GateType xType, GateType gateType)
GateRef CircuitBuilder::TypedUnaryOp(GateRef x, ParamType paramType)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
uint64_t value = TypedUnaryAccessor::ToValue(xType, Op);
uint64_t value = TypedUnaryAccessor::ToValue(paramType, Op);
auto numberUnaryOp = GetCircuit()->NewGate(circuit_->TypedUnaryOp(value),
MachineType::I64, {currentControl, currentDepend, x}, gateType);
MachineType::I64, {currentControl, currentDepend, x}, GateType::AnyType());
currentLabel->SetControl(numberUnaryOp);
currentLabel->SetDepend(numberUnaryOp);
return numberUnaryOp;
}
template<TypedJumpOp Op>
GateRef CircuitBuilder::TypedConditionJump(GateRef x, GateType xType, uint32_t weight)
GateRef CircuitBuilder::TypedConditionJump(GateRef x, ParamType paramType, uint32_t weight)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto machineType = MachineType::NOVALUE;
auto jumpOp = TypedConditionJump(machineType, Op, weight, xType, {currentControl, currentDepend, x});
auto jumpOp = TypedConditionJump(machineType, Op, weight, paramType, {currentControl, currentDepend, x});
currentLabel->SetControl(jumpOp);
currentLabel->SetDepend(jumpOp);
return jumpOp;
@ -696,12 +696,13 @@ GateRef CircuitBuilder::StoreElement(GateRef receiver, GateRef index, GateRef va
return ret;
}
GateRef CircuitBuilder::PrimitiveToNumber(GateRef x, VariableType type)
GateRef CircuitBuilder::PrimitiveToNumber(GateRef x, ParamType paramType)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto numberconvert = TypeConvert(MachineType::I64, type.GetGateType(), GateType::NumberType(),
auto numberconvert = TypeConvert(MachineType::I64, paramType, GateType::NumberType(),
{currentControl, currentDepend, x});
currentLabel->SetControl(numberconvert);
currentLabel->SetDepend(numberconvert);

View File

@ -18,49 +18,6 @@
#include "ecmascript/compiler/gate_meta_data_builder.h"
namespace panda::ecmascript::kungfu {
TypedBinOp TypedBinaryMetaData::GetRevCompareOp(TypedBinOp op)
{
switch (op) {
case TypedBinOp::TYPED_LESS:
return TypedBinOp::TYPED_GREATEREQ;
case TypedBinOp::TYPED_LESSEQ:
return TypedBinOp::TYPED_GREATER;
case TypedBinOp::TYPED_GREATER:
return TypedBinOp::TYPED_LESSEQ;
case TypedBinOp::TYPED_GREATEREQ:
return TypedBinOp::TYPED_LESS;
case TypedBinOp::TYPED_EQ:
return TypedBinOp::TYPED_NOTEQ;
case TypedBinOp::TYPED_NOTEQ:
return TypedBinOp::TYPED_EQ;
default:
UNREACHABLE();
return op;
}
}
TypedBinOp TypedBinaryMetaData::GetSwapCompareOp(TypedBinOp op)
{
switch (op) {
case TypedBinOp::TYPED_LESS:
return TypedBinOp::TYPED_GREATER;
case TypedBinOp::TYPED_LESSEQ:
return TypedBinOp::TYPED_GREATEREQ;
case TypedBinOp::TYPED_GREATER:
return TypedBinOp::TYPED_LESS;
case TypedBinOp::TYPED_GREATEREQ:
return TypedBinOp::TYPED_LESSEQ;
case TypedBinOp::TYPED_EQ:
return TypedBinOp::TYPED_EQ;
case TypedBinOp::TYPED_NOTEQ:
return TypedBinOp::TYPED_NOTEQ;
default:
UNREACHABLE();
return op;
}
}
bool GateMetaData::IsTypedOperator() const
{
return (opcode_ == OpCode::TYPED_BINARY_OP) || (opcode_ == OpCode::TYPE_CONVERT) ||
@ -172,4 +129,4 @@ std::string GateMetaData::Str(ValueType type)
}
return "UNKNOW";
}
}
}

View File

@ -204,100 +204,15 @@ private:
bool noGC_;
};
class TypedCallTargetCheckMetaData : public OneParameterMetaData {
public:
TypedCallTargetCheckMetaData(uint32_t valuesIn, uint64_t value, TypedCallTargetCheckOp checkOp)
: OneParameterMetaData(OpCode::TYPED_CALLTARGETCHECK_OP, GateFlags::CHECKABLE, 1, 1, valuesIn, value),
checkOp_(checkOp)
{
SetKind(GateMetaData::Kind::TYPED_CALLTARGETCHECK_OP);
}
bool equal(const GateMetaData &other) const override
{
if (!OneParameterMetaData::equal(other)) {
return false;
}
auto cast_other =
static_cast<const TypedCallTargetCheckMetaData *>(&other);
if (checkOp_ == cast_other->checkOp_) {
return true;
}
return false;
}
static const TypedCallTargetCheckMetaData* Cast(const GateMetaData* meta)
{
meta->AssertKind(GateMetaData::Kind::TYPED_CALLTARGETCHECK_OP);
return static_cast<const TypedCallTargetCheckMetaData*>(meta);
}
TypedCallTargetCheckOp GetTypedCallTargetCheckOp() const
{
return checkOp_;
}
private:
TypedCallTargetCheckOp checkOp_;
};
class TypedBinaryMetaData : public OneParameterMetaData {
public:
TypedBinaryMetaData(uint64_t value, TypedBinOp binOp, PGOTypeRef type)
: OneParameterMetaData(OpCode::TYPED_BINARY_OP, GateFlags::NO_WRITE, 1, 1, 2, value), // 2: valuesIn
binOp_(binOp), type_(type)
{
SetKind(GateMetaData::Kind::TYPED_BINARY_OP);
}
bool equal(const GateMetaData &other) const override
{
if (!OneParameterMetaData::equal(other)) {
return false;
}
auto cast_other = static_cast<const TypedBinaryMetaData *>(&other);
if (binOp_ == cast_other->binOp_ && type_ == cast_other->type_) {
return true;
}
return false;
}
static const TypedBinaryMetaData* Cast(const GateMetaData* meta)
{
meta->AssertKind(GateMetaData::Kind::TYPED_BINARY_OP);
return static_cast<const TypedBinaryMetaData*>(meta);
}
TypedBinOp GetTypedBinaryOp() const
{
return binOp_;
}
PGOTypeRef GetType() const
{
return type_;
}
std::string Str() const
{
return GateMetaData::Str(binOp_);
}
static TypedBinOp GetRevCompareOp(TypedBinOp op);
static TypedBinOp GetSwapCompareOp(TypedBinOp op);
private:
TypedBinOp binOp_;
PGOTypeRef type_;
};
class TypedUnaryAccessor {
public:
// type bits shift
static constexpr int OPRAND_TYPE_BITS = 32;
explicit TypedUnaryAccessor(uint64_t value) : bitField_(value) {}
GateType GetTypeValue() const
ParamType GetParamType() const
{
return GateType(TypedValueBits::Get(bitField_));
return ParamType(TypedValueBits::Get(bitField_));
}
TypedUnOp GetTypedUnOp() const
@ -305,10 +220,9 @@ public:
return TypedUnOpBits::Get(bitField_);
}
static uint64_t ToValue(GateType typeValue, TypedUnOp unaryOp)
static uint64_t ToValue(ParamType paramType, TypedUnOp unaryOp)
{
return TypedValueBits::Encode(typeValue.Value())
| TypedUnOpBits::Encode(unaryOp);
return TypedValueBits::Encode(paramType.Value()) | TypedUnOpBits::Encode(unaryOp);
}
private:
@ -323,14 +237,10 @@ public:
// type bits shift
static constexpr int OPRAND_TYPE_BITS = 32;
explicit TypedBinaryAccessor(uint64_t value) : bitField_(value) {}
explicit TypedBinaryAccessor(GateType gate, TypedBinOp binOp)
{
bitField_ = TypedValueBits::Encode(gate.Value()) | TypedBinOpBits::Encode(binOp);
}
GateType GetTypeValue() const
ParamType GetParamType() const
{
return GateType(TypedValueBits::Get(bitField_));
return ParamType(TypedValueBits::Get(bitField_));
}
TypedBinOp GetTypedBinOp() const
@ -338,9 +248,9 @@ public:
return TypedBinOpBits::Get(bitField_);
}
uint64_t ToValue() const
static uint64_t ToValue(ParamType operandType, TypedBinOp binOp)
{
return bitField_;
return TypedValueBits::Encode(operandType.Value()) | TypedBinOpBits::Encode(binOp);
}
private:
@ -350,6 +260,28 @@ private:
uint64_t bitField_;
};
class TypedCallTargetCheckAccessor {
public:
// type bits shift
static constexpr int CALLTARGETCHECK_OP_BITS = 32;
explicit TypedCallTargetCheckAccessor(uint64_t value) : bitField_(value) {}
TypedCallTargetCheckOp GetCallTargetCheckOp() const
{
return CallTargetCheckOpBits::Get(bitField_);
}
static uint64_t ToValue(TypedCallTargetCheckOp op)
{
return CallTargetCheckOpBits::Encode(op);
}
private:
using CallTargetCheckOpBits = panda::BitField<TypedCallTargetCheckOp, 0, CALLTARGETCHECK_OP_BITS>;
uint64_t bitField_;
};
class BranchAccessor {
public:
// type bits shift
@ -510,9 +442,9 @@ public:
static constexpr int JUMP_OP_BITS = 8;
explicit TypedJumpAccessor(uint64_t value) : bitField_(value) {}
GateType GetTypeValue() const
ParamType GetParamType() const
{
return GateType(TypedValueBits::Get(bitField_));
return ParamType(TypedValueBits::Get(bitField_));
}
TypedJumpOp GetTypedJumpOp() const
@ -530,9 +462,9 @@ public:
return FalseWeightBits::Get(bitField_);
}
static uint64_t ToValue(GateType typeValue, TypedJumpOp jumpOp, uint32_t weight)
static uint64_t ToValue(ParamType paramType, TypedJumpOp jumpOp, uint32_t weight)
{
return TypedValueBits::Encode(typeValue.Value())
return TypedValueBits::Encode(paramType.Value())
| TypedJumpOpBits::Encode(jumpOp)
| WeightBits::Encode(weight);
}

View File

@ -159,6 +159,7 @@ namespace panda::ecmascript::kungfu {
V(PrimitiveTypeCheck, PRIMITIVE_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(TypedArrayCheck, TYPED_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(LoadTypedArrayLength, LOAD_TYPED_ARRAY_LENGTH, GateFlags::NO_WRITE, 1, 1, 1) \
V(TypedBinaryOp, TYPED_BINARY_OP, GateFlags::NO_WRITE, 1, 1, 2) \
V(TypedUnaryOp, TYPED_UNARY_OP, GateFlags::NO_WRITE, 1, 1, 1) \
V(TypedConditionJump, TYPED_CONDITION_JUMP, GateFlags::NO_WRITE, 1, 1, 1) \
V(TypedConvert, TYPE_CONVERT, GateFlags::NO_WRITE, 1, 1, 1) \
@ -166,22 +167,21 @@ namespace panda::ecmascript::kungfu {
V(Convert, CONVERT, GateFlags::NONE_FLAG, 0, 0, 1) \
V(JSInlineTargetTypeCheck, JSINLINETARGET_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
V(TypeOfCheck, TYPE_OF_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(TypeOf, TYPE_OF, GateFlags::NO_WRITE, 1, 1, 0)
V(TypeOf, TYPE_OF, GateFlags::NO_WRITE, 1, 1, 0) \
V(TypedCallTargetCheckOp, TYPED_CALLTARGETCHECK_OP, GateFlags::CHECKABLE, 1, 1, 2 )
// NOTICE-PGO: wx typedcalltargetcheckop can adopt different number of valueIn
#define MCR_GATE_META_DATA_LIST_WITH_ONE_PARAMETER(V) \
MCR_GATE_META_DATA_LIST_WITH_VALUE(V) \
MCR_GATE_META_DATA_LIST_WITH_GATE_TYPE(V)
#define MCR_GATE_OPCODE_LIST(V) \
V(TYPED_BINARY_OP) \
V(TYPED_CALLTARGETCHECK_OP)
}
#define MCR_GATE_META_DATA_LIST_WITH_VALUE_IN(V) \
V(TypedCreateObjWithBuffer, TYPED_CREATE_OBJ_WITH_BUFFER, GateFlags::CHECKABLE, 1, 1, value) \
V(TypedCallCheck, TYPED_CALL_CHECK, GateFlags::CHECKABLE, 1, 1, value)
V(TypedCallCheck, TYPED_CALL_CHECK, GateFlags::CHECKABLE, 1, 1, value)
#define MCR_GATE_META_DATA_LIST_WITH_SIZE(V) \
MCR_GATE_META_DATA_LIST_WITH_VALUE_IN(V)
}
#endif // ECMASCRIPT_COMPILER_MCR_OPCODE_H

View File

@ -73,7 +73,7 @@ void NativeInlineLowering::RunNativeInlineLowering()
}
auto [argc, skipThis] = optCallInfo.value();
CallTypeInfoAccessor ctia(thread_, circuit_, gate);
BuiltinsStubCSigns::ID id = ctia.TryGetPGOBuiltinId();
BuiltinsStubCSigns::ID id = ctia.TryGetPGOBuiltinMethodId();
switch (id) {
case BuiltinsStubCSigns::ID::StringFromCharCode:
TryInlineStringFromCharCode(gate, argc, skipThis);

View File

@ -102,4 +102,4 @@ private:
const JSThread *thread_ {nullptr};
};
}
#endif // ECMASCRIPT_COMPILER_BUILTIN_INLINE_H
#endif // ECMASCRIPT_COMPILER_BUILTIN_INLINE_H

View File

@ -14,9 +14,10 @@
*/
#include "ecmascript/compiler/ntype_bytecode_lowering.h"
#include "ecmascript/compiler/circuit_builder-inl.h"
#include "ecmascript/dfx/vmstat/opt_code_profiler.h"
#include "ecmascript/compiler/type_info_accessors.h"
#include "ecmascript/dfx/vmstat/opt_code_profiler.h"
#include "ecmascript/jspandafile/program_object.h"
namespace panda::ecmascript::kungfu {
@ -204,8 +205,8 @@ void NTypeBytecodeLowering::LowerNTypedCreateArrayWithBuffer(GateRef gate)
GateRef index = acc_.GetValueIn(gate, 0);
uint32_t cpIdx = static_cast<uint32_t>(acc_.GetConstantValue(index));
auto methodOffset = acc_.TryGetMethodOffset(gate);
uint32_t cpId = tsManager_->GetConstantPoolId(methodOffset);
JSTaggedValue cp = tsManager_->GetConstantPool(methodOffset);
uint32_t cpId = ptManager_->GetConstantPoolIDByMethodOffset(methodOffset);
JSTaggedValue cp = ptManager_->GetConstantPoolByMethodOffset(methodOffset);
panda_file::File::EntityId id = ConstantPool::GetIdFromCache(cp, cpIdx);
int elementIndex = ptManager_->GetElementsIndexByEntityId(id);
@ -301,19 +302,21 @@ void NTypeBytecodeLowering::AddProfiling(GateRef gate)
current = gate;
}
GateRef func = builder_.Undefined();
if (acc_.HasFrameState(gate)) {
GateRef func = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
GateRef bcIndex = builder_.Int32ToTaggedInt(builder_.Int32(acc_.TryGetBcIndex(gate)));
EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
auto ecmaOpcodeGate = builder_.Int32(static_cast<uint32_t>(ecmaOpcode));
GateRef constOpcode = builder_.Int32ToTaggedInt(ecmaOpcodeGate);
GateRef mode =
builder_.Int32ToTaggedInt(builder_.Int32(static_cast<int32_t>(OptCodeProfiler::Mode::TYPED_PATH)));
GateRef profiling = builder_.CallRuntime(glue_, RTSTUB_ID(ProfileOptimizedCode), acc_.GetDep(current),
{ func, bcIndex, constOpcode, mode }, gate);
acc_.SetDep(current, profiling);
builder_.SetDepend(acc_.GetDep(gate)); // set gate depend: profiling or STATE_SPLIT
func = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
}
GateRef bcIndex = builder_.Int32ToTaggedInt(builder_.Int32(acc_.TryGetBcIndex(gate)));
EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
auto ecmaOpcodeGate = builder_.Int32(static_cast<uint32_t>(ecmaOpcode));
GateRef constOpcode = builder_.Int32ToTaggedInt(ecmaOpcodeGate);
GateRef mode =
builder_.Int32ToTaggedInt(builder_.Int32(static_cast<int32_t>(OptCodeProfiler::Mode::TYPED_PATH)));
GateRef profiling = builder_.CallRuntime(glue_, RTSTUB_ID(ProfileOptimizedCode), acc_.GetDep(current),
{ func, bcIndex, constOpcode, mode }, gate);
acc_.SetDep(current, profiling);
builder_.SetDepend(acc_.GetDep(gate)); // set gate depend: profiling or STATE_SPLIT
}
}

View File

@ -17,20 +17,16 @@
#define ECMASCRIPT_COMPILER_NTYPE_BYTECODE_LOWERING_H
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
#include "ecmascript/compiler/bytecode_circuit_builder.h"
#include "ecmascript/compiler/circuit_builder-inl.h"
#include "ecmascript/compiler/pass_manager.h"
namespace panda::ecmascript::kungfu {
class NTypeBytecodeLowering {
public:
NTypeBytecodeLowering(Circuit *circuit, PassContext *ctx, TSManager *tsManager,
NTypeBytecodeLowering(Circuit *circuit, PassContext *ctx,
bool enableLog, const std::string& name)
: circuit_(circuit),
acc_(circuit),
builder_(circuit, ctx->GetCompilerConfig()),
tsManager_(tsManager),
ptManager_(ctx->GetPTManager()),
jsPandaFile_(ctx->GetJSPandaFile()),
enableLog_(enableLog),
@ -89,7 +85,6 @@ private:
Circuit *circuit_ {nullptr};
GateAccessor acc_;
CircuitBuilder builder_;
TSManager *tsManager_ {nullptr};
PGOTypeManager *ptManager_ {nullptr};
const JSPandaFile *jsPandaFile_ {nullptr};
bool enableLog_ {false};

View File

@ -13,13 +13,9 @@
* limitations under the License.
*/
#include "ecmascript/js_arguments.h"
#include "ecmascript/compiler/ntype_hcr_lowering.h"
#include "ecmascript/dfx/vmstat/opt_code_profiler.h"
#include "ecmascript/compiler/new_object_stub_builder.h"
namespace panda::ecmascript::kungfu {
GateRef NTypeHCRLowering::VisitGate(GateRef gate)
{
GateRef glue = acc_.GetGlueFromArgList();
@ -172,15 +168,14 @@ GateRef NTypeHCRLowering::NewJSArrayLiteral(GateRef glue, GateRef gate, GateRef
ElementsKind kind = acc_.GetArrayMetaDataAccessor(gate).GetElementsKind();
GateRef hclass = Circuit::NullGate();
if (!Elements::IsGeneric(kind)) {
auto thread = tsManager_->GetEcmaVM()->GetJSThread();
auto hclassIndex = thread->GetArrayHClassIndexMap().at(kind);
auto hclassIndex = thread_->GetArrayHClassIndexMap().at(kind);
hclass = builder_.GetGlobalConstantValue(hclassIndex);
} else {
GateRef globalEnv = builder_.GetGlobalEnv();
hclass = builder_.GetGlobalEnvObjHClass(globalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
}
JSHandle<JSFunction> arrayFunc(tsManager_->GetEcmaVM()->GetGlobalEnv()->GetArrayFunction());
JSHandle<JSFunction> arrayFunc(thread_->GetEcmaVM()->GetGlobalEnv()->GetArrayFunction());
JSTaggedValue protoOrHClass = arrayFunc->GetProtoOrHClass();
JSHClass *arrayHC = JSHClass::Cast(protoOrHClass.GetTaggedObject());
size_t arraySize = arrayHC->GetObjectSize();

View File

@ -16,12 +16,9 @@
#ifndef ECMASCRIPT_COMPILER_NTYPE_HCR_LOWERING_H
#define ECMASCRIPT_COMPILER_NTYPE_HCR_LOWERING_H
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
#include "ecmascript/compiler/bytecode_circuit_builder.h"
#include "ecmascript/compiler/circuit_builder-inl.h"
#include "ecmascript/compiler/combined_pass_visitor.h"
#include "ecmascript/compiler/pass_manager.h"
#include "ecmascript/jspandafile/program_object.h"
namespace panda::ecmascript::kungfu {
class NTypeHCRLowering : public PassVisitor {
@ -33,7 +30,6 @@ public:
thread_(ctx->GetEcmaVM()->GetJSThread()),
builder_(circuit, ctx->GetCompilerConfig()),
dependEntry_(circuit->GetDependRoot()),
tsManager_(ctx->GetTSManager()),
jsPandaFile_(ctx->GetJSPandaFile()),
recordName_(recordName),
profiling_(ctx->GetCompilerConfig()->IsProfiling()),
@ -84,7 +80,6 @@ private:
JSThread *thread_ {nullptr};
CircuitBuilder builder_;
GateRef dependEntry_;
TSManager *tsManager_ {nullptr};
const JSPandaFile *jsPandaFile_ {nullptr};
const CString &recordName_;
panda_file::File::EntityId methodId_ {0};

View File

@ -131,7 +131,7 @@ void NumberSpeculativeLowering::VisitTypedBinaryOp(GateRef gate)
break;
}
default: {
if (acc_.HasPrimitiveNumberType(gate)) {
if (acc_.HasNumberType(gate)) {
VisitNumberBinaryOp(gate);
}
break;
@ -279,7 +279,7 @@ void NumberSpeculativeLowering::VisitTypedUnaryOp(GateRef gate)
void NumberSpeculativeLowering::VisitTypedConditionJump(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateType type = acc_.GetTypedJumpAccessor(gate).GetTypeValue();
ParamType type = acc_.GetTypedJumpAccessor(gate).GetParamType();
if (type.IsBooleanType()) {
VisitBooleanJump(gate);
} else {
@ -292,17 +292,11 @@ void NumberSpeculativeLowering::VisitNumberCalculate(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateType gateType = acc_.GetGateType(gate);
const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
if (sampleType->IsNumber()) {
if (sampleType->IsInt()) {
gateType = GateType::IntType();
} else {
gateType = GateType::DoubleType();
}
}
TypedBinaryAccessor accessor(acc_.TryGetValue(gate));
const ParamType paramType = accessor.GetParamType();
ASSERT(paramType.HasNumberType());
GateRef result = Circuit::NullGate();
if (gateType.IsIntType()) {
if (paramType.IsIntType()) {
result = CalculateInts<Op>(left, right); // int op int
UpdateRange(result, GetRange(gate));
acc_.SetMachineType(gate, MachineType::I32);
@ -319,20 +313,11 @@ void NumberSpeculativeLowering::VisitNumberCompare(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateType leftType = acc_.GetLeftType(gate);
GateType rightType = acc_.GetRightType(gate);
const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
if (sampleType->IsNumber()) {
if (sampleType->IsInt()) {
leftType = GateType::IntType();
rightType = GateType::IntType();
} else {
leftType = GateType::NumberType();
rightType = GateType::NumberType();
}
}
TypedBinaryAccessor accessor(acc_.TryGetValue(gate));
const ParamType paramType = accessor.GetParamType();
ASSERT(paramType.HasNumberType());
GateRef result = Circuit::NullGate();
if (leftType.IsIntType() && rightType.IsIntType()) {
if (paramType.IsIntType()) {
result = CompareInts<Op>(left, right); // int op int
} else {
result = CompareDoubles<Op>(left, right); // float op float
@ -370,17 +355,11 @@ void NumberSpeculativeLowering::VisitNumberDiv(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateType gateType = acc_.GetGateType(gate);
const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
if (sampleType->IsNumber()) {
if (sampleType->IsInt()) {
gateType = GateType::IntType();
} else {
gateType = GateType::DoubleType();
}
}
TypedBinaryAccessor accessor(acc_.TryGetValue(gate));
const ParamType paramType = accessor.GetParamType();
ASSERT(paramType.HasNumberType());
GateRef result = Circuit::NullGate();
if (gateType.IsIntType()) {
if (paramType.IsIntType()) {
result = builder_.Int32DivWithCheck(left, right);
acc_.SetMachineType(gate, MachineType::I32);
} else {
@ -397,19 +376,11 @@ void NumberSpeculativeLowering::VisitNumberMod(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateType gateType = acc_.GetGateType(gate);
const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
if (sampleType->IsNumber()) {
if (sampleType->IsInt()) {
gateType = GateType::IntType();
} else if (sampleType->IsDouble()) {
gateType = GateType::DoubleType();
} else {
gateType = GateType::NumberType();
}
}
TypedBinaryAccessor accessor(acc_.TryGetValue(gate));
const ParamType paramType = accessor.GetParamType();
ASSERT(paramType.HasNumberType());
GateRef result = Circuit::NullGate();
if (gateType.IsIntType()) {
if (paramType.IsIntType()) {
if (GetRange(right).MaybeZero()) {
builder_.Int32CheckRightIsZero(right);
}
@ -434,8 +405,8 @@ template<TypedUnOp Op>
void NumberSpeculativeLowering::VisitNumberMonocular(GateRef gate)
{
TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
GateType type = accessor.GetTypeValue();
ASSERT(type.IsPrimitiveNumberType());
ParamType type = accessor.GetParamType();
ASSERT(type.HasNumberType());
GateRef value = acc_.GetValueIn(gate, 0);
GateRef result = Circuit::NullGate();
if (type.IsIntType()) {
@ -455,7 +426,7 @@ void NumberSpeculativeLowering::VisitNumberMonocular(GateRef gate)
void NumberSpeculativeLowering::VisitNumberNot(GateRef gate)
{
ASSERT(TypedUnaryAccessor(acc_.TryGetValue(gate)).GetTypeValue().IsPrimitiveNumberType());
ASSERT(TypedUnaryAccessor(acc_.TryGetValue(gate)).GetParamType().HasNumberType());
GateRef value = acc_.GetValueIn(gate, 0);
GateRef result = builder_.Int32Not(value);
UpdateRange(result, GetRange(gate));

View File

@ -44,14 +44,22 @@ GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, GateType gateType)
return old == type ? Circuit::NullGate() : gate;
}
GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, PGOSampleType pgoType)
GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, ParamType paramType)
{
TypeInfo type = GetOutputTypeInfo(gate);
TypeInfo old = type;
if (pgoType.IsInt()) {
if (paramType.IsIntType()) {
type = TypeInfo::INT32;
} else {
} else if (paramType.IsNumberType()) {
type = TypeInfo::FLOAT64;
} else if (paramType.IsDoubleType()) {
type = TypeInfo::FLOAT64;
} else if (paramType.IsIntOverflowType()) {
type = TypeInfo::FLOAT64;
} else if (paramType.IsBooleanType()) {
type = TypeInfo::INT1;
} else {
type = TypeInfo::TAGGED;
}
SetOutputTypeInfo(gate, type);
return old == type ? Circuit::NullGate() : gate;
@ -279,7 +287,7 @@ GateRef NumberSpeculativeRetype::VisitTypedBinaryOp(GateRef gate)
acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_STRICTNOTEQ &&
acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_EQ &&
acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_NOTEQ) {
if (acc_.HasPrimitiveNumberType(gate)) {
if (acc_.HasNumberType(gate)) {
return VisitNumberBinaryOp(gate);
}
}
@ -418,8 +426,7 @@ GateRef NumberSpeculativeRetype::VisitStringAdd(GateRef gate)
GateRef input = acc_.GetValueIn(gate, i);
TypeInfo inputInfo = GetOutputTypeInfo(input);
if (inputInfo == TypeInfo::CHAR) {
GateRef glue = acc_.GetGlueFromArgList();
input = builder_.CallStub(glue, gate, CommonStubCSigns::CreateStringBySingleCharCode, { glue, input });
input = builder_.ConvertCharToEcmaString(input);
}
acc_.ReplaceValueIn(gate, input, i);
}
@ -539,8 +546,11 @@ GateRef NumberSpeculativeRetype::VisitNumberBinaryOp(GateRef gate)
case TypedBinOp::TYPED_XOR: {
return VisitNumberShiftAndLogical(gate);
}
default:
return VisitNumberRelated(gate);
default: {
TypedBinaryAccessor accessor(acc_.TryGetValue(gate));
const ParamType paramType = accessor.GetParamType();
return VisitNumberRelated(gate, paramType);
}
}
}
@ -558,16 +568,19 @@ GateRef NumberSpeculativeRetype::VisitTypedUnaryOp(GateRef gate)
case TypedUnOp::TYPED_ISFALSE:
case TypedUnOp::TYPED_ISTRUE:
return VisitIsTrueOrFalse(gate);
default:
return VisitNumberRelated(gate);
default: {
TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
ParamType paramType = accessor.GetParamType();
return VisitNumberRelated(gate, paramType);
}
}
}
GateRef NumberSpeculativeRetype::VisitTypedConditionJump(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
auto type = accessor.GetTypeValue();
TypedJumpAccessor accessor(acc_.TryGetValue(gate));
ParamType type = accessor.GetParamType();
if (type.IsBooleanType()) {
return VisitBooleanJump(gate);
} else {
@ -579,17 +592,13 @@ GateRef NumberSpeculativeRetype::VisitTypedConditionJump(GateRef gate)
GateRef NumberSpeculativeRetype::VisitNumberCalculate(GateRef gate)
{
if (IsRetype()) {
const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
if (sampleType->IsNumber()) {
return SetOutputType(gate, *sampleType);
} else {
GateType gateType = acc_.GetGateType(gate);
GateType resType = gateType.IsIntType() ? GateType::IntType() : GateType::DoubleType();
return SetOutputType(gate, resType);
}
TypedBinaryAccessor accessor(acc_.TryGetValue(gate));
const ParamType paramType = accessor.GetParamType();
ASSERT(paramType.HasNumberType());
return SetOutputType(gate, paramType);
} else if (IsConvert()) {
Environment env(gate, circuit_, &builder_);
ConvertForBinaryOp(gate);
ConvertForNumberBinaryOp(gate);
}
return Circuit::NullGate();
}
@ -601,7 +610,7 @@ GateRef NumberSpeculativeRetype::VisitNumberCompare(GateRef gate)
}
if (IsConvert()) {
Environment env(gate, circuit_, &builder_);
ConvertForCompareOp(gate);
ConvertForNumberCompareOp(gate);
}
return Circuit::NullGate();
}
@ -613,19 +622,7 @@ GateRef NumberSpeculativeRetype::VisitNumberShiftAndLogical(GateRef gate)
}
if (IsConvert()) {
Environment env(gate, circuit_, &builder_);
GateType leftType = acc_.GetLeftType(gate);
GateType rightType = acc_.GetRightType(gate);
const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
if (sampleType->IsNumber()) {
if (sampleType->IsInt()) {
leftType = GateType::IntType();
rightType = GateType::IntType();
} else {
leftType = GateType::NumberType();
rightType = GateType::NumberType();
}
}
ConvertForShiftAndLogicalOperator(gate, leftType, rightType);
ConvertForNumberShiftAndLogicalOperator(gate);
}
return Circuit::NullGate();
}
@ -633,8 +630,8 @@ GateRef NumberSpeculativeRetype::VisitNumberShiftAndLogical(GateRef gate)
GateRef NumberSpeculativeRetype::VisitNumberMonocular(GateRef gate)
{
TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
GateType type = accessor.GetTypeValue();
ASSERT(type.IsPrimitiveNumberType());
ParamType type = accessor.GetParamType();
ASSERT(type.HasNumberType());
if (type.IsIntType()) {
return VisitIntMonocular(gate);
} else {
@ -665,8 +662,15 @@ GateRef NumberSpeculativeRetype::VisitDoubleMonocular(GateRef gate)
if (IsConvert()) {
TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
ParamType paramType = accessor.GetParamType();
GateRef value = acc_.GetValueIn(gate, 0);
acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(value, accessor.GetTypeValue()), 0);
GateType valueType = GateType::NumberType();
if (paramType.IsIntType()) {
valueType = GateType::IntType();
} else if (paramType.IsDoubleType()) {
valueType = GateType::DoubleType();
}
acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(value, valueType), 0);
acc_.ReplaceStateIn(gate, builder_.GetState());
acc_.ReplaceDependIn(gate, builder_.GetDepend());
}
@ -676,14 +680,23 @@ GateRef NumberSpeculativeRetype::VisitDoubleMonocular(GateRef gate)
GateRef NumberSpeculativeRetype::VisitIsTrueOrFalse(GateRef gate)
{
TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
GateType valueType = accessor.GetTypeValue();
ASSERT(valueType.IsPrimitiveNumberType());
ParamType paramType = accessor.GetParamType();
ASSERT(paramType.HasNumberType() || paramType.IsBooleanType());
if (IsRetype()) {
return SetOutputType(gate, GateType::BooleanType());
}
if (IsConvert()) {
Environment env(gate, circuit_, &builder_);
GateRef value = acc_.GetValueIn(gate, 0);
GateType valueType = GateType::NumberType();
// NOTICE-PGO: wx support undefined
if (paramType.IsIntType()) {
valueType = GateType::IntType();
} else if (paramType.IsDoubleType()) {
valueType = GateType::DoubleType();
} else if (paramType.IsBooleanType()) {
valueType = GateType::BooleanType();
}
auto input = CheckAndConvertToBool(value, valueType);
ResizeAndSetTypeInfo(input, TypeInfo::INT1);
acc_.ReplaceValueIn(gate, input, 0);
@ -696,14 +709,20 @@ GateRef NumberSpeculativeRetype::VisitIsTrueOrFalse(GateRef gate)
GateRef NumberSpeculativeRetype::VisitNumberNot(GateRef gate)
{
TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
GateType valueType = accessor.GetTypeValue();
ASSERT(valueType.IsPrimitiveNumberType());
ParamType paramType = accessor.GetParamType();
ASSERT(paramType.HasNumberType());
if (IsRetype()) {
return SetOutputType(gate, GateType::IntType());
}
if (IsConvert()) {
Environment env(gate, circuit_, &builder_);
GateRef value = acc_.GetValueIn(gate, 0);
GateType valueType = GateType::NumberType();
if (paramType.IsIntType()) {
valueType = GateType::IntType();
} else if (paramType.IsDoubleType()) {
valueType = GateType::DoubleType();
}
acc_.ReplaceValueIn(gate,
CheckAndConvertToInt32(value, valueType, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL), 0);
acc_.ReplaceStateIn(gate, builder_.GetState());
@ -735,7 +754,7 @@ GateRef NumberSpeculativeRetype::VisitBooleanJump(GateRef gate)
return Circuit::NullGate();
}
GateRef NumberSpeculativeRetype::VisitNumberRelated(GateRef gate)
GateRef NumberSpeculativeRetype::VisitNumberRelated(GateRef gate, ParamType paramType)
{
if (IsRetype()) {
return SetOutputType(gate, GateType::NumberType());
@ -743,10 +762,19 @@ GateRef NumberSpeculativeRetype::VisitNumberRelated(GateRef gate)
if (IsConvert()) {
Environment env(gate, circuit_, &builder_);
size_t valueNum = acc_.GetNumValueIn(gate);
GateType inputType = GateType::AnyType();
if (paramType.IsIntType() || paramType.IsIntOverflowType()) {
inputType = GateType::IntType();
} else if (paramType.IsDoubleType()) {
inputType = GateType::DoubleType();
} else if (paramType.IsNumberType()) {
inputType = GateType::NumberType();
} else if (paramType.IsBooleanType()) {
inputType = GateType::BooleanType();
}
for (size_t i = 0; i < valueNum; ++i) {
GateRef input = acc_.GetValueIn(gate, i);
GateType inputType = acc_.GetGateType(input);
if (inputType.IsNumberType() || inputType.IsBooleanType()) {
if (paramType.HasNumberType() || paramType.IsBooleanType()) {
acc_.ReplaceValueIn(gate, CheckAndConvertToTagged(input, inputType, ConvertToNumber::BOOL_ONLY), i);
}
}
@ -829,59 +857,44 @@ GateRef NumberSpeculativeRetype::CheckAndConvertToBool(GateRef gate, GateType ga
}
}
void NumberSpeculativeRetype::ConvertForBinaryOp(GateRef gate)
void NumberSpeculativeRetype::ConvertForNumberBinaryOp(GateRef gate)
{
const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
if (sampleType->IsNumber()) {
if (sampleType->IsInt()) {
GateType leftType = GateType::IntType();
GateType rightType = GateType::IntType();
ConvertForIntOperator(gate, leftType, rightType);
} else {
GateType leftType = GateType::NumberType();
GateType rightType = GateType::NumberType();
if (sampleType->IsIntOverFlow()) {
leftType = GateType::IntType();
rightType = GateType::IntType();
} else if (sampleType->IsDouble()) {
leftType = GateType::DoubleType();
rightType = GateType::DoubleType();
}
ConvertForDoubleOperator(gate, leftType, rightType);
}
} else {
GateType gateType = acc_.GetGateType(gate);
GateType leftType = acc_.GetLeftType(gate);
GateType rightType = acc_.GetRightType(gate);
if (gateType.IsIntType()) {
ConvertForIntOperator(gate, leftType, rightType);
} else {
ConvertForDoubleOperator(gate, leftType, rightType);
}
TypedBinaryAccessor accessor(acc_.TryGetValue(gate));
const ParamType paramType = accessor.GetParamType();
ASSERT(paramType.HasNumberType());
if (paramType.IsIntType()) {
ConvertForIntOperator(gate, GateType::IntType(), GateType::IntType());
} else if (paramType.IsIntOverflowType()) {
ConvertForDoubleOperator(gate, GateType::IntType(), GateType::IntType());
} else if (paramType.IsDoubleType()) {
ConvertForDoubleOperator(gate, GateType::DoubleType(), GateType::DoubleType());
} else if (paramType.IsNumberType()) {
ConvertForDoubleOperator(gate, GateType::NumberType(), GateType::NumberType());
}
}
void NumberSpeculativeRetype::ConvertForCompareOp(GateRef gate)
void NumberSpeculativeRetype::ConvertForNumberCompareOp(GateRef gate)
{
const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
if (sampleType->IsNumber()) {
if (sampleType->IsInt()) {
GateType leftType = GateType::IntType();
GateType rightType = GateType::IntType();
ConvertForIntOperator(gate, leftType, rightType);
} else {
GateType leftType = GateType::NumberType();
GateType rightType = GateType::NumberType();
ConvertForDoubleOperator(gate, leftType, rightType);
}
TypedBinaryAccessor accessor(acc_.TryGetValue(gate));
const ParamType paramType = accessor.GetParamType();
ASSERT(paramType.HasNumberType());
ASSERT(!paramType.IsIntOverflowType());
if (paramType.IsIntType()) {
ConvertForIntOperator(gate, GateType::IntType(), GateType::IntType());
} else {
GateType leftType = acc_.GetLeftType(gate);
GateType rightType = acc_.GetRightType(gate);
if (leftType.IsIntType() && rightType.IsIntType()) {
ConvertForIntOperator(gate, leftType, rightType);
} else {
ConvertForDoubleOperator(gate, leftType, rightType);
}
ConvertForDoubleOperator(gate, GateType::NumberType(), GateType::NumberType());
}
}
void NumberSpeculativeRetype::ConvertForNumberShiftAndLogicalOperator(GateRef gate)
{
TypedBinaryAccessor accessor(acc_.TryGetValue(gate));
const ParamType paramType = accessor.GetParamType();
ASSERT(paramType.HasNumberType());
if (paramType.IsIntType()) {
ConvertForShiftAndLogicalOperator(gate, GateType::IntType(), GateType::IntType());
} else {
ConvertForShiftAndLogicalOperator(gate, GateType::NumberType(), GateType::NumberType());
}
}
@ -1284,6 +1297,9 @@ GateRef NumberSpeculativeRetype::VisitIndexCheck(GateRef gate)
GateRef index = acc_.GetValueIn(gate, 1);
GateType receiverType = acc_.GetGateType(receiver);
GateType indexType = acc_.GetGateType(index);
if (indexType.IsAnyType()) {
indexType = GateType::IntType();
}
acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(receiver, receiverType), 0);
acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType), 1);
@ -1443,15 +1459,15 @@ GateRef NumberSpeculativeRetype::VisitTypeConvert(GateRef gate)
{
GateRef input = acc_.GetValueIn(gate, 0);
TypeInfo inputInfo = GetOutputTypeInfo(input);
TypeConvertAccessor accessor(acc_.TryGetValue(gate));
ParamType paramType = accessor.GetLeftType();
if (IsRetype()) {
if (inputInfo == TypeInfo::TAGGED) {
if (acc_.IsConstantNumber(input)) {
return Circuit::NullGate();
}
GateType gateType = acc_.GetGateType(gate);
ASSERT(gateType.IsNumberType());
GateType resType = gateType.IsIntType() ? GateType::IntType() : GateType::DoubleType();
return SetOutputType(gate, resType);
ASSERT(paramType.HasNumberType());
return SetOutputType(gate, paramType);
}
TypeInfo oldType = GetOutputTypeInfo(gate);
SetOutputTypeInfo(gate, inputInfo);
@ -1461,9 +1477,8 @@ GateRef NumberSpeculativeRetype::VisitTypeConvert(GateRef gate)
ASSERT(inputInfo != TypeInfo::INT1 && inputInfo != TypeInfo::NONE);
Environment env(gate, circuit_, &builder_);
if (inputInfo == TypeInfo::TAGGED && !acc_.IsConstantNumber(input)) {
GateType gateType = acc_.GetGateType(gate);
ASSERT(gateType.IsNumberType());
if (gateType.IsIntType()) {
ASSERT(paramType.HasNumberType());
if (paramType.IsIntType()) {
input = CheckAndConvertToInt32(input, GateType::IntType());
ResizeAndSetTypeInfo(input, TypeInfo::INT32);
} else {

View File

@ -66,8 +66,8 @@ private:
return state_ == State::Convert;
}
GateRef SetOutputType(GateRef gate, PGOSampleType type);
GateRef SetOutputType(GateRef gate, GateType type);
GateRef SetOutputType(GateRef gate, ParamType type);
GateRef SetOutputType(GateRef gate, Representation rep);
GateRef SetOutputType(GateRef gate, TypeInfo type);
TypeInfo GetNumberTypeInfo(GateRef gate);
@ -108,7 +108,7 @@ private:
GateRef VisitStoreElement(GateRef gate);
GateRef VisitStoreProperty(GateRef gate);
GateRef VisitLoadProperty(GateRef gate);
GateRef VisitNumberRelated(GateRef gate);
GateRef VisitNumberRelated(GateRef gate, ParamType paramType);
GateRef VisitCallBuiltins(GateRef gate);
GateRef VisitDataViewGet(GateRef gate);
GateRef VisitDataViewSet(GateRef gate);
@ -126,8 +126,10 @@ private:
GateRef VisitMonoCallGetterOnProto(GateRef gate);
GateRef VisitMonoStoreProperty(GateRef gate);
void ConvertForBinaryOp(GateRef gate);
void ConvertForCompareOp(GateRef gate);
void ConvertForNumberBinaryOp(GateRef gate);
void ConvertForNumberCompareOp(GateRef gate);
void ConvertForNumberShiftAndLogicalOperator(GateRef gate);
void ConvertForIntOperator(GateRef gate, GateType leftType, GateType rightType);
void ConvertForShiftAndLogicalOperator(GateRef gate, GateType leftType, GateType rightType);
void ConvertForDoubleOperator(GateRef gate, GateType leftType, GateType rightType);

View File

@ -16,12 +16,10 @@
#ifndef ECMASCRIPT_COMPILER_PASS_H
#define ECMASCRIPT_COMPILER_PASS_H
#include "ecmascript/compiler/array_bounds_check_elimination.h"
#include "ecmascript/compiler/async_function_lowering.h"
#include "ecmascript/compiler/bytecode_circuit_builder.h"
#include "ecmascript/compiler/codegen/llvm/llvm_codegen.h"
#include "ecmascript/compiler/combined_pass_visitor.h"
#include "ecmascript/compiler/common_stubs.h"
#include "ecmascript/compiler/compiler_log.h"
#include "ecmascript/compiler/constant_folding.h"
#include "ecmascript/compiler/dead_code_elimination.h"
@ -49,8 +47,6 @@
#include "ecmascript/compiler/ts_inline_lowering.h"
#include "ecmascript/compiler/typed_bytecode_lowering.h"
#include "ecmascript/compiler/ts_hcr_opt_pass.h"
#include "ecmascript/compiler/type_inference/global_type_infer.h"
#include "ecmascript/compiler/type_inference/initialization_analysis.h"
#include "ecmascript/compiler/type_inference/pgo_type_infer.h"
#include "ecmascript/compiler/typed_hcr_lowering.h"
#include "ecmascript/compiler/typed_native_inline_lowering.h"
@ -73,12 +69,14 @@ public:
PassData(BytecodeCircuitBuilder *builder, Circuit *circuit, PassContext *ctx, CompilerLog *log,
std::string methodName, MethodInfo *methodInfo = nullptr, bool hasTypes = false,
const CString &recordName = "", MethodLiteral *methodLiteral = nullptr,
uint32_t methodOffset = 0, NativeAreaAllocator *allocator = nullptr,
uint32_t methodOffset = 0, const CallMethodFlagMap *callMethodFlagMap = nullptr,
const CVector<AbcFileInfo> &fileInfos = CVector<AbcFileInfo>{}, NativeAreaAllocator *allocator = nullptr,
PGOProfilerDecoder *decoder = nullptr, PassOptions *passOptions = nullptr,
std::string optBCRange = "")
: builder_(builder), circuit_(circuit), ctx_(ctx), log_(log), methodName_(methodName),
methodInfo_(methodInfo), hasTypes_(hasTypes), recordName_(recordName), methodLiteral_(methodLiteral),
methodOffset_(methodOffset), allocator_(allocator), decoder_(decoder), passOptions_(passOptions),
methodOffset_(methodOffset), callMethodFlagMap_(callMethodFlagMap), fileInfos_(fileInfos),
allocator_(allocator), decoder_(decoder), passOptions_(passOptions),
optBCRange_(optBCRange)
{
}
@ -194,6 +192,16 @@ public:
{
return optBCRange_;
}
const CallMethodFlagMap *GetCallMethodFlagMap() const
{
return callMethodFlagMap_;
}
const CVector<AbcFileInfo> &GetFileInfos() const
{
return fileInfos_;
}
bool IsTypeAbort() const
{
@ -242,6 +250,8 @@ private:
const CString &recordName_;
MethodLiteral *methodLiteral_ {nullptr};
uint32_t methodOffset_;
const CallMethodFlagMap *callMethodFlagMap_ {nullptr};
const CVector<AbcFileInfo> &fileInfos_;
NativeAreaAllocator *allocator_ {nullptr};
PGOProfilerDecoder *decoder_ {nullptr};
PassOptions *passOptions_ {nullptr};
@ -264,24 +274,6 @@ private:
T1* data_;
};
class TypeInferPass {
public:
bool Run(PassData* data)
{
PassOptions *passOptions = data->GetPassOptions();
if (passOptions != nullptr && !passOptions->EnableTypeInfer()) {
return false;
}
TimeScope timescope("TypeInferPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
bool enableLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType();
GlobalTypeInfer globalTypeInfer(data->GetPassContext(), data->GetMethodOffset(), data->GetRecordName(),
data->GetPGOProfilerDecoder(), passOptions->EnableOptTrackField(),
enableLog, data->HasTypes());
globalTypeInfer.ProcessTypeInference(data->GetBuilder(), data->GetCircuit());
return true;
}
};
class PGOTypeInferPass {
public:
bool Run(PassData* data)
@ -289,7 +281,7 @@ public:
TimeScope timescope("PGOTypeInferPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
bool enableLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType();
Chunk chunk(data->GetNativeAreaAllocator());
PGOTypeInfer pgoTypeInfer(data->GetCircuit(), data->GetTSManager(), data->GetBuilder(),
PGOTypeInfer pgoTypeInfer(data->GetCircuit(), data->GetTSManager(), data->GetPTManager(), data->GetBuilder(),
data->GetMethodName(), &chunk, enableLog);
pgoTypeInfer.Run();
return true;
@ -373,6 +365,8 @@ public:
data->GetMethodName(),
passOptions->EnableLoweringBuiltin(),
data->GetRecordName(),
data->GetCallMethodFlagMap(),
data->GetPGOProfilerDecoder(),
data->GetOptBCRange());
bool success = lowering.RunTypedBytecodeLowering();
if (!success) {
@ -402,8 +396,7 @@ public:
TimeScope timescope("NTypeBytecodeLoweringPass", data->GetMethodName(),
data->GetMethodOffset(), data->GetLog());
bool enableLog = data->GetLog()->EnableMethodCIRLog();
NTypeBytecodeLowering lowering(data->GetCircuit(), data->GetPassContext(), data->GetTSManager(),
enableLog, data->GetMethodName());
NTypeBytecodeLowering lowering(data->GetCircuit(), data->GetPassContext(), enableLog, data->GetMethodName());
lowering.RunNTypeBytecodeLowering();
Chunk chunk(data->GetNativeAreaAllocator());
CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
@ -568,7 +561,7 @@ public:
{
TimeScope timescope("SlowPathLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
bool enableLog = data->GetLog()->EnableMethodCIRLog();
SlowPathLowering lowering(data->GetCircuit(), data->GetCompilerConfig(), data->GetTSManager(),
SlowPathLowering lowering(data->GetCircuit(), data->GetCompilerConfig(), data->GetPassContext(),
data->GetMethodLiteral(), enableLog, data->GetMethodName());
lowering.CallRuntimeLowering();
return true;
@ -805,7 +798,7 @@ public:
Chunk chunk(data->GetNativeAreaAllocator());
bool enableLog = data->GetLog()->EnableMethodCIRLog();
bool licm = data->GetPassOptions()->EnableOptLoopInvariantCodeMotion();
bool liteCG = data->GetTSManager()->GetEcmaVM()->GetJSOptions().IsCompilerEnableLiteCG();
bool liteCG = data->GetPassContext()->GetEcmaVM()->GetJSOptions().IsCompilerEnableLiteCG();
GraphLinearizer(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, false, licm, liteCG)
.Run(data->GetCfg());
PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk).Run(data->GetCfg());

View File

@ -13,16 +13,15 @@
* limitations under the License.
*/
#include "ecmascript/compiler/pass_manager.h"
#include "ecmascript/compiler/bytecodes.h"
#include "ecmascript/compiler/compilation_driver.h"
#include "ecmascript/compiler/pass.h"
#include "ecmascript/ecma_handle_scope.h"
#include "ecmascript/jspandafile/js_pandafile_manager.h"
#include "ecmascript/jspandafile/panda_file_translator.h"
#include "ecmascript/log.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
#include "ecmascript/ts_types/ts_manager.h"
namespace panda::ecmascript::kungfu {
using PGOProfilerManager = pgo::PGOProfilerManager;
@ -66,10 +65,7 @@ bool JitPassManager::Compile(JSHandle<JSFunction> &jsFunction, AOTFileGenerator
auto jsPandaFile = ctx_->GetJSPandaFile();
auto cmpCfg = ctx_->GetCompilerConfig();
auto tsManager = ctx_->GetTSManager();
auto module = m->GetModule();
// note: TSManager need to set current constantpool before all pass
tsManager->SetCurConstantPool(jsPandaFile, methodOffset);
log_->SetMethodLog(fileName, methodName, logList_);
std::string fullName = module->GetFuncName(methodLiteral, jsPandaFile);
@ -87,10 +83,9 @@ bool JitPassManager::Compile(JSHandle<JSFunction> &jsFunction, AOTFileGenerator
fullName.c_str(), cmpCfg->Is64Bit(), FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
PGOProfilerDecoder *decoder = passOptions_->EnableOptPGOType() ? &profilerDecoder_ : nullptr;
builder_ = new BytecodeCircuitBuilder(jsPandaFile, methodLiteral, methodPCInfo, tsManager,
circuit_, ctx_->GetByteCodes(), hasTypes, enableMethodLog && log_->OutputCIR(),
passOptions_->EnableTypeLowering(), fullName, recordName, decoder, false,
passOptions_->EnableOptTrackField());
builder_ = new BytecodeCircuitBuilder(jsPandaFile, methodLiteral, methodPCInfo,
circuit_, ctx_->GetByteCodes(), enableMethodLog && log_->OutputCIR(),
passOptions_->EnableTypeLowering(), fullName, recordName, decoder, false);
builder_->SetOsrOffset(osrOffset);
{
TimeScope timeScope("BytecodeToCircuit", methodName, methodOffset, log_);
@ -98,7 +93,8 @@ bool JitPassManager::Compile(JSHandle<JSFunction> &jsFunction, AOTFileGenerator
}
data_ = new PassData(builder_, circuit_, ctx_, log_, fullName, &methodInfo, hasTypes, recordName,
methodLiteral, methodOffset, vm_->GetNativeAreaAllocator(), decoder, passOptions_);
methodLiteral, methodOffset, nullptr, CVector<AbcFileInfo> {},
vm_->GetNativeAreaAllocator(), decoder, passOptions_);
PassRunner<PassData> pipeline(data_);
if (data_->GetMethodLiteral()->HasDebuggerStmt()) {
data_->AbortCompilation();
@ -110,11 +106,6 @@ bool JitPassManager::Compile(JSHandle<JSFunction> &jsFunction, AOTFileGenerator
pipeline.RunPass<LoopOptimizationPass>();
pipeline.RunPass<RedundantPhiEliminationPass>();
}
pipeline.RunPass<TypeInferPass>();
if (data_->IsTypeAbort()) {
data_->AbortCompilation();
return;
}
pipeline.RunPass<PGOTypeInferPass>();
pipeline.RunPass<TSClassAnalysisPass>();
pipeline.RunPass<TSInlineLoweringPass>();
@ -228,10 +219,7 @@ bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName,
PassContext ctx(triple_, log_, &collector, m->GetModule(), &profilerDecoder_);
auto jsPandaFile = ctx.GetJSPandaFile();
auto cmpCfg = ctx.GetCompilerConfig();
auto tsManager = ctx.GetTSManager();
auto module = m->GetModule();
// note: TSManager need to set current constantpool before all pass
tsManager->SetCurConstantPool(jsPandaFile, methodOffset);
log_->SetMethodLog(fileName, methodName, logList_);
std::string fullName = module->GetFuncName(methodLiteral, jsPandaFile);
@ -250,17 +238,17 @@ bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName,
PGOProfilerDecoder *decoder = passOptions_->EnableOptPGOType() ? &profilerDecoder_ : nullptr;
BytecodeCircuitBuilder builder(jsPandaFile, methodLiteral, methodPCInfo, tsManager, &circuit,
ctx.GetByteCodes(), hasTypes, enableMethodLog && log_->OutputCIR(),
passOptions_->EnableTypeLowering(), fullName, recordName, decoder, false,
passOptions_->EnableOptTrackField());
BytecodeCircuitBuilder builder(jsPandaFile, methodLiteral, methodPCInfo, &circuit,
ctx.GetByteCodes(), enableMethodLog && log_->OutputCIR(),
passOptions_->EnableTypeLowering(), fullName, recordName, decoder, false);
{
TimeScope timeScope("BytecodeToCircuit", methodName, methodOffset, log_);
builder.BytecodeToCircuit();
}
PassData data(&builder, &circuit, &ctx, log_, fullName, &methodInfo, hasTypes, recordName,
methodLiteral, methodOffset, vm_->GetNativeAreaAllocator(), decoder, passOptions_,
methodLiteral, methodOffset, callMethodFlagMap_, fileInfos_,
vm_->GetNativeAreaAllocator(), decoder, passOptions_,
optBCRange_);
PassRunner<PassData> pipeline(&data);
if (data.GetMethodLiteral()->HasDebuggerStmt()) {
@ -273,29 +261,14 @@ bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName,
pipeline.RunPass<LoopOptimizationPass>();
pipeline.RunPass<RedundantPhiEliminationPass>();
}
pipeline.RunPass<TypeInferPass>();
if (data.IsTypeAbort()) {
data.AbortCompilation();
return;
}
pipeline.RunPass<PGOTypeInferPass>();
pipeline.RunPass<TSClassAnalysisPass>();
pipeline.RunPass<TSInlineLoweringPass>();
pipeline.RunPass<RedundantPhiEliminationPass>();
pipeline.RunPass<AsyncFunctionLoweringPass>();
// skip async function, because some application run with errors.
if (methodInfo.IsTypeInferAbort()) {
data.AbortCompilation();
return;
}
pipeline.RunPass<TypeBytecodeLoweringPass>();
pipeline.RunPass<InductionVariableAnalysisPass>();
pipeline.RunPass<RedundantPhiEliminationPass>();
pipeline.RunPass<NTypeBytecodeLoweringPass>();
if (data.IsTypeAbort()) {
data.AbortCompilation();
return;
}
pipeline.RunPass<EarlyEliminationPass>();
pipeline.RunPass<NumberSpeculativePass>();
pipeline.RunPass<LaterEliminationPass>();

View File

@ -16,16 +16,15 @@
#ifndef ECMASCRIPT_COMPILER_PASS_MANAGER_H
#define ECMASCRIPT_COMPILER_PASS_MANAGER_H
#include "ecmascript/compiler/aot_compiler_preprocessor.h"
#include "ecmascript/compiler/bytecode_info_collector.h"
#include "ecmascript/compiler/compiler_log.h"
#include "ecmascript/compiler/file_generators.h"
#include "ecmascript/compiler/ir_module.h"
#include "ecmascript/compiler/pass_options.h"
#include "ecmascript/compiler/ir_module.h"
#include "ecmascript/compiler/pass_options.h"
#include "ecmascript/ecma_vm.h"
#include "ecmascript/jspandafile/method_literal.h"
#include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
#include "ecmascript/ts_types/ts_manager.h"
namespace panda::ecmascript::kungfu {
@ -33,6 +32,9 @@ class Bytecodes;
class LexEnvManager;
class CompilationConfig;
class PassData;
class CallMethodFlagMap;
struct AbcFileInfo;
class PassContext {
public:
PassContext(const std::string &triple, CompilerLog *log, BytecodeInfoCollector* collector, IRModule *aotModule,
@ -142,10 +144,12 @@ class PassManager {
public:
explicit PassManager(EcmaVM* vm, std::string &triple, size_t optLevel, size_t relocMode,
CompilerLog *log, AotMethodLogList *logList, size_t maxAotMethodSize, size_t maxMethodsInModule,
PGOProfilerDecoder &profilerDecoder, PassOptions *passOptions, std::string optBCRange)
PGOProfilerDecoder &profilerDecoder, PassOptions *passOptions,
const CallMethodFlagMap *callMethodFlagMap, const CVector<AbcFileInfo> &fileInfos, std::string optBCRange)
: vm_(vm), triple_(triple), optLevel_(optLevel), relocMode_(relocMode), log_(log),
logList_(logList), maxAotMethodSize_(maxAotMethodSize), maxMethodsInModule_(maxMethodsInModule),
profilerDecoder_(profilerDecoder), passOptions_(passOptions), optBCRange_(optBCRange) {
profilerDecoder_(profilerDecoder), passOptions_(passOptions),
callMethodFlagMap_(callMethodFlagMap), fileInfos_(fileInfos), optBCRange_(optBCRange) {
enableJITLog_ = vm_->GetJSOptions().GetTraceJIT();
};
@ -165,6 +169,8 @@ protected:
size_t maxMethodsInModule_ {0};
PGOProfilerDecoder &profilerDecoder_;
PassOptions *passOptions_ {nullptr};
const CallMethodFlagMap *callMethodFlagMap_ {nullptr};
const CVector<AbcFileInfo> &fileInfos_;
std::string optBCRange_ {};
bool enableJITLog_ {false};
};
@ -174,7 +180,8 @@ public:
JitPassManager(EcmaVM* vm, std::string &triple, size_t optLevel, size_t relocMode,
CompilerLog *log, AotMethodLogList *logList,
PGOProfilerDecoder &profilerDecoder, PassOptions *passOptions)
: PassManager(vm, triple, optLevel, relocMode, log, logList, 1, 1, profilerDecoder, passOptions, "") { };
: PassManager(vm, triple, optLevel, relocMode, log, logList, 1, 1, profilerDecoder, passOptions,
nullptr, CVector<AbcFileInfo> {}, "") { };
bool Compile(JSHandle<JSFunction> &jsFunction, AOTFileGenerator &gen, int32_t osrOffset = -1);
bool RunCg();

View File

@ -16,8 +16,8 @@
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
#include "ecmascript/ecma_vm.h"
#include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tagged_array-inl.h"
#include "index_accessor.h"
namespace panda::ecmascript::kungfu {
@ -31,11 +31,24 @@ void PGOTypeManager::Iterate(const RootVisitor &v)
aotSnapshot_.Iterate(v);
}
int32_t PGOTypeManager::GetConstantPoolIDByMethodOffset(const JSPandaFile *jsPandaFile, uint32_t methodOffset)
uint32_t PGOTypeManager::GetConstantPoolIDByMethodOffset(const uint32_t methodOffset) const
{
panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(),
ASSERT(curJSPandaFile_!=nullptr);
panda_file::IndexAccessor indexAccessor(*curJSPandaFile_->GetPandaFile(),
panda_file::File::EntityId(methodOffset));
return static_cast<int32_t>(indexAccessor.GetHeaderIndex());
return static_cast<uint32_t>(indexAccessor.GetHeaderIndex());
}
JSTaggedValue PGOTypeManager::GetConstantPoolByMethodOffset(const uint32_t methodOffset) const
{
uint32_t cpId = GetConstantPoolIDByMethodOffset(methodOffset);
return thread_->GetCurrentEcmaContext()->FindConstpool(curJSPandaFile_, cpId);
}
JSTaggedValue PGOTypeManager::GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx) const
{
JSTaggedValue cp = GetConstantPoolByMethodOffset(methodOffset);
return ConstantPool::GetStringFromCache(thread_, cp, cpIdx);
}
void PGOTypeManager::InitAOTSnapshot(uint32_t compileFilesCount)
@ -180,10 +193,4 @@ JSTaggedValue PGOTypeManager::QueryHClass(ProfileType rootType, ProfileType chil
}
return result;
}
void PGOTypeManager::SetCurConstantPool(const JSPandaFile *jsPandaFile, uint32_t methodOffset)
{
curCPID_ = GetConstantPoolIDByMethodOffset(jsPandaFile, methodOffset);
curCP_ = thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, curCPID_);
}
} // namespace panda::ecmascript

View File

@ -25,27 +25,27 @@ public:
: thread_(vm->GetJSThread()), aotSnapshot_(vm) {}
~PGOTypeManager() = default;
static int32_t GetConstantPoolIDByMethodOffset(const JSPandaFile *jsPandaFile, uint32_t methodOffset);
void Iterate(const RootVisitor &v);
// common
JSThread* GetJSThread()
uint32_t PUBLIC_API GetConstantPoolIDByMethodOffset(const uint32_t methodOffset) const;
JSTaggedValue PUBLIC_API GetConstantPoolByMethodOffset(const uint32_t methodOffset) const;
JSTaggedValue PUBLIC_API GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx) const;
inline JSThread* GetJSThread()
{
return thread_;
}
void PUBLIC_API SetCurConstantPool(const JSPandaFile *jsPandaFile, uint32_t methodOffset);
JSHandle<JSTaggedValue> GetCurConstantPool() const
void PUBLIC_API SetCurCompilationFile(const JSPandaFile *jsPandaFile)
{
return JSHandle<JSTaggedValue>(uintptr_t(&curCP_));
curJSPandaFile_ = jsPandaFile;
}
// snapshot
void PUBLIC_API InitAOTSnapshot(uint32_t compileFilesCount);
void GenArrayInfo();
void GenConstantIndexInfo();
AOTSnapshot& GetAOTSnapshot()
{
@ -103,10 +103,12 @@ public:
{
locToElmsKindMap_.emplace(loc, kind);
}
private:
// snapshot
void GenHClassInfo();
void GenArrayInfo();
void GenConstantIndexInfo();
// opt to std::unordered_map
using TransIdToHClass = std::map<ProfileType, JSTaggedType>;
@ -123,10 +125,9 @@ private:
std::map<panda_file::File::EntityId, ElementsKind> idElmsKindMap_ {};
AOTSnapshot aotSnapshot_;
// When the passmanager iterates each method, the curCP_ and curCPID_ should be updated,
// so that subsequent passes (type_infer, ts_hcr_lowering) can obtain the correct constpool.
JSTaggedValue curCP_ {JSTaggedValue::Hole()};
int32_t curCPID_ {0};
// Since there is only one PGOTypeManager instance during compilation,
// the currently compiled jspandafile needs to be set to satisfy multi-file compilation.
const JSPandaFile *curJSPandaFile_ {nullptr};
};
} // panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_PGO_TYPE_PGO_TYPE_MANAGER_H

View File

@ -265,7 +265,7 @@ void ProfilerStubBuilder::ProfileCall(
Bind(&currentIsHotness);
{
Label icSlotValid(env);
Label isInt(env);
Label isHeapObject(env);
Label uninitialized(env);
Label updateSlot(env);
@ -274,23 +274,21 @@ void ProfilerStubBuilder::ProfileCall(
BRANCH(Int32LessThan(slotId, length), &icSlotValid, &exit);
Bind(&icSlotValid);
GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
BRANCH(TaggedIsInt(slotValue), &isInt, &uninitialized);
Bind(&isInt);
BRANCH(TaggedIsHeapObject(slotValue), &isHeapObject, &uninitialized);
Bind(&isHeapObject);
{
Label change(env);
Label resetSlot(env);
GateRef oldSlotValue = TaggedGetInt(slotValue);
GateRef methodId = env->GetBuilder()->GetMethodId(target);
BRANCH(Int32Equal(oldSlotValue, TruncInt64ToInt32(methodId)), &exit, &change);
GateRef method = env->GetBuilder()->GetMethodFromFunction(target);
BRANCH(Int64Equal(slotValue, method), &exit, &change);
Bind(&change);
{
GateRef polyCallCheck = Int32Equal(oldSlotValue, Int32(base::PGO_POLY_INLINE_REP));
GateRef emptyCallCheck = Int32Equal(oldSlotValue, Int32(0));
BRANCH(BoolOr(polyCallCheck, emptyCallCheck), &exit, &resetSlot);
BRANCH(Int64Equal(ChangeTaggedPointerToInt64(slotValue), Int64(0)), &exit, &resetSlot);
}
Bind(&resetSlot);
{
GateRef nonType = IntToTaggedInt(Int32(base::PGO_POLY_INLINE_REP));
// NOTICE-PGO: lx about poly
GateRef nonType = IntToTaggedInt(Int64(0));
SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, nonType);
TryPreDumpInner(glue, func, profileTypeInfo);
Jump(&exit);
@ -302,9 +300,8 @@ void ProfilerStubBuilder::ProfileCall(
}
Bind(&updateSlot);
{
GateRef methodId = env->GetBuilder()->GetMethodId(target);
GateRef methodIdValue = IntToTaggedInt(TruncInt64ToInt32(methodId));
SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, methodIdValue);
GateRef method = env->GetBuilder()->GetMethodFromFunction(target);
SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, method);
TryPreDumpInner(glue, func, profileTypeInfo);
Jump(&exit);
}
@ -663,7 +660,7 @@ GateRef ProfilerStubBuilder::GetIterationFunctionId(GateRef glue, GateRef iterat
BRANCH(Int64Equal(iterator, *maybeFunc), &isArrayProtoValues, &notArrayProtoValues);
Bind(&isArrayProtoValues);
{
functionId = Int32(PGO_BUILTINS_STUB_ID(ARRAY_PROTO_ITERATOR));
functionId = Int32(PGO_BUILTINS_STUB_ID(ArrayProtoIterator));
Jump(&exit);
}
Bind(&notArrayProtoValues);
@ -671,7 +668,7 @@ GateRef ProfilerStubBuilder::GetIterationFunctionId(GateRef glue, GateRef iterat
BRANCH(Int64Equal(iterator, *maybeFunc), &isSetProtoValues, &notSetProtoValues);
Bind(&isSetProtoValues);
{
functionId = Int32(PGO_BUILTINS_STUB_ID(SET_PROTO_ITERATOR));
functionId = Int32(PGO_BUILTINS_STUB_ID(SetProtoIterator));
Jump(&exit);
}
Bind(&notSetProtoValues);
@ -679,7 +676,7 @@ GateRef ProfilerStubBuilder::GetIterationFunctionId(GateRef glue, GateRef iterat
BRANCH(Int64Equal(iterator, *maybeFunc), &isMapProtoEntries, &notMapProtoEntries);
Bind(&isMapProtoEntries);
{
functionId = Int32(PGO_BUILTINS_STUB_ID(MAP_PROTO_ITERATOR));
functionId = Int32(PGO_BUILTINS_STUB_ID(MapProtoIterator));
Jump(&exit);
}
Bind(&notMapProtoEntries);
@ -687,7 +684,7 @@ GateRef ProfilerStubBuilder::GetIterationFunctionId(GateRef glue, GateRef iterat
BRANCH(Int64Equal(iterator, *maybeFunc), &isStringProtoIter, &notStringProtoIter);
Bind(&isStringProtoIter);
{
functionId = Int32(PGO_BUILTINS_STUB_ID(STRING_PROTO_ITERATOR));
functionId = Int32(PGO_BUILTINS_STUB_ID(StringProtoIterator));
Jump(&exit);
}
Bind(&notStringProtoIter);
@ -696,7 +693,7 @@ GateRef ProfilerStubBuilder::GetIterationFunctionId(GateRef glue, GateRef iterat
BRANCH(Int64Equal(iterator, *maybeFunc), &isTypedArrayProtoValues, &exit);
Bind(&isTypedArrayProtoValues);
{
functionId = Int32(PGO_BUILTINS_STUB_ID(TYPED_ARRAY_PROTO_ITERATOR));
functionId = Int32(PGO_BUILTINS_STUB_ID(TypeArrayProtoIterator));
Jump(&exit);
}
Bind(&exit);

View File

@ -274,10 +274,10 @@ RangeInfo RangeAnalysis::GetRangeOfCompare(GateRef gate, GateRef value, bool fla
ASSERT((left == value) || (right == value));
bool swap = right == value;
if (flag) {
op = TypedBinaryMetaData::GetRevCompareOp(op);
op = acc_.GetRevCompareOpForTypedBinOp(op);
}
if (swap) {
op = TypedBinaryMetaData::GetSwapCompareOp(op);
op = acc_.GetSwapCompareOpForTypedBinOp(op);
}
auto range = GetRange(swap ? left : right);
if (range.IsNone()) {

View File

@ -29,6 +29,7 @@
#include "libpandabase/macros.h"
namespace panda::ecmascript::kungfu {
using ProfileType = pgo::ProfileType;
using GateRef = int32_t;
using PGOTypeRef = pgo::PGOTypeRef;
using PGODefineOpType = pgo::PGODefineOpType;
@ -466,15 +467,15 @@ public:
GateType GetGateType() const
{
return type_;
return GateType(type_);
}
static uint64_t ToValue(GateType type)
ParamType GetParamType() const
{
return static_cast<uint64_t>(type.Value());
return ParamType(type_);
}
private:
GateType type_;
uint32_t type_;
};
class ValuePairTypeAccessor {
@ -513,15 +514,15 @@ private:
uint64_t bitField_;
};
class GatePairTypeAccessor {
class TypeConvertAccessor {
public:
// type bits shift
static constexpr int OPRAND_TYPE_BITS = 32;
explicit GatePairTypeAccessor(uint64_t value) : bitField_(value) {}
explicit TypeConvertAccessor(uint64_t value) : bitField_(value) {}
GateType GetLeftType() const
ParamType GetLeftType() const
{
return GateType(LeftBits::Get(bitField_));
return ParamType(LeftBits::Get(bitField_));
}
GateType GetRightType() const
@ -529,7 +530,7 @@ public:
return GateType(RightBits::Get(bitField_));
}
static uint64_t ToValue(GateType leftType, GateType rightType)
static uint64_t ToValue(ParamType leftType, GateType rightType)
{
return LeftBits::Encode(leftType.Value()) | RightBits::Encode(rightType.Value());
}
@ -670,18 +671,12 @@ private:
class ObjectTypeAccessor {
public:
static constexpr int TYPE_BITS_SIZE = 32;
static constexpr int IS_HEAP_OBJECT_BIT_SIZE = 1;
explicit ObjectTypeAccessor(uint64_t value) : bitField_(value) {}
explicit ObjectTypeAccessor(GateType type, bool isHeapObject = false)
explicit ObjectTypeAccessor(bool isHeapObject = false)
{
bitField_ = TypeBits::Encode(type.Value()) | IsHeapObjectBit::Encode(isHeapObject);
}
GateType GetType() const
{
return GateType(TypeBits::Get(bitField_));
bitField_ = IsHeapObjectBit::Encode(isHeapObject);
}
bool IsHeapObject() const
@ -695,8 +690,7 @@ public:
}
private:
using TypeBits = panda::BitField<uint32_t, 0, TYPE_BITS_SIZE>;
using IsHeapObjectBit = TypeBits::NextField<bool, IS_HEAP_OBJECT_BIT_SIZE>;
using IsHeapObjectBit = panda::BitField<bool, 0, IS_HEAP_OBJECT_BIT_SIZE>;
uint64_t bitField_;
};
@ -753,18 +747,14 @@ public:
};
static constexpr int TYPE_BITS_SIZE = 32;
static constexpr int MODE_BITS_SIZE = 8;
static constexpr int ON_HEAP_MODE_BITS_SIZE = 8;
static constexpr int MODE_BITS_SIZE = 2;
static constexpr int ON_HEAP_MODE_BITS_SIZE = 2;
explicit TypedArrayMetaDateAccessor(uint64_t value) : bitField_(value) {}
explicit TypedArrayMetaDateAccessor(GateType type, Mode mode, OnHeapMode onHeap)
{
bitField_ = TypeBits::Encode(type.Value()) | ModeBits::Encode(mode) | OnHeapModeBits::Encode(onHeap);
}
GateType GetType() const
ParamType GetParamType() const
{
return GateType(TypeBits::Get(bitField_));
return ParamType(TypeBits::Get(bitField_));
}
OnHeapMode GetOnHeapMode() const
@ -777,9 +767,9 @@ public:
return ModeBits::Get(bitField_) == Mode::ACCESS_ELEMENT;
}
uint64_t ToValue() const
static uint64_t ToValue(ParamType paramType, Mode mode, OnHeapMode onHeap)
{
return bitField_;
return TypeBits::Encode(paramType.Value()) | ModeBits::Encode(mode) | OnHeapModeBits::Encode(onHeap);
}
private:

View File

@ -133,7 +133,6 @@ namespace panda::ecmascript::kungfu {
#define GATE_OPCODE_LIST(V) \
SHARE_GATE_OPCODE_LIST(V) \
MCR_GATE_OPCODE_LIST(V) \
HCR_GATE_OPCODE_LIST(V)
enum class OpCode : uint16_t {

View File

@ -14,13 +14,15 @@
*/
#include "ecmascript/compiler/slowpath_lowering.h"
#include "ecmascript/dfx/vm_thread_control.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/dfx/vmstat/opt_code_profiler.h"
#include "ecmascript/js_thread.h"
#include "ecmascript/message_string.h"
#include "ecmascript/compiler/bytecodes.h"
#include "ecmascript/compiler/new_object_stub_builder.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/dfx/vm_thread_control.h"
#include "ecmascript/dfx/vmstat/opt_code_profiler.h"
#include "ecmascript/js_async_generator_object.h"
#include "ecmascript/js_generator_object.h"
#include "ecmascript/js_thread.h"
namespace panda::ecmascript::kungfu {
using UseIterator = GateAccessor::UseIterator;
@ -1542,8 +1544,7 @@ GateRef SlowPathLowering::LowerUpdateArrayHClass(GateRef gate, GateRef array)
{
ElementsKind kind = acc_.TryGetElementsKind(gate);
if (!Elements::IsGeneric(kind)) {
auto thread = tsManager_->GetEcmaVM()->GetJSThread();
size_t hclassIndex = static_cast<size_t>(thread->GetArrayHClassIndexMap().at(kind));
size_t hclassIndex = static_cast<size_t>(thread_->GetArrayHClassIndexMap().at(kind));
GateRef gConstAddr = builder_.Load(VariableType::JS_POINTER(), glue_,
builder_.IntPtr(JSThread::GlueData::GetGlobalConstOffset(false)));
GateRef constantIndex = builder_.IntPtr(JSTaggedValue::TaggedTypeSize() * hclassIndex);
@ -2744,17 +2745,18 @@ void SlowPathLowering::AddProfiling(GateRef gate, bool skipGenerator)
return;
}
GateRef func = builder_.Undefined();
if (acc_.HasFrameState(gate)) {
GateRef func = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
GateRef bcIndex = builder_.Int32ToTaggedInt(builder_.Int32(acc_.TryGetBcIndex(gate)));
auto ecmaOpcodeGate = builder_.Int32(static_cast<uint32_t>(ecmaOpcode));
GateRef constOpcode = builder_.Int32ToTaggedInt(ecmaOpcodeGate);
GateRef mode =
builder_.Int32ToTaggedInt(builder_.Int32(static_cast<int32_t>(OptCodeProfiler::Mode::SLOW_PATH)));
GateRef profiling = builder_.CallRuntime(glue_, RTSTUB_ID(ProfileOptimizedCode), acc_.GetDep(gate),
{ func, bcIndex, constOpcode, mode }, gate);
acc_.SetDep(gate, profiling);
func = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
}
GateRef bcIndex = builder_.Int32ToTaggedInt(builder_.Int32(acc_.TryGetBcIndex(gate)));
auto ecmaOpcodeGate = builder_.Int32(static_cast<uint32_t>(ecmaOpcode));
GateRef constOpcode = builder_.Int32ToTaggedInt(ecmaOpcodeGate);
GateRef mode =
builder_.Int32ToTaggedInt(builder_.Int32(static_cast<int32_t>(OptCodeProfiler::Mode::SLOW_PATH)));
GateRef profiling = builder_.CallRuntime(glue_, RTSTUB_ID(ProfileOptimizedCode), acc_.GetDep(gate),
{ func, bcIndex, constOpcode, mode }, gate);
acc_.SetDep(gate, profiling);
}
}

View File

@ -17,11 +17,10 @@
#define ECMASCRIPT_COMPILER_SLOWPATH_LOWERING_H
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/compiler/bytecode_circuit_builder.h"
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/circuit_builder.h"
#include "ecmascript/compiler/circuit_builder-inl.h"
#include "ecmascript/compiler/gate_accessor.h"
#include "ecmascript/compiler/pass_manager.h"
namespace panda::ecmascript::kungfu {
// slowPath Lowering Process
@ -111,9 +110,9 @@ namespace panda::ecmascript::kungfu {
class SlowPathLowering {
public:
SlowPathLowering(Circuit *circuit, CompilationConfig *cmpCfg,
TSManager *tsManager, const MethodLiteral *methodLiteral,
PassContext *ctx, const MethodLiteral *methodLiteral,
bool enableLog, const std::string& name)
: tsManager_(tsManager), methodLiteral_(methodLiteral),
: thread_(ctx->GetEcmaVM()->GetJSThread()), methodLiteral_(methodLiteral),
circuit_(circuit), acc_(circuit),
argAcc_(circuit), builder_(circuit, cmpCfg),
enableLog_(enableLog), methodName_(name), glue_(acc_.GetGlueFromArgList())
@ -321,7 +320,7 @@ private:
void LowerLdStr(GateRef gate);
void LowerGetConstPool(GateRef gate);
TSManager *tsManager_ {nullptr};
JSThread *thread_;
const MethodLiteral *methodLiteral_ {nullptr};
Circuit *circuit_;
GateAccessor acc_;

View File

@ -5690,7 +5690,7 @@ GateRef StubBuilder::TryStringAdd(Environment *env, GateRef glue, GateRef left,
Bind(&stringLeftAddNumberRight);
{
Label hasPendingException(env);
callback.ProfileOpType(Int32(PGOSampleType::StringType()));
// NOTICE-PGO: support string and number
BuiltinsStringStubBuilder builtinsStringStubBuilder(this);
result = builtinsStringStubBuilder.StringConcat(glue, left, NumberToString(glue, right));
BRANCH(HasPendingException(glue), &hasPendingException, &exit);
@ -5701,7 +5701,7 @@ GateRef StubBuilder::TryStringAdd(Environment *env, GateRef glue, GateRef left,
Bind(&numberLeftAddStringRight);
{
Label hasPendingException(env);
callback.ProfileOpType(Int32(PGOSampleType::StringType()));
// NOTICE-PGO: support string and number
BuiltinsStringStubBuilder builtinsStringStubBuilder(this);
result = builtinsStringStubBuilder.StringConcat(glue, NumberToString(glue, left), right);
BRANCH(HasPendingException(glue), &hasPendingException, &exit);
@ -5743,7 +5743,7 @@ GateRef StubBuilder::FastBinaryOp(GateRef glue, GateRef left, GateRef right,
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
if (Op == OpCode::ADD) { // Try string Add
result = TryStringAdd(env, glue, left, right, intOp, floatOp, callback);
} else {
@ -7036,10 +7036,6 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu
}
// 4. call nonNative
Bind(&methodNotNative);
if (IsCallModeSupportPGO(mode)) {
callback.ProfileCall(func);
}
Label funcIsClassConstructor(env);
Label funcNotClassConstructor(env);
Label methodNotAot(env);
@ -7055,6 +7051,9 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu
BRANCH(IsClassConstructorFromBitField(bitfield), &funcIsClassConstructor, &methodNotAot);
Bind(&funcIsClassConstructor);
}
if (IsCallModeSupportPGO(mode)) {
callback.ProfileCall(func);
}
GateRef sp = 0;
if (env->IsAsmInterp()) {
sp = Argument(static_cast<size_t>(InterpreterHandlerInputs::SP));

View File

@ -844,10 +844,10 @@ public:
inline GateRef IsMarkerCellValid(GateRef cell);
inline GateRef GetAccessorHasChanged(GateRef obj);
inline GateRef ComputeTaggedTypedArraySize(GateRef elementSize, GateRef length);
GateRef ChangeTaggedPointerToInt64(GateRef x);
private:
using BinaryOperation = std::function<GateRef(Environment*, GateRef, GateRef)>;
GateRef ChangeTaggedPointerToInt64(GateRef x);
template<OpCode Op>
GateRef FastAddSubAndMul(GateRef glue, GateRef left, GateRef right, ProfileOperation callback);
GateRef FastIntDiv(GateRef left, GateRef right, Label *bailout, ProfileOperation callback);

View File

@ -56,6 +56,7 @@ using ecmascript::kungfu::TypedBinOp;
using ecmascript::kungfu::PGOTypeRef;
using ecmascript::kungfu::PGOSampleType;
using ecmascript::kungfu::GraphLinearizer;
using ecmascript::kungfu::ParamType;
HWTEST_F_L0(LoopOptimizationTest, LoopInt32TypedArraySumOptimizationTest)
{
// construct a circuit
@ -79,26 +80,20 @@ HWTEST_F_L0(LoopOptimizationTest, LoopInt32TypedArraySumOptimizationTest)
builder.LoopBegin(&loopHead);
auto loopBegin = builder.GetState();
EXPECT_TRUE(acc.IsLoopHead(loopBegin));
auto loadLength = builder.LoadTypedArrayLength(array, GateType::AnyType());
auto loadLength = builder.LoadTypedArrayLength(array, ParamType::AnyType());
acc.SetMachineType(loadLength, MachineType::I32);
acc.SetGateType(loadLength, GateType::NJSValue());
auto cmp = builder.TypedBinaryOp<TypedBinOp::TYPED_ADD>(
*index, loadLength, GateType::IntType(), GateType::IntType(),
GateType::NJSValue(), PGOTypeRef::NoneType());
auto cmp = builder.TypedBinaryOp<TypedBinOp::TYPED_ADD>(*index, loadLength, ParamType::IntType());
acc.SetMachineType(cmp, MachineType::I1);
builder.Branch(cmp, &loopBody, &loopExit);
builder.Bind(&loopBody);
auto loadElement = builder.LoadElement<ecmascript::kungfu::TypedLoadOp::INT32ARRAY_LOAD_ELEMENT>(array, *index);
acc.SetMachineType(loadElement, MachineType::I32);
acc.SetGateType(loadElement, GateType::NJSValue());
auto sumAdd = builder.TypedBinaryOp<TypedBinOp::TYPED_ADD>(
*sum, loadElement, GateType::IntType(), GateType::IntType(),
GateType::NJSValue(), PGOTypeRef::NoneType());
auto sumAdd = builder.TypedBinaryOp<TypedBinOp::TYPED_ADD>(*sum, loadElement, ParamType::IntType());
acc.SetMachineType(sumAdd, MachineType::I32);
sum = sumAdd;
auto indexInc = builder.TypedBinaryOp<TypedBinOp::TYPED_ADD>(
*index, builder.Int32(1), GateType::IntType(), GateType::IntType(),
GateType::NJSValue(), PGOTypeRef::NoneType());
auto indexInc = builder.TypedBinaryOp<TypedBinOp::TYPED_ADD>(*index, builder.Int32(1), ParamType::IntType());
acc.SetMachineType(indexInc, MachineType::I32);
index = indexInc;
builder.LoopEnd(&loopHead);

View File

@ -42,6 +42,8 @@ using ecmascript::kungfu::PGOTypeRef;
using ecmascript::kungfu::PGOSampleType;
using ecmascript::kungfu::TypedBinOp;
using ecmascript::kungfu::TypedCallTargetCheckOp;
using ecmascript::kungfu::ParamType;
using ecmascript::kungfu::TypedCallTargetCheckAccessor;
HWTEST_F_L0(MetaDataEqualTests, StringMetaDataEqualTest)
{
@ -194,31 +196,37 @@ HWTEST_F_L0(MetaDataEqualTests, MCRMetaDataEqualTest)
// TypedCallTargetCheckMetaData
auto callGate3 =
circuit.NewGate(circuit.TypedCallTargetCheckOp(0, 0, TypedCallTargetCheckOp::JSCALLTHIS_FAST), MachineType::I64,
{Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate()}, GateType::AnyType());
circuit.NewGate(circuit.TypedCallTargetCheckOp(
TypedCallTargetCheckAccessor::ToValue(TypedCallTargetCheckOp::JSCALLTHIS_FAST)), MachineType::I64,
{Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate()},
GateType::AnyType());
auto callGate4 =
circuit.NewGate(circuit.TypedCallTargetCheckOp(0, 0, TypedCallTargetCheckOp::JSCALLTHIS_FAST), MachineType::I64,
{Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate()}, GateType::AnyType());
circuit.NewGate(circuit.TypedCallTargetCheckOp(
TypedCallTargetCheckAccessor::ToValue(TypedCallTargetCheckOp::JSCALLTHIS_FAST)), MachineType::I64,
{Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate()},
GateType::AnyType());
EXPECT_TRUE(acc.MetaDataValueEqu(callGate3, callGate4));
EXPECT_TRUE(acc.MetaDataValueEqu(callGate4, callGate3));
// TypedBinaryMetaData
PGOSampleType type5 = PGOSampleType::CreateProfileType(0, 1);
uint64_t valueForType5 = ecmascript::kungfu::TypedBinaryAccessor::ToValue(ParamType::IntType(),
TypedBinOp::TYPED_ADD);
auto callGate5 = circuit.NewGate(
circuit.TypedBinaryOp(0, TypedBinOp::TYPED_ADD, PGOTypeRef(static_cast<const PGOSampleType *>(&type5))),
circuit.TypedBinaryOp(valueForType5),
MachineType::I64, { Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate() },
GateType::AnyType());
// TypedBinaryMetaData
PGOSampleType type6 = PGOSampleType::CreateProfileType(0, 1);
uint64_t valueForType6 = ecmascript::kungfu::TypedBinaryAccessor::ToValue(ParamType::IntType(),
TypedBinOp::TYPED_ADD);
auto callGate6 = circuit.NewGate(
circuit.TypedBinaryOp(0, TypedBinOp::TYPED_ADD, PGOTypeRef(static_cast<const PGOSampleType *>(&type6))),
circuit.TypedBinaryOp(valueForType6),
MachineType::I64, { Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate(), Circuit::NullGate() },
GateType::AnyType());
EXPECT_FALSE(acc.MetaDataValueEqu(callGate5, callGate6));
EXPECT_FALSE(acc.MetaDataValueEqu(callGate6, callGate5));
EXPECT_TRUE(acc.MetaDataValueEqu(callGate5, callGate6));
EXPECT_TRUE(acc.MetaDataValueEqu(callGate6, callGate5));
}

View File

@ -37,6 +37,8 @@ using ecmascript::kungfu::Environment;
using ecmascript::kungfu::CombinedPassVisitor;
using ecmascript::kungfu::TypedHCRLowering;
using ecmascript::OnHeapMode;
using ecmascript::kungfu::ParamType;
HWTEST_F_L0(TypedArrayLoweringTests, LoadTypedArrayLength)
{
// construct a circuit
@ -49,7 +51,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, LoadTypedArrayLength)
// after number speculative runner
builder.SetEnvironment(&env);
auto array = builder.Arguments(1);
auto loadLength = builder.LoadTypedArrayLength(array, GateType::AnyType());
auto loadLength = builder.LoadTypedArrayLength(array, ParamType::AnyType());
acc.SetMachineType(loadLength, MachineType::I32);
acc.SetGateType(loadLength, GateType::NJSValue());
auto convert = builder.ConvertInt32ToTaggedInt(loadLength);

View File

@ -79,8 +79,8 @@ GateRef TSHCROptPass::ConvertStringEqualToConst(GateRef left, GateRef right)
auto leftMethodOffset = acc_.TryGetMethodOffset(left);
auto rightMethodOffset = acc_.TryGetMethodOffset(right);
JSHandle<EcmaString> leftStr(thread_, GetStringFromCP(leftMethodOffset, leftId));
JSHandle<EcmaString> rightStr(thread_, GetStringFromCP(rightMethodOffset, rightId));
JSHandle<EcmaString> leftStr(thread_, GetStringFromConstantPool(leftMethodOffset, leftId));
JSHandle<EcmaString> rightStr(thread_, GetStringFromConstantPool(rightMethodOffset, rightId));
bool isEqual = EcmaStringAccessor::StringsAreEqual(thread_->GetEcmaVM(), leftStr, rightStr);
if (isEqual) {
return builder_.Boolean(true);
@ -93,7 +93,7 @@ bool TSHCROptPass::IsSingleCharString(GateRef gate)
if (acc_.IsConstString(gate)) {
uint32_t strId = acc_.GetStringIdFromLdaStrGate(gate);
auto methodOffset = acc_.TryGetMethodOffset(gate);
JSTaggedValue str = GetStringFromCP(methodOffset, strId);
JSTaggedValue str = GetStringFromConstantPool(methodOffset, strId);
return EcmaStringAccessor(str).GetLength() == 1;
}
return acc_.IsSingleCharGate(gate);
@ -117,7 +117,7 @@ GateRef TSHCROptPass::ConvertConstSingleCharToInt32(GateRef gate)
ASSERT(acc_.IsConstString(gate));
uint32_t strId = acc_.GetStringIdFromLdaStrGate(gate);
auto methodOffset = acc_.TryGetMethodOffset(gate);
JSTaggedValue str = tsManager_->GetStringFromConstantPool(methodOffset, strId);
JSTaggedValue str = GetStringFromConstantPool(methodOffset, strId);
ASSERT(EcmaStringAccessor(str).GetLength() == 1);
uint16_t strToInt = EcmaStringAccessor(str).Get(0);
return builder_.Int32(strToInt);
@ -131,8 +131,7 @@ GateRef TSHCROptPass::ConvertToSingleCharComparison(GateRef left, GateRef right)
} else if (acc_.IsConstString(right)) {
right = ConvertConstSingleCharToInt32(right);
}
return builder_.TypedBinaryOp<TypedBinOp::TYPED_EQ>(left, right, GateType::IntType(),
GateType::IntType(), GateType::BooleanType(),
PGOTypeRef::NoneType());
// change string binary operator to int binary operator
return builder_.TypedBinaryOp<TypedBinOp::TYPED_EQ>(left, right, ParamType::IntType());
}
} // namespace panda::ecmascript::kungfu

View File

@ -27,7 +27,7 @@ public:
PassContext *ctx, bool enableLog, const std::string &name)
: PassVisitor(circuit, chunk, visitor),
builder_(circuit, ctx->GetCompilerConfig()),
tsManager_(ctx->GetTSManager()),
ptManager_(ctx->GetPTManager()),
thread_(ctx->GetEcmaVM()->GetJSThread()),
enableLog_(enableLog),
methodName_(name) {}
@ -47,9 +47,9 @@ private:
return methodName_;
}
JSTaggedValue GetStringFromCP(uint32_t methodOffset, uint32_t cpIdx) const
JSTaggedValue GetStringFromConstantPool(uint32_t methodOffset, uint32_t cpIdx) const
{
return tsManager_->GetStringFromConstantPool(methodOffset, cpIdx);
return ptManager_->GetStringFromConstantPool(methodOffset, cpIdx);
}
GateRef VisitTypedBinaryOp(GateRef gate);
@ -63,7 +63,7 @@ private:
GateRef ConvertToSingleCharComparison(GateRef left, GateRef right);
CircuitBuilder builder_;
TSManager *tsManager_ {nullptr};
PGOTypeManager *ptManager_ {nullptr};
const JSThread *thread_ {nullptr};
bool enableLog_ {false};
std::string methodName_;

View File

@ -12,17 +12,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/compiler/ts_inline_lowering.h"
#include "ecmascript/compiler/bytecode_circuit_builder.h"
#include "ecmascript/compiler/bytecodes.h"
#include "ecmascript/compiler/compiler_log.h"
#include "ecmascript/compiler/pass.h"
#include "ecmascript/compiler/ts_inline_lowering.h"
#include "ecmascript/compiler/type_info_accessors.h"
#include "ecmascript/ts_types/ts_manager.h"
#include "ecmascript/ts_types/ts_type.h"
#include "libpandabase/utils/utf.h"
#include "libpandafile/class_data_accessor-inl.h"
#include "ecmascript/ts_types/ts_type_accessor.h"
namespace panda::ecmascript::kungfu {
void TSInlineLowering::RunTSInlineLowering()
@ -54,18 +50,10 @@ void TSInlineLowering::CollectInlineInfo()
void TSInlineLowering::GetInlinedMethodId(GateRef gate)
{
ASSERT(acc_.GetOpCode(gate) == OpCode::FRAME_ARGS);
GateRef func = acc_.GetValueIn(gate, static_cast<size_t>(FrameArgIdx::FUNC));
uint32_t methodOffset = 0;
auto funcType = acc_.GetGateType(func);
if (tsManager_->IsFunctionTypeKind(funcType)) {
GlobalTSTypeRef gt = funcType.GetGTRef();
methodOffset = tsManager_->GetFuncMethodOffset(gt);
}
if (methodOffset == 0) {
auto pgoType = acc_.TryGetPGOType(gate);
if (pgoType.IsValidCallMethodId()) {
methodOffset = pgoType.GetCallMethodId();
}
auto pgoType = acc_.TryGetPGOType(gate);
if (pgoType.IsValidCallMethodId()) {
methodOffset = pgoType.GetCallMethodId();
}
acc_.UpdateMethodOffset(gate, methodOffset);
}
@ -136,7 +124,7 @@ void TSInlineLowering::TryInline(InlineTypeInfoAccessor &info, ChunkQueue<Inline
auto &methodInfo = bytecodeInfo.GetMethodList().at(methodOffset);
auto &methodPcInfos = bytecodeInfo.GetMethodPcInfos();
auto &methodPcInfo = methodPcInfos[methodInfo.GetMethodPcInfoIndex()];
if (ctx_->FilterMethod(inlinedMethod, methodPcInfo)) {
if (info.IsNormalCall() && ctx_->FilterMethod(inlinedMethod, methodPcInfo)) {
return;
}
GateRef frameState = GetFrameState(info);
@ -213,7 +201,6 @@ void TSInlineLowering::InlineCall(MethodInfo &methodInfo, MethodPcInfo &methodPC
InlineTypeInfoAccessor &info)
{
const JSPandaFile *jsPandaFile = ctx_->GetJSPandaFile();
TSManager *tsManager = ctx_->GetTSManager();
CompilerLog *log = ctx_->GetCompilerLog();
CString recordName = MethodLiteral::GetRecordName(jsPandaFile, method->GetMethodId());
bool hasTyps = jsPandaFile->HasTSTypes(recordName);
@ -223,10 +210,8 @@ void TSInlineLowering::InlineCall(MethodInfo &methodInfo, MethodPcInfo &methodPC
circuit_->InitRoot();
BytecodeCircuitBuilder builder(jsPandaFile, method, methodPCInfo,
tsManager, circuit_,
ctx_->GetByteCodes(), true, IsLogEnabled(),
enableTypeLowering_, fullName, recordName, ctx_->GetPfDecoder(), true,
passOptions_->EnableOptTrackField());
circuit_, ctx_->GetByteCodes(), IsLogEnabled(),
enableTypeLowering_, fullName, recordName, ctx_->GetPfDecoder(), true);
{
if (enableTypeLowering_) {
BuildFrameStateChain(info, builder);
@ -239,14 +224,14 @@ void TSInlineLowering::InlineCall(MethodInfo &methodInfo, MethodPcInfo &methodPC
PassData data(&builder, circuit_, ctx_, log, fullName,
&methodInfo, hasTyps, recordName,
method, method->GetMethodId().GetOffset(), nativeAreaAllocator_, ctx_->GetPfDecoder(), passOptions_);
method, method->GetMethodId().GetOffset(), nullptr, CVector<AbcFileInfo>{},
nativeAreaAllocator_, ctx_->GetPfDecoder(), passOptions_);
PassRunner<PassData> pipeline(&data);
pipeline.RunPass<RedundantPhiEliminationPass>();
if (builder.EnableLoopOptimization()) {
pipeline.RunPass<LoopOptimizationPass>();
pipeline.RunPass<RedundantPhiEliminationPass>();
}
pipeline.RunPass<TypeInferPass>();
pipeline.RunPass<PGOTypeInferPass>();
}
@ -546,7 +531,7 @@ void TSInlineLowering::InlineAccessorCheck(const InlineTypeInfoAccessor &info)
ASSERT(ptManager->QueryHClass(receiverType.first, receiverType.second).IsJSHClass());
bool noNeedCheckHeapObject = acc_.IsHeapObjectFromElementsKind(receiver);
builder_.ObjectTypeCheck(acc_.GetGateType(gate), noNeedCheckHeapObject, receiver, builder_.Int32(receiverHCIndex),
builder_.ObjectTypeCheck(noNeedCheckHeapObject, receiver, builder_.Int32(receiverHCIndex),
acc_.GetFrameState(gate));
auto currentLabel = env.GetCurrentLabel();
auto callState = currentLabel->GetControl();
@ -715,16 +700,14 @@ void TSInlineLowering::SetInitCallTargetAndConstPoolId(InlineTypeInfoAccessor &i
if (initCallTarget_ == Circuit::NullGate()) {
GateRef frameArgs = GetFrameArgs(info);
initCallTarget_ = acc_.GetValueIn(frameArgs, 0);
const JSPandaFile *pf = ctx_->GetJSPandaFile();
initConstantPoolId_ = tsManager_->GetConstantPoolIDByMethodOffset(pf, initMethodOffset_);
initConstantPoolId_ = ptManager_->GetConstantPoolIDByMethodOffset(initMethodOffset_);
}
}
int32_t TSInlineLowering::GetAccessorConstpoolId(InlineTypeInfoAccessor &info)
uint32_t TSInlineLowering::GetAccessorConstpoolId(InlineTypeInfoAccessor &info)
{
ASSERT(info.IsCallAccessor());
uint32_t inlineMethodOffset = info.GetCallMethodId();
const JSPandaFile *pf = ctx_->GetJSPandaFile();
return tsManager_->GetConstantPoolIDByMethodOffset(pf, inlineMethodOffset);
return ptManager_->GetConstantPoolIDByMethodOffset(inlineMethodOffset);
}
} // namespace panda::ecmascript

View File

@ -17,13 +17,10 @@
#define ECMASCRIPT_COMPILER_TS_INLINE_LOWERING_H
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
#include "ecmascript/compiler/bytecode_circuit_builder.h"
#include "ecmascript/compiler/bytecode_info_collector.h"
#include "ecmascript/compiler/circuit_builder-inl.h"
#include "ecmascript/compiler/pass_manager.h"
#include "ecmascript/compiler/type_info_accessors.h"
#include "ecmascript/jspandafile/js_pandafile.h"
namespace panda::ecmascript::kungfu {
class CircuitRootScope {
@ -53,7 +50,7 @@ public:
acc_(circuit),
glue_(acc_.GetGlueFromArgList()),
builder_(circuit, ctx->GetCompilerConfig()),
tsManager_(ctx->GetTSManager()),
ptManager_(ctx->GetPTManager()),
ctx_(ctx),
passOptions_(options),
enableLog_(enableLog),
@ -138,14 +135,14 @@ private:
GateRef GetCallSetterValue(GateRef gate);
GateRef GetFrameState(InlineTypeInfoAccessor &info);
void SetInitCallTargetAndConstPoolId(InlineTypeInfoAccessor &info);
int32_t GetAccessorConstpoolId(InlineTypeInfoAccessor &info);
uint32_t GetAccessorConstpoolId(InlineTypeInfoAccessor &info);
Circuit *circuit_ {nullptr};
JSThread *thread_ {nullptr};
GateAccessor acc_;
GateRef glue_;
CircuitBuilder builder_;
TSManager *tsManager_ {nullptr};
PGOTypeManager *ptManager_ {nullptr};
PassContext *ctx_ {nullptr};
PassOptions *passOptions_ {nullptr};
bool enableLog_ {false};
@ -161,7 +158,7 @@ private:
size_t lastCallId_ {0};
ArgumentAccessor argAcc_;
uint32_t initMethodOffset_ {0};
int32_t initConstantPoolId_ {0};
uint32_t initConstantPoolId_ {0};
GateRef initCallTarget_ {Circuit::NullGate()};
};
} // panda::ecmascript::kungfu

View File

@ -16,6 +16,7 @@
#ifndef ECMASCRIPT_COMPILER_TYPE_H
#define ECMASCRIPT_COMPILER_TYPE_H
#include "ecmascript/js_hclass.h"
#include "ecmascript/ts_types/global_ts_type_ref.h"
#define VALUE_TYPE_LIST(V) \
@ -41,15 +42,102 @@ enum class ValueType : uint8_t {
};
namespace panda::ecmascript::kungfu {
class GateType {
#define PRIMITIVE_TYPE_LIST(V) \
V(ANY, AnyType) \
V(NUMBER, NumberType) \
V(BOOLEAN, BooleanType) \
V(VOID_TYPE, VoidType) \
V(STRING, StringType) \
V(SYMBOL, SymbolType) \
V(NULL_TYPE, NullType) \
V(UNDEFINED, UndefinedType) \
V(INT, IntType) \
V(BIG_INT, BigIntType) \
V(DOUBLE, DoubleType) \
// ParamType: Prediction type from PGO, bound to MetaData in GATE
#define PARAM_TYPE_LIST(V) \
V(INT_OVERFLOW, IntOverflowType) \
class ParamType {
public:
constexpr explicit GateType(uint32_t type = 0) : type_(type)
explicit ParamType(uint32_t type = 0) : type_(type) {}
explicit ParamType(JSType jsType)
{
type_ = BUILTIN_TYPE | static_cast<uint32_t>(jsType);
}
explicit GateType(GlobalTSTypeRef gt) : type_(0)
#define DEFINE_TYPE_CONSTRUCTOR(type, name) \
static ParamType name() { return ParamType(static_cast<uint32_t>(type)); }
PRIMITIVE_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
PARAM_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
#undef DEFINE_TYPE_CONSTRUCTOR
#define DEFINE_JUDGE_METHOD(type, name) \
bool Is##name() const { return type_ == static_cast<uint32_t>(type); }
PRIMITIVE_TYPE_LIST(DEFINE_JUDGE_METHOD)
PARAM_TYPE_LIST(DEFINE_JUDGE_METHOD)
#undef DEFINE_JUDGE_METHOD
uint32_t Value() const
{
type_ |= gt.GetType();
return type_;
}
bool HasNumberType() const
{
return IsNumberType() || IsIntType() || IsIntOverflowType() || IsDoubleType();
}
bool IsBuiltinType() const
{
return type_ & BUILTIN_TYPE;
}
JSType GetBuiltinType() const
{
return static_cast<JSType>(type_ & ~BUILTIN_TYPE);
}
bool operator ==(const ParamType &other) const
{
return type_ == other.type_;
}
bool operator !=(const ParamType &other) const
{
return !(*this == other);
}
private:
enum : uint8_t {
#define DECLARE_TYPE(type, name) type,
PRIMITIVE_TYPE_LIST(DECLARE_TYPE)
PARAM_TYPE_LIST(DECLARE_TYPE)
#undef DECLARE_TYPE
};
static constexpr uint32_t BUILTIN_TYPE = (1 << 31); // 31 : the 31-th bit is set implies builtin type
uint32_t type_ {0};
};
#undef PARAM_TYPE_LIST
// GateType: Trusted type, directly bound to Gate
class GateType {
public:
constexpr explicit GateType(uint32_t type = 0)
{
type_ |= type;
}
explicit GateType([[maybe_unused]]GlobalTSTypeRef gt)
{
// linxiang shoult remove in part3
type_ = EMPTY;
}
~GateType() = default;
@ -86,142 +174,113 @@ public:
static GateType AnyType()
{
GlobalTSTypeRef r(0, static_cast<int>(TSPrimitiveType::ANY));
return GateType(r);
return GateType(static_cast<uint32_t>(TSPrimitiveType::ANY));
}
static GateType NumberType()
{
GlobalTSTypeRef r(0, static_cast<int>(TSPrimitiveType::NUMBER));
return GateType(r);
return GateType(static_cast<uint32_t>(TSPrimitiveType::NUMBER));
}
static GateType DoubleType()
{
GlobalTSTypeRef r(0, static_cast<int>(TSPrimitiveType::DOUBLE));
return GateType(r);
return GateType(static_cast<uint32_t>(TSPrimitiveType::DOUBLE));
}
static GateType BooleanType()
{
GlobalTSTypeRef r(0, static_cast<int>(TSPrimitiveType::BOOLEAN));
return GateType(r);
return GateType(static_cast<uint32_t>(TSPrimitiveType::BOOLEAN));
}
static GateType VoidType()
{
GlobalTSTypeRef r(0, static_cast<int>(TSPrimitiveType::VOID_TYPE));
return GateType(r);
return GateType(static_cast<uint32_t>(TSPrimitiveType::VOID_TYPE));
}
static GateType StringType()
{
GlobalTSTypeRef r(0, static_cast<int>(TSPrimitiveType::STRING));
return GateType(r);
return GateType(static_cast<uint32_t>(TSPrimitiveType::STRING));
}
static GateType SymbolType()
{
GlobalTSTypeRef r(0, static_cast<int>(TSPrimitiveType::SYMBOL));
return GateType(r);
return GateType(static_cast<uint32_t>(TSPrimitiveType::SYMBOL));
}
static GateType NullType()
{
GlobalTSTypeRef r(0, static_cast<int>(TSPrimitiveType::NULL_TYPE));
return GateType(r);
return GateType(static_cast<uint32_t>(TSPrimitiveType::NULL_TYPE));
}
static GateType UndefinedType()
{
GlobalTSTypeRef r(0, static_cast<int>(TSPrimitiveType::UNDEFINED));
return GateType(r);
return GateType(static_cast<uint32_t>(TSPrimitiveType::UNDEFINED));
}
static GateType IntType()
{
GlobalTSTypeRef r(0, static_cast<int>(TSPrimitiveType::INT));
return GateType(r);
return GateType(static_cast<uint32_t>(TSPrimitiveType::INT));
}
static GateType BigIntType()
{
GlobalTSTypeRef r(0, static_cast<int>(TSPrimitiveType::BIG_INT));
return GateType(r);
return GateType(static_cast<uint32_t>(TSPrimitiveType::BIG_INT));
}
bool IsAnyType() const
{
GlobalTSTypeRef r = GetGTRef();
uint32_t m = r.GetModuleId();
uint32_t l = r.GetLocalId();
return (m == 0) && (l == static_cast<uint32_t>(TSPrimitiveType::ANY));
uint32_t type = GetType();
return type == static_cast<uint32_t>(TSPrimitiveType::ANY);
}
bool IsNumberType() const
{
GlobalTSTypeRef r = GetGTRef();
uint32_t m = r.GetModuleId();
uint32_t l = r.GetLocalId();
return (m == 0) && ((l == static_cast<uint32_t>(TSPrimitiveType::NUMBER)) ||
(l == static_cast<uint32_t>(TSPrimitiveType::INT)) ||
(l == static_cast<uint32_t>(TSPrimitiveType::DOUBLE)));
uint32_t type = GetType();
return ((type == static_cast<uint32_t>(TSPrimitiveType::NUMBER)) ||
(type == static_cast<uint32_t>(TSPrimitiveType::INT)) ||
(type == static_cast<uint32_t>(TSPrimitiveType::DOUBLE)));
}
bool IsIntType() const
{
GlobalTSTypeRef r = GetGTRef();
uint32_t m = r.GetModuleId();
uint32_t l = r.GetLocalId();
return (m == 0) && (l == static_cast<uint32_t>(TSPrimitiveType::INT));
uint32_t type = GetType();
return type == static_cast<uint32_t>(TSPrimitiveType::INT);
}
bool IsDoubleType() const
{
GlobalTSTypeRef r = GetGTRef();
uint32_t m = r.GetModuleId();
uint32_t l = r.GetLocalId();
return (m == 0) && (l == static_cast<uint32_t>(TSPrimitiveType::DOUBLE));
uint32_t type = GetType();
return type == static_cast<uint32_t>(TSPrimitiveType::DOUBLE);
}
bool IsStringType() const
{
GlobalTSTypeRef r = GetGTRef();
uint32_t m = r.GetModuleId();
uint32_t l = r.GetLocalId();
return (m == 0) && (l == static_cast<uint32_t>(TSPrimitiveType::STRING));
uint32_t type = GetType();
return type == static_cast<uint32_t>(TSPrimitiveType::STRING);
}
bool IsNullType() const
{
GlobalTSTypeRef r = GetGTRef();
uint32_t m = r.GetModuleId();
uint32_t l = r.GetLocalId();
return (m == 0) && (l == static_cast<uint32_t>(TSPrimitiveType::NULL_TYPE));
uint32_t type = GetType();
return type == static_cast<uint32_t>(TSPrimitiveType::NULL_TYPE);
}
bool IsUndefinedType() const
{
GlobalTSTypeRef r = GetGTRef();
uint32_t m = r.GetModuleId();
uint32_t l = r.GetLocalId();
return (m == 0) && (l == static_cast<uint32_t>(TSPrimitiveType::UNDEFINED));
uint32_t type = GetType();
return type == static_cast<uint32_t>(TSPrimitiveType::UNDEFINED);
}
bool IsBooleanType() const
{
GlobalTSTypeRef r = GetGTRef();
uint32_t m = r.GetModuleId();
uint32_t l = r.GetLocalId();
return (m == 0) && (l == static_cast<uint32_t>(TSPrimitiveType::BOOLEAN));
uint32_t type = GetType();
return type == static_cast<uint32_t>(TSPrimitiveType::BOOLEAN);
}
bool IsBigIntType() const
{
GlobalTSTypeRef r = GetGTRef();
uint32_t m = r.GetModuleId();
uint32_t l = r.GetLocalId();
return (m == 0) && (l == static_cast<uint32_t>(TSPrimitiveType::BIG_INT));
uint32_t type = GetType();
return type == static_cast<uint32_t>(TSPrimitiveType::BIG_INT);
}
bool IsNJSValueType() const
@ -236,10 +295,8 @@ public:
bool IsSymbolType() const
{
GlobalTSTypeRef r = GetGTRef();
uint32_t m = r.GetModuleId();
uint32_t l = r.GetLocalId();
return (m == 0) && (l == static_cast<uint32_t>(TSPrimitiveType::SYMBOL));
uint32_t type = GetType();
return type == static_cast<uint32_t>(TSPrimitiveType::SYMBOL);
}
// In addition to normal number types, null, undefined, boolean types will be converted to numeric types when doing
@ -289,10 +346,16 @@ public:
return type_ >= other.type_;
}
uint32_t GetType() const
{
return type_ & (~MIR_TYPE_MASK);
}
GlobalTSTypeRef GetGTRef() const
{
uint32_t r = type_ & (~MIR_TYPE_MASK);
return GlobalTSTypeRef(r);
// linxiang shoult remove in part3
GlobalTSTypeRef empty;
return empty;
}
private:

View File

@ -1,160 +0,0 @@
/*
* Copyright (c) 2023 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.
*/
#include "ecmascript/compiler/type_inference/global_type_infer.h"
namespace panda::ecmascript::kungfu {
GlobalTypeInfer::GlobalTypeInfer(PassContext *ctx, const uint32_t methodOffset, const CString &recordName,
PGOProfilerDecoder *decoder, bool enableOptTrackField, bool enableLog, bool hasType)
: ctx_(ctx), jsPandaFile_(ctx_->GetJSPandaFile()), bcInfo_(ctx->GetBytecodeInfo()), methodOffset_(methodOffset),
recordName_(recordName), decoder_(decoder), enableOptTrackField_(enableOptTrackField), enableLog_(enableLog),
hasType_(hasType), enableGlobalTypeInfer_(
ctx_->GetTSManager()->GetEcmaVM()->GetJSOptions().IsEnableGlobalTypeInfer())
{
CollectNamespaceMethods(methodOffset);
for (const auto namespaceMethod : namespaceTypes_) {
NewTypeInfer(namespaceMethod);
}
}
GlobalTypeInfer::~GlobalTypeInfer()
{
for (auto it : typeInfers_) {
if (it.second != nullptr) {
delete it.second;
}
}
typeInfers_.clear();
for (auto it : builders_) {
if (it != nullptr) {
delete it;
}
}
builders_.clear();
for (auto it: circuits_) {
if (it != nullptr) {
delete it;
}
}
circuits_.clear();
}
void GlobalTypeInfer::NewTypeInfer(const uint32_t methodOffset)
{
auto module = ctx_->GetAOTModule();
auto &methodList = bcInfo_.GetMethodList();
MethodInfo &methodInfo = methodList.at(methodOffset);
const auto &methodPcInfos = bcInfo_.GetMethodPcInfos();
auto &methodPcInfo = methodPcInfos[methodInfo.GetMethodPcInfoIndex()];
auto methodLiteral = jsPandaFile_->FindMethodLiteral(methodOffset);
std::string fullName = module->GetFuncName(methodLiteral, jsPandaFile_);
Circuit *circuit = new Circuit(ctx_->GetNativeAreaAllocator(), module->GetDebugInfo(),
fullName.c_str(), ctx_->GetCompilerConfig()->Is64Bit(),
FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
circuits_.emplace_back(circuit);
BytecodeCircuitBuilder *builder =
new BytecodeCircuitBuilder(jsPandaFile_, methodLiteral, methodPcInfo, ctx_->GetTSManager(), circuit,
ctx_->GetByteCodes(), jsPandaFile_->HasTSTypes(recordName_), enableLog_, true,
fullName, recordName_, decoder_, false, enableOptTrackField_);
builder->BytecodeToCircuit();
builders_.emplace_back(builder);
MethodTypeInfer *typeInfer = new MethodTypeInfer(builder, circuit, ctx_, methodInfo.GetMethodInfoIndex(),
enableLog_, fullName, recordName_, &methodInfo,
methodLiteral, enableGlobalTypeInfer_, hasType_);
typeInfers_.insert(std::make_pair(methodOffset, typeInfer));
}
void GlobalTypeInfer::CollectNamespaceMethod(const uint32_t methodOffset)
{
auto &methodList = bcInfo_.GetMethodList();
MethodInfo &methodInfo = methodList.at(methodOffset);
auto &innerMethods = methodInfo.GetInnerMethods();
uint32_t length = innerMethods.size();
for (uint32_t i = 0; i < length; i++) {
MethodInfo &innerMethodInfo = methodList.at(innerMethods[i]);
if (innerMethodInfo.IsNamespace()) {
namespaceTypes_.insert(innerMethods[i]);
CollectNamespaceMethod(innerMethods[i]);
}
}
}
void GlobalTypeInfer::CollectNamespaceMethods(const uint32_t methodOffset)
{
if (!enableGlobalTypeInfer_) {
namespaceTypes_.clear();
return;
}
CollectNamespaceMethod(methodOffset);
if (namespaceTypes_.size() > MAX_GLOBAL_INFER_ALLOWED) {
namespaceTypes_.clear();
}
}
void GlobalTypeInfer::ProcessTypeInference(BytecodeCircuitBuilder *builder, Circuit *circuit)
{
auto &methodList = bcInfo_.GetMethodList();
MethodInfo &methodInfo = methodList.at(methodOffset_);
MethodTypeInfer typeInfer(builder, circuit, ctx_, methodInfo.GetMethodInfoIndex(), enableLog_,
builder->GetMethodName(), recordName_, &methodInfo,
jsPandaFile_->FindMethodLiteral(methodOffset_),
enableGlobalTypeInfer_, hasType_);
TSManager *tsManager = ctx_->GetTSManager();
std::stack<MethodTypeInfer *> typeInferStack;
typeInferStack.push(&typeInfer);
// In TS, a namespace declaration is only allowed at the top level of a namespace or module and
// it can be thought of as a formalization of the IIFE pattern. Based on the function definition
// domain chain, there will be no loops containing namespace declarations.
// This shows that the following stack will definitely stop.
while (!typeInferStack.empty()) {
MethodTypeInfer *infer = typeInferStack.top();
if (infer == nullptr) {
typeInferStack.pop();
continue;
}
uint32_t methodId = 0;
GateType type;
std::tie(type, methodId) = infer->TraverseInfer();
if (IsLegalMethod(methodId)) {
MethodTypeInfer *nextInfer = GetTypeInfer(methodId);
if (nextInfer != nullptr) {
nextInfer->SetNamespaceArgType(type);
tsManager->StoreNamespaceType(methodId, type);
typeInferStack.push(nextInfer);
continue;
}
}
typeInferStack.pop();
}
typeInfer.CheckAndPrint();
RunTypeCheck();
}
void GlobalTypeInfer::RunTypeCheck()
{
for (auto it : typeInfers_) {
if (it.second != nullptr) {
it.second->CheckAndPrint();
}
}
}
} // namespace panda::ecmascript

View File

@ -1,68 +0,0 @@
/*
* Copyright (c) 2023 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.
*/
#ifndef ECMASCRIPT_COMPILER_TYPE_INFERENCE_GLOBAL_TYPE_INFER_H
#define ECMASCRIPT_COMPILER_TYPE_INFERENCE_GLOBAL_TYPE_INFER_H
#include "ecmascript/compiler/type_inference/method_type_infer.h"
namespace panda::ecmascript::kungfu {
class GlobalTypeInfer {
public:
GlobalTypeInfer(PassContext *ctx, const uint32_t methodOffset, const CString &recordName,
PGOProfilerDecoder *decoder, bool enableOptTrackField, bool enableLog, bool hasType);
~GlobalTypeInfer();
void ProcessTypeInference(BytecodeCircuitBuilder *builder, Circuit *circuit);
private:
static constexpr size_t MAX_GLOBAL_INFER_ALLOWED = 2;
inline MethodTypeInfer *GetTypeInfer(const uint32_t methodOffset) const
{
auto it = typeInfers_.find(methodOffset);
if (it != typeInfers_.end()) {
return it->second;
}
return nullptr;
}
inline bool IsLegalMethod(const uint32_t methodOffset) const
{
return (methodOffset != 0);
}
void NewTypeInfer(const uint32_t methodOffset);
void CollectNamespaceMethod(const uint32_t methodOffset);
void CollectNamespaceMethods(const uint32_t methodOffset);
void RunTypeCheck();
PassContext *ctx_ {nullptr};
const JSPandaFile *jsPandaFile_ {nullptr};
BCInfo &bcInfo_;
uint32_t methodOffset_ {0};
const CString &recordName_;
PGOProfilerDecoder *decoder_ {nullptr};
bool enableOptTrackField_ {false};
bool enableLog_ {false};
bool hasType_ {false};
bool enableGlobalTypeInfer_ {false};
std::set<uint32_t> namespaceTypes_ {};
std::vector<BytecodeCircuitBuilder *> builders_ {};
std::vector<Circuit *> circuits_ {};
std::map<uint32_t, MethodTypeInfer *> typeInfers_ {};
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_TYPE_INFERENCE_GLOBAL_TYPE_INFER_H

File diff suppressed because it is too large Load Diff

View File

@ -1,197 +0,0 @@
/*
* Copyright (c) 2022 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.
*/
#ifndef ECMASCRIPT_COMPILER_TYPE_INFERENCE_METHOD_TYPE_INFER_H
#define ECMASCRIPT_COMPILER_TYPE_INFERENCE_METHOD_TYPE_INFER_H
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/compiler/bytecode_circuit_builder.h"
#include "ecmascript/compiler/compiler_log.h"
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/gate_accessor.h"
#include "ecmascript/compiler/pass_manager.h"
#include "ecmascript/ts_types/ts_manager.h"
namespace panda::ecmascript::kungfu {
enum InferState : uint8_t {
// loop-begin gate has been infered to non-any type
NORMAL_INFERED = 0,
// loop-begin gate has been fixed to any type manually and it should not be infered to other types
ANY_INFERED,
// the number-types of loop-begin gate under this state should be promoted to number type
NUMBER_INFERED,
};
class MethodTypeInfer {
public:
MethodTypeInfer(BytecodeCircuitBuilder *builder, Circuit *circuit,
PassContext *ctx, size_t methodId, bool enableLog,
const std::string &name, const CString &recordName,
MethodInfo *methodInfo, const MethodLiteral *methodLiteral,
bool enableGlobalTypeInfer, bool hasType);
~MethodTypeInfer() = default;
NO_COPY_SEMANTIC(MethodTypeInfer);
NO_MOVE_SEMANTIC(MethodTypeInfer);
std::pair<GateType, uint32_t> TraverseInfer();
void CheckAndPrint();
void SetNamespaceArgType(GateType type);
bool IsLogEnabled() const
{
return enableLog_;
}
private:
static constexpr int PERCENT_LENS = 2;
static constexpr int HUNDRED_TIME = 100;
const std::string &GetMethodName() const
{
return methodName_;
}
// 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);
GateType HandleTypeCompatibility(const GateType preType, const GateType type) const;
bool ShouldInfer(const GateRef gate) const;
bool Infer(GateRef gate);
bool InferPhiGate(GateRef gate);
bool SetIntType(GateRef gate);
bool SetNumberType(GateRef gate);
bool SetBigIntType(GateRef gate);
bool SetBooleanType(GateRef gate);
bool InferLdUndefined(GateRef gate);
bool InferLdNull(GateRef gate);
bool InferLdai(GateRef gate);
bool InferFLdai(GateRef gate);
bool InferLdSymbol(GateRef gate);
bool InferThrow(GateRef gate);
bool InferTypeOf(GateRef gate);
bool InferAdd2(GateRef gate);
bool InferSub2(GateRef gate);
bool InferMul2(GateRef gate);
bool InferMod2(GateRef gate);
bool InferDiv2(GateRef gate);
bool InferIncDec(GateRef gate);
bool InferToNumberic(GateRef gate);
bool InferLdObjByIndex(GateRef gate);
bool InferLdGlobalVar(GateRef gate);
bool InferReturnUndefined(GateRef gate);
bool InferReturn(GateRef gate);
bool InferLdObjByName(GateRef gate);
bool InferNewObject(GateRef gate);
bool SetStGlobalBcType(GateRef gate, bool hasIC = false);
bool InferLdStr(GateRef gate);
bool InferCallFunction(GateRef gate);
bool InferCallMethod(GateRef gate);
bool InferLdObjByValue(GateRef gate);
bool InferGetNextPropName(GateRef gate);
bool InferDefineGetterSetterByValue(GateRef gate);
bool InferSuperCall(GateRef gate);
bool InferSuperPropertyByName(GateRef gate);
bool InferSuperPropertyByValue(GateRef gate);
bool InferTryLdGlobalByName(GateRef gate);
bool InferLdLexVarDyn(GateRef gate);
bool InferStLexVarDyn(GateRef gate);
bool InferStModuleVar(GateRef gate);
bool InferLdLocalModuleVar(GateRef gate);
bool InferLdExternalModuleVar(GateRef gate);
bool InferStObjByName(GateRef gate);
bool IsNewLexEnv(EcmaOpcode opcode) const;
bool InferGetIterator(GateRef gate);
bool InferLoopBeginPhiGate(GateRef gate);
bool GetObjPropWithName(GateRef gate, GateType objType, uint64_t index);
bool GetSuperProp(GateRef gate, uint64_t index, bool isString = true);
GlobalTSTypeRef ConvertPrimitiveToBuiltin(const GateType &gateType);
GlobalTSTypeRef GetPropType(const GateType type, const JSTaggedValue propertyName) const;
GlobalTSTypeRef GetPropType(const GateType type, const uint64_t key) const;
void UpdateQueueForLoopPhi();
inline bool ShouldInferWithLdObjByValue(const GateType &type) const
{
auto flag = tsManager_->IsObjectTypeKind(type) ||
tsManager_->IsClassTypeKind(type) ||
tsManager_->IsClassInstanceTypeKind(type);
return flag;
}
inline bool ShouldInferWithLdObjByName(const GateType &type) const
{
return ShouldInferWithLdObjByValue(type) || tsManager_->IsIteratorInstanceTypeKind(type) ||
tsManager_->IsInterfaceTypeKind(type) || tsManager_->IsNamespaceTypeKind(type);
}
inline bool ShouldConvertToBuiltinArray(const GateType &type) const
{
return tsManager_->IsArrayTypeKind(type) && tsManager_->IsBuiltinsDTSEnabled();
}
void PrintTypeAnnotation() const;
void PrintByteCodesWithTypes() const;
void PrintCircuitWithTypes() const;
void Verify() const;
void VerifyTypePercent();
void TypeCheck(GateRef gate) const;
void PGOTypeCheck(GateRef gate) const;
void Enqueue(GateRef gate);
std::string CollectGateTypeLogInfo(GateRef gate, DebugInfoExtractor *debugExtractor,
const std::string &logPreFix, bool isPGO) const;
const BytecodeInfo &GetByteCodeInfo(const GateRef gate) const
{
const auto bcIndex = jsgateToBytecode_.at(gate);
return builder_->GetBytecodeInfo(bcIndex);
}
std::pair<GateType, uint32_t> SetAndReturnNamespaceObjType(GateRef gate);
GlobalTSTypeRef TryGetNamespaceType(GateRef gate) const;
bool IsNamespace(GateRef gate) const;
bool CheckNamespaceFunc(GateRef func) const;
bool IsByteCodeGate(const GateRef gate) const
{
return jsgateToBytecode_.find(gate) != jsgateToBytecode_.end();
}
BytecodeCircuitBuilder *builder_ {nullptr};
Circuit *circuit_ {nullptr};
GateAccessor gateAccessor_;
TSManager *tsManager_ {nullptr};
PassContext *ctx_ {nullptr};
LexEnvManager *lexEnvManager_ {nullptr};
size_t methodId_ {0};
bool enableLog_ {false};
std::string methodName_;
std::map<uint16_t, GateType> stringIdToGateType_;
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};
const MethodLiteral *methodLiteral_ {nullptr};
std::vector<bool> inQueue_;
std::unordered_set<GateRef> needInferGates_ {};
std::queue<GateRef> pendingQueue_ {};
bool needUpdateForLoopPhi_ {true};
bool enableGlobalTypeInfer_ {false};
bool hasType_ {false};
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_TYPE_INFERENCE_METHOD_TYPE_INFER_H

View File

@ -262,7 +262,7 @@ void PGOTypeInfer::UpdateTypeForRWOp(GateRef gate, GateRef receiver, uint32_t pr
JSTaggedValue prop = JSTaggedValue::Undefined();
if (propIndex != INVALID_INDEX) {
auto methodOffset = acc_.TryGetMethodOffset(gate);
prop = tsManager_->GetStringFromConstantPool(methodOffset, propIndex);
prop = ptManager_->GetStringFromConstantPool(methodOffset, propIndex);
}
ChunkSet<GateType> inferTypes = helper_.GetInferTypes(chunk_, types, prop);
AddProfiler(gate, tsType, *pgoRwTypes, inferTypes);

View File

@ -25,10 +25,11 @@ namespace panda::ecmascript::kungfu {
struct CollectedType;
class PGOTypeInfer {
public:
PGOTypeInfer(Circuit *circuit, TSManager *tsManager, BytecodeCircuitBuilder *builder,
PGOTypeInfer(Circuit *circuit, TSManager *tsManager, PGOTypeManager *ptManager, BytecodeCircuitBuilder *builder,
const std::string &name, Chunk *chunk, bool enableLog)
: circuit_(circuit), acc_(circuit), argAcc_(circuit), tsManager_(tsManager), helper_(tsManager),
builder_(builder), methodName_(name), chunk_(chunk), enableLog_(enableLog), profiler_(chunk) {}
: circuit_(circuit), acc_(circuit), argAcc_(circuit), tsManager_(tsManager),
ptManager_(ptManager), helper_(tsManager), builder_(builder), methodName_(name), chunk_(chunk),
enableLog_(enableLog), profiler_(chunk) {}
~PGOTypeInfer() = default;
void Run();
@ -88,6 +89,7 @@ private:
GateAccessor acc_;
ArgumentAccessor argAcc_;
TSManager *tsManager_ {nullptr};
PGOTypeManager *ptManager_ {nullptr};
PGOTypeInferHelper helper_;
BytecodeCircuitBuilder *builder_ {nullptr};
const std::string &methodName_;

View File

@ -19,41 +19,84 @@
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/global_env.h"
#include "ecmascript/global_env_fields.h"
#include "ecmascript/js_hclass-inl.h"
#include "ecmascript/jspandafile/js_pandafile.h"
#include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/ts_types/ts_type_accessor.h"
namespace panda::ecmascript::kungfu {
JSTaggedValue TypeInfoAccessor::GetStringFromConstantPool(const JSThread *thread, uint32_t methodId, uint32_t index)
{
return thread->GetCurrentEcmaContext()->GetTSManager()->GetStringFromConstantPool(methodId, index);
return thread->GetCurrentEcmaContext()->GetPTManager()->GetStringFromConstantPool(methodId, index);
}
ParamType TypeInfoAccessor::PGOSampleTypeToParamType() const
{
if (pgoType_.IsPGOSampleType()) {
auto sample = pgoType_.GetPGOSampleType();
if (sample->IsInt()) {
return ParamType::IntType();
} else if (sample->IsIntOverFlow()) {
return ParamType::IntOverflowType();
} else if (sample->IsDouble()) {
return ParamType::DoubleType();
} else if (sample->IsString()) {
return ParamType::StringType();
} else if (sample->IsBigInt()) {
return ParamType::BigIntType();
} else if (sample->IsBoolean()) {
return ParamType::BooleanType();
} else if (sample->IsNumber()) {
return ParamType::NumberType();
}
}
return ParamType::AnyType();
}
ParamType TypeInfoAccessor::PGOBuiltinTypeToParamType(ProfileType pgoType)
{
if (pgoType.IsBuiltinsType()) {
return ParamType(pgoType.GetBuiltinsType());
}
return ParamType::AnyType();
}
// TypeTrusted means the type of gate is already PrimitiveTypeCheck-passed,
// or the gate is constant and no need to check.
bool TypeInfoAccessor::IsTrustedType(GateAccessor acc, GateRef gate)
bool TypeInfoAccessor::IsTrustedBooleanType(GateAccessor acc, GateRef gate)
{
if (acc.IsConstant(gate)) {
if (acc.IsConstant(gate) && acc.GetGateType(gate).IsBooleanType()) {
return true;
}
auto op = acc.GetOpCode(gate);
if (acc.IsTypedOperator(gate)) {
if (op == OpCode::TYPED_BINARY_OP) {
return !acc.GetGateType(gate).IsIntType();
} else {
return true;
if (op == OpCode::TYPED_BINARY_OP) {
TypedBinaryAccessor accessor(acc.TryGetValue(gate));
TypedBinOp binOp = accessor.GetTypedBinOp();
switch (binOp) {
case TypedBinOp::TYPED_EQ:
case TypedBinOp::TYPED_LESS:
case TypedBinOp::TYPED_NOTEQ:
case TypedBinOp::TYPED_LESSEQ:
case TypedBinOp::TYPED_GREATER:
case TypedBinOp::TYPED_STRICTEQ:
case TypedBinOp::TYPED_GREATEREQ:
case TypedBinOp::TYPED_STRICTNOTEQ:
return true;
default:
return false;
}
} else if (op == OpCode::TYPED_UNARY_OP) {
TypedUnaryAccessor accessor(acc.TryGetValue(gate));
TypedUnOp unOp = accessor.GetTypedUnOp();
switch (unOp) {
case TypedUnOp::TYPED_ISTRUE:
case TypedUnOp::TYPED_ISFALSE:
return true;
default:
return false;
}
}
if (op == OpCode::JS_BYTECODE) {
EcmaOpcode ecmaOpcode = acc.GetByteCodeOpcode(gate);
switch (ecmaOpcode) {
case EcmaOpcode::ADD2_IMM8_V8:
case EcmaOpcode::SUB2_IMM8_V8:
case EcmaOpcode::MUL2_IMM8_V8:
return !acc.GetGateType(gate).IsIntType();
case EcmaOpcode::INC_IMM8:
case EcmaOpcode::DEC_IMM8:
case EcmaOpcode::LESS_IMM8_V8:
case EcmaOpcode::LESSEQ_IMM8_V8:
case EcmaOpcode::GREATER_IMM8_V8:
@ -72,6 +115,90 @@ bool TypeInfoAccessor::IsTrustedType(GateAccessor acc, GateRef gate)
return false;
}
bool TypeInfoAccessor::IsTrustedNumberType(GateAccessor acc, GateRef gate)
{
if (acc.IsConstant(gate) && acc.GetGateType(gate).IsNumberType()) {
return true;
}
auto op = acc.GetOpCode(gate);
if (op == OpCode::TYPED_BINARY_OP) {
TypedBinaryAccessor accessor(acc.TryGetValue(gate));
TypedBinOp binOp = accessor.GetTypedBinOp();
switch (binOp) {
case TypedBinOp::TYPED_ADD:
case TypedBinOp::TYPED_SUB:
case TypedBinOp::TYPED_MUL:
case TypedBinOp::TYPED_DIV:
case TypedBinOp::TYPED_MOD:
case TypedBinOp::TYPED_SHL:
case TypedBinOp::TYPED_SHR:
case TypedBinOp::TYPED_ASHR:
case TypedBinOp::TYPED_AND:
case TypedBinOp::TYPED_OR:
case TypedBinOp::TYPED_XOR:
return accessor.GetParamType().HasNumberType();
default:
return false;
}
} else if (op == OpCode::TYPED_UNARY_OP) {
TypedUnaryAccessor accessor(acc.TryGetValue(gate));
TypedUnOp unOp = accessor.GetTypedUnOp();
switch (unOp) {
case TypedUnOp::TYPED_DEC:
case TypedUnOp::TYPED_INC:
case TypedUnOp::TYPED_NEG:
case TypedUnOp::TYPED_NOT:
return accessor.GetParamType().HasNumberType();
default:
return false;
}
} else if (op == OpCode::TYPE_CONVERT) {
// typeconvert only use in tomumeric
return true;
} else if (op == OpCode::LOAD_ELEMENT) {
auto loadOp = acc.GetTypedLoadOp(gate);
switch (loadOp) {
case TypedLoadOp::INT8ARRAY_LOAD_ELEMENT:
case TypedLoadOp::UINT8ARRAY_LOAD_ELEMENT:
case TypedLoadOp::UINT8CLAMPEDARRAY_LOAD_ELEMENT:
case TypedLoadOp::INT16ARRAY_LOAD_ELEMENT:
case TypedLoadOp::UINT16ARRAY_LOAD_ELEMENT:
case TypedLoadOp::INT32ARRAY_LOAD_ELEMENT:
case TypedLoadOp::UINT32ARRAY_LOAD_ELEMENT:
case TypedLoadOp::FLOAT32ARRAY_LOAD_ELEMENT:
case TypedLoadOp::FLOAT64ARRAY_LOAD_ELEMENT:
return true;
default:
return false;
}
}
if (op == OpCode::JS_BYTECODE) {
EcmaOpcode ecmaOpcode = acc.GetByteCodeOpcode(gate);
switch (ecmaOpcode) {
case EcmaOpcode::ADD2_IMM8_V8:
case EcmaOpcode::SUB2_IMM8_V8:
case EcmaOpcode::MUL2_IMM8_V8:
case EcmaOpcode::DIV2_IMM8_V8:
case EcmaOpcode::MOD2_IMM8_V8:
case EcmaOpcode::SHL2_IMM8_V8:
case EcmaOpcode::SHR2_IMM8_V8:
case EcmaOpcode::ASHR2_IMM8_V8:
case EcmaOpcode::AND2_IMM8_V8:
case EcmaOpcode::OR2_IMM8_V8:
case EcmaOpcode::XOR2_IMM8_V8:
case EcmaOpcode::INC_IMM8:
case EcmaOpcode::DEC_IMM8:
case EcmaOpcode::NEG_IMM8:
case EcmaOpcode::NOT_IMM8:
return acc.TryGetPGOType(gate).GetPGOSampleType()->HasNumber();
default:
break;
}
}
return false;
}
bool TypeInfoAccessor::IsTrustedStringType(
const JSThread *thread, Circuit *circuit, Chunk *chunk, GateAccessor acc, GateRef gate)
{
@ -102,71 +229,6 @@ bool TypeInfoAccessor::IsTrustedStringType(
return false;
}
BinOpTypeInfoAccessor::BinOpTypeInfoAccessor(const JSThread *thread, Circuit *circuit,
GateRef gate, bool convertNumberType)
: TypeInfoAccessor(thread, circuit, gate), convertNumberType_(convertNumberType)
{
left_ = acc_.GetValueIn(gate, 0); // 0: left
right_ = acc_.GetValueIn(gate, 1); // 1: right
}
bool BinOpTypeInfoAccessor::HasNumberType() const
{
GateType leftType = acc_.GetGateType(left_);
GateType rightType = acc_.GetGateType(right_);
const PGOSampleType *sampleType = acc_.TryGetPGOType(gate_).GetPGOSampleType();
if (sampleType->IsNumber()) {
return true;
} else if (convertNumberType_ && sampleType->IsNone() && leftType.IsPrimitiveNumberType() &&
rightType.IsPrimitiveNumberType()) {
return true;
} else if (!convertNumberType_ && sampleType->IsNone() && leftType.IsNumberType() && rightType.IsNumberType()) {
return true;
} else {
return false;
}
return false;
}
bool BinOpTypeInfoAccessor::HasStringType() const
{
const PGOSampleType *sampleType = acc_.TryGetPGOType(gate_).GetPGOSampleType();
return sampleType->IsString();
}
UnOpTypeInfoAccessor::UnOpTypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate)
: TypeInfoAccessor(thread, circuit, gate)
{
value_ = acc_.GetValueIn(gate, 0); // 0: value
}
bool UnOpTypeInfoAccessor::ValueIsNumberType() const
{
const PGOSampleType *sampleType = acc_.TryGetPGOType(gate_).GetPGOSampleType();
if (sampleType->IsNumber()) {
return true;
}
return false;
}
GateType UnOpTypeInfoAccessor::FetchNumberType() const
{
const PGOSampleType *sampleType = acc_.TryGetPGOType(gate_).GetPGOSampleType();
if (sampleType->IsNumber()) {
if (sampleType->IsInt()) {
return GateType::IntType();
} else if (sampleType->IsDouble()) {
return GateType::DoubleType();
} else {
return GateType::NumberType();
}
} else {
LOG_COMPILER(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
}
bool NewObjRangeTypeInfoAccessor::FindHClass()
{
auto sampleType = acc_.TryGetPGOType(gate_).GetPGOSampleType();
@ -183,15 +245,7 @@ bool NewObjRangeTypeInfoAccessor::FindHClass()
bool TypeOfTypeInfoAccessor::IsIllegalType() const
{
GateType valueType = GetValueGateType();
if (!valueType.IsDigitablePrimitiveType() && !valueType.IsStringType() && !valueType.IsSymbolType()) {
if (!tsManager_->IsFunctionTypeKind(valueType) && !tsManager_->IsObjectTypeKind(valueType) &&
!tsManager_->IsClassTypeKind(valueType) && !tsManager_->IsClassInstanceTypeKind(valueType) &&
!tsManager_->IsArrayTypeKind(valueType)) {
return true;
}
}
return false;
return true;
}
SuperCallTypeInfoAccessor::SuperCallTypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate)
@ -200,7 +254,7 @@ SuperCallTypeInfoAccessor::SuperCallTypeInfoAccessor(const JSThread *thread, Cir
ctor_ = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
}
BuiltinsStubCSigns::ID CallTypeInfoAccessor::TryGetPGOBuiltinId() const
BuiltinsStubCSigns::ID CallTypeInfoAccessor::TryGetPGOBuiltinMethodId() const
{
PGOTypeRef sampleType = acc_.TryGetPGOType(gate_);
if (sampleType.GetPGOSampleType()->IsNone()) {
@ -212,55 +266,56 @@ BuiltinsStubCSigns::ID CallTypeInfoAccessor::TryGetPGOBuiltinId() const
return BuiltinsStubCSigns::ID::NONE;
}
BuiltinsStubCSigns::ID CallTypeInfoAccessor::TryGetBuiltinId(BuiltinTypeId id) const
{
GateType funcType = acc_.GetGateType(func_);
if (!tsManager_->IsBuiltinObjectMethod(id, funcType)) {
return BuiltinsStubCSigns::ID::NONE;
}
std::string name = tsManager_->GetFuncName(funcType);
BuiltinsStubCSigns::ID stubId = BuiltinsStubCSigns::GetBuiltinId(name);
return stubId;
}
GetIteratorTypeInfoAccessor::GetIteratorTypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate)
: CallTypeInfoAccessor(thread, circuit, gate)
GetIteratorTypeInfoAccessor::GetIteratorTypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate,
const JSPandaFile *jsPandaFile,
const CallMethodFlagMap *callMethodFlagMap)
: CallTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap)
{
argc_ = 0; // 0: number of argc
func_ = acc_.GetValueIn(gate, 0); // 1: func
}
CallArg0TypeInfoAccessor::CallArg0TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate)
: CallTypeInfoAccessor(thread, circuit, gate)
CallArg0TypeInfoAccessor::CallArg0TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate,
const JSPandaFile *jsPandaFile,
const CallMethodFlagMap *callMethodFlagMap)
: CallTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap)
{
argc_ = 0; // 0: number of argc
func_ = acc_.GetValueIn(gate, 0); // 0: func
}
CallArg1TypeInfoAccessor::CallArg1TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate)
: CallTypeInfoAccessor(thread, circuit, gate)
CallArg1TypeInfoAccessor::CallArg1TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate,
const JSPandaFile *jsPandaFile,
const CallMethodFlagMap *callMethodFlagMap)
: CallTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap)
{
argc_ = 1; // 1: number of argc
value_ = acc_.GetValueIn(gate, 0); // 0: value
func_ = acc_.GetValueIn(gate, 1); // 1: func
}
CallArg2TypeInfoAccessor::CallArg2TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate)
: CallTypeInfoAccessor(thread, circuit, gate)
CallArg2TypeInfoAccessor::CallArg2TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate,
const JSPandaFile *jsPandaFile,
const CallMethodFlagMap *callMethodFlagMap)
: CallTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap)
{
argc_ = 2; // 2: number of argc
func_ = acc_.GetValueIn(gate, 2); // 2: func
}
CallArg3TypeInfoAccessor::CallArg3TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate)
: CallTypeInfoAccessor(thread, circuit, gate)
CallArg3TypeInfoAccessor::CallArg3TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate,
const JSPandaFile *jsPandaFile,
const CallMethodFlagMap *callMethodFlagMap)
: CallTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap)
{
argc_ = 3; // 3: number of argc
func_ = acc_.GetValueIn(gate, 3); // 3: func
}
CallRangeTypeInfoAccessor::CallRangeTypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate)
: CallTypeInfoAccessor(thread, circuit, gate)
CallRangeTypeInfoAccessor::CallRangeTypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate,
const JSPandaFile *jsPandaFile,
const CallMethodFlagMap *callMethodFlagMap)
: CallTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap)
{
size_t numArgs = acc_.GetNumValueIn(gate);
constexpr size_t callTargetIndex = 1; // acc
@ -270,51 +325,64 @@ CallRangeTypeInfoAccessor::CallRangeTypeInfoAccessor(const JSThread *thread, Cir
bool CallThisTypeInfoAccessor::CanOptimizeAsFastCall()
{
GateType funcType = acc_.GetGateType(func_);
if (!tsManager_->IsFunctionTypeKind(funcType)) {
return false;
}
auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType();
auto op = acc_.GetOpCode(func_);
if (op != OpCode::LOAD_PROPERTY || !acc_.IsVtable(func_)) {
if (!IsValidCallMethodId()) {
return false;
}
return true;
if (!profileType->IsNone()) {
if (profileType->IsProfileTypeNone() || op != OpCode::LOAD_PROPERTY) {
return false;
}
return true;
}
return false;
}
CallThis0TypeInfoAccessor::CallThis0TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate)
: CallThisTypeInfoAccessor(thread, circuit, gate)
CallThis0TypeInfoAccessor::CallThis0TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate,
const JSPandaFile *jsPandaFile,
const CallMethodFlagMap *callMethodFlagMap)
: CallThisTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap)
{
argc_ = 0; // 0: number of argc
func_ = acc_.GetValueIn(gate, 1); // 1: func
}
CallThis1TypeInfoAccessor::CallThis1TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate)
: CallThisTypeInfoAccessor(thread, circuit, gate)
CallThis1TypeInfoAccessor::CallThis1TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate,
const JSPandaFile *jsPandaFile,
const CallMethodFlagMap *callMethodFlagMap)
: CallThisTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap)
{
argc_ = 1; // 1: number of argc
func_ = acc_.GetValueIn(gate, 2); // 2: func
a0_ = acc_.GetValueIn(gate, 1); // 1: arg0
}
CallThis2TypeInfoAccessor::CallThis2TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate)
: CallThisTypeInfoAccessor(thread, circuit, gate)
CallThis2TypeInfoAccessor::CallThis2TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate,
const JSPandaFile *jsPandaFile,
const CallMethodFlagMap *callMethodFlagMap)
: CallThisTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap)
{
argc_ = 2; // 2: number of argc
func_ = acc_.GetValueIn(gate, 3); // 3: func
}
CallThis3TypeInfoAccessor::CallThis3TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate)
: CallThisTypeInfoAccessor(thread, circuit, gate)
CallThis3TypeInfoAccessor::CallThis3TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate,
const JSPandaFile *jsPandaFile,
const CallMethodFlagMap *callMethodFlagMap)
: CallThisTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap)
{
argc_ = 3; // 3: number of argc
func_ = acc_.GetValueIn(gate, 3); // 3: func
func_ = acc_.GetValueIn(gate, 4); // 4: func
a0_ = acc_.GetValueIn(gate, 1); // 1: arg0
a1_ = acc_.GetValueIn(gate, 2); // 2: arg1
a2_ = acc_.GetValueIn(gate, 3); // 3: arg2
}
CallThisRangeTypeInfoAccessor::CallThisRangeTypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate)
: CallThisTypeInfoAccessor(thread, circuit, gate)
CallThisRangeTypeInfoAccessor::CallThisRangeTypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate,
const JSPandaFile *jsPandaFile,
const CallMethodFlagMap *callMethodFlagMap)
: CallThisTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap)
{
constexpr size_t fixedInputsNum = 1;
constexpr size_t callTargetIndex = 1; // 1: acc
@ -353,7 +421,7 @@ PropertyLookupResult InlineTypeInfoAccessor::GetAccessorPlr() const
GateRef constData = acc_.GetValueIn(gate_, 1);
uint16_t propIndex = acc_.GetConstantValue(constData);
auto methodOffset = acc_.TryGetMethodOffset(gate_);
auto prop = tsManager_->GetStringFromConstantPool(methodOffset, propIndex);
auto prop = ptManager_->GetStringFromConstantPool(methodOffset, propIndex);
// PGO currently does not support call, so GT is still used to support inline operations.
// However, the original GT solution cannot support accessing the property of prototype, so it is filtered here
if (EcmaStringAccessor(prop).ToStdString() == "prototype") {
@ -398,13 +466,11 @@ uint32_t InlineTypeInfoAccessor::GetCallMethodId() const
return methodOffset;
}
}
if (methodOffset == 0) {
if (IsFunctionTypeKind()) {
auto funcGT = GetReceiverGT().GetGTRef();
methodOffset = tsManager_->GetFuncMethodOffset(funcGT);
} else if (IsClassInstanceTypeKind()) {
auto funcGT = GetAccessorFuncGT();
methodOffset = tsManager_->GetFuncMethodOffset(funcGT);
if (IsCallAccessor()) {
const PGORWOpType *pgoTypes = acc_.TryGetPGOType(gate_).GetPGORWOpType();
auto pgoType = pgoTypes->GetObjectInfo(0);
if (pgoType.GetAccessorMethod().GetProfileType().IsValidCallMethodId()) {
return pgoType.GetAccessorMethod().GetProfileType().GetCallMethodId();
}
}
return methodOffset;
@ -687,30 +753,13 @@ LoadBulitinObjTypeInfoAccessor::LoadBulitinObjTypeInfoAccessor(const JSThread *t
FetchBuiltinsTypes();
}
bool AccBuiltinObjTypeInfoAccessor::IsMonoIgnoreElemKind() const
bool AccBuiltinObjTypeInfoAccessor::IsMonoBuiltins() const
{
if (IsMono()) {
return true;
}
if (types_.empty()) {
if (types_.size() == 0) {
return false;
}
auto firstIter = types_[0];
for (auto type : types_) {
if (type.IsBuiltinsType() != firstIter.IsBuiltinsType()) {
return false;
}
}
return true;
}
bool AccBuiltinObjTypeInfoAccessor::IsAllString() const
{
if (types_.empty()) {
return false;
}
for (auto type : types_) {
if (!type.IsBuiltinsString()) {
for (size_t i = 0; i < types_.size(); i++) {
if (!types_[0].IsBuiltinsType()) {
return false;
}
}
@ -788,7 +837,7 @@ void CreateObjWithBufferTypeInfoAccessor::Init()
{
auto imm = acc_.GetConstantValue(index_);
auto methodOffset = acc_.TryGetMethodOffset(GetGate());
JSTaggedValue cp = tsManager_->GetConstantPool(methodOffset);
JSTaggedValue cp = ptManager_->GetConstantPoolByMethodOffset(methodOffset);
JSTaggedValue unsharedCp = thread_->GetCurrentEcmaContext()->FindOrCreateUnsharedConstpool(cp);
JSTaggedValue obj = ConstantPool::GetLiteralFromCache<ConstPoolType::OBJECT_LITERAL>(
tsManager_->GetEcmaVM()->GetJSThread(), unsharedCp, imm, recordName_);

View File

@ -16,11 +16,14 @@
#ifndef ECMASCRIPT_COMPILER_TYPE_INFO_ACCESSORS_H
#define ECMASCRIPT_COMPILER_TYPE_INFO_ACCESSORS_H
#include "ecmascript/compiler/aot_compiler_preprocessor.h"
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
#include "ecmascript/enum_conversion.h"
#include "ecmascript/global_index.h"
#include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/ts_types/ts_manager.h"
#include "libpandafile/index_accessor.h"
namespace panda::ecmascript::kungfu {
class TypeInfoAccessor {
@ -31,21 +34,20 @@ public:
argAcc_(circuit),
gate_(gate)
{
pgoType_ = acc_.TryGetPGOType(gate);
// NOTICE-PGO: wx delete in part3
tsManager_ = thread_->GetCurrentEcmaContext()->GetTSManager();
ptManager_ = thread_->GetCurrentEcmaContext()->GetPTManager();
}
GateRef GetGate() const
inline GateRef GetGate() const
{
return gate_;
}
PGOTypeRef GetPGOType() const
{
return acc_.TryGetPGOType(GetGate());
}
static bool IsTrustedBooleanType(GateAccessor acc, GateRef gate);
static bool IsTrustedType(GateAccessor acc, GateRef gate);
static bool IsTrustedNumberType(GateAccessor acc, GateRef gate);
static bool IsTrustedStringType(
const JSThread *thread, Circuit *circuit, Chunk *chunk, GateAccessor acc, GateRef gate);
@ -53,10 +55,15 @@ public:
static JSTaggedValue GetStringFromConstantPool(const JSThread *thread, uint32_t methodId, uint32_t index);
protected:
ParamType PGOSampleTypeToParamType() const;
static ParamType PGOBuiltinTypeToParamType(ProfileType pgoType);
const JSThread *thread_ {nullptr};
GateAccessor acc_;
ArgumentAccessor argAcc_;
GateRef gate_;
PGOTypeRef pgoType_;
// NOTICE-PGO: wx delete in part3
TSManager *tsManager_ {nullptr};
PGOTypeManager *ptManager_ {nullptr};
};
@ -65,22 +72,46 @@ class BinOpTypeInfoAccessor final : public TypeInfoAccessor {
public:
BinOpTypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate,
bool convertNumberType = false);
GateRef gate)
: TypeInfoAccessor(thread, circuit, gate)
{
left_ = acc_.GetValueIn(gate, 0); // 0: left
right_ = acc_.GetValueIn(gate, 1); // 1: right
}
NO_COPY_SEMANTIC(BinOpTypeInfoAccessor);
NO_MOVE_SEMANTIC(BinOpTypeInfoAccessor);
bool HasNumberType() const;
inline GateRef GetLeftGate() const
{
return left_;
}
bool HasStringType() const;
inline GateRef GetReightGate() const
{
return right_;
}
bool LeftOrRightIsUndefinedOrNullOrHole() const
inline bool HasNumberType() const
{
return pgoType_.HasNumber();
}
inline bool IsStringType() const
{
return pgoType_.IsString();
}
inline bool LeftOrRightIsUndefinedOrNull() const
{
return acc_.IsUndefinedOrNullOrHole(left_) || acc_.IsUndefinedOrNullOrHole(right_);
}
inline ParamType GetParamType() const
{
return PGOSampleTypeToParamType();
}
private:
bool convertNumberType_;
GateRef left_;
GateRef right_;
};
@ -89,29 +120,34 @@ class UnOpTypeInfoAccessor : public TypeInfoAccessor {
public:
UnOpTypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate);
GateRef gate)
: TypeInfoAccessor(thread, circuit, gate)
{
value_ = acc_.GetValueIn(gate, 0); // 0: value
}
NO_COPY_SEMANTIC(UnOpTypeInfoAccessor);
NO_MOVE_SEMANTIC(UnOpTypeInfoAccessor);
bool ValueIsNumberType() const;
GateType FetchNumberType() const;
bool ValueIsPrimitiveNumberType() const
{
return GetValueGateType().IsPrimitiveNumberType();
}
bool ValueIsBooleanType() const
{
return GetValueGateType().IsBooleanType();
}
GateRef GetValue() const
inline GateRef GetValue() const
{
return value_;
}
inline bool HasNumberType() const
{
return pgoType_.HasNumber();
}
inline bool IsBooleanType() const
{
return pgoType_.IsBoolean();
}
inline ParamType GetParamType() const
{
return PGOSampleTypeToParamType();
}
GateType GetValueGateType() const
{
return acc_.GetGateType(value_);
@ -207,9 +243,9 @@ public:
return tsManager_->IsClassTypeKind(acc_.GetGateType(ctor_));
}
bool IsFunctionTypeKind() const
bool IsValidCallMethodId() const
{
return tsManager_->IsFunctionTypeKind(acc_.GetGateType(ctor_));
return pgoType_.IsValidCallMethodId();
}
GateRef GetCtor() const
@ -225,10 +261,14 @@ class CallTypeInfoAccessor : public TypeInfoAccessor {
public:
CallTypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate)
GateRef gate,
const JSPandaFile *jsPandaFile = nullptr,
const CallMethodFlagMap *callMethodFlagMap = nullptr)
: TypeInfoAccessor(thread, circuit, gate),
argc_(0),
func_(Circuit::NullGate())
func_(Circuit::NullGate()),
jsPandaFile_(jsPandaFile),
callMethodFlagMap_(callMethodFlagMap)
{}
size_t GetArgc() const
@ -246,70 +286,128 @@ public:
return acc_.GetGateType(func_);
}
bool IsFunctionTypeKind() const
bool IsValidCallMethodId() const
{
return tsManager_->IsFunctionTypeKind(acc_.GetGateType(func_));
return pgoType_.IsValidCallMethodId();
}
bool IsHotnessFunc() const
{
return tsManager_->IsHotnessFunc(GetFunctionGT());
if (jsPandaFile_ == nullptr || callMethodFlagMap_ == nullptr) {
return false;
}
auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType();
bool haveProfileType = !profileType->IsNone();
if (haveProfileType) {
CString fileDesc = jsPandaFile_->GetNormalizedFileDesc();
uint32_t methodId = profileType->GetProfileType().GetId();
return callMethodFlagMap_->IsAotCompile(fileDesc, methodId);
}
return false;
}
uint32_t GetFunctionTypeLength() const
{
return tsManager_->GetFunctionTypeLength(GetFunctionGT());
if (jsPandaFile_ == nullptr || callMethodFlagMap_ == nullptr) {
return false;
}
auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType();
bool haveProfileType = !profileType->IsNone();
if (haveProfileType) {
uint32_t methodId = profileType->GetProfileType().GetId();
MethodLiteral *targetMethodLiteral = jsPandaFile_->FindMethodLiteral(methodId);
return targetMethodLiteral->GetNumArgsWithCallField();
}
return 0;
}
bool IsNoGC() const
{
return tsManager_->IsNoGC(GetFunctionGT());
}
bool FastCallFlagIsVaild() const
{
return tsManager_->FastCallFlagIsVaild(GetFunctionGT());
if (jsPandaFile_ == nullptr || callMethodFlagMap_ == nullptr) {
return false;
}
auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType();
bool haveProfileType = !profileType->IsNone();
if (haveProfileType) {
uint32_t methodId = profileType->GetProfileType().GetId();
MethodLiteral *targetMethodLiteral = jsPandaFile_->FindMethodLiteral(methodId);
return targetMethodLiteral->IsNoGC();
}
return false;
}
int GetMethodIndex() const
{
return tsManager_->GetMethodIndex(GetFunctionGT());
if (jsPandaFile_ == nullptr || callMethodFlagMap_ == nullptr) {
return false;
}
auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType();
bool haveProfileType = !profileType->IsNone();
if (haveProfileType) {
uint32_t methodId = profileType->GetProfileType().GetId();
panda_file::IndexAccessor indexAccessor(*(jsPandaFile_->GetPandaFile()),
panda_file::File::EntityId(methodId));
uint32_t cpId = static_cast<uint32_t>(indexAccessor.GetHeaderIndex());
JSHandle<ConstantPool> constpoolHandle(thread_,
thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile_, cpId));
return constpoolHandle->GetMethodIndexByEntityId(panda_file::File::EntityId(methodId));
}
return 0;
}
bool MethodOffsetIsVaild() const
{
return tsManager_->MethodOffsetIsVaild(GetFunctionGT());
auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType();
return !profileType->IsNone();
}
bool CanFastCall() const
{
return tsManager_->CanFastCall(GetFunctionGT());
if (jsPandaFile_ == nullptr || callMethodFlagMap_ == nullptr) {
return false;
}
auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType();
bool haveProfileType = !profileType->IsNone();
if (haveProfileType) {
CString fileDesc = jsPandaFile_->GetNormalizedFileDesc();
uint32_t methodId = profileType->GetProfileType().GetId();
return callMethodFlagMap_->IsAotCompile(fileDesc, methodId) &&
callMethodFlagMap_->IsFastCall(fileDesc, methodId);
}
return false;
}
uint32_t GetFuncMethodOffset() const
{
return tsManager_->GetFuncMethodOffset(GetFunctionGT());
if (jsPandaFile_ == nullptr || callMethodFlagMap_ == nullptr) {
return false;
}
auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType();
bool haveProfileType = !profileType->IsNone();
if (haveProfileType) {
uint32_t methodId = profileType->GetProfileType().GetId();
MethodLiteral *targetMethodLiteral = jsPandaFile_->FindMethodLiteral(methodId);
return targetMethodLiteral->GetMethodId().GetOffset();
}
return 0;
}
BuiltinsStubCSigns::ID TryGetPGOBuiltinId() const;
BuiltinsStubCSigns::ID TryGetBuiltinId(BuiltinTypeId id) const;
BuiltinsStubCSigns::ID TryGetPGOBuiltinMethodId() const;
protected:
GlobalTSTypeRef GetFunctionGT() const
{
return acc_.GetGateType(func_).GetGTRef();
}
size_t argc_;
GateRef func_;
const JSPandaFile *jsPandaFile_;
const CallMethodFlagMap *callMethodFlagMap_;
};
class GetIteratorTypeInfoAccessor final : public CallTypeInfoAccessor {
public:
GetIteratorTypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate);
GateRef gate,
const JSPandaFile *jsPandaFile = nullptr,
const CallMethodFlagMap *callMethodFlagMap = nullptr);
NO_COPY_SEMANTIC(GetIteratorTypeInfoAccessor);
NO_MOVE_SEMANTIC(GetIteratorTypeInfoAccessor);
@ -323,7 +421,9 @@ class CallArg0TypeInfoAccessor final : public CallTypeInfoAccessor {
public:
CallArg0TypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate);
GateRef gate,
const JSPandaFile *jsPandaFile = nullptr,
const CallMethodFlagMap *callMethodFlagMap = nullptr);
NO_COPY_SEMANTIC(CallArg0TypeInfoAccessor);
NO_MOVE_SEMANTIC(CallArg0TypeInfoAccessor);
};
@ -332,7 +432,9 @@ class CallArg1TypeInfoAccessor final : public CallTypeInfoAccessor {
public:
CallArg1TypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate);
GateRef gate,
const JSPandaFile *jsPandaFile = nullptr,
const CallMethodFlagMap *callMethodFlagMap = nullptr);
NO_COPY_SEMANTIC(CallArg1TypeInfoAccessor);
NO_MOVE_SEMANTIC(CallArg1TypeInfoAccessor);
@ -354,7 +456,9 @@ class CallArg2TypeInfoAccessor final : public CallTypeInfoAccessor {
public:
CallArg2TypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate);
GateRef gate,
const JSPandaFile *jsPandaFile = nullptr,
const CallMethodFlagMap *callMethodFlagMap = nullptr);
NO_COPY_SEMANTIC(CallArg2TypeInfoAccessor);
NO_MOVE_SEMANTIC(CallArg2TypeInfoAccessor);
};
@ -363,7 +467,9 @@ class CallArg3TypeInfoAccessor final : public CallTypeInfoAccessor {
public:
CallArg3TypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate);
GateRef gate,
const JSPandaFile *jsPandaFile = nullptr,
const CallMethodFlagMap *callMethodFlagMap = nullptr);
NO_COPY_SEMANTIC(CallArg3TypeInfoAccessor);
NO_MOVE_SEMANTIC(CallArg3TypeInfoAccessor);
};
@ -372,7 +478,9 @@ class CallRangeTypeInfoAccessor final : public CallTypeInfoAccessor {
public:
CallRangeTypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate);
GateRef gate,
const JSPandaFile *jsPandaFile = nullptr,
const CallMethodFlagMap *callMethodFlagMap = nullptr);
NO_COPY_SEMANTIC(CallRangeTypeInfoAccessor);
NO_MOVE_SEMANTIC(CallRangeTypeInfoAccessor);
};
@ -381,8 +489,10 @@ class CallThisTypeInfoAccessor : public CallTypeInfoAccessor {
public:
CallThisTypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate)
: CallTypeInfoAccessor(thread, circuit, gate)
GateRef gate,
const JSPandaFile *jsPandaFile = nullptr,
const CallMethodFlagMap *callMethodFlagMap = nullptr)
: CallTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap)
{
thisObj_ = acc_.GetValueIn(gate, 0);
}
@ -403,7 +513,9 @@ class CallThis0TypeInfoAccessor final : public CallThisTypeInfoAccessor {
public:
CallThis0TypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate);
GateRef gate,
const JSPandaFile *jsPandaFile = nullptr,
const CallMethodFlagMap *callMethodFlagMap = nullptr);
NO_COPY_SEMANTIC(CallThis0TypeInfoAccessor);
NO_MOVE_SEMANTIC(CallThis0TypeInfoAccessor);
};
@ -412,7 +524,9 @@ class CallThis1TypeInfoAccessor final : public CallThisTypeInfoAccessor {
public:
CallThis1TypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate);
GateRef gate,
const JSPandaFile *jsPandaFile = nullptr,
const CallMethodFlagMap *callMethodFlagMap = nullptr);
NO_COPY_SEMANTIC(CallThis1TypeInfoAccessor);
NO_MOVE_SEMANTIC(CallThis1TypeInfoAccessor);
@ -434,7 +548,9 @@ class CallThis2TypeInfoAccessor final : public CallThisTypeInfoAccessor {
public:
CallThis2TypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate);
GateRef gate,
const JSPandaFile *jsPandaFile = nullptr,
const CallMethodFlagMap *callMethodFlagMap = nullptr);
NO_COPY_SEMANTIC(CallThis2TypeInfoAccessor);
NO_MOVE_SEMANTIC(CallThis2TypeInfoAccessor);
};
@ -443,7 +559,9 @@ class CallThis3TypeInfoAccessor final : public CallThisTypeInfoAccessor {
public:
CallThis3TypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate);
GateRef gate,
const JSPandaFile *jsPandaFile = nullptr,
const CallMethodFlagMap *callMethodFlagMap = nullptr);
NO_COPY_SEMANTIC(CallThis3TypeInfoAccessor);
NO_MOVE_SEMANTIC(CallThis3TypeInfoAccessor);
@ -462,7 +580,9 @@ class CallThisRangeTypeInfoAccessor final : public CallThisTypeInfoAccessor {
public:
CallThisRangeTypeInfoAccessor(const JSThread *thread,
Circuit *circuit,
GateRef gate);
GateRef gate,
const JSPandaFile *jsPandaFile = nullptr,
const CallMethodFlagMap *callMethodFlagMap = nullptr);
NO_COPY_SEMANTIC(CallThisRangeTypeInfoAccessor);
NO_MOVE_SEMANTIC(CallThisRangeTypeInfoAccessor);
};
@ -486,25 +606,21 @@ public:
bool IsEnableNormalInline() const
{
return IsFunctionTypeKind() || IsValidCallMethodId();
return IsValidCallMethodId();
}
bool IsEnableAccessorInline() const
{
if (plr_.IsAccessor() && IsClassInstanceTypeKind()) {
GlobalTSTypeRef gt = GetAccessorFuncGT();
if (!gt.IsDefault()) {
if (plr_.IsAccessor()) {
const PGORWOpType *pgoTypes = acc_.TryGetPGOType(gate_).GetPGORWOpType();
auto pgoType = pgoTypes->GetObjectInfo(0);
if (pgoType.GetAccessorMethod().GetProfileType().IsValidCallMethodId()) {
return true;
}
}
return false;
}
bool IsFunctionTypeKind() const
{
return tsManager_->IsFunctionTypeKind(acc_.GetGateType(receiver_));
}
bool IsClassInstanceTypeKind() const
{
return tsManager_->IsClassInstanceTypeKind(acc_.GetGateType(receiver_));
@ -512,13 +628,13 @@ public:
bool IsValidCallMethodId() const
{
return GetPGOType().IsValidCallMethodId();
return pgoType_.IsValidCallMethodId();
}
uint32_t GetFuncMethodOffsetFromPGO() const
{
if (GetPGOType().IsValidCallMethodId()) {
return GetPGOType().GetCallMethodId();
if (IsValidCallMethodId()) {
return pgoType_.GetCallMethodId();
}
return 0;
}
@ -567,16 +683,7 @@ public:
uint32_t GetType() const
{
uint32_t type = 0;
if (IsFunctionTypeKind()) {
type = GetReceiverGT().Value();
}
if (type == 0) {
if (IsNormalCall() && IsValidCallMethodId()) {
type = GetPGOType().GetValue();
}
}
return type;
return GetFuncMethodOffsetFromPGO();
}
PropertyLookupResult GetPlr() const
@ -852,12 +959,9 @@ public:
bool IsMono() const
{
return types_.size() == 1 ||
IsAllString();
return types_.size() == 1 || IsMonoBuiltins();
}
bool IsMonoIgnoreElemKind() const;
size_t GetTypeCount()
{
return types_.size();
@ -873,6 +977,25 @@ public:
return types_[0].IsBuiltinsArray();
}
bool IsBuiltinsTypeArray() const
{
return types_[0].IsBuiltinsTypeArray();
}
JSType GetBuiltinsJSType() const
{
if (types_[0].IsBuiltinsType()) {
return types_[0].GetBuiltinsType();
}
return JSType::INVALID;
}
ParamType GetParamType() const
{
ASSERT(IsMono());
return TypeInfoAccessor::PGOBuiltinTypeToParamType(types_[0]);
}
bool IsPolyBuiltinsArray() const
{
if (types_.size() == 0) {
@ -910,6 +1033,9 @@ public:
std::optional<BuiltinTypeId> GetBuiltinsTypeId() const
{
if (!IsMono()) {
return std::nullopt;
}
auto type = types_[0].GetBuiltinsType();
return ToBuiltinsTypeId(type);
}
@ -934,38 +1060,23 @@ public:
return static_cast<uint32_t>(acc_.GetConstantValue(GetKey()));
}
bool KeyIsNumberType() const
{
return acc_.GetGateType(key_).IsNumberType();
}
bool IsArrayTypeKind() const
{
return tsManager_->IsArrayTypeKind(GetReceiverGateType());
}
// Default get is elementsKind before possible transition
ElementsKind TryGetArrayElementsKind() const
{
[[maybe_unused]] bool condition = IsArrayTypeKind() || (IsMonoIgnoreElemKind() && IsBuiltinsArray());
[[maybe_unused]] bool condition = (IsMono() && IsBuiltinsArray());
ASSERT(condition);
return acc_.TryGetArrayElementsKind(gate_);
}
ElementsKind TryGetArrayElementsKindAfterTransition() const
{
[[maybe_unused]] bool condition = IsArrayTypeKind() || (IsMonoIgnoreElemKind() && IsBuiltinsArray());
[[maybe_unused]] bool condition = (IsMono() && IsBuiltinsArray());
ASSERT(condition);
return acc_.TryGetArrayElementsKindAfterTransition(gate_);
}
bool IsValidTypedArrayType() const
{
return tsManager_->IsValidTypedArrayType(GetReceiverGateType());
}
protected:
bool IsAllString() const;
bool IsMonoBuiltins() const;
void FetchBuiltinsTypes();
bool CheckDuplicatedBuiltinType(ProfileType newType) const;
@ -980,24 +1091,6 @@ public:
Chunk *chunk);
NO_COPY_SEMANTIC(LoadBulitinObjTypeInfoAccessor);
NO_MOVE_SEMANTIC(LoadBulitinObjTypeInfoAccessor);
bool IsStringType() const
{
return GetReceiverGateType().IsStringType();
}
bool IsArrayType() const
{
GateType temp = GetReceiverGateType();
return tsManager_->IsArrayTypeKind(temp) ||
tsManager_->IsBuiltinInstanceType(BuiltinTypeId::ARRAY, temp);
}
BuiltinTypeId GetTypedArrayBuiltinId() const
{
ASSERT(IsValidTypedArrayType());
return tsManager_->GetTypedArrayBuiltinId(GetReceiverGateType());
}
};
class StoreBulitinObjTypeInfoAccessor final : public AccBuiltinObjTypeInfoAccessor {

View File

@ -19,17 +19,18 @@
#include "ecmascript/compiler/circuit_builder.h"
#include "ecmascript/compiler/typed_bytecode_lowering.h"
#include "ecmascript/base/string_helper.h"
#include "ecmascript/builtin_entries.h"
#include "ecmascript/compiler/builtins_lowering.h"
#include "ecmascript/compiler/bytecodes.h"
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/type_info_accessors.h"
#include "ecmascript/dfx/vmstat/opt_code_profiler.h"
#include "ecmascript/enum_conversion.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/jspandafile/js_pandafile.h"
#include "ecmascript/jspandafile/js_pandafile_manager.h"
#include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/stackmap/llvm/llvm_stackmap_parser.h"
#include "ecmascript/base/string_helper.h"
namespace panda::ecmascript::kungfu {
bool TypedBytecodeLowering::RunTypedBytecodeLowering()
@ -355,13 +356,13 @@ int32_t TypedBytecodeLowering::GetEcmaOpCodeListIndex(EcmaOpcode ecmaOpCode)
}
template<TypedBinOp Op>
void TypedBytecodeLowering::LowerTypedBinOp(GateRef gate, bool convertNumberType)
void TypedBytecodeLowering::LowerTypedBinOp(GateRef gate)
{
BinOpTypeInfoAccessor tacc(thread_, circuit_, gate, convertNumberType);
BinOpTypeInfoAccessor tacc(thread_, circuit_, gate);
if (tacc.HasNumberType()) {
SpeculateNumbers<Op>(gate);
} else if (tacc.HasStringType()) {
SpeculateStrings<Op>(gate);
SpeculateNumbers<Op>(tacc);
} else if (tacc.IsStringType()) {
SpeculateStrings<Op>(tacc);
}
}
@ -369,7 +370,8 @@ template<TypedUnOp Op>
void TypedBytecodeLowering::LowerTypedUnOp(GateRef gate)
{
UnOpTypeInfoAccessor tacc(thread_, circuit_, gate);
if (tacc.ValueIsNumberType()) {
// NOTICE-PGO: wx add support for PrimitiveNumberType
if (tacc.HasNumberType()) {
SpeculateNumber<Op>(tacc);
}
}
@ -377,75 +379,45 @@ void TypedBytecodeLowering::LowerTypedUnOp(GateRef gate)
template<TypedBinOp Op>
void TypedBytecodeLowering::LowerTypedEqOrNotEq(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateType leftType = acc_.GetGateType(left);
GateType rightType = acc_.GetGateType(right);
GateType gateType = acc_.GetGateType(gate);
PGOTypeRef pgoType = acc_.TryGetPGOType(gate);
BinOpTypeInfoAccessor tacc(thread_, circuit_, gate);
if (tacc.LeftOrRightIsUndefinedOrNullOrHole() || tacc.HasNumberType()) {
if (tacc.LeftOrRightIsUndefinedOrNull()) {
AddProfiling(gate);
GateRef result = builder_.TypedBinaryOp<Op>(
left, right, leftType, rightType, gateType, pgoType);
GateRef left = tacc.GetLeftGate();
GateRef right = tacc.GetReightGate();
GateRef result = builder_.TypedBinaryOp<Op>(left, right, tacc.GetParamType());
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
} else if (tacc.HasStringType()) {
SpeculateStrings<Op>(gate);
} else {
LowerTypedBinOp<Op>(gate);
}
}
template<TypedBinOp Op>
void TypedBytecodeLowering::SpeculateStrings(GateRef gate)
void TypedBytecodeLowering::SpeculateStrings(const BinOpTypeInfoAccessor &tacc)
{
if (Op == TypedBinOp::TYPED_EQ || Op == TypedBinOp::TYPED_ADD) {
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateType leftType = acc_.GetGateType(left);
GateType rightType = acc_.GetGateType(right);
// Only support type is "number" or "string"
if ((!leftType.IsNumberType() && !leftType.IsStringType()) ||
(!rightType.IsNumberType() && !rightType.IsStringType())) {
return ;
}
if (leftType.IsNumberType()) {
left = builder_.NumberToString(left);
leftType = acc_.GetGateType(left);
acc_.ReplaceValueIn(gate, left, 0);
} else if (rightType.IsNumberType()) {
right = builder_.NumberToString(right);
rightType = acc_.GetGateType(right);
acc_.ReplaceValueIn(gate, right, 1);
}
AddProfiling(gate);
AddProfiling(tacc.GetGate());
GateRef left = tacc.GetLeftGate();
GateRef right = tacc.GetReightGate();
if (!TypeInfoAccessor::IsTrustedStringType(thread_, circuit_, chunk_, acc_, left)) {
builder_.EcmaStringCheck(left);
}
if (!TypeInfoAccessor::IsTrustedStringType(thread_, circuit_, chunk_, acc_, right)) {
builder_.EcmaStringCheck(right);
}
GateType gateType = acc_.GetGateType(gate);
PGOTypeRef pgoType = acc_.TryGetPGOType(gate);
pgoTypeLog_.CollectGateTypeLogInfo(gate, true);
GateRef result = builder_.TypedBinaryOp<Op>(left, right, leftType, rightType, gateType, pgoType);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
GateRef result = builder_.TypedBinaryOp<Op>(left, right, tacc.GetParamType());
acc_.ReplaceHirAndDeleteIfException(tacc.GetGate(), builder_.GetStateDepend(), result);
}
}
template<TypedBinOp Op>
void TypedBytecodeLowering::SpeculateNumbers(GateRef gate)
void TypedBytecodeLowering::SpeculateNumbers(const BinOpTypeInfoAccessor &tacc)
{
AddProfiling(gate);
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateType leftType = acc_.GetGateType(left);
GateType rightType = acc_.GetGateType(right);
GateType gateType = acc_.GetGateType(gate);
PGOTypeRef pgoType = acc_.TryGetPGOType(gate);
pgoTypeLog_.CollectGateTypeLogInfo(gate, true);
GateRef result = builder_.TypedBinaryOp<Op>(left, right, leftType, rightType, gateType, pgoType);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
AddProfiling(tacc.GetGate());
pgoTypeLog_.CollectGateTypeLogInfo(tacc.GetGate(), true);
GateRef left = tacc.GetLeftGate();
GateRef right = tacc.GetReightGate();
GateRef result = builder_.TypedBinaryOp<Op>(left, right, tacc.GetParamType());
acc_.ReplaceHirAndDeleteIfException(tacc.GetGate(), builder_.GetStateDepend(), result);
}
template<TypedUnOp Op>
@ -453,16 +425,14 @@ void TypedBytecodeLowering::SpeculateNumber(const UnOpTypeInfoAccessor &tacc)
{
AddProfiling(tacc.GetGate());
pgoTypeLog_.CollectGateTypeLogInfo(tacc.GetGate(), false);
GateRef value = tacc.GetValue();
GateType valueType = tacc.FetchNumberType();
GateRef result = builder_.TypedUnaryOp<Op>(value, valueType, valueType);
GateRef result = builder_.TypedUnaryOp<Op>(tacc.GetValue(), tacc.GetParamType());
acc_.ReplaceHirAndDeleteIfException(tacc.GetGate(), builder_.GetStateDepend(), result);
}
void TypedBytecodeLowering::LowerTypeToNumeric(GateRef gate)
{
UnOpTypeInfoAccessor tacc(thread_, circuit_, gate);
if (tacc.ValueIsNumberType()) {
if (tacc.HasNumberType()) {
AddProfiling(gate);
LowerPrimitiveTypeToNumber(tacc);
}
@ -470,18 +440,14 @@ void TypedBytecodeLowering::LowerTypeToNumeric(GateRef gate)
void TypedBytecodeLowering::LowerPrimitiveTypeToNumber(const UnOpTypeInfoAccessor &tacc)
{
GateRef value = tacc.GetValue();
GateType valueType = tacc.FetchNumberType();
acc_.SetGateType(value, valueType);
GateRef result = builder_.PrimitiveToNumber(value,
VariableType(MachineType::I64, valueType));
GateRef result = builder_.PrimitiveToNumber(tacc.GetValue(), tacc.GetParamType());
acc_.ReplaceHirAndDeleteIfException(tacc.GetGate(), builder_.GetStateDepend(), result);
}
void TypedBytecodeLowering::LowerConditionJump(GateRef gate, bool flag)
{
ConditionJumpTypeInfoAccessor tacc(thread_, circuit_, gate);
if (tacc.ValueIsBooleanType() && TypeInfoAccessor::IsTrustedType(acc_, tacc.GetValue())) {
if (TypeInfoAccessor::IsTrustedBooleanType(acc_, tacc.GetValue())) {
AddProfiling(gate);
SpeculateConditionJump(tacc, flag);
}
@ -490,13 +456,13 @@ void TypedBytecodeLowering::LowerConditionJump(GateRef gate, bool flag)
void TypedBytecodeLowering::SpeculateConditionJump(const ConditionJumpTypeInfoAccessor &tacc, bool flag)
{
GateRef value = tacc.GetValue();
GateType valueType = tacc.GetValueGateType();
ParamType paramType = ParamType::BooleanType();
uint32_t weight = tacc.GetBranchWeight();
GateRef jump = Circuit::NullGate();
if (flag) {
jump = builder_.TypedConditionJump<TypedJumpOp::TYPED_JNEZ>(value, valueType, weight);
jump = builder_.TypedConditionJump<TypedJumpOp::TYPED_JNEZ>(value, paramType, weight);
} else {
jump = builder_.TypedConditionJump<TypedJumpOp::TYPED_JEQZ>(value, valueType, weight);
jump = builder_.TypedConditionJump<TypedJumpOp::TYPED_JEQZ>(value, paramType, weight);
}
acc_.ReplaceGate(tacc.GetGate(), jump, jump, Circuit::NullGate());
}
@ -538,7 +504,7 @@ void TypedBytecodeLowering::LowerTypedLdObjByName(GateRef gate)
GateRef frameState = acc_.GetFrameState(gate);
if (tacc.IsMono()) {
GateRef receiver = tacc.GetReceiver();
builder_.ObjectTypeCheck(acc_.GetGateType(gate), true, receiver,
builder_.ObjectTypeCheck(true, receiver,
builder_.Int32(tacc.GetExpectedHClassIndex(0)), frameState);
if (tacc.IsReceiverEqHolder(0)) {
result = BuildNamedPropertyAccess(gate, receiver, receiver, tacc.GetAccessInfo(0).Plr());
@ -646,7 +612,7 @@ void TypedBytecodeLowering::LowerTypedStObjByName(GateRef gate)
if (tacc.IsMono()) {
GateRef receiver = tacc.GetReceiver();
builder_.ObjectTypeCheck(acc_.GetGateType(gate), true, receiver,
builder_.ObjectTypeCheck(true, receiver,
builder_.Int32(tacc.GetExpectedHClassIndex(0)), frameState);
if (tacc.IsReceiverNoEqNewHolder(0)) {
builder_.ProtoChangeMarkerCheck(tacc.GetReceiver(), frameState);
@ -810,15 +776,6 @@ GateRef TypedBytecodeLowering::BuildNamedPropertyAccess(
return result;
}
bool TypedBytecodeLowering::TryLowerTypedLdObjByNameForBuiltinsId(const LoadBulitinObjTypeInfoAccessor &tacc,
BuiltinTypeId type)
{
if (TryLowerTypedLdObjByNameForBuiltin(tacc, type)) {
return true;
}
return TryLowerTypedLdObjByNameForBuiltinMethod(tacc, type);
}
bool TypedBytecodeLowering::TryLowerTypedLdObjByNameForBuiltin(GateRef gate)
{
LoadBulitinObjTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_);
@ -827,7 +784,10 @@ bool TypedBytecodeLowering::TryLowerTypedLdObjByNameForBuiltin(GateRef gate)
if (tacc.IsBuiltinsType()) {
auto builtinsId = tacc.GetBuiltinsTypeId();
if (builtinsId.has_value()) {
return TryLowerTypedLdObjByNameForBuiltinsId(tacc, builtinsId.value());
if (TryLowerTypedLdObjByNameForBuiltin(tacc)) {
return true;
}
return TryLowerTypedLdObjByNameForBuiltinMethod(tacc, builtinsId.value());
}
} else if (tacc.IsGlobalsType()) {
auto globalsId = tacc.GetGlobalsId();
@ -835,50 +795,30 @@ bool TypedBytecodeLowering::TryLowerTypedLdObjByNameForBuiltin(GateRef gate)
return TryLowerTypedLdObjByNameForGlobalsId(tacc, globalsId.value());
}
}
}
// String: primitive string type only
/* e.g. let s1 = "ABC"; -> OK
* e.g. let s2 = new String("DEF"); -> Not included, whose type is JSType::JS_PRIMITIVE_REF */
if (tacc.IsStringType()) {
return TryLowerTypedLdObjByNameForBuiltin(tacc, BuiltinTypeId::STRING);
}
// Array: created via either array literal or new Array(...)
/* e.g. let a1 = [1, 2, 3]; -> OK
* e.g. let a2 = new Array(1, 2, 3); -> OK */
if (tacc.IsArrayType()) {
return TryLowerTypedLdObjByNameForBuiltin(tacc, BuiltinTypeId::ARRAY);
}
// Other valid types: let x = new X(...);
const auto hclassEntries = thread_->GetBuiltinHClassEntries();
for (BuiltinTypeId type: BuiltinHClassEntries::BUILTIN_TYPES) {
if (type == BuiltinTypeId::ARRAY || type == BuiltinTypeId::STRING || !hclassEntries.EntryIsValid(type)) {
continue; // Checked before or invalid
} else if (tacc.GetTypeCount() > 0) {
auto builtinsId = tacc.GetBuiltinsTypeId();
if (builtinsId.has_value()) {
return TryLowerTypedLdObjByNameForBuiltin(tacc);
}
if (!tacc.IsBuiltinInstanceType(type)) {
continue; // Type mismatch
}
return TryLowerTypedLdObjByNameForBuiltin(tacc, type);
}
return false; // No lowering performed
}
bool TypedBytecodeLowering::TryLowerTypedLdObjByNameForBuiltin(const LoadBulitinObjTypeInfoAccessor &tacc,
BuiltinTypeId type)
bool TypedBytecodeLowering::TryLowerTypedLdObjByNameForBuiltin(const LoadBulitinObjTypeInfoAccessor &tacc)
{
EcmaString *propString = EcmaString::Cast(tacc.GetKeyTaggedValue().GetTaggedObject());
// (1) get length
EcmaString *lengthString = EcmaString::Cast(thread_->GlobalConstants()->GetLengthString().GetTaggedObject());
if (propString == lengthString) {
if (type == BuiltinTypeId::ARRAY) {
if (tacc.IsBuiltinsArray()) {
LowerTypedLdArrayLength(tacc);
return true;
}
if (type == BuiltinTypeId::STRING) {
if (tacc.IsBuiltinsString()) {
LowerTypedLdStringLength(tacc);
return true;
}
if (IsTypedArrayType(type)) {
if (tacc.IsBuiltinsTypeArray()) {
LowerTypedLdTypedArrayLength(tacc);
return true;
}
@ -988,7 +928,7 @@ void TypedBytecodeLowering::LowerTypedLdTypedArrayLength(const LoadBulitinObjTyp
GateRef gate = tacc.GetGate();
GateRef array = tacc.GetReceiver();
AddProfiling(gate);
GateType arrayType = tacc.GetReceiverGateType();
ParamType arrayType = tacc.GetParamType();
OnHeapMode onHeap = acc_.TryGetOnHeapMode(gate);
if (!Uncheck()) {
builder_.TypedArrayCheck(array, arrayType, TypedArrayMetaDateAccessor::Mode::LOAD_LENGTH, onHeap);
@ -1069,11 +1009,14 @@ bool TypedBytecodeLowering::TryLowerTypedLdObjByIndexForBuiltin(GateRef gate)
{
LoadBulitinObjTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_);
GateRef result = Circuit::NullGate();
if (tacc.IsValidTypedArrayType()) {
AddProfiling(gate);
result = LoadTypedArrayByIndex(tacc);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
return true;
// Just supported mono.
if (tacc.IsMono()) {
if (tacc.IsBuiltinsTypeArray()) { // pgo need dump profile type
AddProfiling(gate);
result = LoadTypedArrayByIndex(tacc);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
return true;
}
}
return false;
}
@ -1088,13 +1031,12 @@ void TypedBytecodeLowering::LowerTypedLdObjByIndex(GateRef gate)
bool TypedBytecodeLowering::TryLowerTypedStObjByIndexForBuiltin(GateRef gate)
{
StoreBulitinObjTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_);
if (!tacc.IsBuiltinInstanceType(BuiltinTypeId::FLOAT32_ARRAY) ||
!tacc.ValueIsNumberType()) {
if (tacc.GetBuiltinsJSType() != JSType::JS_FLOAT32_ARRAY) {
return false;
}
AddProfiling(gate);
GateRef receiver = tacc.GetReceiver();
GateType receiverType = tacc.GetReceiverGateType();
ParamType receiverType = tacc.GetParamType();
if (!Uncheck()) {
OnHeapMode onHeap = tacc.TryGetHeapMode();
builder_.TypedArrayCheck(receiver, receiverType, TypedArrayMetaDateAccessor::Mode::ACCESS_ELEMENT, onHeap);
@ -1123,7 +1065,7 @@ bool TypedBytecodeLowering::TryLowerTypedLdObjByValueForBuiltin(GateRef gate)
LoadBulitinObjTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_);
GateRef result = Circuit::NullGate();
// Just supported mono.
if (tacc.IsMonoIgnoreElemKind()) {
if (tacc.IsMono()) {
if (tacc.IsBuiltinsString()) {
AddProfiling(gate);
result = LoadStringByIndex(tacc);
@ -1134,18 +1076,13 @@ bool TypedBytecodeLowering::TryLowerTypedLdObjByValueForBuiltin(GateRef gate)
result = LoadJSArrayByIndex(tacc);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
return true;
} else if (tacc.IsBuiltinsTypeArray()) {
AddProfiling(gate);
result = LoadTypedArrayByIndex(tacc);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
return true;
}
}
if (!tacc.KeyIsNumberType()) {
return false;
}
if (tacc.IsValidTypedArrayType()) {
AddProfiling(gate);
result = LoadTypedArrayByIndex(tacc);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
return true;
}
return false;
}
@ -1204,33 +1141,33 @@ GateRef TypedBytecodeLowering::LoadJSArrayByIndex(const LoadBulitinObjTypeInfoAc
GateRef TypedBytecodeLowering::LoadTypedArrayByIndex(const LoadBulitinObjTypeInfoAccessor &tacc)
{
GateRef receiver = tacc.GetReceiver();
GateType receiverType = tacc.GetReceiverGateType();
ParamType receiverType = tacc.GetParamType();
GateRef propKey = tacc.GetKey();
OnHeapMode onHeap = tacc.TryGetHeapMode();
BuiltinTypeId builtinTypeId = tacc.GetTypedArrayBuiltinId();
JSType builtinsType = tacc.GetBuiltinsJSType();
if (!Uncheck()) {
builder_.TypedArrayCheck(receiver, receiverType, TypedArrayMetaDateAccessor::Mode::ACCESS_ELEMENT, onHeap);
GateRef length = builder_.LoadTypedArrayLength(receiver, receiverType, onHeap);
propKey = builder_.IndexCheck(length, propKey);
}
switch (builtinTypeId) {
case BuiltinTypeId::INT8_ARRAY:
switch (builtinsType) {
case JSType::JS_INT8_ARRAY:
return builder_.LoadElement<TypedLoadOp::INT8ARRAY_LOAD_ELEMENT>(receiver, propKey, onHeap);
case BuiltinTypeId::UINT8_ARRAY:
case JSType::JS_UINT8_ARRAY:
return builder_.LoadElement<TypedLoadOp::UINT8ARRAY_LOAD_ELEMENT>(receiver, propKey, onHeap);
case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
case JSType::JS_UINT8_CLAMPED_ARRAY:
return builder_.LoadElement<TypedLoadOp::UINT8CLAMPEDARRAY_LOAD_ELEMENT>(receiver, propKey, onHeap);
case BuiltinTypeId::INT16_ARRAY:
case JSType::JS_INT16_ARRAY:
return builder_.LoadElement<TypedLoadOp::INT16ARRAY_LOAD_ELEMENT>(receiver, propKey, onHeap);
case BuiltinTypeId::UINT16_ARRAY:
case JSType::JS_UINT16_ARRAY:
return builder_.LoadElement<TypedLoadOp::UINT16ARRAY_LOAD_ELEMENT>(receiver, propKey, onHeap);
case BuiltinTypeId::INT32_ARRAY:
case JSType::JS_INT32_ARRAY:
return builder_.LoadElement<TypedLoadOp::INT32ARRAY_LOAD_ELEMENT>(receiver, propKey, onHeap);
case BuiltinTypeId::UINT32_ARRAY:
case JSType::JS_UINT32_ARRAY:
return builder_.LoadElement<TypedLoadOp::UINT32ARRAY_LOAD_ELEMENT>(receiver, propKey, onHeap);
case BuiltinTypeId::FLOAT32_ARRAY:
case JSType::JS_FLOAT32_ARRAY:
return builder_.LoadElement<TypedLoadOp::FLOAT32ARRAY_LOAD_ELEMENT>(receiver, propKey, onHeap);
case BuiltinTypeId::FLOAT64_ARRAY:
case JSType::JS_FLOAT64_ARRAY:
return builder_.LoadElement<TypedLoadOp::FLOAT64ARRAY_LOAD_ELEMENT>(receiver, propKey, onHeap);
default:
LOG_ECMA(FATAL) << "this branch is unreachable";
@ -1265,7 +1202,7 @@ void TypedBytecodeLowering::StoreJSArrayByIndex(const StoreBulitinObjTypeInfoAcc
void TypedBytecodeLowering::StoreTypedArrayByIndex(const StoreBulitinObjTypeInfoAccessor &tacc)
{
GateRef receiver = tacc.GetReceiver();
GateType receiverType = tacc.GetReceiverGateType();
ParamType receiverType = tacc.GetParamType();
GateRef propKey = tacc.GetKey();
GateRef value = tacc.GetValue();
OnHeapMode onHeap = tacc.TryGetHeapMode();
@ -1275,33 +1212,33 @@ void TypedBytecodeLowering::StoreTypedArrayByIndex(const StoreBulitinObjTypeInfo
propKey = builder_.IndexCheck(length, propKey);
}
auto builtinTypeId = tsManager_->GetTypedArrayBuiltinId(receiverType);
switch (builtinTypeId) {
case BuiltinTypeId::INT8_ARRAY:
JSType builtinsType = tacc.GetBuiltinsJSType();
switch (builtinsType) {
case JSType::JS_INT8_ARRAY:
builder_.StoreElement<TypedStoreOp::INT8ARRAY_STORE_ELEMENT>(receiver, propKey, value, onHeap);
break;
case BuiltinTypeId::UINT8_ARRAY:
case JSType::JS_UINT8_ARRAY:
builder_.StoreElement<TypedStoreOp::UINT8ARRAY_STORE_ELEMENT>(receiver, propKey, value, onHeap);
break;
case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
case JSType::JS_UINT8_CLAMPED_ARRAY:
builder_.StoreElement<TypedStoreOp::UINT8CLAMPEDARRAY_STORE_ELEMENT>(receiver, propKey, value, onHeap);
break;
case BuiltinTypeId::INT16_ARRAY:
case JSType::JS_INT16_ARRAY:
builder_.StoreElement<TypedStoreOp::INT16ARRAY_STORE_ELEMENT>(receiver, propKey, value, onHeap);
break;
case BuiltinTypeId::UINT16_ARRAY:
case JSType::JS_UINT16_ARRAY:
builder_.StoreElement<TypedStoreOp::UINT16ARRAY_STORE_ELEMENT>(receiver, propKey, value, onHeap);
break;
case BuiltinTypeId::INT32_ARRAY:
case JSType::JS_INT32_ARRAY:
builder_.StoreElement<TypedStoreOp::INT32ARRAY_STORE_ELEMENT>(receiver, propKey, value, onHeap);
break;
case BuiltinTypeId::UINT32_ARRAY:
case JSType::JS_UINT32_ARRAY:
builder_.StoreElement<TypedStoreOp::UINT32ARRAY_STORE_ELEMENT>(receiver, propKey, value, onHeap);
break;
case BuiltinTypeId::FLOAT32_ARRAY:
case JSType::JS_FLOAT32_ARRAY:
builder_.StoreElement<TypedStoreOp::FLOAT32ARRAY_STORE_ELEMENT>(receiver, propKey, value, onHeap);
break;
case BuiltinTypeId::FLOAT64_ARRAY:
case JSType::JS_FLOAT64_ARRAY:
builder_.StoreElement<TypedStoreOp::FLOAT64ARRAY_STORE_ELEMENT>(receiver, propKey, value, onHeap);
break;
default:
@ -1314,26 +1251,20 @@ bool TypedBytecodeLowering::TryLowerTypedStObjByValueForBuiltin(GateRef gate)
{
StoreBulitinObjTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_);
// Just supported mono.
if (tacc.IsMonoIgnoreElemKind()) {
if (tacc.IsMono()) {
if (tacc.IsBuiltinsArray()) {
AddProfiling(gate);
StoreJSArrayByIndex(tacc);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), Circuit::NullGate());
return true;
} else if (tacc.IsBuiltinsTypeArray()) {
AddProfiling(gate);
StoreTypedArrayByIndex(tacc);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), Circuit::NullGate());
return true;
}
}
if (!tacc.KeyIsNumberType()) {
return false;
}
if (tacc.IsValidTypedArrayType()) {
AddProfiling(gate);
StoreTypedArrayByIndex(tacc);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), Circuit::NullGate());
return true;
}
return false;
}
@ -1347,17 +1278,20 @@ void TypedBytecodeLowering::LowerTypedStObjByValue(GateRef gate)
void TypedBytecodeLowering::LowerTypedIsTrueOrFalse(GateRef gate, bool flag)
{
UnOpTypeInfoAccessor tacc(thread_, circuit_, gate);
if (!tacc.ValueIsPrimitiveNumberType() && !tacc.ValueIsBooleanType()) {
ParamType paramType;
if (TypeInfoAccessor::IsTrustedBooleanType(acc_, tacc.GetValue())) {
paramType = ParamType::BooleanType();
} else if (TypeInfoAccessor::IsTrustedNumberType(acc_, tacc.GetValue())) {
paramType = ParamType::NumberType();
} else {
return;
}
AddProfiling(gate);
GateRef value = tacc.GetValue();
GateType valueType = tacc.GetValueGateType();
GateRef result;
if (!flag) {
result = builder_.TypedUnaryOp<TypedUnOp::TYPED_ISFALSE>(value, valueType, GateType::TaggedValue());
result = builder_.TypedUnaryOp<TypedUnOp::TYPED_ISFALSE>(tacc.GetValue(), paramType);
} else {
result = builder_.TypedUnaryOp<TypedUnOp::TYPED_ISTRUE>(value, valueType, GateType::TaggedValue());
result = builder_.TypedUnaryOp<TypedUnOp::TYPED_ISTRUE>(tacc.GetValue(), paramType);
}
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
@ -1425,7 +1359,7 @@ bool TypedBytecodeLowering::TryLowerNewBuiltinConstructor(GateRef gate)
void TypedBytecodeLowering::LowerTypedSuperCall(GateRef gate)
{
SuperCallTypeInfoAccessor tacc(thread_, circuit_, gate);
if (!tacc.IsClassTypeKind() && !tacc.IsFunctionTypeKind()) {
if (!tacc.IsClassTypeKind() && !tacc.IsValidCallMethodId()) {
return;
}
AddProfiling(gate);
@ -1496,14 +1430,12 @@ void TypedBytecodeLowering::CheckFastCallThisCallTarget(const TypeAccessor &tacc
}
GateRef func = tacc.GetFunc();
GateRef gate = tacc.GetGate();
GateType funcType = tacc.GetFuncGateType();
if (tacc.IsNoGC()) {
uint32_t methodOffset = tacc.GetFuncMethodOffset();
builder_.JSNoGCCallThisTargetTypeCheck<TypedCallTargetCheckOp::JSCALLTHIS_FAST_NOGC>(funcType,
builder_.JSNoGCCallThisTargetTypeCheck<TypedCallTargetCheckOp::JSCALLTHIS_FAST_NOGC>(
func, builder_.IntPtr(methodOffset), gate);
} else {
builder_.JSCallThisTargetTypeCheck<TypedCallTargetCheckOp::JSCALLTHIS_FAST>(funcType,
func, gate);
builder_.JSCallThisTargetTypeCheck<TypedCallTargetCheckOp::JSCALLTHIS_FAST>(func, gate);
}
}
@ -1515,14 +1447,12 @@ void TypedBytecodeLowering::CheckCallThisCallTarget(const TypeAccessor &tacc)
}
GateRef func = tacc.GetFunc();
GateRef gate = tacc.GetGate();
GateType funcType = tacc.GetFuncGateType();
if (tacc.IsNoGC()) {
auto methodOffset = tacc.GetFuncMethodOffset();
builder_.JSNoGCCallThisTargetTypeCheck<TypedCallTargetCheckOp::JSCALLTHIS_NOGC>(funcType,
builder_.JSNoGCCallThisTargetTypeCheck<TypedCallTargetCheckOp::JSCALLTHIS_NOGC>(
func, builder_.IntPtr(methodOffset), gate);
} else {
builder_.JSCallThisTargetTypeCheck<TypedCallTargetCheckOp::JSCALLTHIS>(funcType,
func, gate);
builder_.JSCallThisTargetTypeCheck<TypedCallTargetCheckOp::JSCALLTHIS>(func, gate);
}
}
@ -1530,9 +1460,6 @@ template<class TypeAccessor>
void TypedBytecodeLowering::CheckThisCallTargetAndLowerCall(const TypeAccessor &tacc,
const std::vector<GateRef> &args, const std::vector<GateRef> &argsFastCall)
{
if (!tacc.FastCallFlagIsVaild()) {
return;
}
GateRef func = tacc.GetFunc();
GateRef gate = tacc.GetGate();
bool isNoGC = tacc.IsNoGC();
@ -1551,9 +1478,8 @@ void TypedBytecodeLowering::CheckCallTargetFromDefineFuncAndLowerCall(const Type
{
GateRef func = tacc.GetFunc();
GateRef gate = tacc.GetGate();
GateType funcType = tacc.GetFuncGateType();
if (!Uncheck()) {
builder_.JSCallTargetFromDefineFuncCheck(funcType, func, gate);
builder_.JSCallTargetFromDefineFuncCheck(func, gate);
}
if (tacc.CanFastCall()) {
LowerFastCall(gate, func, argsFastCall, isNoGC);
@ -1572,9 +1498,6 @@ void TypedBytecodeLowering::CheckCallTargetAndLowerCall(const TypeAccessor &tacc
} else {
bool isNoGC = tacc.IsNoGC();
auto op = acc_.GetOpCode(func);
if (!tacc.FastCallFlagIsVaild()) {
return;
}
if (op == OpCode::JS_BYTECODE && (acc_.GetByteCodeOpcode(func) == EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8 ||
acc_.GetByteCodeOpcode(func) == EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8)) {
CheckCallTargetFromDefineFuncAndLowerCall(tacc, args, argsFastCall, isNoGC);
@ -1586,17 +1509,16 @@ void TypedBytecodeLowering::CheckCallTargetAndLowerCall(const TypeAccessor &tacc
}
GateRef gate = tacc.GetGate();
GateType funcType = tacc.GetFuncGateType();
if (tacc.CanFastCall()) {
if (!Uncheck()) {
builder_.JSCallTargetTypeCheck<TypedCallTargetCheckOp::JSCALL_FAST>(funcType,
func, builder_.IntPtr(methodIndex), gate);
builder_.JSCallTargetTypeCheck<TypedCallTargetCheckOp::JSCALL_FAST>(func,
builder_.IntPtr(methodIndex), gate);
}
LowerFastCall(gate, func, argsFastCall, isNoGC);
} else {
if (!Uncheck()) {
builder_.JSCallTargetTypeCheck<TypedCallTargetCheckOp::JSCALL>(funcType,
func, builder_.IntPtr(methodIndex), gate);
builder_.JSCallTargetTypeCheck<TypedCallTargetCheckOp::JSCALL>(func,
builder_.IntPtr(methodIndex), gate);
}
LowerCall(gate, func, args, isNoGC);
}
@ -1656,13 +1578,30 @@ void TypedBytecodeLowering::LowerTypedCall(const TypeAccessor &tacc)
argsFastCall.emplace_back(builder_.Undefined());
args.emplace_back(builder_.Undefined());
}
AddProfiling(gate);
CheckCallTargetAndLowerCall(tacc, args, argsFastCall);
}
const JSPandaFile* TypedBytecodeLowering::GetCalleePandaFile(GateRef gate)
{
auto profileType = acc_.TryGetPGOType(gate).GetPGOSampleType();
bool haveProfileType = profileType->IsProfileType() && !profileType->IsProfileTypeNone();
if (haveProfileType) {
auto abcId = profileType->GetProfileType().GetAbcId();
CString fileDesc;
if (!decoder_->GetAbcNameById(abcId, fileDesc)) {
UNREACHABLE();
}
return JSPandaFileManager::GetInstance()->FindJSPandaFileByNormalizedName(fileDesc).get();
}
// nullptr if no pgo info
return nullptr;
}
void TypedBytecodeLowering::LowerTypedCallArg0(GateRef gate)
{
CallArg0TypeInfoAccessor tacc(thread_, circuit_, gate);
if (!tacc.IsFunctionTypeKind()) {
CallArg0TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_);
if (!tacc.IsValidCallMethodId()) {
return;
}
LowerTypedCall<EcmaOpcode::CALLARG0_IMM8>(tacc);
@ -1670,15 +1609,15 @@ void TypedBytecodeLowering::LowerTypedCallArg0(GateRef gate)
void TypedBytecodeLowering::LowerTypedCallArg1(GateRef gate)
{
CallArg1TypeInfoAccessor tacc(thread_, circuit_, gate);
CallArg1TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_);
GateRef func = tacc.GetFunc();
GateRef a0Value = tacc.GetValue();
BuiltinsStubCSigns::ID id = tacc.TryGetPGOBuiltinId();
BuiltinsStubCSigns::ID id = tacc.TryGetPGOBuiltinMethodId();
if (IS_TYPED_BUILTINS_NUMBER_ID(id)) {
AddProfiling(gate);
SpeculateCallBuiltin(gate, func, { a0Value }, id, true);
} else {
if (!tacc.IsFunctionTypeKind()) {
if (!tacc.IsValidCallMethodId()) {
return;
}
LowerTypedCall<EcmaOpcode::CALLARG1_IMM8_V8>(tacc);
@ -1687,8 +1626,8 @@ void TypedBytecodeLowering::LowerTypedCallArg1(GateRef gate)
void TypedBytecodeLowering::LowerTypedCallArg2(GateRef gate)
{
CallArg2TypeInfoAccessor tacc(thread_, circuit_, gate);
if (!tacc.IsFunctionTypeKind()) {
CallArg2TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_);
if (!tacc.IsValidCallMethodId()) {
return;
}
LowerTypedCall<EcmaOpcode::CALLARGS2_IMM8_V8_V8>(tacc);
@ -1696,8 +1635,8 @@ void TypedBytecodeLowering::LowerTypedCallArg2(GateRef gate)
void TypedBytecodeLowering::LowerTypedCallArg3(GateRef gate)
{
CallArg3TypeInfoAccessor tacc(thread_, circuit_, gate);
if (!tacc.IsFunctionTypeKind()) {
CallArg3TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_);
if (!tacc.IsValidCallMethodId()) {
return;
}
LowerTypedCall<EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8>(tacc);
@ -1705,8 +1644,8 @@ void TypedBytecodeLowering::LowerTypedCallArg3(GateRef gate)
void TypedBytecodeLowering::LowerTypedCallrange(GateRef gate)
{
CallRangeTypeInfoAccessor tacc(thread_, circuit_, gate);
if (!tacc.IsFunctionTypeKind()) {
CallRangeTypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_);
if (!tacc.IsValidCallMethodId()) {
return;
}
LowerTypedCall<EcmaOpcode::CALLRANGE_IMM8_IMM8_V8>(tacc);
@ -1715,7 +1654,7 @@ void TypedBytecodeLowering::LowerTypedCallrange(GateRef gate)
bool TypedBytecodeLowering::IsLoadVtable(GateRef func)
{
auto op = acc_.GetOpCode(func);
if (op != OpCode::LOAD_PROPERTY || !acc_.IsVtable(func)) {
if (op != OpCode::LOAD_PROPERTY) {
return false;
}
return true;
@ -1772,19 +1711,14 @@ void TypedBytecodeLowering::LowerTypedThisCall(const TypeAccessor &tacc)
argsFastCall.emplace_back(builder_.Undefined());
args.emplace_back(builder_.Undefined());
}
AddProfiling(gate);
CheckThisCallTargetAndLowerCall(tacc, args, argsFastCall);
}
void TypedBytecodeLowering::LowerTypedCallthis0(GateRef gate)
{
CallThis0TypeInfoAccessor tacc(thread_, circuit_, gate);
BuiltinsStubCSigns::ID id = tacc.TryGetBuiltinId(BuiltinTypeId::ARRAY);
if (id == BuiltinsStubCSigns::ID::SORT) {
AddProfiling(gate);
SpeculateCallBuiltin(gate, tacc.GetFunc(), { tacc.GetThisObj() }, id, true);
return;
}
BuiltinsStubCSigns::ID pgoFuncId = tacc.TryGetPGOBuiltinId();
CallThis0TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_);
BuiltinsStubCSigns::ID pgoFuncId = tacc.TryGetPGOBuiltinMethodId();
if (IS_TYPED_BUILTINS_ID_CALL_THIS0(pgoFuncId)) {
AddProfiling(gate);
SpeculateCallBuiltin(gate, tacc.GetFunc(), { tacc.GetThisObj() }, pgoFuncId, true, true);
@ -1798,19 +1732,12 @@ void TypedBytecodeLowering::LowerTypedCallthis0(GateRef gate)
void TypedBytecodeLowering::LowerTypedCallthis1(GateRef gate)
{
CallThis1TypeInfoAccessor tacc(thread_, circuit_, gate);
BuiltinsStubCSigns::ID id = tacc.TryGetBuiltinId(BuiltinTypeId::MATH);
if (id == BuiltinsStubCSigns::ID::NONE) {
id = tacc.TryGetBuiltinId(BuiltinTypeId::JSON);
if (id != BuiltinsStubCSigns::ID::NONE) {
AddProfiling(gate);
SpeculateCallBuiltin(gate, tacc.GetFunc(), { tacc.GetArg0() }, id, true);
return;
}
} else if (tacc.Arg0IsNumberType()) {
AddProfiling(gate);
SpeculateCallBuiltin(gate, tacc.GetFunc(), { tacc.GetArg0() }, id, false);
return;
CallThis1TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_);
BuiltinsStubCSigns::ID pgoFuncId = tacc.TryGetPGOBuiltinMethodId();
if (IS_TYPED_BUILTINS_ID_CALL_THIS1(pgoFuncId)) {
AddProfiling(gate);
SpeculateCallBuiltin(gate, tacc.GetFunc(), { tacc.GetArg0() }, pgoFuncId, true);
return;
}
if (!tacc.CanOptimizeAsFastCall()) {
return;
@ -1820,7 +1747,7 @@ void TypedBytecodeLowering::LowerTypedCallthis1(GateRef gate)
void TypedBytecodeLowering::LowerTypedCallthis2(GateRef gate)
{
CallThis2TypeInfoAccessor tacc(thread_, circuit_, gate);
CallThis2TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_);
if (!tacc.CanOptimizeAsFastCall()) {
return;
}
@ -1829,11 +1756,11 @@ void TypedBytecodeLowering::LowerTypedCallthis2(GateRef gate)
void TypedBytecodeLowering::LowerTypedCallthis3(GateRef gate)
{
CallThis3TypeInfoAccessor tacc(thread_, circuit_, gate);
BuiltinsStubCSigns::ID id = tacc.TryGetBuiltinId(BuiltinTypeId::STRING);
if (IS_TYPED_BUILTINS_ID_CALL_THIS3(id)) {
CallThis3TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_);
BuiltinsStubCSigns::ID pgoFuncId = tacc.TryGetPGOBuiltinMethodId();
if (IS_TYPED_BUILTINS_ID_CALL_THIS3(pgoFuncId)) {
AddProfiling(gate);
SpeculateCallBuiltin(gate, tacc.GetFunc(), tacc.GetArgs(), id, true);
SpeculateCallBuiltin(gate, tacc.GetFunc(), { tacc.GetArgs() }, pgoFuncId, true);
return;
}
if (!tacc.CanOptimizeAsFastCall()) {
@ -1844,7 +1771,7 @@ void TypedBytecodeLowering::LowerTypedCallthis3(GateRef gate)
void TypedBytecodeLowering::LowerTypedCallthisrange(GateRef gate)
{
CallThisRangeTypeInfoAccessor tacc(thread_, circuit_, gate);
CallThisRangeTypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_);
if (!tacc.CanOptimizeAsFastCall()) {
return;
}
@ -1891,20 +1818,21 @@ void TypedBytecodeLowering::AddProfiling(GateRef gate)
current = gate;
}
GateRef func = builder_.Undefined();
if (acc_.HasFrameState(gate)) {
// func, pcoffset, opcode, mode
GateRef func = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
GateRef bcIndex = builder_.Int32ToTaggedInt(builder_.Int32(acc_.TryGetBcIndex(gate)));
EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
auto ecmaOpcodeGate = builder_.Int32(static_cast<uint32_t>(ecmaOpcode));
GateRef constOpcode = builder_.Int32ToTaggedInt(ecmaOpcodeGate);
GateRef mode =
builder_.Int32ToTaggedInt(builder_.Int32(static_cast<int32_t>(OptCodeProfiler::Mode::TYPED_PATH)));
GateRef profiling = builder_.CallRuntime(glue_, RTSTUB_ID(ProfileOptimizedCode), acc_.GetDep(current),
{ func, bcIndex, constOpcode, mode }, gate);
acc_.SetDep(current, profiling);
builder_.SetDepend(acc_.GetDep(gate)); // set gate depend: profiling or STATE_SPLIT
func = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
}
GateRef bcIndex = builder_.Int32ToTaggedInt(builder_.Int32(acc_.TryGetBcIndex(gate)));
EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
auto ecmaOpcodeGate = builder_.Int32(static_cast<uint32_t>(ecmaOpcode));
GateRef constOpcode = builder_.Int32ToTaggedInt(ecmaOpcodeGate);
GateRef mode =
builder_.Int32ToTaggedInt(builder_.Int32(static_cast<int32_t>(OptCodeProfiler::Mode::TYPED_PATH)));
GateRef profiling = builder_.CallRuntime(glue_, RTSTUB_ID(ProfileOptimizedCode), acc_.GetDep(current),
{ func, bcIndex, constOpcode, mode }, gate);
acc_.SetDep(current, profiling);
builder_.SetDepend(acc_.GetDep(gate)); // set gate depend: profiling or STATE_SPLIT
}
}
@ -1934,23 +1862,22 @@ void TypedBytecodeLowering::AddHitBytecodeCount()
void TypedBytecodeLowering::LowerTypedTypeOf(GateRef gate)
{
// 1: number of value inputs
TypeOfTypeInfoAccessor tacc(thread_, circuit_, gate);
if (tacc.IsIllegalType()) {
return;
}
AddProfiling(gate);
if (!Uncheck()) {
builder_.TypeOfCheck(tacc.GetValue(), tacc.GetValueGateType());
builder_.TypeOfCheck(tacc.GetValue(), tacc.GetParamType());
}
GateRef result = builder_.TypedTypeOf(tacc.GetValueGateType());
GateRef result = builder_.TypedTypeOf(tacc.GetParamType());
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
}
void TypedBytecodeLowering::LowerGetIterator(GateRef gate)
{
GetIteratorTypeInfoAccessor tacc(thread_, circuit_, gate);
BuiltinsStubCSigns::ID id = tacc.TryGetPGOBuiltinId();
GetIteratorTypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_);
BuiltinsStubCSigns::ID id = tacc.TryGetPGOBuiltinMethodId();
if (id == BuiltinsStubCSigns::ID::NONE) {
return;
}
@ -1999,7 +1926,7 @@ void TypedBytecodeLowering::LowerInstanceOf(GateRef gate)
GateRef obj = tacc.GetReceiver();
GateRef target = tacc.GetTarget();
builder_.ObjectTypeCheck(acc_.GetGateType(gate), true, target, expectedHCIndexes[0]);
builder_.ObjectTypeCheck(true, target, expectedHCIndexes[0]);
builder_.ProtoChangeMarkerCheck(target);
result = builder_.OrdinaryHasInstance(obj, target);

View File

@ -18,6 +18,7 @@
#include "ecmascript/builtin_entries.h"
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/compiler/aot_compiler_preprocessor.h"
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
#include "ecmascript/compiler/bytecode_circuit_builder.h"
#include "ecmascript/compiler/circuit_builder-inl.h"
@ -38,6 +39,8 @@ public:
const std::string& name,
bool enableLoweringBuiltin,
const CString& recordName,
const CallMethodFlagMap* callMethodFlagMap,
PGOProfilerDecoder *decoder,
const std::string optBCRange)
: circuit_(circuit),
acc_(circuit),
@ -58,6 +61,8 @@ public:
thread_(ctx->GetEcmaVM()->GetJSThread()),
enableLoweringBuiltin_(enableLoweringBuiltin),
recordName_(recordName),
callMethodFlagMap_(callMethodFlagMap),
decoder_(decoder),
optBCRange_(optBCRange)
{
}
@ -99,7 +104,7 @@ private:
void Lower(GateRef gate);
template<TypedBinOp Op>
void LowerTypedBinOp(GateRef gate, bool convertNumberType = true);
void LowerTypedBinOp(GateRef gate);
template<TypedUnOp Op>
void LowerTypedUnOp(GateRef gate);
template<TypedBinOp Op>
@ -119,7 +124,7 @@ private:
using AccessMode = PGOObjectAccessHelper::AccessMode;
bool TryLowerTypedLdObjByNameForBuiltin(GateRef gate);
bool TryLowerTypedLdObjByNameForBuiltinsId(const LoadBulitinObjTypeInfoAccessor &tacc, BuiltinTypeId type);
bool TryLowerTypedLdObjByNameForBuiltin(const LoadBulitinObjTypeInfoAccessor &tacc, BuiltinTypeId type);
bool TryLowerTypedLdObjByNameForBuiltin(const LoadBulitinObjTypeInfoAccessor &tacc);
bool TryLowerTypedLdObjByNameForGlobalsId(const LoadBulitinObjTypeInfoAccessor &tacc, GlobalIndex globalsId);
void LowerTypedLdArrayLength(const LoadBulitinObjTypeInfoAccessor &tacc);
void LowerTypedLdTypedArrayLength(const LoadBulitinObjTypeInfoAccessor &tacc);
@ -197,9 +202,9 @@ private:
void AddHitBytecodeCount();
template<TypedBinOp Op>
void SpeculateStrings(GateRef gate);
void SpeculateStrings(const BinOpTypeInfoAccessor& tacc);
template<TypedBinOp Op>
void SpeculateNumbers(GateRef gate);
void SpeculateNumbers(const BinOpTypeInfoAccessor& tacc);
template<TypedUnOp Op>
void SpeculateNumber(const UnOpTypeInfoAccessor& tacc);
void SpeculateConditionJump(const ConditionJumpTypeInfoAccessor &tacc, bool flag);
@ -211,6 +216,9 @@ private:
bool CheckIsInOptBCIgnoreRange(int32_t index, EcmaOpcode ecmaOpcode);
int32_t GetEcmaOpCodeListIndex(EcmaOpcode ecmaOpCode);
void ParseOptBytecodeRange();
const JSPandaFile* GetCalleePandaFile(GateRef gate);
void AddProfiling(GateRef gate);
bool Uncheck() const
@ -243,6 +251,8 @@ private:
const JSThread *thread_ {nullptr};
bool enableLoweringBuiltin_ {false};
const CString &recordName_;
const CallMethodFlagMap *callMethodFlagMap_;
PGOProfilerDecoder *decoder_ {nullptr};
std::string optBCRange_;
std::vector<std::vector<int32_t>> optBCRangeList_;
};

View File

@ -313,52 +313,52 @@ void TypedHCRLowering::LowerStableArrayCheck(GateRef gate)
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void TypedHCRLowering::SetDeoptTypeInfo(BuiltinTypeId id, DeoptType &type, size_t &typedArrayRootHclassIndex,
void TypedHCRLowering::SetDeoptTypeInfo(JSType jstype, DeoptType &type, size_t &typedArrayRootHclassIndex,
size_t &typedArrayRootHclassOnHeapIndex)
{
type = DeoptType::NOTARRAY1;
switch (id) {
case BuiltinTypeId::INT8_ARRAY:
switch (jstype) {
case JSType::JS_INT8_ARRAY:
typedArrayRootHclassIndex = GlobalEnv::INT8_ARRAY_ROOT_HCLASS_INDEX;
typedArrayRootHclassOnHeapIndex = GlobalEnv::INT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
break;
case BuiltinTypeId::UINT8_ARRAY:
case JSType::JS_UINT8_ARRAY:
typedArrayRootHclassIndex = GlobalEnv::UINT8_ARRAY_ROOT_HCLASS_INDEX;
typedArrayRootHclassOnHeapIndex = GlobalEnv::UINT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
break;
case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
case JSType::JS_UINT8_CLAMPED_ARRAY:
typedArrayRootHclassIndex = GlobalEnv::UINT8_CLAMPED_ARRAY_ROOT_HCLASS_INDEX;
typedArrayRootHclassOnHeapIndex = GlobalEnv::UINT8_CLAMPED_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
break;
case BuiltinTypeId::INT16_ARRAY:
case JSType::JS_INT16_ARRAY:
typedArrayRootHclassIndex = GlobalEnv::INT16_ARRAY_ROOT_HCLASS_INDEX;
typedArrayRootHclassOnHeapIndex = GlobalEnv::INT16_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
break;
case BuiltinTypeId::UINT16_ARRAY:
case JSType::JS_UINT16_ARRAY:
typedArrayRootHclassIndex = GlobalEnv::UINT16_ARRAY_ROOT_HCLASS_INDEX;
typedArrayRootHclassOnHeapIndex = GlobalEnv::UINT16_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
break;
case BuiltinTypeId::INT32_ARRAY:
case JSType::JS_INT32_ARRAY:
typedArrayRootHclassIndex = GlobalEnv::INT32_ARRAY_ROOT_HCLASS_INDEX;
typedArrayRootHclassOnHeapIndex = GlobalEnv::INT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
break;
case BuiltinTypeId::UINT32_ARRAY:
case JSType::JS_UINT32_ARRAY:
typedArrayRootHclassIndex = GlobalEnv::UINT32_ARRAY_ROOT_HCLASS_INDEX;
typedArrayRootHclassOnHeapIndex = GlobalEnv::UINT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
break;
case BuiltinTypeId::FLOAT32_ARRAY:
case JSType::JS_FLOAT32_ARRAY:
typedArrayRootHclassIndex = GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_INDEX;
typedArrayRootHclassOnHeapIndex = GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
break;
case BuiltinTypeId::FLOAT64_ARRAY:
case JSType::JS_FLOAT64_ARRAY:
typedArrayRootHclassIndex = GlobalEnv::FLOAT64_ARRAY_ROOT_HCLASS_INDEX;
typedArrayRootHclassOnHeapIndex = GlobalEnv::FLOAT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
break;
case BuiltinTypeId::BIGINT64_ARRAY:
case JSType::JS_BIGINT64_ARRAY:
typedArrayRootHclassIndex = GlobalEnv::BIGINT64_ARRAY_ROOT_HCLASS_INDEX;
typedArrayRootHclassOnHeapIndex = GlobalEnv::BIGINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
break;
case BuiltinTypeId::BIGUINT64_ARRAY:
case JSType::JS_BIGUINT64_ARRAY:
typedArrayRootHclassIndex = GlobalEnv::BIGUINT64_ARRAY_ROOT_HCLASS_INDEX;
typedArrayRootHclassOnHeapIndex = GlobalEnv::BIGUINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
break;
@ -375,9 +375,10 @@ void TypedHCRLowering::LowerTypedArrayCheck(GateRef gate)
size_t typedArrayRootHclassIndex = GlobalEnv::INT8_ARRAY_ROOT_HCLASS_INDEX;
size_t typedArrayRootHclassOnHeapIndex = GlobalEnv::INT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
auto deoptType = DeoptType::NOTCHECK;
auto builtinTypeId = tsManager_->GetTypedArrayBuiltinId(accessor.GetType());
SetDeoptTypeInfo(builtinTypeId, deoptType, typedArrayRootHclassIndex, typedArrayRootHclassOnHeapIndex);
ParamType paramType = accessor.GetParamType();
ASSERT(paramType.IsBuiltinType());
auto builtinType = paramType.GetBuiltinType();
SetDeoptTypeInfo(builtinType, deoptType, typedArrayRootHclassIndex, typedArrayRootHclassOnHeapIndex);
GateRef frameState = GetFrameState(gate);
GateRef glueGlobalEnv = builder_.GetGlobalEnv();
@ -626,18 +627,21 @@ GateRef TypedHCRLowering::LowerCallRuntime(GateRef glue, GateRef hirGate, int in
void TypedHCRLowering::LowerTypeConvert(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
auto leftType = acc_.GetLeftType(gate);
auto rightType = acc_.GetRightType(gate);
TypeConvertAccessor accessor(acc_.TryGetValue(gate));
ParamType leftType = accessor.GetLeftType();
GateType rightType = accessor.GetRightType();
if (rightType.IsNumberType()) {
GateRef value = acc_.GetValueIn(gate, 0);
if (leftType.IsDigitablePrimitiveType()) {
// NOTICE-PGO: wx support undefined/null/boolean type:
if (leftType.HasNumberType()) {
LowerPrimitiveToNumber(gate, value, leftType);
}
return;
}
}
void TypedHCRLowering::LowerPrimitiveToNumber(GateRef dst, GateRef src, GateType srcType)
void TypedHCRLowering::LowerPrimitiveToNumber(GateRef dst, GateRef src, ParamType srcType)
{
DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
if (srcType.IsBooleanType()) {
@ -658,7 +662,8 @@ void TypedHCRLowering::LowerPrimitiveToNumber(GateRef dst, GateRef src, GateType
builder_.Bind(&exit);
} else if (srcType.IsUndefinedType()) {
result = DoubleToTaggedDoublePtr(builder_.Double(base::NAN_VALUE));
} else if (srcType.IsBigIntType() || srcType.IsNumberType()) {
} else if (srcType.IsBigIntType() || srcType.HasNumberType()) {
ASSERT(!srcType.IsIntOverflowType());
result = src;
} else if (srcType.IsNullType()) {
result = IntToTaggedIntPtr(builder_.Int32(0));
@ -1343,142 +1348,100 @@ void TypedHCRLowering::LowerTypedCallBuitin(GateRef gate)
void TypedHCRLowering::LowerJSCallTargetFromDefineFuncCheck(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
auto type = acc_.GetParamGateType(gate);
if (tsManager_->IsFunctionTypeKind(type)) {
GateRef frameState = GetFrameState(gate);
auto func = acc_.GetValueIn(gate, 0);
GateRef check = builder_.JudgeAotAndFastCall(func, CircuitBuilder::JudgeMethodType::HAS_AOT);
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT1);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
} else {
LOG_COMPILER(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
GateRef frameState = GetFrameState(gate);
auto func = acc_.GetValueIn(gate, 0);
GateRef check = builder_.JudgeAotAndFastCall(func, CircuitBuilder::JudgeMethodType::HAS_AOT);
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT1);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void TypedHCRLowering::LowerJSCallTargetTypeCheck(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
auto type = acc_.GetParamGateType(gate);
if (tsManager_->IsFunctionTypeKind(type)) {
ArgumentAccessor argAcc(circuit_);
GateRef frameState = GetFrameState(gate);
GateRef constpool = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::CONST_POOL);
auto func = acc_.GetValueIn(gate, 0);
auto methodIndex = acc_.GetValueIn(gate, 1);
GateRef isObj = builder_.TaggedIsHeapObject(func);
GateRef funcMethodTarget = builder_.GetMethodFromFunction(func);
GateRef isOptimized = builder_.JudgeAotAndFastCallWithMethod(funcMethodTarget,
CircuitBuilder::JudgeMethodType::HAS_AOT);
GateRef checkFunc = builder_.BoolAnd(isObj, isOptimized);
GateRef methodTarget = builder_.GetValueFromTaggedArray(constpool, methodIndex);
GateRef check = builder_.BoolAnd(checkFunc, builder_.Equal(funcMethodTarget, methodTarget));
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT2);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
} else {
LOG_COMPILER(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
ArgumentAccessor argAcc(circuit_);
GateRef frameState = GetFrameState(gate);
GateRef constpool = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::CONST_POOL);
auto func = acc_.GetValueIn(gate, 0);
auto methodIndex = acc_.GetValueIn(gate, 1);
GateRef isObj = builder_.TaggedIsHeapObject(func);
GateRef funcMethodTarget = builder_.GetMethodFromFunction(func);
GateRef isOptimized = builder_.JudgeAotAndFastCallWithMethod(funcMethodTarget,
CircuitBuilder::JudgeMethodType::HAS_AOT);
GateRef checkFunc = builder_.BoolAnd(isObj, isOptimized);
GateRef methodTarget = builder_.GetValueFromTaggedArray(constpool, methodIndex);
GateRef check = builder_.BoolAnd(checkFunc, builder_.Equal(funcMethodTarget, methodTarget));
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT2);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void TypedHCRLowering::LowerJSFastCallTargetTypeCheck(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
auto type = acc_.GetParamGateType(gate);
if (tsManager_->IsFunctionTypeKind(type)) {
ArgumentAccessor argAcc(circuit_);
GateRef frameState = GetFrameState(gate);
GateRef constpool = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::CONST_POOL);
auto func = acc_.GetValueIn(gate, 0);
auto methodIndex = acc_.GetValueIn(gate, 1);
GateRef isObj = builder_.TaggedIsHeapObject(func);
GateRef canFastCall = builder_.CanFastCall(func);
GateRef funcMethodTarget = builder_.GetMethodFromFunction(func);
GateRef checkFunc = builder_.BoolAnd(isObj, canFastCall);
GateRef methodTarget = builder_.GetValueFromTaggedArray(constpool, methodIndex);
GateRef check = builder_.BoolAnd(checkFunc, builder_.Equal(funcMethodTarget, methodTarget));
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT1);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
} else {
LOG_COMPILER(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
ArgumentAccessor argAcc(circuit_);
GateRef frameState = GetFrameState(gate);
GateRef constpool = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::CONST_POOL);
auto func = acc_.GetValueIn(gate, 0);
auto methodIndex = acc_.GetValueIn(gate, 1);
GateRef isObj = builder_.TaggedIsHeapObject(func);
GateRef canFastCall = builder_.CanFastCall(func);
GateRef funcMethodTarget = builder_.GetMethodFromFunction(func);
GateRef checkFunc = builder_.BoolAnd(isObj, canFastCall);
GateRef methodTarget = builder_.GetValueFromTaggedArray(constpool, methodIndex);
GateRef check = builder_.BoolAnd(checkFunc, builder_.Equal(funcMethodTarget, methodTarget));
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT1);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void TypedHCRLowering::LowerJSCallThisTargetTypeCheck(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
auto type = acc_.GetParamGateType(gate);
if (tsManager_->IsFunctionTypeKind(type)) {
GateRef frameState = GetFrameState(gate);
auto func = acc_.GetValueIn(gate, 0);
GateRef isObj = builder_.TaggedIsHeapObject(func);
GateRef isOptimized = builder_.JudgeAotAndFastCall(func, CircuitBuilder::JudgeMethodType::HAS_AOT_NOTFASTCALL);
GateRef check = builder_.BoolAnd(isObj, isOptimized);
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT3);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
} else {
LOG_COMPILER(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
GateRef frameState = GetFrameState(gate);
auto func = acc_.GetValueIn(gate, 0);
GateRef isObj = builder_.TaggedIsHeapObject(func);
GateRef isOptimized = builder_.JudgeAotAndFastCall(func, CircuitBuilder::JudgeMethodType::HAS_AOT_NOTFASTCALL);
GateRef check = builder_.BoolAnd(isObj, isOptimized);
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT3);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void TypedHCRLowering::LowerJSNoGCCallThisTargetTypeCheck(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
auto type = acc_.GetParamGateType(gate);
if (tsManager_->IsFunctionTypeKind(type)) {
GateRef frameState = GetFrameState(gate);
auto func = acc_.GetValueIn(gate, 0);
GateRef isObj = builder_.TaggedIsHeapObject(func);
GateRef isOptimized = builder_.JudgeAotAndFastCall(func, CircuitBuilder::JudgeMethodType::HAS_AOT_NOTFASTCALL);
GateRef methodId = builder_.GetMethodId(func);
GateRef checkOptimized = builder_.BoolAnd(isObj, isOptimized);
GateRef check = builder_.BoolAnd(checkOptimized, builder_.Equal(methodId, acc_.GetValueIn(gate, 1)));
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT4);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
} else {
LOG_COMPILER(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
GateRef frameState = GetFrameState(gate);
auto func = acc_.GetValueIn(gate, 0);
GateRef isObj = builder_.TaggedIsHeapObject(func);
GateRef isOptimized = builder_.JudgeAotAndFastCall(func, CircuitBuilder::JudgeMethodType::HAS_AOT_NOTFASTCALL);
GateRef methodId = builder_.GetMethodId(func);
GateRef checkOptimized = builder_.BoolAnd(isObj, isOptimized);
GateRef check = builder_.BoolAnd(checkOptimized, builder_.Equal(methodId, acc_.GetValueIn(gate, 1)));
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT4);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void TypedHCRLowering::LowerJSFastCallThisTargetTypeCheck(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
auto type = acc_.GetParamGateType(gate);
if (tsManager_->IsFunctionTypeKind(type)) {
GateRef frameState = GetFrameState(gate);
auto func = acc_.GetValueIn(gate, 0);
GateRef isObj = builder_.TaggedIsHeapObject(func);
GateRef canFastCall = builder_.CanFastCall(func);
GateRef check = builder_.BoolAnd(isObj, canFastCall);
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT2);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
} else {
LOG_COMPILER(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
GateRef frameState = GetFrameState(gate);
auto func = acc_.GetValueIn(gate, 0);
GateRef isObj = builder_.TaggedIsHeapObject(func);
GateRef canFastCall = builder_.CanFastCall(func);
GateRef check = builder_.BoolAnd(isObj, canFastCall);
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT2);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void TypedHCRLowering::LowerJSNoGCFastCallThisTargetTypeCheck(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
auto type = acc_.GetParamGateType(gate);
if (tsManager_->IsFunctionTypeKind(type)) {
GateRef frameState = GetFrameState(gate);
auto func = acc_.GetValueIn(gate, 0);
GateRef isObj = builder_.TaggedIsHeapObject(func);
GateRef canFastCall = builder_.CanFastCall(func);
GateRef methodId = builder_.GetMethodId(func);
GateRef checkOptimized = builder_.BoolAnd(isObj, canFastCall);
GateRef check = builder_.BoolAnd(checkOptimized, builder_.Equal(methodId, acc_.GetValueIn(gate, 1)));
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT3);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
} else {
LOG_COMPILER(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
GateRef frameState = GetFrameState(gate);
auto func = acc_.GetValueIn(gate, 0);
GateRef isObj = builder_.TaggedIsHeapObject(func);
GateRef canFastCall = builder_.CanFastCall(func);
GateRef methodId = builder_.GetMethodId(func);
GateRef checkOptimized = builder_.BoolAnd(isObj, canFastCall);
GateRef check = builder_.BoolAnd(checkOptimized, builder_.Equal(methodId, acc_.GetValueIn(gate, 1)));
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT3);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void TypedHCRLowering::LowerCallTargetCheck(GateRef gate)
@ -2134,7 +2097,8 @@ void TypedHCRLowering::LowerTypeOfCheck(GateRef gate)
Environment env(gate, circuit_, &builder_);
GateRef frameState = GetFrameState(gate);
GateRef value = acc_.GetValueIn(gate, 0);
GateType type = acc_.GetParamGateType(gate);
GateTypeAccessor accessor(acc_.TryGetValue(gate));
ParamType type = accessor.GetParamType();
GateRef check = Circuit::NullGate();
if (type.IsNumberType()) {
check = builder_.TaggedIsNumber(value);
@ -2145,6 +2109,7 @@ void TypedHCRLowering::LowerTypeOfCheck(GateRef gate)
} else if (type.IsUndefinedType()) {
check = builder_.TaggedIsUndefined(value);
} else {
// NOTICE-PGO: wx add support for builtin(Function Object ArrayKind)
builder_.DeoptCheck(builder_.TaggedIsHeapObject(value), frameState, DeoptType::INCONSISTENTTYPE1);
if (type.IsStringType()) {
check = builder_.TaggedIsString(value);
@ -2152,12 +2117,6 @@ void TypedHCRLowering::LowerTypeOfCheck(GateRef gate)
check = builder_.IsJsType(value, JSType::BIGINT);
} else if (type.IsSymbolType()) {
check = builder_.IsJsType(value, JSType::SYMBOL);
} else if (tsManager_->IsFunctionTypeKind(type) || tsManager_->IsClassTypeKind(type)) {
check = builder_.IsCallable(value);
} else if (tsManager_->IsObjectTypeKind(type) || tsManager_->IsClassInstanceTypeKind(type)) {
check = builder_.IsJsType(value, JSType::JS_OBJECT);
} else if (tsManager_->IsArrayTypeKind(type)) {
check = builder_.IsJsType(value, JSType::JS_ARRAY);
} else {
UNREACHABLE();
}
@ -2170,10 +2129,12 @@ void TypedHCRLowering::LowerTypeOfCheck(GateRef gate)
void TypedHCRLowering::LowerTypeOf(GateRef gate, GateRef glue)
{
Environment env(gate, circuit_, &builder_);
GateType type = acc_.GetParamGateType(gate);
GateTypeAccessor accessor(acc_.TryGetValue(gate));
ParamType type = accessor.GetParamType();
GateRef gConstAddr = builder_.Load(VariableType::JS_POINTER(), glue,
builder_.IntPtr(JSThread::GlueData::GetGlobalConstOffset(builder_.GetCompilationConfig()->Is32Bit())));
ConstantIndex index;
// NOTICE-PGO: wx add support for builtin(Function Object ArrayKind)
if (type.IsNumberType()) {
index = ConstantIndex::NUMBER_STRING_INDEX;
} else if (type.IsBooleanType()) {
@ -2188,12 +2149,6 @@ void TypedHCRLowering::LowerTypeOf(GateRef gate, GateRef glue)
index = ConstantIndex::BIGINT_STRING_INDEX;
} else if (type.IsSymbolType()) {
index = ConstantIndex::SYMBOL_STRING_INDEX;
} else if (tsManager_->IsFunctionTypeKind(type) || tsManager_->IsClassTypeKind(type)) {
index = ConstantIndex::FUNCTION_STRING_INDEX;
} else if (tsManager_->IsObjectTypeKind(type) || tsManager_->IsClassInstanceTypeKind(type)) {
index = ConstantIndex::OBJECT_STRING_INDEX;
} else if (tsManager_->IsArrayTypeKind(type)) {
index = ConstantIndex::OBJECT_STRING_INDEX;
} else {
UNREACHABLE();
}

View File

@ -20,6 +20,7 @@
#include "ecmascript/compiler/bytecode_circuit_builder.h"
#include "ecmascript/compiler/circuit_builder-inl.h"
#include "ecmascript/compiler/combined_pass_visitor.h"
#include "ecmascript/compiler/type_info_accessors.h"
namespace panda::ecmascript::kungfu {
// TypeHCRLowering Process
@ -126,7 +127,7 @@ private:
void LowerType(GateRef gate);
void LowerPrimitiveTypeCheck(GateRef gate);
void LowerTypeConvert(GateRef gate);
void LowerPrimitiveToNumber(GateRef dst, GateRef src, GateType srcType);
void LowerPrimitiveToNumber(GateRef dst, GateRef src, ParamType srcType);
void LowerIntCheck(GateRef gate);
void LowerDoubleCheck(GateRef gate);
void LowerNumberCheck(GateRef gate);
@ -189,7 +190,7 @@ private:
void LowerTypedSuperAllocateThis(GateRef gate, GateRef glue);
void LowerGetSuperConstructor(GateRef gate);
void LowerJSInlineTargetTypeCheck(GateRef gate);
void SetDeoptTypeInfo(BuiltinTypeId id, DeoptType &type, size_t &typedArrayRootHclassIndex,
void SetDeoptTypeInfo(JSType jstype, DeoptType &type, size_t &typedArrayRootHclassIndex,
size_t &typedArrayRootHclassOnHeapIndex);
void LowerLookupHolder(GateRef gate);
void LowerLoadGetter(GateRef gate);

View File

@ -40,7 +40,7 @@ void OptCodeProfiler::PrintAndReset()
LOG_ECMA(INFO) << "Runtime Statistics of optimized code path:";
static constexpr int nameRightAdjustment = 46;
static constexpr int numberRightAdjustment = 15;
static constexpr int hundred = 85;
static constexpr int hundred = 100;
LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "Bytecode"
<< std::setw(numberRightAdjustment) << "bcIndex"
<< std::setw(numberRightAdjustment) << "Count"
@ -114,11 +114,11 @@ void OptCodeProfiler::PrintMethodRecord(Key key, std::string methodName)
static constexpr int nameRightAdjustment = 46;
static constexpr int numberRightAdjustment = 15;
static constexpr int hundred = 85;
static constexpr int hundred = 100;
BcRecord& bcRecord = methodIdToRecord_[key.Value()];
for (auto it = bcRecord.begin(); it != bcRecord.end(); it++) {
Record record = it->second;
if (record.Count() == 0 || record.Count() < static_cast<uint64_t>(skipMaxCount_)) {
if (record.Count() == 0) {
break;
}
@ -132,62 +132,66 @@ void OptCodeProfiler::PrintMethodRecord(Key key, std::string methodName)
}
void OptCodeProfiler::Update(JSHandle<JSTaggedValue> &func, int bcIndex, EcmaOpcode opcode, Mode mode)
{
auto it = profMap_.find(opcode);
if (it != profMap_.end()) {
(mode == Mode::TYPED_PATH) ? (it->second.typedPathValue++) : (it->second.slowPathValue++);
}
// methodId & methodName
auto funcPoint = JSFunction::Cast(func->GetTaggedObject());
auto method = funcPoint->GetMethod();
if (!method.IsMethod()) {
return;
}
auto methodPoint = Method::Cast(method);
auto methodId = methodPoint->GetMethodId().GetOffset();
auto methodName = methodPoint->GetMethodName();
const auto *pf = methodPoint->GetJSPandaFile();
ASSERT(pf != nullptr);
auto pfName = pf->GetJSPandaFileDesc();
auto itr = std::find(abcNames_.begin(), abcNames_.end(), pfName);
uint32_t index = 0;
if (itr != abcNames_.end()) {
index = static_cast<uint32_t>(std::distance(abcNames_.begin(), itr));
} else {
index = abcNames_.size();
abcNames_.emplace_back(pfName);
}
Key key(index, methodId);
// deal methodIdToName
auto result = methodIdToName_.find(key.Value());
if (result != methodIdToName_.end()) {
result->second.Inc();
} else {
methodIdToName_.emplace(key.Value(), Name(methodName));
}
// deal methodIdToRecord_
auto result2 = methodIdToRecord_.find(key.Value());
if (result2 == methodIdToRecord_.end()) {
BcRecord bcRecord;
bcRecord.emplace(bcIndex, Record(opcode));
methodIdToRecord_.emplace(key.Value(), bcRecord);
}
result2 = methodIdToRecord_.find(key.Value());
auto result3 = result2->second.find(bcIndex);
if (result3 != result2->second.end()) {
(mode == Mode::TYPED_PATH) ? (result3->second.IncFast()) : (result3->second.IncSlow());
} else {
auto record = Record(opcode);
(mode == Mode::TYPED_PATH) ? (record.IncFast()) : (record.IncSlow());
result2->second.emplace(bcIndex, record);
}
{
auto it = profMap_.find(opcode);
if (it != profMap_.end()) {
(mode == Mode::TYPED_PATH) ? (it->second.typedPathValue++) : (it->second.slowPathValue++);
}
if (func->IsUndefined()) {
return;
}
// methodId & methodName
auto funcPoint = JSFunction::Cast(func->GetTaggedObject());
auto method = funcPoint->GetMethod();
if (!method.IsMethod()) {
return;
}
auto methodPoint = Method::Cast(method);
auto methodId = methodPoint->GetMethodId().GetOffset();
auto methodName = methodPoint->GetMethodName();
const auto *pf = methodPoint->GetJSPandaFile();
ASSERT(pf != nullptr);
auto pfName = pf->GetJSPandaFileDesc();
auto itr = std::find(abcNames_.begin(), abcNames_.end(), pfName);
uint32_t index = 0;
if (itr != abcNames_.end()) {
index = static_cast<uint32_t>(std::distance(abcNames_.begin(), itr));
} else {
index = abcNames_.size();
abcNames_.emplace_back(pfName);
}
Key key(index, methodId);
// deal methodIdToName
auto result = methodIdToName_.find(key.Value());
if (result != methodIdToName_.end()) {
result->second.Inc();
} else {
methodIdToName_.emplace(key.Value(), Name(methodName));
}
// deal methodIdToRecord_
auto result2 = methodIdToRecord_.find(key.Value());
if (result2 == methodIdToRecord_.end()) {
BcRecord bcRecord;
bcRecord.emplace(bcIndex, Record(opcode));
methodIdToRecord_.emplace(key.Value(), bcRecord);
}
result2 = methodIdToRecord_.find(key.Value());
auto result3 = result2->second.find(bcIndex);
if (result3 != result2->second.end()) {
(mode == Mode::TYPED_PATH) ? (result3->second.IncFast()) : (result3->second.IncSlow());
} else {
auto record = Record(opcode);
(mode == Mode::TYPED_PATH) ? (record.IncFast()) : (record.IncSlow());
result2->second.emplace(bcIndex, record);
}
}
OptCodeProfiler::~OptCodeProfiler()
{
PrintAndReset();

View File

@ -199,7 +199,6 @@ private:
}
int printMehodCount_ {10};
int skipMaxCount_ {10000};
std::map<EcmaOpcode, Value> profMap_;
std::map<uint64_t, BcRecord> methodIdToRecord_;
std::map<uint64_t, Name> methodIdToName_;

View File

@ -20,6 +20,7 @@
#include "ecmascript/js_tagged_value-inl.h"
#include "ecmascript/js_typed_array.h"
#include "ecmascript/mem/tagged_object.h"
#include "ecmascript/js_function.h"
namespace panda::ecmascript {
class HandlerBase {
@ -387,6 +388,21 @@ public:
if (op.IsFound()) {
handler->SetHolder(thread, op.GetHolder());
}
if (op.IsAccessorDescriptor()) {
JSTaggedValue result = op.GetValue();
if (result.IsPropertyBox()) {
result = PropertyBox::Cast(result.GetTaggedObject())->GetValue();
}
AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject());
if (!accessor->IsInternal()) {
JSTaggedValue getter = accessor->GetGetter();
if (!getter.IsUndefined()) {
JSHandle<JSFunction> func(thread, getter);
uint32_t methodOffset = Method::Cast(func->GetMethod())->GetMethodId().GetOffset();
handler->SetAccessorMethodId(methodOffset);
}
}
}
// ShareToLocal is prohibited
if (!hclass->IsJSShared()) {
auto result = JSHClass::EnableProtoChangeMarker(thread, hclass);
@ -402,6 +418,19 @@ public:
JSHandle<JSTaggedValue> handlerInfo = StoreHandler::StoreProperty(thread, op);
handler->SetHandlerInfo(thread, handlerInfo);
handler->SetHolder(thread, op.GetHolder());
if (op.IsAccessorDescriptor()) {
JSTaggedValue result = op.GetValue();
if (result.IsPropertyBox()) {
result = PropertyBox::Cast(result.GetTaggedObject())->GetValue();
}
AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject());
if (!accessor->IsInternal()) {
JSTaggedValue getter = accessor->GetSetter();
JSHandle<JSFunction> func(thread, getter);
handler->SetAccessorMethodId(
Method::Cast(func->GetMethod())->GetMethodId().GetOffset());
}
}
// ShareToLocal is prohibited
if (!hclass->IsJSShared()) {
auto result = JSHClass::EnableProtoChangeMarker(thread, hclass);
@ -416,9 +445,12 @@ public:
ACCESSORS(ProtoCell, PROTO_CELL_OFFSET, HOLDER_OFFSET)
ACCESSORS(Holder, HOLDER_OFFSET, SIZE)
ACCESSORS(Holder, HOLDER_OFFSET, ACCESSOR_METHOD_ID_OFFSET)
DECL_VISIT_OBJECT(HANDLER_INFO_OFFSET, SIZE)
ACCESSORS_PRIMITIVE_FIELD(AccessorMethodId, uint32_t, ACCESSOR_METHOD_ID_OFFSET, LAST_OFFSET)
DEFINE_ALIGN_SIZE(LAST_OFFSET);
DECL_VISIT_OBJECT(HANDLER_INFO_OFFSET, ACCESSOR_METHOD_ID_OFFSET)
DECL_DUMP()
};

View File

@ -340,7 +340,6 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
WasSet(option);
switch (option) {
case OPTION_AOT_FILE:
LOG_ECMA(ERROR) << "aot output file:" << optarg;
SetAOTOutputFile(optarg);
ecmascript::AnFileDataManager::GetInstance()->SetEnable(true);
break;

View File

@ -19,6 +19,7 @@
#include "ecmascript/jspandafile/js_pandafile.h"
#include "ecmascript/jspandafile/panda_file_translator.h"
#include "ecmascript/jspandafile/debug_info_extractor.h"
#include "ecmascript/ts_types/ts_type_table.h"
#include "ecmascript/platform/mutex.h"
namespace panda {
@ -75,6 +76,24 @@ public:
}
}
template<typename Callback>
void EnumerateNonVirtualJSPandaFiles(Callback cb)
{
LockHolder lock(jsPandaFileLock_);
for (const auto &item : loadedJSPandaFiles_) {
if (item.first == panda::ecmascript::TSTypeTable::DEFAULT_TYPE_VIRTUAL_NAME) {
continue;
}
if (!cb(item.second)) {
return;
}
}
for (const auto &item : oldJSPandaFiles_) {
if (!cb(item)) {
return;
}
}
}
std::shared_ptr<JSPandaFile> FindJSPandaFileByNormalizedName(const CString &normalizedName);
std::shared_ptr<JSPandaFile> FindJSPandaFile(const CString &filename);
std::shared_ptr<JSPandaFile> FindMergedJSPandaFile();

View File

@ -3638,6 +3638,7 @@ JSHandle<PrototypeHandler> ObjectFactory::NewPrototypeHandler()
handler->SetHandlerInfo(thread_, JSTaggedValue::Undefined());
handler->SetProtoCell(thread_, JSTaggedValue::Undefined());
handler->SetHolder(thread_, JSTaggedValue::Undefined());
handler->SetAccessorMethodId(0);
return handler;
}

View File

@ -868,7 +868,9 @@ void PGOProfiler::DumpICByNameWithHandler(ApEntityId abcId, const CString &recor
if (HandlerBase::IsNonExist(handlerInfo)) {
return;
}
if (!AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, holderHClass, holderHClass)) {
auto accessorMethodId = prototypeHandler->GetAccessorMethodId();
if (!AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, holderHClass,
holderHClass, accessorMethodId)) {
return AddBuiltinsInfoByNameInProt(abcId, recordName, methodId, bcOffset, hclass, holderHClass);
}
}
@ -909,7 +911,8 @@ void PGOProfiler::DumpICByNameWithHandler(ApEntityId abcId, const CString &recor
}
auto holder = prototypeHandler->GetHolder();
auto holderHClass = holder.GetTaggedObject()->GetClass();
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, holderHClass, holderHClass);
auto accessorMethodId = prototypeHandler->GetAccessorMethodId();
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId);
} else if (secondValue.IsPropertyBox()) {
// StoreGlobal
} else if (secondValue.IsStoreTSHandler()) {
@ -1160,15 +1163,26 @@ void PGOProfiler::DumpCall(ApEntityId abcId, const CString &recordName, EntityId
uint32_t slotId, ProfileTypeInfo *profileTypeInfo)
{
JSTaggedValue slotValue = profileTypeInfo->Get(slotId);
if (!slotValue.IsInt()) {
ProfileType::Kind kind;
int calleeMethodId = 0;
ApEntityId calleeAbcId = 0;
if (slotValue.IsInt()) {
calleeMethodId = slotValue.GetInt();
calleeAbcId = abcId;
ASSERT(calleeMethodId <= 0);
if (calleeMethodId == 0) {
return;
}
kind = ProfileType::Kind::BuiltinFunctionId;
} else if (slotValue.IsMethod()) {
Method *calleeMethod = Method::Cast(slotValue);
calleeMethodId = calleeMethod->GetMethodId().GetOffset();
calleeAbcId = GetMethodAbcId(slotValue);
kind = ProfileType::Kind::MethodId;
} else {
return;
}
int calleeMethodId = slotValue.GetInt();
if (calleeMethodId == 0) {
return;
}
ProfileType::Kind kind = (calleeMethodId < 0) ? ProfileType::Kind::BuiltinFunctionId : ProfileType::Kind::MethodId;
PGOSampleType type = PGOSampleType::CreateProfileType(abcId, std::abs(calleeMethodId), kind);
PGOSampleType type = PGOSampleType::CreateProfileType(calleeAbcId, std::abs(calleeMethodId), kind);
ProfileType recordType = GetRecordProfileType(abcId, recordName);
recordInfos_->AddCallTargetType(recordType, methodId, bcOffset, type);
}
@ -1195,10 +1209,15 @@ void PGOProfiler::DumpNewObjRange(ApEntityId abcId, const CString &recordName, E
uint32_t slotId, ProfileTypeInfo *profileTypeInfo)
{
JSTaggedValue slotValue = profileTypeInfo->Get(slotId);
if (!slotValue.IsInt()) {
int ctorMethodId = 0;
if (slotValue.IsInt()) {
ctorMethodId = slotValue.GetInt();
} else if (slotValue.IsMethod()) {
Method *calleeMethod = Method::Cast(slotValue);
ctorMethodId = calleeMethod->GetMethodId().GetOffset();
} else {
return;
}
int ctorMethodId = slotValue.GetInt();
if (ctorMethodId > 0) {
auto type = PGOSampleType::CreateProfileType(abcId, ctorMethodId, ProfileType::Kind::ClassId, true);
ProfileType recordType = GetRecordProfileType(abcId, recordName);
@ -1314,8 +1333,8 @@ void PGOProfiler::UpdateTranstionLayout(JSHClass *parent, JSHClass *child)
}
}
bool PGOProfiler::AddTranstionObjectInfo(
ProfileType recordType, EntityId methodId, int32_t bcOffset, JSHClass *receiver, JSHClass *hold, JSHClass *holdTra)
bool PGOProfiler::AddTranstionObjectInfo(ProfileType recordType, EntityId methodId,
int32_t bcOffset, JSHClass *receiver, JSHClass *hold, JSHClass *holdTra, PGOSampleType accessorMethod)
{
auto receiverRootHClass = JSTaggedType(JSHClass::FindRootHClass(receiver));
auto receiverRootType = GetProfileTypeSafe(receiverRootHClass, receiverRootHClass);
@ -1348,17 +1367,19 @@ bool PGOProfiler::AddTranstionObjectInfo(
UpdateTranstionLayout(hold, holdTra);
}
PGOObjectInfo info(receiverRootType, receiverType, holdRootType, holdType, holdTraRootType, holdTraType);
PGOObjectInfo info(receiverRootType, receiverType, holdRootType, holdType, holdTraRootType, holdTraType,
accessorMethod);
UpdatePrototypeChainInfo(receiver, hold, info);
recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info);
return true;
}
bool PGOProfiler::AddObjectInfo(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
JSHClass *receiver, JSHClass *hold, JSHClass *holdTra)
JSHClass *receiver, JSHClass *hold, JSHClass *holdTra, uint32_t accessorMethodId)
{
PGOSampleType accessor = PGOSampleType::CreateProfileType(abcId, accessorMethodId, ProfileType::Kind::MethodId);
ProfileType recordType = GetRecordProfileType(abcId, recordName);
return AddTranstionObjectInfo(recordType, methodId, bcOffset, receiver, hold, holdTra);
return AddTranstionObjectInfo(recordType, methodId, bcOffset, receiver, hold, holdTra, accessor);
}
void PGOProfiler::UpdatePrototypeChainInfo(JSHClass *receiver, JSHClass *holder, PGOObjectInfo &info)
@ -1392,7 +1413,7 @@ void PGOProfiler::AddObjectInfoWithMega(
ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset)
{
auto megaType = ProfileType::CreateMegeType();
PGOObjectInfo info(megaType, megaType, megaType, megaType, megaType, megaType);
PGOObjectInfo info(megaType, megaType, megaType, megaType, megaType, megaType, PGOSampleType());
ProfileType recordType = GetRecordProfileType(abcId, recordName);
recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info);
}
@ -1652,15 +1673,14 @@ void PGOProfiler::Reset(bool isEnable)
}
}
ApEntityId PGOProfiler::GetMethodAbcId(JSFunction *jsFunction)
ApEntityId PGOProfiler::GetMethodAbcId(JSTaggedValue jsMethod)
{
ASSERT(jsMethod.IsMethod());
CString pfName;
auto jsMethod = jsFunction->GetMethod();
if (jsMethod.IsMethod()) {
const auto *pf = Method::Cast(jsMethod)->GetJSPandaFile();
if (pf != nullptr) {
pfName = pf->GetJSPandaFileDesc();
}
const auto *pf = Method::Cast(jsMethod)->GetJSPandaFile();
if (pf != nullptr) {
pfName = pf->GetJSPandaFileDesc();
}
ApEntityId abcId(0);
if (!PGOProfilerManager::GetInstance()->GetPandaFileId(pfName, abcId) && !pfName.empty()) {
@ -1668,6 +1688,16 @@ ApEntityId PGOProfiler::GetMethodAbcId(JSFunction *jsFunction)
}
return abcId;
}
ApEntityId PGOProfiler::GetMethodAbcId(JSFunction *jsFunction)
{
CString pfName;
auto jsMethod = jsFunction->GetMethod();
if (jsMethod.IsMethod()) {
return GetMethodAbcId(jsMethod);
}
LOG_ECMA(ERROR) << "Get method abc id failed. Not a method.";
UNREACHABLE();
}
ProfileType PGOProfiler::GetRecordProfileType(JSFunction *jsFunction, const CString &recordName)
{

View File

@ -150,11 +150,11 @@ private:
void UpdateLayout(JSHClass *hclass);
void UpdateTranstionLayout(JSHClass *parent, JSHClass *child);
bool AddTranstionObjectInfo(ProfileType recordType, EntityId methodId, int32_t bcOffset, JSHClass *receiver,
JSHClass *hold, JSHClass *holdTra);
JSHClass *hold, JSHClass *holdTra, PGOSampleType accessorMethod);
void UpdatePrototypeChainInfo(JSHClass *receiver, JSHClass *holder, PGOObjectInfo &info);
bool AddObjectInfo(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
JSHClass *receiver, JSHClass *hold, JSHClass *holdTra);
JSHClass *receiver, JSHClass *hold, JSHClass *holdTra, uint32_t accessorMethodId = 0);
void AddObjectInfoWithMega(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset);
void AddBuiltinsInfoByNameInInstance(ApEntityId abcId, const CString &recordName, EntityId methodId,
int32_t bcOffset, JSHClass *receiver);
@ -443,6 +443,7 @@ private:
};
static ApEntityId GetMethodAbcId(JSFunction *jsFunction);
static ApEntityId GetMethodAbcId(JSTaggedValue jsMethod);
ProfileType GetRecordProfileType(JSFunction *jsFunction, const CString &recordName);
ProfileType GetRecordProfileType(ApEntityId abcId, const CString &recordName);
ProfileType GetRecordProfileType(const std::shared_ptr<JSPandaFile> &pf, ApEntityId abcId,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* 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

View File

@ -58,15 +58,15 @@ public:
static constexpr uint32_t RECORD_ID_FOR_BUNDLE = 1;
static const ProfileType PROFILE_TYPE_NONE;
static PUBLIC_API const ProfileType PROFILE_TYPE_NONE;
static constexpr uint32_t ID_BITFIELD_NUM = 32;
static constexpr uint32_t ABC_ID_BITFIELD_NUM = 20;
static constexpr uint32_t KIND_BITFIELD_NUM = 11;
static constexpr uint32_t ID_BITFIELD_NUM = 32; // 0-31
static constexpr uint32_t ABC_ID_BITFIELD_NUM = 10; // 32-41
static constexpr uint32_t KIND_BITFIELD_NUM = 8; // 42 - 49
using IdBits = BitField<uint32_t, 0, ID_BITFIELD_NUM>;
using AbcIdBits = IdBits::NextField<uint32_t, ABC_ID_BITFIELD_NUM>;
using KindBits = AbcIdBits::NextField<Kind, KIND_BITFIELD_NUM>;
using IsRootBits = KindBits::NextFlag;
using IsRootBits = KindBits::NextFlag; // 50
class BuiltinsId {
public:

View File

@ -190,7 +190,7 @@ public:
PGOSampleTemplate CombineType(PGOSampleTemplate type)
{
if (type_.index() == 0) {
if (IsPrimitiveType()) {
auto oldType = static_cast<uint32_t>(std::get<Type>(type_));
oldType = oldType & static_cast<uint32_t>(AnyType());
type_ =
@ -223,7 +223,7 @@ public:
std::string GetTypeString() const
{
if (type_.index() == 0) {
if (IsPrimitiveType()) {
return std::to_string(static_cast<uint32_t>(std::get<Type>(type_)));
} else {
return std::get<PGOProfileType>(type_).GetTypeString();
@ -232,7 +232,7 @@ public:
std::string ToString() const
{
if (type_.index() == 0) {
if (IsPrimitiveType()) {
auto type = std::get<Type>(type_);
switch (type) {
case Type::NONE:
@ -285,50 +285,80 @@ public:
return std::get<PGOProfileType>(type_);
}
bool IsPrimitiveType() const
{
return type_.index() == 0;
}
Type GetPrimitiveType() const
{
ASSERT(IsPrimitiveType());
auto type = static_cast<uint32_t>(std::get<Type>(type_));
return Type(type & static_cast<uint32_t>(AnyType()));
}
uint32_t GetWeight() const
{
ASSERT(type_.index() == 0);
ASSERT(IsPrimitiveType());
auto type = static_cast<uint32_t>(std::get<Type>(type_));
return type >> WEIGHT_START_BIT;
}
bool IsAny() const
{
return type_.index() == 0 && GetPrimitiveType() == Type::ANY;
return IsPrimitiveType() && GetPrimitiveType() == Type::ANY;
}
bool IsNone() const
{
return type_.index() == 0 && GetPrimitiveType() == Type::NONE;
return IsPrimitiveType() && GetPrimitiveType() == Type::NONE;
}
bool IsInt() const
{
return type_.index() == 0 && GetPrimitiveType() == Type::INT;
return IsPrimitiveType() && GetPrimitiveType() == Type::INT;
}
bool IsIntOverFlow() const
{
return type_.index() == 0 && GetPrimitiveType() == Type::INT_OVERFLOW;
return IsPrimitiveType() && GetPrimitiveType() == Type::INT_OVERFLOW;
}
bool IsDouble() const
{
return type_.index() == 0 && GetPrimitiveType() == Type::DOUBLE;
return IsPrimitiveType() && GetPrimitiveType() == Type::DOUBLE;
}
bool IsString() const
{
return type_.index() == 0 && GetPrimitiveType() == Type::STRING;
return IsPrimitiveType() && GetPrimitiveType() == Type::STRING;
}
bool IsBigInt() const
{
return type_.index() == 0 && GetPrimitiveType() == Type::BIG_INT;
}
bool IsBoolean() const
{
return type_.index() == 0 && GetPrimitiveType() == Type::BOOLEAN;
}
bool IsHeapObject() const
{
return type_.index() == 0 && GetPrimitiveType() == Type::HEAP_OBJECT;
}
bool IsNumber() const
{
if (type_.index() != 0) {
return false;
}
auto primType = GetPrimitiveType();
return primType == Type::NUMBER || primType == Type::NUMBER1;
}
bool HasNumber() const
{
if (type_.index() != 0) {
return false;
@ -346,6 +376,11 @@ public:
}
}
bool IsProfileTypeNone() const
{
return type_.index() == 1 && GetProfileType() == ProfileType::PROFILE_TYPE_NONE;
}
bool operator<(const PGOSampleTemplate &right) const
{
return type_ < right.type_;
@ -457,15 +492,17 @@ enum class ProtoChainMarker : uint8_t {
NOT_EXSIT,
};
template <typename PGOProfileType>
template <typename PGOProfileType, typename PGOSampleType>
class PGOObjectTemplate {
public:
PGOObjectTemplate() = default;
PGOObjectTemplate(PGOProfileType type) : receiverType_(type) {}
PGOObjectTemplate(PGOProfileType receiverRootType, PGOProfileType receiverType, PGOProfileType holdRootType,
PGOProfileType holdType, PGOProfileType holdTraRootType, PGOProfileType holdTraType)
PGOProfileType holdType, PGOProfileType holdTraRootType,
PGOProfileType holdTraType, PGOSampleType accessorMethod)
: receiverRootType_(receiverRootType), receiverType_(receiverType), holdRootType_(holdRootType),
holdType_(holdType), holdTraRootType_(holdTraRootType), holdTraType_(holdTraType) {}
holdType_(holdType), holdTraRootType_(holdTraRootType),
holdTraType_(holdTraType), accessorMethod_(accessorMethod) {}
void AddPrototypePt(std::vector<std::pair<PGOProfileType, PGOProfileType>> protoChain)
{
@ -485,6 +522,7 @@ public:
holdType_ = PGOProfileType(context, from.GetHoldType());
holdTraRootType_ = PGOProfileType(context, from.GetHoldTraRootType());
holdTraType_ = PGOProfileType(context, from.GetHoldTraType());
accessorMethod_ = PGOSampleType::ConvertFrom(context, from.GetAccessorMethod());
protoChainMarker_ = from.GetProtoChainMarker();
}
@ -502,6 +540,8 @@ public:
result += holdTraRootType_.GetTypeString();
result += ", holdTra";
result += holdTraType_.GetTypeString();
result += ", accessorMethod";
result += accessorMethod_.GetTypeString();
result += ")";
return result;
}
@ -541,6 +581,11 @@ public:
return holdTraType_;
}
PGOSampleType GetAccessorMethod() const
{
return accessorMethod_;
}
ProtoChainMarker GetProtoChainMarker() const
{
return protoChainMarker_;
@ -597,11 +642,12 @@ private:
PGOProfileType holdType_ { PGOProfileType() };
PGOProfileType holdTraRootType_ { PGOProfileType() };
PGOProfileType holdTraType_ { PGOProfileType() };
PGOSampleType accessorMethod_ { PGOSampleType() };
ProtoChainMarker protoChainMarker_ {ProtoChainMarker::NOT_EXSIT};
PGOProtoChainTemplate<PGOProfileType> *protoChain_ { nullptr };
};
using PGOObjectInfo = PGOObjectTemplate<ProfileType>;
using PGOObjectInfoRef = PGOObjectTemplate<ProfileTypeRef>;
using PGOObjectInfo = PGOObjectTemplate<ProfileType, PGOSampleType>;
using PGOObjectInfoRef = PGOObjectTemplate<ProfileTypeRef, PGOSampleTypeRef>;
template <typename PGOObjectInfoType>
class PGORWOpTemplate : public PGOType {
@ -845,7 +891,7 @@ public:
return sampleType->GetProfileType().GetRaw();
}
const PGOSampleType* GetPGOSampleType()
const PGOSampleType* GetPGOSampleType() const
{
if (type_ == nullptr) {
static PGOSampleType noneType = PGOSampleType::NoneType();
@ -855,6 +901,29 @@ public:
return static_cast<const PGOSampleType*>(type_);
}
bool IsPGOSampleType() const
{
if (type_ == nullptr) {
return false;
}
return type_->IsScalarOpType();
}
bool HasNumber() const
{
return GetPGOSampleType()->HasNumber();
}
bool IsBoolean() const
{
return GetPGOSampleType()->IsBoolean();
}
bool IsString() const
{
return GetPGOSampleType()->IsString();
}
const PGORWOpType* GetPGORWOpType()
{
if (type_ == nullptr) {

View File

@ -1000,7 +1000,7 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump)
break;
}
case JSType::PROTOTYPE_HANDLER: {
CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), PrototypeHandler::SIZE, 3U);
CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), PrototypeHandler::SIZE, 4U);
JSHandle<PrototypeHandler> protoHandler = factory->NewPrototypeHandler();
DUMP_FOR_HANDLE(protoHandler);
break;

View File

@ -84,6 +84,7 @@
panda::ecmascript::WorkSpaceChunk::*;
panda::ecmascript::pgo::PGOProfilerDecoder::*;
panda::ecmascript::pgo::PGOProfilerEncoder::*;
panda::ecmascript::pgo::ProfileType::PROFILE_TYPE_NONE;
panda::ecmascript::containers::ContainerError::*;
panda::ecmascript::NativeAreaAllocator::*;
@ -329,6 +330,9 @@
panda::ecmascript::kungfu::ArkStackMapBuilder::GenerateArkStackMap*;
panda::ecmascript::kungfu::ArkStackMapBuilder::Run*;
panda::ecmascript::kungfu::PGOBCInfo::Record*;
panda::ecmascript::kungfu::PGOTypeManager::GetConstantPoolIDByMethodOffset*;
panda::ecmascript::kungfu::PGOTypeManager::GetConstantPoolByMethodOffset*;
panda::ecmascript::kungfu::PGOTypeManager::GetStringFromConstantPool*;
panda::ecmascript::kungfu::PGOTypeManager::GetElementsIndexByEntityId*;
panda::ecmascript::kungfu::PGOTypeManager::GetHClassIndexByProfileType*;
panda::ecmascript::kungfu::PGOTypeManager::InitAOTSnapshot*;

View File

@ -138,12 +138,8 @@ group("ark_aot_ts_test") {
"ldobjbyvalue",
"ldstlexvar",
"ldsuperbyname",
"lexenv_specialization",
"lexenv_specialization",
"lexenv_specialization_noopt",
"load_local_module_var",
"logic_op",
"loop_hoist",
"loop_peeling",
"loop_phi",
"loop_with_variable_exchange",
@ -237,29 +233,6 @@ group("ark_aot_ts_test") {
"tryldglobalbyname_global_record",
"trystglobalbynameprefid32",
"ts_hclass_generator",
"ts_inline",
"ts_inline_accessor",
"ts_inline_accessor_deopt",
"ts_inline_accessor_extends",
"ts_inline_accessor_same_name",
"ts_inline_change_target",
"ts_inline_deopt",
"ts_inline_deopt_loop",
"ts_inline_exception1",
"ts_inline_exception2",
"ts_inline_exception3",
"ts_inline_exception4",
"ts_inline_exception5",
"ts_inline_exception6",
"ts_inline_exception7",
"ts_inline_exception8",
"ts_inline_extends",
"ts_inline_loop",
"ts_inline_max_call",
"ts_multi_inline",
"ts_multi_inline_deopt",
"ts_multi_inline_max_call",
"ts_multi_inline_recursive",
"typedarray",
"typedarray_load_store",
"typedarrayfill",
@ -276,7 +249,36 @@ group("ark_aot_ts_test") {
]
if (!is_debug) {
test_list += [ "pgo_call_deopt" ]
test_list += [
#"lexenv_specialization",
#"lexenv_specialization_multi_inline",
#"lexenv_specialization_noopt",
#"loop_hoist",
#"pgo_call_deopt",
#"ts_inline",
#"ts_inline_accessor",
#"ts_inline_accessor_deopt",
#"ts_inline_accessor_extends",
#"ts_inline_accessor_same_name",
#"ts_inline_change_target",
#"ts_inline_deopt",
#"ts_inline_deopt_loop",
#"ts_inline_exception1",
#"ts_inline_exception2",
#"ts_inline_exception3",
#"ts_inline_exception4",
#"ts_inline_exception5",
#"ts_inline_exception6",
#"ts_inline_exception7",
#"ts_inline_exception8",
#"ts_inline_extends",
#"ts_inline_loop",
#"ts_inline_max_call",
#"ts_multi_inline",
#"ts_multi_inline_deopt",
#"ts_multi_inline_max_call",
#"ts_multi_inline_recursive",
]
}
deps = [ "builtin_inlining:ark_aot_builtin_inlining_test" ]

View File

@ -105,6 +105,7 @@ print(myMap.get(obj)); //: undefined
function Throwing() {
this.value = -1;
}
//aot: [trace] Check Type: InconsistentHClass6
Throwing.prototype.valueOf = function() {
if (this.value > 0) {
throw new Error("already positive");

View File

@ -104,6 +104,7 @@ print(myMap.has(obj)); //: false
function Throwing() {
this.value = -1;
}
//aot: [trace] Check Type: InconsistentHClass6
Throwing.prototype.valueOf = function() {
if (this.value > 0) {
throw new Error("already positive");

View File

@ -99,6 +99,7 @@ print(Math.abs(4, 0, 0, 0)); //: 4
print(Math.abs(-4, 0, 0, 0, 0)); //: 4
// Replace standard builtin
//aot: [trace] Check Type: NotJSCallTarget4
let true_abs = Math.abs
Math.abs = replace
@ -109,17 +110,17 @@ Math.abs = true_abs
// Check edge cases
const INT_MAX: number = 2147483647;
const INT_MIN: number = -INT_MAX - 1;
//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
print(Math.abs(INT_MAX)); //: 2147483647
//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
print(Math.abs(2147483648)); //: 2147483648
//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
print(Math.abs(-INT_MAX)); //: 2147483647
//aot: [trace] aot inline builtin: Math.abs, caller function name:doAbs@builtinMathAbs
printAbs(INT_MAX); //: 2147483647
//aot: [trace] aot inline builtin: Math.abs, caller function name:doAbs@builtinMathAbs
printAbs(2147483648); //: 2147483648
//aot: [trace] aot inline builtin: Math.abs, caller function name:doAbs@builtinMathAbs
printAbs(-INT_MAX); //: 2147483647
//aot: [trace] aot inline builtin: Math.abs, caller function name:printAbs2@builtinMathAbs
//aot: [trace] Check Type: NotInt3
printAbs2(); //: 2147483648
//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
print(Math.abs(INT_MIN - 1)); //: 2147483649
//aot: [trace] aot inline builtin: Math.abs, caller function name:doAbs@builtinMathAbs
printAbs(INT_MIN - 1); //: 2147483649
//aot: [trace] aot inline builtin: Math.abs, caller function name:doAbs@builtinMathAbs
printAbs(-12); //: 12
@ -158,8 +159,6 @@ try {
let obj = {
valueOf: () => { return -23; }
};
//aot: [trace] aot inline builtin: Math.abs, caller function name:func_main_0@builtinMathAbs
//aot: [trace] Check Type: NotNumber2
print(Math.abs(obj)); //: 23
function Throwing() {

View File

@ -51,6 +51,7 @@ len = Math.acos(10);
print(len); //: NaN
// Replace standart builtin
//aot: [trace] Check Type: NotJSCallTarget4
let true_acos = Math.acos
Math.acos = replace
len = Math.acos(111);
@ -58,7 +59,5 @@ print(len); //: 111
// Call standart builtin with non-number param
Math.acos = true_acos
//aot: [trace] aot inline builtin: Math.acos, caller function name:func_main_0@builtinMathAcos
//aot: [trace] Check Type: NotNumber1
len = Math.acos("NaN"); // deopt
print(len); //: NaN

View File

@ -51,14 +51,13 @@ len = Math.acosh(10);
print(len); //: 2.993222846126381
// Replace standart builtin
//aot: [trace] Check Type: NotJSCallTarget4
let true_acosh = Math.acosh
Math.acosh = replace
len = Math.acosh(111);
print(len); //: 111
// Call standart builtin with non-number param
// Call standart builtin with non-number
Math.acosh = true_acosh
len = Math.acosh("NaN"); // deopt
//aot: [trace] aot inline builtin: Math.acosh, caller function name:func_main_0@builtinMathAcosh
//aot: [trace] Check Type: NotNumber1
print(len); //: NaN

View File

@ -51,6 +51,7 @@ len = Math.asin(10);
print(len); //: NaN
// Replace standart builtin
//aot: [trace] Check Type: NotJSCallTarget4
let true_asin = Math.asin
Math.asin = replace
len = Math.asin(111);
@ -59,6 +60,4 @@ print(len); //: 111
// Call standart builtin with non-number param
Math.asin = true_asin
len = Math.asin("NaN"); // deopt
//aot: [trace] aot inline builtin: Math.asin, caller function name:func_main_0@builtinMathAsin
//aot: [trace] Check Type: NotNumber1
print(len); //: NaN

View File

@ -51,6 +51,7 @@ len = Math.asinh(10);
print(len); //: 2.99822295029797
// Replace standart builtin
//aot: [trace] Check Type: NotJSCallTarget4
let true_asinh = Math.asinh
Math.asinh = replace
len = Math.asinh(111);
@ -59,6 +60,4 @@ print(len); //: 111
// Call standart builtin with non-number param
Math.asinh = true_asinh
len = Math.asinh("NaN"); // deopt
//aot: [trace] aot inline builtin: Math.asinh, caller function name:func_main_0@builtinMathAsinh
//aot: [trace] Check Type: NotNumber1
print(len); //: NaN

View File

@ -51,6 +51,7 @@ len = Math.atan(10);
print(len); //: 1.4711276743037347
// Replace standart builtin
//aot: [trace] Check Type: NotJSCallTarget4
let true_atan = Math.atan
Math.atan = replace
len = Math.atan(111);
@ -59,6 +60,4 @@ print(len); //: 111
// Call standart builtin with non-number param
Math.atan = true_atan
len = Math.atan("NaN"); // deopt
//aot: [trace] aot inline builtin: Math.atan, caller function name:func_main_0@builtinMathAtan
//aot: [trace] Check Type: NotNumber1
print(len); //: NaN

View File

@ -75,6 +75,7 @@ len = Math.atan2(1, Number.POSITIVE_INFINITY)
print(len) //: 0
// Replace standart builtin
//aot: [trace] Check Type: NotJSCallTarget4
let true_atan2 = Math.atan2
Math.atan2 = replace
len = Math.atan2(111);
@ -83,6 +84,4 @@ print(len); //: 111
// Call standart builtin with non-number param
Math.atan2 = true_atan2
len = Math.atan2(0, "NaN"); // deopt
//aot: [trace] aot inline builtin: Math.atan2, caller function name:func_main_0@builtinMathAtan2
//aot: [trace] Check Type: NotNumber1
print(len); //: NaN

View File

@ -56,6 +56,7 @@ len = Math.atanh(10);
print(len); //: NaN
// Replace standart builtin
//aot: [trace] Check Type: NotJSCallTarget4
let true_atanh = Math.atanh
Math.atanh = replace
len = Math.atanh(111);
@ -64,6 +65,4 @@ print(len); //: 111
// Call standart builtin with non-number param
Math.atanh = true_atanh
len = Math.atanh("abc"); // deopt
//aot: [trace] aot inline builtin: Math.atanh, caller function name:func_main_0@builtinMathAtanh
//aot: [trace] Check Type: NotNumber1
print(len); //: NaN

View File

@ -76,6 +76,7 @@ print("1/x: " + 1.0/res); //: 1/x: -Infinity
print(Math.cbrt(NaN)); //: NaN
// Replace standard builtin
//aot: [trace] Check Type: NotJSCallTarget4
let true_cbrt = Math.cbrt;
Math.cbrt = replace;
@ -122,8 +123,6 @@ try {
let obj = {};
obj.valueOf = (() => { return -64; })
//aot: [trace] aot inline builtin: Math.cbrt, caller function name:func_main_0@builtinMathCbrt
//aot: [trace] Check Type: NotNumber1
print(Math.cbrt(obj)); //: -4
function Throwing() {

Some files were not shown because too many files have changed in this diff Show More