mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2025-02-26 07:16:57 +00:00
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:
parent
024e742dc7
commit
58abf70f8e
@ -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,
|
||||
|
@ -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 ] ] ) */ \
|
||||
|
@ -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 ) */ \
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
|
||||
#include "ecmascript/compiler/async_function_lowering.h"
|
||||
|
||||
#include "ecmascript/js_generator_object.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
void AsyncFunctionLowering::ProcessAll()
|
||||
{
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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_ {};
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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_;
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -102,4 +102,4 @@ private:
|
||||
const JSThread *thread_ {nullptr};
|
||||
};
|
||||
}
|
||||
#endif // ECMASCRIPT_COMPILER_BUILTIN_INLINE_H
|
||||
#endif // ECMASCRIPT_COMPILER_BUILTIN_INLINE_H
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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};
|
||||
|
@ -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();
|
||||
|
@ -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};
|
||||
|
@ -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));
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
@ -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>();
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -265,7 +265,7 @@ void ProfilerStubBuilder::ProfileCall(
|
||||
Bind(¤tIsHotness);
|
||||
{
|
||||
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, ¬ArrayProtoValues);
|
||||
Bind(&isArrayProtoValues);
|
||||
{
|
||||
functionId = Int32(PGO_BUILTINS_STUB_ID(ARRAY_PROTO_ITERATOR));
|
||||
functionId = Int32(PGO_BUILTINS_STUB_ID(ArrayProtoIterator));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬ArrayProtoValues);
|
||||
@ -671,7 +668,7 @@ GateRef ProfilerStubBuilder::GetIterationFunctionId(GateRef glue, GateRef iterat
|
||||
BRANCH(Int64Equal(iterator, *maybeFunc), &isSetProtoValues, ¬SetProtoValues);
|
||||
Bind(&isSetProtoValues);
|
||||
{
|
||||
functionId = Int32(PGO_BUILTINS_STUB_ID(SET_PROTO_ITERATOR));
|
||||
functionId = Int32(PGO_BUILTINS_STUB_ID(SetProtoIterator));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬SetProtoValues);
|
||||
@ -679,7 +676,7 @@ GateRef ProfilerStubBuilder::GetIterationFunctionId(GateRef glue, GateRef iterat
|
||||
BRANCH(Int64Equal(iterator, *maybeFunc), &isMapProtoEntries, ¬MapProtoEntries);
|
||||
Bind(&isMapProtoEntries);
|
||||
{
|
||||
functionId = Int32(PGO_BUILTINS_STUB_ID(MAP_PROTO_ITERATOR));
|
||||
functionId = Int32(PGO_BUILTINS_STUB_ID(MapProtoIterator));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬MapProtoEntries);
|
||||
@ -687,7 +684,7 @@ GateRef ProfilerStubBuilder::GetIterationFunctionId(GateRef glue, GateRef iterat
|
||||
BRANCH(Int64Equal(iterator, *maybeFunc), &isStringProtoIter, ¬StringProtoIter);
|
||||
Bind(&isStringProtoIter);
|
||||
{
|
||||
functionId = Int32(PGO_BUILTINS_STUB_ID(STRING_PROTO_ITERATOR));
|
||||
functionId = Int32(PGO_BUILTINS_STUB_ID(StringProtoIterator));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬StringProtoIter);
|
||||
@ -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);
|
||||
|
@ -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()) {
|
||||
|
@ -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:
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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_;
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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_;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
@ -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
@ -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
|
@ -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);
|
||||
|
@ -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_;
|
||||
|
@ -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_);
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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_;
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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_;
|
||||
|
@ -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()
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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*;
|
||||
|
@ -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" ]
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user