mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 18:20:04 +00:00
!6907 Remove TSManager and TSTypes
Merge pull request !6907 from huoqingyi/remove_tsmanager
This commit is contained in:
commit
9363d1718e
37
BUILD.gn
37
BUILD.gn
@ -103,7 +103,6 @@ group("ark_js_unittest") {
|
||||
"ecmascript/serializer/tests:unittest",
|
||||
"ecmascript/snapshot/tests:unittest",
|
||||
"ecmascript/tests:unittest",
|
||||
"ecmascript/ts_types/tests:unittest",
|
||||
]
|
||||
if (is_ohos && is_standard_system) {
|
||||
deps += [ "test/fuzztest:fuzztest" ]
|
||||
@ -140,7 +139,6 @@ group("ark_unittest") {
|
||||
"ecmascript/serializer/tests:host_unittest",
|
||||
"ecmascript/snapshot/tests:host_unittest",
|
||||
"ecmascript/tests:host_unittest",
|
||||
"ecmascript/ts_types/tests:host_unittest",
|
||||
]
|
||||
if (!run_with_asan) {
|
||||
if (!(ark_standalone_build && current_os == "ohos")) {
|
||||
@ -152,29 +150,6 @@ group("ark_unittest") {
|
||||
}
|
||||
}
|
||||
|
||||
_builtins_dts_path_ = rebase_path("./ecmascript/ts_types/lib_ark_builtins.d.ts")
|
||||
|
||||
_es2abc_builtins_d_abc_path_ =
|
||||
"$target_out_dir/lib_ark_builtins/es2abc/lib_ark_builtins.d.abc"
|
||||
|
||||
es2abc_gen_abc("es2abc_gen_builtins_d_abc") {
|
||||
extra_visibility = [ "*" ]
|
||||
|
||||
# extra_dependencies = _deps_
|
||||
src_js = rebase_path(_builtins_dts_path_)
|
||||
dst_file = rebase_path(_es2abc_builtins_d_abc_path_)
|
||||
extension = "ts"
|
||||
extra_args = [
|
||||
"--module",
|
||||
"--merge-abc",
|
||||
"--type-extractor",
|
||||
"--type-dts-builtin",
|
||||
]
|
||||
|
||||
in_puts = [ _builtins_dts_path_ ]
|
||||
out_puts = [ _es2abc_builtins_d_abc_path_ ]
|
||||
}
|
||||
|
||||
group("ark_runtime_host_unittest") {
|
||||
testonly = true
|
||||
deps = []
|
||||
@ -703,7 +678,6 @@ ecma_source = [
|
||||
"ecmascript/jspandafile/class_info_extractor.cpp",
|
||||
"ecmascript/jspandafile/debug_info_extractor.cpp",
|
||||
"ecmascript/jspandafile/literal_data_extractor.cpp",
|
||||
"ecmascript/jspandafile/type_literal_extractor.cpp",
|
||||
"ecmascript/jspandafile/accessor/module_data_accessor.cpp",
|
||||
"ecmascript/jspandafile/panda_file_translator.cpp",
|
||||
"ecmascript/jspandafile/js_pandafile_executor.cpp",
|
||||
@ -857,7 +831,6 @@ ecma_source = [
|
||||
"ecmascript/stackmap/litecg/litecg_stackmap_type.cpp",
|
||||
"ecmascript/stackmap/llvm/llvm_stackmap_parser.cpp",
|
||||
"ecmascript/stackmap/llvm/llvm_stackmap_type.cpp",
|
||||
"ecmascript/subtyping_operator.cpp",
|
||||
"ecmascript/sustaining_js_handle.cpp",
|
||||
"ecmascript/taskpool/taskpool.cpp",
|
||||
"ecmascript/taskpool/runner.cpp",
|
||||
@ -881,13 +854,6 @@ ecma_source = [
|
||||
"ecmascript/waiter_list.cpp",
|
||||
"ecmascript/weak_vector.cpp",
|
||||
"ecmascript/stubs/runtime_stubs.cpp",
|
||||
"ecmascript/ts_types/ts_type.cpp",
|
||||
"ecmascript/ts_types/ts_type_accessor.cpp",
|
||||
"ecmascript/ts_types/ts_type_table.cpp",
|
||||
"ecmascript/ts_types/ts_manager.cpp",
|
||||
"ecmascript/ts_types/ts_obj_layout_info.cpp",
|
||||
"ecmascript/ts_types/ts_type_parser.cpp",
|
||||
"ecmascript/ts_types/ts_type_table_generator.cpp",
|
||||
"ecmascript/stubs/test_runtime_stubs.cpp",
|
||||
"ecmascript/builtins/builtins_cjs_module.cpp",
|
||||
"ecmascript/builtins/builtins_cjs_require.cpp",
|
||||
@ -1100,9 +1066,6 @@ ohos_source_set("libark_jsruntime_test_set") {
|
||||
rebase_path("$root_gen_dir/arkcompiler/ets_runtime/stub.an")
|
||||
}
|
||||
defines += [ "STUB_AN_FILE=\"${stub_an_file_path}\"" ]
|
||||
target_builtins_dts_path =
|
||||
"/system/lib64/${arkcompiler_relative_lib_path}/lib_ark_builtins.d.abc"
|
||||
defines += [ "TARGET_BUILTINS_DTS_PATH=\"${target_builtins_dts_path}\"" ]
|
||||
|
||||
deps = []
|
||||
external_deps = [ "zlib:libz" ]
|
||||
|
@ -390,7 +390,7 @@ used time is: 0:01:04.439642
|
||||
1. 通过方舟前端生成hello-world.abc文件,编译命令:
|
||||
|
||||
```
|
||||
/your_code_path/out/rk3568/clang_x64/arkcompiler/ets_frontend/es2abc --module --type-extractor --merge-abc hello-world.ts
|
||||
/your_code_path/out/rk3568/clang_x64/arkcompiler/ets_frontend/es2abc --module --merge-abc hello-world.ts
|
||||
```
|
||||
2. 设置搜索路径:
|
||||
|
||||
|
@ -156,7 +156,6 @@ libark_jsoptimizer_sources = [
|
||||
"number_speculative_lowering.cpp",
|
||||
"number_speculative_retype.cpp",
|
||||
"number_speculative_runner.cpp",
|
||||
"object_access_helper.cpp",
|
||||
"operations_stub_builder.cpp",
|
||||
"pass_manager.cpp",
|
||||
"post_schedule.cpp",
|
||||
@ -179,15 +178,11 @@ libark_jsoptimizer_sources = [
|
||||
"trampoline/x64/common_call.cpp",
|
||||
"trampoline/x64/optimized_call.cpp",
|
||||
"trampoline/x64/optimized_fast_call.cpp",
|
||||
"ts_class_analysis.cpp",
|
||||
"ts_hclass_generator.cpp",
|
||||
"ts_hcr_opt_pass.cpp",
|
||||
"ts_inline_lowering.cpp",
|
||||
"type.cpp",
|
||||
"type_inference/pgo_type_infer.cpp",
|
||||
"type_inference/pgo_type_infer_helper.cpp",
|
||||
"type_info_accessors.cpp",
|
||||
"type_recorder.cpp",
|
||||
"typed_bytecode_lowering.cpp",
|
||||
"typed_hcr_lowering.cpp",
|
||||
"typed_native_inline_lowering.cpp",
|
||||
@ -516,10 +511,7 @@ ohos_executable("ark_aot_compiler") {
|
||||
"$js_root:ark_jsruntime_public_config",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":lib_ark_builtins.d.abc",
|
||||
":libark_mock_stub_set",
|
||||
]
|
||||
deps = [ ":libark_mock_stub_set" ]
|
||||
|
||||
if (is_ohos) {
|
||||
deps += [
|
||||
@ -645,20 +637,3 @@ action("build_stub_to_cpp") {
|
||||
|
||||
outputs = [ "$root_gen_dir/arkcompiler/ets_runtime/stub_an.cpp" ]
|
||||
}
|
||||
|
||||
ohos_copy("lib_ark_builtins.d.abc") {
|
||||
deps = [ "$js_root:es2abc_gen_builtins_d_abc" ]
|
||||
sources = [ rebase_path(root_out_dir) + "/obj/arkcompiler/ets_runtime/lib_ark_builtins/es2abc/lib_ark_builtins.d.abc" ]
|
||||
|
||||
# Set the output directory
|
||||
outputs = [ "$target_out_dir/lib_ark_builtins.d.abc" ]
|
||||
|
||||
# Set the install directory
|
||||
install_enable = true
|
||||
module_type = "lib"
|
||||
relative_install_dir = arkcompiler_relative_lib_path
|
||||
|
||||
# Set the subsystem name
|
||||
part_name = "ets_runtime"
|
||||
subsystem_name = "arkcompiler"
|
||||
}
|
||||
|
@ -13,14 +13,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "ecmascript/compiler/aot_compilation_env.h"
|
||||
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
|
||||
#include "ecmascript/ecma_context.h"
|
||||
#include "ecmascript/jspandafile/program_object.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
AOTCompilationEnv::AOTCompilationEnv(EcmaVM *vm) : CompilationEnv(vm)
|
||||
{
|
||||
tsManager_ = thread_->GetCurrentEcmaContext()->GetTSManager(),
|
||||
ptManager_ = thread_->GetCurrentEcmaContext()->GetPTManager();
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ int Main(const int argc, const char **argv)
|
||||
LocalScope scope(vm);
|
||||
arg_list_t pandaFileNames {};
|
||||
std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
|
||||
CompilationOptions cOptions(vm, runtimeOptions);
|
||||
CompilationOptions cOptions(runtimeOptions);
|
||||
|
||||
CompilerLog log(cOptions.logOption_);
|
||||
log.SetEnableCompilerLogTime(cOptions.compilerLogTime_);
|
||||
@ -134,7 +134,6 @@ int Main(const int argc, const char **argv)
|
||||
profilerDecoder.SetHotnessThreshold(cOptions.hotnessThreshold_);
|
||||
profilerDecoder.SetInPath(cOptions.profilerIn_);
|
||||
cPreprocessor.AOTInitialize();
|
||||
cPreprocessor.SetShouldCollectLiteralInfo(cOptions, &log);
|
||||
uint32_t checksum = cPreprocessor.GenerateAbcFileInfos();
|
||||
// Notice: lx move load pandaFileHead and verify before GeneralAbcFileInfos.
|
||||
// need support muilt abc
|
||||
@ -155,14 +154,12 @@ int Main(const int argc, const char **argv)
|
||||
.EnableEarlyElimination(cOptions.isEnableEarlyElimination_)
|
||||
.EnableLaterElimination(cOptions.isEnableLaterElimination_)
|
||||
.EnableValueNumbering(cOptions.isEnableValueNumbering_)
|
||||
.EnableTypeInfer(cOptions.isEnableTypeInfer_)
|
||||
.EnableOptInlining(cOptions.isEnableOptInlining_)
|
||||
.EnableOptString(cOptions.isEnableOptString_)
|
||||
.EnableOptPGOType(cOptions.isEnableOptPGOType_)
|
||||
.EnableOptTrackField(cOptions.isEnableOptTrackField_)
|
||||
.EnableOptLoopPeeling(cOptions.isEnableOptLoopPeeling_)
|
||||
.EnableOptLoopInvariantCodeMotion(cOptions.isEnableOptLoopInvariantCodeMotion_)
|
||||
.EnableCollectLiteralInfo(cOptions.isEnableCollectLiteralInfo_)
|
||||
.EnableOptConstantFolding(cOptions.isEnableOptConstantFolding_)
|
||||
.EnableLexenvSpecialization(cOptions.isEnableLexenvSpecialization_)
|
||||
.EnableInlineNative(cOptions.isEnableNativeInline_)
|
||||
|
@ -26,7 +26,7 @@ constexpr int32_t DEFAULT_OPT_LEVEL = 3; // 3: default opt level
|
||||
} // namespace
|
||||
using PGOProfilerManager = pgo::PGOProfilerManager;
|
||||
|
||||
CompilationOptions::CompilationOptions(EcmaVM *vm, JSRuntimeOptions &runtimeOptions)
|
||||
CompilationOptions::CompilationOptions(JSRuntimeOptions &runtimeOptions)
|
||||
{
|
||||
triple_ = runtimeOptions.GetTargetTriple();
|
||||
if (runtimeOptions.GetAOTOutputFile().empty()) {
|
||||
@ -51,14 +51,11 @@ CompilationOptions::CompilationOptions(EcmaVM *vm, JSRuntimeOptions &runtimeOpti
|
||||
isEnableValueNumbering_ = runtimeOptions.IsEnableValueNumbering();
|
||||
isEnableOptInlining_ = runtimeOptions.IsEnableOptInlining();
|
||||
isEnableOptString_ = runtimeOptions.IsEnableOptString();
|
||||
isEnableTypeInfer_ = isEnableTypeLowering_ ||
|
||||
vm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->AssertTypes();
|
||||
isEnableOptPGOType_ = runtimeOptions.IsEnableOptPGOType();
|
||||
isEnableOptTrackField_ = runtimeOptions.IsEnableOptTrackField();
|
||||
isEnableOptLoopPeeling_ = runtimeOptions.IsEnableOptLoopPeeling();
|
||||
isEnableOptLoopInvariantCodeMotion_ = runtimeOptions.IsEnableOptLoopInvariantCodeMotion();
|
||||
isEnableOptConstantFolding_ = runtimeOptions.IsEnableOptConstantFolding();
|
||||
isEnableCollectLiteralInfo_ = false;
|
||||
isEnableLexenvSpecialization_ = runtimeOptions.IsEnableLexenvSpecialization();
|
||||
isEnableNativeInline_ = runtimeOptions.IsEnableNativeInline();
|
||||
isEnableLoweringBuiltin_ = runtimeOptions.IsEnableLoweringBuiltin();
|
||||
@ -166,14 +163,6 @@ void AotCompilerPreprocessor::AOTInitialize()
|
||||
CommonStubCSigns::Initialize();
|
||||
BuiltinsStubCSigns::Initialize();
|
||||
RuntimeStubCSigns::Initialize();
|
||||
vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->Initialize();
|
||||
}
|
||||
|
||||
void AotCompilerPreprocessor::SetShouldCollectLiteralInfo(CompilationOptions &cOptions, const CompilerLog *log)
|
||||
{
|
||||
TSManager *tsManager = vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager();
|
||||
cOptions.isEnableCollectLiteralInfo_ = cOptions.isEnableTypeInfer_ &&
|
||||
(profilerDecoder_.IsLoaded() || tsManager->AssertTypes() || log->OutputType());
|
||||
}
|
||||
|
||||
uint32_t AotCompilerPreprocessor::GenerateAbcFileInfos()
|
||||
@ -250,8 +239,8 @@ void AotCompilerPreprocessor::RecordArrayElement(const CompilationOptions &cOpti
|
||||
JSPandaFile *jsPandaFile = fileInfo.jsPandaFile_.get();
|
||||
PGOTypeManager *ptManager = vm_->GetJSThread()->GetCurrentEcmaContext()->GetPTManager();
|
||||
ptManager->SetCurCompilationFile(jsPandaFile);
|
||||
BytecodeInfoCollector collector(&aotCompilationEnv_, jsPandaFile, profilerDecoder_, cOptions.maxAotMethodSize_,
|
||||
cOptions.isEnableCollectLiteralInfo_);
|
||||
BytecodeInfoCollector collector(&aotCompilationEnv_, jsPandaFile, profilerDecoder_,
|
||||
cOptions.maxAotMethodSize_);
|
||||
BCInfo &bytecodeInfo = collector.GetBytecodeInfo();
|
||||
const PGOBCInfo *bcInfo = collector.GetPGOBCInfo();
|
||||
auto &methodList = bytecodeInfo.GetMethodList();
|
||||
@ -284,8 +273,8 @@ void AotCompilerPreprocessor::GeneratePGOTypes(const CompilationOptions &cOption
|
||||
PGOTypeManager *ptManager = vm_->GetJSThread()->GetCurrentEcmaContext()->GetPTManager();
|
||||
for (const AbcFileInfo &fileInfo : fileInfos_) {
|
||||
JSPandaFile *jsPandaFile = fileInfo.jsPandaFile_.get();
|
||||
BytecodeInfoCollector collector(&aotCompilationEnv_, jsPandaFile, profilerDecoder_, cOptions.maxAotMethodSize_,
|
||||
cOptions.isEnableCollectLiteralInfo_);
|
||||
BytecodeInfoCollector collector(&aotCompilationEnv_, jsPandaFile, profilerDecoder_,
|
||||
cOptions.maxAotMethodSize_);
|
||||
PGOTypeParser parser(profilerDecoder_, ptManager);
|
||||
parser.CreatePGOType(collector);
|
||||
}
|
||||
@ -366,8 +355,8 @@ void AotCompilerPreprocessor::GenerateMethodMap(CompilationOptions &cOptions)
|
||||
jsPandaFileManager->EnumerateNonVirtualJSPandaFiles(
|
||||
[this, &cOptions] (std::shared_ptr<JSPandaFile> jsPandaFilePtr) {
|
||||
JSPandaFile *jsPandaFile = jsPandaFilePtr.get();
|
||||
BytecodeInfoCollector collector(&aotCompilationEnv_, jsPandaFile, profilerDecoder_, cOptions.maxAotMethodSize_,
|
||||
cOptions.isEnableCollectLiteralInfo_);
|
||||
BytecodeInfoCollector collector(&aotCompilationEnv_, jsPandaFile, profilerDecoder_,
|
||||
cOptions.maxAotMethodSize_);
|
||||
BCInfo &bytecodeInfo = collector.GetBytecodeInfo();
|
||||
const auto &methodPcInfos = bytecodeInfo.GetMethodPcInfos();
|
||||
auto &methodList = bytecodeInfo.GetMethodList();
|
||||
|
@ -49,7 +49,7 @@ private:
|
||||
};
|
||||
|
||||
struct CompilationOptions {
|
||||
explicit CompilationOptions(EcmaVM *vm, JSRuntimeOptions &runtimeOptions);
|
||||
explicit CompilationOptions(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_;
|
||||
@ -73,12 +73,10 @@ struct CompilationOptions {
|
||||
bool isEnableValueNumbering_;
|
||||
bool isEnableOptInlining_;
|
||||
bool isEnableOptString_;
|
||||
bool isEnableTypeInfer_;
|
||||
bool isEnableOptPGOType_;
|
||||
bool isEnableOptTrackField_;
|
||||
bool isEnableOptLoopPeeling_;
|
||||
bool isEnableOptLoopInvariantCodeMotion_;
|
||||
bool isEnableCollectLiteralInfo_;
|
||||
bool isEnableOptConstantFolding_;
|
||||
bool isEnableLexenvSpecialization_;
|
||||
bool isEnableNativeInline_;
|
||||
@ -111,8 +109,6 @@ public:
|
||||
|
||||
void AOTInitialize();
|
||||
|
||||
void SetShouldCollectLiteralInfo(CompilationOptions &cOptions, const CompilerLog *log);
|
||||
|
||||
uint32_t GenerateAbcFileInfos();
|
||||
|
||||
bool HandleMergedPgoFile(uint32_t checksum);
|
||||
|
@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "ecmascript/compiler/aot_file/an_file_data_manager.h"
|
||||
#include "ecmascript/compiler/aot_snapshot/snapshot_global_data.h"
|
||||
#include "ecmascript/js_file_path.h"
|
||||
#include "ecmascript/platform/file.h"
|
||||
|
||||
|
@ -49,6 +49,7 @@
|
||||
namespace panda::ecmascript {
|
||||
using CommonStubCSigns = kungfu::CommonStubCSigns;
|
||||
using BytecodeStubCSigns = kungfu::BytecodeStubCSigns;
|
||||
using SnapshotGlobalData = kungfu::SnapshotGlobalData;
|
||||
|
||||
void AOTFileManager::Iterate(const RootVisitor &v)
|
||||
{
|
||||
|
@ -16,12 +16,11 @@
|
||||
#include "ecmascript/compiler/aot_snapshot/aot_snapshot.h"
|
||||
|
||||
#include "ecmascript/common.h"
|
||||
#include "ecmascript/compiler/aot_snapshot/aot_snapshot_constants.h"
|
||||
#include "ecmascript/global_env_constants-inl.h"
|
||||
#include "ecmascript/jspandafile/program_object.h"
|
||||
#include "ecmascript/log_wrapper.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
#include "ecmascript/global_env_constants-inl.h"
|
||||
#include "ecmascript/compiler/aot_snapshot/aot_snapshot_constants.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
void AOTSnapshot::InitSnapshot(uint32_t compileFilesCount)
|
||||
|
@ -57,21 +57,6 @@ bool ArgumentAccessor::ArgGateNotExisted(const size_t currentVreg)
|
||||
return false;
|
||||
}
|
||||
|
||||
GateRef ArgumentAccessor::GetTypedArgGate(const size_t argIndex) const
|
||||
{
|
||||
if (argIndex == static_cast<size_t>(TypedArgIdx::FUNC)) {
|
||||
return GetCommonArgGate(CommonArgIdx::FUNC);
|
||||
}
|
||||
if (argIndex == static_cast<size_t>(TypedArgIdx::NEW_TARGET)) {
|
||||
return GetCommonArgGate(CommonArgIdx::NEW_TARGET);
|
||||
}
|
||||
if (argIndex == static_cast<size_t>(TypedArgIdx::THIS_OBJECT)) {
|
||||
return GetCommonArgGate(CommonArgIdx::THIS_OBJECT);
|
||||
}
|
||||
return args_.at(argIndex - static_cast<size_t>(TypedArgIdx::NUM_OF_TYPED_ARGS) +
|
||||
static_cast<size_t>(CommonArgIdx::NUM_OF_ARGS));
|
||||
}
|
||||
|
||||
GateRef ArgumentAccessor::GetCommonArgGate(const CommonArgIdx arg) const
|
||||
{
|
||||
return args_.at(static_cast<size_t>(arg));
|
||||
@ -117,21 +102,6 @@ size_t ArgumentAccessor::GetFunctionArgIndex(const size_t currentVreg, const boo
|
||||
return currentVreg - numCommonArgs + static_cast<size_t>(CommonArgIdx::NUM_OF_ARGS);
|
||||
}
|
||||
|
||||
void ArgumentAccessor::FillArgsGateType(const TypeRecorder *typeRecorder)
|
||||
{
|
||||
ASSERT(method_ != nullptr);
|
||||
GateAccessor gateAcc(circuit_);
|
||||
const size_t numOfTypedArgs = method_->GetNumArgsWithCallField() +
|
||||
static_cast<size_t>(TypedArgIdx::NUM_OF_TYPED_ARGS);
|
||||
for (uint32_t argIndex = 0; argIndex < numOfTypedArgs; argIndex++) {
|
||||
auto argType = typeRecorder->GetArgType(argIndex);
|
||||
if (!argType.IsAnyType()) {
|
||||
auto gate = GetTypedArgGate(argIndex);
|
||||
gateAcc.SetGateType(gate, argType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArgumentAccessor::CollectArgs()
|
||||
{
|
||||
if (args_.size() == 0) {
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "ecmascript/compiler/circuit.h"
|
||||
#include "ecmascript/compiler/gate.h"
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
#include "ecmascript/compiler/type_recorder.h"
|
||||
#include "ecmascript/method.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
@ -77,7 +76,6 @@ public:
|
||||
{
|
||||
return args_.size();
|
||||
}
|
||||
void FillArgsGateType(const TypeRecorder *typeRecorder);
|
||||
void CollectArgs();
|
||||
static size_t GetFixArgsNum()
|
||||
{
|
||||
@ -105,7 +103,6 @@ private:
|
||||
GateRef GetCommonArgGate(const CommonArgIdx arg) const;
|
||||
size_t GetFunctionArgIndex(const size_t currentVreg, const bool haveFunc,
|
||||
const bool haveNewTarget, const bool haveThis) const;
|
||||
GateRef GetTypedArgGate(const size_t argIndex) const;
|
||||
|
||||
Circuit *circuit_ {nullptr};
|
||||
const MethodLiteral *method_ {nullptr};
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
#include "ecmascript/deoptimizer/deoptimizer.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
#include "libpandafile/bytecode_instruction-inl.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
|
@ -15,12 +15,9 @@
|
||||
|
||||
#include "ecmascript/compiler/bytecode_info_collector.h"
|
||||
|
||||
#include "ecmascript/compiler/type_recorder.h"
|
||||
#include "ecmascript/interpreter/interpreter-inl.h"
|
||||
#include "ecmascript/jspandafile/type_literal_extractor.h"
|
||||
#include "ecmascript/module/module_path_helper.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
|
||||
#include "ecmascript/ts_types/ts_type_parser.h"
|
||||
#include "libpandafile/code_data_accessor.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
@ -32,51 +29,25 @@ static T *InitializeMemory(T *mem, Args... args)
|
||||
|
||||
BytecodeInfoCollector::BytecodeInfoCollector(CompilationEnv *env, JSPandaFile *jsPandaFile,
|
||||
PGOProfilerDecoder &pfDecoder,
|
||||
size_t maxAotMethodSize, bool enableCollectLiteralInfo)
|
||||
size_t maxAotMethodSize)
|
||||
: compilationEnv_(env),
|
||||
jsPandaFile_(jsPandaFile),
|
||||
bytecodeInfo_(maxAotMethodSize),
|
||||
pfDecoder_(pfDecoder),
|
||||
snapshotCPData_(new SnapshotConstantPoolData(env->GetEcmaVM(), jsPandaFile, &pfDecoder)),
|
||||
enableCollectLiteralInfo_(enableCollectLiteralInfo)
|
||||
snapshotCPData_(new SnapshotConstantPoolData(env->GetEcmaVM(), jsPandaFile, &pfDecoder))
|
||||
{
|
||||
compilationEnv_->GetTSManager()->SetBytecodeInfoCollector(this);
|
||||
ProcessClasses();
|
||||
ProcessEnvs();
|
||||
}
|
||||
|
||||
BytecodeInfoCollector::BytecodeInfoCollector(CompilationEnv *env, JSPandaFile *jsPandaFile,
|
||||
PGOProfilerDecoder &pfDecoder, bool enableCollectLiteralInfo)
|
||||
PGOProfilerDecoder &pfDecoder)
|
||||
: compilationEnv_(env),
|
||||
jsPandaFile_(jsPandaFile),
|
||||
bytecodeInfo_(1),
|
||||
pfDecoder_(pfDecoder),
|
||||
snapshotCPData_(nullptr), // jit no need
|
||||
enableCollectLiteralInfo_(enableCollectLiteralInfo)
|
||||
snapshotCPData_(nullptr) // jit no need
|
||||
{
|
||||
ProcessMethod();
|
||||
ProcessEnvs();
|
||||
}
|
||||
|
||||
BytecodeInfoCollector::~BytecodeInfoCollector()
|
||||
{
|
||||
if (envManager_ != nullptr) {
|
||||
delete envManager_;
|
||||
envManager_ = nullptr;
|
||||
}
|
||||
|
||||
if (compilationEnv_->IsAotCompiler()) {
|
||||
auto tsManager = compilationEnv_->GetTSManager();
|
||||
tsManager->PrintTypeInfo(jsPandaFile_);
|
||||
tsManager->SetBytecodeInfoCollector(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::ProcessEnvs()
|
||||
{
|
||||
if (envManager_ == nullptr) {
|
||||
envManager_ = new LexEnvManager(bytecodeInfo_);
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::ProcessClasses()
|
||||
@ -105,7 +76,6 @@ void BytecodeInfoCollector::ProcessClasses()
|
||||
&methodIndexes, &classConstructIndexes] (panda_file::MethodDataAccessor &mda) {
|
||||
auto methodId = mda.GetMethodId();
|
||||
methodIndexes.emplace_back(methodId);
|
||||
CollectFunctionTypeId(methodId);
|
||||
|
||||
// Generate all constpool
|
||||
compilationEnv_->FindOrCreateConstPool(jsPandaFile_, methodId);
|
||||
@ -134,14 +104,9 @@ void BytecodeInfoCollector::ProcessClasses()
|
||||
const uint8_t *insns = codeDataAccessor.GetInstructions();
|
||||
auto it = processedMethod.find(methodOffset);
|
||||
if (it == processedMethod.end()) {
|
||||
std::vector<std::string> classNameVec;
|
||||
CollectMethodPcsFromBC(codeSize, insns, methodLiteral, classNameVec,
|
||||
CollectMethodPcsFromBC(codeSize, insns, methodLiteral,
|
||||
recordName, methodOffset, classConstructIndexes);
|
||||
processedMethod[methodOffset] = std::make_pair(methodPcInfos.size() - 1, methodOffset);
|
||||
// collect className and literal offset for type infer
|
||||
if (EnableCollectLiteralInfo()) {
|
||||
CollectClassLiteralInfo(methodLiteral, classNameVec);
|
||||
}
|
||||
}
|
||||
|
||||
SetMethodPcInfoIndex(methodOffset, processedMethod[methodOffset]);
|
||||
@ -179,7 +144,6 @@ void BytecodeInfoCollector::ProcessMethod()
|
||||
const CString recordName = jsPandaFile_->GetRecordNameWithBundlePack(methodIdx);
|
||||
recordNames.emplace_back(recordName);
|
||||
auto methodId = mda.GetMethodId();
|
||||
CollectFunctionTypeId(methodId);
|
||||
|
||||
ASSERT(jsPandaFile_->IsNewVersion());
|
||||
|
||||
@ -192,12 +156,10 @@ void BytecodeInfoCollector::ProcessMethod()
|
||||
|
||||
std::map<uint32_t, std::pair<size_t, uint32_t>> processedMethod;
|
||||
std::vector<panda_file::File::EntityId> classConstructIndexes;
|
||||
std::vector<std::string> classNameVec;
|
||||
|
||||
CollectMethodPcsFromBC(codeSize, insns, methodLiteral, classNameVec,
|
||||
CollectMethodPcsFromBC(codeSize, insns, methodLiteral,
|
||||
recordName, methodOffset, classConstructIndexes);
|
||||
processedMethod[methodOffset] = std::make_pair(methodPcInfos.size() - 1, methodOffset);
|
||||
|
||||
SetMethodPcInfoIndex(methodOffset, processedMethod[methodOffset]);
|
||||
// class Construct need to use new target, can not fastcall
|
||||
if (methodLiteral->GetFunctionKind() == FunctionKind::CLASS_CONSTRUCTOR) {
|
||||
@ -206,90 +168,9 @@ void BytecodeInfoCollector::ProcessMethod()
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::CollectClassLiteralInfo(const MethodLiteral *method,
|
||||
const std::vector<std::string> &classNameVec)
|
||||
{
|
||||
std::vector<uint32_t> classOffsetVec;
|
||||
IterateLiteral(method, classOffsetVec);
|
||||
|
||||
if (classOffsetVec.size() == classNameVec.size()) {
|
||||
for (uint32_t i = 0; i < classOffsetVec.size(); i++) {
|
||||
compilationEnv_->GetTSManager()->AddElementToClassNameMap(
|
||||
jsPandaFile_, classOffsetVec[i], classNameVec[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::CollectFunctionTypeId(panda_file::File::EntityId fieldId)
|
||||
{
|
||||
uint32_t offset = fieldId.GetOffset();
|
||||
TypeAnnotationExtractor annoExtractor(jsPandaFile_, offset);
|
||||
uint32_t typeId = annoExtractor.GetMethodTypeOffset();
|
||||
if (typeId != 0) {
|
||||
bytecodeInfo_.SetFunctionTypeIDAndMethodOffset(typeId, offset);
|
||||
}
|
||||
if (annoExtractor.IsNamespace()) {
|
||||
MarkMethodNamespace(offset);
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::CollectInnerFuncType(const MethodLiteral *method, uint32_t innerMethodId, int32_t bcIndex)
|
||||
{
|
||||
auto &methodList = bytecodeInfo_.GetMethodList();
|
||||
auto methodId = method->GetMethodId().GetOffset();
|
||||
auto methodIter = methodList.find(methodId);
|
||||
if (methodIter == methodList.end()) {
|
||||
return;
|
||||
}
|
||||
TypeAnnotationExtractor annoExtractor(jsPandaFile_, innerMethodId);
|
||||
uint32_t innerFuncType = annoExtractor.GetMethodTypeOffset();
|
||||
if (innerFuncType != 0) {
|
||||
methodIter->second.AddBcToTypeId(bcIndex, innerFuncType);
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::IterateLiteral(const MethodLiteral *method,
|
||||
std::vector<uint32_t> &classOffsetVector)
|
||||
{
|
||||
panda_file::File::EntityId fieldId = method->GetMethodId();
|
||||
uint32_t defineMethodOffset = fieldId.GetOffset();
|
||||
TypeAnnotationExtractor annoExtractor(jsPandaFile_, defineMethodOffset);
|
||||
std::map<int32_t, uint32_t> offsetTypeMap;
|
||||
annoExtractor.EnumerateInstsAndTypes(
|
||||
[this, &offsetTypeMap, defineMethodOffset](const int32_t bcOffset, const uint32_t typeOffset) {
|
||||
if (classDefBCIndexes_.find(bcOffset) != classDefBCIndexes_.end() ||
|
||||
classDefBCIndexes_.find(bcOffset - 1) != classDefBCIndexes_.end()) { // for getter setter
|
||||
bytecodeInfo_.SetClassTypeOffsetAndDefMethod(typeOffset, defineMethodOffset);
|
||||
}
|
||||
if (bcOffset != TypeRecorder::METHOD_ANNOTATION_THIS_TYPE_OFFSET &&
|
||||
TSTypeParser::IsUserDefinedType(typeOffset)) {
|
||||
offsetTypeMap.insert(std::make_pair(bcOffset, typeOffset));
|
||||
}
|
||||
});
|
||||
|
||||
for (auto item : offsetTypeMap) {
|
||||
uint32_t typeOffset = item.second;
|
||||
StoreClassTypeOffset(typeOffset, classOffsetVector);
|
||||
}
|
||||
|
||||
classDefBCIndexes_.clear();
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::StoreClassTypeOffset(const uint32_t typeOffset, std::vector<uint32_t> &classOffsetVector)
|
||||
{
|
||||
TypeLiteralExtractor typeLiteralExtractor(jsPandaFile_, typeOffset);
|
||||
if (typeLiteralExtractor.GetTypeKind() != TSTypeKind::CLASS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (classOffsetVector.empty() || typeOffset != classOffsetVector.back()) {
|
||||
classOffsetVector.emplace_back(typeOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::CollectMethodPcsFromBC(const uint32_t insSz, const uint8_t *insArr,
|
||||
MethodLiteral *method, std::vector<std::string> &classNameVec, const CString &recordName,
|
||||
uint32_t methodOffset, std::vector<panda_file::File::EntityId> &classConstructIndexes)
|
||||
MethodLiteral *method, const CString &recordName, uint32_t methodOffset,
|
||||
std::vector<panda_file::File::EntityId> &classConstructIndexes)
|
||||
{
|
||||
auto bcIns = BytecodeInst(insArr);
|
||||
auto bcInsLast = bcIns.JumpTo(insSz);
|
||||
@ -304,7 +185,7 @@ void BytecodeInfoCollector::CollectMethodPcsFromBC(const uint32_t insSz, const u
|
||||
|
||||
while (bcIns.GetAddress() != bcInsLast.GetAddress()) {
|
||||
bool fastCallFlag = true;
|
||||
CollectMethodInfoFromBC(bcIns, method, classNameVec, bcIndex, classConstructIndexes, &fastCallFlag);
|
||||
CollectMethodInfoFromBC(bcIns, method, bcIndex, classConstructIndexes, &fastCallFlag);
|
||||
if (!fastCallFlag) {
|
||||
canFastCall = false;
|
||||
}
|
||||
@ -338,8 +219,6 @@ void BytecodeInfoCollector::SetMethodPcInfoIndex(uint32_t methodOffset,
|
||||
{
|
||||
auto processedMethodPcInfoIndex = processedMethodInfo.first;
|
||||
auto processedMethodOffset = processedMethodInfo.second;
|
||||
uint32_t numOfLexVars = 0;
|
||||
LexicalEnvStatus status = LexicalEnvStatus::VIRTUAL_LEXENV;
|
||||
auto &methodList = bytecodeInfo_.GetMethodList();
|
||||
std::set<uint32_t> indexSet{};
|
||||
// Methods with the same instructions in abc files have the same static information. Since
|
||||
@ -348,8 +227,6 @@ void BytecodeInfoCollector::SetMethodPcInfoIndex(uint32_t methodOffset,
|
||||
auto processedIter = methodList.find(processedMethodOffset);
|
||||
if (processedIter != methodList.end()) {
|
||||
const MethodInfo &processedMethod = processedIter->second;
|
||||
numOfLexVars = processedMethod.GetNumOfLexVars();
|
||||
status = processedMethod.GetLexEnvStatus();
|
||||
indexSet = processedMethod.GetImportIndexes();
|
||||
}
|
||||
|
||||
@ -357,14 +234,12 @@ void BytecodeInfoCollector::SetMethodPcInfoIndex(uint32_t methodOffset,
|
||||
if (iter != methodList.end()) {
|
||||
MethodInfo &methodInfo = iter->second;
|
||||
methodInfo.SetMethodPcInfoIndex(processedMethodPcInfoIndex);
|
||||
methodInfo.SetNumOfLexVars(numOfLexVars);
|
||||
methodInfo.SetLexEnvStatus(status);
|
||||
// if these methods have the same bytecode, their import indexs must be the same.
|
||||
methodInfo.CopyImportIndex(indexSet);
|
||||
return;
|
||||
}
|
||||
MethodInfo info(GetMethodInfoID(), processedMethodPcInfoIndex, LexEnv::DEFAULT_ROOT,
|
||||
MethodInfo::DEFAULT_OUTMETHOD_OFFSET, numOfLexVars, status);
|
||||
MethodInfo info(GetMethodInfoID(), processedMethodPcInfoIndex,
|
||||
MethodInfo::DEFAULT_OUTMETHOD_OFFSET);
|
||||
info.CopyImportIndex(indexSet);
|
||||
methodList.emplace(methodOffset, info);
|
||||
}
|
||||
@ -388,7 +263,7 @@ void BytecodeInfoCollector::CollectInnerMethods(uint32_t methodId, uint32_t inne
|
||||
methodInfo.AddInnerMethod(innerMethodOffset, isConstructor);
|
||||
} else {
|
||||
methodInfoId = GetMethodInfoID();
|
||||
MethodInfo info(methodInfoId, 0, LexEnv::DEFAULT_ROOT);
|
||||
MethodInfo info(methodInfoId, 0);
|
||||
methodList.emplace(methodId, info);
|
||||
methodList.at(methodId).AddInnerMethod(innerMethodOffset, isConstructor);
|
||||
}
|
||||
@ -403,20 +278,6 @@ void BytecodeInfoCollector::CollectInnerMethods(uint32_t methodId, uint32_t inne
|
||||
methodList.emplace(innerMethodOffset, innerInfo);
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::MarkMethodNamespace(const uint32_t methodOffset)
|
||||
{
|
||||
auto &methodList = bytecodeInfo_.GetMethodList();
|
||||
auto iter = methodList.find(methodOffset);
|
||||
if (iter != methodList.end()) {
|
||||
MethodInfo &methodInfo = iter->second;
|
||||
methodInfo.MarkMethodNamespace();
|
||||
return;
|
||||
}
|
||||
MethodInfo info(GetMethodInfoID(), 0, LexEnv::DEFAULT_ROOT, MethodInfo::DEFAULT_OUTMETHOD_OFFSET,
|
||||
0, LexicalEnvStatus::VIRTUAL_LEXENV, true);
|
||||
methodList.emplace(methodOffset, info);
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::CollectInnerMethodsFromLiteral(const MethodLiteral *method, uint64_t index)
|
||||
{
|
||||
std::vector<uint32_t> methodOffsets;
|
||||
@ -426,22 +287,6 @@ void BytecodeInfoCollector::CollectInnerMethodsFromLiteral(const MethodLiteral *
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::NewLexEnvWithSize(const MethodLiteral *method, uint64_t numOfLexVars)
|
||||
{
|
||||
auto &methodList = bytecodeInfo_.GetMethodList();
|
||||
auto methodOffset = method->GetMethodId().GetOffset();
|
||||
auto iter = methodList.find(methodOffset);
|
||||
if (iter != methodList.end()) {
|
||||
MethodInfo &methodInfo = iter->second;
|
||||
methodInfo.SetNumOfLexVars(numOfLexVars);
|
||||
methodInfo.SetLexEnvStatus(LexicalEnvStatus::REALITY_LEXENV);
|
||||
return;
|
||||
}
|
||||
MethodInfo info(GetMethodInfoID(), 0, LexEnv::DEFAULT_ROOT, MethodInfo::DEFAULT_OUTMETHOD_OFFSET,
|
||||
numOfLexVars, LexicalEnvStatus::REALITY_LEXENV);
|
||||
methodList.emplace(methodOffset, info);
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::CollectInnerMethodsFromNewLiteral(const MethodLiteral *method,
|
||||
panda_file::File::EntityId literalId)
|
||||
{
|
||||
@ -452,9 +297,8 @@ void BytecodeInfoCollector::CollectInnerMethodsFromNewLiteral(const MethodLitera
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::CollectMethodInfoFromBC(const BytecodeInstruction &bcIns,
|
||||
const MethodLiteral *method, std::vector<std::string> &classNameVec, int32_t bcIndex,
|
||||
std::vector<panda_file::File::EntityId> &classConstructIndexes, bool *canFastCall)
|
||||
void BytecodeInfoCollector::CollectMethodInfoFromBC(const BytecodeInstruction &bcIns, const MethodLiteral *method,
|
||||
int32_t bcIndex, std::vector<panda_file::File::EntityId> &classConstructIndexes, bool *canFastCall)
|
||||
{
|
||||
if (!(bcIns.HasFlag(BytecodeInstruction::Flags::STRING_ID) &&
|
||||
BytecodeInstruction::HasId(BytecodeInstruction::GetFormat(bcIns.GetOpcode()), 0))) {
|
||||
@ -466,7 +310,6 @@ void BytecodeInfoCollector::CollectMethodInfoFromBC(const BytecodeInstruction &b
|
||||
methodId = jsPandaFile_->ResolveMethodIndex(method->GetMethodId(),
|
||||
static_cast<uint16_t>(bcIns.GetId().AsRawValue())).GetOffset();
|
||||
CollectInnerMethods(method, methodId);
|
||||
CollectInnerFuncType(method, methodId, bcIndex);
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM8_ID16_IMM8:
|
||||
@ -480,7 +323,6 @@ void BytecodeInfoCollector::CollectMethodInfoFromBC(const BytecodeInstruction &b
|
||||
auto entityId = jsPandaFile_->ResolveMethodIndex(method->GetMethodId(),
|
||||
(bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 0>()).AsRawValue());
|
||||
classConstructIndexes.emplace_back(entityId);
|
||||
classNameVec.emplace_back(GetClassName(entityId));
|
||||
classDefBCIndexes_.insert(bcIndex);
|
||||
methodId = entityId.GetOffset();
|
||||
CollectInnerMethods(method, methodId, true);
|
||||
@ -493,7 +335,6 @@ void BytecodeInfoCollector::CollectMethodInfoFromBC(const BytecodeInstruction &b
|
||||
auto entityId = jsPandaFile_->ResolveMethodIndex(method->GetMethodId(),
|
||||
(bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 0>()).AsRawValue());
|
||||
classConstructIndexes.emplace_back(entityId);
|
||||
classNameVec.emplace_back(GetClassName(entityId));
|
||||
classDefBCIndexes_.insert(bcIndex);
|
||||
methodId = entityId.GetOffset();
|
||||
CollectInnerMethods(method, methodId, true);
|
||||
@ -526,26 +367,6 @@ void BytecodeInfoCollector::CollectMethodInfoFromBC(const BytecodeInstruction &b
|
||||
CollectInnerMethodsFromLiteral(method, imm);
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Opcode::NEWLEXENV_IMM8: {
|
||||
auto imm = bcIns.GetImm<BytecodeInstruction::Format::IMM8>();
|
||||
NewLexEnvWithSize(method, imm);
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Opcode::NEWLEXENVWITHNAME_IMM8_ID16: {
|
||||
auto imm = bcIns.GetImm<BytecodeInstruction::Format::IMM8_ID16>();
|
||||
NewLexEnvWithSize(method, imm);
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Opcode::WIDE_NEWLEXENV_PREF_IMM16: {
|
||||
auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_IMM16>();
|
||||
NewLexEnvWithSize(method, imm);
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Opcode::WIDE_NEWLEXENVWITHNAME_PREF_IMM16_ID16: {
|
||||
auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_IMM16_ID16>();
|
||||
NewLexEnvWithSize(method, imm);
|
||||
break;
|
||||
}
|
||||
case EcmaOpcode::RESUMEGENERATOR:
|
||||
case EcmaOpcode::SUSPENDGENERATOR_V8:
|
||||
case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8:
|
||||
@ -616,7 +437,7 @@ void BytecodeInfoCollector::CollectImportIndexs(uint32_t methodOffset, uint32_t
|
||||
methodInfo.AddImportIndex(index);
|
||||
return;
|
||||
}
|
||||
MethodInfo info(GetMethodInfoID(), 0, LexEnv::DEFAULT_ROOT);
|
||||
MethodInfo info(GetMethodInfoID(), 0);
|
||||
info.AddImportIndex(index);
|
||||
methodList.emplace(methodOffset, info);
|
||||
}
|
||||
@ -653,40 +474,7 @@ void BytecodeInfoCollector::CollectExportIndexs(const CString &recordName, uint3
|
||||
exportName = localName;
|
||||
}
|
||||
|
||||
JSHandle<EcmaString> exportNameStr(thread, EcmaString::Cast(exportName->GetTaggedObject()));
|
||||
// In order to reduce redundant compilation, when a export element satisfies one of the following conditions,
|
||||
// it will be added to the ExportRecordInfo of this record.
|
||||
// 1) its name is not recorded in exportTypeTable, or
|
||||
// 2) its type is classType or any.
|
||||
if (!CheckExportNameAndClassType(recordName, exportNameStr)) {
|
||||
bytecodeInfo_.AddExportIndexToRecord(recordName, index);
|
||||
}
|
||||
}
|
||||
|
||||
bool BytecodeInfoCollector::CheckExportNameAndClassType(const CString &recordName,
|
||||
const JSHandle<EcmaString> &exportStr)
|
||||
{
|
||||
ASSERT(compilationEnv_->IsAotCompiler());
|
||||
auto tsManager = compilationEnv_->GetTSManager();
|
||||
JSHandle<TaggedArray> exportTypeTable = tsManager->GetExportTableFromLiteral(jsPandaFile_, recordName);
|
||||
uint32_t length = exportTypeTable->GetLength();
|
||||
for (uint32_t i = 0; i < length; i = i + 2) { // 2: skip a pair of key and value
|
||||
EcmaString *valueString = EcmaString::Cast(exportTypeTable->Get(i).GetTaggedObject());
|
||||
if (!EcmaStringAccessor::StringsAreEqual(*exportStr, valueString)) {
|
||||
continue;
|
||||
}
|
||||
uint32_t typeId = static_cast<uint32_t>(exportTypeTable->Get(i + 1).GetInt());
|
||||
if (TSTypeParser::IsUserDefinedType(typeId)) {
|
||||
TypeLiteralExtractor typeExtractor(jsPandaFile_, typeId);
|
||||
if (typeExtractor.GetTypeKind() == TSTypeKind::CLASS) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (typeId != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
bytecodeInfo_.AddExportIndexToRecord(recordName, index);
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::CollectRecordReferenceREL()
|
||||
@ -778,45 +566,4 @@ void BytecodeInfoCollector::RearrangeInnerMethods()
|
||||
methodInfo.RearrangeInnerMethods();
|
||||
}
|
||||
}
|
||||
|
||||
LexEnvManager::LexEnvManager(BCInfo &bcInfo)
|
||||
: lexEnvs_(bcInfo.GetMethodList().size())
|
||||
{
|
||||
const auto &methodList = bcInfo.GetMethodList();
|
||||
for (const auto &it : methodList) {
|
||||
const MethodInfo &methodInfo = it.second;
|
||||
lexEnvs_[methodInfo.GetMethodInfoIndex()].Inilialize(methodInfo.GetOutMethodId(),
|
||||
methodInfo.GetNumOfLexVars(),
|
||||
methodInfo.GetLexEnvStatus());
|
||||
}
|
||||
}
|
||||
|
||||
void LexEnvManager::SetLexEnvElementType(uint32_t methodId, uint32_t level, uint32_t slot, const GateType &type)
|
||||
{
|
||||
uint32_t offset = GetTargetLexEnv(methodId, level);
|
||||
lexEnvs_[offset].SetLexVarType(slot, type);
|
||||
}
|
||||
|
||||
GateType LexEnvManager::GetLexEnvElementType(uint32_t methodId, uint32_t level, uint32_t slot) const
|
||||
{
|
||||
uint32_t offset = GetTargetLexEnv(methodId, level);
|
||||
return lexEnvs_[offset].GetLexVarType(slot);
|
||||
}
|
||||
|
||||
uint32_t LexEnvManager::GetTargetLexEnv(uint32_t methodId, uint32_t level) const
|
||||
{
|
||||
auto offset = methodId;
|
||||
auto status = GetLexEnvStatus(offset);
|
||||
while (!HasDefaultRoot(offset) && ((level > 0) || (status != LexicalEnvStatus::REALITY_LEXENV))) {
|
||||
offset = GetOutMethodId(offset);
|
||||
if (HasDefaultRoot(offset)) {
|
||||
break;
|
||||
}
|
||||
if (status == LexicalEnvStatus::REALITY_LEXENV && level != 0) {
|
||||
--level;
|
||||
}
|
||||
status = GetLexEnvStatus(offset);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -25,90 +25,8 @@
|
||||
#include "libpandafile/bytecode_instruction-inl.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
/* ts source code
|
||||
* let a:number = 1;
|
||||
* function f() {
|
||||
* let b:number = 1;
|
||||
* function g() {
|
||||
* return a + b;
|
||||
* }
|
||||
* return g();
|
||||
* }
|
||||
*
|
||||
* The structure of Lexical Environment
|
||||
*
|
||||
* Lexical Environment Lexical Environment
|
||||
* Global Environment of function f of function g
|
||||
* +-------------------+ <----+ +-------------------+ <----+ +-------------------+
|
||||
* null <----| Outer Reference | +----| Outer Reference | +----| Outer Reference |
|
||||
* +-------------------+ +-------------------+ +-------------------+
|
||||
* |Environment Recoder| |Environment Recoder| |Environment Recoder|
|
||||
* +-------------------+ +-------------------+ +-------------------+
|
||||
*
|
||||
* We only record the type of the variable in Environment Recoder.
|
||||
* In the design of the Ark bytecode, if a method does not have any
|
||||
* lex-env variable in its Lexical Environment, then there will be
|
||||
* no EcmaOpcode::NEWLEXENV in it which leads to ARK runtime will
|
||||
* not create a Lexical Environment when the method is executed.
|
||||
* In order to simulate the state of the runtime as much as possible,
|
||||
* a field named 'status' will be added into the class LexEnv to
|
||||
* measure this state. Take the above code as an example, although in
|
||||
* static analysis, we will create LexEnv for each method, only Lexenvs
|
||||
* of global and function f will be created when methods are executed.
|
||||
*/
|
||||
|
||||
using PGOProfilerDecoder = pgo::PGOProfilerDecoder;
|
||||
|
||||
enum class LexicalEnvStatus : uint8_t {
|
||||
VIRTUAL_LEXENV,
|
||||
REALITY_LEXENV
|
||||
};
|
||||
|
||||
class LexEnv {
|
||||
public:
|
||||
LexEnv() = default;
|
||||
~LexEnv() = default;
|
||||
|
||||
static constexpr uint32_t DEFAULT_ROOT = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
inline void Inilialize(uint32_t outMethodId, uint32_t numOfLexVars, LexicalEnvStatus status)
|
||||
{
|
||||
outerMethodId_ = outMethodId;
|
||||
lexVarTypes_.resize(numOfLexVars, GateType::AnyType());
|
||||
status_ = status;
|
||||
}
|
||||
|
||||
inline uint32_t GetOutMethodId() const
|
||||
{
|
||||
return outerMethodId_;
|
||||
}
|
||||
|
||||
inline LexicalEnvStatus GetLexEnvStatus() const
|
||||
{
|
||||
return status_;
|
||||
}
|
||||
|
||||
inline GateType GetLexVarType(uint32_t slot) const
|
||||
{
|
||||
if (slot < lexVarTypes_.size()) {
|
||||
return lexVarTypes_[slot];
|
||||
}
|
||||
return GateType::AnyType();
|
||||
}
|
||||
|
||||
inline void SetLexVarType(uint32_t slot, const GateType &type)
|
||||
{
|
||||
if (slot < lexVarTypes_.size()) {
|
||||
lexVarTypes_[slot] = type;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t outerMethodId_ { DEFAULT_ROOT };
|
||||
std::vector<GateType> lexVarTypes_ {};
|
||||
LexicalEnvStatus status_ { LexicalEnvStatus::VIRTUAL_LEXENV };
|
||||
};
|
||||
|
||||
// each method in the abc file corresponds to one MethodInfo and
|
||||
// methods with the same instructions share one common MethodPcInfo
|
||||
struct MethodPcInfo {
|
||||
@ -193,17 +111,17 @@ private:
|
||||
|
||||
class MethodInfo {
|
||||
public:
|
||||
MethodInfo(uint32_t methodInfoIndex, uint32_t methodPcInfoIndex, uint32_t outMethodIdx,
|
||||
uint32_t outMethodOffset = MethodInfo::DEFAULT_OUTMETHOD_OFFSET, uint32_t num = 0,
|
||||
LexicalEnvStatus lexEnvStatus = LexicalEnvStatus::VIRTUAL_LEXENV, bool isNamespace = false)
|
||||
MethodInfo(uint32_t methodInfoIndex, uint32_t methodPcInfoIndex, uint32_t outMethodIdx = MethodInfo::DEFAULT_ROOT,
|
||||
uint32_t outMethodOffset = MethodInfo::DEFAULT_OUTMETHOD_OFFSET)
|
||||
: methodInfoIndex_(methodInfoIndex), methodPcInfoIndex_(methodPcInfoIndex), outerMethodId_(outMethodIdx),
|
||||
outerMethodOffset_(outMethodOffset), numOfLexVars_(num), status_(lexEnvStatus), isNamespace_(isNamespace)
|
||||
outerMethodOffset_(outMethodOffset)
|
||||
{
|
||||
}
|
||||
|
||||
~MethodInfo() = default;
|
||||
|
||||
static constexpr uint32_t DEFAULT_OUTMETHOD_OFFSET = 0;
|
||||
static constexpr uint32_t DEFAULT_ROOT = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
inline uint32_t GetOutMethodId() const
|
||||
{
|
||||
@ -225,28 +143,6 @@ public:
|
||||
outerMethodOffset_ = outMethodOffset;
|
||||
}
|
||||
|
||||
inline uint32_t GetNumOfLexVars() const
|
||||
{
|
||||
return numOfLexVars_;
|
||||
}
|
||||
|
||||
inline void SetNumOfLexVars(uint32_t numOfLexVars)
|
||||
{
|
||||
if (numOfLexVars > numOfLexVars_) {
|
||||
numOfLexVars_ = numOfLexVars;
|
||||
}
|
||||
}
|
||||
|
||||
inline LexicalEnvStatus GetLexEnvStatus() const
|
||||
{
|
||||
return status_;
|
||||
}
|
||||
|
||||
inline void SetLexEnvStatus(LexicalEnvStatus status)
|
||||
{
|
||||
status_ = status;
|
||||
}
|
||||
|
||||
inline uint32_t GetMethodPcInfoIndex() const
|
||||
{
|
||||
return methodPcInfoIndex_;
|
||||
@ -291,16 +187,6 @@ public:
|
||||
return bcToFuncTypeId_;
|
||||
}
|
||||
|
||||
inline void MarkMethodNamespace()
|
||||
{
|
||||
isNamespace_ = true;
|
||||
}
|
||||
|
||||
inline bool IsNamespace() const
|
||||
{
|
||||
return isNamespace_;
|
||||
}
|
||||
|
||||
inline const std::vector<uint32_t> &GetInnerMethods() const
|
||||
{
|
||||
return innerMethods_;
|
||||
@ -387,13 +273,10 @@ private:
|
||||
std::vector<uint32_t> innerMethods_ {};
|
||||
std::vector<uint32_t> constructorMethods_ {};
|
||||
std::unordered_map<int32_t, uint32_t> bcToFuncTypeId_ {};
|
||||
uint32_t outerMethodId_ { LexEnv::DEFAULT_ROOT };
|
||||
uint32_t outerMethodId_ { MethodInfo::DEFAULT_ROOT };
|
||||
uint32_t outerMethodOffset_ { MethodInfo::DEFAULT_OUTMETHOD_OFFSET };
|
||||
uint32_t numOfLexVars_ { 0 };
|
||||
LexicalEnvStatus status_ { LexicalEnvStatus::VIRTUAL_LEXENV };
|
||||
std::set<uint32_t> importIndex_ {};
|
||||
CompileStateBit compileState_ { 0 };
|
||||
bool isNamespace_ {false};
|
||||
};
|
||||
|
||||
struct FastCallInfo {
|
||||
@ -625,54 +508,18 @@ private:
|
||||
std::unordered_map<uint32_t, FastCallInfo> methodOffsetToFastCallInfos_ {};
|
||||
};
|
||||
|
||||
class LexEnvManager {
|
||||
public:
|
||||
explicit LexEnvManager(BCInfo &bcInfo);
|
||||
~LexEnvManager() = default;
|
||||
NO_COPY_SEMANTIC(LexEnvManager);
|
||||
NO_MOVE_SEMANTIC(LexEnvManager);
|
||||
|
||||
void SetLexEnvElementType(uint32_t methodId, uint32_t level, uint32_t slot, const GateType &type);
|
||||
GateType GetLexEnvElementType(uint32_t methodId, uint32_t level, uint32_t slot) const;
|
||||
|
||||
private:
|
||||
uint32_t GetTargetLexEnv(uint32_t methodId, uint32_t level) const;
|
||||
|
||||
inline uint32_t GetOutMethodId(uint32_t methodId) const
|
||||
{
|
||||
return lexEnvs_[methodId].GetOutMethodId();
|
||||
}
|
||||
|
||||
inline LexicalEnvStatus GetLexEnvStatus(uint32_t methodId) const
|
||||
{
|
||||
return lexEnvs_[methodId].GetLexEnvStatus();
|
||||
}
|
||||
|
||||
inline bool HasDefaultRoot(uint32_t methodId) const
|
||||
{
|
||||
return GetOutMethodId(methodId) == LexEnv::DEFAULT_ROOT;
|
||||
}
|
||||
|
||||
std::vector<LexEnv> lexEnvs_ {};
|
||||
};
|
||||
|
||||
class BytecodeInfoCollector {
|
||||
public:
|
||||
BytecodeInfoCollector(CompilationEnv *env, JSPandaFile *jsPandaFile, PGOProfilerDecoder &pfDecoder,
|
||||
size_t maxAotMethodSize, bool enableCollectLiteralInfo);
|
||||
size_t maxAotMethodSize);
|
||||
|
||||
BytecodeInfoCollector(CompilationEnv *env, JSPandaFile *jsPandaFile,
|
||||
PGOProfilerDecoder &pfDecoder, bool enableCollectLiteralInfo);
|
||||
PGOProfilerDecoder &pfDecoder);
|
||||
|
||||
~BytecodeInfoCollector();
|
||||
~BytecodeInfoCollector() = default;;
|
||||
NO_COPY_SEMANTIC(BytecodeInfoCollector);
|
||||
NO_MOVE_SEMANTIC(BytecodeInfoCollector);
|
||||
|
||||
bool EnableCollectLiteralInfo() const
|
||||
{
|
||||
return enableCollectLiteralInfo_;
|
||||
}
|
||||
|
||||
Bytecodes* GetByteCodes()
|
||||
{
|
||||
return &bytecodes_;
|
||||
@ -729,11 +576,6 @@ public:
|
||||
return compilationEnv_;
|
||||
}
|
||||
|
||||
LexEnvManager* GetEnvManager() const
|
||||
{
|
||||
return envManager_;
|
||||
}
|
||||
|
||||
template <class Callback>
|
||||
void IterateAllMethods(const Callback &cb)
|
||||
{
|
||||
@ -745,54 +587,34 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void ProcessEnvs();
|
||||
|
||||
inline size_t GetMethodInfoID()
|
||||
{
|
||||
return methodInfoIndex_++;
|
||||
}
|
||||
|
||||
inline std::string GetClassName(const EntityId entityId)
|
||||
{
|
||||
std::string className(MethodLiteral::GetMethodName(jsPandaFile_, entityId));
|
||||
if (LIKELY(className.find('#') != std::string::npos)) {
|
||||
size_t poiIndex = className.find_last_of('#');
|
||||
className = className.substr(poiIndex + 1);
|
||||
}
|
||||
return className;
|
||||
}
|
||||
|
||||
const CString GetEntryFunName(const std::string_view &entryPoint) const;
|
||||
void ProcessClasses();
|
||||
void ProcessMethod();
|
||||
void RearrangeInnerMethods();
|
||||
void CollectMethodPcsFromBC(const uint32_t insSz, const uint8_t *insArr,
|
||||
MethodLiteral *method, std::vector<std::string> &classNameVec, const CString &recordName,
|
||||
uint32_t methodOffset, std::vector<panda_file::File::EntityId> &classConstructIndexes);
|
||||
MethodLiteral *method, const CString &recordName, uint32_t methodOffset,
|
||||
std::vector<panda_file::File::EntityId> &classConstructIndexes);
|
||||
void SetMethodPcInfoIndex(uint32_t methodOffset, const std::pair<size_t, uint32_t> &processedMethodInfo);
|
||||
void CollectInnerMethods(const MethodLiteral *method, uint32_t innerMethodOffset, bool isConstructor = false);
|
||||
void CollectInnerMethods(uint32_t methodId, uint32_t innerMethodOffset, bool isConstructor = false);
|
||||
void CollectInnerMethodsFromLiteral(const MethodLiteral *method, uint64_t index);
|
||||
void CollectInnerFuncType(const MethodLiteral *method, uint32_t innerMethodOffset, int32_t bcIndex);
|
||||
void NewLexEnvWithSize(const MethodLiteral *method, uint64_t numOfLexVars);
|
||||
void CollectInnerMethodsFromNewLiteral(const MethodLiteral *method, panda_file::File::EntityId literalId);
|
||||
void CollectMethodInfoFromBC(const BytecodeInstruction &bcIns, const MethodLiteral *method,
|
||||
std::vector<std::string> &classNameVec, int32_t bcIndex,
|
||||
std::vector<panda_file::File::EntityId> &classConstructIndexes,
|
||||
bool *canFastCall);
|
||||
void CollectMethodInfoFromBC(const BytecodeInstruction &bcIns, const MethodLiteral *method, int32_t bcIndex,
|
||||
std::vector<panda_file::File::EntityId> &classConstructIndexes, bool *canFastCall);
|
||||
void CollectModuleInfoFromBC(const BytecodeInstruction &bcIns, const MethodLiteral *method,
|
||||
const CString &recordName);
|
||||
void IterateLiteral(const MethodLiteral *method, std::vector<uint32_t> &classOffsetVector);
|
||||
void StoreClassTypeOffset(const uint32_t typeOffset, std::vector<uint32_t> &classOffsetVector);
|
||||
void CollectClassLiteralInfo(const MethodLiteral *method, const std::vector<std::string> &classNameVec);
|
||||
void CollectFunctionTypeId(panda_file::File::EntityId fieldId);
|
||||
void CollectImportIndexs(uint32_t methodOffset, uint32_t index);
|
||||
void CollectExportIndexs(const CString &recordName, uint32_t index);
|
||||
bool CheckExportNameAndClassType(const CString &recordName, const JSHandle<EcmaString> &exportStr);
|
||||
void CollectRecordReferenceREL();
|
||||
void CollectRecordImportInfo(const CString &recordName);
|
||||
void CollectRecordExportInfo(const CString &recordName);
|
||||
void MarkMethodNamespace(const uint32_t methodOffset);
|
||||
|
||||
CompilationEnv *compilationEnv_ {nullptr};
|
||||
JSPandaFile *jsPandaFile_ {nullptr};
|
||||
@ -801,9 +623,7 @@ private:
|
||||
PGOBCInfo pgoBCInfo_ {};
|
||||
std::unique_ptr<SnapshotConstantPoolData> snapshotCPData_;
|
||||
size_t methodInfoIndex_ {0};
|
||||
bool enableCollectLiteralInfo_ {false};
|
||||
std::set<int32_t> classDefBCIndexes_ {};
|
||||
LexEnvManager* envManager_ {nullptr};
|
||||
Bytecodes bytecodes_;
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "ecmascript/compiler/rt_call_signature.h"
|
||||
#include "ecmascript/deoptimizer/deoptimizer.h"
|
||||
#include "ecmascript/frames.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
#include "ecmascript/js_thread.h"
|
||||
#include "ecmascript/method.h"
|
||||
#include "triple.h"
|
||||
|
@ -14,9 +14,10 @@
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/compilation_driver.h"
|
||||
|
||||
#include "ecmascript/compiler/file_generators.h"
|
||||
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
|
||||
#include "ecmascript/jspandafile/method_literal.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
CompilationDriver::CompilationDriver(PGOProfilerDecoder &profilerDecoder,
|
||||
@ -45,10 +46,6 @@ CompilationDriver::CompilationDriver(PGOProfilerDecoder &profilerDecoder,
|
||||
maxMethodsInModule_(maxMethodsInModule),
|
||||
optionMethodsRange_(compilerMethodsRange)
|
||||
{
|
||||
if (compilationEnv_->IsAotCompiler()) {
|
||||
compilationEnv_->GetTSManager()->SetCompilationDriver(this);
|
||||
}
|
||||
|
||||
if (!optionSelectMethods.empty() && !optionSkipMethods.empty()) {
|
||||
LOG_COMPILER(FATAL) <<
|
||||
"--compiler-select-methods and --compiler-skip-methods should not be set at the same time";
|
||||
@ -63,13 +60,6 @@ CompilationDriver::CompilationDriver(PGOProfilerDecoder &profilerDecoder,
|
||||
}
|
||||
}
|
||||
|
||||
CompilationDriver::~CompilationDriver()
|
||||
{
|
||||
if (compilationEnv_->IsAotCompiler()) {
|
||||
compilationEnv_->GetTSManager()->SetCompilationDriver(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
Module *CompilationDriver::GetModule()
|
||||
{
|
||||
return IsCurModuleFull() ? fileGenerator_->AddModule(fileName_, triple_, *lOptions_, outputAsm_)
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
bool outputAsm,
|
||||
size_t maxMethodsInModule,
|
||||
const std::pair<uint32_t, uint32_t> &compilerMethodsRange);
|
||||
virtual ~CompilationDriver();
|
||||
~CompilationDriver() = default;
|
||||
|
||||
NO_COPY_SEMANTIC(CompilationDriver);
|
||||
NO_MOVE_SEMANTIC(CompilationDriver);
|
||||
|
@ -15,12 +15,11 @@
|
||||
#include "ecmascript/compiler/compilation_env.h"
|
||||
#include "ecmascript/ecma_context.h"
|
||||
#include "ecmascript/jspandafile/program_object.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
CompilationEnv::CompilationEnv(EcmaVM *vm) : vm_(vm), thread_(vm_->GetJSThread()),
|
||||
tsManager_(nullptr), ptManager_(nullptr) { }
|
||||
ptManager_(nullptr) { }
|
||||
|
||||
NativeAreaAllocator *CompilationEnv::GetNativeAreaAllocator() const
|
||||
{
|
||||
|
@ -24,7 +24,6 @@ namespace panda::ecmascript {
|
||||
namespace kungfu {
|
||||
class PGOTypeManager;
|
||||
};
|
||||
class TSManager;
|
||||
class ConstantPool;
|
||||
namespace pgo {
|
||||
class PGOProfiler;
|
||||
@ -56,11 +55,6 @@ public:
|
||||
return ptManager_;
|
||||
}
|
||||
|
||||
TSManager *GetTSManager() const
|
||||
{
|
||||
return tsManager_;
|
||||
}
|
||||
|
||||
NativeAreaAllocator *GetNativeAreaAllocator() const;
|
||||
virtual JSRuntimeOptions &GetJSOptions() = 0;
|
||||
virtual std::shared_ptr<pgo::PGOProfiler> GetPGOProfiler() const;
|
||||
@ -124,7 +118,6 @@ public:
|
||||
protected:
|
||||
EcmaVM *vm_ {nullptr};
|
||||
JSThread *thread_ {nullptr};
|
||||
TSManager *tsManager_ {nullptr};
|
||||
kungfu::PGOTypeManager *ptManager_ {nullptr};
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "ecmascript/common.h"
|
||||
#include "ecmascript/compiler/aot_file/aot_file_manager.h"
|
||||
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
|
||||
#include "ecmascript/platform/code_sign.h"
|
||||
#include "ecmascript/platform/directory.h"
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "ecmascript/compiler/codegen/llvm/llvm_ir_builder.h"
|
||||
#include "ecmascript/compiler/compiler_log.h"
|
||||
#include "ecmascript/compiler/ir_module.h"
|
||||
#include "ecmascript/compiler/jit_compilation_env.h"
|
||||
#include "ecmascript/stackmap/cg_stackmap.h"
|
||||
#include "ecmascript/mem/machine_code.h"
|
||||
|
||||
|
@ -17,7 +17,8 @@
|
||||
#include "ecmascript/compiler/circuit_builder.h"
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
#include "ecmascript/compiler/graph_editor.h"
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
#include "ecmascript/js_tagged_value-inl.h"
|
||||
#include "ecmascript/mem/assert_scope.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
using UseIterator = GateAccessor::UseIterator;
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "ecmascript/compiler/jit_compilation_env.h"
|
||||
#include "ecmascript/ecma_context.h"
|
||||
#include "ecmascript/jspandafile/program_object.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
|
@ -56,14 +56,11 @@ JitCompilationOptions::JitCompilationOptions(JSRuntimeOptions runtimeOptions)
|
||||
isEnableValueNumbering_ = runtimeOptions.IsEnableValueNumbering();
|
||||
isEnableOptInlining_ = runtimeOptions.IsEnableOptInlining();
|
||||
isEnableOptString_ = runtimeOptions.IsEnableOptString();
|
||||
isEnableTypeInfer_ =
|
||||
isEnableTypeLowering_ || runtimeOptions.AssertTypes();
|
||||
isEnableOptPGOType_ = runtimeOptions.IsEnableOptPGOType();
|
||||
isEnableOptTrackField_ = runtimeOptions.IsEnableOptTrackField();
|
||||
isEnableOptLoopPeeling_ = runtimeOptions.IsEnableOptLoopPeeling();
|
||||
isEnableOptOnHeapCheck_ = runtimeOptions.IsEnableOptOnHeapCheck();
|
||||
isEnableOptLoopInvariantCodeMotion_ = runtimeOptions.IsEnableOptLoopInvariantCodeMotion();
|
||||
isEnableCollectLiteralInfo_ = false;
|
||||
isEnableOptConstantFolding_ = runtimeOptions.IsEnableOptConstantFolding();
|
||||
isEnableLexenvSpecialization_ = runtimeOptions.IsEnableLexenvSpecialization();
|
||||
isEnableNativeInline_ = runtimeOptions.IsEnableNativeInline();
|
||||
@ -86,14 +83,12 @@ void JitCompiler::Init(JSRuntimeOptions runtimeOptions)
|
||||
.EnableEarlyElimination(jitOptions_.isEnableEarlyElimination_)
|
||||
.EnableLaterElimination(jitOptions_.isEnableLaterElimination_)
|
||||
.EnableValueNumbering(jitOptions_.isEnableValueNumbering_)
|
||||
.EnableTypeInfer(jitOptions_.isEnableTypeInfer_)
|
||||
.EnableOptInlining(jitOptions_.isEnableOptInlining_)
|
||||
.EnableOptString(jitOptions_.isEnableOptString_)
|
||||
.EnableOptPGOType(jitOptions_.isEnableOptPGOType_)
|
||||
.EnableOptTrackField(jitOptions_.isEnableOptTrackField_)
|
||||
.EnableOptLoopPeeling(jitOptions_.isEnableOptLoopPeeling_)
|
||||
.EnableOptLoopInvariantCodeMotion(jitOptions_.isEnableOptLoopInvariantCodeMotion_)
|
||||
.EnableCollectLiteralInfo(jitOptions_.isEnableCollectLiteralInfo_)
|
||||
.EnableOptConstantFolding(jitOptions_.isEnableOptConstantFolding_)
|
||||
.EnableLexenvSpecialization(jitOptions_.isEnableLexenvSpecialization_)
|
||||
.EnableInlineNative(jitOptions_.isEnableNativeInline_)
|
||||
|
@ -54,13 +54,11 @@ struct JitCompilationOptions {
|
||||
bool isEnableValueNumbering_;
|
||||
bool isEnableOptInlining_;
|
||||
bool isEnableOptString_;
|
||||
bool isEnableTypeInfer_;
|
||||
bool isEnableOptPGOType_;
|
||||
bool isEnableOptTrackField_;
|
||||
bool isEnableOptLoopPeeling_;
|
||||
bool isEnableOptOnHeapCheck_;
|
||||
bool isEnableOptLoopInvariantCodeMotion_;
|
||||
bool isEnableCollectLiteralInfo_;
|
||||
bool isEnableOptConstantFolding_;
|
||||
bool isEnableLexenvSpecialization_;
|
||||
bool isEnableNativeInline_;
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "ecmascript/compiler/share_gate_meta_data.h"
|
||||
#include "ecmascript/compiler/type_info_accessors.h"
|
||||
#include "ecmascript/js_dataview.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class NativeInlineLowering {
|
||||
@ -35,7 +34,6 @@ public:
|
||||
builder_(circuit, cmpCfg),
|
||||
acc_(circuit),
|
||||
glue_(acc_.GetGlueFromArgList()),
|
||||
tsManager_(ctx->GetTSManager()),
|
||||
enableLog_(enableLog),
|
||||
methodName_(name),
|
||||
nocheck_(ctx->GetCompilationEnv()->GetJSOptions().IsCompilerNoCheck()),
|
||||
@ -103,7 +101,6 @@ private:
|
||||
CircuitBuilder builder_;
|
||||
GateAccessor acc_;
|
||||
GateRef glue_;
|
||||
TSManager *tsManager_;
|
||||
bool enableLog_;
|
||||
std::string methodName_;
|
||||
bool nocheck_;
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "ecmascript/compiler/number_gate_info.h"
|
||||
#include "ecmascript/compiler/type.h"
|
||||
#include "ecmascript/mem/chunk_containers.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class NumberSpeculativeLowering {
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "ecmascript/compiler/number_gate_info.h"
|
||||
#include "ecmascript/compiler/type.h"
|
||||
#include "ecmascript/mem/chunk_containers.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class NumberSpeculativeRetype {
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "ecmascript/compiler/pass_manager.h"
|
||||
#include "ecmascript/compiler/number_speculative_retype.h"
|
||||
#include "ecmascript/compiler/range_guard.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class NumberSpeculativeRunner {
|
||||
|
@ -1,163 +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/object_access_helper.h"
|
||||
|
||||
#include "ecmascript/js_hclass-inl.h"
|
||||
#include "ecmascript/ts_types/ts_type.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
bool ObjectAccessHelper::Compute(ChunkVector<ObjectAccessInfo> &infos)
|
||||
{
|
||||
ASSERT(compilationEnv_->IsAotCompiler());
|
||||
ASSERT(infos.empty());
|
||||
bool result = false;
|
||||
ObjectAccessInfo info(type_);
|
||||
TSTypeKind kind = tsManager_->GetTypeKind(type_.GetGTRef());
|
||||
switch (kind) {
|
||||
case TSTypeKind::CLASS_INSTANCE:
|
||||
result = ComputeForClassInstance(info);
|
||||
break;
|
||||
case TSTypeKind::CLASS:
|
||||
case TSTypeKind::OBJECT:
|
||||
result = ComputeForClassOrObject(info);
|
||||
break;
|
||||
case TSTypeKind::UNION:
|
||||
return ComputePolymorphism(infos);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
infos.emplace_back(info);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ObjectAccessHelper::ComputeForClassInstance(ObjectAccessInfo &info)
|
||||
{
|
||||
int hclassIndex = tsManager_->GetHClassIndexByInstanceGateType(info.Type());
|
||||
if (hclassIndex == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSHClass *hclass = JSHClass::Cast(tsManager_->GetAOTHClassInfoByIndex(hclassIndex).GetTaggedObject());
|
||||
if (!hclass->HasTSSubtyping()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(compilationEnv_->GetJSThread(), hclass, key_);
|
||||
info.Set(hclassIndex, plr);
|
||||
|
||||
if (IsLoading()) {
|
||||
return plr.IsFound();
|
||||
}
|
||||
|
||||
return (plr.IsFound() && !plr.IsFunction());
|
||||
}
|
||||
|
||||
bool ObjectAccessHelper::ComputeForClassOrObject(ObjectAccessInfo &info)
|
||||
{
|
||||
GateType type = info.Type();
|
||||
int hclassIndex = -1;
|
||||
if (tsManager_->IsClassTypeKind(type)) {
|
||||
hclassIndex = tsManager_->GetConstructorHClassIndexByClassGateType(type);
|
||||
} else if (tsManager_->IsObjectTypeKind(type)) {
|
||||
hclassIndex = tsManager_->GetHClassIndexByObjectType(type);
|
||||
}
|
||||
|
||||
if (hclassIndex == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSHClass *hclass = JSHClass::Cast(tsManager_->GetAOTHClassInfoByIndex(hclassIndex).GetTaggedObject());
|
||||
PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(compilationEnv_->GetJSThread(), hclass, key_);
|
||||
info.Set(hclassIndex, plr);
|
||||
|
||||
if (IsLoading()) {
|
||||
return (plr.IsFound() && plr.IsLocal() && !plr.IsAccessor());
|
||||
}
|
||||
|
||||
return (plr.IsFound() && plr.IsLocal() && !plr.IsAccessor() && plr.IsWritable());
|
||||
}
|
||||
|
||||
bool ObjectAccessHelper::ComputePolymorphism(ChunkVector<ObjectAccessInfo> &infos)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
ASSERT(tsManager_->IsUnionTypeKind(type_));
|
||||
JSHandle<TSUnionType> unionType(tsManager_->GetTSType(type_.GetGTRef()));
|
||||
TaggedArray *components = TaggedArray::Cast(unionType->GetComponents().GetTaggedObject());
|
||||
uint32_t length = components->GetLength();
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
GlobalTSTypeRef gt(components->Get(i).GetInt());
|
||||
GateType type = GateType(gt);
|
||||
ObjectAccessInfo info(type);
|
||||
TSTypeKind kind = tsManager_->GetTypeKind(gt);
|
||||
switch (kind) {
|
||||
case TSTypeKind::CLASS_INSTANCE: {
|
||||
if (!ComputeForClassInstance(info)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TSTypeKind::CLASS:
|
||||
case TSTypeKind::OBJECT: {
|
||||
if (!ComputeForClassOrObject(info)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
infos.emplace_back(info);
|
||||
}
|
||||
|
||||
return infos.size() <= POLYMORPHIC_MAX_SIZE;
|
||||
}
|
||||
|
||||
bool PGOObjectAccessHelper::ComputeForClassInstance(PGOObjectAccessInfo &info)
|
||||
{
|
||||
auto type = info.Type();
|
||||
PGOTypeManager *ptManager = compilationEnv_->GetPTManager();
|
||||
int hclassIndex = static_cast<int>(ptManager->GetHClassIndexByProfileType(type));
|
||||
if (hclassIndex == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSHClass *hclass = JSHClass::Cast(ptManager->QueryHClass(type.first, type.second).GetTaggedObject());
|
||||
|
||||
PropertyLookupResult plr = JSHClass::LookupPropertyInPGOHClass(compilationEnv_->GetJSThread(), hclass, key_);
|
||||
info.Set(hclassIndex, plr);
|
||||
|
||||
if (IsLoading()) {
|
||||
return plr.IsFound();
|
||||
}
|
||||
|
||||
return (plr.IsFound() && !plr.IsFunction());
|
||||
}
|
||||
|
||||
bool PGOObjectAccessHelper::ClassInstanceIsCallable(PGOObjectAccessInfo &info)
|
||||
{
|
||||
auto type = info.Type();
|
||||
PGOTypeManager *ptManager = compilationEnv_->GetPTManager();
|
||||
int hclassIndex = static_cast<int>(ptManager->GetHClassIndexByProfileType(type));
|
||||
if (hclassIndex == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSHClass *hclass = JSHClass::Cast(ptManager->QueryHClass(type.first, type.second).GetTaggedObject());
|
||||
|
||||
return hclass->IsCallable();
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
@ -1,216 +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_OBJECT_ACCESS_HELPER_H
|
||||
#define ECMASCRIPT_COMPILER_OBJECT_ACCESS_HELPER_H
|
||||
|
||||
#include "ecmascript/compiler/pgo_type/pgo_type_location.h"
|
||||
#include "ecmascript/compiler/share_gate_meta_data.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class ObjectAccessInfo final {
|
||||
public:
|
||||
explicit ObjectAccessInfo(GateType type, int hclassIndex = -1, PropertyLookupResult plr = PropertyLookupResult())
|
||||
: type_(type), hclassIndex_(hclassIndex), plr_(plr) {}
|
||||
~ObjectAccessInfo() = default;
|
||||
|
||||
void Set(int hclassIndex, PropertyLookupResult plr)
|
||||
{
|
||||
hclassIndex_ = hclassIndex;
|
||||
plr_ = plr;
|
||||
}
|
||||
|
||||
GateType Type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
int HClassIndex() const
|
||||
{
|
||||
return hclassIndex_;
|
||||
}
|
||||
|
||||
PropertyLookupResult Plr() const
|
||||
{
|
||||
return plr_;
|
||||
}
|
||||
|
||||
private:
|
||||
GateType type_ {GateType::AnyType()};
|
||||
int hclassIndex_ {-1};
|
||||
PropertyLookupResult plr_ {};
|
||||
};
|
||||
|
||||
class PGOObjectAccessInfo final {
|
||||
public:
|
||||
explicit PGOObjectAccessInfo(
|
||||
ProfileTyper type, int hclassIndex = -1, PropertyLookupResult plr = PropertyLookupResult())
|
||||
: type_(type), hclassIndex_(hclassIndex), plr_(plr) {}
|
||||
~PGOObjectAccessInfo() = default;
|
||||
|
||||
void Set(int hclassIndex, PropertyLookupResult plr)
|
||||
{
|
||||
hclassIndex_ = hclassIndex;
|
||||
plr_ = plr;
|
||||
}
|
||||
|
||||
ProfileTyper Type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
int HClassIndex() const
|
||||
{
|
||||
return hclassIndex_;
|
||||
}
|
||||
|
||||
PropertyLookupResult Plr() const
|
||||
{
|
||||
return plr_;
|
||||
}
|
||||
|
||||
private:
|
||||
ProfileTyper type_ {ProfileTyper()};
|
||||
int hclassIndex_ {-1};
|
||||
PropertyLookupResult plr_ {};
|
||||
};
|
||||
|
||||
// An auxiliary class serving TypedBytecodeLowering, used for named object property access,
|
||||
// invoking TSManager and HClass.
|
||||
class ObjectAccessHelper final {
|
||||
public:
|
||||
static constexpr size_t POLYMORPHIC_MAX_SIZE = 4;
|
||||
|
||||
enum AccessMode : uint8_t {
|
||||
LOAD = 0,
|
||||
STORE
|
||||
};
|
||||
|
||||
explicit ObjectAccessHelper(CompilationEnv *env, AccessMode mode, GateRef receiver, GateType type,
|
||||
JSTaggedValue key, GateRef value)
|
||||
: tsManager_(env->GetTSManager()),
|
||||
compilationEnv_(env),
|
||||
mode_(mode),
|
||||
receiver_(receiver),
|
||||
type_(type),
|
||||
key_(key),
|
||||
value_(value) {}
|
||||
|
||||
~ObjectAccessHelper() = default;
|
||||
|
||||
bool Compute(ChunkVector<ObjectAccessInfo> &infos);
|
||||
|
||||
AccessMode GetAccessMode() const
|
||||
{
|
||||
return mode_;
|
||||
}
|
||||
|
||||
bool IsLoading() const
|
||||
{
|
||||
return mode_ == AccessMode::LOAD;
|
||||
}
|
||||
|
||||
GateRef GetReceiver() const
|
||||
{
|
||||
return receiver_;
|
||||
}
|
||||
|
||||
GateRef GetValue() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool ComputeForClassInstance(ObjectAccessInfo &info);
|
||||
bool ComputeForClassOrObject(ObjectAccessInfo &info);
|
||||
bool ComputePolymorphism(ChunkVector<ObjectAccessInfo> &infos);
|
||||
|
||||
TSManager *tsManager_ {nullptr};
|
||||
const CompilationEnv *compilationEnv_ {nullptr};
|
||||
AccessMode mode_ {};
|
||||
GateRef receiver_ {Circuit::NullGate()};
|
||||
GateType type_ {GateType::AnyType()};
|
||||
JSTaggedValue key_ {JSTaggedValue::Hole()};
|
||||
GateRef value_ {Circuit::NullGate()};
|
||||
};
|
||||
|
||||
class PGOObjectAccessHelper final {
|
||||
public:
|
||||
static constexpr size_t POLYMORPHIC_MAX_SIZE = 4;
|
||||
|
||||
enum AccessMode : uint8_t {
|
||||
LOAD = 0,
|
||||
STORE
|
||||
};
|
||||
|
||||
explicit PGOObjectAccessHelper(CompilationEnv *env, AccessMode mode, GateRef receiver, ProfileTyper type,
|
||||
JSTaggedValue key, GateRef value)
|
||||
: tsManager_(env->GetTSManager()),
|
||||
compilationEnv_(env),
|
||||
mode_(mode),
|
||||
receiver_(receiver),
|
||||
holder_(receiver),
|
||||
type_(type),
|
||||
key_(key),
|
||||
value_(value) {}
|
||||
|
||||
~PGOObjectAccessHelper() = default;
|
||||
|
||||
AccessMode GetAccessMode() const
|
||||
{
|
||||
return mode_;
|
||||
}
|
||||
|
||||
bool IsLoading() const
|
||||
{
|
||||
return mode_ == AccessMode::LOAD;
|
||||
}
|
||||
|
||||
GateRef GetReceiver() const
|
||||
{
|
||||
return receiver_;
|
||||
}
|
||||
|
||||
GateRef GetHolder() const
|
||||
{
|
||||
return holder_;
|
||||
}
|
||||
|
||||
void SetHolder(GateRef holder)
|
||||
{
|
||||
holder_ = holder;
|
||||
}
|
||||
|
||||
GateRef GetValue() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
bool ComputeForClassInstance(PGOObjectAccessInfo &info);
|
||||
bool ClassInstanceIsCallable(PGOObjectAccessInfo &info);
|
||||
|
||||
private:
|
||||
|
||||
TSManager *tsManager_ {nullptr};
|
||||
const CompilationEnv *compilationEnv_ {nullptr};
|
||||
AccessMode mode_ {};
|
||||
GateRef receiver_ {Circuit::NullGate()};
|
||||
GateRef holder_ {Circuit::NullGate()};
|
||||
ProfileTyper type_ {ProfileTyper()};
|
||||
JSTaggedValue key_ {JSTaggedValue::Hole()};
|
||||
GateRef value_ {Circuit::NullGate()};
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_OBJECT_ACCESS_HELPER_H
|
@ -45,7 +45,6 @@
|
||||
#include "ecmascript/compiler/string_builder_optimizer.h"
|
||||
#include "ecmascript/compiler/slowpath_lowering.h"
|
||||
#include "ecmascript/compiler/state_split_linearizer.h"
|
||||
#include "ecmascript/compiler/ts_class_analysis.h"
|
||||
#include "ecmascript/compiler/ts_inline_lowering.h"
|
||||
#include "ecmascript/compiler/typed_bytecode_lowering.h"
|
||||
#include "ecmascript/compiler/ts_hcr_opt_pass.h"
|
||||
@ -115,11 +114,6 @@ public:
|
||||
return ctx_->GetCompilerConfig();
|
||||
}
|
||||
|
||||
TSManager* GetTSManager() const
|
||||
{
|
||||
return ctx_->GetTSManager();
|
||||
}
|
||||
|
||||
PGOTypeManager* GetPTManager() const
|
||||
{
|
||||
return ctx_->GetPTManager();
|
||||
@ -213,13 +207,6 @@ public:
|
||||
if (methodInfo_->IsTypeInferAbort() && !methodInfo_->IsResolvedMethod()) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// For js method, type infer pass will be skipped and it don't have a type percent.
|
||||
// If we set an non zero type threshold, js method will be skipped from full compilation.
|
||||
// The default Type threshold is -1.
|
||||
if (ctx_->GetTSManager()->GetTypeThreshold() >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// when a method will be full compiled, we should confirm its TypeInferAbortBit to be false
|
||||
// maybe it used to be true in the first round of compilation.
|
||||
@ -283,25 +270,12 @@ 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->GetPTManager(), data->GetBuilder(),
|
||||
data->GetMethodName(), &chunk, enableLog,
|
||||
data->GetPassContext()->GetCompilationEnv());
|
||||
PGOTypeInfer pgoTypeInfer(data->GetCircuit(), data->GetBuilder(), data->GetMethodName(), &chunk, enableLog);
|
||||
pgoTypeInfer.Run();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class TSClassAnalysisPass {
|
||||
public:
|
||||
bool Run(PassData *data)
|
||||
{
|
||||
TimeScope timescope("TSClassAnalysisPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
|
||||
TSClassAnalysis analyzer(data->GetPassContext()->GetTSManager());
|
||||
analyzer.Run();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class EscapeAnalysisPass {
|
||||
public:
|
||||
bool Run(PassData *data)
|
||||
@ -371,10 +345,7 @@ public:
|
||||
data->GetCallMethodFlagMap(),
|
||||
data->GetPGOProfilerDecoder(),
|
||||
data->GetOptBCRange());
|
||||
bool success = lowering.RunTypedBytecodeLowering();
|
||||
if (!success) {
|
||||
data->MarkAsTypeAbort();
|
||||
}
|
||||
lowering.RunTypedBytecodeLowering();
|
||||
CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
|
||||
DeadCodeElimination deadCodeElimination(data->GetCircuit(), &visitor, &chunk);
|
||||
TSHCROptPass optimization(data->GetCircuit(), &visitor, &chunk, data->GetPassContext(), enableLog,
|
||||
@ -448,7 +419,6 @@ public:
|
||||
data->GetPassContext()->GetCompilationEnv(),
|
||||
&visitor,
|
||||
data->GetCompilerConfig(),
|
||||
data->GetTSManager(),
|
||||
&chunk,
|
||||
passOptions->EnableLoweringBuiltin());
|
||||
visitor.AddPass(&lowering);
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_utils.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
#include "ecmascript/jit/jit.h"
|
||||
#include "jsnapi_expo.h"
|
||||
|
||||
@ -134,10 +133,6 @@ bool JitPassManager::Compile(JSHandle<ProfileTypeInfo> &profileTypeInfo,
|
||||
Jit::JitLockHolder lock(compilationEnv_, "PGOTypeInferPass");
|
||||
pipeline.RunPass<PGOTypeInferPass>();
|
||||
}
|
||||
{
|
||||
Jit::JitLockHolder lock(compilationEnv_, "TSClassAnalysisPass");
|
||||
pipeline.RunPass<TSClassAnalysisPass>();
|
||||
}
|
||||
{
|
||||
Jit::JitLockHolder lock(compilationEnv_, "TSInlineLoweringPass");
|
||||
pipeline.RunPass<TSInlineLoweringPass>();
|
||||
@ -217,8 +212,7 @@ bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName,
|
||||
{
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(compilationEnv_->GetJSThread());
|
||||
|
||||
BytecodeInfoCollector collector(compilationEnv_, jsPandaFile, profilerDecoder_,
|
||||
maxAotMethodSize_, passOptions_->EnableCollectLiteralInfo());
|
||||
BytecodeInfoCollector collector(compilationEnv_, jsPandaFile, profilerDecoder_, maxAotMethodSize_);
|
||||
// Checking released/debuggable pandafile uses method literals, which are initialized in BytecodeInfoCollector,
|
||||
// should after it.
|
||||
if (!IsReleasedPandaFile(jsPandaFile)) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "ecmascript/compiler/aot_compiler_preprocessor.h"
|
||||
#include "ecmascript/compiler/jit_compilation_env.h"
|
||||
#include "ecmascript/compiler/bytecode_info_collector.h"
|
||||
#include "ecmascript/compiler/compilation_driver.h"
|
||||
#include "ecmascript/compiler/compiler_log.h"
|
||||
#include "ecmascript/compiler/file_generators.h"
|
||||
#include "ecmascript/compiler/ir_module.h"
|
||||
@ -27,11 +28,9 @@
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/jit/jit_profiler.h"
|
||||
#include "ecmascript/jspandafile/method_literal.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class Bytecodes;
|
||||
class LexEnvManager;
|
||||
class CompilationConfig;
|
||||
class PassData;
|
||||
class CallMethodFlagMap;
|
||||
@ -42,9 +41,7 @@ public:
|
||||
PGOProfilerDecoder *decoder)
|
||||
: compilationEnv_(collector->GetCompilationEnv()),
|
||||
bcInfoCollector_(collector),
|
||||
tsManager_(compilationEnv_->GetTSManager()),
|
||||
bytecodes_(collector->GetByteCodes()),
|
||||
lexEnvManager_(bcInfoCollector_->GetEnvManager()),
|
||||
cmpCfg_(triple, &compilationEnv_->GetJSOptions()),
|
||||
log_(log),
|
||||
jsPandaFile_(collector->GetJSPandaFile()),
|
||||
@ -53,11 +50,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
TSManager* GetTSManager() const
|
||||
{
|
||||
return tsManager_;
|
||||
}
|
||||
|
||||
PGOTypeManager* GetPTManager() const
|
||||
{
|
||||
return compilationEnv_->GetPTManager();
|
||||
@ -68,11 +60,6 @@ public:
|
||||
return bytecodes_;
|
||||
}
|
||||
|
||||
LexEnvManager* GetLexEnvManager() const
|
||||
{
|
||||
return lexEnvManager_;
|
||||
}
|
||||
|
||||
CompilationConfig* GetCompilerConfig()
|
||||
{
|
||||
return &cmpCfg_;
|
||||
@ -131,9 +118,7 @@ public:
|
||||
private:
|
||||
CompilationEnv *compilationEnv_ {nullptr};
|
||||
BytecodeInfoCollector *bcInfoCollector_ {nullptr};
|
||||
TSManager *tsManager_ {nullptr};
|
||||
Bytecodes *bytecodes_ {nullptr};
|
||||
LexEnvManager *lexEnvManager_ {nullptr};
|
||||
CompilationConfig cmpCfg_;
|
||||
CompilerLog *log_ {nullptr};
|
||||
const JSPandaFile *jsPandaFile_ {nullptr};
|
||||
|
@ -23,7 +23,6 @@ namespace panda::ecmascript::kungfu {
|
||||
V(EarlyElimination, true) \
|
||||
V(LaterElimination, true) \
|
||||
V(ValueNumbering, false) \
|
||||
V(TypeInfer, false) \
|
||||
V(OptInlining, false) \
|
||||
V(OptNoGCCall, false) \
|
||||
V(OptPGOType, false) \
|
||||
|
@ -58,7 +58,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, LoadTypedArrayLength)
|
||||
builder.Return(convert);
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "LoadTypedArrayLength", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -88,7 +88,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, Int32ArrayLoadElement)
|
||||
builder.Return(convert);
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "Int32ArrayLoadElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -125,7 +125,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, Int32OnHeapArrayLoadElement)
|
||||
builder.Return(convert);
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "Int32OnHeapArrayLoadElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -157,7 +157,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, Float64OnHeapArrayLoadElement)
|
||||
builder.Return(convert);
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "Float64OnHeapArrayLoadElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -189,7 +189,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, FLOAT32OnHeapArrayLoadElement)
|
||||
builder.Return(convert);
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "FLOAT32OnHeapArrayLoadElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -224,7 +224,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, Int8OnHeapArrayLoadElement)
|
||||
builder.Return(convert);
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "Int8OnHeapArrayLoadElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -259,7 +259,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, UInt8OnHeapArrayLoadElement)
|
||||
builder.Return(convert);
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "UInt8OnHeapArrayLoadElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -294,7 +294,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, Int16OnHeapArrayLoadElement)
|
||||
builder.Return(convert);
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "Int16OnHeapArrayLoadElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -329,7 +329,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, UInt16OnHeapArrayLoadElement)
|
||||
builder.Return(convert);
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "UInt16OnHeapArrayLoadElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -363,7 +363,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, Int32ArrayStoreElement)
|
||||
auto ret = builder.Return(builder.Undefined());
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "Int32ArrayStoreElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -400,7 +400,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, Int32OnHeapArrayStoreElement)
|
||||
auto ret = builder.Return(builder.Undefined());
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "Int32OnHeapArrayStoreElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -432,7 +432,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, Float64OnHeapArrayStoreElement)
|
||||
auto ret = builder.Return(builder.Undefined());
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "Float64OnHeapArrayStoreElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -464,7 +464,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, Int8OnHeapArrayStoreElement)
|
||||
auto ret = builder.Return(builder.Undefined());
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "Int8OnHeapArrayStoreElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -498,7 +498,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, UInt8OnHeapArrayStoreElement)
|
||||
auto ret = builder.Return(builder.Undefined());
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "UInt8OnHeapArrayStoreElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -532,7 +532,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, Int16OnHeapArrayStoreElement)
|
||||
auto ret = builder.Return(builder.Undefined());
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "Int16OnHeapArrayStoreElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -566,7 +566,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, UInt16OnHeapArrayStoreElement)
|
||||
auto ret = builder.Return(builder.Undefined());
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "UInt16OnHeapArrayStoreElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
@ -600,7 +600,7 @@ HWTEST_F_L0(TypedArrayLoweringTests, Float32OnHeapArrayStoreElement)
|
||||
auto ret = builder.Return(builder.Undefined());
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CombinedPassVisitor visitor(&circuit, false, "Float32OnHeapArrayStoreElement", &chunk);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false);
|
||||
TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, &chunk, false);
|
||||
visitor.AddPass(&lowering);
|
||||
visitor.VisitGraph();
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
|
@ -1,156 +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/ts_class_analysis.h"
|
||||
|
||||
#include "ecmascript/js_hclass-inl.h"
|
||||
#include "ecmascript/layout_info.h"
|
||||
#include "ecmascript/ts_types/ts_type_accessor.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
void TSClassAnalysis::Run() const
|
||||
{
|
||||
const JSThread *thread = tsManager_->GetThread();
|
||||
std::set<GlobalTSTypeRef> &collectedGT = GetCollectedGT();
|
||||
for (auto iter = collectedGT.begin(); iter != collectedGT.end();) {
|
||||
JSHandle<JSTaggedValue> tsType = tsManager_->GetTSType(*iter);
|
||||
if (tsType->IsUndefined()) {
|
||||
++iter;
|
||||
continue;
|
||||
}
|
||||
ASSERT(tsType->IsTSClassType());
|
||||
JSHandle<TSClassType> classType(tsType);
|
||||
if (CheckInitInfoOnInheritanceChain(*classType)) {
|
||||
AnalyzeProperties(thread, *classType);
|
||||
collectedGT.erase(iter++);
|
||||
} else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TSClassAnalysis::CheckInitInfoOnInheritanceChain(const TSClassType *classType) const
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
if (!tsManager_->HasTSHClass(classType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// All extended class types and itself have completed initialization analysis.
|
||||
if (classType->IsBaseClassType()) {
|
||||
return classType->GetHasAnalysedInitialization();
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (!classType->GetHasAnalysedInitialization()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (classType->IsBaseClassType()) {
|
||||
break;
|
||||
}
|
||||
|
||||
classType = tsManager_->GetExtendedClassType(classType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TSClassAnalysis::HasEscapedThisOnSuper(const TSClassType *classType) const
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
if (classType->IsBaseClassType()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
classType = tsManager_->GetExtendedClassType(classType);
|
||||
if (classType->GetHasEscapedThisInConstructor()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (classType->IsBaseClassType()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TSClassAnalysis::AnalyzeProperties(const JSThread *thread, const TSClassType *classType) const
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
// Using this in self constructor will not mark flag in initialization analysis.
|
||||
if (HasEscapedThisOnSuper(classType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!classType->GetHasPassedSubtypingCheck()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GlobalTSTypeRef classGT = classType->GetGT();
|
||||
int hclassIndex = tsManager_->GetHClassIndex(classGT);
|
||||
ASSERT(hclassIndex != -1);
|
||||
JSHClass *hclass = JSHClass::Cast(tsManager_->GetAOTHClassInfoByIndex(hclassIndex).GetTaggedObject());
|
||||
if (UNLIKELY(hclass->IsDictionaryMode())) {
|
||||
return;
|
||||
}
|
||||
|
||||
LayoutInfo *layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
|
||||
|
||||
for (uint32_t index = 0; index < hclass->NumberOfProps(); ++index) {
|
||||
JSTaggedValue key = layout->GetKey(index);
|
||||
if (AnalyzePropertyOnSelf(thread, classType, key) || AnalyzePropertyOnSupers(thread, classType, key)) {
|
||||
layout->SetIsNotHole(thread, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TSClassAnalysis::AnalyzePropertyOnSelf(const JSThread *thread, const TSClassType *classType,
|
||||
JSTaggedValue key) const
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
JSHandle<TSObjectType> instanceType(thread, classType->GetInstanceType());
|
||||
JSHandle<TSObjLayoutInfo> tsLayout(thread, instanceType->GetObjLayoutInfo());
|
||||
int index = tsLayout->GetElementIndexByKey(key);
|
||||
if (!TSObjLayoutInfo::IsValidIndex(index)) {
|
||||
return false;
|
||||
}
|
||||
TSFieldAttributes tsAttr(tsLayout->GetAttribute(index).GetInt());
|
||||
return tsAttr.GetInitializedFlag();
|
||||
}
|
||||
|
||||
bool TSClassAnalysis::AnalyzePropertyOnSupers(const JSThread *thread, const TSClassType *classType,
|
||||
JSTaggedValue key) const
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
if (classType->IsBaseClassType()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TSClassType *type = tsManager_->GetExtendedClassType(classType);
|
||||
while (true) {
|
||||
if (AnalyzePropertyOnSelf(thread, type, key)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type->IsBaseClassType()) {
|
||||
break;
|
||||
}
|
||||
|
||||
type = tsManager_->GetExtendedClassType(type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
@ -1,48 +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_TS_CLASS_ANALYSIS_H
|
||||
#define ECMASCRIPT_COMPILER_TS_CLASS_ANALYSIS_H
|
||||
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class TSClassAnalysis {
|
||||
public:
|
||||
TSClassAnalysis(TSManager *tsManager): tsManager_(tsManager) {}
|
||||
~TSClassAnalysis() = default;
|
||||
|
||||
void Run() const;
|
||||
|
||||
private:
|
||||
bool CheckInitInfoOnInheritanceChain(const TSClassType *classType) const;
|
||||
|
||||
bool HasEscapedThisOnSuper(const TSClassType *classType) const;
|
||||
|
||||
void AnalyzeProperties(const JSThread *thread, const TSClassType *classType) const;
|
||||
|
||||
bool AnalyzePropertyOnSelf(const JSThread *thread, const TSClassType *classType, JSTaggedValue key) const;
|
||||
|
||||
bool AnalyzePropertyOnSupers(const JSThread *thread, const TSClassType *classType, JSTaggedValue key) const;
|
||||
|
||||
inline std::set<GlobalTSTypeRef>& GetCollectedGT() const
|
||||
{
|
||||
return tsManager_->GetCollectedGT();
|
||||
}
|
||||
|
||||
TSManager *tsManager_ {nullptr};
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_TS_CLASS_ANALYSIS_H
|
@ -1,307 +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/ts_hclass_generator.h"
|
||||
#include "ecmascript/global_env_constants-inl.h"
|
||||
#include "ecmascript/layout_info-inl.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
#include "ecmascript/jspandafile/class_info_extractor.h"
|
||||
#include "ecmascript/subtyping_operator.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
using ClassInfoExtractor = panda::ecmascript::ClassInfoExtractor;
|
||||
void TSHClassGenerator::GenerateTSHClasses() const
|
||||
{
|
||||
const JSThread *thread = tsManager_->GetThread();
|
||||
const std::set<GlobalTSTypeRef> &collectedGT = GetCollectedGT();
|
||||
for (const auto > : collectedGT) {
|
||||
JSHandle<JSTaggedValue> tsType = tsManager_->GetTSType(gt);
|
||||
if (tsType->IsUndefined()) {
|
||||
continue;
|
||||
}
|
||||
ASSERT(tsType->IsTSClassType());
|
||||
JSHandle<TSClassType> classType(tsType);
|
||||
if (tsManager_->HasTSHClass(classType)) {
|
||||
continue;
|
||||
} else if (tsManager_->IsUserDefinedClassTypeKind(gt)) {
|
||||
RecursiveGenerate(classType);
|
||||
} else if (!classType->GetHasLinked()) {
|
||||
SubtypingOperator::MergeClassField(thread, classType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TSHClassGenerator::RecursiveGenerate(const JSHandle<TSClassType> &classType) const
|
||||
{
|
||||
if (!classType->IsBaseClassType()) {
|
||||
JSHandle<TSClassType> extendedClassType(tsManager_->GetExtendedClassType(classType));
|
||||
if (!tsManager_->HasTSHClass(extendedClassType)) {
|
||||
RecursiveGenerate(extendedClassType);
|
||||
}
|
||||
}
|
||||
|
||||
JSThread *thread = tsManager_->GetThread();
|
||||
bool passed = false;
|
||||
if (classType->IsBaseClassType()) {
|
||||
passed = SubtypingOperator::CheckBaseClass(thread, classType);
|
||||
} else {
|
||||
passed = SubtypingOperator::CheckSubtyping(thread, classType);
|
||||
}
|
||||
|
||||
classType->SetHasPassedSubtypingCheck(passed);
|
||||
|
||||
if (passed) {
|
||||
if (!classType->IsBaseClassType()) {
|
||||
SubtypingOperator::MergeClassField(thread, classType);
|
||||
}
|
||||
JSHandle<JSHClass> ihclass = Generate(classType);
|
||||
SubtypingOperator::FillTSInheritInfo(thread, classType, ihclass);
|
||||
return;
|
||||
}
|
||||
Generate(classType);
|
||||
}
|
||||
|
||||
JSHandle<JSHClass> TSHClassGenerator::Generate(const JSHandle<TSClassType> &classType) const
|
||||
{
|
||||
const JSThread *thread = tsManager_->GetThread();
|
||||
JSHandle<JSHClass> ihclass = CreateHClass(thread, classType, Kind::INSTANCE);
|
||||
JSHandle<JSHClass> phclass = CreateHClass(thread, classType, Kind::PROTOTYPE);
|
||||
JSHandle<JSHClass> chclass = CreateHClass(thread, classType, Kind::CONSTRUCTOR);
|
||||
JSHandle<JSObject> prototype = thread->GetEcmaVM()->GetFactory()->NewJSObject(phclass);
|
||||
ihclass->SetProto(thread, prototype);
|
||||
|
||||
GlobalTSTypeRef gt = classType->GetGT();
|
||||
tsManager_->AddInstanceTSHClass(gt, ihclass);
|
||||
tsManager_->AddConstructorTSHClass(gt, chclass);
|
||||
return ihclass;
|
||||
}
|
||||
|
||||
JSHandle<JSHClass> TSHClassGenerator::CreateHClass(const JSThread *thread, const JSHandle<TSClassType> &classType,
|
||||
Kind kind) const
|
||||
{
|
||||
JSHandle<JSHClass> hclass(thread->GlobalConstants()->GetHandledUndefined());
|
||||
switch (kind) {
|
||||
case Kind::INSTANCE: {
|
||||
hclass = CreateIHClass(thread, classType);
|
||||
break;
|
||||
}
|
||||
case Kind::PROTOTYPE: {
|
||||
hclass = CreatePHClass(thread, classType);
|
||||
break;
|
||||
}
|
||||
case Kind::CONSTRUCTOR: {
|
||||
hclass = CreateCHClass(thread, classType);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
return hclass;
|
||||
}
|
||||
|
||||
JSHandle<JSHClass> TSHClassGenerator::CreateIHClass(const JSThread *thread,
|
||||
const JSHandle<TSClassType> &classType) const
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
|
||||
JSHandle<TSObjectType> instanceType(thread, classType->GetInstanceType());
|
||||
JSHandle<TSObjLayoutInfo> tsLayout(thread, instanceType->GetObjLayoutInfo());
|
||||
uint32_t numOfProps = tsLayout->GetNumOfProperties();
|
||||
JSHandle<JSHClass> hclass;
|
||||
if (LIKELY(numOfProps <= PropertyAttributes::MAX_FAST_PROPS_CAPACITY)) {
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
JSHandle<LayoutInfo> layout = factory->CreateLayoutInfo(numOfProps);
|
||||
for (uint32_t index = 0; index < numOfProps; ++index) {
|
||||
JSTaggedValue tsPropKey = tsLayout->GetKey(index);
|
||||
key.Update(tsPropKey);
|
||||
ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
|
||||
PropertyAttributes attributes = PropertyAttributes::Default();
|
||||
attributes.SetIsInlinedProps(true);
|
||||
attributes.SetRepresentation(Representation::NONE);
|
||||
attributes.SetOffset(index);
|
||||
layout->AddKey(thread, index, key.GetTaggedValue(), attributes);
|
||||
}
|
||||
hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, numOfProps);
|
||||
hclass->SetLayout(thread, layout);
|
||||
hclass->SetNumberOfProps(numOfProps);
|
||||
} else {
|
||||
// dictionary mode
|
||||
hclass = factory->NewEcmaHClass(JSFunction::SIZE, JSType::JS_OBJECT, 0); // without in-obj
|
||||
hclass->SetIsDictionaryMode(true);
|
||||
hclass->SetNumberOfProps(0);
|
||||
}
|
||||
|
||||
hclass->SetTS(true);
|
||||
|
||||
return hclass;
|
||||
}
|
||||
|
||||
JSHandle<JSHClass> TSHClassGenerator::CreatePHClass(const JSThread *thread,
|
||||
const JSHandle<TSClassType> &classType) const
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
|
||||
JSHandle<TSObjectType> prototypeType(thread, classType->GetPrototypeType());
|
||||
JSHandle<TSObjLayoutInfo> tsLayout(thread, prototypeType->GetObjLayoutInfo());
|
||||
uint32_t numOfProps = tsLayout->GetNumOfProperties();
|
||||
JSHandle<JSHClass> hclass;
|
||||
// There is only function information in abc, which needs to be brought up to the front for processing.
|
||||
// Other fields should be collected first and then optimized to the end.
|
||||
// Please note that there may be a problem with order in this way
|
||||
if (LIKELY(numOfProps <= PropertyAttributes::MAX_FAST_PROPS_CAPACITY)) {
|
||||
TSManager *tsManager = thread->GetCurrentEcmaContext()->GetTSManager();
|
||||
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
|
||||
JSHandle<JSTaggedValue> ctor = globalConst->GetHandledConstructorString();
|
||||
CVector<std::pair<JSHandle<JSTaggedValue>, GlobalTSTypeRef>> sortedPrototype {{ctor, GlobalTSTypeRef()}};
|
||||
CUnorderedMap<std::string, uint32_t> keysMap;
|
||||
for (uint32_t index = 0; index < numOfProps; ++index) {
|
||||
JSHandle<JSTaggedValue> key(thread, tsLayout->GetKey(index));
|
||||
auto value = GlobalTSTypeRef(tsLayout->GetTypeId(index).GetInt());
|
||||
// Usually, abstract methods in abstract class have no specific implementation,
|
||||
// and method signatures will be added after class scope.
|
||||
// Strategy: ignore abstract method, and rearrange the order of method signature to be at the end.
|
||||
bool isSame = JSTaggedValue::SameValue(key, ctor);
|
||||
bool isAbs = tsManager->IsAbstractMethod(value);
|
||||
if (!isSame && !isAbs) {
|
||||
bool isSign = tsManager->IsMethodSignature(value);
|
||||
if (isSign) {
|
||||
continue;
|
||||
}
|
||||
std::string keyStr = EcmaStringAccessor(key.GetTaggedValue()).ToStdString();
|
||||
auto it = keysMap.find(keyStr);
|
||||
if (it != keysMap.end()) {
|
||||
sortedPrototype[it->second] = std::make_pair(key, value);
|
||||
continue;
|
||||
}
|
||||
keysMap[keyStr] = sortedPrototype.size();
|
||||
sortedPrototype.emplace_back(std::make_pair(key, value));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t keysLen = sortedPrototype.size();
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
JSHandle<LayoutInfo> layout = factory->CreateLayoutInfo(keysLen);
|
||||
|
||||
for (uint32_t index = 0; index < keysLen; ++index) {
|
||||
key.Update(sortedPrototype[index].first);
|
||||
ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
|
||||
PropertyAttributes attributes = PropertyAttributes::Default(true, false, true);
|
||||
if (tsManager->IsGetterSetterFunc(sortedPrototype[index].second)) {
|
||||
attributes.SetIsAccessor(true);
|
||||
}
|
||||
attributes.SetIsInlinedProps(true);
|
||||
attributes.SetRepresentation(Representation::NONE);
|
||||
attributes.SetOffset(index);
|
||||
layout->AddKey(thread, index, key.GetTaggedValue(), attributes);
|
||||
}
|
||||
hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, keysLen);
|
||||
hclass->SetLayout(thread, layout);
|
||||
hclass->SetNumberOfProps(keysLen);
|
||||
} else {
|
||||
// dictionary mode
|
||||
hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, 0); // without in-obj
|
||||
hclass->SetIsDictionaryMode(true);
|
||||
hclass->SetNumberOfProps(0);
|
||||
}
|
||||
|
||||
hclass->SetTS(true);
|
||||
hclass->SetClassPrototype(true);
|
||||
hclass->SetIsPrototype(true);
|
||||
|
||||
return hclass;
|
||||
}
|
||||
|
||||
JSHandle<JSHClass> TSHClassGenerator::CreateCHClass(const JSThread *thread,
|
||||
const JSHandle<TSClassType> &classType) const
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
|
||||
JSHandle<TSObjectType> constructorType(thread, classType->GetConstructorType());
|
||||
JSHandle<TSObjLayoutInfo> tsLayout(thread, constructorType->GetObjLayoutInfo());
|
||||
uint32_t numOfProps = tsLayout->GetNumOfProperties() + ClassInfoExtractor::STATIC_RESERVED_LENGTH;
|
||||
JSHandle<JSHClass> hclass;
|
||||
if (LIKELY(numOfProps <= PropertyAttributes::MAX_FAST_PROPS_CAPACITY)) {
|
||||
TSManager *tsManager = thread->GetCurrentEcmaContext()->GetTSManager();
|
||||
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
|
||||
JSHandle<LayoutInfo> layout = factory->CreateLayoutInfo(numOfProps);
|
||||
std::vector<JSHandle<JSTaggedValue>> noFunc;
|
||||
int functionCount = -1;
|
||||
for (uint32_t index = 0; index < numOfProps; ++index) {
|
||||
JSTaggedValue tsPropKey;
|
||||
PropertyAttributes attributes;
|
||||
switch (index) {
|
||||
case ClassInfoExtractor::LENGTH_INDEX:
|
||||
attributes = PropertyAttributes::Default(false, false, true);
|
||||
tsPropKey = globalConst->GetLengthString();
|
||||
functionCount++;
|
||||
break;
|
||||
case ClassInfoExtractor::NAME_INDEX:
|
||||
attributes = PropertyAttributes::Default(false, false, true);
|
||||
tsPropKey = globalConst->GetNameString();
|
||||
functionCount++;
|
||||
break;
|
||||
case ClassInfoExtractor::PROTOTYPE_INDEX:
|
||||
attributes = PropertyAttributes::DefaultAccessor(false, false, false);
|
||||
tsPropKey = globalConst->GetPrototypeString();
|
||||
functionCount++;
|
||||
break;
|
||||
default:
|
||||
attributes = PropertyAttributes::Default(true, false, true);
|
||||
tsPropKey = tsLayout->GetKey(index - ClassInfoExtractor::STATIC_RESERVED_LENGTH);
|
||||
JSTaggedValue typeId = tsLayout->GetTypeId(index - ClassInfoExtractor::STATIC_RESERVED_LENGTH);
|
||||
GlobalTSTypeRef gt(static_cast<uint32_t>(typeId.GetNumber()));
|
||||
if (!tsManager->IsFunctionTypeKind(gt)) {
|
||||
noFunc.emplace_back(JSHandle<JSTaggedValue>(thread, tsPropKey));
|
||||
continue;
|
||||
}
|
||||
if (tsManager->IsGetterSetterFunc(gt)) {
|
||||
attributes.SetIsAccessor(true);
|
||||
}
|
||||
functionCount++;
|
||||
break;
|
||||
}
|
||||
ASSERT_PRINT(JSTaggedValue::IsPropertyKey(JSHandle<JSTaggedValue>(thread, tsPropKey)),
|
||||
"Key is not a property key");
|
||||
attributes.SetIsInlinedProps(true);
|
||||
attributes.SetRepresentation(Representation::NONE);
|
||||
attributes.SetOffset(functionCount);
|
||||
layout->AddKey(thread, functionCount, tsPropKey, attributes);
|
||||
}
|
||||
for (uint32_t index = 1; index <= noFunc.size(); index++) {
|
||||
PropertyAttributes attributes = PropertyAttributes::Default();
|
||||
attributes.SetIsInlinedProps(true);
|
||||
attributes.SetRepresentation(Representation::NONE);
|
||||
attributes.SetOffset(index + functionCount);
|
||||
layout->AddKey(thread, index + functionCount, noFunc[index - 1].GetTaggedValue(), attributes);
|
||||
}
|
||||
hclass = factory->NewEcmaHClass(JSFunction::SIZE, JSType::JS_FUNCTION, numOfProps);
|
||||
hclass->SetLayout(thread, layout);
|
||||
hclass->SetNumberOfProps(numOfProps);
|
||||
} else {
|
||||
// dictionary mode
|
||||
hclass = factory->NewEcmaHClass(JSFunction::SIZE, JSType::JS_FUNCTION, 0); // without in-obj
|
||||
hclass->SetIsDictionaryMode(true);
|
||||
hclass->SetNumberOfProps(0);
|
||||
}
|
||||
|
||||
hclass->SetTS(true);
|
||||
hclass->SetClassConstructor(true);
|
||||
hclass->SetConstructor(true);
|
||||
|
||||
return hclass;
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
@ -1,56 +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_TS_HCLASS_GENERATOR_H
|
||||
#define ECMASCRIPT_COMPILER_TS_HCLASS_GENERATOR_H
|
||||
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class TSHClassGenerator {
|
||||
public:
|
||||
explicit TSHClassGenerator(TSManager *tsManager): tsManager_(tsManager) {};
|
||||
~TSHClassGenerator() = default;
|
||||
|
||||
void GenerateTSHClasses() const;
|
||||
|
||||
private:
|
||||
void RecursiveGenerate(const JSHandle<TSClassType> &classType) const;
|
||||
|
||||
JSHandle<JSHClass> Generate(const JSHandle<TSClassType> &classType) const;
|
||||
|
||||
enum class Kind : uint8_t {
|
||||
INSTANCE = 0,
|
||||
PROTOTYPE,
|
||||
CONSTRUCTOR,
|
||||
};
|
||||
|
||||
JSHandle<JSHClass> CreateHClass(const JSThread *thread, const JSHandle<TSClassType> &classType, Kind kind) const;
|
||||
|
||||
JSHandle<JSHClass> CreateIHClass(const JSThread *thread, const JSHandle<TSClassType> &classType) const;
|
||||
|
||||
JSHandle<JSHClass> CreatePHClass(const JSThread *thread, const JSHandle<TSClassType> &classType) const;
|
||||
|
||||
JSHandle<JSHClass> CreateCHClass(const JSThread *thread, const JSHandle<TSClassType> &classType) const;
|
||||
|
||||
inline const std::set<GlobalTSTypeRef>& GetCollectedGT() const
|
||||
{
|
||||
return tsManager_->GetCollectedGT();
|
||||
}
|
||||
|
||||
TSManager *tsManager_ {nullptr};
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_TS_HCLASS_GENERATOR_H
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "ecmascript/compiler/combined_pass_visitor.h"
|
||||
#include "ecmascript/compiler/pass_manager.h"
|
||||
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
|
||||
#include "ecmascript/ecma_string-inl.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
|
@ -1,336 +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/initialization_analysis.h"
|
||||
#include "ecmascript/ts_types/ts_type_accessor.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
void InitializationAnalysis::Run()
|
||||
{
|
||||
if (classType_.IsAnyType()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CollectThisEscapedInfo(thisObject_);
|
||||
std::vector<GateRef> gateList;
|
||||
circuit_->GetAllGates(gateList);
|
||||
for (const auto &gate : gateList) {
|
||||
auto op = acc_.GetOpCode(gate);
|
||||
if (op == OpCode::JS_BYTECODE) {
|
||||
Analyse(gate);
|
||||
}
|
||||
}
|
||||
MarkHasAnalysedInitialization();
|
||||
|
||||
if (IsLogEnabled()) {
|
||||
Print();
|
||||
}
|
||||
}
|
||||
|
||||
void InitializationAnalysis::Analyse(GateRef gate)
|
||||
{
|
||||
ASSERT(acc_.GetOpCode(gate) == OpCode::JS_BYTECODE);
|
||||
EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
|
||||
switch (ecmaOpcode) {
|
||||
case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
|
||||
case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
|
||||
case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8: {
|
||||
CollectInitializationType(gate, ThisUsage::INDEFINITE_THIS);
|
||||
CollectInitializationInfo(gate, ThisUsage::INDEFINITE_THIS);
|
||||
break;
|
||||
}
|
||||
case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
|
||||
case EcmaOpcode::STTHISBYNAME_IMM16_ID16: {
|
||||
CollectInitializationType(gate, ThisUsage::DEFINITE_THIS);
|
||||
CollectInitializationInfo(gate, ThisUsage::DEFINITE_THIS);
|
||||
break;
|
||||
}
|
||||
case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8:
|
||||
case EcmaOpcode::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8:
|
||||
case EcmaOpcode::SUPERCALLARROWRANGE_IMM8_IMM8_V8:
|
||||
case EcmaOpcode::WIDE_SUPERCALLARROWRANGE_PREF_IMM16_V8:
|
||||
case EcmaOpcode::SUPERCALLSPREAD_IMM8_V8: {
|
||||
MarkSuperClass();
|
||||
CollectThisEscapedInfo(gate);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitializationAnalysis::CollectInitializationType(GateRef gate, ThisUsage thisUsage)
|
||||
{
|
||||
GateRef value = acc_.GetValueIn(gate, 3); // 3: index of value
|
||||
GateType valueType = acc_.GetGateType(value);
|
||||
if (valueType.IsAnyType()) {
|
||||
return;
|
||||
}
|
||||
if (thisUsage == ThisUsage::INDEFINITE_THIS) {
|
||||
GateRef receiver = acc_.GetValueIn(gate, 2); // 2: index of receiver
|
||||
GateType receiverType = acc_.GetGateType(receiver);
|
||||
auto receiverGT = receiverType.GetGTRef();
|
||||
if (tsManager_->IsClassInstanceTypeKind(receiverType)) {
|
||||
receiverGT = tsManager_->GetClassType(receiverType);
|
||||
}
|
||||
if (!CheckIsThisObject(receiver) && receiverGT != classType_.GetGTRef()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t index = acc_.GetConstantValue(acc_.GetValueIn(gate, 1)); // 1: stringId
|
||||
auto methodOffset = acc_.TryGetMethodOffset(gate);
|
||||
JSTaggedValue propKey = tsManager_->GetStringFromConstantPool(methodOffset, index);
|
||||
|
||||
if (valueType.IsNumberType()) {
|
||||
valueType = GateType::NumberType();
|
||||
}
|
||||
|
||||
TSTypeAccessor typeAccessor(tsManager_, classType_);
|
||||
typeAccessor.UpdateNonStaticProp(propKey, valueType.GetGTRef());
|
||||
}
|
||||
|
||||
void InitializationAnalysis::CollectInitializationInfo(GateRef gate, ThisUsage thisUsage)
|
||||
{
|
||||
if (thisUsage == ThisUsage::INDEFINITE_THIS) {
|
||||
GateRef receiver = acc_.GetValueIn(gate, 2); // 2: index of receiver
|
||||
if (!CheckIsThisObject(receiver)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t index = acc_.GetConstantValue(acc_.GetValueIn(gate, 1)); // 1: stringId
|
||||
if (!CheckSimpleCFG(gate, index)) {
|
||||
return;
|
||||
}
|
||||
auto methodOffset = acc_.TryGetMethodOffset(gate);
|
||||
JSTaggedValue propKey = tsManager_->GetStringFromConstantPool(methodOffset, index);
|
||||
TSTypeAccessor typeAccessor(tsManager_, classType_);
|
||||
typeAccessor.MarkPropertyInitialized(propKey);
|
||||
}
|
||||
|
||||
bool InitializationAnalysis::CheckIsThisObject(GateRef receiver) const
|
||||
{
|
||||
return IsThisFromArg(receiver) || IsThisFromSuperCall(receiver);
|
||||
}
|
||||
|
||||
bool InitializationAnalysis::IsThisFromSuperCall(GateRef gate) const
|
||||
{
|
||||
auto op = acc_.GetOpCode(gate);
|
||||
if (op != OpCode::JS_BYTECODE) {
|
||||
return false;
|
||||
}
|
||||
EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
|
||||
switch (ecmaOpcode) {
|
||||
case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8:
|
||||
case EcmaOpcode::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8:
|
||||
case EcmaOpcode::SUPERCALLARROWRANGE_IMM8_IMM8_V8:
|
||||
case EcmaOpcode::WIDE_SUPERCALLARROWRANGE_PREF_IMM16_V8:
|
||||
case EcmaOpcode::SUPERCALLSPREAD_IMM8_V8: {
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InitializationAnalysis::CheckSimpleCFG(GateRef gate, const uint16_t index) const
|
||||
{
|
||||
while (!acc_.IsStateRoot(gate)) {
|
||||
if (CheckSimpleGate(gate, index)) {
|
||||
return false;
|
||||
}
|
||||
gate = acc_.GetState(gate);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InitializationAnalysis::CheckSimpleGate(GateRef gate, const uint16_t index) const
|
||||
{
|
||||
OpCode opCode = acc_.GetOpCode(gate);
|
||||
switch (opCode) {
|
||||
case OpCode::IF_TRUE:
|
||||
case OpCode::IF_FALSE: {
|
||||
return true;
|
||||
}
|
||||
case OpCode::JS_BYTECODE: {
|
||||
return CheckSimpleJSGate(gate, index);
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InitializationAnalysis::CheckSimpleJSGate(GateRef gate, const uint16_t index) const
|
||||
{
|
||||
ASSERT(acc_.GetOpCode(gate) == OpCode::JS_BYTECODE);
|
||||
EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
|
||||
switch (ecmaOpcode) {
|
||||
case EcmaOpcode::LDOBJBYNAME_IMM8_ID16:
|
||||
case EcmaOpcode::LDOBJBYNAME_IMM16_ID16: {
|
||||
return CheckLdObjByName(gate, index, ThisUsage::INDEFINITE_THIS);
|
||||
}
|
||||
case EcmaOpcode::LDTHISBYNAME_IMM8_ID16:
|
||||
case EcmaOpcode::LDTHISBYNAME_IMM16_ID16: {
|
||||
return CheckLdObjByName(gate, index, ThisUsage::DEFINITE_THIS);
|
||||
}
|
||||
case EcmaOpcode::LDTHISBYVALUE_IMM8:
|
||||
case EcmaOpcode::LDTHISBYVALUE_IMM16: {
|
||||
return true;
|
||||
}
|
||||
case EcmaOpcode::LDOBJBYVALUE_IMM8_V8:
|
||||
case EcmaOpcode::LDOBJBYVALUE_IMM16_V8:
|
||||
case EcmaOpcode::LDOBJBYINDEX_IMM8_IMM16:
|
||||
case EcmaOpcode::LDOBJBYINDEX_IMM16_IMM16:
|
||||
case EcmaOpcode::WIDE_LDOBJBYINDEX_PREF_IMM32: {
|
||||
return CheckLdObjByIndexOrValue(gate);
|
||||
}
|
||||
case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
|
||||
case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
|
||||
case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
|
||||
case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
|
||||
case EcmaOpcode::STTHISBYNAME_IMM16_ID16:
|
||||
case EcmaOpcode::THROW_IFSUPERNOTCORRECTCALL_PREF_IMM8:
|
||||
case EcmaOpcode::THROW_IFSUPERNOTCORRECTCALL_PREF_IMM16: {
|
||||
return false;
|
||||
}
|
||||
default: {
|
||||
return CheckThisAsValueIn(gate);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InitializationAnalysis::CheckLdObjByName(GateRef gate, const uint16_t index, ThisUsage thisUsage) const
|
||||
{
|
||||
if (thisUsage == ThisUsage::INDEFINITE_THIS) {
|
||||
GateRef receiver = acc_.GetValueIn(gate, 2); // 2: index of receiver
|
||||
if (!CheckIsThisObject(receiver)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto constData = acc_.GetValueIn(gate, 1); // 1: stringId
|
||||
uint16_t stringId = acc_.GetConstantValue(constData);
|
||||
return stringId == index;
|
||||
}
|
||||
|
||||
bool InitializationAnalysis::CheckLdObjByIndexOrValue(GateRef gate) const
|
||||
{
|
||||
GateRef receiver = acc_.GetValueIn(gate, 1); // 1: index of receiver
|
||||
return CheckIsThisObject(receiver);
|
||||
}
|
||||
|
||||
void InitializationAnalysis::MarkSuperClass()
|
||||
{
|
||||
TSTypeAccessor typeAccessor(tsManager_, classType_);
|
||||
typeAccessor.MarkClassHasSuperCallInConstructor();
|
||||
}
|
||||
|
||||
void InitializationAnalysis::StoreThisObject()
|
||||
{
|
||||
ArgumentAccessor argAcc(circuit_);
|
||||
thisObject_ = argAcc.GetCommonArgGate(CommonArgIdx::THIS_OBJECT);
|
||||
auto type = acc_.GetGateType(thisObject_);
|
||||
if (tsManager_->IsClassInstanceTypeKind(type)) {
|
||||
classType_ = GateType(tsManager_->GetClassType(type));
|
||||
}
|
||||
}
|
||||
|
||||
bool InitializationAnalysis::CheckThisAsValueIn(GateRef gate) const
|
||||
{
|
||||
ASSERT(acc_.GetOpCode(gate) == OpCode::JS_BYTECODE);
|
||||
uint32_t numIns = acc_.GetNumValueIn(gate);
|
||||
for (uint32_t i = 0; i < numIns; ++i) {
|
||||
if (CheckIsThisObject(acc_.GetValueIn(gate, i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void InitializationAnalysis::CollectThisEscapedInfo(GateRef gate)
|
||||
{
|
||||
ASSERT(gate != Circuit::NullGate());
|
||||
std::vector<GateRef> valueUses;
|
||||
acc_.GetValueUses(gate, valueUses);
|
||||
for (const auto useGate : valueUses) {
|
||||
if (!HasEscapedThis(useGate)) {
|
||||
continue;
|
||||
}
|
||||
TSTypeAccessor typeAccessor(tsManager_, classType_);
|
||||
typeAccessor.MarkClassHasEscapedThisInConstructor();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool InitializationAnalysis::HasEscapedThis(GateRef gate) const
|
||||
{
|
||||
if (acc_.GetOpCode(gate) != OpCode::JS_BYTECODE) {
|
||||
return false;
|
||||
}
|
||||
EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
|
||||
switch (ecmaOpcode) {
|
||||
case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
|
||||
case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
|
||||
case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
|
||||
case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
|
||||
case EcmaOpcode::STTHISBYNAME_IMM16_ID16:
|
||||
case EcmaOpcode::THROW_IFSUPERNOTCORRECTCALL_PREF_IMM8:
|
||||
case EcmaOpcode::THROW_IFSUPERNOTCORRECTCALL_PREF_IMM16: {
|
||||
return false;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void InitializationAnalysis::MarkHasAnalysedInitialization()
|
||||
{
|
||||
TSTypeAccessor typeAccessor(tsManager_, classType_);
|
||||
typeAccessor.MarkClassHasAnalysedInitialization();
|
||||
}
|
||||
|
||||
bool InitializationAnalysis::CheckCall() const
|
||||
{
|
||||
TSTypeAccessor typeAccessor(tsManager_, classType_);
|
||||
return typeAccessor.ClassHasEscapedThisInConstructor();
|
||||
}
|
||||
|
||||
void InitializationAnalysis::Print() const
|
||||
{
|
||||
LOG_COMPILER(INFO) << " ";
|
||||
LOG_COMPILER(INFO) << "\033[34m" << "================="
|
||||
<< " After initialization analysis "
|
||||
<< "[" << GetMethodName() << "] "
|
||||
<< "=================" << "\033[0m";
|
||||
TSTypeAccessor typeAccessor(tsManager_, classType_);
|
||||
LOG_COMPILER(INFO) << "In the constructor of class " << typeAccessor.GetClassTypeName()
|
||||
<< " of record " << std::string(recordName_)
|
||||
<< ", the following propertiess will be initialized.";
|
||||
LOG_COMPILER(INFO) << (typeAccessor.GetInitializedProperties());
|
||||
if (typeAccessor.ClassHasEscapedThisInConstructor()) {
|
||||
LOG_COMPILER(INFO) << "This-object will be called by some functions in the constructor.";
|
||||
}
|
||||
LOG_COMPILER(INFO) << "\033[34m" << "=========================== End ===========================" << "\033[0m";
|
||||
}
|
||||
} // namespace panda::ecmascript
|
@ -1,88 +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_INITIALIZATION_ANALYSIS_H
|
||||
#define ECMASCRIPT_COMPILER_TYPE_INFERENCE_INITIALIZATION_ANALYSIS_H
|
||||
|
||||
#include "ecmascript/compiler/argument_accessor.h"
|
||||
#include "ecmascript/compiler/circuit.h"
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
enum class ThisUsage : uint8_t {
|
||||
INDEFINITE_THIS = 0,
|
||||
DEFINITE_THIS,
|
||||
};
|
||||
|
||||
class InitializationAnalysis {
|
||||
public:
|
||||
InitializationAnalysis(Circuit *circuit, TSManager *tsManager, const CString &recordName,
|
||||
const std::string &name, bool enableLog)
|
||||
: tsManager_(tsManager), circuit_(circuit), acc_(circuit), recordName_(recordName),
|
||||
methodName_(name), enableLog_(enableLog)
|
||||
{
|
||||
StoreThisObject();
|
||||
}
|
||||
~InitializationAnalysis() = default;
|
||||
|
||||
void Run();
|
||||
|
||||
private:
|
||||
inline bool IsLogEnabled() const
|
||||
{
|
||||
return enableLog_;
|
||||
}
|
||||
|
||||
inline const std::string &GetMethodName() const
|
||||
{
|
||||
return methodName_;
|
||||
}
|
||||
|
||||
inline bool IsThisFromArg(GateRef gate) const
|
||||
{
|
||||
return gate == thisObject_;
|
||||
}
|
||||
|
||||
void Analyse(GateRef gate);
|
||||
void CollectInitializationInfo(GateRef gate, ThisUsage thisUsage);
|
||||
void CollectInitializationType(GateRef gate, ThisUsage thisUsage);
|
||||
bool CheckIsThisObject(GateRef receiver) const;
|
||||
void MarkSuperClass();
|
||||
bool CheckSimpleCFG(GateRef gate, const uint16_t index) const;
|
||||
bool CheckSimpleGate(GateRef gate, const uint16_t index) const;
|
||||
bool CheckSimpleJSGate(GateRef gate, const uint16_t index) const;
|
||||
bool CheckLdObjByName(GateRef gate, const uint16_t index, ThisUsage thisUsage) const;
|
||||
bool CheckLdObjByIndexOrValue(GateRef gate) const;
|
||||
bool CheckCall() const;
|
||||
void StoreThisObject();
|
||||
bool CheckThisAsValueIn(GateRef gate) const;
|
||||
void CollectThisEscapedInfo(GateRef gate);
|
||||
bool HasEscapedThis(GateRef gate) const;
|
||||
void MarkHasAnalysedInitialization();
|
||||
bool IsThisFromSuperCall(GateRef gate) const;
|
||||
void Print() const;
|
||||
|
||||
TSManager *tsManager_ {nullptr};
|
||||
Circuit *circuit_ {nullptr};
|
||||
GateAccessor acc_;
|
||||
GateRef thisObject_ {Circuit::NullGate()};
|
||||
GateType classType_ {GateType::AnyType()};
|
||||
const CString &recordName_;
|
||||
const std::string &methodName_;
|
||||
bool enableLog_ {false};
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_TYPE_INFERENCE_INITIALIZATION_ANALYSIS_H
|
@ -14,7 +14,6 @@
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/type_inference/pgo_type_infer.h"
|
||||
#include "ecmascript/ts_types/ts_type_accessor.h"
|
||||
#include "ecmascript/compiler/bytecode_circuit_builder.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
@ -28,10 +27,6 @@ void PGOTypeInfer::Run()
|
||||
RunTypeInfer(gate);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsLogEnabled()) {
|
||||
Print();
|
||||
}
|
||||
}
|
||||
|
||||
void PGOTypeInfer::RunTypeInfer(GateRef gate)
|
||||
@ -45,19 +40,6 @@ void PGOTypeInfer::RunTypeInfer(GateRef gate)
|
||||
case EcmaOpcode::LDTHISBYNAME_IMM16_ID16:
|
||||
InferLdObjByName(gate);
|
||||
break;
|
||||
case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
|
||||
case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
|
||||
case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
|
||||
InferStObjByName(gate, false);
|
||||
break;
|
||||
case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
|
||||
case EcmaOpcode::STTHISBYNAME_IMM16_ID16:
|
||||
InferStObjByName(gate, true);
|
||||
break;
|
||||
case EcmaOpcode::STOWNBYNAME_IMM8_ID16_V8:
|
||||
case EcmaOpcode::STOWNBYNAME_IMM16_ID16_V8:
|
||||
InferStOwnByName(gate);
|
||||
break;
|
||||
case EcmaOpcode::STOWNBYINDEX_IMM8_V8_IMM16:
|
||||
case EcmaOpcode::STOWNBYINDEX_IMM16_V8_IMM16:
|
||||
InferStOwnByIndex(gate);
|
||||
@ -83,112 +65,20 @@ void PGOTypeInfer::RunTypeInfer(GateRef gate)
|
||||
}
|
||||
}
|
||||
|
||||
void PGOTypeInfer::Print() const
|
||||
{
|
||||
LOG_COMPILER(INFO) << " ";
|
||||
LOG_COMPILER(INFO) << "\033[34m" << "================="
|
||||
<< " After pgo type infer "
|
||||
<< "[" << GetMethodName() << "] "
|
||||
<< "=================" << "\033[0m";
|
||||
|
||||
for (const auto &value : profiler_.datas) {
|
||||
std::string log("\"id\"=" + std::to_string(acc_.GetId(value.gate)) +
|
||||
", \"bytecode\"=\"" + GetEcmaOpcodeStr(acc_.GetByteCodeOpcode(value.gate)) + "\", ");
|
||||
log += "TSType: [type:" + tsManager_->GetTypeStr(value.tsType) + ", "
|
||||
+ "moduleId: " + std::to_string(value.tsType.GetGTRef().GetModuleId()) + ", "
|
||||
+ "localId: " + std::to_string(value.tsType.GetGTRef().GetLocalId()) + "], ";
|
||||
log += "PGOTypes: [";
|
||||
for (auto pgoType : value.pgoTypes) {
|
||||
log += "[type:" + tsManager_->GetTypeStr(pgoType) + ", "
|
||||
+ "moduleId: " + std::to_string(pgoType.GetGTRef().GetModuleId()) + ", "
|
||||
+ "localId: " + std::to_string(pgoType.GetGTRef().GetLocalId()) + "], ";
|
||||
}
|
||||
log += "] InferTypes: [";
|
||||
for (auto type : value.inferTypes) {
|
||||
log += "[type:" + tsManager_->GetTypeStr(type) + ", "
|
||||
+ "moduleId: " + std::to_string(type.GetGTRef().GetModuleId()) + ", "
|
||||
+ "localId: " + std::to_string(type.GetGTRef().GetLocalId()) + "]";
|
||||
}
|
||||
log += "]";
|
||||
LOG_COMPILER(INFO) << std::dec << log;
|
||||
}
|
||||
LOG_COMPILER(INFO) << "\033[34m" << "=========================== End ===========================" << "\033[0m";
|
||||
}
|
||||
|
||||
void PGOTypeInfer::AddProfiler(GateRef gate, GateType tsType, PGORWOpType pgoType, ChunkSet<GateType>& inferTypes)
|
||||
{
|
||||
if (enableLog_) {
|
||||
Profiler::Value value;
|
||||
value.gate = gate;
|
||||
value.tsType = tsType;
|
||||
for (uint32_t i = 0; i < pgoType.GetCount(); i++) {
|
||||
value.pgoTypes.emplace_back(tsManager_->GetGateTypeByPt(pgoType.GetObjectInfo(i).GetProfileType()));
|
||||
}
|
||||
for (GateType type : inferTypes) {
|
||||
value.inferTypes.emplace_back(type);
|
||||
}
|
||||
profiler_.datas.emplace_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
void PGOTypeInfer::InferLdObjByName(GateRef gate)
|
||||
{
|
||||
if (!builder_->ShouldPGOTypeInfer(gate)) {
|
||||
return;
|
||||
}
|
||||
GateRef constData = acc_.GetValueIn(gate, 1); // 1: valueIn 1
|
||||
uint16_t propIndex = acc_.GetConstantValue(constData);
|
||||
GateRef receiver = acc_.GetValueIn(gate, 2); // 2: acc or this object
|
||||
|
||||
UpdateTypeForRWOp(gate, receiver, propIndex);
|
||||
TrySetElementsKind(gate);
|
||||
}
|
||||
|
||||
void PGOTypeInfer::InferStObjByName(GateRef gate, bool isThis)
|
||||
{
|
||||
if (!builder_->ShouldPGOTypeInfer(gate)) {
|
||||
return;
|
||||
}
|
||||
GateRef constData = acc_.GetValueIn(gate, 1); // 1: valueIn 1
|
||||
uint16_t propIndex = acc_.GetConstantValue(constData);
|
||||
GateRef receiver = Circuit::NullGate();
|
||||
if (isThis) {
|
||||
// 3: number of value inputs
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 3);
|
||||
receiver = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::THIS_OBJECT);
|
||||
} else {
|
||||
// 4: number of value inputs
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 4);
|
||||
receiver = acc_.GetValueIn(gate, 2); // 2: receiver
|
||||
}
|
||||
|
||||
UpdateTypeForRWOp(gate, receiver, propIndex);
|
||||
}
|
||||
|
||||
void PGOTypeInfer::InferStOwnByName(GateRef gate)
|
||||
{
|
||||
if (!builder_->ShouldPGOTypeInfer(gate)) {
|
||||
return;
|
||||
}
|
||||
// 3: number of value inputs
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 3);
|
||||
GateRef constData = acc_.GetValueIn(gate, 0);
|
||||
uint16_t propIndex = acc_.GetConstantValue(constData);
|
||||
GateRef receiver = acc_.GetValueIn(gate, 1);
|
||||
|
||||
UpdateTypeForRWOp(gate, receiver, propIndex);
|
||||
}
|
||||
|
||||
void PGOTypeInfer::InferStOwnByIndex(GateRef gate)
|
||||
{
|
||||
if (!builder_->ShouldPGOTypeInfer(gate)) {
|
||||
return;
|
||||
}
|
||||
// 3: number of value inputs
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 3);
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
|
||||
UpdateTypeForRWOp(gate, receiver);
|
||||
TrySetElementsKind(gate);
|
||||
TrySetTransitionElementsKind(gate);
|
||||
TrySetOnHeapMode(gate);
|
||||
@ -214,7 +104,6 @@ void PGOTypeInfer::InferAccessObjByValue(GateRef gate)
|
||||
if (!builder_->ShouldPGOTypeInfer(gate)) {
|
||||
return;
|
||||
}
|
||||
GateRef receiver = Circuit::NullGate();
|
||||
GateRef propKey = Circuit::NullGate();
|
||||
EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
|
||||
switch (ecmaOpcode) {
|
||||
@ -222,57 +111,24 @@ void PGOTypeInfer::InferAccessObjByValue(GateRef gate)
|
||||
case EcmaOpcode::LDOBJBYVALUE_IMM16_V8:
|
||||
case EcmaOpcode::STOBJBYVALUE_IMM8_V8_V8:
|
||||
case EcmaOpcode::STOBJBYVALUE_IMM16_V8_V8:
|
||||
receiver = acc_.GetValueIn(gate, 1); // 1: receiver
|
||||
propKey = acc_.GetValueIn(gate, 2); // 2: the third parameter
|
||||
break;
|
||||
case EcmaOpcode::LDTHISBYVALUE_IMM8:
|
||||
case EcmaOpcode::LDTHISBYVALUE_IMM16:
|
||||
case EcmaOpcode::STTHISBYVALUE_IMM8_V8:
|
||||
case EcmaOpcode::STTHISBYVALUE_IMM16_V8:
|
||||
receiver = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::THIS_OBJECT);
|
||||
propKey = acc_.GetValueIn(gate, 1);
|
||||
break;
|
||||
default:
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
}
|
||||
UpdateTypeForRWOp(gate, receiver);
|
||||
TrySetPropKeyKind(gate, propKey);
|
||||
TrySetElementsKind(gate);
|
||||
TrySetTransitionElementsKind(gate);
|
||||
TrySetOnHeapMode(gate);
|
||||
}
|
||||
|
||||
void PGOTypeInfer::UpdateTypeForRWOp(GateRef gate, GateRef receiver, uint32_t propIndex)
|
||||
{
|
||||
GateType tsType = acc_.GetGateType(receiver);
|
||||
auto pgoTypes = acc_.TryGetPGOType(gate);
|
||||
const PGORWOpType *pgoRwTypes = pgoTypes.GetPGORWOpType();
|
||||
|
||||
CollectedType types(chunk_);
|
||||
helper_.CollectGateType(types, tsType, *pgoRwTypes);
|
||||
|
||||
// polymorphism is not currently supported,
|
||||
// all types must in the same kind
|
||||
if (!types.AllInSameKind()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// polymorphism is not currently supported
|
||||
JSTaggedValue prop = JSTaggedValue::Undefined();
|
||||
if (propIndex != INVALID_INDEX) {
|
||||
auto methodOffset = acc_.TryGetMethodOffset(gate);
|
||||
prop = compilationEnv_->GetStringFromConstantPool(methodOffset, propIndex);
|
||||
}
|
||||
ChunkSet<GateType> inferTypes = helper_.GetInferTypes(chunk_, types, prop);
|
||||
AddProfiler(gate, tsType, *pgoRwTypes, inferTypes);
|
||||
if (!IsMonoTypes(inferTypes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
acc_.SetGateType(receiver, *inferTypes.begin());
|
||||
}
|
||||
|
||||
void PGOTypeInfer::TrySetElementsKind(GateRef gate)
|
||||
{
|
||||
auto kinds = builder_->GetElementsKindsForUser(gate);
|
||||
|
@ -16,20 +16,17 @@
|
||||
#ifndef ECMASCRIPT_COMPILER_TYPE_INFERENCE_PGO_TYPE_INFER_H
|
||||
#define ECMASCRIPT_COMPILER_TYPE_INFERENCE_PGO_TYPE_INFER_H
|
||||
|
||||
#include "ecmascript/compiler/type_inference/pgo_type_infer_helper.h"
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
#include "ecmascript/compiler/argument_accessor.h"
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
struct CollectedType;
|
||||
class PGOTypeInfer {
|
||||
public:
|
||||
PGOTypeInfer(Circuit *circuit, TSManager *tsManager, PGOTypeManager *ptManager, BytecodeCircuitBuilder *builder,
|
||||
const std::string &name, Chunk *chunk, bool enableLog, CompilationEnv *env)
|
||||
: circuit_(circuit), acc_(circuit), argAcc_(circuit), tsManager_(tsManager),
|
||||
ptManager_(ptManager), helper_(tsManager), builder_(builder), methodName_(name), chunk_(chunk),
|
||||
enableLog_(enableLog), profiler_(chunk), compilationEnv_(env) {}
|
||||
PGOTypeInfer(Circuit *circuit, BytecodeCircuitBuilder *builder, const std::string &name,
|
||||
Chunk *chunk, bool enableLog)
|
||||
: circuit_(circuit), acc_(circuit), argAcc_(circuit), builder_(builder), methodName_(name),
|
||||
enableLog_(enableLog), profiler_(chunk) {}
|
||||
~PGOTypeInfer() = default;
|
||||
|
||||
void Run();
|
||||
@ -70,33 +67,22 @@ private:
|
||||
|
||||
void RunTypeInfer(GateRef gate);
|
||||
void InferLdObjByName(GateRef gate);
|
||||
void InferStObjByName(GateRef gate, bool isThis);
|
||||
void InferStOwnByName(GateRef gate);
|
||||
void InferStOwnByIndex(GateRef gate);
|
||||
void InferAccessObjByValue(GateRef gate);
|
||||
void InferCreateArray(GateRef gate);
|
||||
|
||||
void UpdateTypeForRWOp(GateRef gate, GateRef receiver, uint32_t propIdx = INVALID_INDEX);
|
||||
void TrySetElementsKind(GateRef gate);
|
||||
void TrySetTransitionElementsKind(GateRef gate);
|
||||
void TrySetPropKeyKind(GateRef gate, GateRef propKey);
|
||||
void TrySetOnHeapMode(GateRef gate);
|
||||
|
||||
void Print() const;
|
||||
void AddProfiler(GateRef gate, GateType tsType, PGORWOpType pgoType, ChunkSet<GateType>& inferTypes);
|
||||
|
||||
Circuit *circuit_ {nullptr};
|
||||
GateAccessor acc_;
|
||||
ArgumentAccessor argAcc_;
|
||||
TSManager *tsManager_ {nullptr};
|
||||
[[maybe_unused]] PGOTypeManager *ptManager_ {nullptr};
|
||||
PGOTypeInferHelper helper_;
|
||||
BytecodeCircuitBuilder *builder_ {nullptr};
|
||||
const std::string &methodName_;
|
||||
Chunk *chunk_ {nullptr};
|
||||
bool enableLog_ {false};
|
||||
Profiler profiler_;
|
||||
CompilationEnv *compilationEnv_ {nullptr};
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_TYPE_INFERENCE_PGO_TYPE_INFER_H
|
||||
|
@ -1,251 +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/pgo_type_infer_helper.h"
|
||||
|
||||
#include "ecmascript/js_hclass-inl.h"
|
||||
#include "ecmascript/ts_types/ts_type_accessor.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
bool ClassTypeStrategy::CheckAndInsert(CollectedType &types, const GateType &type, TSManager *tsManager)
|
||||
{
|
||||
if (tsManager->IsUserDefinedClassTypeKind(type)) {
|
||||
int hclassIndex = tsManager->GetConstructorHClassIndexByClassGateType(type);
|
||||
if (hclassIndex == -1) {
|
||||
return true;
|
||||
}
|
||||
types.classTypes.insert(type);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClassTypeStrategy::Merge(ChunkSet<GateType> &inferTypes, CollectedType &types,
|
||||
[[maybe_unused]] TSManager *tsManager)
|
||||
{
|
||||
for (GateType type : types.classTypes) {
|
||||
inferTypes.insert(type);
|
||||
}
|
||||
}
|
||||
|
||||
bool ClassInstanceTypeStrategy::CheckAndInsert(CollectedType &types, const GateType &type, TSManager *tsManager)
|
||||
{
|
||||
if (tsManager->IsClassInstanceTypeKind(type) &&
|
||||
tsManager->IsUserDefinedClassTypeKind(tsManager->GetClassType(type))) {
|
||||
int hclassIndex = tsManager->GetHClassIndexByInstanceGateType(type);
|
||||
if (hclassIndex == -1) {
|
||||
return true;
|
||||
}
|
||||
JSHClass *hclass = JSHClass::Cast(tsManager->GetAOTHClassInfoByIndex(hclassIndex).GetTaggedObject());
|
||||
if (hclass->HasTSSubtyping()) {
|
||||
GlobalTSTypeRef instanceGT = type.GetGTRef();
|
||||
GateType classType = GateType(tsManager->GetClassType(instanceGT));
|
||||
types.classInstanceTypes.insert(classType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClassInstanceTypeStrategy::Merge(ChunkSet<GateType> &inferTypes, CollectedType &types, TSManager *tsManager)
|
||||
{
|
||||
for (GateType type : types.classInstanceTypes) {
|
||||
GlobalTSTypeRef gt = type.GetGTRef();
|
||||
GlobalTSTypeRef instanceGT = tsManager->CreateClassInstanceType(gt);
|
||||
inferTypes.insert(GateType(instanceGT));
|
||||
}
|
||||
}
|
||||
|
||||
bool BuiltinTypeStrategy::CheckAndInsert(CollectedType &types, const GateType &type, TSManager *tsManager)
|
||||
{
|
||||
if (tsManager->IsValidTypedArrayType(type)) {
|
||||
types.builtinTypes.insert(type);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BuiltinTypeStrategy::Merge(ChunkSet<GateType> &inferTypes, CollectedType &types,
|
||||
[[maybe_unused]] TSManager *tsManager)
|
||||
{
|
||||
for (GateType type : types.builtinTypes) {
|
||||
inferTypes.insert(type);
|
||||
}
|
||||
}
|
||||
|
||||
bool OtherTypeStrategy::CheckAndInsert(CollectedType &types, const GateType &type, [[maybe_unused]]TSManager *tsManager)
|
||||
{
|
||||
if (!type.IsAnyType()) {
|
||||
types.otherTypes.insert(type);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void OtherTypeStrategy::Merge(ChunkSet<GateType> &inferTypes, CollectedType &types,
|
||||
[[maybe_unused]] TSManager *tsManager)
|
||||
{
|
||||
for (GateType type : types.otherTypes) {
|
||||
inferTypes.insert(type);
|
||||
}
|
||||
}
|
||||
|
||||
void PGOTypeInferHelper::CollectGateType(CollectedType &types, GateType tsType, PGORWOpType pgoTypes)
|
||||
{
|
||||
// for static TS uinon type
|
||||
if (tsManager_->IsUnionTypeKind(tsType)) {
|
||||
JSHandle<TSUnionType> unionType(tsManager_->GetTSType(tsType.GetGTRef()));
|
||||
TaggedArray *components = TaggedArray::Cast(unionType->GetComponents().GetTaggedObject());
|
||||
uint32_t length = components->GetLength();
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
GlobalTSTypeRef gt(components->Get(i).GetInt());
|
||||
CheckAndInsert(types, GateType(gt));
|
||||
}
|
||||
} else {
|
||||
CheckAndInsert(types, tsType);
|
||||
}
|
||||
|
||||
// for pgo type
|
||||
for (uint32_t i = 0; i < pgoTypes.GetCount(); i++) {
|
||||
ProfileType profileType = pgoTypes.GetObjectInfo(i).GetProfileType();
|
||||
GateType pgoType = tsManager_->GetGateTypeByPt(profileType);
|
||||
if (tsManager_->IsClassTypeKind(pgoType) && !pgoTypes.GetObjectInfo(i).InConstructor()) {
|
||||
pgoType = GateType(tsManager_->CreateClassInstanceType(pgoType));
|
||||
}
|
||||
CheckAndInsert(types, pgoType);
|
||||
}
|
||||
}
|
||||
|
||||
ChunkSet<GateType> PGOTypeInferHelper::GetInferTypes(Chunk *chunk, CollectedType &types, JSTaggedValue prop)
|
||||
{
|
||||
if (!prop.IsUndefined()) {
|
||||
UpdateType(types, prop);
|
||||
}
|
||||
ChunkSet<GateType> inferTypes(chunk);
|
||||
for (auto &strategy : strategies_) {
|
||||
strategy->Merge(inferTypes, types, tsManager_);
|
||||
}
|
||||
return inferTypes;
|
||||
}
|
||||
|
||||
void PGOTypeInferHelper::CheckAndInsert(CollectedType &types, GateType type)
|
||||
{
|
||||
for (auto &strategy : strategies_) {
|
||||
if (strategy->CheckAndInsert(types, type, tsManager_)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PGOTypeInferHelper::UpdateType(CollectedType &types, JSTaggedValue prop)
|
||||
{
|
||||
ChunkSet<GateType> &classTypes = types.classTypes;
|
||||
InferTypeForClass(classTypes, prop);
|
||||
|
||||
ChunkSet<GateType> &classInstanceTypes = types.classInstanceTypes;
|
||||
InferTypeForClass(classInstanceTypes, prop);
|
||||
|
||||
ChunkSet<GateType> &builtinTypes = types.builtinTypes;
|
||||
InferTypeForBuiltin(builtinTypes);
|
||||
}
|
||||
|
||||
void PGOTypeInferHelper::InferTypeForClass(ChunkSet<GateType> &types, JSTaggedValue prop)
|
||||
{
|
||||
if (NoNeedUpdate(types)) {
|
||||
return;
|
||||
}
|
||||
EliminateSubclassTypes(types);
|
||||
ComputeCommonSuperClassTypes(types, prop);
|
||||
}
|
||||
|
||||
void PGOTypeInferHelper::InferTypeForBuiltin(ChunkSet<GateType> &types)
|
||||
{
|
||||
if (NoNeedUpdate(types)) {
|
||||
return;
|
||||
}
|
||||
std::set<GateType> deletedGates;
|
||||
std::set<GlobalTSTypeRef> builtinGTSet;
|
||||
|
||||
for (GateType type : types) {
|
||||
GlobalTSTypeRef classGT = tsManager_->GetClassType(type);
|
||||
auto it = builtinGTSet.find(classGT);
|
||||
if (it != builtinGTSet.end()) {
|
||||
deletedGates.insert(type);
|
||||
continue;
|
||||
}
|
||||
builtinGTSet.insert(classGT);
|
||||
}
|
||||
for (GateType gateType : deletedGates) {
|
||||
types.erase(gateType);
|
||||
}
|
||||
}
|
||||
|
||||
void PGOTypeInferHelper::EliminateSubclassTypes(ChunkSet<GateType> &types)
|
||||
{
|
||||
std::set<GateType> deletedGates;
|
||||
for (GateType type : types) {
|
||||
if (deletedGates.find(type) != deletedGates.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::stack<GateType> ancestors;
|
||||
GateType curType = type;
|
||||
do {
|
||||
if (types.find(curType) != types.end()) {
|
||||
ancestors.push(curType);
|
||||
}
|
||||
} while (tsManager_->GetSuperGateType(curType));
|
||||
|
||||
ancestors.pop(); // top type is alive
|
||||
while (!ancestors.empty()) {
|
||||
curType = ancestors.top();
|
||||
ancestors.pop();
|
||||
auto it = deletedGates.find(curType);
|
||||
if (it != deletedGates.end()) {
|
||||
deletedGates.insert(curType);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (GateType gateType : deletedGates) {
|
||||
types.erase(gateType);
|
||||
}
|
||||
}
|
||||
|
||||
void PGOTypeInferHelper::ComputeCommonSuperClassTypes(ChunkSet<GateType> &types, JSTaggedValue prop)
|
||||
{
|
||||
JSThread *thread = tsManager_->GetEcmaVM()->GetJSThread();
|
||||
std::map<GateType, GateType> removeTypes;
|
||||
for (GateType type : types) {
|
||||
GateType curType = type;
|
||||
GateType preType = type;
|
||||
while (tsManager_->GetSuperGateType(curType)) {
|
||||
JSHClass *ihc = JSHClass::Cast(tsManager_->GetTSHClass(curType).GetTaggedObject());
|
||||
PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(thread, ihc, prop);
|
||||
if (!plr.IsFound()) {
|
||||
break;
|
||||
}
|
||||
preType = curType;
|
||||
}
|
||||
if (type != preType) {
|
||||
removeTypes[type] = preType;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto item : removeTypes) {
|
||||
types.erase(item.first);
|
||||
types.insert(item.second);
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript
|
@ -1,102 +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_PGO_TYPE_INFER_HELPER_H
|
||||
#define ECMASCRIPT_COMPILER_TYPE_INFERENCE_PGO_TYPE_INFER_HELPER_H
|
||||
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
#define TYPE_LIST(V) \
|
||||
V(Class, class) \
|
||||
V(ClassInstance, classInstance) \
|
||||
V(Builtin, builtin) \
|
||||
V(Other, other)
|
||||
|
||||
struct CollectedType {
|
||||
explicit CollectedType(Chunk *chunk) : classTypes(chunk),
|
||||
classInstanceTypes(chunk),
|
||||
builtinTypes(chunk),
|
||||
otherTypes(chunk) {}
|
||||
|
||||
bool AllInSameKind() const
|
||||
{
|
||||
uint8_t kind = classTypes.empty() ? 0 : 1;
|
||||
kind += classInstanceTypes.empty() ? 0 : 1;
|
||||
kind += builtinTypes.empty() ? 0 : 1;
|
||||
kind += otherTypes.empty() ? 0 : 1;
|
||||
return kind == 1;
|
||||
}
|
||||
|
||||
#define DEFINE_TYPE_SET(V, name) \
|
||||
ChunkSet<GateType> name##Types;
|
||||
|
||||
TYPE_LIST(DEFINE_TYPE_SET)
|
||||
#undef DEFINE_TYPE_SET
|
||||
};
|
||||
|
||||
class TypeStrategy {
|
||||
public:
|
||||
TypeStrategy() = default;
|
||||
virtual ~TypeStrategy() = default;
|
||||
virtual bool CheckAndInsert(CollectedType &types, const GateType &type, TSManager *tsManager) = 0;
|
||||
virtual void Merge(ChunkSet<GateType> &inferTypes, CollectedType &types, TSManager *tsManager) = 0;
|
||||
};
|
||||
|
||||
#define DEFINE_TYPE_STRATEGY_DERIVED_CLASS(name, ...) \
|
||||
class name##TypeStrategy : public TypeStrategy { \
|
||||
public: \
|
||||
virtual bool CheckAndInsert(CollectedType &types, const GateType &type, TSManager *tsManager) override; \
|
||||
virtual void Merge(ChunkSet<GateType> &inferTypes, CollectedType &types, TSManager *tsManager) override; \
|
||||
};
|
||||
|
||||
TYPE_LIST(DEFINE_TYPE_STRATEGY_DERIVED_CLASS)
|
||||
#undef DEFINE_TYPE_STRATEGY_DERIVED_CLASS
|
||||
|
||||
class PGOTypeInferHelper {
|
||||
public:
|
||||
PGOTypeInferHelper(TSManager *tsManager) : tsManager_(tsManager)
|
||||
{
|
||||
#define ADD_STRATEGY(name, ...) \
|
||||
strategies_.push_back(std::make_unique<name##TypeStrategy>());
|
||||
|
||||
TYPE_LIST(ADD_STRATEGY)
|
||||
#undef ADD_STRATEGY
|
||||
}
|
||||
~PGOTypeInferHelper() = default;
|
||||
|
||||
void CollectGateType(CollectedType &types, GateType tsType, PGORWOpType pgoTypes);
|
||||
|
||||
ChunkSet<GateType> GetInferTypes(Chunk *chunk, CollectedType &types, JSTaggedValue prop);
|
||||
|
||||
private:
|
||||
inline bool NoNeedUpdate(const ChunkSet<GateType> &types) const
|
||||
{
|
||||
return types.size() <= 1;
|
||||
}
|
||||
|
||||
void CheckAndInsert(CollectedType &types, GateType type);
|
||||
void UpdateType(CollectedType &types, JSTaggedValue prop);
|
||||
void InferTypeForClass(ChunkSet<GateType> &types, JSTaggedValue prop);
|
||||
void EliminateSubclassTypes(ChunkSet<GateType> &types);
|
||||
void ComputeCommonSuperClassTypes(ChunkSet<GateType> &types, JSTaggedValue prop);
|
||||
void InferTypeForBuiltin(ChunkSet<GateType> &types);
|
||||
|
||||
TSManager *tsManager_ {nullptr};
|
||||
std::vector<std::unique_ptr<TypeStrategy>> strategies_ {};
|
||||
};
|
||||
#undef TYPE_LIST
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_TYPE_INFERENCE_PGO_TYPE_INFER_HELPER_H
|
@ -20,7 +20,6 @@
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/global_env_fields.h"
|
||||
#include "ecmascript/jspandafile/program_object.h"
|
||||
#include "ecmascript/ts_types/ts_type_accessor.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
ParamType TypeInfoAccessor::PGOSampleTypeToParamType() const
|
||||
@ -397,21 +396,6 @@ InlineTypeInfoAccessor::InlineTypeInfoAccessor(
|
||||
}
|
||||
}
|
||||
|
||||
GlobalTSTypeRef InlineTypeInfoAccessor::GetAccessorFuncGT() const
|
||||
{
|
||||
GateType receiverType = acc_.GetGateType(receiver_);
|
||||
receiverType = tsManager_->TryNarrowUnionType(receiverType);
|
||||
GlobalTSTypeRef classInstanceGT = receiverType.GetGTRef();
|
||||
GlobalTSTypeRef classGT = tsManager_->GetClassType(classInstanceGT);
|
||||
TSTypeAccessor tsTypeAcc(tsManager_, classGT);
|
||||
GateRef constData = acc_.GetValueIn(gate_, 1);
|
||||
uint16_t propIndex = acc_.GetConstantValue(constData);
|
||||
auto methodOffset = acc_.TryGetMethodOffset(gate_);
|
||||
auto prop = compilationEnv_->GetStringFromConstantPool(methodOffset, propIndex);
|
||||
GlobalTSTypeRef funcGT = tsTypeAcc.GetAccessorGT(prop, IsCallSetter());
|
||||
return funcGT;
|
||||
}
|
||||
|
||||
PropertyLookupResult InlineTypeInfoAccessor::GetAccessorPlr() const
|
||||
{
|
||||
GateRef constData = acc_.GetValueIn(gate_, 1);
|
||||
|
@ -22,7 +22,6 @@
|
||||
#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 {
|
||||
@ -36,7 +35,6 @@ public:
|
||||
{
|
||||
pgoType_ = acc_.TryGetPGOType(gate);
|
||||
// NOTICE-PGO: wx delete in part3
|
||||
tsManager_ = compilationEnv_->GetTSManager();
|
||||
ptManager_ = compilationEnv_->GetPTManager();
|
||||
}
|
||||
|
||||
@ -62,7 +60,6 @@ protected:
|
||||
GateRef gate_;
|
||||
PGOTypeRef pgoType_;
|
||||
// NOTICE-PGO: wx delete in part3
|
||||
TSManager *tsManager_ {nullptr};
|
||||
PGOTypeManager *ptManager_ {nullptr};
|
||||
};
|
||||
|
||||
@ -204,12 +201,9 @@ public:
|
||||
return GetCtorGT().IsBuiltinModule();
|
||||
}
|
||||
|
||||
bool IsBuiltinConstructor(BuiltinTypeId type)
|
||||
bool IsBuiltinConstructor([[maybe_unused]] BuiltinTypeId type)
|
||||
{
|
||||
if (compilationEnv_->IsJitCompiler()) {
|
||||
return false;
|
||||
}
|
||||
return tsManager_->IsBuiltinConstructor(type, GetCtorGT());
|
||||
return false; // NOTICE-PGO:: tsManager_->IsBuiltinConstructor(type, GetCtorGT());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -239,14 +233,6 @@ public:
|
||||
NO_COPY_SEMANTIC(SuperCallTypeInfoAccessor);
|
||||
NO_MOVE_SEMANTIC(SuperCallTypeInfoAccessor);
|
||||
|
||||
bool IsClassTypeKind() const
|
||||
{
|
||||
if (compilationEnv_->IsJitCompiler()) {
|
||||
return false;
|
||||
}
|
||||
return tsManager_->IsClassTypeKind(acc_.GetGateType(ctor_));
|
||||
}
|
||||
|
||||
bool IsValidCallMethodId() const
|
||||
{
|
||||
return pgoType_.IsValidCallMethodId();
|
||||
@ -625,14 +611,6 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsClassInstanceTypeKind() const
|
||||
{
|
||||
if (compilationEnv_->IsJitCompiler()) {
|
||||
return false;
|
||||
}
|
||||
return tsManager_->IsClassInstanceTypeKind(acc_.GetGateType(receiver_));
|
||||
}
|
||||
|
||||
bool IsValidCallMethodId() const
|
||||
{
|
||||
return pgoType_.IsValidCallMethodId();
|
||||
@ -700,7 +678,6 @@ public:
|
||||
|
||||
private:
|
||||
PropertyLookupResult GetAccessorPlr() const;
|
||||
GlobalTSTypeRef GetAccessorFuncGT() const;
|
||||
|
||||
GateRef receiver_;
|
||||
CallKind kind_ {CallKind::INVALID};
|
||||
@ -766,14 +743,6 @@ public:
|
||||
return receiver_;
|
||||
}
|
||||
|
||||
GateType GetReceiverGateType() const
|
||||
{
|
||||
if (compilationEnv_->IsJitCompiler()) {
|
||||
return acc_.GetGateType(receiver_);
|
||||
}
|
||||
return tsManager_->TryNarrowUnionType(acc_.GetGateType(receiver_));
|
||||
}
|
||||
|
||||
protected:
|
||||
Chunk *chunk_;
|
||||
AccessMode mode_;
|
||||
@ -1060,14 +1029,6 @@ public:
|
||||
return types_[0].GetGlobalsId();
|
||||
}
|
||||
|
||||
bool IsBuiltinInstanceType(BuiltinTypeId type) const
|
||||
{
|
||||
if (compilationEnv_->IsJitCompiler()) {
|
||||
return false;
|
||||
}
|
||||
return tsManager_->IsBuiltinInstanceType(type, GetReceiverGateType());
|
||||
}
|
||||
|
||||
OnHeapMode TryGetHeapMode() const
|
||||
{
|
||||
return acc_.TryGetOnHeapMode(gate_);
|
||||
|
@ -1,322 +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.
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/type_recorder.h"
|
||||
|
||||
#include "ecmascript/compiler/ts_hclass_generator.h"
|
||||
#include "ecmascript/jspandafile/type_literal_extractor.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler_layout.h"
|
||||
#include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
|
||||
#include "ecmascript/ts_types/ts_type_parser.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
using PGOHClassTreeDesc = pgo::PGOHClassTreeDesc;
|
||||
using PGOType = pgo::PGOType;
|
||||
using PGOObjectInfo = pgo::PGOObjectInfo;
|
||||
TypeRecorder::TypeRecorder(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral,
|
||||
TSManager *tsManager, const CString &recordName, PGOProfilerDecoder *decoder,
|
||||
const MethodPcInfo &methodPCInfo, const Bytecodes *bytecodes, bool enableOptTrackField)
|
||||
: argTypes_(methodLiteral->GetNumArgsWithCallField() + static_cast<size_t>(TypedArgIdx::NUM_OF_TYPED_ARGS),
|
||||
GateType::AnyType()), decoder_(decoder), enableOptTrackField_(enableOptTrackField),
|
||||
pcOffsets_(methodPCInfo.pcOffsets), bytecodes_(bytecodes)
|
||||
{
|
||||
TSHClassGenerator generator(tsManager);
|
||||
if (jsPandaFile->HasTSTypes(recordName)) {
|
||||
LoadTypes(jsPandaFile, methodLiteral, tsManager, recordName);
|
||||
}
|
||||
LoadTypesFromPGO(jsPandaFile, methodLiteral, recordName);
|
||||
CreateTypesForPGO(jsPandaFile, methodLiteral, tsManager, recordName);
|
||||
generator.GenerateTSHClasses();
|
||||
}
|
||||
|
||||
void TypeRecorder::LoadTypes(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral,
|
||||
TSManager *tsManager, const CString &recordName)
|
||||
{
|
||||
TSTypeParser typeParser(tsManager);
|
||||
panda_file::File::EntityId fieldId = methodLiteral->GetMethodId();
|
||||
uint32_t methodOffset = fieldId.GetOffset();
|
||||
TypeAnnotationExtractor annoExtractor(jsPandaFile, methodOffset);
|
||||
GlobalTSTypeRef funcGT = typeParser.CreateGT(jsPandaFile, recordName, annoExtractor.GetMethodTypeOffset());
|
||||
GlobalTSTypeRef thisGT;
|
||||
annoExtractor.EnumerateInstsAndTypes([this, &typeParser, &jsPandaFile, &recordName,
|
||||
&thisGT, tsManager, methodOffset](const int32_t bcIdx, const uint32_t typeId) {
|
||||
GlobalTSTypeRef gt = typeParser.CreateGT(jsPandaFile, recordName, typeId);
|
||||
if (TypeNeedFilter(gt)) {
|
||||
return;
|
||||
}
|
||||
TypeLocation loc(jsPandaFile, methodOffset, bcIdx);
|
||||
CollectLiteralGT(tsManager, loc, gt);
|
||||
|
||||
// The type of a function is recorded as (-1, funcTypeId). If the function is a member of a class,
|
||||
// the type of the class or its instance is is recorded as (-2, classTypeId). If it is a static
|
||||
// member, the type id refers to the type of the class; otherwise, it links to the type of the
|
||||
// instances of the class.
|
||||
if (bcIdx == METHOD_ANNOTATION_THIS_TYPE_OFFSET) {
|
||||
thisGT = gt;
|
||||
return;
|
||||
}
|
||||
auto type = GateType(gt);
|
||||
bcOffsetGtMap_.emplace(bcIdx, type);
|
||||
});
|
||||
const auto &methodList = typeParser.GetMethodList();
|
||||
auto methodIter = methodList.find(methodOffset);
|
||||
if (methodIter != methodList.end()) {
|
||||
const auto &methodInfo = methodIter->second;
|
||||
const auto &bcTypes = methodInfo.GetBCAndTypes();
|
||||
for (const auto &pair : bcTypes) {
|
||||
GlobalTSTypeRef gt = typeParser.CreateGT(jsPandaFile, recordName, pair.second);
|
||||
// if the function type has already recorded in the next pc, we should skip it.
|
||||
if (CheckTypeMarkForDefineFunc(pair.first)) {
|
||||
continue;
|
||||
}
|
||||
bcOffsetGtMap_.emplace(pair.first, GateType(gt));
|
||||
}
|
||||
}
|
||||
LoadArgTypes(tsManager, funcGT, thisGT);
|
||||
}
|
||||
|
||||
void TypeRecorder::CollectLiteralGT(TSManager *tsManager, TypeLocation &loc, GlobalTSTypeRef gt)
|
||||
{
|
||||
int32_t bcIdx = loc.GetBcIdx();
|
||||
if (bcIdx < 0 || bcIdx >= static_cast<int32_t>(pcOffsets_.size())) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (bytecodes_->GetOpcode(pcOffsets_[bcIdx]) == EcmaOpcode::STA_V8) {
|
||||
// bcIndex of literal marked in es2abc maybe in the next bc whose opcode should be sta.
|
||||
bcIdx--;
|
||||
loc.SetBcIdx(bcIdx);
|
||||
}
|
||||
|
||||
EcmaOpcode ecmaOpcode = bytecodes_->GetOpcode(pcOffsets_[bcIdx]);
|
||||
|
||||
switch (ecmaOpcode) {
|
||||
case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8:
|
||||
case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: {
|
||||
if (tsManager->IsUserDefinedClassTypeKind(gt)) {
|
||||
tsManager->InsertLiteralGTMap(loc, gt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
|
||||
case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: {
|
||||
if (tsManager->IsObjectTypeKind(gt)) {
|
||||
tsManager->InsertLiteralGTMap(loc, gt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool TypeRecorder::CheckTypeMarkForDefineFunc(uint32_t checkBc) const
|
||||
{
|
||||
// bcOffset of definefunc marked in es2abc maybe in the next bc whose opcode should be sta.
|
||||
uint32_t staBc = checkBc + 1;
|
||||
return bcOffsetGtMap_.find(staBc) != bcOffsetGtMap_.end() &&
|
||||
staBc < pcOffsets_.size() && bytecodes_->GetOpcode(pcOffsets_[staBc]) == EcmaOpcode::STA_V8;
|
||||
}
|
||||
|
||||
void TypeRecorder::LoadTypesFromPGO(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral,
|
||||
const CString &recordName)
|
||||
{
|
||||
auto callback = [this] (uint32_t offset, const PGOType *type) {
|
||||
if (type->IsScalarOpType()) {
|
||||
bcOffsetPGOOpTypeMap_[offset] = reinterpret_cast<const PGOSampleType *>(type);
|
||||
} else if (type->IsRwOpType()) {
|
||||
bcOffsetPGORwTypeMap_[offset] = reinterpret_cast<const PGORWOpType *>(type);
|
||||
} else if (type->IsDefineOpType()) {
|
||||
bcOffsetPGODefOpTypeMap_[offset] = reinterpret_cast<const PGODefineOpType *>(type);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
};
|
||||
if (decoder_ != nullptr) {
|
||||
decoder_->GetTypeInfo(jsPandaFile, recordName, methodLiteral, callback);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeRecorder::CreateTypesForPGO(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral,
|
||||
TSManager *tsManager, const CString &recordName)
|
||||
{
|
||||
TSTypeParser typeParser(tsManager);
|
||||
uint32_t methodOffset = methodLiteral->GetMethodId().GetOffset();
|
||||
const PGOBCInfo *bcInfo = tsManager->GetBytecodeInfoCollector()->GetPGOBCInfo();
|
||||
bcInfo->IterateInfoAndType(methodOffset, [this, &typeParser, methodOffset, &recordName, &jsPandaFile, tsManager]
|
||||
(const PGOBCInfo::Type type, const uint32_t bcIdx, const uint32_t bcOffset, const uint32_t cpIdx) {
|
||||
EcmaOpcode ecmaOpcode = bytecodes_->GetOpcode(pcOffsets_[bcIdx]);
|
||||
if (jsPandaFile->HasTSTypes(recordName) && Bytecodes::IsCallOp(ecmaOpcode)) {
|
||||
auto it = bcOffsetPGOOpTypeMap_.find(bcOffset);
|
||||
if (it == bcOffsetPGOOpTypeMap_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t callTargetMethodOffset = it->second->GetProfileType().GetId();
|
||||
if (callTargetMethodOffset == 0) {
|
||||
return;
|
||||
}
|
||||
// Recompiling the application ABC changes the content, and there may be a calltargetMethodOffset
|
||||
// that does not exist in ABC. Type resolution should be skipped when it does not exist,
|
||||
// or parsing pandafile will fail
|
||||
if (jsPandaFile->GetMethodLiteralByIndex(callTargetMethodOffset) == nullptr) {
|
||||
return;
|
||||
}
|
||||
TypeAnnotationExtractor annoExtractor(jsPandaFile, callTargetMethodOffset);
|
||||
GlobalTSTypeRef funcGT =
|
||||
typeParser.CreateGT(jsPandaFile, recordName, annoExtractor.GetMethodTypeOffset());
|
||||
if (funcGT.IsDefault()) {
|
||||
return;
|
||||
}
|
||||
// Target method was not compiled by AOT.
|
||||
if (!decoder_->Match(jsPandaFile, recordName, pgo::PGOMethodId(callTargetMethodOffset))) {
|
||||
tsManager->SetHotnessFunc(funcGT, false);
|
||||
}
|
||||
GateType callTargetType = GateType(funcGT);
|
||||
bcOffsetCallTargetGtMap_.emplace(bcIdx, callTargetType);
|
||||
return;
|
||||
}
|
||||
auto it = bcOffsetPGODefOpTypeMap_.find(bcOffset);
|
||||
if (it == bcOffsetPGODefOpTypeMap_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TypeLocation loc(jsPandaFile, methodOffset, bcIdx);
|
||||
if (!tsManager->GetLiteralGT(loc).IsDefault()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GlobalTSTypeRef gt = typeParser.CreatePGOGT(TSTypeParser::PGOInfo { jsPandaFile, recordName, methodOffset,
|
||||
cpIdx, PGOSampleType(it->second->GetProfileType()), type, decoder_, enableOptTrackField_ });
|
||||
if (TypeNeedFilter(gt)) {
|
||||
return;
|
||||
}
|
||||
CollectLiteralGT(tsManager, loc, gt);
|
||||
});
|
||||
}
|
||||
|
||||
void TypeRecorder::BindPgoTypeToGateType(const JSPandaFile *jsPandaFile, TSManager *tsManager,
|
||||
const MethodLiteral *methodLiteral) const
|
||||
{
|
||||
uint32_t methodOffset = methodLiteral->GetMethodId().GetOffset();
|
||||
const PGOBCInfo *bcInfo = tsManager->GetBytecodeInfoCollector()->GetPGOBCInfo();
|
||||
bcInfo->IterateInfoAndType(methodOffset, [this, methodOffset, &jsPandaFile, tsManager]
|
||||
(const PGOBCInfo::Type, const uint32_t bcIdx, const uint32_t bcOffset, const uint32_t) {
|
||||
auto it = bcOffsetPGODefOpTypeMap_.find(bcOffset);
|
||||
if (it == bcOffsetPGODefOpTypeMap_.end()) {
|
||||
return;
|
||||
}
|
||||
TypeLocation loc(jsPandaFile, methodOffset, bcIdx);
|
||||
if (!tsManager->GetLiteralGT(loc).IsDefault()) {
|
||||
GlobalTSTypeRef gt = tsManager->GetLiteralGT(loc);
|
||||
PGOHClassTreeDesc *desc;
|
||||
if (decoder_->GetHClassTreeDesc(PGOSampleType(it->second->GetProfileType()), &desc)) {
|
||||
GateType gateType(gt);
|
||||
tsManager->InsertPtToGtMap(desc->GetProfileType(), gateType);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void TypeRecorder::LoadArgTypes(const TSManager *tsManager, GlobalTSTypeRef funcGT, GlobalTSTypeRef thisGT)
|
||||
{
|
||||
argTypes_[static_cast<size_t>(TypedArgIdx::FUNC)] = TryGetFuncType(funcGT);
|
||||
argTypes_[static_cast<size_t>(TypedArgIdx::NEW_TARGET)] = TryGetNewTargetType(tsManager, thisGT);
|
||||
argTypes_[static_cast<size_t>(TypedArgIdx::THIS_OBJECT)] = TryGetThisType(tsManager, funcGT, thisGT);
|
||||
|
||||
if (funcGT.IsDefault()) {
|
||||
return;
|
||||
}
|
||||
size_t extraParasNum = static_cast<size_t>(TypedArgIdx::NUM_OF_TYPED_ARGS);
|
||||
uint32_t numExplicitArgs = tsManager->GetFunctionTypeLength(funcGT);
|
||||
for (uint32_t explicitArgId = 0; explicitArgId < numExplicitArgs; explicitArgId++) {
|
||||
argTypes_[extraParasNum++] = GateType(tsManager->GetFuncParameterTypeGT(funcGT, explicitArgId));
|
||||
}
|
||||
}
|
||||
|
||||
GateType TypeRecorder::TryGetThisType(const TSManager *tsManager, GlobalTSTypeRef funcGT, GlobalTSTypeRef thisGT) const
|
||||
{
|
||||
// The parameter 'this' may be declared explicitly, e.g. foo(this: Person, num: number). In this case, the type
|
||||
// of 'this' is recorded in the type of the function. And this type is preferred over the type derived from
|
||||
// 'thisGT' if both are given.
|
||||
if (!funcGT.IsDefault()) {
|
||||
auto gt = tsManager->GetFuncThisGT(funcGT);
|
||||
if (!gt.IsDefault()) {
|
||||
return GateType(gt);
|
||||
}
|
||||
}
|
||||
return GateType(thisGT);
|
||||
}
|
||||
|
||||
GateType TypeRecorder::TryGetNewTargetType(const TSManager *tsManager, GlobalTSTypeRef thisGT) const
|
||||
{
|
||||
if (thisGT.IsDefault()) {
|
||||
return GateType::AnyType();
|
||||
}
|
||||
|
||||
GateType thisType(thisGT);
|
||||
if (tsManager->IsClassInstanceTypeKind(thisType)) {
|
||||
return GateType(tsManager->GetClassType(thisGT));
|
||||
} else {
|
||||
return thisType;
|
||||
}
|
||||
}
|
||||
|
||||
GateType TypeRecorder::TryGetFuncType(GlobalTSTypeRef funcGT) const
|
||||
{
|
||||
if (funcGT.IsDefault()) {
|
||||
return GateType::AnyType();
|
||||
}
|
||||
return GateType(funcGT);
|
||||
}
|
||||
|
||||
GateType TypeRecorder::GetType(const int32_t offset) const
|
||||
{
|
||||
if (bcOffsetGtMap_.find(offset) != bcOffsetGtMap_.end()) {
|
||||
return bcOffsetGtMap_.at(offset);
|
||||
}
|
||||
return GateType::AnyType();
|
||||
}
|
||||
|
||||
GateType TypeRecorder::GetArgType(const uint32_t argIndex) const
|
||||
{
|
||||
ASSERT(argIndex < argTypes_.size());
|
||||
return argTypes_[argIndex];
|
||||
}
|
||||
|
||||
GateType TypeRecorder::UpdateType(const int32_t offset, const GateType &type) const
|
||||
{
|
||||
auto tempType = GetType(offset);
|
||||
if (!tempType.IsAnyType()) {
|
||||
ASSERT(type.IsAnyType());
|
||||
return tempType;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
GateType TypeRecorder::GetCallTargetType(int32_t offset) const
|
||||
{
|
||||
if (bcOffsetCallTargetGtMap_.find(offset) != bcOffsetCallTargetGtMap_.end()) {
|
||||
return bcOffsetCallTargetGtMap_.at(offset);
|
||||
}
|
||||
return GateType::AnyType();
|
||||
}
|
||||
|
||||
bool TypeRecorder::TypeNeedFilter(GlobalTSTypeRef gt) const
|
||||
{
|
||||
return gt.IsDefault() || gt.IsGenericsModule();
|
||||
}
|
||||
} // namespace panda::ecmascript
|
@ -1,91 +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_RECORDER_H
|
||||
#define ECMASCRIPT_COMPILER_TYPE_RECORDER_H
|
||||
|
||||
#include "ecmascript/compiler/type.h"
|
||||
#include "ecmascript/jspandafile/js_pandafile.h"
|
||||
#include "ecmascript/method.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
using PGODefineOpType = pgo::PGODefineOpType;
|
||||
enum class TypedArgIdx : uint8_t {
|
||||
FUNC = 0,
|
||||
NEW_TARGET,
|
||||
THIS_OBJECT,
|
||||
NUM_OF_TYPED_ARGS,
|
||||
};
|
||||
|
||||
class TypeRecorder {
|
||||
public:
|
||||
TypeRecorder(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral,
|
||||
TSManager *tsManager, const CString &recordName, PGOProfilerDecoder *decoder,
|
||||
const MethodPcInfo &methodPCInfo, const Bytecodes *bytecodes, bool enableOptTrackField);
|
||||
~TypeRecorder() = default;
|
||||
|
||||
GateType GetType(const int32_t offset) const;
|
||||
GateType GetArgType(const uint32_t argIndex) const;
|
||||
GateType UpdateType(const int32_t offset, const GateType &type) const;
|
||||
GateType GetCallTargetType(int32_t offset) const;
|
||||
void BindPgoTypeToGateType(const JSPandaFile *jsPandaFile, TSManager *tsManager,
|
||||
const MethodLiteral *methodLiteral) const;
|
||||
|
||||
static constexpr int METHOD_ANNOTATION_THIS_TYPE_OFFSET = -2;
|
||||
|
||||
private:
|
||||
void LoadTypes(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral,
|
||||
TSManager *tsManager, const CString &recordName);
|
||||
|
||||
void CreateTypesForPGO(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral,
|
||||
TSManager *tsManager, const CString &recordName);
|
||||
|
||||
void LoadTypesFromPGO(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral,
|
||||
const CString &recordName);
|
||||
|
||||
void LoadArgTypes(const TSManager *tsManager, GlobalTSTypeRef funcGT, GlobalTSTypeRef thisGT);
|
||||
|
||||
// This function tries to get the type of 'this'. In success, the type of the class is returned if the function is
|
||||
// a static member, or the type of instances of the class is returned. Otherwise the type 'any' is returned.
|
||||
GateType TryGetThisType(const TSManager *tsManager, GlobalTSTypeRef funcGT, GlobalTSTypeRef thisGT) const;
|
||||
|
||||
// This function tries to get the type of 'newTarget'. In success, the type of the class is returned. Otherwise,
|
||||
// the type 'any' is returned.
|
||||
GateType TryGetNewTargetType(const TSManager *tsManager, GlobalTSTypeRef thisGT) const;
|
||||
|
||||
// This function tries to get the type of the function. On failure, the type 'any' is returned.
|
||||
GateType TryGetFuncType(GlobalTSTypeRef funcGT) const;
|
||||
|
||||
bool TypeNeedFilter(GlobalTSTypeRef gt) const;
|
||||
|
||||
bool CheckTypeMarkForDefineFunc(uint32_t checkBc) const;
|
||||
|
||||
void CollectLiteralGT(TSManager *tsManager, TypeLocation &tLoc, GlobalTSTypeRef gt);
|
||||
|
||||
std::unordered_map<int32_t, GateType> bcOffsetGtMap_ {};
|
||||
std::unordered_map<int32_t, GateType> bcOffsetCallTargetGtMap_ {};
|
||||
std::unordered_map<int32_t, const PGOSampleType*> bcOffsetPGOOpTypeMap_ {};
|
||||
std::unordered_map<int32_t, const PGODefineOpType*> bcOffsetPGODefOpTypeMap_ {};
|
||||
std::unordered_map<int32_t, const PGORWOpType*> bcOffsetPGORwTypeMap_ {};
|
||||
std::vector<GateType> argTypes_;
|
||||
PGOProfilerDecoder *decoder_ {nullptr};
|
||||
bool enableOptTrackField_ {false};
|
||||
const std::vector<const uint8_t*> &pcOffsets_;
|
||||
const Bytecodes *bytecodes_ {nullptr};
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_TYPE_RECORDER_H
|
@ -34,7 +34,7 @@
|
||||
#include "ecmascript/jit/jit.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
bool TypedBytecodeLowering::RunTypedBytecodeLowering()
|
||||
void TypedBytecodeLowering::RunTypedBytecodeLowering()
|
||||
{
|
||||
std::vector<GateRef> gateList;
|
||||
circuit_->GetAllGates(gateList);
|
||||
@ -43,18 +43,6 @@ bool TypedBytecodeLowering::RunTypedBytecodeLowering()
|
||||
auto op = acc_.GetOpCode(gate);
|
||||
if (op == OpCode::JS_BYTECODE) {
|
||||
Lower(gate);
|
||||
allJSBcCount_++;
|
||||
}
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
double typeHitRate = 0.0;
|
||||
auto allTypedOpCount = allJSBcCount_ - allNonTypedOpCount_;
|
||||
if (allTypedOpCount != 0) {
|
||||
typeHitRate = static_cast<double>(hitTypedOpCount_) / static_cast<double>(allTypedOpCount);
|
||||
auto typeThreshold = const_cast<CompilationEnv*>(compilationEnv_)->GetJSOptions().GetTypeThreshold();
|
||||
if (typeHitRate <= typeThreshold) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,10 +58,6 @@ bool TypedBytecodeLowering::RunTypedBytecodeLowering()
|
||||
<< "[" << GetMethodName() << "]"
|
||||
<< "===================="
|
||||
<< "\033[0m";
|
||||
circuit_->PrintAllGatesWithBytecode();
|
||||
LOG_COMPILER(INFO) << "\033[34m" << " =========================== End typeHitRate: "
|
||||
<< std::to_string(typeHitRate)
|
||||
<< " ===========================" << "\033[0m";
|
||||
for (auto a : bytecodeMap_) {
|
||||
if (bytecodeHitTimeMap_.find(a.first) != bytecodeHitTimeMap_.end()) {
|
||||
double rate = static_cast<double>(bytecodeHitTimeMap_[a.first]) / static_cast<double>(a.second);
|
||||
@ -91,8 +75,6 @@ bool TypedBytecodeLowering::RunTypedBytecodeLowering()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void TypedBytecodeLowering::ParseOptBytecodeRange()
|
||||
@ -1419,7 +1401,7 @@ bool TypedBytecodeLowering::TryLowerNewBuiltinConstructor(GateRef gate)
|
||||
void TypedBytecodeLowering::LowerTypedSuperCall(GateRef gate)
|
||||
{
|
||||
SuperCallTypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
|
||||
if (!tacc.IsClassTypeKind() && !tacc.IsValidCallMethodId()) {
|
||||
if (!tacc.IsValidCallMethodId()) {
|
||||
return;
|
||||
}
|
||||
AddProfiling(gate);
|
||||
|
@ -22,7 +22,6 @@
|
||||
#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/object_access_helper.h"
|
||||
#include "ecmascript/compiler/pass_manager.h"
|
||||
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
|
||||
#include "ecmascript/compiler/type_info_accessors.h"
|
||||
@ -46,7 +45,6 @@ public:
|
||||
acc_(circuit),
|
||||
builder_(circuit, ctx->GetCompilerConfig()),
|
||||
dependEntry_(circuit->GetDependRoot()),
|
||||
tsManager_(ctx->GetTSManager()),
|
||||
chunk_(chunk),
|
||||
enableLog_(enableLog),
|
||||
enableTypeLog_(enableTypeLog),
|
||||
@ -69,7 +67,7 @@ public:
|
||||
|
||||
~TypedBytecodeLowering() = default;
|
||||
|
||||
bool RunTypedBytecodeLowering();
|
||||
void RunTypedBytecodeLowering();
|
||||
|
||||
private:
|
||||
bool IsLogEnabled() const
|
||||
@ -121,7 +119,6 @@ private:
|
||||
GateRef BuildNamedPropertyAccess(GateRef hir, GateRef receiver, GateRef holder, PropertyLookupResult plr);
|
||||
GateRef BuildNamedPropertyAccess(GateRef hir, GateRef receiver, GateRef holder,
|
||||
GateRef value, PropertyLookupResult plr, uint32_t receiverHClassIndex = 0);
|
||||
using AccessMode = PGOObjectAccessHelper::AccessMode;
|
||||
bool TryLowerTypedLdObjByNameForBuiltin(GateRef gate);
|
||||
bool TryLowerTypedLdObjByNameForBuiltinsId(const LoadBulitinObjTypeInfoAccessor &tacc, BuiltinTypeId type);
|
||||
bool TryLowerTypedLdObjByNameForBuiltin(const LoadBulitinObjTypeInfoAccessor &tacc);
|
||||
@ -231,7 +228,6 @@ private:
|
||||
GateAccessor acc_;
|
||||
CircuitBuilder builder_;
|
||||
GateRef dependEntry_ {Gate::InvalidGateRef};
|
||||
TSManager *tsManager_ {nullptr};
|
||||
Chunk *chunk_ {nullptr};
|
||||
bool enableLog_ {false};
|
||||
bool enableTypeLog_ {false};
|
||||
|
@ -14,10 +14,12 @@
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/typed_hcr_lowering.h"
|
||||
|
||||
#include "ecmascript/compiler/builtins_lowering.h"
|
||||
#include "ecmascript/compiler/builtins/builtins_string_stub_builder.h"
|
||||
#include "ecmascript/compiler/mcr_gate_meta_data.h"
|
||||
#include "ecmascript/compiler/new_object_stub_builder.h"
|
||||
#include "ecmascript/compiler/builtins/builtins_string_stub_builder.h"
|
||||
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
|
||||
#include "ecmascript/compiler/rt_call_signature.h"
|
||||
#include "ecmascript/compiler/share_gate_meta_data.h"
|
||||
#include "ecmascript/compiler/variable_type.h"
|
||||
@ -31,7 +33,6 @@
|
||||
#include "ecmascript/js_primitive_ref.h"
|
||||
#include "ecmascript/linked_hash_table.h"
|
||||
#include "ecmascript/message_string.h"
|
||||
#include "ecmascript/subtyping_operator.h"
|
||||
#include "ecmascript/vtable.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
|
@ -104,7 +104,6 @@ public:
|
||||
CompilationEnv *env,
|
||||
RPOVisitor* visitor,
|
||||
CompilationConfig* cmpCfg,
|
||||
TSManager* tsManager,
|
||||
Chunk* chunk,
|
||||
bool enableLoweringBuiltin)
|
||||
: PassVisitor(circuit, chunk, visitor),
|
||||
@ -113,7 +112,6 @@ public:
|
||||
acc_(circuit),
|
||||
builder_(circuit, cmpCfg),
|
||||
dependEntry_(circuit->GetDependRoot()),
|
||||
tsManager_(tsManager),
|
||||
enableLoweringBuiltin_(enableLoweringBuiltin)
|
||||
{
|
||||
if (cmpCfg != nullptr) {
|
||||
@ -276,7 +274,6 @@ private:
|
||||
GateAccessor acc_;
|
||||
CircuitBuilder builder_;
|
||||
GateRef dependEntry_;
|
||||
[[maybe_unused]] TSManager *tsManager_ {nullptr};
|
||||
bool enableLoweringBuiltin_ {false};
|
||||
bool typedOpProfiling_ {false};
|
||||
};
|
||||
|
@ -35,7 +35,6 @@ foreach(file, test_js_files) {
|
||||
dst_file = rebase_path(test_abc)
|
||||
extra_args = [ "--module" ]
|
||||
extra_args += [ "--merge-abc" ]
|
||||
extra_args += [ "--type-extractor" ]
|
||||
|
||||
in_puts = [ test_js ]
|
||||
out_puts = [ test_abc ]
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "ecmascript/base/aligned_struct.h"
|
||||
#include "ecmascript/compiler/argument_accessor.h"
|
||||
#include "ecmascript/deoptimizer/calleeReg.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/js_handle.h"
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
#include "ecmascript/stackmap/llvm/llvm_stackmap_type.h"
|
||||
|
@ -602,20 +602,6 @@ CString *HeapSnapshot::GenerateNodeName(TaggedObject *entry)
|
||||
return GetString("MachineCode");
|
||||
case JSType::CLASS_INFO_EXTRACTOR:
|
||||
return GetString("ClassInfoExtractor");
|
||||
case JSType::TS_OBJECT_TYPE:
|
||||
return GetString("TSObjectType");
|
||||
case JSType::TS_INTERFACE_TYPE:
|
||||
return GetString("TSInterfaceType");
|
||||
case JSType::TS_CLASS_TYPE:
|
||||
return GetString("TSClassType");
|
||||
case JSType::TS_UNION_TYPE:
|
||||
return GetString("TSUnionType");
|
||||
case JSType::TS_CLASS_INSTANCE_TYPE:
|
||||
return GetString("TSClassInstanceType");
|
||||
case JSType::TS_FUNCTION_TYPE:
|
||||
return GetString("TSFunctionType");
|
||||
case JSType::TS_ARRAY_TYPE:
|
||||
return GetString("TSArrayType");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ foreach(file, test_js_files) {
|
||||
dst_file = rebase_path(test_abc)
|
||||
extra_args = [ "--module" ]
|
||||
extra_args += [ "--merge-abc" ]
|
||||
extra_args += [ "--type-extractor" ]
|
||||
|
||||
in_puts = [ test_js ]
|
||||
out_puts = [ test_abc ]
|
||||
|
@ -127,7 +127,6 @@
|
||||
#include "ecmascript/tagged_tree.h"
|
||||
#include "ecmascript/template_map.h"
|
||||
#include "ecmascript/transitions_dictionary.h"
|
||||
#include "ecmascript/ts_types/ts_type.h"
|
||||
#include "ecmascript/js_displaynames.h"
|
||||
#include "ecmascript/js_list_format.h"
|
||||
#include "js_hclass.h"
|
||||
@ -436,24 +435,6 @@ CString JSHClass::DumpJSType(JSType type)
|
||||
return "ClassInfoExtractor";
|
||||
case JSType::JS_API_ARRAY_LIST:
|
||||
return "ArrayList";
|
||||
case JSType::TS_OBJECT_TYPE:
|
||||
return "TSObjectType";
|
||||
case JSType::TS_CLASS_TYPE:
|
||||
return "TSClassType";
|
||||
case JSType::TS_INTERFACE_TYPE:
|
||||
return "TSInterfaceType";
|
||||
case JSType::TS_CLASS_INSTANCE_TYPE:
|
||||
return "TSClassInstanceType";
|
||||
case JSType::TS_UNION_TYPE:
|
||||
return "TSUnionType";
|
||||
case JSType::TS_FUNCTION_TYPE:
|
||||
return "TSFunctionType";
|
||||
case JSType::TS_ARRAY_TYPE:
|
||||
return "TSArrayType";
|
||||
case JSType::TS_ITERATOR_INSTANCE_TYPE:
|
||||
return "TSIteratorInstanceType";
|
||||
case JSType::TS_NAMESPACE_TYPE:
|
||||
return "TSNamespaceType";
|
||||
case JSType::JS_API_ARRAYLIST_ITERATOR:
|
||||
return "JSArraylistIterator";
|
||||
case JSType::LINKED_NODE:
|
||||
@ -1203,33 +1184,6 @@ static void DumpObject(TaggedObject *obj, std::ostream &os)
|
||||
case JSType::JS_API_LIGHT_WEIGHT_SET_ITERATOR:
|
||||
JSAPILightWeightSetIterator::Cast(obj)->Dump(os);
|
||||
break;
|
||||
case JSType::TS_OBJECT_TYPE:
|
||||
TSObjectType::Cast(obj)->Dump(os);
|
||||
break;
|
||||
case JSType::TS_CLASS_TYPE:
|
||||
TSClassType::Cast(obj)->Dump(os);
|
||||
break;
|
||||
case JSType::TS_INTERFACE_TYPE:
|
||||
TSInterfaceType::Cast(obj)->Dump(os);
|
||||
break;
|
||||
case JSType::TS_CLASS_INSTANCE_TYPE:
|
||||
TSClassInstanceType::Cast(obj)->Dump(os);
|
||||
break;
|
||||
case JSType::TS_UNION_TYPE:
|
||||
TSUnionType::Cast(obj)->Dump(os);
|
||||
break;
|
||||
case JSType::TS_FUNCTION_TYPE:
|
||||
TSFunctionType::Cast(obj)->Dump(os);
|
||||
break;
|
||||
case JSType::TS_ARRAY_TYPE:
|
||||
TSArrayType::Cast(obj)->Dump(os);
|
||||
break;
|
||||
case JSType::TS_ITERATOR_INSTANCE_TYPE:
|
||||
TSIteratorInstanceType::Cast(obj)->Dump(os);
|
||||
break;
|
||||
case JSType::TS_NAMESPACE_TYPE:
|
||||
TSNamespaceType::Cast(obj)->Dump(os);
|
||||
break;
|
||||
case JSType::LINKED_NODE:
|
||||
LinkedNode::Cast(obj)->Dump(os);
|
||||
break;
|
||||
@ -3649,274 +3603,6 @@ void ClassInfoExtractor::Dump(std::ostream &os) const
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void TSObjectType::Dump(std::ostream &os) const
|
||||
{
|
||||
os << " - TSObjectType globalTSTypeRef: ";
|
||||
GlobalTSTypeRef gt = GetGT();
|
||||
uint64_t globalTSTypeRef = gt.GetType();
|
||||
os << globalTSTypeRef;
|
||||
os << "\n";
|
||||
os << " - TSObjectType moduleId: ";
|
||||
uint32_t moduleId = gt.GetModuleId();
|
||||
os << moduleId;
|
||||
os << "\n";
|
||||
os << " - TSObjectType localTypeId: ";
|
||||
uint32_t localTypeId = gt.GetLocalId();
|
||||
os << localTypeId;
|
||||
os << "\n";
|
||||
os << " - ObjLayoutInfo: ";
|
||||
DumpArrayClass(TaggedArray::Cast(GetObjLayoutInfo().GetTaggedObject()), os);
|
||||
|
||||
os << " - Index signature: ";
|
||||
if (GetIndexSigns().IsUndefined()) {
|
||||
os << " no index signature type " << "\n";
|
||||
} else {
|
||||
DumpArrayClass(TaggedArray::Cast(GetIndexSigns().GetTaggedObject()), os);
|
||||
}
|
||||
}
|
||||
|
||||
void TSClassType::Dump(std::ostream &os) const
|
||||
{
|
||||
os << " - Dump TSClassType - " << "\n";
|
||||
os << " - TSClassType globalTSTypeRef: ";
|
||||
GlobalTSTypeRef gt = GetGT();
|
||||
uint64_t globalTSTypeRef = gt.GetType();
|
||||
os << globalTSTypeRef;
|
||||
os << "\n";
|
||||
os << " - TSClassType moduleId: ";
|
||||
uint32_t moduleId = gt.GetModuleId();
|
||||
os << moduleId;
|
||||
os << "\n";
|
||||
os << " - TSClassType localTypeId: ";
|
||||
uint32_t localTypeId = gt.GetLocalId();
|
||||
os << localTypeId;
|
||||
os << "\n";
|
||||
os << " - ExtensionTypeGT: ";
|
||||
GlobalTSTypeRef extensionGT = GetExtensionGT();
|
||||
if (extensionGT.IsDefault()) {
|
||||
os << " (base class type) ";
|
||||
} else {
|
||||
os << extensionGT.GetType();
|
||||
}
|
||||
os << "\n";
|
||||
|
||||
CString hasLinked = GetHasLinked() ? "true" : "false";
|
||||
os << " - HasLinked: " << hasLinked << "\n";
|
||||
|
||||
os << " - InstanceType: " << "\n";
|
||||
if (GetInstanceType().IsTSObjectType()) {
|
||||
TSObjectType *instanceType = TSObjectType::Cast(GetInstanceType().GetTaggedObject());
|
||||
instanceType->Dump(os);
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
os << " - ConstructorType: " << "\n";
|
||||
if (GetConstructorType().IsTSObjectType()) {
|
||||
TSObjectType *constructorType = TSObjectType::Cast(GetConstructorType().GetTaggedObject());
|
||||
constructorType->Dump(os);
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
os << " - PrototypeType: " << "\n";
|
||||
if (GetPrototypeType().IsTSObjectType()) {
|
||||
TSObjectType *prototypeType = TSObjectType::Cast(GetPrototypeType().GetTaggedObject());
|
||||
prototypeType->Dump(os);
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
os << " - Index signature: ";
|
||||
if (GetIndexSigns().IsUndefined()) {
|
||||
os << " no index signature type " << "\n";
|
||||
} else {
|
||||
DumpArrayClass(TaggedArray::Cast(GetIndexSigns().GetTaggedObject()), os);
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void TSInterfaceType::Dump(std::ostream &os) const
|
||||
{
|
||||
os << " - Dump Interface Type - " << "\n";
|
||||
os << " - TSInterfaceType globalTSTypeRef: ";
|
||||
GlobalTSTypeRef gt = GetGT();
|
||||
uint64_t globalTSTypeRef = gt.GetType();
|
||||
os << globalTSTypeRef;
|
||||
os << "\n";
|
||||
os << " - TSInterfaceType moduleId: ";
|
||||
uint32_t moduleId = gt.GetModuleId();
|
||||
os << moduleId;
|
||||
os << "\n";
|
||||
os << " - TSInterfaceType localTypeId: ";
|
||||
uint32_t localTypeId = gt.GetLocalId();
|
||||
os << localTypeId;
|
||||
os << "\n";
|
||||
os << " - Extends TypeId: " << "\n";
|
||||
if (TaggedArray::Cast(GetExtends().GetTaggedObject())->GetLength() == 0) {
|
||||
os << " (base interface type) "<< "\n";
|
||||
}
|
||||
DumpArrayClass(TaggedArray::Cast(GetExtends().GetTaggedObject()), os);
|
||||
|
||||
os << " - Fields: " << "\n";
|
||||
if (GetFields().IsTSObjectType()) {
|
||||
TSObjectType *fieldsType = TSObjectType::Cast(GetFields().GetTaggedObject());
|
||||
fieldsType->Dump(os);
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
os << " - Index signature: ";
|
||||
if (GetIndexSigns().IsUndefined()) {
|
||||
os << " no index signature type " << "\n";
|
||||
} else {
|
||||
DumpArrayClass(TaggedArray::Cast(GetIndexSigns().GetTaggedObject()), os);
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void TSClassInstanceType::Dump(std::ostream &os) const
|
||||
{
|
||||
os << " - Dump ClassInstance Type - " << "\n";
|
||||
os << " - TSClassInstanceType globalTSTypeRef: ";
|
||||
GlobalTSTypeRef gt = GetGT();
|
||||
uint64_t globalTSTypeRef = gt.GetType();
|
||||
os << globalTSTypeRef;
|
||||
os << "\n";
|
||||
os << " - TSClassInstanceType moduleId: ";
|
||||
uint32_t moduleId = gt.GetModuleId();
|
||||
os << moduleId;
|
||||
os << "\n";
|
||||
os << " - TSClassInstanceType localTypeId: ";
|
||||
uint32_t localTypeId = gt.GetLocalId();
|
||||
os << localTypeId;
|
||||
os << "\n";
|
||||
|
||||
os << " - createClassType GT: ";
|
||||
GlobalTSTypeRef createClassTypeGT = GetClassGT();
|
||||
os << createClassTypeGT.GetType();
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void TSUnionType::Dump(std::ostream &os) const
|
||||
{
|
||||
os << " - Dump UnionType Type - " << "\n";
|
||||
os << " - TSUnionType globalTSTypeRef: ";
|
||||
GlobalTSTypeRef gt = GetGT();
|
||||
uint64_t globalTSTypeRef = gt.GetType();
|
||||
os << globalTSTypeRef;
|
||||
os << "\n";
|
||||
os << " - TSUnionType moduleId: ";
|
||||
uint32_t moduleId = gt.GetModuleId();
|
||||
os << moduleId;
|
||||
os << "\n";
|
||||
os << " - TSUnionType localTypeId: ";
|
||||
uint32_t localTypeId = gt.GetLocalId();
|
||||
os << localTypeId;
|
||||
os << "\n";
|
||||
os << " - TSUnionType TypeId: " << "\n";
|
||||
DumpArrayClass(TaggedArray::Cast(GetComponents().GetTaggedObject()), os);
|
||||
}
|
||||
|
||||
void TSFunctionType::Dump(std::ostream &os) const
|
||||
{
|
||||
os << " - Dump TSFunctionType - " << "\n";
|
||||
os << " - TSFunctionType globalTSTypeRef: ";
|
||||
GlobalTSTypeRef gt = GetGT();
|
||||
uint64_t globalTSTypeRef = gt.GetType();
|
||||
os << globalTSTypeRef;
|
||||
os << "\n";
|
||||
os << " - TSFunctionType moduleId: ";
|
||||
uint32_t moduleId = gt.GetModuleId();
|
||||
os << moduleId;
|
||||
os << "\n";
|
||||
os << " - TSFunctionType localTypeId: ";
|
||||
uint32_t localTypeId = gt.GetLocalId();
|
||||
os << localTypeId;
|
||||
os << "\n";
|
||||
os << " - TSFunctionType Name: ";
|
||||
JSTaggedValue name = GetName();
|
||||
if (name.IsString()) {
|
||||
os << ConvertToString(EcmaString::Cast(name.GetTaggedObject()));
|
||||
}
|
||||
os << "\n";
|
||||
os << " - TSFunctionType ParameterTypeIds: " << "\n";
|
||||
DumpArrayClass(TaggedArray::Cast(GetParameterTypes().GetTaggedObject()), os);
|
||||
os << " - TSFunctionType ReturnType: " << GetReturnGT().GetType() << "\n";
|
||||
os << " - TSFunctionType ThisType: " << GetThisGT().GetType() << "\n";
|
||||
TSFunctionType::Visibility visibility = GetVisibility();
|
||||
switch (visibility) {
|
||||
case TSFunctionType::Visibility::PUBLIC:
|
||||
os << " - Visibility: public";
|
||||
break;
|
||||
case TSFunctionType::Visibility::PRIVATE:
|
||||
os << " - Visibility: private";
|
||||
break;
|
||||
case TSFunctionType::Visibility::PROTECTED:
|
||||
os << " - Visibility: protected";
|
||||
break;
|
||||
}
|
||||
os << " | IsStatic: " << std::boolalpha << GetStatic();
|
||||
os << " | IsAsync: " << std::boolalpha << GetAsync();
|
||||
os << " | IsGenerator: " << std::boolalpha << GetGenerator();
|
||||
os << " | IsGetterSetter: " << std::boolalpha << GetIsGetterSetter();
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void TSArrayType::Dump(std::ostream &os) const
|
||||
{
|
||||
os << " - Dump TSArrayType - " << "\n";
|
||||
os << " - TSArrayType globalTSTypeRef: ";
|
||||
GlobalTSTypeRef gt = GetGT();
|
||||
os << gt.GetType();
|
||||
os << "\n";
|
||||
os << " - TSArrayType ElementGT: ";
|
||||
os << GetElementGT().GetType();
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void TSIteratorInstanceType::Dump(std::ostream &os) const
|
||||
{
|
||||
os << " - Dump IteratorInstance Type - " << "\n";
|
||||
os << " - TSIteratorInstanceType globalTSTypeRef: ";
|
||||
GlobalTSTypeRef gt = GetGT();
|
||||
uint64_t globalTSTypeRef = gt.GetType();
|
||||
os << globalTSTypeRef;
|
||||
os << "\n";
|
||||
os << " - TSIteratorInstanceType moduleId: ";
|
||||
uint32_t moduleId = gt.GetModuleId();
|
||||
os << moduleId;
|
||||
os << "\n";
|
||||
os << " - TSIteratorInstanceType localTypeId: ";
|
||||
uint32_t localTypeId = gt.GetLocalId();
|
||||
os << localTypeId;
|
||||
os << "\n";
|
||||
|
||||
os << " - TSIteratorInstanceType KindGT: ";
|
||||
os << GetKindGT().GetType();
|
||||
os << "\n";
|
||||
|
||||
os << " - TSIteratorInstanceType ElementGT: ";
|
||||
os << GetElementGT().GetType();
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void TSNamespaceType::Dump(std::ostream &os) const
|
||||
{
|
||||
os << " - Dump Namespace Type - " << "\n";
|
||||
os << " - TSNamespaceType globalTSTypeRef: ";
|
||||
GlobalTSTypeRef gt = GetGT();
|
||||
uint64_t globalTSTypeRef = gt.GetType();
|
||||
os << globalTSTypeRef;
|
||||
os << "\n";
|
||||
os << " - TSNamespaceType moduleId: ";
|
||||
uint32_t moduleId = gt.GetModuleId();
|
||||
os << moduleId;
|
||||
os << "\n";
|
||||
os << " - TSNamespaceType localTypeId: ";
|
||||
uint32_t localTypeId = gt.GetLocalId();
|
||||
os << localTypeId;
|
||||
os << "\n";
|
||||
os << " - Properties: ";
|
||||
DumpArrayClass(TaggedArray::Cast(GetPropertyType().GetTaggedObject()), os);
|
||||
}
|
||||
|
||||
void SourceTextModule::Dump(std::ostream &os) const
|
||||
{
|
||||
os << " - Environment: ";
|
||||
@ -4737,33 +4423,6 @@ static void DumpObject(TaggedObject *obj, std::vector<Reference> &vec, bool isVm
|
||||
case JSType::CLASS_INFO_EXTRACTOR:
|
||||
ClassInfoExtractor::Cast(obj)->DumpForSnapshot(vec);
|
||||
return;
|
||||
case JSType::TS_OBJECT_TYPE:
|
||||
TSObjectType::Cast(obj)->DumpForSnapshot(vec);
|
||||
return;
|
||||
case JSType::TS_CLASS_TYPE:
|
||||
TSClassType::Cast(obj)->DumpForSnapshot(vec);
|
||||
return;
|
||||
case JSType::TS_INTERFACE_TYPE:
|
||||
TSInterfaceType::Cast(obj)->DumpForSnapshot(vec);
|
||||
return;
|
||||
case JSType::TS_CLASS_INSTANCE_TYPE:
|
||||
TSClassInstanceType::Cast(obj)->DumpForSnapshot(vec);
|
||||
return;
|
||||
case JSType::TS_UNION_TYPE:
|
||||
TSUnionType::Cast(obj)->DumpForSnapshot(vec);
|
||||
return;
|
||||
case JSType::TS_FUNCTION_TYPE:
|
||||
TSFunctionType::Cast(obj)->DumpForSnapshot(vec);
|
||||
return;
|
||||
case JSType::TS_ARRAY_TYPE:
|
||||
TSArrayType::Cast(obj)->DumpForSnapshot(vec);
|
||||
return;
|
||||
case JSType::TS_ITERATOR_INSTANCE_TYPE:
|
||||
TSIteratorInstanceType::Cast(obj)->DumpForSnapshot(vec);
|
||||
return;
|
||||
case JSType::TS_NAMESPACE_TYPE:
|
||||
TSNamespaceType::Cast(obj)->DumpForSnapshot(vec);
|
||||
return;
|
||||
case JSType::METHOD:
|
||||
Method::Cast(obj)->DumpForSnapshot(vec);
|
||||
return;
|
||||
@ -6258,79 +5917,6 @@ void ClassInfoExtractor::DumpForSnapshot(std::vector<Reference> &vec) const
|
||||
vec.emplace_back(CString("BitField"), JSTaggedValue(GetBitField()));
|
||||
}
|
||||
|
||||
void TSObjectType::DumpForSnapshot(std::vector<Reference> &vec) const
|
||||
{
|
||||
vec.emplace_back(CString("ObjLayoutInfo"), GetObjLayoutInfo());
|
||||
vec.emplace_back(CString("IndexSigns"), GetIndexSigns());
|
||||
}
|
||||
|
||||
void TSClassType::DumpForSnapshot(std::vector<Reference> &vec) const
|
||||
{
|
||||
// please update the NUM_OF_ITEMS if you change the items below
|
||||
constexpr int16_t NUM_OF_ITEMS = 5;
|
||||
vec.reserve(vec.size() + NUM_OF_ITEMS);
|
||||
vec.emplace_back(CString("InstanceType"), GetInstanceType());
|
||||
vec.emplace_back(CString("ConstructorType"), GetConstructorType());
|
||||
vec.emplace_back(CString("PrototypeType"), GetPrototypeType());
|
||||
vec.emplace_back(CString("ExtensionGT"), JSTaggedValue(GetExtensionGT().GetType()));
|
||||
vec.emplace_back(CString("HasLinked"), JSTaggedValue(GetHasLinked()));
|
||||
vec.emplace_back(CString("Name"), JSTaggedValue(GetName()));
|
||||
if (!GetIndexSigns().IsUndefined()) {
|
||||
DumpArrayClass(TaggedArray::Cast(GetIndexSigns().GetTaggedObject()), vec);
|
||||
}
|
||||
}
|
||||
|
||||
void TSInterfaceType::DumpForSnapshot(std::vector<Reference> &vec) const
|
||||
{
|
||||
vec.emplace_back(CString("Fields"), GetFields());
|
||||
vec.emplace_back(CString("Extends"), GetExtends());
|
||||
DumpArrayClass(TaggedArray::Cast(GetExtends().GetTaggedObject()), vec);
|
||||
if (!GetIndexSigns().IsUndefined()) {
|
||||
DumpArrayClass(TaggedArray::Cast(GetIndexSigns().GetTaggedObject()), vec);
|
||||
}
|
||||
}
|
||||
|
||||
void TSClassInstanceType::DumpForSnapshot(std::vector<Reference> &vec) const
|
||||
{
|
||||
vec.emplace_back(CString("ClassGT"), JSTaggedValue(GetClassGT().GetType()));
|
||||
}
|
||||
|
||||
void TSUnionType::DumpForSnapshot(std::vector<Reference> &vec) const
|
||||
{
|
||||
vec.emplace_back(CString("ComponentTypes"), GetComponents());
|
||||
DumpArrayClass(TaggedArray::Cast(GetComponents().GetTaggedObject()), vec);
|
||||
}
|
||||
|
||||
void TSFunctionType::DumpForSnapshot(std::vector<Reference> &vec) const
|
||||
{
|
||||
// please update the NUM_OF_ITEMS if you change the items below
|
||||
constexpr int16_t NUM_OF_ITEMS = 5;
|
||||
vec.reserve(vec.size() + NUM_OF_ITEMS);
|
||||
vec.emplace_back(CString("Name"), GetName());
|
||||
vec.emplace_back(CString("ParameterTypes"), GetParameterTypes());
|
||||
DumpArrayClass(TaggedArray::Cast(GetParameterTypes().GetTaggedObject()), vec);
|
||||
vec.emplace_back(CString("ReturnGT"), JSTaggedValue(GetReturnGT().GetType()));
|
||||
vec.emplace_back(CString("ThisGT"), JSTaggedValue(GetThisGT().GetType()));
|
||||
vec.emplace_back(CString("BitField"), JSTaggedValue(GetBitField()));
|
||||
}
|
||||
|
||||
void TSArrayType::DumpForSnapshot(std::vector<Reference> &vec) const
|
||||
{
|
||||
vec.emplace_back(CString("ParameterTypeRef"), JSTaggedValue(GetElementGT().GetType()));
|
||||
}
|
||||
|
||||
void TSIteratorInstanceType::DumpForSnapshot(std::vector<Reference> &vec) const
|
||||
{
|
||||
vec.emplace_back(CString("kindGT"), JSTaggedValue(GetKindGT().GetType()));
|
||||
vec.emplace_back(CString("elementGT"), JSTaggedValue(GetElementGT().GetType()));
|
||||
}
|
||||
|
||||
void TSNamespaceType::DumpForSnapshot(std::vector<Reference> &vec) const
|
||||
{
|
||||
vec.emplace_back(CString("PropertyType"), GetPropertyType());
|
||||
DumpArrayClass(TaggedArray::Cast(GetPropertyType().GetTaggedObject()), vec);
|
||||
}
|
||||
|
||||
void SourceTextModule::DumpForSnapshot(std::vector<Reference> &vec) const
|
||||
{
|
||||
// please update the NUM_OF_ITEMS if you change the items below
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "ecmascript/builtins/builtins_string.h"
|
||||
#include "ecmascript/compiler/aot_file/an_file_data_manager.h"
|
||||
#include "ecmascript/compiler/common_stubs.h"
|
||||
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
|
||||
#include "ecmascript/ecma_string.h"
|
||||
#include "ecmascript/ecma_string_table.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
@ -83,14 +84,6 @@ bool EcmaContext::Destroy(EcmaContext *context)
|
||||
return false;
|
||||
}
|
||||
|
||||
void EcmaContext::SetTSManager(TSManager *set)
|
||||
{
|
||||
if (tsManager_ != nullptr) {
|
||||
delete tsManager_;
|
||||
}
|
||||
tsManager_ = set;
|
||||
}
|
||||
|
||||
bool EcmaContext::Initialize()
|
||||
{
|
||||
LOG_ECMA(DEBUG) << "EcmaContext::Initialize";
|
||||
@ -125,7 +118,6 @@ bool EcmaContext::Initialize()
|
||||
SetupStringToListResultCache();
|
||||
microJobQueue_ = factory_->NewMicroJobQueue().GetTaggedValue();
|
||||
moduleManager_ = new ModuleManager(vm_);
|
||||
tsManager_ = new TSManager(vm_);
|
||||
ptManager_ = new kungfu::PGOTypeManager(vm_);
|
||||
optCodeProfiler_ = new OptCodeProfiler();
|
||||
if (vm_->GetJSOptions().GetTypedOpProfiler()) {
|
||||
@ -234,10 +226,6 @@ EcmaContext::~EcmaContext()
|
||||
delete moduleManager_;
|
||||
moduleManager_ = nullptr;
|
||||
}
|
||||
if (tsManager_ != nullptr) {
|
||||
delete tsManager_;
|
||||
tsManager_ = nullptr;
|
||||
}
|
||||
if (ptManager_ != nullptr) {
|
||||
delete ptManager_;
|
||||
ptManager_ = nullptr;
|
||||
@ -903,9 +891,6 @@ void EcmaContext::Iterate(const RootVisitor &v, const RootRangeVisitor &rv)
|
||||
if (moduleManager_) {
|
||||
moduleManager_->Iterate(v);
|
||||
}
|
||||
if (tsManager_) {
|
||||
tsManager_->Iterate(v);
|
||||
}
|
||||
if (ptManager_) {
|
||||
ptManager_->Iterate(v);
|
||||
}
|
||||
|
@ -61,7 +61,6 @@ class JSPromise;
|
||||
class JSTaggedValue;
|
||||
class EcmaVM;
|
||||
class ModuleManager;
|
||||
class TSManager;
|
||||
class AOTFileManager;
|
||||
class QuickFixManager;
|
||||
class OptCodeProfiler;
|
||||
@ -135,18 +134,11 @@ public:
|
||||
return moduleManager_;
|
||||
}
|
||||
|
||||
TSManager *GetTSManager() const
|
||||
{
|
||||
return tsManager_;
|
||||
}
|
||||
|
||||
kungfu::PGOTypeManager *GetPTManager() const
|
||||
{
|
||||
return ptManager_;
|
||||
}
|
||||
|
||||
void PUBLIC_API SetTSManager(TSManager *set);
|
||||
|
||||
ARK_INLINE JSThread *GetJSThread() const
|
||||
{
|
||||
return thread_;
|
||||
@ -570,7 +562,6 @@ private:
|
||||
|
||||
// VM resources.
|
||||
ModuleManager *moduleManager_ {nullptr};
|
||||
TSManager *tsManager_ {nullptr};
|
||||
kungfu::PGOTypeManager *ptManager_ {nullptr};
|
||||
AOTFileManager *aotFileManager_ {nullptr};
|
||||
|
||||
|
@ -91,7 +91,6 @@
|
||||
#include "ecmascript/tagged_queue.h"
|
||||
#include "ecmascript/taskpool/task.h"
|
||||
#include "ecmascript/taskpool/taskpool.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
#include "ecmascript/ohos/enable_aot_list_helper.h"
|
||||
|
||||
|
@ -81,7 +81,6 @@ class JSArrayBuffer;
|
||||
class JSFunction;
|
||||
class SourceTextModule;
|
||||
class Program;
|
||||
class TSManager;
|
||||
class AOTFileManager;
|
||||
class SlowRuntimeStub;
|
||||
class RequireManager;
|
||||
|
@ -80,9 +80,8 @@
|
||||
#include "ecmascript/shared_objects/js_shared_map_iterator.h"
|
||||
#include "ecmascript/shared_objects/js_shared_set.h"
|
||||
#include "ecmascript/shared_objects/js_shared_set_iterator.h"
|
||||
#include "ecmascript/subtyping_operator.h"
|
||||
#include "ecmascript/tagged_node.h"
|
||||
#include "ecmascript/ts_types/ts_type.h"
|
||||
#include "ecmascript/vtable.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
void GlobalEnvConstants::Init(JSThread *thread)
|
||||
@ -231,26 +230,6 @@ void GlobalEnvConstants::InitSharedRootsClasses(ObjectFactory *factory)
|
||||
SetConstant(ConstantIndex::CLASS_INFO_EXTRACTOR_HCLASS_INDEX,
|
||||
factory->NewSEcmaReadOnlyHClass(hClass, ClassInfoExtractor::SIZE,
|
||||
JSType::CLASS_INFO_EXTRACTOR));
|
||||
SetConstant(ConstantIndex::TS_OBJECT_TYPE_CLASS_INDEX,
|
||||
factory->NewSEcmaReadOnlyHClass(hClass, TSObjectType::SIZE, JSType::TS_OBJECT_TYPE));
|
||||
SetConstant(ConstantIndex::TS_CLASS_TYPE_CLASS_INDEX,
|
||||
factory->NewSEcmaReadOnlyHClass(hClass, TSClassType::SIZE, JSType::TS_CLASS_TYPE));
|
||||
SetConstant(ConstantIndex::TS_UNION_TYPE_CLASS_INDEX,
|
||||
factory->NewSEcmaReadOnlyHClass(hClass, TSUnionType::SIZE, JSType::TS_UNION_TYPE));
|
||||
SetConstant(ConstantIndex::TS_INTERFACE_TYPE_CLASS_INDEX,
|
||||
factory->NewSEcmaReadOnlyHClass(hClass, TSInterfaceType::SIZE, JSType::TS_INTERFACE_TYPE));
|
||||
SetConstant(ConstantIndex::TS_CLASS_INSTANCE_TYPE_CLASS_INDEX,
|
||||
factory->NewSEcmaReadOnlyHClass(hClass, TSClassInstanceType::SIZE,
|
||||
JSType::TS_CLASS_INSTANCE_TYPE));
|
||||
SetConstant(ConstantIndex::TS_FUNCTION_TYPE_CLASS_INDEX,
|
||||
factory->NewSEcmaReadOnlyHClass(hClass, TSFunctionType::SIZE, JSType::TS_FUNCTION_TYPE));
|
||||
SetConstant(ConstantIndex::TS_ARRAY_TYPE_CLASS_INDEX,
|
||||
factory->NewSEcmaReadOnlyHClass(hClass, TSArrayType::SIZE, JSType::TS_ARRAY_TYPE));
|
||||
SetConstant(ConstantIndex::TS_ITERATOR_INSTANCE_TYPE_CLASS_INDEX,
|
||||
factory->NewSEcmaReadOnlyHClass(hClass, TSIteratorInstanceType::SIZE,
|
||||
JSType::TS_ITERATOR_INSTANCE_TYPE));
|
||||
SetConstant(ConstantIndex::TS_NAMESPACE_TYPE_CLASS_INDEX,
|
||||
factory->NewSEcmaReadOnlyHClass(hClass, TSNamespaceType::SIZE, JSType::TS_NAMESPACE_TYPE));
|
||||
SetConstant(ConstantIndex::CELL_RECORD_CLASS_INDEX,
|
||||
factory->NewSEcmaReadOnlyHClass(hClass, CellRecord::SIZE, JSType::CELL_RECORD));
|
||||
SetConstant(ConstantIndex::METHOD_CLASS_INDEX,
|
||||
@ -383,7 +362,7 @@ void GlobalEnvConstants::InitMiscellanious(JSThread *thread, ObjectFactory *fact
|
||||
SetConstant(ConstantIndex::EMPTY_LAYOUT_INFO_OBJECT_INDEX, factory->CreateLayoutInfo(0));
|
||||
SetConstant(ConstantIndex::EMPTY_TAGGED_QUEUE_OBJECT_INDEX, factory->NewTaggedQueue(0));
|
||||
SetConstant(ConstantIndex::DEFAULT_SUPERS_INDEX,
|
||||
WeakVector::Create(thread, SubtypingOperator::DEFAULT_SUPERS_CAPACITY, MemSpaceType::NON_MOVABLE));
|
||||
WeakVector::Create(thread, VTable::DEFAULT_SUPERS_CAPACITY, MemSpaceType::NON_MOVABLE));
|
||||
|
||||
// non ECMA standard jsapi containers iterators, init to Undefined first
|
||||
InitJSAPIContainers();
|
||||
|
@ -85,15 +85,6 @@ class ObjectFactory;
|
||||
V(JSTaggedValue, ResolvedIndexBindingClass, RESOLVED_INDEX_BINDING_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, MachineCodeClass, MACHINE_CODE_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, ClassInfoExtractorHClass, CLASS_INFO_EXTRACTOR_HCLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, TSObjectTypeClass, TS_OBJECT_TYPE_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, TSClassTypeClass, TS_CLASS_TYPE_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, TSUnionTypeClass, TS_UNION_TYPE_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, TSInterfaceTypeClass, TS_INTERFACE_TYPE_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, TSClassInstanceTypeClass, TS_CLASS_INSTANCE_TYPE_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, TSFunctionTypeClass, TS_FUNCTION_TYPE_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, TSArrayTypeClass, TS_ARRAY_TYPE_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, TSIteratorInstanceTypeClass, TS_ITERATOR_INSTANCE_TYPE_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, TSNamespaceTypeClass, TS_NAMESPACE_TYPE_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, CellRecordClass, CELL_RECORD_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, AOTLiteralInfoClass, AOT_LITERAL_INFO_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, MethodClass, METHOD_CLASS_INDEX, ecma_roots_class) \
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "ecmascript/jit/jit.h"
|
||||
#include "ecmascript/jit/jit_task.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
#include "ecmascript/platform/mutex.h"
|
||||
#include "ecmascript/platform/file.h"
|
||||
#include "ecmascript/dfx/vmstat/jit_preheat_profiler.h"
|
||||
|
@ -17,9 +17,11 @@
|
||||
#define ECMASCRIPT_JIT_H
|
||||
|
||||
#include "ecmascript/common.h"
|
||||
#include "ecmascript/compiler/compilation_env.h"
|
||||
#include "ecmascript/platform/mutex.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/mem/clock_scope.h"
|
||||
#include "ecmascript/mem/machine_code.h"
|
||||
#include "ecmascript/compiler/compiler_log.h"
|
||||
#include "ecmascript/jit/jit_thread.h"
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "ecmascript/compiler/codegen/maple/maple_util/include/profile_type.h"
|
||||
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
|
||||
#include "ecmascript/elements.h"
|
||||
#include "ecmascript/enum_conversion.h"
|
||||
#include "ecmascript/ic/ic_handler.h"
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "ecmascript/object_factory.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/compiler/aot_file/func_entry_des.h"
|
||||
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
|
||||
#include "ecmascript/ic/profile_type_info.h"
|
||||
#include "ecmascript/patch/patch_loader.h"
|
||||
#include "ecmascript/jspandafile/program_object.h"
|
||||
|
@ -30,12 +30,13 @@
|
||||
#include "ecmascript/js_object-inl.h"
|
||||
#include "ecmascript/js_symbol.h"
|
||||
#include "ecmascript/mem/c_containers.h"
|
||||
#include "ecmascript/subtyping_operator.h"
|
||||
#include "ecmascript/tagged_array-inl.h"
|
||||
#include "ecmascript/tagged_dictionary.h"
|
||||
#include "ecmascript/weak_vector.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
using ProfileType = pgo::ProfileType;
|
||||
|
||||
JSHandle<TransitionsDictionary> TransitionsDictionary::PutIfAbsent(const JSThread *thread,
|
||||
const JSHandle<TransitionsDictionary> &dictionary,
|
||||
const JSHandle<JSTaggedValue> &key,
|
||||
@ -336,11 +337,6 @@ void JSHClass::AddProperty(const JSThread *thread, const JSHandle<JSObject> &obj
|
||||
obj->SynchronizedSetClass(thread, *newJsHClass);
|
||||
// Because we currently only supports Fast ElementsKind
|
||||
TryRestoreElementsKind(thread, newJsHClass, obj);
|
||||
|
||||
// Maintaining subtyping is no longer required when transition succeeds.
|
||||
if (jshclass->HasTSSubtyping()) {
|
||||
SubtypingOperator::TryMaintainTSSubtyping(thread, jshclass, newJsHClass, key);
|
||||
}
|
||||
}
|
||||
|
||||
void JSHClass::TryRestoreElementsKind(const JSThread *thread, JSHandle<JSHClass> newJsHClass,
|
||||
@ -920,8 +916,7 @@ JSHandle<ProtoChangeDetails> JSHClass::GetProtoChangeDetails(const JSThread *thr
|
||||
return GetProtoChangeDetails(thread, jshclass);
|
||||
}
|
||||
|
||||
void JSHClass::MarkProtoChanged(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
|
||||
JSTaggedValue addedKey)
|
||||
void JSHClass::MarkProtoChanged(const JSThread *thread, const JSHandle<JSHClass> &jshclass)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
ASSERT(jshclass->IsPrototype() || jshclass->HasTSSubtyping());
|
||||
@ -932,12 +927,6 @@ void JSHClass::MarkProtoChanged(const JSThread *thread, const JSHandle<JSHClass>
|
||||
}
|
||||
|
||||
if (jshclass->HasTSSubtyping()) {
|
||||
if (addedKey.IsString()) {
|
||||
JSHandle<JSTaggedValue> key(thread, addedKey);
|
||||
if (SubtypingOperator::TryMaintainTSSubtypingOnPrototype(thread, jshclass, key)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
jshclass->InitTSInheritInfo(thread);
|
||||
}
|
||||
}
|
||||
@ -946,7 +935,7 @@ void JSHClass::NoticeThroughChain(const JSThread *thread, const JSHandle<JSHClas
|
||||
JSTaggedValue addedKey)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
MarkProtoChanged(thread, jshclass, addedKey);
|
||||
MarkProtoChanged(thread, jshclass);
|
||||
JSTaggedValue protoDetailsValue = jshclass->GetProtoChangeDetails();
|
||||
if (!protoDetailsValue.IsProtoChangeDetails()) {
|
||||
return;
|
||||
|
@ -292,15 +292,6 @@ struct Reference;
|
||||
COMPLETION_RECORD, /* JS_RECORD_LAST ////////////////////////////////////////////////////////////////////// */ \
|
||||
MACHINE_CODE_OBJECT, \
|
||||
CLASS_INFO_EXTRACTOR, /* //////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
TS_ARRAY_TYPE, /* ////////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
TS_UNION_TYPE, /* ////////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
TS_FUNCTION_TYPE, /* /////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
TS_OBJECT_TYPE, /* ///////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
TS_CLASS_TYPE, /* //////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
TS_CLASS_INSTANCE_TYPE, /* ///////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
TS_INTERFACE_TYPE, /* //////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
TS_ITERATOR_INSTANCE_TYPE, /* //////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
TS_NAMESPACE_TYPE, /* ////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
\
|
||||
VTABLE, /* //////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
AOT_LITERAL_INFO, /* //////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
@ -336,9 +327,6 @@ struct Reference;
|
||||
MODULE_RECORD_FIRST = MODULE_RECORD, /* ///////////////////////////////////////////////////////////-PADDING */ \
|
||||
MODULE_RECORD_LAST = SOURCE_TEXT_MODULE_RECORD, /* ////////////////////////////////////////////////-PADDING */ \
|
||||
\
|
||||
TS_TYPE_FIRST = TS_ARRAY_TYPE, /* /////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
TS_TYPE_LAST = TS_NAMESPACE_TYPE, /* //////////////////////////////////////////////////////////////-PADDING */ \
|
||||
\
|
||||
STRING_FIRST = LINE_STRING, /* ////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
STRING_LAST = TREE_STRING /* /////////////////////////////////////////////////////////////////////-PADDING */
|
||||
|
||||
@ -489,8 +477,7 @@ public:
|
||||
inline void UpdatePropertyMetaData(const JSThread *thread, const JSTaggedValue &key,
|
||||
const PropertyAttributes &metaData);
|
||||
|
||||
static void MarkProtoChanged(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
|
||||
JSTaggedValue addedKey = JSTaggedValue::Undefined());
|
||||
static void MarkProtoChanged(const JSThread *thread, const JSHandle<JSHClass> &jshclass);
|
||||
|
||||
static void NoticeThroughChain(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
|
||||
JSTaggedValue addedKey = JSTaggedValue::Undefined());
|
||||
@ -1628,57 +1615,6 @@ public:
|
||||
return GetObjectType() == JSType::MACHINE_CODE_OBJECT;
|
||||
}
|
||||
|
||||
inline bool IsTSType() const
|
||||
{
|
||||
JSType jsType = GetObjectType();
|
||||
return jsType >= JSType::TS_TYPE_FIRST && jsType <= JSType::TS_TYPE_LAST;
|
||||
}
|
||||
|
||||
inline bool IsTSObjectType() const
|
||||
{
|
||||
return GetObjectType() == JSType::TS_OBJECT_TYPE;
|
||||
}
|
||||
|
||||
inline bool IsTSClassType() const
|
||||
{
|
||||
return GetObjectType() == JSType::TS_CLASS_TYPE;
|
||||
}
|
||||
|
||||
inline bool IsTSInterfaceType() const
|
||||
{
|
||||
return GetObjectType() == JSType::TS_INTERFACE_TYPE;
|
||||
}
|
||||
|
||||
inline bool IsTSUnionType() const
|
||||
{
|
||||
return GetObjectType() == JSType::TS_UNION_TYPE;
|
||||
}
|
||||
|
||||
inline bool IsTSClassInstanceType() const
|
||||
{
|
||||
return GetObjectType() == JSType::TS_CLASS_INSTANCE_TYPE;
|
||||
}
|
||||
|
||||
inline bool IsTSFunctionType() const
|
||||
{
|
||||
return GetObjectType() == JSType::TS_FUNCTION_TYPE;
|
||||
}
|
||||
|
||||
inline bool IsTSArrayType() const
|
||||
{
|
||||
return GetObjectType() == JSType::TS_ARRAY_TYPE;
|
||||
}
|
||||
|
||||
inline bool IsTSIteratorInstanceType() const
|
||||
{
|
||||
return GetObjectType() == JSType::TS_ITERATOR_INSTANCE_TYPE;
|
||||
}
|
||||
|
||||
inline bool IsTSNamespaceType() const
|
||||
{
|
||||
return GetObjectType() == JSType::TS_NAMESPACE_TYPE;
|
||||
}
|
||||
|
||||
inline bool IsAOTLiteralInfo() const
|
||||
{
|
||||
return GetObjectType() == JSType::AOT_LITERAL_INFO;
|
||||
|
@ -46,8 +46,6 @@ const std::string PUBLIC_API HELP_OPTION_MSG =
|
||||
"--ark-bundle-name: Set ark bundle name\n"
|
||||
"--asm-interpreter: Enable asm interpreter. Default: 'true'\n"
|
||||
"--asm-opcode-disable-range: Opcode range when asm interpreter is enabled.\n"
|
||||
"--compiler-assert-types: Enable type assertion for type inference tests. Default: 'false'\n"
|
||||
"--builtins-dts: Builtins.d.abc file path for AOT.\n"
|
||||
"--builtins-lazy: Load some builtins function later.This option is only valid in workervm.\n"
|
||||
"--compiler-log: Log Option For aot compiler and stub compiler,\n"
|
||||
" 'none': no log,\n"
|
||||
@ -65,7 +63,6 @@ const std::string PUBLIC_API HELP_OPTION_MSG =
|
||||
"Default: 'none'\n"
|
||||
"--compiler-type-threshold: enable to skip methods whose type is no more than threshold. Default: -1\n"
|
||||
"--compiler-log-snapshot: Enable to print snapshot information. Default: 'false'\n"
|
||||
"--compiler-opt-global-typeinfer: Enable global typeinfer for aot compiler: Default: 'false'\n"
|
||||
"--compiler-log-time: Enable to print pass compiler time. Default: 'false'\n"
|
||||
"--enable-ark-tools: Enable ark tools to debug. Default: 'false'\n"
|
||||
"--compiler-trace-bc: Enable tracing bytecode for aot runtime. Default: 'false'\n"
|
||||
@ -127,7 +124,6 @@ const std::string PUBLIC_API HELP_OPTION_MSG =
|
||||
"--merge-abc: ABC file is merge abc. Default: 'false'\n"
|
||||
"--compiler-opt-level: Optimization level configuration of aot compiler. Default: '3'\n"
|
||||
"--options: Print compiler and runtime options\n"
|
||||
"--compiler-print-type-info: Enable print type info. Default: 'false'\n"
|
||||
"--serializer-buffer-size-limit: Max serializer buffer size used by the VM in Byte. Default size is 2GB\n"
|
||||
"--snapshot-file: Snapshot file. Default: '/system/etc/snapshot'\n"
|
||||
"--startup-time: Print the start time of command execution. Default: 'false'\n"
|
||||
@ -191,14 +187,11 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
|
||||
{"ark-bundleName", required_argument, nullptr, OPTION_ARK_BUNDLENAME},
|
||||
{"asm-interpreter", required_argument, nullptr, OPTION_ENABLE_ASM_INTERPRETER},
|
||||
{"asm-opcode-disable-range", required_argument, nullptr, OPTION_ASM_OPCODE_DISABLE_RANGE},
|
||||
{"compiler-assert-types", required_argument, nullptr, OPTION_COMPILER_ASSERT_TYPES},
|
||||
{"builtins-dts", required_argument, nullptr, OPTION_BUILTINS_DTS},
|
||||
{"builtins-lazy", required_argument, nullptr, OPTION_ENABLE_BUILTINS_LAZY},
|
||||
{"compiler-log", required_argument, nullptr, OPTION_COMPILER_LOG_OPT},
|
||||
{"compiler-log-methods", required_argument, nullptr, OPTION_COMPILER_LOG_METHODS},
|
||||
{"compiler-log-snapshot", required_argument, nullptr, OPTION_COMPILER_LOG_SNAPSHOT},
|
||||
{"compiler-log-time", required_argument, nullptr, OPTION_COMPILER_LOG_TIME},
|
||||
{"compiler-opt-global-typeinfer", required_argument, nullptr, OPTION_COMPILER_OPT_GLOBAL_TYPEINFER},
|
||||
{"compiler-type-threshold", required_argument, nullptr, OPTION_COMPILER_TYPE_THRESHOLD},
|
||||
{"enable-ark-tools", required_argument, nullptr, OPTION_ENABLE_ARK_TOOLS},
|
||||
{"compiler-trace-bc", required_argument, nullptr, OPTION_COMPILER_TRACE_BC},
|
||||
@ -251,7 +244,6 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
|
||||
{"merge-abc", required_argument, nullptr, OPTION_MERGE_ABC},
|
||||
{"enable-context", required_argument, nullptr, OPTION_ENABLE_CONTEXT},
|
||||
{"compiler-opt-level", required_argument, nullptr, OPTION_ASM_OPT_LEVEL},
|
||||
{"compiler-print-type-info", required_argument, nullptr, OPTION_COMPILER_PRINT_TYPE_INFO},
|
||||
{"reloc-mode", required_argument, nullptr, OPTION_RELOCATION_MODE},
|
||||
{"serializer-buffer-size-limit", required_argument, nullptr, OPTION_SERIALIZER_BUFFER_SIZE_LIMIT},
|
||||
{"startup-time", required_argument, nullptr, OPTION_STARTUP_TIME},
|
||||
@ -372,17 +364,6 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
|
||||
case OPTION_ASM_OPCODE_DISABLE_RANGE:
|
||||
SetAsmOpcodeDisableRange(optarg);
|
||||
break;
|
||||
case OPTION_COMPILER_ASSERT_TYPES:
|
||||
ret = ParseBoolParam(&argBool);
|
||||
if (ret) {
|
||||
SetAssertTypes(argBool);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPTION_BUILTINS_DTS:
|
||||
SetBuiltinsDTS(optarg);
|
||||
break;
|
||||
case OPTION_ENABLE_BUILTINS_LAZY:
|
||||
ret = ParseBoolParam(&argBool);
|
||||
if (ret) {
|
||||
@ -655,14 +636,6 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPTION_COMPILER_PRINT_TYPE_INFO:
|
||||
ret = ParseBoolParam(&argBool);
|
||||
if (ret) {
|
||||
SetPrintTypeInfo(argBool);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPTION_PRINT_EXECUTE_TIME:
|
||||
ret = ParseBoolParam(&argBool);
|
||||
if (ret) {
|
||||
@ -846,14 +819,6 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPTION_COMPILER_OPT_GLOBAL_TYPEINFER:
|
||||
ret = ParseBoolParam(&argBool);
|
||||
if (ret) {
|
||||
SetEnableGlobalTypeInfer(argBool);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPTION_COMPILER_VERIFY_VTABLE:
|
||||
ret = ParseBoolParam(&argBool);
|
||||
if (ret) {
|
||||
@ -1241,17 +1206,9 @@ void JSRuntimeOptions::ParseListArgParam(const std::string &option, arg_list_t *
|
||||
return;
|
||||
}
|
||||
|
||||
void JSRuntimeOptions::SetTargetBuiltinsDtsPath()
|
||||
{
|
||||
WasSet(CommandValues::OPTION_BUILTINS_DTS);
|
||||
std::string builtinsDtsPath = TARGET_BUILTINS_DTS_PATH;
|
||||
SetBuiltinsDTS(builtinsDtsPath);
|
||||
}
|
||||
|
||||
void JSRuntimeOptions::SetOptionsForTargetCompilation()
|
||||
{
|
||||
if (IsTargetCompilerMode()) {
|
||||
SetTargetBuiltinsDtsPath();
|
||||
SetTargetTriple("aarch64-unknown-linux-gnu");
|
||||
SetEnableOptTrackField(false);
|
||||
SetEnableOptInlining(false);
|
||||
|
@ -93,12 +93,9 @@ enum CommandValues {
|
||||
OPTION_COMPILER_LOG_METHODS,
|
||||
OPTION_COMPILER_TYPE_THRESHOLD,
|
||||
OPTION_ENABLE_RUNTIME_STAT,
|
||||
OPTION_COMPILER_ASSERT_TYPES,
|
||||
OPTION_COMPILER_PRINT_TYPE_INFO,
|
||||
OPTION_COMPILER_LOG_SNAPSHOT,
|
||||
OPTION_COMPILER_LOG_TIME,
|
||||
OPTION_ENABLE_WORKER,
|
||||
OPTION_BUILTINS_DTS,
|
||||
OPTION_COMPILER_TRACE_BC,
|
||||
OPTION_COMPILER_TRACE_DEOPT,
|
||||
OPTION_COMPILER_TRACE_INLINE,
|
||||
@ -127,13 +124,12 @@ enum CommandValues {
|
||||
OPTION_COMPILER_OPT_INLINING,
|
||||
OPTION_COMPILER_OPT_PGOTYPE,
|
||||
OPTION_COMPILER_OPT_TRACK_FIELD,
|
||||
OPTION_COMPILER_OPT_GLOBAL_TYPEINFER,
|
||||
OPTION_COMPILER_PGO_PROFILER_PATH,
|
||||
OPTION_SPLIT_ONE,
|
||||
OPTION_COMPILER_PGO_HOTNESS_THRESHOLD,
|
||||
OPTION_COMPILER_PGO_SAVE_MIN_INTERVAL,
|
||||
OPTION_ENABLE_PGO_PROFILER,
|
||||
OPTION_PRINT_EXECUTE_TIME,
|
||||
OPTION_SPLIT_ONE,
|
||||
OPTION_COMPILER_DEVICE_STATE,
|
||||
OPTION_COMPILER_VERIFY_VTABLE,
|
||||
OPTION_COMPILER_SELECT_METHODS,
|
||||
@ -771,41 +767,6 @@ public:
|
||||
return WasOptionSet(OPTION_STARTUP_TIME);
|
||||
}
|
||||
|
||||
bool AssertTypes() const
|
||||
{
|
||||
return assertTypes_;
|
||||
}
|
||||
|
||||
void SetAssertTypes(bool value)
|
||||
{
|
||||
assertTypes_ = value;
|
||||
}
|
||||
|
||||
bool PrintTypeInfo() const
|
||||
{
|
||||
return printTypeInfo_;
|
||||
}
|
||||
|
||||
void SetPrintTypeInfo(bool value)
|
||||
{
|
||||
printTypeInfo_ = value;
|
||||
}
|
||||
|
||||
void SetBuiltinsDTS(const std::string& value)
|
||||
{
|
||||
builtinsDTS_ = panda::os::file::File::GetExtendedFilePath(value);
|
||||
}
|
||||
|
||||
bool WasSetBuiltinsDTS() const
|
||||
{
|
||||
return WasOptionSet(OPTION_BUILTINS_DTS);
|
||||
}
|
||||
|
||||
std::string GetBuiltinsDTS() const
|
||||
{
|
||||
return builtinsDTS_;
|
||||
}
|
||||
|
||||
void SetTraceBc(bool value)
|
||||
{
|
||||
traceBc_ = value;
|
||||
@ -1217,16 +1178,6 @@ public:
|
||||
return enableOptTrackField_;
|
||||
}
|
||||
|
||||
void SetEnableGlobalTypeInfer(bool value)
|
||||
{
|
||||
enableGlobalTypeInfer_ = value;
|
||||
}
|
||||
|
||||
bool IsEnableGlobalTypeInfer() const
|
||||
{
|
||||
return enableGlobalTypeInfer_;
|
||||
}
|
||||
|
||||
uint32_t GetCompilerModuleMethods() const
|
||||
{
|
||||
return compilerModuleMethods_;
|
||||
@ -1452,8 +1403,6 @@ public:
|
||||
return compilerNoCheck_;
|
||||
}
|
||||
|
||||
void SetTargetBuiltinsDtsPath();
|
||||
|
||||
void SetOptionsForTargetCompilation();
|
||||
|
||||
void SetFastAOTCompileMode(bool value)
|
||||
@ -1760,10 +1709,7 @@ private:
|
||||
bool compilerLogSnapshot_ {false};
|
||||
bool compilerLogTime_ {false};
|
||||
bool enableRuntimeStat_ {false};
|
||||
bool assertTypes_ {false};
|
||||
bool printTypeInfo_ {false};
|
||||
bool isWorker_ {false};
|
||||
std::string builtinsDTS_ {""};
|
||||
bool traceBc_ {false};
|
||||
std::string logLevel_ {"error"};
|
||||
arg_list_t logDebug_ {{"all"}};
|
||||
@ -1794,7 +1740,6 @@ private:
|
||||
uint16_t jitHotnessThreshold_ {2};
|
||||
uint16_t osrHotnessThreshold_ {2};
|
||||
bool forceJitCompileMain_{false};
|
||||
bool enableGlobalTypeInfer_ {false};
|
||||
bool enableOptTrackField_ {true};
|
||||
uint32_t compilerModuleMethods_ {100};
|
||||
uint64_t wasSetPartOne_ {0};
|
||||
|
@ -1511,36 +1511,6 @@ inline bool JSTaggedValue::IsClassInfoExtractor() const
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsClassInfoExtractor();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsTSType() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSType();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsTSObjectType() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSObjectType();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsTSClassType() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSClassType();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsTSInterfaceType() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSInterfaceType();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsTSUnionType() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSUnionType();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsTSClassInstanceType() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSClassInstanceType();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsCjsExports() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsCjsExports();
|
||||
@ -1556,26 +1526,6 @@ inline bool JSTaggedValue::IsCjsRequire() const
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsCjsRequire();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsTSFunctionType() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSFunctionType();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsTSArrayType() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSArrayType();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsTSIteratorInstanceType() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSIteratorInstanceType();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsTSNamespaceType() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSNamespaceType();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsModuleRecord() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsModuleRecord();
|
||||
|
@ -659,16 +659,6 @@ public:
|
||||
bool IsRegularObject() const;
|
||||
bool IsMachineCodeObject() const;
|
||||
bool IsClassInfoExtractor() const;
|
||||
bool IsTSType() const;
|
||||
bool IsTSObjectType() const;
|
||||
bool IsTSClassType() const;
|
||||
bool IsTSUnionType() const;
|
||||
bool IsTSInterfaceType() const;
|
||||
bool IsTSClassInstanceType() const;
|
||||
bool IsTSFunctionType() const;
|
||||
bool IsTSArrayType() const;
|
||||
bool IsTSIteratorInstanceType() const;
|
||||
bool IsTSNamespaceType() const;
|
||||
|
||||
bool IsCjsExports() const;
|
||||
bool IsCjsModule() const;
|
||||
|
@ -19,7 +19,6 @@
|
||||
#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 {
|
||||
@ -81,9 +80,6 @@ public:
|
||||
{
|
||||
LockHolder lock(jsPandaFileLock_);
|
||||
for (const auto &item : loadedJSPandaFiles_) {
|
||||
if (item.first == panda::ecmascript::TSTypeTable::DEFAULT_TYPE_VIRTUAL_NAME) {
|
||||
continue;
|
||||
}
|
||||
if (!cb(item.second)) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,378 +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/jspandafile/type_literal_extractor.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include "libpandafile/literal_data_accessor-inl.h"
|
||||
#include "libpandafile/method_data_accessor-inl.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
using LiteralTag = panda_file::LiteralTag;
|
||||
using LiteralValue = panda_file::LiteralDataAccessor::LiteralValue;
|
||||
using StringData = panda_file::StringData;
|
||||
using EntityId = panda_file::File::EntityId;
|
||||
using LiteralDataAccessor = panda_file::LiteralDataAccessor;
|
||||
|
||||
static constexpr const char *TYPE_ANNO_RECORD_NAME = "L_ESTypeAnnotation;";
|
||||
|
||||
static bool IsLegalOffset(uint32_t offset)
|
||||
{
|
||||
return offset != 0U;
|
||||
}
|
||||
|
||||
static uint32_t GetMethodAnnoOffset(const JSPandaFile *jsPandaFile, uint32_t methodOffset, const char *annoName)
|
||||
{
|
||||
const panda_file::File &pf = *jsPandaFile->GetPandaFile();
|
||||
EntityId methodId(methodOffset);
|
||||
panda_file::MethodDataAccessor mda(pf, methodId);
|
||||
|
||||
uint32_t annoOffset = 0;
|
||||
mda.EnumerateAnnotations([&jsPandaFile, &annoName, &pf, &annoOffset](EntityId annotationId) {
|
||||
panda_file::AnnotationDataAccessor ada(pf, annotationId);
|
||||
auto *annotationName = reinterpret_cast<const char *>(jsPandaFile->GetStringData(ada.GetClassId()).data);
|
||||
ASSERT(annotationName != nullptr);
|
||||
if (::strcmp(TYPE_ANNO_RECORD_NAME, annotationName) != 0) {
|
||||
return;
|
||||
}
|
||||
uint32_t length = ada.GetCount();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
panda_file::AnnotationDataAccessor::Elem adae = ada.GetElement(i);
|
||||
auto *elemName = reinterpret_cast<const char *>(jsPandaFile->GetStringData(adae.GetNameId()).data);
|
||||
ASSERT(elemName != nullptr);
|
||||
|
||||
if (::strcmp(annoName, elemName) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
panda_file::ScalarValue sv = adae.GetScalarValue();
|
||||
annoOffset = sv.GetValue();
|
||||
}
|
||||
});
|
||||
return annoOffset;
|
||||
}
|
||||
|
||||
TypeLiteralExtractor::TypeLiteralExtractor(const JSPandaFile *jsPandaFile, const uint32_t typeOffset)
|
||||
: typeOffset_(typeOffset)
|
||||
{
|
||||
ProcessTypeLiteral(jsPandaFile, typeOffset);
|
||||
}
|
||||
|
||||
void TypeLiteralExtractor::ProcessTypeLiteral(const JSPandaFile *jsPandaFile, const uint32_t typeOffset)
|
||||
{
|
||||
EntityId literalId(typeOffset);
|
||||
LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
|
||||
bool isFirst = true;
|
||||
lda.EnumerateLiteralVals(literalId,
|
||||
[this, &jsPandaFile, &isFirst](const LiteralValue &value, const LiteralTag &tag) {
|
||||
if (isFirst) {
|
||||
uint32_t kindValue = std::get<uint32_t>(value);
|
||||
if (UNLIKELY(!IsVaildKind(kindValue))) {
|
||||
LOG_COMPILER(FATAL) << "Load type literal failure.";
|
||||
return;
|
||||
}
|
||||
kind_ = static_cast<TSTypeKind>(std::get<uint32_t>(value));
|
||||
isFirst = false;
|
||||
return;
|
||||
}
|
||||
switch (tag) {
|
||||
case LiteralTag::INTEGER: {
|
||||
uint32_t valueValue = std::get<uint32_t>(value);
|
||||
if (static_cast<int32_t>(valueValue) < 0) {
|
||||
isGenerics_ = true;
|
||||
}
|
||||
array_.emplace_back(valueValue);
|
||||
break;
|
||||
}
|
||||
case LiteralTag::LITERALARRAY: {
|
||||
array_.emplace_back(std::get<uint32_t>(value));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::BUILTINTYPEINDEX: {
|
||||
array_.emplace_back(static_cast<uint32_t>(std::get<uint8_t>(value)));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::STRING: {
|
||||
StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
|
||||
CString stringValue = utf::Mutf8AsCString(sd.data);
|
||||
array_.emplace_back(stringValue);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_COMPILER(FATAL) << "TypeLiteral should not exist LiteralTag: " << static_cast<uint32_t>(tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void TypeLiteralExtractor::Print() const
|
||||
{
|
||||
std::string log("[TypeLiteral] TypeOffset: ");
|
||||
log += (std::to_string(typeOffset_) + ", " + PrintTypeKind(kind_));
|
||||
if (isGenerics_) {
|
||||
log += ", generics";
|
||||
}
|
||||
uint32_t length = array_.size();
|
||||
log += ", [";
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
if (std::holds_alternative<uint32_t>(array_[i])) {
|
||||
log += std::to_string(std::get<uint32_t>(array_[i]));
|
||||
} else if (std::holds_alternative<CString>(array_[i])) {
|
||||
log += std::get<CString>(array_[i]);
|
||||
}
|
||||
if (i == length - 1) {
|
||||
log += "]";
|
||||
} else {
|
||||
log += ", ";
|
||||
}
|
||||
}
|
||||
LOG_COMPILER(INFO) << log;
|
||||
}
|
||||
|
||||
std::string TypeLiteralExtractor::PrintTypeKind(TSTypeKind typeKind) const
|
||||
{
|
||||
switch (typeKind) {
|
||||
case TSTypeKind::CLASS:
|
||||
return "class";
|
||||
case TSTypeKind::CLASS_INSTANCE:
|
||||
return "class_instance";
|
||||
case TSTypeKind::FUNCTION:
|
||||
return "function";
|
||||
case TSTypeKind::UNION:
|
||||
return "union";
|
||||
case TSTypeKind::ARRAY:
|
||||
return "array";
|
||||
case TSTypeKind::OBJECT:
|
||||
return "object";
|
||||
case TSTypeKind::IMPORT:
|
||||
return "import";
|
||||
case TSTypeKind::INTERFACE:
|
||||
return "interface";
|
||||
case TSTypeKind::BUILTIN_INSTANCE:
|
||||
return "builtin_instance";
|
||||
case TSTypeKind::GENERIC_INSTANCE:
|
||||
return "generic_instance";
|
||||
case TSTypeKind::INDEXSIG:
|
||||
return "index_signature";
|
||||
default:
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
TypeSummaryExtractor::TypeSummaryExtractor(const JSPandaFile *jsPandaFile, const CString &recordName)
|
||||
: jsPandaFile_(jsPandaFile)
|
||||
{
|
||||
ProcessTypeSummary(jsPandaFile, jsPandaFile->GetTypeSummaryOffset(recordName));
|
||||
}
|
||||
|
||||
void TypeSummaryExtractor::ProcessTypeSummary(const JSPandaFile *jsPandaFile, const uint32_t summaryOffset)
|
||||
{
|
||||
EntityId summaryId(summaryOffset);
|
||||
LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
|
||||
bool isFirstIndex = true;
|
||||
lda.EnumerateLiteralVals(summaryId,
|
||||
[this, &isFirstIndex, &jsPandaFile](const LiteralValue &value, const LiteralTag &tag) {
|
||||
switch (tag) {
|
||||
case LiteralTag::LITERALARRAY: {
|
||||
typeOffsets_.emplace_back(std::get<uint32_t>(value));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::BUILTINTYPEINDEX: {
|
||||
typeOffsets_.emplace_back(static_cast<uint32_t>(std::get<uint8_t>(value)));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::INTEGER: {
|
||||
if (isFirstIndex) {
|
||||
numOfTypes_ = std::get<uint32_t>(value);
|
||||
typeOffsets_.emplace_back(numOfTypes_);
|
||||
isFirstIndex = false;
|
||||
} else {
|
||||
numOfRedirects_ = std::get<uint32_t>(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LiteralTag::STRING: {
|
||||
StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
|
||||
CString stringValue = utf::Mutf8AsCString(sd.data);
|
||||
reDirects_.emplace_back(stringValue);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_COMPILER(FATAL) << "TypeSummary should not exist LiteralTag: " << static_cast<uint32_t>(tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
ASSERT(typeOffsets_.size() == numOfTypes_ + 1);
|
||||
ASSERT(reDirects_.size() == numOfRedirects_);
|
||||
}
|
||||
|
||||
void TypeSummaryExtractor::Print() const
|
||||
{
|
||||
for (uint32_t i = 1; i <= numOfTypes_; ++i) { // 1: start index of typeOffsets
|
||||
TypeLiteralExtractor(jsPandaFile_, typeOffsets_[i]).Print();
|
||||
}
|
||||
}
|
||||
|
||||
TypeAnnotationExtractor::TypeAnnotationExtractor(const JSPandaFile *jsPandaFile, const uint32_t methodOffset)
|
||||
{
|
||||
ProcessTypeAnnotation(jsPandaFile, methodOffset);
|
||||
CollectTSMethodKind();
|
||||
}
|
||||
|
||||
void TypeAnnotationExtractor::ProcessTypeAnnotation(const JSPandaFile *jsPandaFile, const uint32_t methodOffset)
|
||||
{
|
||||
uint32_t annoOffset = GetMethodAnnoOffset(jsPandaFile, methodOffset, TYPE_ANNO_ELEMENT_NAME);
|
||||
if (!IsLegalOffset(annoOffset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityId annoId(annoOffset);
|
||||
LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
|
||||
lda.EnumerateLiteralVals(annoId, [this](const LiteralValue &value, const LiteralTag &tag) {
|
||||
switch (tag) {
|
||||
case LiteralTag::INTEGER: {
|
||||
int32_t valueValue = base::bit_cast<int32_t>(std::get<uint32_t>(value));
|
||||
bcOffsets_.emplace_back(valueValue);
|
||||
break;
|
||||
}
|
||||
case LiteralTag::LITERALARRAY: {
|
||||
typeIds_.emplace_back(std::get<uint32_t>(value));
|
||||
tags_.emplace_back(tag);
|
||||
break;
|
||||
}
|
||||
case LiteralTag::BUILTINTYPEINDEX: {
|
||||
typeIds_.emplace_back(static_cast<uint32_t>(std::get<uint8_t>(value)));
|
||||
tags_.emplace_back(tag);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_COMPILER(FATAL) << "TypeAnnotation should not exist LiteralTag: " << static_cast<uint32_t>(tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
ASSERT(bcOffsets_.size() == typeIds_.size());
|
||||
ASSERT(tags_.size() == typeIds_.size());
|
||||
}
|
||||
|
||||
void TypeAnnotationExtractor::CollectTSMethodKind()
|
||||
{
|
||||
ASSERT(bcOffsets_.size() == typeIds_.size());
|
||||
uint32_t length = bcOffsets_.size();
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
if (bcOffsets_[i] != METHOD_ANNOTATION_FUNCTION_TYPE_OFFSET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tags_[i] != LiteralTag::BUILTINTYPEINDEX) {
|
||||
methodTypeOffset_ = typeIds_[i];
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeIds_[i] == METHOD_ANNOTATION_NAMESPACE) {
|
||||
isNamespace_ = true;
|
||||
}
|
||||
typeIds_[i] = 0; // set default value
|
||||
}
|
||||
}
|
||||
|
||||
void TypeAnnotationExtractor::Print() const
|
||||
{
|
||||
const uint32_t typeRightAdjustment = 6;
|
||||
ASSERT(bcOffsets_.size() == typeIds_.size());
|
||||
ASSERT(tags_.size() == typeIds_.size());
|
||||
LOG_COMPILER(INFO) << "====================================================================";
|
||||
LOG_COMPILER(INFO) << "[TypeAnnotation]";
|
||||
uint32_t length = bcOffsets_.size();
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
LOG_COMPILER(INFO) << "Order of bytecodes: " << std::setw(typeRightAdjustment) << bcOffsets_[i] << ", "
|
||||
<< "typeId: " << std::setw(typeRightAdjustment) << typeIds_[i] << ", "
|
||||
<< "tag of typeId: " << PrintTag(tags_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
std::string TypeAnnotationExtractor::PrintTag(LiteralTag tag) const
|
||||
{
|
||||
switch (tag) {
|
||||
case LiteralTag::LITERALARRAY: {
|
||||
return "type literal offset";
|
||||
}
|
||||
case LiteralTag::BUILTINTYPEINDEX: {
|
||||
return "builtin type index";
|
||||
}
|
||||
default: {
|
||||
return "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExportTypeTableExtractor::ExportTypeTableExtractor(const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
bool isBuiltinTable)
|
||||
{
|
||||
ProcessExportTable(jsPandaFile, recordName, isBuiltinTable);
|
||||
}
|
||||
|
||||
void ExportTypeTableExtractor::ProcessExportTable(const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
bool isBuiltinTable)
|
||||
{
|
||||
const char *name = isBuiltinTable ? DECLARED_SYMBOL_TYPES : EXPORTED_SYMBOL_TYPES;
|
||||
uint32_t methodOffset = jsPandaFile->GetMainMethodIndex(recordName);
|
||||
uint32_t annoOffset = GetMethodAnnoOffset(jsPandaFile, methodOffset, name);
|
||||
if (!IsLegalOffset(annoOffset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityId annoId(annoOffset);
|
||||
LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
|
||||
lda.EnumerateLiteralVals(annoId, [this, &jsPandaFile](const LiteralValue &value, const LiteralTag &tag) {
|
||||
switch (tag) {
|
||||
case LiteralTag::LITERALARRAY: {
|
||||
typeIds_.emplace_back(std::get<uint32_t>(value));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::BUILTINTYPEINDEX: {
|
||||
typeIds_.emplace_back(static_cast<uint32_t>(std::get<uint8_t>(value)));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::STRING: {
|
||||
StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
|
||||
exportVars_.emplace_back(utf::Mutf8AsCString(sd.data));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_COMPILER(FATAL) << "TypeExportTable should not exist LiteralTag: " << static_cast<uint32_t>(tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
ASSERT(exportVars_.size() == typeIds_.size());
|
||||
}
|
||||
|
||||
void ExportTypeTableExtractor::Print() const
|
||||
{
|
||||
ASSERT(exportVars_.size() == typeIds_.size());
|
||||
LOG_COMPILER(INFO) << "[ExportTypeTable]";
|
||||
uint32_t length = typeIds_.size();
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
LOG_COMPILER(INFO) << "Export variable: " << exportVars_[i] << ", "
|
||||
<< "typeId: " << typeIds_[i];
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript
|
@ -1,248 +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_JSPANDAFILE_TYPE_LITERAL_EXTRACTOR_H
|
||||
#define ECMASCRIPT_JSPANDAFILE_TYPE_LITERAL_EXTRACTOR_H
|
||||
|
||||
#include "ecmascript/jspandafile/js_pandafile.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class TypeLiteralExtractor {
|
||||
using TypeLiteralValue = std::variant<uint32_t, CString>;
|
||||
|
||||
public:
|
||||
explicit PUBLIC_API TypeLiteralExtractor(const JSPandaFile *jsPandaFile, const uint32_t typeOffset);
|
||||
~TypeLiteralExtractor() = default;
|
||||
NO_COPY_SEMANTIC(TypeLiteralExtractor);
|
||||
NO_MOVE_SEMANTIC(TypeLiteralExtractor);
|
||||
|
||||
inline bool IsVaildTypeLiteral() const
|
||||
{
|
||||
return !array_.empty();
|
||||
}
|
||||
|
||||
inline TSTypeKind GetTypeKind() const
|
||||
{
|
||||
return kind_;
|
||||
}
|
||||
|
||||
inline bool IsGenerics() const
|
||||
{
|
||||
return isGenerics_;
|
||||
}
|
||||
|
||||
inline uint32_t GetIntValue(const uint32_t index) const
|
||||
{
|
||||
ASSERT(index < array_.size());
|
||||
auto t = array_[index];
|
||||
ASSERT(std::holds_alternative<uint32_t>(t));
|
||||
return std::get<uint32_t>(t);
|
||||
}
|
||||
|
||||
inline const CString &GetStringValue(const uint32_t index) const
|
||||
{
|
||||
ASSERT(index < array_.size());
|
||||
const auto &t = array_[index];
|
||||
ASSERT(std::holds_alternative<CString>(t));
|
||||
return std::get<CString>(t);
|
||||
}
|
||||
|
||||
inline uint32_t GetTypeOffset() const
|
||||
{
|
||||
return typeOffset_;
|
||||
}
|
||||
|
||||
template <class Callback>
|
||||
void EnumerateElements(const uint32_t numIndex, const Callback &callback)
|
||||
{
|
||||
ASSERT(numIndex < array_.size());
|
||||
uint32_t length = std::get<uint32_t>(array_[numIndex]);
|
||||
ASSERT(numIndex + length < array_.size());
|
||||
for (uint32_t i = 1; i <= length; i++) {
|
||||
uint32_t value = GetIntValue(numIndex + i);
|
||||
callback(value);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Callback>
|
||||
void EnumerateTypesWithIntKey(const uint32_t numIndex, const Callback &callback)
|
||||
{
|
||||
ASSERT(numIndex < array_.size());
|
||||
const uint32_t gap = 2;
|
||||
uint32_t length = std::get<uint32_t>(array_[numIndex]);
|
||||
ASSERT(numIndex + length * gap < array_.size());
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
uint32_t keyIndex = numIndex + i * gap + KEY_OFFSET;
|
||||
uint32_t valueIndex = numIndex + i * gap + VALUE_OFFSET;
|
||||
uint32_t key = GetIntValue(keyIndex);
|
||||
uint32_t value = GetIntValue(valueIndex);
|
||||
callback(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Callback>
|
||||
void EnumerateProperties(const uint32_t numIndex, const uint32_t gap, const Callback &callback)
|
||||
{
|
||||
ASSERT(numIndex < array_.size());
|
||||
ASSERT(gap >= VALUE_OFFSET);
|
||||
uint32_t length = std::get<uint32_t>(array_[numIndex]);
|
||||
ASSERT(numIndex + length * gap < array_.size());
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
uint32_t keyIndex = numIndex + i * gap + KEY_OFFSET;
|
||||
uint32_t valueIndex = numIndex + i * gap + VALUE_OFFSET;
|
||||
const CString &key = GetStringValue(keyIndex);
|
||||
uint32_t value = GetIntValue(valueIndex);
|
||||
callback(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
void Print() const;
|
||||
|
||||
private:
|
||||
static constexpr uint32_t KEY_OFFSET = 1;
|
||||
static constexpr uint32_t VALUE_OFFSET = 2;
|
||||
|
||||
inline bool IsVaildKind(const uint32_t kindValue) const
|
||||
{
|
||||
return (static_cast<uint32_t>(TSTypeKind::TYPEKIND_FIRST) <= kindValue) &&
|
||||
(kindValue <= static_cast<uint32_t>(TSTypeKind::TYPEKIND_LAST));
|
||||
}
|
||||
|
||||
void ProcessTypeLiteral(const JSPandaFile *jsPandaFile, const uint32_t typeOffset);
|
||||
std::string PrintTypeKind(TSTypeKind typeKind) const;
|
||||
|
||||
std::vector<TypeLiteralValue> array_;
|
||||
uint32_t typeOffset_ { 0 };
|
||||
TSTypeKind kind_ { TSTypeKind::UNKNOWN };
|
||||
bool isGenerics_ { false };
|
||||
};
|
||||
|
||||
class TypeSummaryExtractor {
|
||||
public:
|
||||
explicit TypeSummaryExtractor(const JSPandaFile *jsPandaFile, const CString &recordName);
|
||||
~TypeSummaryExtractor() = default;
|
||||
NO_COPY_SEMANTIC(TypeSummaryExtractor);
|
||||
NO_MOVE_SEMANTIC(TypeSummaryExtractor);
|
||||
|
||||
template <class Callback>
|
||||
void EnumerateTypeOffsets(const uint32_t lastIndex, const Callback &callback)
|
||||
{
|
||||
ASSERT(lastIndex < typeOffsets_.size());
|
||||
for (uint32_t i = 0; i <= lastIndex; i++) {
|
||||
callback(typeOffsets_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
inline uint32_t GetNumOfTypes() const
|
||||
{
|
||||
return numOfTypes_;
|
||||
}
|
||||
|
||||
void Print() const;
|
||||
|
||||
private:
|
||||
void ProcessTypeSummary(const JSPandaFile *jsPandaFile, const uint32_t summaryOffset);
|
||||
|
||||
const JSPandaFile *jsPandaFile_ {nullptr};
|
||||
std::vector<uint32_t> typeOffsets_ {};
|
||||
std::vector<CString> reDirects_ {};
|
||||
uint32_t numOfTypes_ { 0 };
|
||||
uint32_t numOfRedirects_ { 0 };
|
||||
};
|
||||
|
||||
class TypeAnnotationExtractor {
|
||||
using LiteralTag = panda_file::LiteralTag;
|
||||
|
||||
public:
|
||||
explicit PUBLIC_API TypeAnnotationExtractor(const JSPandaFile *jsPandaFile, const uint32_t methodOffset);
|
||||
~TypeAnnotationExtractor() = default;
|
||||
NO_COPY_SEMANTIC(TypeAnnotationExtractor);
|
||||
NO_MOVE_SEMANTIC(TypeAnnotationExtractor);
|
||||
|
||||
template <class Callback>
|
||||
void EnumerateInstsAndTypes(const Callback &callback)
|
||||
{
|
||||
ASSERT(bcOffsets_.size() == typeIds_.size());
|
||||
uint32_t length = bcOffsets_.size();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
callback(bcOffsets_[i], typeIds_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t GetMethodTypeOffset() const
|
||||
{
|
||||
return methodTypeOffset_;
|
||||
}
|
||||
|
||||
bool IsNamespace() const
|
||||
{
|
||||
return isNamespace_;
|
||||
}
|
||||
|
||||
void PUBLIC_API Print() const;
|
||||
|
||||
private:
|
||||
static constexpr const char *TYPE_ANNO_ELEMENT_NAME = "_TypeOfInstruction";
|
||||
static constexpr int METHOD_ANNOTATION_FUNCTION_TYPE_OFFSET = -1;
|
||||
static constexpr int METHOD_ANNOTATION_NAMESPACE = 255;
|
||||
static constexpr int METHOD_ANNOTATION_ENUM = 254;
|
||||
|
||||
void ProcessTypeAnnotation(const JSPandaFile *jsPandaFile, const uint32_t methodOffset);
|
||||
void CollectTSMethodKind();
|
||||
std::string PrintTag(LiteralTag tag) const;
|
||||
|
||||
uint32_t methodTypeOffset_ {0};
|
||||
std::vector<int32_t> bcOffsets_ {};
|
||||
std::vector<uint32_t> typeIds_ {};
|
||||
std::vector<LiteralTag> tags_ {};
|
||||
bool isNamespace_ {false};
|
||||
};
|
||||
|
||||
class ExportTypeTableExtractor {
|
||||
public:
|
||||
explicit ExportTypeTableExtractor(const JSPandaFile *jsPandaFile, const CString &recordName, bool isBuiltinTable);
|
||||
~ExportTypeTableExtractor() = default;
|
||||
NO_COPY_SEMANTIC(ExportTypeTableExtractor);
|
||||
NO_MOVE_SEMANTIC(ExportTypeTableExtractor);
|
||||
|
||||
inline uint32_t GetLength() const
|
||||
{
|
||||
ASSERT(exportVars_.size() == typeIds_.size());
|
||||
return exportVars_.size() + typeIds_.size();
|
||||
}
|
||||
|
||||
template <class Callback>
|
||||
void EnumerateModuleTypes(const Callback &callback)
|
||||
{
|
||||
ASSERT(exportVars_.size() == typeIds_.size());
|
||||
uint32_t length = exportVars_.size();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
callback(exportVars_[i], typeIds_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Print() const;
|
||||
|
||||
private:
|
||||
static constexpr const char *DECLARED_SYMBOL_TYPES = "declaredSymbolTypes";
|
||||
static constexpr const char *EXPORTED_SYMBOL_TYPES = "exportedSymbolTypes";
|
||||
|
||||
void ProcessExportTable(const JSPandaFile *jsPandaFile, const CString &recordName, bool isBuiltinTable);
|
||||
|
||||
std::vector<CString> exportVars_ {};
|
||||
std::vector<uint32_t> typeIds_ {};
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_JSPANDAFILE_TYPE_LITERAL_EXTRACTOR_H
|
@ -17,6 +17,7 @@
|
||||
#define ECMASCRIPT_LEXICALENV_H
|
||||
|
||||
#include "ecmascript/js_object.h"
|
||||
#include "ecmascript/tagged_array-inl.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class LexicalEnv : public TaggedArray {
|
||||
|
@ -116,8 +116,6 @@
|
||||
#include "ecmascript/shared_objects/js_shared_set_iterator.h"
|
||||
#include "ecmascript/shared_objects/js_shared_typed_array.h"
|
||||
#include "ecmascript/tagged_node.h"
|
||||
#include "ecmascript/ts_types/ts_type.h"
|
||||
#include "ecmascript/ts_types/ts_type_table.h"
|
||||
#include "ecmascript/require/js_cjs_module.h"
|
||||
#include "ecmascript/require/js_cjs_require.h"
|
||||
#include "ecmascript/require/js_cjs_exports.h"
|
||||
@ -616,36 +614,6 @@ public:
|
||||
case JSType::JS_API_LIGHT_WEIGHT_SET_ITERATOR:
|
||||
JSAPILightWeightSetIterator::Cast(object)->VisitRangeSlot<visitType>(visitor);
|
||||
break;
|
||||
case JSType::TS_OBJECT_TYPE:
|
||||
TSObjectType::Cast(object)->VisitRangeSlot<visitType>(visitor);
|
||||
break;
|
||||
case JSType::TS_CLASS_TYPE:
|
||||
TSClassType::Cast(object)->VisitRangeSlot<visitType>(visitor);
|
||||
break;
|
||||
case JSType::TS_UNION_TYPE:
|
||||
TSUnionType::Cast(object)->VisitRangeSlot<visitType>(visitor);
|
||||
break;
|
||||
case JSType::TS_INTERFACE_TYPE:
|
||||
TSInterfaceType::Cast(object)->VisitRangeSlot<visitType>(visitor);
|
||||
break;
|
||||
case JSType::TS_CLASS_INSTANCE_TYPE:
|
||||
break;
|
||||
case JSType::TS_FUNCTION_TYPE:
|
||||
TSFunctionType::Cast(object)->VisitRangeSlot<visitType>(visitor);
|
||||
break;
|
||||
case JSType::TS_ARRAY_TYPE:
|
||||
if (visitType == VisitType::ALL_VISIT) {
|
||||
TSArrayType::Cast(object)->VisitRangeSlot<visitType>(visitor);
|
||||
}
|
||||
break;
|
||||
case JSType::TS_ITERATOR_INSTANCE_TYPE:
|
||||
if (visitType == VisitType::ALL_VISIT) {
|
||||
TSIteratorInstanceType::Cast(object)->VisitRangeSlot<visitType>(visitor);
|
||||
}
|
||||
break;
|
||||
case JSType::TS_NAMESPACE_TYPE:
|
||||
TSNamespaceType::Cast(object)->VisitRangeSlot<visitType>(visitor);
|
||||
break;
|
||||
case JSType::RB_TREENODE:
|
||||
RBTreeNode::Cast(object)->VisitRangeSlot<visitType>(visitor);
|
||||
break;
|
||||
|
@ -139,9 +139,6 @@
|
||||
#include "ecmascript/tagged_node.h"
|
||||
#include "ecmascript/tagged_tree.h"
|
||||
#include "ecmascript/template_map.h"
|
||||
#include "ecmascript/ts_types/ts_obj_layout_info.h"
|
||||
#include "ecmascript/ts_types/ts_type.h"
|
||||
#include "ecmascript/ts_types/ts_type_table.h"
|
||||
#include "ecmascript/vtable.h"
|
||||
#ifdef ARK_SUPPORT_INTL
|
||||
#include "ecmascript/js_collator.h"
|
||||
@ -3916,193 +3913,6 @@ JSHandle<ClassInfoExtractor> ObjectFactory::NewClassInfoExtractor(JSHandle<JSTag
|
||||
return obj;
|
||||
}
|
||||
|
||||
// ----------------------------------- new TSType ----------------------------------------
|
||||
JSHandle<TSObjLayoutInfo> ObjectFactory::CreateTSObjLayoutInfo(int propNum, JSTaggedValue initVal)
|
||||
{
|
||||
uint32_t arrayLength = TSObjLayoutInfo::ComputeArrayLength(propNum);
|
||||
JSHandle<TSObjLayoutInfo> tsPropInfoHandle = JSHandle<TSObjLayoutInfo>::Cast(NewTaggedArray(arrayLength, initVal));
|
||||
tsPropInfoHandle->SetNumOfProperties(thread_, 0);
|
||||
return tsPropInfoHandle;
|
||||
}
|
||||
|
||||
JSHandle<TSObjectType> ObjectFactory::NewTSObjectType(uint32_t numOfKeys)
|
||||
{
|
||||
NewObjectHook();
|
||||
|
||||
TaggedObject *header = heap_->AllocateYoungOrHugeObject(
|
||||
JSHClass::Cast(thread_->GlobalConstants()->GetTSObjectTypeClass().GetTaggedObject()));
|
||||
JSHandle<TSObjectType> objectType(thread_, header);
|
||||
objectType->SetObjLayoutInfo(thread_, JSTaggedValue::Undefined());
|
||||
objectType->SetIndexSigns(thread_, JSTaggedValue::Undefined());
|
||||
objectType->SetGT(GlobalTSTypeRef::Default());
|
||||
|
||||
JSHandle<TSObjLayoutInfo> tsPropInfo = CreateTSObjLayoutInfo(numOfKeys);
|
||||
objectType->SetObjLayoutInfo(thread_, tsPropInfo);
|
||||
return objectType;
|
||||
}
|
||||
|
||||
JSHandle<TSClassType> ObjectFactory::NewTSClassType()
|
||||
{
|
||||
NewObjectHook();
|
||||
|
||||
TaggedObject *header = heap_->AllocateYoungOrHugeObject(
|
||||
JSHClass::Cast(thread_->GlobalConstants()->GetTSClassTypeClass().GetTaggedObject()));
|
||||
JSHandle<TSClassType> classType(thread_, header);
|
||||
|
||||
classType->SetGT(GlobalTSTypeRef::Default());
|
||||
classType->SetInstanceType(thread_, JSTaggedValue::Undefined());
|
||||
classType->SetConstructorType(thread_, JSTaggedValue::Undefined());
|
||||
classType->SetPrototypeType(thread_, JSTaggedValue::Undefined());
|
||||
classType->SetName(thread_, JSTaggedValue::Undefined());
|
||||
classType->SetIndexSigns(thread_, JSTaggedValue::Undefined());
|
||||
classType->SetExtensionGT(GlobalTSTypeRef::Default());
|
||||
classType->ClearBitField();
|
||||
|
||||
return classType;
|
||||
}
|
||||
|
||||
JSHandle<TSInterfaceType> ObjectFactory::NewTSInterfaceType()
|
||||
{
|
||||
NewObjectHook();
|
||||
|
||||
TaggedObject *header = heap_->AllocateYoungOrHugeObject(
|
||||
JSHClass::Cast(thread_->GlobalConstants()->GetTSInterfaceTypeClass().GetTaggedObject()));
|
||||
JSHandle<TSInterfaceType> interfaceType(thread_, header);
|
||||
|
||||
JSHandle<TaggedArray> extends = EmptyArray();
|
||||
interfaceType->SetGT(GlobalTSTypeRef::Default());
|
||||
interfaceType->SetExtends(thread_, extends);
|
||||
interfaceType->SetFields(thread_, JSTaggedValue::Undefined());
|
||||
interfaceType->SetIndexSigns(thread_, JSTaggedValue::Undefined());
|
||||
|
||||
return interfaceType;
|
||||
}
|
||||
|
||||
|
||||
JSHandle<TSUnionType> ObjectFactory::NewTSUnionType(uint32_t length)
|
||||
{
|
||||
NewObjectHook();
|
||||
ASSERT(length > 0);
|
||||
|
||||
TaggedObject *header = heap_->AllocateYoungOrHugeObject(
|
||||
JSHClass::Cast(thread_->GlobalConstants()->GetTSUnionTypeClass().GetTaggedObject()));
|
||||
JSHandle<TSUnionType> unionType(thread_, header);
|
||||
|
||||
unionType->SetGT(GlobalTSTypeRef::Default());
|
||||
unionType->SetComponents(thread_, JSTaggedValue::Undefined());
|
||||
JSHandle<TaggedArray> componentTypes = NewTaggedArray(length, JSTaggedValue::Undefined());
|
||||
unionType->SetComponents(thread_, componentTypes);
|
||||
|
||||
return unionType;
|
||||
}
|
||||
|
||||
JSHandle<TSClassInstanceType> ObjectFactory::NewTSClassInstanceType()
|
||||
{
|
||||
NewObjectHook();
|
||||
|
||||
TaggedObject *header = heap_->AllocateYoungOrHugeObject(
|
||||
JSHClass::Cast(thread_->GlobalConstants()->GetTSClassInstanceTypeClass().GetTaggedObject()));
|
||||
JSHandle<TSClassInstanceType> classInstanceType(thread_, header);
|
||||
|
||||
classInstanceType->SetGT(GlobalTSTypeRef::Default());
|
||||
classInstanceType->SetClassGT(GlobalTSTypeRef::Default());
|
||||
|
||||
return classInstanceType;
|
||||
}
|
||||
|
||||
JSHandle<TSFunctionType> ObjectFactory::NewTSFunctionType(uint32_t length)
|
||||
{
|
||||
NewObjectHook();
|
||||
|
||||
TaggedObject *header = heap_->AllocateYoungOrHugeObject(
|
||||
JSHClass::Cast(thread_->GlobalConstants()->GetTSFunctionTypeClass().GetTaggedObject()));
|
||||
JSHandle<TSFunctionType> functionType(thread_, header);
|
||||
|
||||
functionType->SetGT(GlobalTSTypeRef::Default());
|
||||
functionType->SetName(thread_, JSTaggedValue::Undefined());
|
||||
functionType->SetParameterTypes(thread_, JSTaggedValue::Undefined());
|
||||
functionType->SetReturnGT(GlobalTSTypeRef::Default());
|
||||
functionType->SetThisGT(GlobalTSTypeRef::Default());
|
||||
functionType->ClearBitField();
|
||||
functionType->SetMethodOffset(0);
|
||||
|
||||
JSHandle<TaggedArray> parameterTypes = NewTaggedArray(length, JSTaggedValue::Undefined());
|
||||
functionType->SetParameterTypes(thread_, parameterTypes);
|
||||
|
||||
return functionType;
|
||||
}
|
||||
|
||||
JSHandle<TSArrayType> ObjectFactory::NewTSArrayType()
|
||||
{
|
||||
NewObjectHook();
|
||||
|
||||
TaggedObject *header = heap_->AllocateYoungOrHugeObject(
|
||||
JSHClass::Cast(thread_->GlobalConstants()->GetTSArrayTypeClass().GetTaggedObject()));
|
||||
|
||||
JSHandle<TSArrayType> arrayType(thread_, header);
|
||||
arrayType->SetElementGT(GlobalTSTypeRef::Default());
|
||||
|
||||
return arrayType;
|
||||
}
|
||||
|
||||
JSHandle<TSTypeTable> ObjectFactory::NewTSTypeTable(uint32_t length)
|
||||
{
|
||||
NewObjectHook();
|
||||
|
||||
size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length + TSTypeTable::RESERVE_TABLE_LENGTH);
|
||||
JSHClass *arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject());
|
||||
auto header = heap_->AllocateOldOrHugeObject(arrayClass, size);
|
||||
|
||||
JSHandle<TSTypeTable> table(thread_, header);
|
||||
table->InitializeWithSpecialValue(JSTaggedValue::Undefined(), length + TSTypeTable::RESERVE_TABLE_LENGTH);
|
||||
table->SetNumberOfTypes(thread_);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
JSHandle<TSModuleTable> ObjectFactory::NewTSModuleTable(uint32_t length)
|
||||
{
|
||||
NewObjectHook();
|
||||
ASSERT(length > 0);
|
||||
|
||||
size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length);
|
||||
JSHClass *arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject());
|
||||
auto header = heap_->AllocateYoungOrHugeObject(arrayClass, size);
|
||||
JSHandle<TSModuleTable> array(thread_, header);
|
||||
array->InitializeWithSpecialValue(JSTaggedValue::Undefined(), length);
|
||||
array->SetNumberOfTSTypeTables(thread_, 0);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
JSHandle<TSIteratorInstanceType> ObjectFactory::NewTSIteratorInstanceType()
|
||||
{
|
||||
NewObjectHook();
|
||||
|
||||
TaggedObject *header = heap_->AllocateYoungOrHugeObject(
|
||||
JSHClass::Cast(thread_->GlobalConstants()->GetTSIteratorInstanceTypeClass().GetTaggedObject()));
|
||||
JSHandle<TSIteratorInstanceType> iteratorInstanceType(thread_, header);
|
||||
|
||||
iteratorInstanceType->SetGT(GlobalTSTypeRef::Default());
|
||||
iteratorInstanceType->SetKindGT(GlobalTSTypeRef::Default());
|
||||
iteratorInstanceType->SetElementGT(GlobalTSTypeRef::Default());
|
||||
|
||||
return iteratorInstanceType;
|
||||
}
|
||||
|
||||
JSHandle<TSNamespaceType> ObjectFactory::NewTSNamespaceType()
|
||||
{
|
||||
NewObjectHook();
|
||||
|
||||
TaggedObject *header = heap_->AllocateYoungOrHugeObject(
|
||||
JSHClass::Cast(thread_->GlobalConstants()->GetTSNamespaceTypeClass().GetTaggedObject()));
|
||||
JSHandle<TSNamespaceType> namespaceType(thread_, header);
|
||||
|
||||
namespaceType->SetPropertyType(thread_, JSTaggedValue::Undefined());
|
||||
JSHandle<TSObjLayoutInfo> tsPropInfo = CreateTSObjLayoutInfo(TSObjLayoutInfo::DEFAULT_CAPACITY);
|
||||
namespaceType->SetPropertyType(thread_, tsPropInfo);
|
||||
return namespaceType;
|
||||
}
|
||||
// ----------------------------------- new string ----------------------------------------
|
||||
JSHandle<EcmaString> ObjectFactory::NewFromASCII(std::string_view data)
|
||||
{
|
||||
|
@ -106,19 +106,6 @@ class LayoutInfo;
|
||||
class JSIntlBoundFunction;
|
||||
class FreeObject;
|
||||
class JSNativePointer;
|
||||
class TSModuleTable;
|
||||
class TSTypeTable;
|
||||
class TSObjLayoutInfo;
|
||||
class TSType;
|
||||
class TSObjectType;
|
||||
class TSClassType;
|
||||
class TSUnionType;
|
||||
class TSInterfaceType;
|
||||
class TSClassInstanceType;
|
||||
class TSFunctionType;
|
||||
class TSArrayType;
|
||||
class TSIteratorInstanceType;
|
||||
class TSNamespaceType;
|
||||
class JSAPIArrayList;
|
||||
class JSAPIArrayListIterator;
|
||||
class JSAPIDeque;
|
||||
@ -571,20 +558,6 @@ public:
|
||||
JSHandle<ClassInfoExtractor> NewClassInfoExtractor(JSHandle<JSTaggedValue> method);
|
||||
JSHandle<ClassLiteral> NewClassLiteral();
|
||||
|
||||
// ----------------------------------- new TSType ----------------------------------------
|
||||
JSHandle<TSObjLayoutInfo> CreateTSObjLayoutInfo(int propNum, JSTaggedValue initVal = JSTaggedValue::Hole());
|
||||
JSHandle<TSObjectType> NewTSObjectType(uint32_t numOfKeys);
|
||||
JSHandle<TSClassType> NewTSClassType();
|
||||
JSHandle<TSUnionType> NewTSUnionType(uint32_t length);
|
||||
JSHandle<TSInterfaceType> NewTSInterfaceType();
|
||||
JSHandle<TSClassInstanceType> NewTSClassInstanceType();
|
||||
JSHandle<TSTypeTable> NewTSTypeTable(uint32_t length);
|
||||
JSHandle<TSModuleTable> NewTSModuleTable(uint32_t length);
|
||||
JSHandle<TSFunctionType> NewTSFunctionType(uint32_t length);
|
||||
JSHandle<TSArrayType> NewTSArrayType();
|
||||
JSHandle<TSIteratorInstanceType> NewTSIteratorInstanceType();
|
||||
JSHandle<TSNamespaceType> NewTSNamespaceType();
|
||||
|
||||
// ----------------------------------- new string ----------------------------------------
|
||||
JSHandle<EcmaString> PUBLIC_API NewFromASCII(std::string_view data);
|
||||
JSHandle<EcmaString> PUBLIC_API NewFromUtf8(std::string_view data);
|
||||
@ -877,7 +850,6 @@ private:
|
||||
friend class GlobalEnvConstants;
|
||||
friend class EcmaString;
|
||||
friend class SnapshotProcessor;
|
||||
friend class TSManager;
|
||||
friend class SingleCharTable;
|
||||
void InitObjectFields(const TaggedObject *object);
|
||||
|
||||
|
@ -147,7 +147,7 @@ HWTEST_F_L0(OhosTest, OhosPkgArgsParse)
|
||||
runtimeOptions_.SetPGOProfilerPath(runtimeAp);
|
||||
runtimeOptions_.SetCompilerPkgJsonInfo(BuildOhosPkgJson(""));
|
||||
|
||||
CompilationOptions cOptions(vm_, runtimeOptions_);
|
||||
CompilationOptions cOptions(runtimeOptions_);
|
||||
AotCompilerPreprocessor preProcessor(vm_, runtimeOptions_, pkgArgsMap, decoder, pandaFileNames);
|
||||
OhosPkgArgs::ParseArgs(preProcessor, cOptions);
|
||||
|
||||
@ -169,7 +169,7 @@ HWTEST_F_L0(OhosTest, OhosPkgArgsParsePgoDir)
|
||||
arg_list_t pandaFileNames {};
|
||||
std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
|
||||
PGOProfilerDecoder decoder;
|
||||
CompilationOptions cOptions(vm_, runtimeOptions_);
|
||||
CompilationOptions cOptions(runtimeOptions_);
|
||||
AotCompilerPreprocessor preProcessor(vm_, runtimeOptions_, pkgArgsMap, decoder, pandaFileNames);
|
||||
OhosPkgArgs::ParseArgs(preProcessor, cOptions);
|
||||
|
||||
@ -192,7 +192,7 @@ HWTEST_F_L0(OhosTest, UseBaselineApFromPgoDir)
|
||||
arg_list_t pandaFileNames {};
|
||||
std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
|
||||
PGOProfilerDecoder decoder;
|
||||
CompilationOptions cOptions(vm_, runtimeOptions_);
|
||||
CompilationOptions cOptions(runtimeOptions_);
|
||||
AotCompilerPreprocessor preProcessor(vm_, runtimeOptions_, pkgArgsMap, decoder, pandaFileNames);
|
||||
runtimeOptions_.SetCompilerPkgJsonInfo(BuildOhosPkgJson(pgoDir));
|
||||
// Input format is correct, but there is no available ap file for pgoDir, return success.
|
||||
@ -220,7 +220,7 @@ HWTEST_F_L0(OhosTest, UseRuntimeApWhenOnlyRuntimeExits)
|
||||
arg_list_t pandaFileNames {};
|
||||
std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
|
||||
PGOProfilerDecoder decoder;
|
||||
CompilationOptions cOptions(vm_, runtimeOptions_);
|
||||
CompilationOptions cOptions(runtimeOptions_);
|
||||
AotCompilerPreprocessor preProcessor(vm_, runtimeOptions_, pkgArgsMap, decoder, pandaFileNames);
|
||||
runtimeOptions_.SetCompilerPkgJsonInfo(BuildOhosPkgJson(pgoDir));
|
||||
ASSERT_TRUE(FileExist(runtimeAp.c_str()));
|
||||
@ -250,7 +250,7 @@ HWTEST_F_L0(OhosTest, UseMergedApWhenOnlyMergedExist)
|
||||
arg_list_t pandaFileNames {};
|
||||
std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
|
||||
PGOProfilerDecoder decoder;
|
||||
CompilationOptions cOptions(vm_, runtimeOptions_);
|
||||
CompilationOptions cOptions(runtimeOptions_);
|
||||
AotCompilerPreprocessor preProcessor(vm_, runtimeOptions_, pkgArgsMap, decoder, pandaFileNames);
|
||||
runtimeOptions_.SetCompilerPkgJsonInfo(BuildOhosPkgJson(pgoDir));
|
||||
ASSERT_TRUE(preProcessor.HandleTargetCompilerMode(cOptions));
|
||||
@ -280,7 +280,7 @@ HWTEST_F_L0(OhosTest, UseMergedApWhenBothRuntimeAndMergedExist)
|
||||
arg_list_t pandaFileNames {};
|
||||
std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
|
||||
PGOProfilerDecoder decoder;
|
||||
CompilationOptions cOptions(vm_, runtimeOptions_);
|
||||
CompilationOptions cOptions(runtimeOptions_);
|
||||
AotCompilerPreprocessor preProcessor(vm_, runtimeOptions_, pkgArgsMap, decoder, pandaFileNames);
|
||||
runtimeOptions_.SetCompilerPkgJsonInfo(BuildOhosPkgJson(pgoDir));
|
||||
ASSERT_TRUE(OhosPkgArgs::ParseArgs(preProcessor, cOptions));
|
||||
|
@ -46,7 +46,6 @@ foreach(file, test_js_files) {
|
||||
extra_args = []
|
||||
extra_args += [ "--module" ]
|
||||
extra_args += [ "--merge-abc" ]
|
||||
extra_args += [ "--type-extractor" ]
|
||||
in_puts = [ test_js ]
|
||||
out_puts = [ test_abc ]
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <cerrno>
|
||||
|
||||
#include "ecmascript/compiler/aot_file/aot_file_manager.h"
|
||||
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/jobs/micro_job_queue.h"
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "ecmascript/snapshot/mem/snapshot.h"
|
||||
#include "ecmascript/snapshot/mem/snapshot_processor.h"
|
||||
#include "ecmascript/snapshot/tests/snapshot_mock.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
using namespace panda::ecmascript;
|
||||
|
||||
|
@ -46,7 +46,6 @@
|
||||
#include "ecmascript/runtime.h"
|
||||
#include "ecmascript/stackmap/llvm/llvm_stackmap_parser.h"
|
||||
#include "ecmascript/template_string.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
using ArrayHelper = base::ArrayHelper;
|
||||
|
@ -74,10 +74,8 @@
|
||||
#include "ecmascript/object_factory.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler.h"
|
||||
#include "ecmascript/stubs/runtime_stubs.h"
|
||||
#include "ecmascript/subtyping_operator.h"
|
||||
#include "ecmascript/tagged_dictionary.h"
|
||||
#include "ecmascript/tagged_node.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
#include "ecmascript/linked_hash_table.h"
|
||||
#include "ecmascript/builtins/builtins_object.h"
|
||||
#include "libpandafile/bytecode_instruction-inl.h"
|
||||
@ -541,9 +539,6 @@ DEF_RUNTIME_STUBS(UpdateLayOutAndAddTransition)
|
||||
|
||||
JSHClass::AddPropertyToNewHClass(thread, oldHClassHandle, newHClassHandle, keyHandle, attrValue);
|
||||
|
||||
if (oldHClassHandle->HasTSSubtyping()) {
|
||||
SubtypingOperator::TryMaintainTSSubtyping(thread, oldHClassHandle, newHClassHandle, keyHandle);
|
||||
}
|
||||
return JSTaggedValue::Hole().GetRawData();
|
||||
}
|
||||
|
||||
|
@ -1,131 +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_SUBTYPING_OPERATOR_INL_H
|
||||
#define ECMASCRIPT_SUBTYPING_OPERATOR_INL_H
|
||||
|
||||
#include "ecmascript/subtyping_operator.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
template<class T>
|
||||
int SubtypingOperator::GetElementByKey(const JSThread *thread, T *obj, JSTaggedValue key)
|
||||
{
|
||||
if constexpr(std::is_same_v<T, TSObjLayoutInfo>) {
|
||||
return obj->GetElementIndexByKey(key);
|
||||
} else if constexpr(std::is_same_v<T, VTable>) {
|
||||
return obj->GetTupleIndexByName(key);
|
||||
} else if constexpr(std::is_same_v<T, JSHClass>) {
|
||||
LayoutInfo *objLayout = LayoutInfo::Cast(obj->GetLayout().GetTaggedObject());
|
||||
return objLayout->FindElementWithCache(thread, obj, key, obj->NumberOfProps());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool SubtypingOperator::IsLegalElement(const JSThread *thread, T *obj, JSTaggedValue key, JSTaggedValue expectedType)
|
||||
{
|
||||
// when the property of the subtyping does not exist on the parent class,
|
||||
// or exists and has the same type, the property is considered legal
|
||||
if constexpr(std::is_same_v<T, TSObjLayoutInfo>) {
|
||||
int index = obj->GetElementIndexByKey(key);
|
||||
if (index != -1 && obj->GetTypeId(index) != expectedType) {
|
||||
return false;
|
||||
}
|
||||
} else if constexpr(std::is_same_v<T, VTable>) {
|
||||
int index = obj->GetTupleIndexByName(key);
|
||||
if (index != -1) {
|
||||
// type: ture --> isAccessor, false --> normal function
|
||||
ASSERT(expectedType.IsBoolean());
|
||||
bool isAccessor = expectedType.IsTrue();
|
||||
if (obj->IsAccessor(index) != isAccessor) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if constexpr(std::is_same_v<T, JSHClass>) {
|
||||
LayoutInfo *objLayout = LayoutInfo::Cast(obj->GetLayout().GetTaggedObject());
|
||||
int index = objLayout->FindElementWithCache(thread, obj, key, obj->NumberOfProps());
|
||||
if (index != -1) {
|
||||
// type: ture --> isAccessor, false --> normal function
|
||||
ASSERT(expectedType.IsBoolean());
|
||||
PropertyAttributes attr(objLayout->GetAttr(index));
|
||||
bool isAccessor = expectedType.IsTrue();
|
||||
if (attr.IsAccessor() != isAccessor) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
uint32_t SubtypingOperator::GetLength(T *obj)
|
||||
{
|
||||
if constexpr(std::is_same_v<T, TSObjLayoutInfo>) {
|
||||
return obj->GetNumOfProperties();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
JSTaggedValue SubtypingOperator::GetKey(T *obj, uint32_t index)
|
||||
{
|
||||
if constexpr(std::is_same_v<T, TSObjLayoutInfo>) {
|
||||
return obj->GetKey(index);
|
||||
} else {
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
JSTaggedValue SubtypingOperator::GetType(const JSThread *thread, T *obj, uint32_t index, ConditionType ConditionType)
|
||||
{
|
||||
if constexpr(std::is_same_v<T, TSObjLayoutInfo>) {
|
||||
if (ConditionType == ConditionType::SUB_LOCAL_CONTAIN_SUP_LOCAL) {
|
||||
return obj->GetTypeId(index);
|
||||
} else if (ConditionType == ConditionType::SUB_VTABLE_CONTAIN_SUP_VTABLE) {
|
||||
TSManager *tsManager = const_cast<JSThread*>(thread)->GetCurrentEcmaContext()->GetTSManager();
|
||||
GlobalTSTypeRef typeGT = GlobalTSTypeRef(obj->GetTypeId(index).GetInt());
|
||||
return JSTaggedValue(tsManager->IsGetterSetterFunc(typeGT));
|
||||
}
|
||||
}
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
||||
template<class Suber, class Super>
|
||||
bool SubtypingOperator::SubtypingCondition(const JSThread *thread, Suber *suber, Super *super,
|
||||
ConditionType ConditionType)
|
||||
{
|
||||
uint32_t len = GetLength(suber);
|
||||
for (uint32_t index = 0; index < len; ++index) {
|
||||
JSTaggedValue key = GetKey(suber, index);
|
||||
ASSERT(!key.IsUndefined());
|
||||
if (ConditionType == ConditionType::SUB_LOCAL_CONTAIN_SUP_LOCAL ||
|
||||
ConditionType == ConditionType::SUB_VTABLE_CONTAIN_SUP_VTABLE) {
|
||||
JSTaggedValue type = GetType(thread, suber, index, ConditionType);
|
||||
ASSERT(!type.IsUndefined());
|
||||
if (!IsLegalElement(thread, super, key, type)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (GetElementByKey(thread, super, key) != -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_SUBTYPING_OPERATOR_INL_H
|
@ -1,266 +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/global_env.h"
|
||||
#include "ecmascript/ic/proto_change_details.h"
|
||||
#include "ecmascript/subtyping_operator-inl.h"
|
||||
#include "ecmascript/vtable.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
bool SubtypingOperator::CheckBaseClass(const JSThread *thread, const JSHandle<TSClassType> &classType)
|
||||
{
|
||||
// the base class type does not need to check rules 2 and 4, because Object has no local properties
|
||||
TSObjectType *it = TSObjectType::Cast(classType->GetInstanceType().GetTaggedObject());
|
||||
TSObjLayoutInfo *itLayout = TSObjLayoutInfo::Cast(it->GetObjLayoutInfo().GetTaggedObject());
|
||||
TSObjectType *pt = TSObjectType::Cast(classType->GetPrototypeType().GetTaggedObject());
|
||||
TSObjLayoutInfo *ptLayout = TSObjLayoutInfo::Cast(pt->GetObjLayoutInfo().GetTaggedObject());
|
||||
|
||||
// itLayout -> local, ptLayout -> vtable
|
||||
if (!SubtypingCondition(thread, itLayout, ptLayout, ConditionType::NO_OVERLAP_SUB_LOCAL_SUB_VTABLE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSHandle<panda::ecmascript::GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
JSHClass *oProtoHClass = JSHClass::Cast(env->GetObjectFunctionPrototypeClass()->GetTaggedObject());
|
||||
|
||||
if (!SubtypingCondition(thread, ptLayout, oProtoHClass, ConditionType::SUB_VTABLE_CONTAIN_SUP_VTABLE) ||
|
||||
!SubtypingCondition(thread, itLayout, oProtoHClass, ConditionType::NO_OVERLAP_SUP_VTABLE_SUB_LOCAL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SubtypingOperator::CheckSubtyping(const JSThread *thread, const JSHandle<TSClassType> &classType)
|
||||
{
|
||||
TSManager *tsManager = const_cast<JSThread*>(thread)->GetCurrentEcmaContext()->GetTSManager();
|
||||
JSHandle<TSClassType> eClassType = tsManager->GetExtendedClassType(classType);
|
||||
JSHClass *eIhc = JSHClass::Cast(tsManager->GetInstanceTSHClass(eClassType).GetTaggedObject());
|
||||
WeakVector *eSupers = WeakVector::Cast(eIhc->GetSupers().GetTaggedObject());
|
||||
|
||||
// if the supers of extended IHClass is empty, means the chain is broken
|
||||
// will be overwritten by IsTSChainInfoFilled() in PR Part2.
|
||||
if (eSupers->Empty() || eIhc->GetLevel() + 1 == MAX_LEVEL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TSObjectType *it = TSObjectType::Cast(classType->GetInstanceType().GetTaggedObject());
|
||||
TSObjLayoutInfo *itLayout = TSObjLayoutInfo::Cast(it->GetObjLayoutInfo().GetTaggedObject());
|
||||
TSObjectType *pt = TSObjectType::Cast(classType->GetPrototypeType().GetTaggedObject());
|
||||
TSObjLayoutInfo *ptLayout = TSObjLayoutInfo::Cast(pt->GetObjLayoutInfo().GetTaggedObject());
|
||||
|
||||
TSObjectType *eIt = TSObjectType::Cast(eClassType->GetInstanceType().GetTaggedObject());
|
||||
TSObjLayoutInfo *eItLayout = TSObjLayoutInfo::Cast(eIt->GetObjLayoutInfo().GetTaggedObject());
|
||||
VTable *eVtable = VTable::Cast(eIhc->GetVTable().GetTaggedObject());
|
||||
|
||||
// itLayout -> local, eItLayout -> extended local
|
||||
// ptLayout -> vtable, eVtable -> extended vtable
|
||||
if (!SubtypingCondition(thread, itLayout, ptLayout, ConditionType::NO_OVERLAP_SUB_LOCAL_SUB_VTABLE) ||
|
||||
!SubtypingCondition(thread, itLayout, eItLayout, ConditionType::SUB_LOCAL_CONTAIN_SUP_LOCAL) ||
|
||||
!SubtypingCondition(thread, ptLayout, eVtable, ConditionType::SUB_VTABLE_CONTAIN_SUP_VTABLE) ||
|
||||
!SubtypingCondition(thread, ptLayout, eItLayout, ConditionType::NO_OVERLAP_SUP_LOCAL_SUB_VTABLE) ||
|
||||
!SubtypingCondition(thread, itLayout, eVtable, ConditionType::NO_OVERLAP_SUP_VTABLE_SUB_LOCAL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SubtypingOperator::MergeClassField(const JSThread *thread, const JSHandle<TSClassType> &classType)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
TSManager *tsManager = const_cast<JSThread*>(thread)->GetCurrentEcmaContext()->GetTSManager();
|
||||
|
||||
JSHandle<TSClassType> eClassType = tsManager->GetExtendedClassType(classType);
|
||||
JSHandle<TSObjectType> field(thread, classType->GetInstanceType());
|
||||
TSObjectType *eField = TSObjectType::Cast(eClassType->GetInstanceType());
|
||||
|
||||
JSHandle<TSObjLayoutInfo> layout(thread, field->GetObjLayoutInfo());
|
||||
JSHandle<TSObjLayoutInfo> eLayout(thread, eField->GetObjLayoutInfo());
|
||||
|
||||
uint32_t numSelfTypes = layout->GetNumOfProperties();
|
||||
uint32_t numExtendTypes = eLayout->GetNumOfProperties();
|
||||
uint32_t numTypes = numSelfTypes + numExtendTypes;
|
||||
JSHandle<TSObjLayoutInfo> newLayout = factory->CreateTSObjLayoutInfo(numTypes);
|
||||
|
||||
for (uint32_t index = 0; index < numExtendTypes; index++) {
|
||||
JSTaggedValue key = eLayout->GetKey(index);
|
||||
JSTaggedValue type = eLayout->GetTypeId(index);
|
||||
JSTaggedValue attribute = eLayout->GetAttribute(index);
|
||||
newLayout->AddProperty(thread, key, type, attribute);
|
||||
}
|
||||
|
||||
for (uint32_t index = 0; index < numSelfTypes; index++) {
|
||||
JSTaggedValue key = layout->GetKey(index);
|
||||
if (eLayout->Find(key)) {
|
||||
continue;
|
||||
}
|
||||
JSTaggedValue type = layout->GetTypeId(index);
|
||||
JSTaggedValue attribute = layout->GetAttribute(index);
|
||||
newLayout->AddProperty(thread, key, type, attribute);
|
||||
}
|
||||
|
||||
field->SetObjLayoutInfo(thread, newLayout);
|
||||
classType->SetHasLinked(true);
|
||||
}
|
||||
|
||||
void SubtypingOperator::FillTSInheritInfo(JSThread *thread, const JSHandle<TSClassType> &classType,
|
||||
const JSHandle<JSHClass> &ihcHandle)
|
||||
{
|
||||
TSManager *tsManager = thread->GetCurrentEcmaContext()->GetTSManager();
|
||||
JSObject *prototype = JSObject::Cast(ihcHandle->GetProto());
|
||||
JSHandle<JSHClass> phcHandle(thread, prototype->GetJSHClass());
|
||||
JSHandle<JSHClass> eIhcHandle(thread, JSTaggedValue::Undefined());
|
||||
|
||||
if (classType->IsBaseClassType()) {
|
||||
GenVTable(thread, ihcHandle, phcHandle, eIhcHandle);
|
||||
ihcHandle->SetLevel(0);
|
||||
AddSuper(thread, ihcHandle, eIhcHandle);
|
||||
} else {
|
||||
// get extended instance TSHclass
|
||||
JSHandle<TSClassType> eClassType = tsManager->GetExtendedClassType(classType);
|
||||
JSTaggedValue eIhc = tsManager->GetInstanceTSHClass(eClassType);
|
||||
eIhcHandle = JSHandle<JSHClass>(thread, eIhc);
|
||||
|
||||
uint8_t eIhcLevel = eIhcHandle->GetLevel();
|
||||
JSHandle<JSObject> ePrototype(thread, eIhcHandle->GetProto());
|
||||
|
||||
GenVTable(thread, ihcHandle, phcHandle, eIhcHandle);
|
||||
ihcHandle->SetLevel(eIhcLevel + 1);
|
||||
AddSuper(thread, ihcHandle, eIhcHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void SubtypingOperator::GenVTable(const JSThread *thread, const JSHandle<JSHClass> &ihcHandle,
|
||||
const JSHandle<JSHClass> &phcHandle, const JSHandle<JSHClass> &eIhcHandle)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
|
||||
JSHandle<JSTaggedValue> owner(thread, ihcHandle->GetProto());
|
||||
uint32_t propNumber = phcHandle->NumberOfProps();
|
||||
JSMutableHandle<VTable> eVTable(thread, JSTaggedValue::Undefined());
|
||||
uint32_t ePropNumber = 0;
|
||||
if (!eIhcHandle.GetTaggedValue().IsUndefined()) {
|
||||
eVTable.Update(eIhcHandle->GetVTable());
|
||||
ePropNumber = eVTable->GetNumberOfTuples();
|
||||
}
|
||||
|
||||
uint32_t loc = 0;
|
||||
uint32_t finalLength = propNumber + ePropNumber;
|
||||
JSHandle<VTable> vtable = factory->NewVTable(finalLength);
|
||||
|
||||
for (uint32_t index = 0; index < ePropNumber; ++index) {
|
||||
VTable::Tuple tuple = eVTable->GetTuple(thread, index);
|
||||
vtable->SetByIndex(thread, loc++, tuple);
|
||||
}
|
||||
|
||||
for (uint32_t index = 0; index < propNumber; ++index) {
|
||||
VTable::Tuple tuple = VTable::CreateTuple(thread, phcHandle.GetTaggedValue(), owner, index);
|
||||
JSTaggedValue nameVal = tuple.GetItem(VTable::TupleItem::NAME).GetTaggedValue();
|
||||
// When the vtable and the parent class vtable have the same name attribute,
|
||||
// the attribute of the parent class vtable should be overwritten
|
||||
int tIndex = vtable->GetTupleIndexByName(nameVal);
|
||||
if (tIndex == -1) {
|
||||
vtable->SetByIndex(thread, loc++, tuple);
|
||||
} else {
|
||||
vtable->SetByIndex(thread, tIndex, tuple);
|
||||
}
|
||||
}
|
||||
|
||||
if (loc != finalLength) {
|
||||
vtable->Trim(thread, loc);
|
||||
}
|
||||
ihcHandle->SetVTable(thread, vtable);
|
||||
}
|
||||
|
||||
void SubtypingOperator::AddSuper(const JSThread *thread, const JSHandle<JSHClass> &iHClass,
|
||||
const JSHandle<JSHClass> &superHClass)
|
||||
{
|
||||
JSHandle<WeakVector> old;
|
||||
if (superHClass.GetTaggedValue().IsUndefined()) {
|
||||
old = JSHandle<WeakVector>(thread, iHClass->GetSupers());
|
||||
} else {
|
||||
old = JSHandle<WeakVector>(thread, superHClass->GetSupers());
|
||||
}
|
||||
JSHandle<WeakVector> supersHandle = WeakVector::Copy(thread, old, old->Full());
|
||||
|
||||
JSHandle<JSTaggedValue> iHClassVal(iHClass);
|
||||
JSHandle<WeakVector> newSupers = WeakVector::Append(thread, supersHandle,
|
||||
iHClassVal, WeakVector::ElementType::WEAK);
|
||||
iHClass->SetSupers(thread, newSupers);
|
||||
}
|
||||
|
||||
// when add property in local, try maintain.
|
||||
void SubtypingOperator::TryMaintainTSSubtyping(const JSThread *thread, const JSHandle<JSHClass> &oldHClass,
|
||||
JSHandle<JSHClass> &newHClass, const JSHandle<JSTaggedValue> &key)
|
||||
{
|
||||
if (!key->IsString()) { // symbol
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(!oldHClass->IsPrototype()); // normal object hclass
|
||||
JSHandle<VTable> vtable(thread, oldHClass->GetVTable());
|
||||
ASSERT(!vtable.GetTaggedValue().IsUndefined());
|
||||
ASSERT(vtable->GetNumberOfTuples() > 0); // there have default key 'constructor' at least
|
||||
|
||||
if (vtable->Find(key.GetTaggedValue())) { // new key shadows vtable property
|
||||
LOG_ECMA(DEBUG) << "TryMaintainTSSubtyping failed, key: "
|
||||
<< ConvertToString(EcmaString::Cast(key->GetTaggedObject()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Add newHClass to phc's listeners
|
||||
JSHandle<JSTaggedValue> prototype(thread, oldHClass->GetPrototype());
|
||||
ASSERT(prototype->IsClassPrototype());
|
||||
JSHandle<JSHClass> phc(thread, prototype->GetTaggedObject()->GetClass());
|
||||
// If hclass has inherit info, it had been registered on proto chain, details and listeners must not be Undefined.
|
||||
JSHandle<ProtoChangeDetails> details(thread, phc->GetProtoChangeDetails());
|
||||
JSHandle<ChangeListener> listeners(thread, details->GetChangeListener());
|
||||
uint32_t registerIndex = 0;
|
||||
JSHandle<ChangeListener> newListeners = ChangeListener::Add(thread, listeners, newHClass, ®isterIndex);
|
||||
if (UNLIKELY(registerIndex == TaggedArray::MAX_ARRAY_INDEX)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// maintaining succeeds
|
||||
details->SetChangeListener(thread, newListeners);
|
||||
|
||||
JSHClass::CopyTSInheritInfo(thread, oldHClass, newHClass);
|
||||
}
|
||||
|
||||
// when add property on prototype, try maintain.
|
||||
bool SubtypingOperator::TryMaintainTSSubtypingOnPrototype(const JSThread *thread, const JSHandle<JSHClass> &hclass,
|
||||
const JSHandle<JSTaggedValue> &key)
|
||||
{
|
||||
ASSERT(key->IsString());
|
||||
JSHandle<VTable> vtable(thread, hclass->GetVTable());
|
||||
ASSERT(vtable->GetNumberOfTuples() > 0); // there have default key 'constructor' at least
|
||||
|
||||
if (vtable->Find(key.GetTaggedValue())) { // new key shadows vtable property
|
||||
LOG_ECMA(DEBUG) << "TryMaintainTSSubtypingOnPrototype failed, key: "
|
||||
<< ConvertToString(EcmaString::Cast(key->GetTaggedObject()));
|
||||
return false;
|
||||
}
|
||||
|
||||
int entry = JSHClass::FindPropertyEntry(thread, *hclass, key.GetTaggedValue());
|
||||
if (entry != -1) { // new key shadows loacl property
|
||||
LOG_ECMA(DEBUG) << "TryMaintainTSSubtypingOnPrototype failed, key: "
|
||||
<< ConvertToString(EcmaString::Cast(key->GetTaggedObject()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
@ -1,92 +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_SUBTYPING_OPERATOR_H
|
||||
#define ECMASCRIPT_SUBTYPING_OPERATOR_H
|
||||
|
||||
#include "ecmascript/ts_types/ts_type.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class SubtypingOperator {
|
||||
public:
|
||||
static constexpr uint32_t DEFAULT_SUPERS_CAPACITY = 4;
|
||||
|
||||
PUBLIC_API static bool CheckBaseClass(const JSThread *thread, const JSHandle<TSClassType> &classType);
|
||||
|
||||
PUBLIC_API static bool CheckSubtyping(const JSThread *thread, const JSHandle<TSClassType> &classType);
|
||||
|
||||
PUBLIC_API static void MergeClassField(const JSThread *thread, const JSHandle<TSClassType> &classType);
|
||||
|
||||
PUBLIC_API static void FillTSInheritInfo(JSThread *thread, const JSHandle<TSClassType> &classType,
|
||||
const JSHandle<JSHClass> &ihcHandle);
|
||||
|
||||
static void GenVTable(const JSThread *thread, const JSHandle<JSHClass> &ihcHandle,
|
||||
const JSHandle<JSHClass> &phcHandle, const JSHandle<JSHClass> &eIhcHandle);
|
||||
|
||||
static void TryMaintainTSSubtyping(const JSThread *thread, const JSHandle<JSHClass> &oldHClass,
|
||||
JSHandle<JSHClass> &newHClass, const JSHandle<JSTaggedValue> &key);
|
||||
|
||||
static bool TryMaintainTSSubtypingOnPrototype(const JSThread *thread, const JSHandle<JSHClass> &hclass,
|
||||
const JSHandle<JSTaggedValue> &key);
|
||||
|
||||
private:
|
||||
static constexpr uint8_t MAX_LEVEL = 1 << JSHClass::LEVEL_BTTFIELD_NUM;
|
||||
|
||||
/* rule check operations will check whether the properties in the Local and Vtable
|
||||
* of TSHClass meet the requirements for establishing a TSHClass chain.The local
|
||||
* properties refer to the properties that exists on the object instance, and the
|
||||
* vtable properties refers to the properties of its ancestor prototype objects
|
||||
* (such as accessor, method, and ordinary property in special cases)
|
||||
*
|
||||
* if B extends A
|
||||
* specific requirements are as follows (N: name, T: type):
|
||||
* 1. local_N(B) ∩ vtable_N(B) = ∅
|
||||
* 2. local(A) ⊆ local(B)
|
||||
* 3. vtable_NT(A) ⊆ vtable_NT(B)
|
||||
* 4. local_N(A) ∩ vtable_N(B) = ∅
|
||||
* 5. vtable_N(A) ∩ local_N(B) = ∅
|
||||
*/
|
||||
enum class ConditionType : uint8_t {
|
||||
NO_OVERLAP_SUB_LOCAL_SUB_VTABLE = 0,
|
||||
SUB_LOCAL_CONTAIN_SUP_LOCAL,
|
||||
SUB_VTABLE_CONTAIN_SUP_VTABLE,
|
||||
NO_OVERLAP_SUP_LOCAL_SUB_VTABLE,
|
||||
NO_OVERLAP_SUP_VTABLE_SUB_LOCAL,
|
||||
};
|
||||
|
||||
template<class T>
|
||||
static int GetElementByKey(const JSThread *thread, T *obj, JSTaggedValue key);
|
||||
|
||||
template<class T>
|
||||
static bool IsLegalElement(const JSThread *thread, T *obj, JSTaggedValue key, JSTaggedValue expectedType);
|
||||
|
||||
template<class T>
|
||||
static uint32_t GetLength(T *obj);
|
||||
|
||||
template<class T>
|
||||
static JSTaggedValue GetKey(T *obj, uint32_t index);
|
||||
|
||||
template<class T>
|
||||
static JSTaggedValue GetType(const JSThread *thread, T *obj, uint32_t index, ConditionType ConditionType);
|
||||
|
||||
template<class Suber, class Super>
|
||||
static bool SubtypingCondition(const JSThread *thread, Suber *suber, Super *super, ConditionType ConditionType);
|
||||
|
||||
static void AddSuper(const JSThread *thread, const JSHandle<JSHClass> &iHClass,
|
||||
const JSHandle<JSHClass> &extendHClass);
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
#endif // ECMASCRIPT_SUBTYPING_OPERATOR_H
|
@ -130,7 +130,6 @@
|
||||
#include "ecmascript/template_map.h"
|
||||
#include "ecmascript/tests/test_helper.h"
|
||||
#include "ecmascript/transitions_dictionary.h"
|
||||
#include "ecmascript/ts_types/ts_type.h"
|
||||
#include "ecmascript/require/js_cjs_module.h"
|
||||
#include "ecmascript/require/js_cjs_require.h"
|
||||
#include "ecmascript/require/js_cjs_exports.h"
|
||||
@ -1183,60 +1182,6 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump)
|
||||
DUMP_FOR_HANDLE(classInfoExtractor);
|
||||
break;
|
||||
}
|
||||
case JSType::TS_OBJECT_TYPE: {
|
||||
CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), TSObjectType::SIZE, 3U);
|
||||
JSHandle<TSObjectType> objectType = factory->NewTSObjectType(0);
|
||||
DUMP_FOR_HANDLE(objectType);
|
||||
break;
|
||||
}
|
||||
case JSType::TS_CLASS_TYPE: {
|
||||
CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), TSClassType::SIZE, 7U);
|
||||
JSHandle<TSClassType> classType = factory->NewTSClassType();
|
||||
DUMP_FOR_HANDLE(classType);
|
||||
break;
|
||||
}
|
||||
case JSType::TS_INTERFACE_TYPE: {
|
||||
CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), TSInterfaceType::SIZE, 4U);
|
||||
JSHandle<TSInterfaceType> interfaceType = factory->NewTSInterfaceType();
|
||||
DUMP_FOR_HANDLE(interfaceType);
|
||||
break;
|
||||
}
|
||||
case JSType::TS_CLASS_INSTANCE_TYPE: {
|
||||
CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), TSClassInstanceType::SIZE, 2U);
|
||||
JSHandle<TSClassInstanceType> classInstanceType = factory->NewTSClassInstanceType();
|
||||
DUMP_FOR_HANDLE(classInstanceType);
|
||||
break;
|
||||
}
|
||||
case JSType::TS_UNION_TYPE: {
|
||||
CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), TSUnionType::SIZE, 2U);
|
||||
JSHandle<TSUnionType> unionType = factory->NewTSUnionType(1);
|
||||
DUMP_FOR_HANDLE(unionType);
|
||||
break;
|
||||
}
|
||||
case JSType::TS_FUNCTION_TYPE: {
|
||||
CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), TSFunctionType::SIZE, 5U);
|
||||
JSHandle<TSFunctionType> functionType = factory->NewTSFunctionType(1);
|
||||
DUMP_FOR_HANDLE(functionType);
|
||||
break;
|
||||
}
|
||||
case JSType::TS_ARRAY_TYPE: {
|
||||
CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), TSArrayType::SIZE, 2U);
|
||||
JSHandle<TSArrayType> arrayType = factory->NewTSArrayType();
|
||||
DUMP_FOR_HANDLE(arrayType);
|
||||
break;
|
||||
}
|
||||
case JSType::TS_ITERATOR_INSTANCE_TYPE: {
|
||||
CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), TSIteratorInstanceType::SIZE, 2U);
|
||||
JSHandle<TSIteratorInstanceType> iteratorInstanceType = factory->NewTSIteratorInstanceType();
|
||||
DUMP_FOR_HANDLE(iteratorInstanceType);
|
||||
break;
|
||||
}
|
||||
case JSType::TS_NAMESPACE_TYPE: {
|
||||
CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), TSNamespaceType::SIZE, 2U);
|
||||
JSHandle<TSNamespaceType> namespaceType = factory->NewTSNamespaceType();
|
||||
DUMP_FOR_HANDLE(namespaceType);
|
||||
break;
|
||||
}
|
||||
case JSType::JS_API_ARRAY_LIST: {
|
||||
// 1 : 1 dump fileds number
|
||||
CHECK_DUMP_FIELDS(JSObject::SIZE, JSAPIArrayList::SIZE, 1U);
|
||||
|
@ -1,63 +0,0 @@
|
||||
# Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//arkcompiler/ets_runtime/js_runtime_config.gni")
|
||||
import("//arkcompiler/ets_runtime/test/test_helper.gni")
|
||||
|
||||
module_output_path = "arkcompiler/ets_runtime"
|
||||
|
||||
host_unittest_action("TSTypeTest") {
|
||||
module_out_path = module_output_path
|
||||
|
||||
sources = [
|
||||
# test file
|
||||
"ts_type_parser_test.cpp",
|
||||
"ts_type_table_generator_test.cpp",
|
||||
]
|
||||
|
||||
configs = [
|
||||
"//arkcompiler/ets_runtime:ecma_test_config",
|
||||
"$ark_root/assembler:arkassembler_public_config",
|
||||
"$ark_root/libpandafile:arkfile_public_config",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"$ark_third_party_root/icu/icu4c:shared_icui18n",
|
||||
"$ark_third_party_root/icu/icu4c:shared_icuuc",
|
||||
"//arkcompiler/ets_runtime:libark_jsruntime_test",
|
||||
"//arkcompiler/runtime_core/assembler:libarkassembler_static",
|
||||
sdk_libc_secshared_dep,
|
||||
]
|
||||
|
||||
# hiviewdfx libraries
|
||||
external_deps = hiviewdfx_ext_deps
|
||||
deps += hiviewdfx_deps
|
||||
}
|
||||
|
||||
group("unittest") {
|
||||
testonly = true
|
||||
|
||||
# deps file
|
||||
deps = [ ":TSTypeTest" ]
|
||||
}
|
||||
|
||||
group("host_unittest") {
|
||||
testonly = true
|
||||
|
||||
# deps file
|
||||
deps = [ ":TSTypeTestAction" ]
|
||||
|
||||
if (is_mac) {
|
||||
deps -= [ ":TSTypeTestAction" ]
|
||||
}
|
||||
}
|
@ -1,428 +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.
|
||||
*/
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/jspandafile/js_pandafile_manager.h"
|
||||
#include "ecmascript/ts_types/tests/ts_type_test_helper.h"
|
||||
#include "ecmascript/ts_types/ts_type_parser.h"
|
||||
|
||||
namespace panda::test {
|
||||
using namespace panda::ecmascript;
|
||||
using namespace panda::panda_file;
|
||||
using namespace panda::pandasm;
|
||||
using LiteralValueType = std::variant<uint8_t, uint32_t, std::string>;
|
||||
|
||||
static constexpr uint16_t FIRST_USER_DEFINE_MODULE_ID = static_cast<uint32_t>(ModuleTableIdx::NUM_OF_DEFAULT_TABLES);
|
||||
static constexpr uint16_t FIRST_USER_DEFINE_LOCAL_ID = 1;
|
||||
|
||||
class TSTypeParserTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "SetUpTestCase";
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "TearDownCase";
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
TestHelper::CreateEcmaVMWithScope(ecmaVm, thread, scope);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
TestHelper::DestroyEcmaVMWithScope(ecmaVm, scope);
|
||||
}
|
||||
|
||||
EcmaVM *ecmaVm {nullptr};
|
||||
EcmaHandleScope *scope {nullptr};
|
||||
JSThread *thread {nullptr};
|
||||
};
|
||||
|
||||
HWTEST_F_L0(TSTypeParserTest, TestPrimetiveType)
|
||||
{
|
||||
auto tsManager = ecmaVm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager();
|
||||
tsManager->Initialize();
|
||||
TSTypeParser tsTypeParser(tsManager);
|
||||
JSPandaFile *jsPandaFile = nullptr;
|
||||
const CString recordName("");
|
||||
uint32_t primetiveTypeId = 0U;
|
||||
GlobalTSTypeRef resultGT = tsTypeParser.CreateGT(jsPandaFile, recordName, primetiveTypeId);
|
||||
EXPECT_EQ(resultGT, GlobalTSTypeRef(static_cast<uint32_t>(ModuleTableIdx::PRIMITIVE), primetiveTypeId));
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TSTypeParserTest, TestBuiltinType)
|
||||
{
|
||||
auto tsManager = ecmaVm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager();
|
||||
tsManager->Initialize();
|
||||
TSTypeParser tsTypeParser(tsManager);
|
||||
JSPandaFile *jsPandaFile = nullptr;
|
||||
const CString recordName("");
|
||||
uint32_t builtinTypeId = 50U;
|
||||
GlobalTSTypeRef builtinGT = tsTypeParser.CreateGT(jsPandaFile, recordName, builtinTypeId);
|
||||
EXPECT_EQ(builtinGT, GlobalTSTypeRef(static_cast<uint32_t>(ModuleTableIdx::BUILTIN), builtinTypeId));
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TSTypeParserTest, TestTSClassType)
|
||||
{
|
||||
const char *source = R"(
|
||||
.language ECMAScript
|
||||
.record test {}
|
||||
.function void foo() {}
|
||||
)";
|
||||
pandasm::Parser parser;
|
||||
auto res = parser.Parse(source);
|
||||
EXPECT_EQ(parser.ShowError().err, Error::ErrorType::ERR_NONE);
|
||||
auto &program = res.Value();
|
||||
|
||||
const std::string classId("test_1");
|
||||
const std::string valueStr("value");
|
||||
std::vector<panda_file::LiteralTag> classTags { panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::BUILTINTYPEINDEX,
|
||||
panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::STRING,
|
||||
panda_file::LiteralTag::BUILTINTYPEINDEX,
|
||||
panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::INTEGER };
|
||||
std::vector<LiteralValueType> classValues { static_cast<uint32_t>(1),
|
||||
static_cast<uint32_t>(0),
|
||||
static_cast<uint8_t>(0),
|
||||
static_cast<uint32_t>(0),
|
||||
static_cast<uint32_t>(0),
|
||||
static_cast<uint32_t>(0),
|
||||
static_cast<uint32_t>(1),
|
||||
valueStr,
|
||||
static_cast<uint8_t>(1),
|
||||
static_cast<uint32_t>(0),
|
||||
static_cast<uint32_t>(0),
|
||||
static_cast<uint32_t>(0) };
|
||||
TSTypeTestHelper::AddLiteral(program, classId, classTags, classValues);
|
||||
|
||||
const std::string abcFileName("TSClassTypeTest.abc");
|
||||
TSTypeTestHelper::AddTypeSummary(program, { classId });
|
||||
TSTypeTestHelper::AddCommonJsField(program);
|
||||
std::map<std::string, size_t> *statp = nullptr;
|
||||
pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {};
|
||||
pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = &maps;
|
||||
EXPECT_TRUE(pandasm::AsmEmitter::Emit(abcFileName, program, statp, mapsp, false));
|
||||
std::unique_ptr<const panda_file::File> pfPtr = panda_file::File::Open(abcFileName);
|
||||
EXPECT_NE(pfPtr.get(), nullptr);
|
||||
|
||||
Span<const uint32_t> literalArrays = pfPtr.get()->GetLiteralArrays();
|
||||
EXPECT_TRUE(literalArrays.size() >= 2);
|
||||
// typeIds in order from largest to smallest and the last one is typeSummary literal
|
||||
uint32_t testTypeIndex = literalArrays.size() - 2;
|
||||
uint32_t testTypeOffset = literalArrays[testTypeIndex];
|
||||
|
||||
JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
|
||||
const CString fileName(abcFileName.c_str());
|
||||
const auto jsPandaFile = pfManager->NewJSPandaFile(pfPtr.release(), fileName);
|
||||
EXPECT_NE(jsPandaFile, nullptr);
|
||||
|
||||
auto tsManager = ecmaVm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager();
|
||||
tsManager->Initialize();
|
||||
TSTypeParser tsTypeParser(tsManager);
|
||||
const CString recordName("test");
|
||||
GlobalTSTypeRef resultGT = tsTypeParser.CreateGT(jsPandaFile.get(), recordName, testTypeOffset);
|
||||
EXPECT_EQ(resultGT, GlobalTSTypeRef(FIRST_USER_DEFINE_MODULE_ID, FIRST_USER_DEFINE_LOCAL_ID));
|
||||
EXPECT_TRUE(tsManager->IsClassTypeKind(resultGT));
|
||||
JSHandle<JSTaggedValue> type = tsManager->GetTSType(resultGT);
|
||||
EXPECT_TRUE(type->IsTSClassType());
|
||||
|
||||
JSHandle<TSClassType> classType(type);
|
||||
EXPECT_EQ(resultGT, classType->GetGT());
|
||||
auto factory = ecmaVm->GetFactory();
|
||||
JSHandle<JSTaggedValue> propertyName(factory->NewFromStdString(valueStr));
|
||||
GlobalTSTypeRef propGT = TSClassType::GetPropTypeGT(thread, classType, propertyName);
|
||||
EXPECT_EQ(propGT, GlobalTSTypeRef(static_cast<uint32_t>(ModuleTableIdx::PRIMITIVE),
|
||||
static_cast<uint32_t>(TSPrimitiveType::NUMBER)));
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TSTypeParserTest, TestTSFunctionType)
|
||||
{
|
||||
const char *source = R"(
|
||||
.language ECMAScript
|
||||
.record test {}
|
||||
.function void foo() {}
|
||||
)";
|
||||
pandasm::Parser parser;
|
||||
auto res = parser.Parse(source);
|
||||
EXPECT_EQ(parser.ShowError().err, Error::ErrorType::ERR_NONE);
|
||||
auto &program = res.Value();
|
||||
|
||||
const std::string functionId("test_1");
|
||||
const std::string functionName("foo");
|
||||
const uint32_t numOfParas = 2;
|
||||
std::vector<panda_file::LiteralTag> functionTags { panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::STRING,
|
||||
panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::BUILTINTYPEINDEX,
|
||||
panda_file::LiteralTag::BUILTINTYPEINDEX,
|
||||
panda_file::LiteralTag::BUILTINTYPEINDEX };
|
||||
std::vector<LiteralValueType> functionValues { static_cast<uint32_t>(3),
|
||||
static_cast<uint32_t>(0),
|
||||
functionName,
|
||||
static_cast<uint32_t>(0),
|
||||
numOfParas,
|
||||
static_cast<uint8_t>(1),
|
||||
static_cast<uint8_t>(4),
|
||||
static_cast<uint8_t>(2) };
|
||||
TSTypeTestHelper::AddLiteral(program, functionId, functionTags, functionValues);
|
||||
|
||||
const std::string abcFileName("TSFunctionTypeTest.abc");
|
||||
TSTypeTestHelper::AddTypeSummary(program, { functionId });
|
||||
TSTypeTestHelper::AddCommonJsField(program);
|
||||
std::map<std::string, size_t> *statp = nullptr;
|
||||
pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {};
|
||||
pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = &maps;
|
||||
EXPECT_TRUE(pandasm::AsmEmitter::Emit(abcFileName, program, statp, mapsp, false));
|
||||
std::unique_ptr<const panda_file::File> pfPtr = panda_file::File::Open(abcFileName);
|
||||
EXPECT_NE(pfPtr.get(), nullptr);
|
||||
|
||||
Span<const uint32_t> literalArrays = pfPtr.get()->GetLiteralArrays();
|
||||
EXPECT_TRUE(literalArrays.size() >= 2);
|
||||
// typeIds in order from largest to smallest and the last one is typeSummary literal
|
||||
uint32_t testTypeIndex = literalArrays.size() - 2;
|
||||
uint32_t testTypeOffset = literalArrays[testTypeIndex];
|
||||
|
||||
JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
|
||||
const CString fileName(abcFileName.c_str());
|
||||
const auto jsPandaFile = pfManager->NewJSPandaFile(pfPtr.release(), fileName);
|
||||
EXPECT_NE(jsPandaFile, nullptr);
|
||||
|
||||
auto tsManager = ecmaVm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager();
|
||||
tsManager->Initialize();
|
||||
TSTypeParser tsTypeParser(tsManager);
|
||||
const CString recordName("test");
|
||||
GlobalTSTypeRef resultGT = tsTypeParser.CreateGT(jsPandaFile.get(), recordName, testTypeOffset);
|
||||
EXPECT_EQ(resultGT, GlobalTSTypeRef(FIRST_USER_DEFINE_MODULE_ID, FIRST_USER_DEFINE_LOCAL_ID));
|
||||
EXPECT_TRUE(tsManager->IsFunctionTypeKind(resultGT));
|
||||
JSHandle<JSTaggedValue> type = tsManager->GetTSType(resultGT);
|
||||
EXPECT_TRUE(type->IsTSFunctionType());
|
||||
|
||||
JSHandle<TSFunctionType> functionType(type);
|
||||
EXPECT_EQ(resultGT, functionType->GetGT());
|
||||
EXPECT_EQ(functionType->GetLength(), numOfParas);
|
||||
EXPECT_EQ(functionType->GetParameterTypeGT(0), GlobalTSTypeRef(static_cast<uint32_t>(ModuleTableIdx::PRIMITIVE),
|
||||
static_cast<uint32_t>(TSPrimitiveType::NUMBER)));
|
||||
EXPECT_EQ(functionType->GetParameterTypeGT(1), GlobalTSTypeRef(static_cast<uint32_t>(ModuleTableIdx::PRIMITIVE),
|
||||
static_cast<uint32_t>(TSPrimitiveType::STRING)));
|
||||
EXPECT_EQ(functionType->GetReturnGT(), GlobalTSTypeRef(static_cast<uint32_t>(ModuleTableIdx::PRIMITIVE),
|
||||
static_cast<uint32_t>(TSPrimitiveType::BOOLEAN)));
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TSTypeParserTest, TestTSUnionType)
|
||||
{
|
||||
const char *source = R"(
|
||||
.language ECMAScript
|
||||
.record test {}
|
||||
.function void foo() {}
|
||||
)";
|
||||
pandasm::Parser parser;
|
||||
auto res = parser.Parse(source);
|
||||
EXPECT_EQ(parser.ShowError().err, Error::ErrorType::ERR_NONE);
|
||||
auto &program = res.Value();
|
||||
|
||||
const std::string unionId("test_1");
|
||||
const uint32_t numOfTypes = 2;
|
||||
std::vector<panda_file::LiteralTag> unionTags { panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::BUILTINTYPEINDEX,
|
||||
panda_file::LiteralTag::BUILTINTYPEINDEX };
|
||||
std::vector<LiteralValueType> unionValues { static_cast<uint32_t>(4),
|
||||
numOfTypes,
|
||||
static_cast<uint8_t>(1),
|
||||
static_cast<uint8_t>(4) };
|
||||
TSTypeTestHelper::AddLiteral(program, unionId, unionTags, unionValues);
|
||||
|
||||
const std::string abcFileName("TSUnionTypeTest.abc");
|
||||
TSTypeTestHelper::AddTypeSummary(program, { unionId });
|
||||
TSTypeTestHelper::AddCommonJsField(program);
|
||||
std::map<std::string, size_t> *statp = nullptr;
|
||||
pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {};
|
||||
pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = &maps;
|
||||
EXPECT_TRUE(pandasm::AsmEmitter::Emit(abcFileName, program, statp, mapsp, false));
|
||||
std::unique_ptr<const panda_file::File> pfPtr = panda_file::File::Open(abcFileName);
|
||||
EXPECT_NE(pfPtr.get(), nullptr);
|
||||
|
||||
Span<const uint32_t> literalArrays = pfPtr.get()->GetLiteralArrays();
|
||||
EXPECT_TRUE(literalArrays.size() >= 2);
|
||||
// typeIds in order from largest to smallest and the last one is typeSummary literal
|
||||
uint32_t testTypeIndex = literalArrays.size() - 2;
|
||||
uint32_t testTypeOffset = literalArrays[testTypeIndex];
|
||||
|
||||
JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
|
||||
const CString fileName(abcFileName.c_str());
|
||||
const auto jsPandaFile = pfManager->NewJSPandaFile(pfPtr.release(), fileName);
|
||||
EXPECT_NE(jsPandaFile, nullptr);
|
||||
|
||||
auto tsManager = ecmaVm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager();
|
||||
tsManager->Initialize();
|
||||
TSTypeParser tsTypeParser(tsManager);
|
||||
const CString recordName("test");
|
||||
GlobalTSTypeRef resultGT = tsTypeParser.CreateGT(jsPandaFile.get(), recordName, testTypeOffset);
|
||||
EXPECT_EQ(resultGT, GlobalTSTypeRef(FIRST_USER_DEFINE_MODULE_ID, FIRST_USER_DEFINE_LOCAL_ID));
|
||||
EXPECT_TRUE(tsManager->IsUnionTypeKind(resultGT));
|
||||
JSHandle<JSTaggedValue> type = tsManager->GetTSType(resultGT);
|
||||
EXPECT_TRUE(type->IsTSUnionType());
|
||||
|
||||
JSHandle<TSUnionType> unionType(type);
|
||||
EXPECT_EQ(resultGT, unionType->GetGT());
|
||||
EXPECT_EQ(tsManager->GetUnionTypeLength(resultGT), numOfTypes);
|
||||
EXPECT_EQ(tsManager->GetUnionTypeByIndex(resultGT, 0),
|
||||
GlobalTSTypeRef(static_cast<uint32_t>(ModuleTableIdx::PRIMITIVE),
|
||||
static_cast<uint32_t>(TSPrimitiveType::NUMBER)));
|
||||
EXPECT_EQ(tsManager->GetUnionTypeByIndex(resultGT, 1),
|
||||
GlobalTSTypeRef(static_cast<uint32_t>(ModuleTableIdx::PRIMITIVE),
|
||||
static_cast<uint32_t>(TSPrimitiveType::STRING)));
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TSTypeParserTest, TestTSArrayType)
|
||||
{
|
||||
const char *source = R"(
|
||||
.language ECMAScript
|
||||
.record test {}
|
||||
.function void foo() {}
|
||||
)";
|
||||
pandasm::Parser parser;
|
||||
auto res = parser.Parse(source);
|
||||
EXPECT_EQ(parser.ShowError().err, Error::ErrorType::ERR_NONE);
|
||||
auto &program = res.Value();
|
||||
|
||||
const std::string arrayId("test_1");
|
||||
std::vector<panda_file::LiteralTag> arrayTags { panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::BUILTINTYPEINDEX };
|
||||
std::vector<LiteralValueType> arrayValues { static_cast<uint32_t>(5),
|
||||
static_cast<uint8_t>(1) };
|
||||
TSTypeTestHelper::AddLiteral(program, arrayId, arrayTags, arrayValues);
|
||||
|
||||
const std::string abcFileName("TSArrayTypeTest.abc");
|
||||
TSTypeTestHelper::AddTypeSummary(program, { arrayId });
|
||||
TSTypeTestHelper::AddCommonJsField(program);
|
||||
std::map<std::string, size_t> *statp = nullptr;
|
||||
pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {};
|
||||
pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = &maps;
|
||||
EXPECT_TRUE(pandasm::AsmEmitter::Emit(abcFileName, program, statp, mapsp, false));
|
||||
std::unique_ptr<const panda_file::File> pfPtr = panda_file::File::Open(abcFileName);
|
||||
EXPECT_NE(pfPtr.get(), nullptr);
|
||||
|
||||
Span<const uint32_t> literalArrays = pfPtr.get()->GetLiteralArrays();
|
||||
EXPECT_TRUE(literalArrays.size() >= 2);
|
||||
// typeIds in order from largest to smallest and the last one is typeSummary literal
|
||||
uint32_t testTypeIndex = literalArrays.size() - 2;
|
||||
uint32_t testTypeOffset = literalArrays[testTypeIndex];
|
||||
|
||||
JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
|
||||
const CString fileName(abcFileName.c_str());
|
||||
const auto jsPandaFile = pfManager->NewJSPandaFile(pfPtr.release(), fileName);
|
||||
EXPECT_NE(jsPandaFile, nullptr);
|
||||
|
||||
auto tsManager = ecmaVm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager();
|
||||
tsManager->Initialize();
|
||||
TSTypeParser tsTypeParser(tsManager);
|
||||
const CString recordName("test");
|
||||
GlobalTSTypeRef resultGT = tsTypeParser.CreateGT(jsPandaFile.get(), recordName, testTypeOffset);
|
||||
EXPECT_EQ(resultGT, GlobalTSTypeRef(FIRST_USER_DEFINE_MODULE_ID, FIRST_USER_DEFINE_LOCAL_ID));
|
||||
EXPECT_TRUE(tsManager->IsArrayTypeKind(resultGT));
|
||||
JSHandle<JSTaggedValue> type = tsManager->GetTSType(resultGT);
|
||||
EXPECT_TRUE(type->IsTSArrayType());
|
||||
|
||||
JSHandle<TSArrayType> arrayType(type);
|
||||
EXPECT_EQ(resultGT, arrayType->GetGT());
|
||||
EXPECT_EQ(arrayType->GetElementGT(), GlobalTSTypeRef(static_cast<uint32_t>(ModuleTableIdx::PRIMITIVE),
|
||||
static_cast<uint32_t>(TSPrimitiveType::NUMBER)));
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TSTypeParserTest, TestTSObjectType)
|
||||
{
|
||||
const char *source = R"(
|
||||
.language ECMAScript
|
||||
.record test {}
|
||||
.function void foo() {}
|
||||
)";
|
||||
pandasm::Parser parser;
|
||||
auto res = parser.Parse(source);
|
||||
EXPECT_EQ(parser.ShowError().err, Error::ErrorType::ERR_NONE);
|
||||
auto &program = res.Value();
|
||||
|
||||
const std::string objectId("test_1");
|
||||
const std::string ageStr("age");
|
||||
const std::string funStr("fun");
|
||||
std::vector<panda_file::LiteralTag> objectTags { panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::INTEGER,
|
||||
panda_file::LiteralTag::STRING,
|
||||
panda_file::LiteralTag::BUILTINTYPEINDEX,
|
||||
panda_file::LiteralTag::STRING,
|
||||
panda_file::LiteralTag::BUILTINTYPEINDEX };
|
||||
std::vector<LiteralValueType> objectValues { static_cast<uint32_t>(6),
|
||||
static_cast<uint32_t>(2),
|
||||
ageStr,
|
||||
static_cast<uint8_t>(1),
|
||||
funStr,
|
||||
static_cast<uint8_t>(1) };
|
||||
TSTypeTestHelper::AddLiteral(program, objectId, objectTags, objectValues);
|
||||
|
||||
const std::string abcFileName("TSObjectTypeTest.abc");
|
||||
TSTypeTestHelper::AddTypeSummary(program, { objectId });
|
||||
TSTypeTestHelper::AddCommonJsField(program);
|
||||
std::map<std::string, size_t> *statp = nullptr;
|
||||
pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {};
|
||||
pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = &maps;
|
||||
EXPECT_TRUE(pandasm::AsmEmitter::Emit(abcFileName, program, statp, mapsp, false));
|
||||
std::unique_ptr<const panda_file::File> pfPtr = panda_file::File::Open(abcFileName);
|
||||
EXPECT_NE(pfPtr.get(), nullptr);
|
||||
|
||||
Span<const uint32_t> literalArrays = pfPtr.get()->GetLiteralArrays();
|
||||
EXPECT_TRUE(literalArrays.size() >= 2);
|
||||
// typeIds in order from largest to smallest and the last one is typeSummary literal
|
||||
uint32_t testTypeIndex = literalArrays.size() - 2;
|
||||
uint32_t testTypeOffset = literalArrays[testTypeIndex];
|
||||
|
||||
JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
|
||||
const CString fileName(abcFileName.c_str());
|
||||
const auto jsPandaFile = pfManager->NewJSPandaFile(pfPtr.release(), fileName);
|
||||
EXPECT_NE(jsPandaFile, nullptr);
|
||||
|
||||
auto tsManager = ecmaVm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager();
|
||||
tsManager->Initialize();
|
||||
TSTypeParser tsTypeParser(tsManager);
|
||||
const CString recordName("test");
|
||||
GlobalTSTypeRef resultGT = tsTypeParser.CreateGT(jsPandaFile.get(), recordName, testTypeOffset);
|
||||
EXPECT_EQ(resultGT, GlobalTSTypeRef(FIRST_USER_DEFINE_MODULE_ID, FIRST_USER_DEFINE_LOCAL_ID));
|
||||
EXPECT_TRUE(tsManager->IsObjectTypeKind(resultGT));
|
||||
JSHandle<JSTaggedValue> type = tsManager->GetTSType(resultGT);
|
||||
EXPECT_TRUE(type->IsTSObjectType());
|
||||
|
||||
JSHandle<TSObjectType> objectType(type);
|
||||
EXPECT_EQ(resultGT, objectType->GetGT());
|
||||
auto factory = ecmaVm->GetFactory();
|
||||
JSHandle<JSTaggedValue> propName(factory->NewFromStdString(ageStr));
|
||||
GlobalTSTypeRef propGT = TSObjectType::GetPropTypeGT(thread, objectType, propName);
|
||||
EXPECT_EQ(propGT, GlobalTSTypeRef(static_cast<uint32_t>(ModuleTableIdx::PRIMITIVE),
|
||||
static_cast<uint32_t>(TSPrimitiveType::NUMBER)));
|
||||
}
|
||||
} // namespace panda::test
|
@ -1,122 +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 <thread>
|
||||
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/jspandafile/js_pandafile_manager.h"
|
||||
#include "ecmascript/ts_types/tests/ts_type_test_helper.h"
|
||||
#include "ecmascript/ts_types/ts_type_table_generator.h"
|
||||
|
||||
namespace panda::test {
|
||||
using namespace panda::ecmascript;
|
||||
using namespace panda::panda_file;
|
||||
using namespace panda::pandasm;
|
||||
|
||||
static constexpr uint16_t FIRST_USER_DEFINE_MODULE_ID = static_cast<uint32_t>(ModuleTableIdx::NUM_OF_DEFAULT_TABLES);
|
||||
|
||||
class TSTypeTableGeneratorTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "SetUpTestCase";
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "TearDownCase";
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
TestHelper::CreateEcmaVMWithScope(ecmaVm, thread, scope);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
TestHelper::DestroyEcmaVMWithScope(ecmaVm, scope);
|
||||
}
|
||||
|
||||
EcmaVM *ecmaVm {nullptr};
|
||||
EcmaHandleScope *scope {nullptr};
|
||||
JSThread *thread {nullptr};
|
||||
};
|
||||
|
||||
HWTEST_F_L0(TSTypeTableGeneratorTest, TestTryGetModuleId)
|
||||
{
|
||||
const auto *abcName = TSTypeTable::DEFAULT_TYPE_VIRTUAL_NAME;
|
||||
auto *tsManager = ecmaVm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager();
|
||||
tsManager->Initialize();
|
||||
TSTypeTableGenerator tableGenerator(tsManager);
|
||||
uint32_t primitiveTableId = tableGenerator.TryGetModuleId(abcName, TSTypeTable::PRIMITIVE_TABLE_NAME);
|
||||
uint32_t builtinTableId = tableGenerator.TryGetModuleId(abcName, TSTypeTable::BUILTINS_TABLE_NAME);
|
||||
uint32_t inferTableId = tableGenerator.TryGetModuleId(abcName, TSTypeTable::INFER_TABLE_NAME);
|
||||
uint32_t runtimeTableId = tableGenerator.TryGetModuleId(abcName, TSTypeTable::RUNTIME_TABLE_NAME);
|
||||
uint32_t genericsTableId = tableGenerator.TryGetModuleId(abcName, TSTypeTable::GENERICS_TABLE_NAME);
|
||||
uint32_t firstUserModuleId = tableGenerator.TryGetModuleId(abcName, "test");
|
||||
EXPECT_EQ(primitiveTableId, static_cast<uint32_t>(ModuleTableIdx::PRIMITIVE));
|
||||
EXPECT_EQ(builtinTableId, static_cast<uint32_t>(ModuleTableIdx::BUILTIN));
|
||||
EXPECT_EQ(inferTableId, static_cast<uint32_t>(ModuleTableIdx::INFERRED));
|
||||
EXPECT_EQ(runtimeTableId, static_cast<uint32_t>(ModuleTableIdx::RUNTIME));
|
||||
EXPECT_EQ(genericsTableId, static_cast<uint32_t>(ModuleTableIdx::GENERICS));
|
||||
EXPECT_EQ(firstUserModuleId, FIRST_USER_DEFINE_MODULE_ID);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TSTypeTableGeneratorTest, TestTryGetLocalId)
|
||||
{
|
||||
auto tsManager = ecmaVm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager();
|
||||
tsManager->Initialize();
|
||||
TSTypeTableGenerator tableGenerator(tsManager);
|
||||
JSHandle<TSTypeTable> table = ecmaVm->GetFactory()->NewTSTypeTable(0);
|
||||
table->SetNumberOfTypes(ecmaVm->GetJSThread());
|
||||
uint32_t localId = tableGenerator.TryGetLocalId(table);
|
||||
EXPECT_EQ(localId, 1U);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TSTypeTableGeneratorTest, GetOrGenerateTSTypeTable)
|
||||
{
|
||||
const char *source = R"(
|
||||
.language ECMAScript
|
||||
.record test {}
|
||||
.function void foo() {}
|
||||
)";
|
||||
pandasm::Parser parser;
|
||||
auto res = parser.Parse(source);
|
||||
EXPECT_EQ(parser.ShowError().err, Error::ErrorType::ERR_NONE);
|
||||
auto &program = res.Value();
|
||||
|
||||
const std::string abcFileName("TSTypeTableTest.abc");
|
||||
TSTypeTestHelper::AddTypeSummary(program, {});
|
||||
TSTypeTestHelper::AddCommonJsField(program);
|
||||
std::map<std::string, size_t> *statp = nullptr;
|
||||
pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {};
|
||||
pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = &maps;
|
||||
EXPECT_TRUE(pandasm::AsmEmitter::Emit(abcFileName, program, statp, mapsp, false));
|
||||
std::unique_ptr<const panda_file::File> pfPtr = panda_file::File::Open(abcFileName);
|
||||
EXPECT_NE(pfPtr.get(), nullptr);
|
||||
|
||||
JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
|
||||
const CString fileName(abcFileName.c_str());
|
||||
std::shared_ptr<JSPandaFile> jsPandaFile = pfManager->NewJSPandaFile(pfPtr.release(), fileName);
|
||||
EXPECT_NE(jsPandaFile, nullptr);
|
||||
|
||||
auto tsManager = ecmaVm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager();
|
||||
tsManager->Initialize();
|
||||
TSTypeTableGenerator tableGenerator(tsManager);
|
||||
[[maybe_unused]] JSHandle<TSTypeTable> table =
|
||||
tableGenerator.GetOrGenerateTSTypeTable(jsPandaFile.get(), "test", 0U);
|
||||
ASSERT(table->GetNumberOfTypes() == 0U);
|
||||
}
|
||||
} // namespace panda::test
|
@ -1,132 +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_TS_TYPES_TESTS_TS_TYPE_TEST_HELPER_H
|
||||
#define ECMASCRIPT_TS_TYPES_TESTS_TS_TYPE_TEST_HELPER_H
|
||||
|
||||
#include "assembler/assembly-parser.h"
|
||||
#include "ecmascript/tests/test_helper.h"
|
||||
|
||||
namespace panda::test {
|
||||
using namespace panda::ecmascript;
|
||||
using namespace panda::panda_file;
|
||||
using namespace panda::pandasm;
|
||||
using LiteralValueType = std::variant<uint8_t, uint32_t, std::string>;
|
||||
|
||||
class TSTypeTestHelper {
|
||||
public:
|
||||
static void AddLiteral(pandasm::Program &program, const std::string &literalId,
|
||||
const std::vector<panda_file::LiteralTag> &tags,
|
||||
const std::vector<LiteralValueType> &values)
|
||||
{
|
||||
EXPECT_EQ(tags.size(), values.size());
|
||||
std::vector<pandasm::LiteralArray::Literal> literal {};
|
||||
for (uint32_t i = 0; i < tags.size(); i++) {
|
||||
AddTagValue(literal, tags[i], values[i]);
|
||||
}
|
||||
pandasm::LiteralArray literalArray(literal);
|
||||
program.literalarray_table.emplace(literalId, literalArray);
|
||||
}
|
||||
|
||||
static void AddTypeSummary(pandasm::Program &program, const std::vector<std::string> &typeIds)
|
||||
{
|
||||
const std::string typeSummaryId("test_0");
|
||||
AddSummaryLiteral(program, typeSummaryId, typeIds);
|
||||
|
||||
const std::string testStr("test");
|
||||
auto iter = program.record_table.find(testStr);
|
||||
EXPECT_NE(iter, program.record_table.end());
|
||||
if (iter != program.record_table.end()) {
|
||||
auto &rec = iter->second;
|
||||
auto typeSummaryIndexField = pandasm::Field(pandasm::extensions::Language::ECMASCRIPT);
|
||||
typeSummaryIndexField.name = "typeSummaryOffset";
|
||||
typeSummaryIndexField.type = pandasm::Type("u32", 0);
|
||||
typeSummaryIndexField.metadata->SetValue(
|
||||
pandasm::ScalarValue::Create<pandasm::Value::Type::LITERALARRAY>(typeSummaryId));
|
||||
rec.field_list.emplace_back(std::move(typeSummaryIndexField));
|
||||
}
|
||||
}
|
||||
|
||||
static void AddCommonJsField(pandasm::Program &program)
|
||||
{
|
||||
const std::string testStr("test");
|
||||
auto iter = program.record_table.find(testStr);
|
||||
EXPECT_NE(iter, program.record_table.end());
|
||||
if (iter != program.record_table.end()) {
|
||||
auto &rec = iter->second;
|
||||
auto isCommonJsField = pandasm::Field(pandasm::extensions::Language::ECMASCRIPT);
|
||||
isCommonJsField.name = "isCommonjs";
|
||||
isCommonJsField.type = pandasm::Type("u8", 0);
|
||||
isCommonJsField.metadata->SetValue(
|
||||
pandasm::ScalarValue::Create<pandasm::Value::Type::U8>(static_cast<uint8_t>(false)));
|
||||
rec.field_list.emplace_back(std::move(isCommonJsField));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static void AddTagValue(std::vector<LiteralArray::Literal> &literalArray,
|
||||
const panda_file::LiteralTag tag,
|
||||
const LiteralValueType &value)
|
||||
{
|
||||
pandasm::LiteralArray::Literal literalTag;
|
||||
literalTag.tag_ = panda_file::LiteralTag::TAGVALUE;
|
||||
literalTag.value_ = static_cast<uint8_t>(tag);
|
||||
literalArray.emplace_back(std::move(literalTag));
|
||||
|
||||
pandasm::LiteralArray::Literal literalValue;
|
||||
literalValue.tag_ = tag;
|
||||
|
||||
switch (tag) {
|
||||
case panda_file::LiteralTag::INTEGER: {
|
||||
literalValue.value_ = std::get<uint32_t>(value);
|
||||
break;
|
||||
}
|
||||
case panda_file::LiteralTag::BUILTINTYPEINDEX: {
|
||||
literalValue.value_ = std::get<uint8_t>(value);
|
||||
break;
|
||||
}
|
||||
case panda_file::LiteralTag::STRING: {
|
||||
literalValue.value_ = std::get<std::string>(value);
|
||||
break;
|
||||
}
|
||||
case panda_file::LiteralTag::LITERALARRAY: {
|
||||
literalValue.value_ = std::get<std::string>(value);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
EXPECT_FALSE(true);
|
||||
}
|
||||
}
|
||||
|
||||
literalArray.emplace_back(std::move(literalValue));
|
||||
}
|
||||
|
||||
static void AddSummaryLiteral(pandasm::Program &program, const std::string &typeSummaryId,
|
||||
const std::vector<std::string> &typeIds)
|
||||
{
|
||||
uint32_t numOfTypes = typeIds.size();
|
||||
std::vector<panda_file::LiteralTag> typeSummaryTags { panda_file::LiteralTag::INTEGER };
|
||||
std::vector<LiteralValueType> typeSummaryValues { numOfTypes };
|
||||
for (uint32_t i = 0; i < numOfTypes; i++) {
|
||||
typeSummaryTags.emplace_back(panda_file::LiteralTag::LITERALARRAY);
|
||||
typeSummaryValues.emplace_back(typeIds[i]);
|
||||
}
|
||||
typeSummaryTags.emplace_back(panda_file::LiteralTag::INTEGER);
|
||||
typeSummaryValues.emplace_back(static_cast<uint32_t>(0U));
|
||||
AddLiteral(program, typeSummaryId, typeSummaryTags, typeSummaryValues);
|
||||
}
|
||||
};
|
||||
} // namespace panda::test
|
||||
#endif // ECMASCRIPT_TS_TYPES_TESTS_TS_TYPE_TEST_HELPER_H
|
File diff suppressed because it is too large
Load Diff
@ -1,767 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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_TS_TYPES_TS_MANAGER_H
|
||||
#define ECMASCRIPT_TS_TYPES_TS_MANAGER_H
|
||||
|
||||
#include "ecmascript/compiler/aot_snapshot/aot_snapshot.h"
|
||||
#include "ecmascript/compiler/bytecode_info_collector.h"
|
||||
#include "ecmascript/compiler/compilation_driver.h"
|
||||
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
|
||||
#include "ecmascript/js_handle.h"
|
||||
#include "ecmascript/js_tagged_value-inl.h"
|
||||
#include "ecmascript/ts_types/builtin_type_id.h"
|
||||
#include "ecmascript/ts_types/global_ts_type_ref.h"
|
||||
#include "ecmascript/ts_types/global_type_info.h"
|
||||
#include "ecmascript/ts_types/ts_obj_layout_info.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
using ProfileType = pgo::ProfileType;
|
||||
using SnapshotGlobalData = kungfu::SnapshotGlobalData;
|
||||
enum class PropertyType : uint8_t {
|
||||
NORMAL = 0,
|
||||
STATIC,
|
||||
OTHERS,
|
||||
};
|
||||
|
||||
struct ModuleInfo {
|
||||
const JSPandaFile *jsPandaFile {nullptr}; // there may be serval merged abc files.
|
||||
const CString recordName {""}; // distinguish different files which are all merged to one abc file.
|
||||
uint32_t index {0}; // bytecode "stmoudlevar index", exportVar index is unique in the same record.
|
||||
bool operator < (const ModuleInfo &moduleInfo) const
|
||||
{
|
||||
if (index < moduleInfo.index) {
|
||||
return true;
|
||||
}
|
||||
if (index == moduleInfo.index && recordName < moduleInfo.recordName) {
|
||||
return true;
|
||||
}
|
||||
if (index == moduleInfo.index && recordName == moduleInfo.recordName &&
|
||||
jsPandaFile < moduleInfo.jsPandaFile) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class TSModuleTable : public TaggedArray {
|
||||
public:
|
||||
// Each TSTypeTable occupies three positions
|
||||
static constexpr int ELEMENTS_LENGTH = 4;
|
||||
static constexpr int MODULE_REQUEST_OFFSET = 1;
|
||||
static constexpr int SORT_ID_OFFSET = 2;
|
||||
static constexpr int TYPE_TABLE_OFFSET = 3;
|
||||
static constexpr int ABC_ID_OFFSET = 4;
|
||||
// Reserve a position which is used to store the number of TSTypeTables and a TSTypeTable storage space
|
||||
static constexpr int INITIAL_CAPACITY = ELEMENTS_LENGTH + 1;
|
||||
static constexpr int NUMBER_OF_TABLES_INDEX = 0;
|
||||
static constexpr int INCREASE_CAPACITY_RATE = 2;
|
||||
static constexpr int NOT_FOUND = -1;
|
||||
|
||||
static TSModuleTable *Cast(TaggedObject *object)
|
||||
{
|
||||
ASSERT(JSTaggedValue(object).IsTaggedArray());
|
||||
return static_cast<TSModuleTable *>(object);
|
||||
}
|
||||
|
||||
JSHandle<EcmaString> GetModuleRequestByModuleId(JSThread *thread, int entry) const;
|
||||
|
||||
JSHandle<EcmaString> GetAbcRequestByModuleId(JSThread *thread, int entry) const;
|
||||
|
||||
int GetGlobalModuleID(JSThread *thread, JSHandle<EcmaString> amiPath, JSHandle<EcmaString> abcPath) const;
|
||||
|
||||
inline int GetNumberOfTSTypeTables() const
|
||||
{
|
||||
return Get(NUMBER_OF_TABLES_INDEX).GetInt();
|
||||
}
|
||||
|
||||
inline void SetNumberOfTSTypeTables(JSThread *thread, int num)
|
||||
{
|
||||
Set(thread, NUMBER_OF_TABLES_INDEX, JSTaggedValue(num));
|
||||
}
|
||||
|
||||
static uint32_t GetTSTypeTableOffset(int entry)
|
||||
{
|
||||
return entry * ELEMENTS_LENGTH + TYPE_TABLE_OFFSET;
|
||||
}
|
||||
|
||||
static int GetModuleRequestOffset(int entry)
|
||||
{
|
||||
return entry * ELEMENTS_LENGTH + MODULE_REQUEST_OFFSET;
|
||||
}
|
||||
|
||||
static int GetSortIdOffset(int entry)
|
||||
{
|
||||
return entry * ELEMENTS_LENGTH + SORT_ID_OFFSET;
|
||||
}
|
||||
|
||||
static uint32_t GetAbcRequestOffset(int entry)
|
||||
{
|
||||
return entry * ELEMENTS_LENGTH + ABC_ID_OFFSET;
|
||||
}
|
||||
};
|
||||
|
||||
class PUBLIC_API TSManager {
|
||||
public:
|
||||
explicit TSManager(EcmaVM *vm);
|
||||
~TSManager() = default;
|
||||
|
||||
void Initialize();
|
||||
|
||||
void Dump();
|
||||
|
||||
void Iterate(const RootVisitor &v);
|
||||
|
||||
JSHandle<TSModuleTable> GetTSModuleTable() const
|
||||
{
|
||||
return JSHandle<TSModuleTable>(reinterpret_cast<uintptr_t>(&globalModuleTable_));
|
||||
}
|
||||
|
||||
void SetTSModuleTable(JSHandle<TSModuleTable> table)
|
||||
{
|
||||
globalModuleTable_ = table.GetTaggedValue();
|
||||
}
|
||||
|
||||
JSHandle<TSTypeTable> GetTSTypeTable(int entry) const;
|
||||
|
||||
void SetTSTypeTable(const JSHandle<TSTypeTable> &table, int tableId) const;
|
||||
|
||||
void GenerateBuiltinSummary();
|
||||
|
||||
inline uint32_t GetBuiltinOffset(uint32_t index) const
|
||||
{
|
||||
if (index == static_cast<uint32_t>(BuiltinTypeId::NUM_INDEX_IN_SUMMARY)) {
|
||||
return builtinOffsets_[index];
|
||||
}
|
||||
return builtinOffsets_[index - static_cast<uint32_t>(BuiltinTypeId::BUILTIN_OFFSET)];
|
||||
}
|
||||
|
||||
inline GlobalTSTypeRef PUBLIC_API GetPropType(GlobalTSTypeRef gt, JSTaggedValue propertyName) const
|
||||
{
|
||||
return GetPropType(gt, JSHandle<JSTaggedValue>(thread_, propertyName));
|
||||
}
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetPropType(GlobalTSTypeRef gt, const uint64_t key) const;
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetIndexSignType(GlobalTSTypeRef objType, kungfu::GateType indexType) const;
|
||||
|
||||
inline GlobalTSTypeRef PUBLIC_API CreateClassInstanceType(kungfu::GateType gateType)
|
||||
{
|
||||
GlobalTSTypeRef gt = gateType.GetGTRef();
|
||||
return CreateClassInstanceType(gt);
|
||||
}
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API CreateClassInstanceType(GlobalTSTypeRef gt);
|
||||
|
||||
inline GlobalTSTypeRef PUBLIC_API GetClassType(kungfu::GateType gateType)
|
||||
{
|
||||
GlobalTSTypeRef gt = gateType.GetGTRef();
|
||||
return GetClassType(gt);
|
||||
}
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetClassType(GlobalTSTypeRef classInstanceGT) const;
|
||||
|
||||
JSHandle<TSClassType> GetExtendedClassType(JSHandle<TSClassType> classType) const;
|
||||
|
||||
TSClassType* GetExtendedClassType(const TSClassType *classType) const;
|
||||
|
||||
uint32_t PUBLIC_API GetUnionTypeLength(GlobalTSTypeRef gt) const;
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetUnionTypeByIndex(GlobalTSTypeRef gt, int index) const;
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetOrCreateUnionType(CVector<GlobalTSTypeRef> unionTypeVec);
|
||||
|
||||
uint32_t PUBLIC_API GetFunctionTypeLength(GlobalTSTypeRef gt) const;
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetOrCreateTSIteratorInstanceType(TSRuntimeType runtimeType, GlobalTSTypeRef elementGt);
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetIteratorInstanceElementGt(GlobalTSTypeRef gt) const;
|
||||
|
||||
inline GlobalTSTypeRef PUBLIC_API GetIteratorInstanceElementGt(kungfu::GateType gateType) const
|
||||
{
|
||||
GlobalTSTypeRef gt = GlobalTSTypeRef(gateType.GetGTRef());
|
||||
return GetIteratorInstanceElementGt(gt);
|
||||
}
|
||||
|
||||
bool PUBLIC_API IsStaticFunc(GlobalTSTypeRef gt) const;
|
||||
|
||||
bool PUBLIC_API IsHotnessFunc(GlobalTSTypeRef gt) const;
|
||||
|
||||
void PUBLIC_API SetHotnessFunc(GlobalTSTypeRef gt, bool isHotness) const;
|
||||
|
||||
bool PUBLIC_API GetSuperGateType(kungfu::GateType &gateType) const;
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetSuperPropType(GlobalTSTypeRef gt,
|
||||
JSHandle<JSTaggedValue> propertyName,
|
||||
PropertyType propType) const;
|
||||
|
||||
inline GlobalTSTypeRef PUBLIC_API GetSuperPropType(GlobalTSTypeRef gt,
|
||||
JSTaggedValue propertyName,
|
||||
PropertyType propType) const
|
||||
{
|
||||
return GetSuperPropType(gt, JSHandle<JSTaggedValue>(vm_->GetJSThread(), propertyName),
|
||||
propType);
|
||||
}
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetSuperPropType(GlobalTSTypeRef gt,
|
||||
const uint64_t key,
|
||||
PropertyType propType) const;
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetFuncParameterTypeGT(GlobalTSTypeRef gt, int index) const;
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetFuncThisGT(GlobalTSTypeRef gt) const;
|
||||
|
||||
void PUBLIC_API SetFuncMethodOffset(GlobalTSTypeRef gt, uint32_t methodOffset);
|
||||
|
||||
uint32_t PUBLIC_API GetFuncMethodOffset(GlobalTSTypeRef gt) const;
|
||||
|
||||
bool PUBLIC_API IsGetterSetterFunc(GlobalTSTypeRef gt) const;
|
||||
|
||||
bool IsAbstractMethod(GlobalTSTypeRef gt) const;
|
||||
|
||||
bool IsMethodSignature(GlobalTSTypeRef gt) const;
|
||||
bool CanFastCall(GlobalTSTypeRef gt) const;
|
||||
bool IsNoGC(GlobalTSTypeRef gt) const;
|
||||
bool MethodOffsetIsVaild(GlobalTSTypeRef gt) const;
|
||||
bool FastCallFlagIsVaild(GlobalTSTypeRef gt) const;
|
||||
|
||||
inline GlobalTSTypeRef PUBLIC_API GetFuncReturnValueTypeGT(kungfu::GateType gateType) const
|
||||
{
|
||||
GlobalTSTypeRef gt = gateType.GetGTRef();
|
||||
return GetFuncReturnValueTypeGT(gt);
|
||||
}
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetFuncReturnValueTypeGT(GlobalTSTypeRef gt) const;
|
||||
|
||||
std::string PUBLIC_API GetFuncName(kungfu::GateType gt) const;
|
||||
|
||||
int PUBLIC_API GetMethodIndex(GlobalTSTypeRef gt) const;
|
||||
|
||||
inline GlobalTSTypeRef PUBLIC_API GetArrayParameterTypeGT(kungfu::GateType gateType) const
|
||||
{
|
||||
GlobalTSTypeRef gt = gateType.GetGTRef();
|
||||
return GetArrayParameterTypeGT(gt);
|
||||
}
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetArrayParameterTypeGT(GlobalTSTypeRef gt) const;
|
||||
|
||||
bool PUBLIC_API AssertTypes() const
|
||||
{
|
||||
return assertTypes_;
|
||||
}
|
||||
|
||||
double PUBLIC_API GetTypeThreshold() const
|
||||
{
|
||||
return typeThreshold_;
|
||||
}
|
||||
|
||||
bool IsBuiltinsDTSEnabled() const
|
||||
{
|
||||
return vm_->GetJSOptions().WasSetBuiltinsDTS();
|
||||
}
|
||||
|
||||
CString GetBuiltinsDTS() const
|
||||
{
|
||||
std::string fileName = vm_->GetJSOptions().GetBuiltinsDTS();
|
||||
return CString(fileName);
|
||||
}
|
||||
|
||||
void AddInstanceTSHClass(GlobalTSTypeRef gt, JSHandle<JSHClass> &ihclass);
|
||||
|
||||
void AddConstructorTSHClass(GlobalTSTypeRef gt, JSHandle<JSHClass> &constructorHClass);
|
||||
|
||||
JSTaggedValue GetInstanceTSHClass(const JSHandle<TSClassType> &classType) const;
|
||||
|
||||
bool HasTSHClass(const JSHandle<TSClassType> &classType) const;
|
||||
|
||||
bool HasTSHClass(const TSClassType *classType) const;
|
||||
|
||||
JSHandle<JSTaggedValue> GetTSType(const GlobalTSTypeRef >) const;
|
||||
|
||||
std::string PUBLIC_API GetTypeStr(kungfu::GateType gateType) const;
|
||||
|
||||
int PUBLIC_API GetHClassIndexByObjectType(const kungfu::GateType &gateType);
|
||||
|
||||
int PUBLIC_API GetHClassIndexByInstanceGateType(const kungfu::GateType &gateType);
|
||||
|
||||
int PUBLIC_API GetConstructorHClassIndexByClassGateType(const kungfu::GateType &gateType);
|
||||
|
||||
int PUBLIC_API GetHClassIndexByClassGateType(const kungfu::GateType &gateType);
|
||||
|
||||
JSTaggedValue GetTSHClass(const kungfu::GateType &gateType) const;
|
||||
|
||||
JSTaggedValue PUBLIC_API GetAOTHClassInfoByIndex(uint32_t index);
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API CreateArrayType();
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API CreateNamespaceType();
|
||||
|
||||
bool AddNamespacePropType(kungfu::GateType objType, JSTaggedValue name, kungfu::GateType valueType);
|
||||
|
||||
inline bool IsUserDefinedClassTypeKind(const kungfu::GateType &gateType) const
|
||||
{
|
||||
GlobalTSTypeRef gt = gateType.GetGTRef();
|
||||
return IsUserDefinedClassTypeKind(gt);
|
||||
}
|
||||
|
||||
inline bool IsUserDefinedClassTypeKind(const GlobalTSTypeRef >) const
|
||||
{
|
||||
return IsClassTypeKind(gt) && (!gt.IsBuiltinModule());
|
||||
}
|
||||
|
||||
inline void StoreNamespaceType(const uint32_t methodOffset, const kungfu::GateType type)
|
||||
{
|
||||
methodOffsetToType_.insert(std::make_pair(methodOffset, type));
|
||||
}
|
||||
|
||||
inline kungfu::GateType GetNamespaceObjType(const uint32_t methodOffset) const
|
||||
{
|
||||
ASSERT(HasInferredNamespaceType(methodOffset));
|
||||
return methodOffsetToType_.at(methodOffset);
|
||||
}
|
||||
|
||||
inline bool HasInferredNamespaceType(const uint32_t methodOffset) const
|
||||
{
|
||||
return methodOffsetToType_.find(methodOffset) != methodOffsetToType_.end();
|
||||
}
|
||||
|
||||
EcmaVM *GetEcmaVM() const
|
||||
{
|
||||
return vm_;
|
||||
}
|
||||
|
||||
JSThread *GetThread() const
|
||||
{
|
||||
return thread_;
|
||||
}
|
||||
|
||||
#define IS_TSTYPEKIND_METHOD_LIST(V) \
|
||||
V(Primitive, TSTypeKind::PRIMITIVE) \
|
||||
V(Class, TSTypeKind::CLASS) \
|
||||
V(ClassInstance, TSTypeKind::CLASS_INSTANCE) \
|
||||
V(Function, TSTypeKind::FUNCTION) \
|
||||
V(Union, TSTypeKind::UNION) \
|
||||
V(Array, TSTypeKind::ARRAY) \
|
||||
V(Object, TSTypeKind::OBJECT) \
|
||||
V(Import, TSTypeKind::IMPORT) \
|
||||
V(Interface, TSTypeKind::INTERFACE) \
|
||||
V(IteratorInstance, TSTypeKind::ITERATOR_INSTANCE) \
|
||||
V(Namespace, TSTypeKind::NAMESPACE)
|
||||
|
||||
#define IS_TSTYPEKIND(NAME, TSTYPEKIND) \
|
||||
inline bool PUBLIC_API Is##NAME##TypeKind(const kungfu::GateType &gateType) const \
|
||||
{ \
|
||||
GlobalTSTypeRef gt = gateType.GetGTRef(); \
|
||||
return GetTypeKind(gt) == (TSTYPEKIND); \
|
||||
} \
|
||||
\
|
||||
inline bool PUBLIC_API Is##NAME##TypeKind(const GlobalTSTypeRef >) const \
|
||||
{ \
|
||||
return GetTypeKind(gt) == (TSTYPEKIND); \
|
||||
}
|
||||
|
||||
IS_TSTYPEKIND_METHOD_LIST(IS_TSTYPEKIND)
|
||||
#undef IS_TSTYPEKIND
|
||||
|
||||
bool PUBLIC_API IsBuiltinClassType(BuiltinTypeId id, kungfu::GateType gateType) const;
|
||||
|
||||
bool PUBLIC_API IsBuiltinInstanceType(BuiltinTypeId id, kungfu::GateType gateType) const;
|
||||
|
||||
bool PUBLIC_API IsTypedArrayType(kungfu::GateType gateType) const;
|
||||
|
||||
bool PUBLIC_API IsValidTypedArrayType(kungfu::GateType gateType) const;
|
||||
|
||||
inline bool PUBLIC_API IsBuiltinObjectType(kungfu::GateType gateType) const
|
||||
{
|
||||
return gateType.GetGTRef().IsBuiltinModule() && IsClassTypeKind(gateType);
|
||||
}
|
||||
|
||||
bool PUBLIC_API IsIntTypedArrayType(kungfu::GateType gateType) const;
|
||||
|
||||
bool PUBLIC_API IsDoubleTypedArrayType(kungfu::GateType gateType) const;
|
||||
|
||||
BuiltinTypeId PUBLIC_API GetTypedArrayBuiltinId(kungfu::GateType gateType) const;
|
||||
|
||||
static const std::vector<BuiltinTypeId> &GetValidTypedArrayIds();
|
||||
|
||||
inline void AddElementToIdGTMap(const GlobalTypeID &id, GlobalTSTypeRef gt,
|
||||
const CString &recordName = "", bool isImportType = false)
|
||||
{
|
||||
auto it = idGTMap_.find(id);
|
||||
if (it != idGTMap_.end()) {
|
||||
it->second = gt;
|
||||
} else {
|
||||
idGTMap_.emplace(id, gt);
|
||||
}
|
||||
if (!isImportType && !id.IsPGOType()) {
|
||||
auto value = std::make_tuple(id.GetJSPandaFile()->GetNormalizedFileDesc(), recordName, id.GetTypeId());
|
||||
gtLiteralOffsetMap_.emplace(gt, value);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool HasCreatedGT(const GlobalTypeID &id) const
|
||||
{
|
||||
return idGTMap_.find(id) != idGTMap_.end();
|
||||
}
|
||||
|
||||
inline GlobalTSTypeRef GetGTByGlobalTypeID(const GlobalTypeID &id) const
|
||||
{
|
||||
return idGTMap_.at(id);
|
||||
}
|
||||
|
||||
inline bool HasOffsetFromGT(GlobalTSTypeRef gt) const
|
||||
{
|
||||
return gtLiteralOffsetMap_.find(gt) != gtLiteralOffsetMap_.end();
|
||||
}
|
||||
|
||||
inline std::tuple<CString, CString, uint32_t> GetOffsetFromGt(GlobalTSTypeRef gt) const
|
||||
{
|
||||
return gtLiteralOffsetMap_.at(gt);
|
||||
}
|
||||
|
||||
inline void AddTypeToModuleVarGtMap(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
uint32_t index, GlobalTSTypeRef gt)
|
||||
{
|
||||
ModuleInfo key = {jsPandaFile, recordName, index};
|
||||
if (moduleVarGtMap_.find(key) == moduleVarGtMap_.end()) {
|
||||
moduleVarGtMap_.emplace(key, gt);
|
||||
} else {
|
||||
moduleVarGtMap_[key] = gt;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool HasExportGT(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
uint32_t index) const
|
||||
{
|
||||
ModuleInfo key = {jsPandaFile, recordName, index};
|
||||
return moduleVarGtMap_.find(key) != moduleVarGtMap_.end();
|
||||
}
|
||||
|
||||
inline GlobalTSTypeRef GetGTFromModuleMap(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
uint32_t index) const
|
||||
{
|
||||
ModuleInfo key = {jsPandaFile, recordName, index};
|
||||
return moduleVarGtMap_.at(key);
|
||||
}
|
||||
|
||||
inline void AddResolvedExportTable(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
JSTaggedValue exportTable)
|
||||
{
|
||||
auto key = std::make_pair(jsPandaFile, recordName);
|
||||
if (resolvedExportTable_.find(key) == resolvedExportTable_.end()) {
|
||||
resolvedExportTable_.emplace(key, exportTable);
|
||||
} else {
|
||||
resolvedExportTable_[key] = exportTable;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool HasResolvedExportTable(const JSPandaFile *jsPandaFile, const CString &recordName) const
|
||||
{
|
||||
auto key = std::make_pair(jsPandaFile, recordName);
|
||||
return resolvedExportTable_.find(key) != resolvedExportTable_.end();
|
||||
}
|
||||
|
||||
inline JSTaggedValue GetResolvedExportTable(const JSPandaFile *jsPandaFile, const CString &recordName) const
|
||||
{
|
||||
auto key = std::make_pair(jsPandaFile, recordName);
|
||||
return resolvedExportTable_.at(key);
|
||||
}
|
||||
|
||||
bool IsTSIterator(GlobalTSTypeRef gt) const
|
||||
{
|
||||
uint32_t l = gt.GetLocalId();
|
||||
return gt.IsRuntimeModule() && (l == static_cast<uint32_t>(TSRuntimeType::ITERATOR));
|
||||
}
|
||||
|
||||
bool IsTSIteratorResult(GlobalTSTypeRef gt) const
|
||||
{
|
||||
uint32_t l = gt.GetLocalId();
|
||||
return gt.IsRuntimeModule() && (l == static_cast<uint32_t>(TSRuntimeType::ITERATOR_RESULT));
|
||||
}
|
||||
|
||||
void PUBLIC_API SetCurConstantPool(const JSPandaFile *jsPandaFile, uint32_t methodOffset);
|
||||
|
||||
int32_t PUBLIC_API GetConstantPoolIDByMethodOffset(const JSPandaFile *jsPandaFile, uint32_t methodOffset);
|
||||
|
||||
uint32_t GetConstantPoolId(uint32_t methodId) const;
|
||||
JSTaggedValue GetConstantPool(uint32_t methodId) const;
|
||||
|
||||
JSHandle<JSTaggedValue> PUBLIC_API GetConstantPool() const
|
||||
{
|
||||
return JSHandle<JSTaggedValue>(uintptr_t(&curCP_));
|
||||
}
|
||||
|
||||
JSTaggedValue PUBLIC_API GetStringFromConstantPool(uint32_t methodId, const uint16_t stringId) const;
|
||||
|
||||
inline std::string PUBLIC_API GetStdStringFromConstantPool(uint32_t methodId, const uint16_t stringId) const
|
||||
{
|
||||
JSTaggedValue str = GetStringFromConstantPool(methodId, stringId);
|
||||
return EcmaStringAccessor(str).ToStdString(StringConvertedUsage::LOGICOPERATION);
|
||||
}
|
||||
|
||||
bool PUBLIC_API IsBuiltinObjectMethod(BuiltinTypeId id, kungfu::GateType funcType) const;
|
||||
bool PUBLIC_API IsBuiltinConstructor(BuiltinTypeId id, GlobalTSTypeRef ctorType) const;
|
||||
|
||||
inline const JSPandaFile *GetBuiltinPandaFile() const
|
||||
{
|
||||
return builtinPandaFile_;
|
||||
}
|
||||
|
||||
inline const CString &GetBuiltinRecordName() const
|
||||
{
|
||||
return builtinsRecordName_;
|
||||
}
|
||||
|
||||
inline kungfu::BytecodeInfoCollector *GetBytecodeInfoCollector() const
|
||||
{
|
||||
return bcInfoCollector_;
|
||||
}
|
||||
|
||||
inline void SetBytecodeInfoCollector(kungfu::BytecodeInfoCollector *bcInfoCollector)
|
||||
{
|
||||
bcInfoCollector_ = bcInfoCollector;
|
||||
}
|
||||
|
||||
class IHClassData {
|
||||
public:
|
||||
explicit IHClassData(JSTaggedType ihc) : ihc_(ihc) {}
|
||||
|
||||
void Iterate(const RootVisitor &v)
|
||||
{
|
||||
v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&ihc_)));
|
||||
}
|
||||
|
||||
std::unordered_map<int32_t, uint32_t>& GetCPIndexMap()
|
||||
{
|
||||
return cpIndexMap_;
|
||||
}
|
||||
|
||||
JSTaggedType GetIHC() const
|
||||
{
|
||||
return ihc_;
|
||||
}
|
||||
|
||||
private:
|
||||
JSTaggedType ihc_ {0};
|
||||
std::unordered_map<int32_t, uint32_t> cpIndexMap_ {};
|
||||
};
|
||||
|
||||
void SetCompilationDriver(kungfu::CompilationDriver *cmpDriver)
|
||||
{
|
||||
cmpDriver_ = cmpDriver;
|
||||
}
|
||||
|
||||
kungfu::CompilationDriver *GetCompilationDriver() const
|
||||
{
|
||||
return cmpDriver_;
|
||||
}
|
||||
|
||||
void AddElementToClassNameMap(const JSPandaFile *jsPandaFile, uint32_t offset, std::string className)
|
||||
{
|
||||
literalOffsetClassNameMap_.emplace(std::make_pair(jsPandaFile, offset), className);
|
||||
}
|
||||
|
||||
const std::string GetClassNameByOffset(const JSPandaFile *jsPandaFile, uint32_t typeId) const
|
||||
{
|
||||
std::pair<const JSPandaFile *, uint32_t> pair = std::make_pair(jsPandaFile, typeId);
|
||||
std::string name = "";
|
||||
if (literalOffsetClassNameMap_.find(pair) != literalOffsetClassNameMap_.end()) {
|
||||
name = literalOffsetClassNameMap_.at(pair);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
inline void CollectGT(GlobalTSTypeRef gt)
|
||||
{
|
||||
if (IsClassTypeKind(gt)) {
|
||||
collectedGT_.insert(gt);
|
||||
}
|
||||
}
|
||||
|
||||
inline std::set<GlobalTSTypeRef>& GetCollectedGT()
|
||||
{
|
||||
return collectedGT_;
|
||||
}
|
||||
|
||||
inline void InsertLiteralGTMap(TypeLocation &loc, GlobalTSTypeRef gt)
|
||||
{
|
||||
literalGTMap_[loc] = gt;
|
||||
}
|
||||
|
||||
inline GlobalTSTypeRef GetLiteralGT(TypeLocation &loc)
|
||||
{
|
||||
auto it = literalGTMap_.find(loc);
|
||||
if (it != literalGTMap_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return GlobalTSTypeRef::Default();
|
||||
}
|
||||
|
||||
inline void InsertPtToGtMap(ProfileType pgoType, const kungfu::GateType &gateType)
|
||||
{
|
||||
ptToGtMap_.emplace(pgoType, gateType);
|
||||
}
|
||||
|
||||
inline const kungfu::GateType GetGateTypeByPt(ProfileType pgoType)
|
||||
{
|
||||
if (pgoType.IsBuiltinsType()) {
|
||||
return GetBuiltinsGateTypeByPt(pgoType);
|
||||
}
|
||||
auto it = ptToGtMap_.find(pgoType);
|
||||
if (it != ptToGtMap_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return kungfu::GateType::AnyType();
|
||||
}
|
||||
|
||||
void PrintNumOfTypes() const;
|
||||
|
||||
void PrintTypeInfo(const JSPandaFile *jsPandaFile) const;
|
||||
|
||||
kungfu::GateType TryNarrowUnionType(kungfu::GateType gateType);
|
||||
|
||||
JSHandle<TaggedArray> GetExportTableFromLiteral(const JSPandaFile *jsPandaFile, const CString &recordName);
|
||||
|
||||
int GetHClassIndex(GlobalTSTypeRef classGT, bool isConstructor = false);
|
||||
|
||||
uint32_t GetPGOGTCountByRecordName(const CString &recordName) const
|
||||
{
|
||||
if (bcInfoCollector_ == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
const kungfu::PGOBCInfo *bcInfo = bcInfoCollector_->GetPGOBCInfo();
|
||||
return bcInfo->GetPGOExtendGTCount(recordName);
|
||||
}
|
||||
|
||||
inline std::string GetBuiltinsName(GlobalTSTypeRef builtinGT) const
|
||||
{
|
||||
uint32_t index = GetBuiltinIndex(builtinGT);
|
||||
return GetBuiltinsName(index);
|
||||
}
|
||||
|
||||
TSTypeKind PUBLIC_API GetTypeKind(const GlobalTSTypeRef >) const;
|
||||
|
||||
#define TSTYPETABLE_ACCESSOR_LIST(V) \
|
||||
V(Builtin, ModuleTableIdx::BUILTIN) \
|
||||
V(Inferred, ModuleTableIdx::INFERRED) \
|
||||
V(Runtime, ModuleTableIdx::RUNTIME) \
|
||||
V(Generics, ModuleTableIdx::GENERICS)
|
||||
|
||||
#define TSTYPETABLE_ACCESSOR(NAME, MODULEID) \
|
||||
inline GlobalTSTypeRef AddTSTypeTo##NAME##Table(const JSHandle<TSType> &type) const \
|
||||
{ \
|
||||
return AddTSTypeToTypeTable(type, static_cast<uint32_t>(MODULEID)); \
|
||||
} \
|
||||
\
|
||||
inline JSHandle<TSTypeTable> Get##NAME##Table() const \
|
||||
{ \
|
||||
return GetTSTypeTable(static_cast<uint32_t>(MODULEID)); \
|
||||
} \
|
||||
\
|
||||
inline void Set##NAME##Table(const JSHandle<TSTypeTable> &table) \
|
||||
{ \
|
||||
SetTSTypeTable(table, static_cast<uint32_t>(MODULEID)); \
|
||||
}
|
||||
|
||||
TSTYPETABLE_ACCESSOR_LIST(TSTYPETABLE_ACCESSOR)
|
||||
#undef TSTYPETABLE_ACCESSOR
|
||||
|
||||
private:
|
||||
NO_COPY_SEMANTIC(TSManager);
|
||||
NO_MOVE_SEMANTIC(TSManager);
|
||||
|
||||
GlobalTSTypeRef AddTSTypeToTypeTable(const JSHandle<TSType> &type, int tableId) const;
|
||||
|
||||
JSHandle<TaggedArray> GenerateExportTableFromLiteral(const JSPandaFile *jsPandaFile, const CString &recordName);
|
||||
|
||||
GlobalTSTypeRef FindUnionInTypeTable(JSHandle<TSTypeTable> table, JSHandle<TSUnionType> unionType) const;
|
||||
|
||||
GlobalTSTypeRef FindIteratorInstanceInInferTable(GlobalTSTypeRef kindGt, GlobalTSTypeRef elementGt) const;
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetPropType(GlobalTSTypeRef gt, JSHandle<JSTaggedValue> propertyName) const;
|
||||
|
||||
std::string GetClassTypeStr(GlobalTSTypeRef gt) const;
|
||||
|
||||
std::string GetClassInstanceTypeStr(GlobalTSTypeRef gt) const;
|
||||
|
||||
std::string GetFunctionTypeStr(GlobalTSTypeRef gt) const;
|
||||
|
||||
std::string GetArrayTypeStr(GlobalTSTypeRef gt) const;
|
||||
|
||||
std::string GetPrimitiveStr(const GlobalTSTypeRef >) const;
|
||||
|
||||
uint32_t RecordIhcToVecAndIndexMap(IHClassData &ihcData);
|
||||
|
||||
uint32_t GetBuiltinIndex(GlobalTSTypeRef builtinGT) const;
|
||||
|
||||
std::string GetBuiltinsName(uint32_t index) const;
|
||||
|
||||
inline void SetBuiltinPandaFile(JSPandaFile *jsPandaFile)
|
||||
{
|
||||
builtinPandaFile_ = jsPandaFile;
|
||||
}
|
||||
|
||||
inline void SetBuiltinRecordName(CString &builtinsRecordName)
|
||||
{
|
||||
builtinsRecordName_ = builtinsRecordName;
|
||||
}
|
||||
|
||||
// for jsarray
|
||||
void TryGetElmsKind(panda_file::File::EntityId id, JSHandle<JSTaggedValue> &ekd);
|
||||
|
||||
const kungfu::GateType GetBuiltinsGateTypeByPt(ProfileType pgoType);
|
||||
|
||||
BuiltinTypeId GetBuiltinTypeIdByJSType(JSType jsType);
|
||||
|
||||
EcmaVM *vm_ {nullptr};
|
||||
JSThread *thread_ {nullptr};
|
||||
ObjectFactory *factory_ {nullptr};
|
||||
// kungfu::PGOTypeManager ptManager_;
|
||||
JSTaggedValue globalModuleTable_ {JSTaggedValue::Hole()};
|
||||
CMap<ProfileType, const kungfu::GateType> ptToGtMap_ {};
|
||||
std::map<GlobalTSTypeRef, IHClassData> gtIhcMap_ {};
|
||||
std::map<GlobalTSTypeRef, IHClassData> gtConstructorhcMap_ {};
|
||||
std::unordered_map<TypeLocation, GlobalTSTypeRef, HashTypeLocation> literalGTMap_ {};
|
||||
std::map<JSType, GlobalTSTypeRef> pgoBuiltinGTCache_ {};
|
||||
bool assertTypes_ {false};
|
||||
double typeThreshold_ {-1};
|
||||
|
||||
// when the passmanager iterates each method, the curCP_ and curCPID_ should be updated
|
||||
// so that subsequent passes (type_infer, type_bytecode_lowering) can obtain the correct constpool.
|
||||
JSTaggedValue curCP_ {JSTaggedValue::Hole()};
|
||||
int32_t curCPID_ {0};
|
||||
const JSPandaFile *curJSPandaFile_ {nullptr};
|
||||
|
||||
std::unordered_map<GlobalTypeID, GlobalTSTypeRef, HashGlobalTypeID> idGTMap_ {};
|
||||
std::map<GlobalTSTypeRef, std::tuple<CString, CString, uint32_t>> gtLiteralOffsetMap_ {};
|
||||
std::vector<uint32_t> builtinOffsets_ {};
|
||||
JSPandaFile *builtinPandaFile_ {nullptr};
|
||||
CString builtinsRecordName_ {""};
|
||||
std::map<ModuleInfo, GlobalTSTypeRef> moduleVarGtMap_{};
|
||||
kungfu::CompilationDriver *cmpDriver_ {nullptr};
|
||||
std::set<GlobalTSTypeRef> collectedGT_ {}; // use for storing types that need to generate hclasses
|
||||
|
||||
friend class EcmaVM;
|
||||
friend class TSTypeAccessor;
|
||||
|
||||
std::map<std::pair<const JSPandaFile *, uint32_t>, std::string> literalOffsetClassNameMap_ {};
|
||||
kungfu::BytecodeInfoCollector *bcInfoCollector_ {nullptr};
|
||||
// use for collect the literal of export type table.
|
||||
CMap<std::pair<const JSPandaFile *, CString>, JSTaggedValue> resolvedExportTable_ {};
|
||||
CMap<uint32_t, kungfu::GateType> methodOffsetToType_ {};
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
#endif // ECMASCRIPT_TS_TYPES_TS_MANAGER_H
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user