diff --git a/BUILD.gn b/BUILD.gn index 68f6a0a99d..d5141a7a62 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -693,6 +693,8 @@ ecma_source = [ "ecmascript/intl/locale_helper.cpp", "ecmascript/jit/jit.cpp", "ecmascript/jit/jit_task.cpp", + "ecmascript/jit/jit_thread.cpp", + "ecmascript/jit/persistent_handles.cpp", "ecmascript/jobs/micro_job_queue.cpp", "ecmascript/jspandafile/js_pandafile.cpp", "ecmascript/jspandafile/js_pandafile_manager.cpp", diff --git a/ecmascript/builtins/builtins_ark_tools.cpp b/ecmascript/builtins/builtins_ark_tools.cpp index 672099d459..bcbe2152e4 100644 --- a/ecmascript/builtins/builtins_ark_tools.cpp +++ b/ecmascript/builtins/builtins_ark_tools.cpp @@ -1142,4 +1142,57 @@ JSTaggedValue BuiltinsArkTools::ClearFunctionFeedback([[maybe_unused]] EcmaRunti LOG_ECMA(DEBUG) << "Enter ClearFunctionFeedback()"; return JSTaggedValue::Undefined(); } + +JSTaggedValue BuiltinsArkTools::JitCompileSync(EcmaRuntimeCallInfo *info) +{ + JSThread *thread = info->GetThread(); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + + JSHandle thisValue = GetCallArg(info, 0); + if (!thisValue->IsJSFunction()) { + return JSTaggedValue::False(); + } + JSHandle jsFunction(thisValue); + Jit::Compile(thread->GetEcmaVM(), jsFunction, MachineCode::INVALID_OSR_OFFSET, JitCompileMode::SYNC); + return JSTaggedValue::True(); +} + +JSTaggedValue BuiltinsArkTools::JitCompileAsync(EcmaRuntimeCallInfo *info) +{ + JSThread *thread = info->GetThread(); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + + JSHandle thisValue = GetCallArg(info, 0); + if (!thisValue->IsJSFunction()) { + return JSTaggedValue::False(); + } + JSHandle jsFunction(thisValue); + Jit::Compile(thread->GetEcmaVM(), jsFunction, MachineCode::INVALID_OSR_OFFSET, JitCompileMode::ASYNC); + return JSTaggedValue::True(); +} + +JSTaggedValue BuiltinsArkTools::WaitJitCompileFinish(EcmaRuntimeCallInfo *info) +{ + JSThread *thread = info->GetThread(); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + + JSHandle thisValue = GetCallArg(info, 0); + if (!thisValue->IsJSFunction()) { + return JSTaggedValue::False(); + } + JSHandle jsFunction(thisValue); + + auto jit = Jit::GetInstance(); + if (!jit->IsEnable()) { + return JSTaggedValue::False(); + } + if (jsFunction->GetMachineCode() == JSTaggedValue::Undefined()) { + return JSTaggedValue::False(); + } + while (jsFunction->GetMachineCode() == JSTaggedValue::Hole()) { + // just spin check + thread->CheckSafepoint(); + } + return JSTaggedValue::True(); +} } // namespace panda::ecmascript::builtins diff --git a/ecmascript/builtins/builtins_ark_tools.h b/ecmascript/builtins/builtins_ark_tools.h index 252290a9dc..d83ae81803 100644 --- a/ecmascript/builtins/builtins_ark_tools.h +++ b/ecmascript/builtins/builtins_ark_tools.h @@ -121,6 +121,11 @@ V("isBeingInterpreted", IsBeingInterpreted, 0, INVALID) \ V("clearFunctionFeedback", ClearFunctionFeedback, 1, INVALID) +#define BUILTIN_ARK_TOOLS_FUNCTIONS_JITCOMPILE(V) \ + V("jitCompileSync", JitCompileSync, 1, INVALID) \ + V("jitCompileAsync", JitCompileAsync, 1, INVALID) \ + V("waitJitCompileFinish", WaitJitCompileFinish, 1, INVALID) + #ifdef ECMASCRIPT_SUPPORT_CPUPROFILER #define BUILTIN_ARK_TOOLS_FUNCTIONS_CPUPROFILER(V) \ @@ -133,7 +138,8 @@ #define BUILTIN_ARK_TOOLS_FUNCTIONS(V) \ BUILTIN_ARK_TOOLS_FUNCTIONS_COMMON(V) \ BUILTIN_ARK_TOOLS_FUNCTIONS_CPUPROFILER(V) \ - BUILTIN_ARK_TOOLS_FUNCTIONS_REGRESS(V) + BUILTIN_ARK_TOOLS_FUNCTIONS_REGRESS(V) \ + BUILTIN_ARK_TOOLS_FUNCTIONS_JITCOMPILE(V) namespace panda::ecmascript::builtins { class BuiltinsArkTools : public base::BuiltinsBase { @@ -342,6 +348,10 @@ public: static JSTaggedValue ClearFunctionFeedback(EcmaRuntimeCallInfo *info); + static JSTaggedValue JitCompileSync(EcmaRuntimeCallInfo *info); + static JSTaggedValue JitCompileAsync(EcmaRuntimeCallInfo *info); + static JSTaggedValue WaitJitCompileFinish(EcmaRuntimeCallInfo *info); + static Span GetArkToolsFunctions() { return Span(ARK_TOOLS_FUNCTIONS); diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index d375bcedb9..51af0dc4eb 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -78,6 +78,7 @@ config("include_maple") { libark_jsoptimizer_sources = [ "access_object_stub_builder.cpp", + "aot_compilation_env.cpp", "aot_compiler_preprocessor.cpp", "argument_accessor.cpp", "array_bounds_check_elimination.cpp", @@ -114,6 +115,7 @@ libark_jsoptimizer_sources = [ "combined_pass_visitor.cpp", "common_stubs.cpp", "compilation_driver.cpp", + "compilation_env.cpp", "compiler_log.cpp", "constant_folding.cpp", "dead_code_elimination.cpp", @@ -136,6 +138,7 @@ libark_jsoptimizer_sources = [ "interpreter_stub.cpp", "ir_builder.cpp", "ir_module.cpp", + "jit_compilation_env.cpp", "jit_compiler.cpp", "later_elimination.cpp", "lcr_circuit_builder.cpp", diff --git a/ecmascript/compiler/aot_compilation_env.cpp b/ecmascript/compiler/aot_compilation_env.cpp new file mode 100644 index 0000000000..33ad3c5e7f --- /dev/null +++ b/ecmascript/compiler/aot_compilation_env.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ecmascript/compiler/aot_compilation_env.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(); +} + +JSRuntimeOptions &AOTCompilationEnv::GetJSOptions() +{ + return vm_->GetJSOptions(); +} + +JSHandle AOTCompilationEnv::GetGlobalEnv() const +{ + return vm_->GetGlobalEnv(); +} + +const CMap &AOTCompilationEnv::GetArrayHClassIndexMap() const +{ + return thread_->GetArrayHClassIndexMap(); +} + +const BuiltinHClassEntries &AOTCompilationEnv::GetBuiltinHClassEntries() const +{ + return thread_->GetBuiltinHClassEntries(); +} + +JSHClass *AOTCompilationEnv::GetBuiltinPrototypeHClass(BuiltinTypeId type) const +{ + return thread_->GetBuiltinPrototypeHClass(type); +} + +JSTaggedValue AOTCompilationEnv::FindConstpool(const JSPandaFile *jsPandaFile, panda_file::File::EntityId id) const +{ + return thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, id); +} + +JSTaggedValue AOTCompilationEnv::FindConstpool(const JSPandaFile *jsPandaFile, int32_t index) const +{ + return thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, index); +} + +JSTaggedValue AOTCompilationEnv::FindOrCreateUnsharedConstpool(const uint32_t methodOffset) const +{ + JSTaggedValue cp = ptManager_->GetConstantPoolByMethodOffset(methodOffset); + return thread_->GetCurrentEcmaContext()->FindOrCreateUnsharedConstpool(cp); +} + +JSTaggedValue AOTCompilationEnv::FindOrCreateUnsharedConstpool(JSTaggedValue sharedConstpool) const +{ + return thread_->GetCurrentEcmaContext()->FindOrCreateUnsharedConstpool(sharedConstpool); +} + +JSHandle AOTCompilationEnv::FindOrCreateConstPool(const JSPandaFile *jsPandaFile, + panda_file::File::EntityId id) +{ + return thread_->GetCurrentEcmaContext()->FindOrCreateConstPool(jsPandaFile, id); +} + +JSTaggedValue AOTCompilationEnv::GetConstantPoolByMethodOffset(const uint32_t methodOffset) const +{ + return ptManager_->GetConstantPoolByMethodOffset(methodOffset); +} + +const GlobalEnvConstants *AOTCompilationEnv::GlobalConstants() const +{ + return thread_->GlobalConstants(); +} + +JSTaggedValue AOTCompilationEnv::GetArrayLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const +{ + return ConstantPool::GetLiteralFromCache(thread_, constpool, index, entry); +} + +JSTaggedValue AOTCompilationEnv::GetObjectLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const +{ + return ConstantPool::GetLiteralFromCache(thread_, constpool, index, entry); +} + +panda_file::File::EntityId AOTCompilationEnv::GetIdFromCache(JSTaggedValue constpool, uint32_t index) const +{ + return ConstantPool::GetIdFromCache(constpool, index); +} + +JSTaggedValue AOTCompilationEnv::GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx) const +{ + return ptManager_->GetStringFromConstantPool(methodOffset, cpIdx); +} +} // namespace panda::ecmascript diff --git a/ecmascript/compiler/aot_compilation_env.h b/ecmascript/compiler/aot_compilation_env.h new file mode 100644 index 0000000000..bd22893962 --- /dev/null +++ b/ecmascript/compiler/aot_compilation_env.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_COMPILER_AOT_COMPILATION_ENV_H +#define ECMASCRIPT_COMPILER_AOT_COMPILATION_ENV_H +#include "ecmascript/compiler/compilation_env.h" + +namespace panda::ecmascript { +class AOTCompilationEnv final : public CompilationEnv { +public: + AOTCompilationEnv(EcmaVM *vm); + ~AOTCompilationEnv() = default; + bool IsAotCompiler() const override + { + return true; + } + + JSRuntimeOptions &GetJSOptions() override; + + // thread + const CMap &GetArrayHClassIndexMap() const override; + const BuiltinHClassEntries &GetBuiltinHClassEntries() const override; + JSHClass *GetBuiltinPrototypeHClass(BuiltinTypeId type) const override; + + // context + JSTaggedValue FindConstpool(const JSPandaFile *jsPandaFile, panda_file::File::EntityId id) const override; + JSTaggedValue FindConstpool(const JSPandaFile *jsPandaFile, int32_t index) const override; + JSTaggedValue FindOrCreateUnsharedConstpool(const uint32_t methodOffset) const override; + JSTaggedValue FindOrCreateUnsharedConstpool(JSTaggedValue sharedConstpool) const override; + JSHandle FindOrCreateConstPool(const JSPandaFile *jsPandaFile, + panda_file::File::EntityId id) override; + JSTaggedValue GetConstantPoolByMethodOffset(const uint32_t methodOffset) const override; + + // ConstantPool + JSTaggedValue GetArrayLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const override; + JSTaggedValue GetObjectLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const override; + panda_file::File::EntityId GetIdFromCache(JSTaggedValue constpool, uint32_t index) const override; + + // GlobalEnv + JSHandle GetGlobalEnv() const override; + + // GlobalConstants + const GlobalEnvConstants *GlobalConstants() const override; + + JSTaggedValue GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx) const override; +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_COMPILER_AOT_COMPILATION_ENV_H \ No newline at end of file diff --git a/ecmascript/compiler/aot_compiler.cpp b/ecmascript/compiler/aot_compiler.cpp index 79567bb3b6..de79ac088a 100644 --- a/ecmascript/compiler/aot_compiler.cpp +++ b/ecmascript/compiler/aot_compiler.cpp @@ -22,6 +22,7 @@ #include "ecmascript/compiler/aot_compiler_preprocessor.h" #include "ecmascript/compiler/aot_file/aot_file_manager.h" #include "ecmascript/compiler/pass_manager.h" +#include "ecmascript/compiler/aot_compilation_env.h" #include "ecmascript/ecma_string.h" #include "ecmascript/js_runtime_options.h" #include "ecmascript/log.h" @@ -110,6 +111,7 @@ int Main(const int argc, const char **argv) } { + AOTCompilationEnv aotCompilationEnv(vm); ecmascript::ThreadManagedScope managedScope(vm->GetJSThread()); LocalScope scope(vm); arg_list_t pandaFileNames {}; @@ -170,7 +172,7 @@ int Main(const int argc, const char **argv) .EnableInductionVariableAnalysis(cOptions.isEnableInductionVariableAnalysis_) .Build(); - PassManager passManager(vm, + PassManager passManager(&aotCompilationEnv, cOptions.triple_, cOptions.optLevel_, cOptions.relocMode_, @@ -193,7 +195,7 @@ int Main(const int argc, const char **argv) } vm->GetJSOptions().SetCompilerEnableLiteCG(isEnableLiteCG); - AOTFileGenerator generator(&log, &logList, vm, cOptions.triple_, isEnableLiteCG); + AOTFileGenerator generator(&log, &logList, &aotCompilationEnv, cOptions.triple_, isEnableLiteCG); CompileValidFiles(passManager, generator, ret, fileInfos); std::string appSignature = cPreprocessor.GetMainPkgArgsAppSignature(); diff --git a/ecmascript/compiler/aot_compiler_preprocessor.cpp b/ecmascript/compiler/aot_compiler_preprocessor.cpp index 378ab53385..2b5f4f58dd 100644 --- a/ecmascript/compiler/aot_compiler_preprocessor.cpp +++ b/ecmascript/compiler/aot_compiler_preprocessor.cpp @@ -250,7 +250,7 @@ void AotCompilerPreprocessor::RecordArrayElement(const CompilationOptions &cOpti JSPandaFile *jsPandaFile = fileInfo.jsPandaFile_.get(); PGOTypeManager *ptManager = vm_->GetJSThread()->GetCurrentEcmaContext()->GetPTManager(); ptManager->SetCurCompilationFile(jsPandaFile); - BytecodeInfoCollector collector(vm_, jsPandaFile, profilerDecoder_, cOptions.maxAotMethodSize_, + BytecodeInfoCollector collector(&aotCompilationEnv_, jsPandaFile, profilerDecoder_, cOptions.maxAotMethodSize_, cOptions.isEnableCollectLiteralInfo_); BCInfo &bytecodeInfo = collector.GetBytecodeInfo(); const PGOBCInfo *bcInfo = collector.GetPGOBCInfo(); @@ -284,7 +284,7 @@ void AotCompilerPreprocessor::GeneratePGOTypes(const CompilationOptions &cOption PGOTypeManager *ptManager = vm_->GetJSThread()->GetCurrentEcmaContext()->GetPTManager(); for (const AbcFileInfo &fileInfo : fileInfos_) { JSPandaFile *jsPandaFile = fileInfo.jsPandaFile_.get(); - BytecodeInfoCollector collector(vm_, jsPandaFile, profilerDecoder_, cOptions.maxAotMethodSize_, + BytecodeInfoCollector collector(&aotCompilationEnv_, jsPandaFile, profilerDecoder_, cOptions.maxAotMethodSize_, cOptions.isEnableCollectLiteralInfo_); PGOTypeParser parser(profilerDecoder_, ptManager); parser.CreatePGOType(collector); @@ -366,7 +366,7 @@ void AotCompilerPreprocessor::GenerateMethodMap(CompilationOptions &cOptions) jsPandaFileManager->EnumerateNonVirtualJSPandaFiles( [this, &cOptions] (std::shared_ptr jsPandaFilePtr) { JSPandaFile *jsPandaFile = jsPandaFilePtr.get(); - BytecodeInfoCollector collector(vm_, jsPandaFile, profilerDecoder_, cOptions.maxAotMethodSize_, + BytecodeInfoCollector collector(&aotCompilationEnv_, jsPandaFile, profilerDecoder_, cOptions.maxAotMethodSize_, cOptions.isEnableCollectLiteralInfo_); BCInfo &bytecodeInfo = collector.GetBytecodeInfo(); const auto &methodPcInfos = bytecodeInfo.GetMethodPcInfos(); diff --git a/ecmascript/compiler/aot_compiler_preprocessor.h b/ecmascript/compiler/aot_compiler_preprocessor.h index 46baf5b2ef..367b952533 100644 --- a/ecmascript/compiler/aot_compiler_preprocessor.h +++ b/ecmascript/compiler/aot_compiler_preprocessor.h @@ -21,6 +21,7 @@ #include "ecmascript/compiler/pass_manager.h" #include "ecmascript/ecma_vm.h" #include "macros.h" +#include "ecmascript/compiler/aot_compilation_env.h" namespace panda::ecmascript::kungfu { class OhosPkgArgs; @@ -99,7 +100,8 @@ public: runtimeOptions_(runtimeOptions), pkgsArgs_(pkgsArgs), profilerDecoder_(profilerDecoder), - pandaFileNames_(pandaFileNames) {}; + pandaFileNames_(pandaFileNames), + aotCompilationEnv_(vm) {}; ~AotCompilerPreprocessor() = default; @@ -206,6 +208,7 @@ private: arg_list_t &pandaFileNames_; CVector fileInfos_; CallMethodFlagMap callMethodFlagMap_; + AOTCompilationEnv aotCompilationEnv_; friend class OhosPkgArgs; }; } // namespace panda::ecmascript::kungfu diff --git a/ecmascript/compiler/bytecode_info_collector.cpp b/ecmascript/compiler/bytecode_info_collector.cpp index 31670a3845..faa0ab0ece 100644 --- a/ecmascript/compiler/bytecode_info_collector.cpp +++ b/ecmascript/compiler/bytecode_info_collector.cpp @@ -30,31 +30,31 @@ static T *InitializeMemory(T *mem, Args... args) return new (mem) T(std::forward(args)...); } -BytecodeInfoCollector::BytecodeInfoCollector(EcmaVM *vm, JSPandaFile *jsPandaFile, PGOProfilerDecoder &pfDecoder, +BytecodeInfoCollector::BytecodeInfoCollector(CompilationEnv *env, JSPandaFile *jsPandaFile, + PGOProfilerDecoder &pfDecoder, size_t maxAotMethodSize, bool enableCollectLiteralInfo) - : vm_(vm), + : compilationEnv_(env), jsPandaFile_(jsPandaFile), bytecodeInfo_(maxAotMethodSize), pfDecoder_(pfDecoder), - snapshotCPData_(vm, jsPandaFile, &pfDecoder), + snapshotCPData_(new SnapshotConstantPoolData(env->GetEcmaVM(), jsPandaFile, &pfDecoder)), enableCollectLiteralInfo_(enableCollectLiteralInfo) { - vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->SetBytecodeInfoCollector(this); + compilationEnv_->GetTSManager()->SetBytecodeInfoCollector(this); ProcessClasses(); ProcessEnvs(); } -BytecodeInfoCollector::BytecodeInfoCollector(EcmaVM *vm, JSPandaFile *jsPandaFile, JSHandle &jsFunction, +BytecodeInfoCollector::BytecodeInfoCollector(CompilationEnv *env, JSPandaFile *jsPandaFile, PGOProfilerDecoder &pfDecoder, bool enableCollectLiteralInfo) - : vm_(vm), + : compilationEnv_(env), jsPandaFile_(jsPandaFile), bytecodeInfo_(1), pfDecoder_(pfDecoder), - snapshotCPData_(vm, jsPandaFile, &pfDecoder), + snapshotCPData_(nullptr), // jit no need enableCollectLiteralInfo_(enableCollectLiteralInfo) { - vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->SetBytecodeInfoCollector(this); - ProcessMethod(jsFunction); + ProcessMethod(); ProcessEnvs(); } @@ -64,9 +64,12 @@ BytecodeInfoCollector::~BytecodeInfoCollector() delete envManager_; envManager_ = nullptr; } - auto tsManager = vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager(); - tsManager->PrintTypeInfo(jsPandaFile_); - tsManager->SetBytecodeInfoCollector(nullptr); + + if (compilationEnv_->IsAotCompiler()) { + auto tsManager = compilationEnv_->GetTSManager(); + tsManager->PrintTypeInfo(jsPandaFile_); + tsManager->SetBytecodeInfoCollector(nullptr); + } } void BytecodeInfoCollector::ProcessEnvs() @@ -105,7 +108,7 @@ void BytecodeInfoCollector::ProcessClasses() CollectFunctionTypeId(methodId); // Generate all constpool - vm_->GetJSThread()->GetCurrentEcmaContext()->FindOrCreateConstPool(jsPandaFile_, methodId); + compilationEnv_->FindOrCreateConstPool(jsPandaFile_, methodId); auto methodOffset = methodId.GetOffset(); CString name = reinterpret_cast(jsPandaFile_->GetStringData(mda.GetNameId()).data); @@ -164,33 +167,23 @@ void BytecodeInfoCollector::ProcessClasses() << methodIdx; } -void BytecodeInfoCollector::ProcessMethod(JSHandle &jsFunction) +void BytecodeInfoCollector::ProcessMethod() { auto &recordNames = bytecodeInfo_.GetRecordNames(); auto &methodPcInfos = bytecodeInfo_.GetMethodPcInfos(); + MethodLiteral *methodLiteral = compilationEnv_->GetMethodLiteral(); - Method *method = Method::Cast(jsFunction->GetMethod().GetTaggedObject()); const panda_file::File *pf = jsPandaFile_->GetPandaFile(); - panda_file::File::EntityId methodIdx = method->GetMethodId(); + panda_file::File::EntityId methodIdx = methodLiteral->GetMethodId(); panda_file::MethodDataAccessor mda(*pf, methodIdx); const CString recordName = jsPandaFile_->GetRecordNameWithBundlePack(methodIdx); recordNames.emplace_back(recordName); auto methodId = mda.GetMethodId(); CollectFunctionTypeId(methodId); - // Generate all constpool - [[maybe_unused]] JSTaggedValue constpool = - vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile_, methodId); - ASSERT(!constpool.IsHole()); - - auto methodOffset = methodId.GetOffset(); - CString name = reinterpret_cast(jsPandaFile_->GetStringData(mda.GetNameId()).data); - if (JSPandaFile::IsEntryOrPatch(name)) { - } - - MethodLiteral *methodLiteral = method->GetMethodLiteral(); ASSERT(jsPandaFile_->IsNewVersion()); + auto methodOffset = methodId.GetOffset(); auto codeId = mda.GetCodeId(); ASSERT(codeId.has_value()); panda_file::CodeDataAccessor codeDataAccessor(*pf, codeId.value()); @@ -204,20 +197,13 @@ void BytecodeInfoCollector::ProcessMethod(JSHandle &jsFunction) CollectMethodPcsFromBC(codeSize, insns, methodLiteral, classNameVec, 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]); // class Construct need to use new target, can not fastcall - if (method->GetFunctionKind() == FunctionKind::CLASS_CONSTRUCTOR) { + if (methodLiteral->GetFunctionKind() == FunctionKind::CLASS_CONSTRUCTOR) { methodLiteral->SetIsFastCall(false); bytecodeInfo_.ModifyMethodOffsetToCanFastCall(methodIdx.GetOffset(), false); } - // Collect import(infer-needed) and export relationship among all records. - CollectRecordReferenceREL(); - RearrangeInnerMethods(); } void BytecodeInfoCollector::CollectClassLiteralInfo(const MethodLiteral *method, @@ -228,7 +214,7 @@ void BytecodeInfoCollector::CollectClassLiteralInfo(const MethodLiteral *method, if (classOffsetVec.size() == classNameVec.size()) { for (uint32_t i = 0; i < classOffsetVec.size(); i++) { - vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->AddElementToClassNameMap( + compilationEnv_->GetTSManager()->AddElementToClassNameMap( jsPandaFile_, classOffsetVec[i], classNameVec[i]); } } @@ -322,8 +308,12 @@ void BytecodeInfoCollector::CollectMethodPcsFromBC(const uint32_t insSz, const u if (!fastCallFlag) { canFastCall = false; } - CollectModuleInfoFromBC(bcIns, method, recordName); - snapshotCPData_.Record(bcIns, bcIndex, recordName, method); + if (compilationEnv_->IsAotCompiler()) { + CollectModuleInfoFromBC(bcIns, method, recordName); + } + if (snapshotCPData_ != nullptr) { + snapshotCPData_->Record(bcIns, bcIndex, recordName, method); + } pgoBCInfo_.Record(bcIns, bcIndex, recordName, method); if (noGC && !bytecodes_.GetBytecodeMetaData(curPc).IsNoGC()) { noGC = false; @@ -633,10 +623,11 @@ void BytecodeInfoCollector::CollectImportIndexs(uint32_t methodOffset, uint32_t void BytecodeInfoCollector::CollectExportIndexs(const CString &recordName, uint32_t index) { - JSThread *thread = vm_->GetJSThread(); + ASSERT(compilationEnv_->IsAotCompiler()); + JSThread *thread = compilationEnv_->GetJSThread(); ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); CString exportLocalName = "*default*"; - ObjectFactory *objFactory = vm_->GetFactory(); + ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory(); [[maybe_unused]] EcmaHandleScope scope(thread); JSHandle currentModule = moduleManager->HostGetImportedModule(recordName); if (currentModule->GetLocalExportEntries().IsUndefined()) { @@ -675,7 +666,8 @@ void BytecodeInfoCollector::CollectExportIndexs(const CString &recordName, uint3 bool BytecodeInfoCollector::CheckExportNameAndClassType(const CString &recordName, const JSHandle &exportStr) { - auto tsManager = vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager(); + ASSERT(compilationEnv_->IsAotCompiler()); + auto tsManager = compilationEnv_->GetTSManager(); JSHandle 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 @@ -717,7 +709,8 @@ void BytecodeInfoCollector::CollectRecordReferenceREL() */ void BytecodeInfoCollector::CollectRecordImportInfo(const CString &recordName) { - auto thread = vm_->GetJSThread(); + ASSERT(compilationEnv_->IsAotCompiler()); + auto thread = compilationEnv_->GetJSThread(); ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); [[maybe_unused]] EcmaHandleScope scope(thread); JSHandle currentModule = moduleManager->HostGetImportedModule(recordName); @@ -747,7 +740,8 @@ void BytecodeInfoCollector::CollectRecordImportInfo(const CString &recordName) // For type infer under retranmission (export * from "xxx"), we collect the star export records in this function. void BytecodeInfoCollector::CollectRecordExportInfo(const CString &recordName) { - auto thread = vm_->GetJSThread(); + ASSERT(compilationEnv_->IsAotCompiler()); + auto thread = compilationEnv_->GetJSThread(); ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); [[maybe_unused]] EcmaHandleScope scope(thread); JSHandle currentModule = moduleManager->HostGetImportedModule(recordName); diff --git a/ecmascript/compiler/bytecode_info_collector.h b/ecmascript/compiler/bytecode_info_collector.h index 80e21bce4f..8c4063e6cf 100644 --- a/ecmascript/compiler/bytecode_info_collector.h +++ b/ecmascript/compiler/bytecode_info_collector.h @@ -21,6 +21,7 @@ #include "ecmascript/jspandafile/js_pandafile.h" #include "ecmascript/jspandafile/method_literal.h" #include "ecmascript/pgo_profiler/pgo_profiler_decoder.h" +#include "ecmascript/compiler/compilation_env.h" #include "libpandafile/bytecode_instruction-inl.h" namespace panda::ecmascript::kungfu { @@ -657,10 +658,10 @@ private: class BytecodeInfoCollector { public: - BytecodeInfoCollector(EcmaVM *vm, JSPandaFile *jsPandaFile, PGOProfilerDecoder &pfDecoder, + BytecodeInfoCollector(CompilationEnv *env, JSPandaFile *jsPandaFile, PGOProfilerDecoder &pfDecoder, size_t maxAotMethodSize, bool enableCollectLiteralInfo); - BytecodeInfoCollector(EcmaVM *vm, JSPandaFile *jsPandaFile, JSHandle &jsFunction, + BytecodeInfoCollector(CompilationEnv *env, JSPandaFile *jsPandaFile, PGOProfilerDecoder &pfDecoder, bool enableCollectLiteralInfo); ~BytecodeInfoCollector(); @@ -694,7 +695,7 @@ public: void StoreDataToGlobalData(SnapshotGlobalData &snapshotData) { - snapshotCPData_.StoreDataToGlobalData(snapshotData, GetSkippedMethodSet()); + snapshotCPData_->StoreDataToGlobalData(snapshotData, GetSkippedMethodSet()); } const std::set& GetSkippedMethodSet() const @@ -723,9 +724,9 @@ public: return jsPandaFile_; } - EcmaVM *GetVM() const + CompilationEnv *GetCompilationEnv() const { - return vm_; + return compilationEnv_; } LexEnvManager* GetEnvManager() const @@ -763,7 +764,7 @@ private: const CString GetEntryFunName(const std::string_view &entryPoint) const; void ProcessClasses(); - void ProcessMethod(JSHandle &jsFunction); + void ProcessMethod(); void RearrangeInnerMethods(); void CollectMethodPcsFromBC(const uint32_t insSz, const uint8_t *insArr, MethodLiteral *method, std::vector &classNameVec, const CString &recordName, @@ -793,12 +794,12 @@ private: void CollectRecordExportInfo(const CString &recordName); void MarkMethodNamespace(const uint32_t methodOffset); - EcmaVM *vm_; + CompilationEnv *compilationEnv_ {nullptr}; JSPandaFile *jsPandaFile_ {nullptr}; BCInfo bytecodeInfo_; PGOProfilerDecoder &pfDecoder_; PGOBCInfo pgoBCInfo_ {}; - SnapshotConstantPoolData snapshotCPData_; + std::unique_ptr snapshotCPData_; size_t methodInfoIndex_ {0}; bool enableCollectLiteralInfo_ {false}; std::set classDefBCIndexes_ {}; diff --git a/ecmascript/compiler/compilation_driver.cpp b/ecmascript/compiler/compilation_driver.cpp index b8d22e3337..0459fa0465 100644 --- a/ecmascript/compiler/compilation_driver.cpp +++ b/ecmascript/compiler/compilation_driver.cpp @@ -31,7 +31,7 @@ CompilationDriver::CompilationDriver(PGOProfilerDecoder &profilerDecoder, bool outputAsm, size_t maxMethodsInModule, const std::pair &compilerMethodsRange) - : vm_(collector->GetVM()), + : compilationEnv_(collector->GetCompilationEnv()), jsPandaFile_(collector->GetJSPandaFile()), pfDecoder_(profilerDecoder), collector_(collector), @@ -45,7 +45,9 @@ CompilationDriver::CompilationDriver(PGOProfilerDecoder &profilerDecoder, maxMethodsInModule_(maxMethodsInModule), optionMethodsRange_(compilerMethodsRange) { - vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->SetCompilationDriver(this); + if (compilationEnv_->IsAotCompiler()) { + compilationEnv_->GetTSManager()->SetCompilationDriver(this); + } if (!optionSelectMethods.empty() && !optionSkipMethods.empty()) { LOG_COMPILER(FATAL) << @@ -63,7 +65,9 @@ CompilationDriver::CompilationDriver(PGOProfilerDecoder &profilerDecoder, CompilationDriver::~CompilationDriver() { - vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->SetCompilationDriver(nullptr); + if (compilationEnv_->IsAotCompiler()) { + compilationEnv_->GetTSManager()->SetCompilationDriver(nullptr); + } } Module *CompilationDriver::GetModule() @@ -259,7 +263,7 @@ bool CompilationDriver::FilterOption(const std::mapGetJSThread()->GetCurrentEcmaContext()->GetPTManager(); + PGOTypeManager *ptManager = compilationEnv_->GetPTManager(); ptManager->SetCurCompilationFile(jsPandaFile_); } @@ -271,7 +275,7 @@ void CompilationDriver::StoreConstantPoolInfo() const bytecodeInfo_.AddSkippedMethod(x.first); } } - PGOTypeManager *ptManager = vm_->GetJSThread()->GetCurrentEcmaContext()->GetPTManager(); + PGOTypeManager *ptManager = compilationEnv_->GetPTManager(); ptManager->GetAOTSnapshot().StoreConstantPoolInfo(collector_); } diff --git a/ecmascript/compiler/compilation_driver.h b/ecmascript/compiler/compilation_driver.h index df9a3960b1..5c07ffd0ec 100644 --- a/ecmascript/compiler/compilation_driver.h +++ b/ecmascript/compiler/compilation_driver.h @@ -357,7 +357,7 @@ protected: void StoreConstantPoolInfo() const; - EcmaVM *vm_ {nullptr}; + CompilationEnv *compilationEnv_ {nullptr}; const JSPandaFile *jsPandaFile_ {nullptr}; PGOProfilerDecoder &pfDecoder_; BytecodeInfoCollector* collector_; @@ -399,14 +399,12 @@ public: Module *GetModule(); template - void CompileMethod(JSHandle &jsFunction, const Callback &cb) + void CompileMethod(const JSPandaFile *jsPandaFile, MethodLiteral *methodLiteral, const Callback &cb) { + SetCurrentCompilationFile(); for (auto mi : bytecodeInfo_.GetMethodList()) { bytecodeInfo_.AddSkippedMethod(mi.first); } - const JSPandaFile *jsPandaFile = Method::Cast(jsFunction->GetMethod().GetTaggedObject())->GetJSPandaFile(); - Method *method = Method::Cast(jsFunction->GetMethod().GetTaggedObject()); - MethodLiteral *methodLiteral = method->GetMethodLiteral(); const std::string methodName(MethodLiteral::GetMethodName(jsPandaFile, methodLiteral->GetMethodId())); auto &methodList = bytecodeInfo_.GetMethodList(); diff --git a/ecmascript/compiler/compilation_env.cpp b/ecmascript/compiler/compilation_env.cpp new file mode 100644 index 0000000000..dee2fee9cb --- /dev/null +++ b/ecmascript/compiler/compilation_env.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ecmascript/compiler/compilation_env.h" +#include "ecmascript/ecma_context.h" +#include "ecmascript/jspandafile/program_object.h" +#include "ecmascript/ts_types/ts_manager.h" + +namespace panda::ecmascript { +CompilationEnv::CompilationEnv(EcmaVM *vm) : vm_(vm), thread_(vm_->GetJSThread()), + tsManager_(nullptr), ptManager_(nullptr) { } + +NativeAreaAllocator *CompilationEnv::GetNativeAreaAllocator() const +{ + return vm_->GetNativeAreaAllocator(); +} +} // namespace panda::ecmascript diff --git a/ecmascript/compiler/compilation_env.h b/ecmascript/compiler/compilation_env.h new file mode 100644 index 0000000000..9f1a286fed --- /dev/null +++ b/ecmascript/compiler/compilation_env.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_COMPILER_COMPILATION_ENV_H +#define ECMASCRIPT_COMPILER_COMPILATION_ENV_H +#include "ecmascript/js_thread.h" +#include "ecmascript/js_handle.h" + +namespace panda::ecmascript { +namespace kungfu { +class PGOTypeManager; +}; +class TSManager; +class ConstantPool; +namespace pgo { +class PGOProfiler; +}; +class CompilationEnv { +public: + CompilationEnv(EcmaVM *vm); + virtual ~CompilationEnv() = default; + virtual bool IsJitCompiler() const + { + return false; + } + virtual bool IsAotCompiler() const + { + return false; + } + EcmaVM *GetEcmaVM() const + { + return vm_; + } + + JSThread *GetJSThread() const + { + return thread_; + } + + kungfu::PGOTypeManager *GetPTManager() const + { + return ptManager_; + } + + TSManager *GetTSManager() const + { + return tsManager_; + } + + NativeAreaAllocator *GetNativeAreaAllocator() const; + virtual JSRuntimeOptions &GetJSOptions() = 0; + + // thread + virtual const CMap &GetArrayHClassIndexMap() const = 0; + virtual const BuiltinHClassEntries &GetBuiltinHClassEntries() const = 0; + virtual JSHClass *GetBuiltinPrototypeHClass(BuiltinTypeId type) const = 0; + + // context + virtual JSTaggedValue FindConstpool(const JSPandaFile *jsPandaFile, panda_file::File::EntityId id) const = 0; + virtual JSTaggedValue FindConstpool(const JSPandaFile *jsPandaFile, int32_t index) const = 0; + virtual JSTaggedValue FindOrCreateUnsharedConstpool(const uint32_t methodOffset) const = 0; + virtual JSTaggedValue FindOrCreateUnsharedConstpool(JSTaggedValue sharedConstpool) const = 0; + virtual JSHandle FindOrCreateConstPool(const JSPandaFile *jsPandaFile, + panda_file::File::EntityId id) = 0; + virtual JSTaggedValue GetConstantPoolByMethodOffset(const uint32_t methodOffset) const = 0; + + // ConstantPool + virtual JSTaggedValue GetArrayLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const = 0; + virtual JSTaggedValue GetObjectLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const = 0; + virtual panda_file::File::EntityId GetIdFromCache(JSTaggedValue constpool, uint32_t index) const = 0; + virtual JSTaggedValue GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx) const = 0; + + // GlobalEnv + virtual JSHandle GetGlobalEnv() const = 0; + + // GlobalConstants + virtual const GlobalEnvConstants *GlobalConstants() const = 0; + + virtual JSThread *GetHostThread() const + { + ASSERT(0); + return nullptr; + } + + virtual JSPandaFile *GetJSPandaFile() const + { + ASSERT(0); + return nullptr; + } + + virtual MethodLiteral *GetMethodLiteral() const + { + ASSERT(0); + return nullptr; + } + +protected: + EcmaVM *vm_ {nullptr}; + JSThread *thread_ {nullptr}; + TSManager *tsManager_ {nullptr}; + kungfu::PGOTypeManager *ptManager_ {nullptr}; +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_COMPILER_COMPILATION_ENV_H \ No newline at end of file diff --git a/ecmascript/compiler/file_generators.cpp b/ecmascript/compiler/file_generators.cpp index 76e67a2f65..4d0b97f64b 100644 --- a/ecmascript/compiler/file_generators.cpp +++ b/ecmascript/compiler/file_generators.cpp @@ -436,8 +436,9 @@ Module* AOTFileGenerator::AddModule(const std::string &name, const std::string & { #ifdef COMPILE_MAPLE if (useLiteCG_) { - LMIRModule *irModule = new LMIRModule(vm_->GetNativeAreaAllocator(), name, logDebug, triple, isJit); - LiteCGAssembler *ass = new LiteCGAssembler(*irModule, vm_->GetJSOptions().GetCompilerCodegenOptions()); + LMIRModule *irModule = new LMIRModule(compilationEnv_->GetNativeAreaAllocator(), name, logDebug, triple, isJit); + LiteCGAssembler *ass = new LiteCGAssembler(*irModule, + compilationEnv_->GetJSOptions().GetCompilerCodegenOptions()); modulePackage_.emplace_back(Module(irModule, ass)); if (stackMapInfo_ == nullptr) { stackMapInfo_ = new LiteCGStackMapInfo(); @@ -445,7 +446,7 @@ Module* AOTFileGenerator::AddModule(const std::string &name, const std::string & return &modulePackage_.back(); } #endif - LLVMModule *m = new LLVMModule(vm_->GetNativeAreaAllocator(), name, logDebug, triple); + LLVMModule *m = new LLVMModule(compilationEnv_->GetNativeAreaAllocator(), name, logDebug, triple); LLVMAssembler *ass = new LLVMAssembler(m, option); modulePackage_.emplace_back(Module(m, ass)); if (stackMapInfo_ == nullptr) { @@ -500,7 +501,7 @@ void AOTFileGenerator::CompileLatestModuleThenDestroy() Module *latestModule = GetLatestModule(); #ifdef COMPILE_MAPLE static uint32_t lastModulePC = 0; - if (useLiteCG_ && vm_->IsEnableJit()) { + if (useLiteCG_ && compilationEnv_->IsJitCompiler()) { lastModulePC = 0; } if (latestModule->GetModule()->GetModuleKind() != MODULE_LLVM) { @@ -514,7 +515,7 @@ void AOTFileGenerator::CompileLatestModuleThenDestroy() uint32_t latestModuleIdx = GetModuleVecSize() - 1; { TimeScope timescope("LLVMIROpt", const_cast(log_)); - bool fastCompileMode = vm_->GetJSOptions().GetFastAOTCompileMode(); + bool fastCompileMode = compilationEnv_->GetJSOptions().GetFastAOTCompileMode(); latestModule->RunAssembler(*(log_), fastCompileMode); } { @@ -655,10 +656,10 @@ bool AOTFileGenerator::isAArch64() const void AOTFileGenerator::SaveSnapshotFile() { TimeScope timescope("LLVMCodeGenPass-AI", const_cast(log_)); - Snapshot snapshot(vm_); - const CString snapshotPath(vm_->GetJSOptions().GetAOTOutputFile().c_str()); + Snapshot snapshot(compilationEnv_->GetEcmaVM()); + const CString snapshotPath(compilationEnv_->GetJSOptions().GetAOTOutputFile().c_str()); const auto &methodToEntryIndexMap = aotInfo_.GetMethodToEntryIndexMap(); - PGOTypeManager *ptManager = vm_->GetJSThread()->GetCurrentEcmaContext()->GetPTManager(); + PGOTypeManager *ptManager = compilationEnv_->GetPTManager(); ptManager->GetAOTSnapshot().ResolveSnapshotData(methodToEntryIndexMap); CString aiPath = snapshotPath + AOTFileManager::FILE_EXTENSION_AI; diff --git a/ecmascript/compiler/file_generators.h b/ecmascript/compiler/file_generators.h index b33787a351..e47cee7be6 100644 --- a/ecmascript/compiler/file_generators.h +++ b/ecmascript/compiler/file_generators.h @@ -177,9 +177,9 @@ protected: class AOTFileGenerator : public FileGenerator { public: - AOTFileGenerator(const CompilerLog *log, const MethodLogList *logList, EcmaVM* vm, const std::string &triple, - bool useLiteCG = false) - : FileGenerator(log, logList), vm_(vm), cfg_(triple), useLiteCG_(useLiteCG) {} + AOTFileGenerator(const CompilerLog *log, const MethodLogList *logList, CompilationEnv *env, + const std::string &triple, bool useLiteCG = false) + : FileGenerator(log, logList), compilationEnv_(env), cfg_(triple), useLiteCG_(useLiteCG) {} ~AOTFileGenerator() override = default; @@ -222,7 +222,7 @@ private: AnFileInfo aotInfo_; CGStackMapInfo *stackMapInfo_ = nullptr; - EcmaVM* vm_; + CompilationEnv *compilationEnv_ {nullptr}; CompilationConfig cfg_; std::string curCompileFileName_; // MethodID->EntryIndex diff --git a/ecmascript/compiler/jit_compilation_env.cpp b/ecmascript/compiler/jit_compilation_env.cpp new file mode 100644 index 0000000000..1883c8ed97 --- /dev/null +++ b/ecmascript/compiler/jit_compilation_env.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#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 { +// jit +JitCompilationEnv::JitCompilationEnv(EcmaVM *jitVm, EcmaVM *jsVm, JSHandle &jsFunction) + : CompilationEnv(jitVm), hostThread_(jsVm->GetJSThread()), jsFunction_(jsFunction) + { + ptManager_ = hostThread_->GetCurrentEcmaContext()->GetPTManager(); + Method *method = Method::Cast(jsFunction->GetMethod().GetTaggedObject()); + jsPandaFile_ = const_cast(method->GetJSPandaFile()); + methodLiteral_ = method->GetMethodLiteral(); + } + +JSRuntimeOptions &JitCompilationEnv::GetJSOptions() +{ + return hostThread_->GetEcmaVM()->GetJSOptions(); +} + +const CMap &JitCompilationEnv::GetArrayHClassIndexMap() const +{ + return hostThread_->GetArrayHClassIndexMap(); +} + +const BuiltinHClassEntries &JitCompilationEnv::GetBuiltinHClassEntries() const +{ + return hostThread_->GetBuiltinHClassEntries(); +} + +JSHClass *JitCompilationEnv::GetBuiltinPrototypeHClass(BuiltinTypeId type) const +{ + return hostThread_->GetBuiltinPrototypeHClass(type); +} + +void JitCompilationEnv::SetTsManagerCompilationEnv() +{ + auto pt = hostThread_->GetCurrentEcmaContext()->GetPTManager(); + ptManager_ = pt; +} + +JSTaggedValue JitCompilationEnv::FindConstpool([[maybe_unused]] const JSPandaFile *jsPandaFile, + [[maybe_unused]] panda_file::File::EntityId id) const +{ + Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); + return method->GetConstantPool(); +} + +JSTaggedValue JitCompilationEnv::FindConstpool([[maybe_unused]] const JSPandaFile *jsPandaFile, + [[maybe_unused]] int32_t index) const +{ + Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); + return method->GetConstantPool(); +} + +JSTaggedValue JitCompilationEnv::FindOrCreateUnsharedConstpool([[maybe_unused]] const uint32_t methodOffset) const +{ + Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); + JSTaggedValue constpool = method->GetConstantPool(); + if (!ConstantPool::CheckUnsharedConstpool(constpool)) { + constpool = hostThread_->GetCurrentEcmaContext()->FindUnsharedConstpool(constpool); + return constpool; + } + ASSERT(constpool.IsHole()); + return constpool; +} + +JSTaggedValue JitCompilationEnv::FindOrCreateUnsharedConstpool([[maybe_unused]] JSTaggedValue sharedConstpool) const +{ + return FindOrCreateUnsharedConstpool(0); +} + +JSHandle JitCompilationEnv::FindOrCreateConstPool([[maybe_unused]] const JSPandaFile *jsPandaFile, + [[maybe_unused]] panda_file::File::EntityId id) +{ + ASSERT_PRINT(0, "jit should unreachable"); + return JSHandle(); +} + +JSTaggedValue JitCompilationEnv::GetConstantPoolByMethodOffset([[maybe_unused]] const uint32_t methodOffset) const +{ + Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); + return method->GetConstantPool(); +} + +JSTaggedValue JitCompilationEnv::GetArrayLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const +{ + return ConstantPool::GetLiteralFromCache(constpool, index, entry); +} + +JSTaggedValue JitCompilationEnv::GetObjectLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const +{ + return ConstantPool::GetLiteralFromCache(constpool, index, entry); +} + +panda_file::File::EntityId JitCompilationEnv::GetIdFromCache(JSTaggedValue constpool, uint32_t index) const +{ + return ConstantPool::GetIdFromCache(constpool, index); +} + +JSHandle JitCompilationEnv::GetGlobalEnv() const +{ + return hostThread_->GetEcmaVM()->GetGlobalEnv(); +} + +const GlobalEnvConstants *JitCompilationEnv::GlobalConstants() const +{ + return hostThread_->GlobalConstants(); +} + +JSTaggedValue JitCompilationEnv::GetStringFromConstantPool([[maybe_unused]] const uint32_t methodOffset, + [[maybe_unused]] const uint16_t cpIdx) const +{ + Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); + JSTaggedValue constpool = method->GetConstantPool(); + return ConstantPool::GetStringFromCacheForJit(GetJSThread(), constpool, cpIdx); +} +} // namespace panda::ecmascript diff --git a/ecmascript/compiler/jit_compilation_env.h b/ecmascript/compiler/jit_compilation_env.h new file mode 100644 index 0000000000..09e9d5126f --- /dev/null +++ b/ecmascript/compiler/jit_compilation_env.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_COMPILER_JIT_COMPILATION_ENV_H +#define ECMASCRIPT_COMPILER_JIT_COMPILATION_ENV_H +#include "ecmascript/compiler/compilation_env.h" + +namespace panda::ecmascript { +class JitCompilationEnv final : public CompilationEnv { +public: + JitCompilationEnv(EcmaVM *vm, EcmaVM *hVm, JSHandle &jsFunction); + ~JitCompilationEnv() = default; + bool IsJitCompiler() const override + { + return true; + } + JSRuntimeOptions &GetJSOptions() override; + // thread + const CMap &GetArrayHClassIndexMap() const override; + const BuiltinHClassEntries &GetBuiltinHClassEntries() const override; + JSHClass *GetBuiltinPrototypeHClass(BuiltinTypeId type) const override; + void SetTsManagerCompilationEnv(); + + // context + JSTaggedValue FindConstpool(const JSPandaFile *jsPandaFile, panda_file::File::EntityId id) const override; + JSTaggedValue FindConstpool(const JSPandaFile *jsPandaFile, int32_t index) const override; + JSTaggedValue FindOrCreateUnsharedConstpool(const uint32_t methodOffset) const override; + JSTaggedValue FindOrCreateUnsharedConstpool(JSTaggedValue sharedConstpool) const override; + JSHandle FindOrCreateConstPool(const JSPandaFile *jsPandaFile, + panda_file::File::EntityId id) override; + JSTaggedValue GetConstantPoolByMethodOffset(const uint32_t methodOffset) const override; + + // ConstantPool + JSTaggedValue GetArrayLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const override; + JSTaggedValue GetObjectLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const override; + panda_file::File::EntityId GetIdFromCache(JSTaggedValue constpool, uint32_t index) const override; + + // GlobalEnv + JSHandle GetGlobalEnv() const override; + + // GlobalConstants + const GlobalEnvConstants *GlobalConstants() const override; + + JSTaggedValue GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx) const override; + + JSThread *GetHostThread() const override + { + return hostThread_; + } + + JSPandaFile *GetJSPandaFile() const override + { + return jsPandaFile_; + } + + MethodLiteral *GetMethodLiteral() const override + { + return methodLiteral_; + } + +private: + JSThread *hostThread_ {nullptr}; + JSHandle jsFunction_; + JSPandaFile *jsPandaFile_ {nullptr}; + MethodLiteral *methodLiteral_ {nullptr}; +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_COMPILER_JIT_COMPILATION_ENV_H \ No newline at end of file diff --git a/ecmascript/compiler/jit_compiler.cpp b/ecmascript/compiler/jit_compiler.cpp index b2497dc937..75a44b3c5f 100644 --- a/ecmascript/compiler/jit_compiler.cpp +++ b/ecmascript/compiler/jit_compiler.cpp @@ -108,15 +108,8 @@ JitCompilerTask *JitCompilerTask::CreateJitCompilerTask(JitTask *jitTask) bool JitCompilerTask::Compile() { - TSManager *tsm = new (std::nothrow) TSManager(vm_); - if (tsm == nullptr) { - return false; - } - vm_->GetJSThread()->GetCurrentEcmaContext()->SetTSManager(tsm); - vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->Initialize(); - JitCompiler *jitCompiler = JitCompiler::GetInstance(); - auto jitPassManager = new (std::nothrow) JitPassManager(vm_, + auto jitPassManager = new (std::nothrow) JitPassManager(jitCompilationEnv_.get(), jitCompiler->GetJitOptions().triple_, jitCompiler->GetJitOptions().optLevel_, jitCompiler->GetJitOptions().relocMode_, @@ -129,13 +122,21 @@ bool JitCompilerTask::Compile() } passManager_.reset(jitPassManager); auto aotFileGenerator = new (std::nothrow) AOTFileGenerator(&jitCompiler->GetCompilerLog(), - &jitCompiler->GetLogList(), - vm_, jitCompiler->GetJitOptions().triple_, vm_->GetJSOptions().IsCompilerEnableLiteCG()); + &jitCompiler->GetLogList(), jitCompilationEnv_.get(), + jitCompiler->GetJitOptions().triple_, jitCompilationEnv_->GetJSOptions().IsCompilerEnableLiteCG()); if (aotFileGenerator == nullptr) { return false; } jitCodeGenerator_.reset(aotFileGenerator); - return passManager_->Compile(jsFunction_, *jitCodeGenerator_, offset_); + return passManager_->Compile(*jitCodeGenerator_, offset_); +} + +void JitCompilerTask::ReleaseJitPassManager() +{ + // release passManager before jitCompilerTask release, + // in future release JitCompilerTask when compile finish + JitPassManager *passManager = passManager_.release(); + delete passManager; } bool JitCompilerTask::Finalize(JitTask *jitTask) @@ -146,6 +147,7 @@ bool JitCompilerTask::Finalize(JitTask *jitTask) jitCodeGenerator_->JitCreateLitecgModule(); passManager_->RunCg(); jitCodeGenerator_->GetMemoryCodeInfos(jitTask->GetMachineCodeDesc()); + ReleaseJitPassManager(); return true; } diff --git a/ecmascript/compiler/jit_compiler.h b/ecmascript/compiler/jit_compiler.h index 4a29a1722b..c0c597250c 100644 --- a/ecmascript/compiler/jit_compiler.h +++ b/ecmascript/compiler/jit_compiler.h @@ -17,8 +17,10 @@ #define ECMASCRIPT_COMPILER_JIT_COMPILER_H #include "ecmascript/compiler/pass_manager.h" +#include "ecmascript/compiler/jit_compilation_env.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/jit/jit_task.h" +#include "ecmascript/pgo_profiler/pgo_profiler.h" namespace panda::ecmascript::kungfu { extern "C" { @@ -67,18 +69,21 @@ struct JitCompilationOptions { class JitCompilerTask final { public: - JitCompilerTask(JitTask *jitTask) : vm_(jitTask->GetVM()), jsFunction_(jitTask->GetJsFunction()), - offset_(jitTask->GetOffset()), passManager_(nullptr), jitCodeGenerator_(nullptr) { }; + JitCompilerTask(JitTask *jitTask) : jsFunction_(jitTask->GetJsFunction()), offset_(jitTask->GetOffset()), + jitCompilationEnv_(new JitCompilationEnv(jitTask->GetCompilerVM(), jitTask->GetHostVM(), jsFunction_)), + passManager_(nullptr), jitCodeGenerator_(nullptr) { }; static JitCompilerTask *CreateJitCompilerTask(JitTask *jitTask); bool Compile(); bool Finalize(JitTask *jitTask); + void ReleaseJitPassManager(); + private: - EcmaVM *vm_; JSHandle jsFunction_; int32_t offset_; + std::unique_ptr jitCompilationEnv_; std::unique_ptr passManager_; // need refact AOTFileGenerator to JitCodeGenerator std::unique_ptr jitCodeGenerator_; diff --git a/ecmascript/compiler/native_inline_lowering.cpp b/ecmascript/compiler/native_inline_lowering.cpp index 0d2d18ce60..24aef6cc69 100644 --- a/ecmascript/compiler/native_inline_lowering.cpp +++ b/ecmascript/compiler/native_inline_lowering.cpp @@ -46,11 +46,11 @@ std::optional> NativeInlineLowering::GetCallInfo(GateRef case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: return {{3U, true}}; case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8: { - CallRangeTypeInfoAccessor tia(thread_, circuit_, gate); + CallRangeTypeInfoAccessor tia(compilationEnv_, circuit_, gate); return {{tia.GetArgc(), false}}; } case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: { - CallThisRangeTypeInfoAccessor tia(thread_, circuit_, gate); + CallThisRangeTypeInfoAccessor tia(compilationEnv_, circuit_, gate); return {{tia.GetArgc(), true}}; } default: @@ -72,7 +72,7 @@ void NativeInlineLowering::RunNativeInlineLowering() continue; } auto [argc, skipThis] = optCallInfo.value(); - CallTypeInfoAccessor ctia(thread_, circuit_, gate); + CallTypeInfoAccessor ctia(compilationEnv_, circuit_, gate); BuiltinsStubCSigns::ID id = ctia.TryGetPGOBuiltinMethodId(); switch (id) { case BuiltinsStubCSigns::ID::StringFromCharCode: @@ -257,7 +257,7 @@ void NativeInlineLowering::TryInlineStringFromCharCode(GateRef gate, size_t argc if (argc != 1) { return; } - CallThis1TypeInfoAccessor tacc(thread_, circuit_, gate); + CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); Environment env(gate, circuit_, &builder_); if (!Uncheck()) { builder_.CallTargetCheck(gate, tacc.GetFunc(), @@ -281,7 +281,7 @@ void NativeInlineLowering::TryInlineNumberIsFinite(GateRef gate, size_t argc, bo if (argc != 1) { return; } - CallThis1TypeInfoAccessor tacc(thread_, circuit_, gate); + CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); Environment env(gate, circuit_, &builder_); if (!Uncheck()) { builder_.CallTargetCheck(gate, tacc.GetFunc(), @@ -299,7 +299,7 @@ void NativeInlineLowering::TryInlineNumberIsInteger(GateRef gate, size_t argc, b if (argc != 1) { return; } - CallThis1TypeInfoAccessor tacc(thread_, circuit_, gate); + CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); Environment env(gate, circuit_, &builder_); if (!Uncheck()) { builder_.CallTargetCheck(gate, tacc.GetFunc(), @@ -317,7 +317,7 @@ void NativeInlineLowering::TryInlineNumberIsNaN(GateRef gate, size_t argc, bool if (argc != 1) { return; } - CallThis1TypeInfoAccessor tacc(thread_, circuit_, gate); + CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); Environment env(gate, circuit_, &builder_); if (!Uncheck()) { builder_.CallTargetCheck(gate, tacc.GetFunc(), @@ -335,7 +335,7 @@ void NativeInlineLowering::TryInlineNumberIsSafeInteger(GateRef gate, size_t arg if (argc != 1) { return; } - CallThis1TypeInfoAccessor tacc(thread_, circuit_, gate); + CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); Environment env(gate, circuit_, &builder_); if (!Uncheck()) { builder_.CallTargetCheck(gate, tacc.GetFunc(), @@ -516,7 +516,7 @@ void NativeInlineLowering::TryInlineArrayBufferIsView(GateRef gate, if (argc != 1) { return; } - CallThis1TypeInfoAccessor tacc(thread_, circuit_, gate); + CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); Environment env(gate, circuit_, &builder_); if (!Uncheck()) { builder_.CallTargetCheck(gate, tacc.GetFunc(), builder_.IntPtr(static_cast(id)), {tacc.GetArg0()}); diff --git a/ecmascript/compiler/native_inline_lowering.h b/ecmascript/compiler/native_inline_lowering.h index 2c3a7ea6a4..56fc107c29 100644 --- a/ecmascript/compiler/native_inline_lowering.h +++ b/ecmascript/compiler/native_inline_lowering.h @@ -37,9 +37,9 @@ public: tsManager_(ctx->GetTSManager()), enableLog_(enableLog), methodName_(name), - nocheck_(ctx->GetEcmaVM()->GetJSOptions().IsCompilerNoCheck()), - traceInline_(ctx->GetEcmaVM()->GetJSOptions().GetTraceInline()), - thread_(ctx->GetEcmaVM()->GetJSThread()) {} + nocheck_(ctx->GetCompilationEnv()->GetJSOptions().IsCompilerNoCheck()), + traceInline_(ctx->GetCompilationEnv()->GetJSOptions().GetTraceInline()), + compilationEnv_(ctx->GetCompilationEnv()) {} ~NativeInlineLowering() = default; void RunNativeInlineLowering(); @@ -101,7 +101,7 @@ private: std::string methodName_; bool nocheck_; bool traceInline_; - const JSThread *thread_ {nullptr}; + const CompilationEnv *compilationEnv_ {nullptr}; }; } #endif // ECMASCRIPT_COMPILER_BUILTIN_INLINE_H diff --git a/ecmascript/compiler/ntype_bytecode_lowering.cpp b/ecmascript/compiler/ntype_bytecode_lowering.cpp index e1286903c9..c3cc7f8a97 100644 --- a/ecmascript/compiler/ntype_bytecode_lowering.cpp +++ b/ecmascript/compiler/ntype_bytecode_lowering.cpp @@ -18,6 +18,7 @@ #include "ecmascript/compiler/type_info_accessors.h" #include "ecmascript/dfx/vmstat/opt_code_profiler.h" #include "ecmascript/jspandafile/program_object.h" +#include "ecmascript/jit/jit.h" namespace panda::ecmascript::kungfu { @@ -56,8 +57,10 @@ void NTypeBytecodeLowering::Lower(GateRef gate) LowerNTypedCreateEmptyArray(gate); break; case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16: - case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16: - LowerNTypedCreateArrayWithBuffer(gate); + case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16: { + Jit::JitLockHolder lock(compilationEnv_, "LowerNTypedCreateArrayWithBuffer"); + LowerNTypedCreateArrayWithBuffer(gate); + } break; case EcmaOpcode::COPYRESTARGS_IMM8: case EcmaOpcode::WIDE_COPYRESTARGS_PREF_IMM16: @@ -100,8 +103,10 @@ void NTypeBytecodeLowering::Lower(GateRef gate) LowerStModuleVar(gate); break; case EcmaOpcode::STOWNBYNAME_IMM8_ID16_V8: - case EcmaOpcode::STOWNBYNAME_IMM16_ID16_V8: - LowerNTypedStOwnByName(gate); + case EcmaOpcode::STOWNBYNAME_IMM16_ID16_V8: { + Jit::JitLockHolder lock(compilationEnv_, "LowerNTypedStOwnByName"); + LowerNTypedStOwnByName(gate); + } break; default: break; @@ -206,7 +211,7 @@ void NTypeBytecodeLowering::LowerNTypedCreateArrayWithBuffer(GateRef gate) uint32_t cpIdx = static_cast(acc_.GetConstantValue(index)); auto methodOffset = acc_.TryGetMethodOffset(gate); uint32_t cpId = ptManager_->GetConstantPoolIDByMethodOffset(methodOffset); - JSTaggedValue cp = ptManager_->GetConstantPoolByMethodOffset(methodOffset); + JSTaggedValue cp = compilationEnv_->GetConstantPoolByMethodOffset(methodOffset); panda_file::File::EntityId id = ConstantPool::GetIdFromCache(cp, cpIdx); int elementIndex = ptManager_->GetElementsIndexByEntityId(id); @@ -351,10 +356,10 @@ void NTypeBytecodeLowering::LowerNTypedStOwnByName(GateRef gate) GateRef hclassGate = acc_.GetValueIn(receiver, 2); // 2: hclass offset JSTaggedValue taggedHClass(acc_.GetConstantValue(hclassGate)); GateRef stringId = acc_.GetValueIn(gate, 0); - JSTaggedValue key = TypeInfoAccessor::GetStringFromConstantPool(thread_, acc_.TryGetMethodOffset(gate), - acc_.GetConstantValue(stringId)); + JSTaggedValue key = compilationEnv_->GetStringFromConstantPool(acc_.TryGetMethodOffset(gate), + acc_.GetConstantValue(stringId)); JSHClass *hclass = JSHClass::Cast(taggedHClass.GetTaggedObject()); - int entry = JSHClass::FindPropertyEntry(thread_, hclass, key); + int entry = JSHClass::FindPropertyEntry(compilationEnv_->GetJSThread(), hclass, key); if (entry == -1) { return; } diff --git a/ecmascript/compiler/ntype_bytecode_lowering.h b/ecmascript/compiler/ntype_bytecode_lowering.h index 31ff0a5226..02d11f34b8 100644 --- a/ecmascript/compiler/ntype_bytecode_lowering.h +++ b/ecmascript/compiler/ntype_bytecode_lowering.h @@ -35,7 +35,7 @@ public: methodName_(name), glue_(acc_.GetGlueFromArgList()), argAcc_(circuit), - thread_(ctx->GetEcmaVM()->GetJSThread()) {} + compilationEnv_(ctx->GetCompilationEnv()) {} ~NTypeBytecodeLowering() = default; @@ -93,7 +93,7 @@ private: std::string methodName_; GateRef glue_ {Circuit::NullGate()}; ArgumentAccessor argAcc_; - const JSThread *thread_ {nullptr}; + const CompilationEnv *compilationEnv_ {nullptr}; }; } // panda::ecmascript::kungfu #endif // ECMASCRIPT_COMPILER_NTYPE_BYTECODE_LOWERING_H diff --git a/ecmascript/compiler/ntype_hcr_lowering.cpp b/ecmascript/compiler/ntype_hcr_lowering.cpp index 56bbeb5a1a..38ee4b3f44 100644 --- a/ecmascript/compiler/ntype_hcr_lowering.cpp +++ b/ecmascript/compiler/ntype_hcr_lowering.cpp @@ -14,6 +14,7 @@ */ #include "ecmascript/compiler/ntype_hcr_lowering.h" +#include "ecmascript/jit/jit.h" namespace panda::ecmascript::kungfu { GateRef NTypeHCRLowering::VisitGate(GateRef gate) @@ -21,11 +22,15 @@ GateRef NTypeHCRLowering::VisitGate(GateRef gate) GateRef glue = acc_.GetGlueFromArgList(); auto op = acc_.GetOpCode(gate); switch (op) { - case OpCode::CREATE_ARRAY: - LowerCreateArray(gate, glue); + case OpCode::CREATE_ARRAY: { + Jit::JitLockHolder lock(compilationEnv_, "LowerCreateArray"); + LowerCreateArray(gate, glue); + } break; - case OpCode::CREATE_ARRAY_WITH_BUFFER: - LowerCreateArrayWithBuffer(gate, glue); + case OpCode::CREATE_ARRAY_WITH_BUFFER: { + Jit::JitLockHolder lock(compilationEnv_, "LowerCreateArrayWithBuffer"); + LowerCreateArrayWithBuffer(gate, glue); + } break; case OpCode::CREATE_ARGUMENTS: LowerCreateArguments(gate, glue); @@ -89,7 +94,11 @@ void NTypeHCRLowering::LowerCreateArrayWithBuffer(GateRef gate, GateRef glue) GateRef literialElements = LoadFromConstPool(constpool, elementIndex, ConstantPool::AOT_ARRAY_INFO_INDEX); uint32_t cpIdVal = static_cast(acc_.GetConstantValue(cpId)); JSTaggedValue arr = GetArrayLiteralValue(cpIdVal, constPoolIndex); - JSHandle arrayHandle(thread_, arr); + if (arr.IsUndefined()) { + return; + } + DISALLOW_GARBAGE_COLLECTION; + JSArray *arrayHandle = JSArray::Cast(arr.GetTaggedObject()); TaggedArray *arrayLiteral = TaggedArray::Cast(arrayHandle->GetElements()); uint32_t literialLength = arrayLiteral->GetLength(); uint32_t arrayLength = acc_.GetArraySize(gate); @@ -168,14 +177,14 @@ GateRef NTypeHCRLowering::NewJSArrayLiteral(GateRef glue, GateRef gate, GateRef ElementsKind kind = acc_.GetArrayMetaDataAccessor(gate).GetElementsKind(); GateRef hclass = Circuit::NullGate(); if (!Elements::IsGeneric(kind)) { - auto hclassIndex = thread_->GetArrayHClassIndexMap().at(kind); + auto hclassIndex = compilationEnv_->GetArrayHClassIndexMap().at(kind); hclass = builder_.GetGlobalConstantValue(hclassIndex); } else { GateRef globalEnv = builder_.GetGlobalEnv(); hclass = builder_.GetGlobalEnvObjHClass(globalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX); } - JSHandle arrayFunc(thread_->GetEcmaVM()->GetGlobalEnv()->GetArrayFunction()); + JSHandle arrayFunc(compilationEnv_->GetGlobalEnv()->GetArrayFunction()); JSTaggedValue protoOrHClass = arrayFunc->GetProtoOrHClass(); JSHClass *arrayHC = JSHClass::Cast(protoOrHClass.GetTaggedObject()); size_t arraySize = arrayHC->GetObjectSize(); diff --git a/ecmascript/compiler/ntype_hcr_lowering.h b/ecmascript/compiler/ntype_hcr_lowering.h index a524ee37f4..9adb5306ee 100644 --- a/ecmascript/compiler/ntype_hcr_lowering.h +++ b/ecmascript/compiler/ntype_hcr_lowering.h @@ -27,7 +27,7 @@ public: : PassVisitor(circuit, chunk, visitor), circuit_(circuit), acc_(circuit), - thread_(ctx->GetEcmaVM()->GetJSThread()), + compilationEnv_(ctx->GetCompilationEnv()), builder_(circuit, ctx->GetCompilerConfig()), dependEntry_(circuit->GetDependRoot()), jsPandaFile_(ctx->GetJSPandaFile()), @@ -64,20 +64,19 @@ private: JSTaggedValue GetConstantpoolValue(uint32_t cpId) { - return thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile_, cpId); + return compilationEnv_->FindConstpool(jsPandaFile_, cpId); } JSTaggedValue GetArrayLiteralValue(uint32_t cpId, uint32_t cpIdx) { JSTaggedValue cp = GetConstantpoolValue(cpId); - JSTaggedValue unsharedCp = thread_->GetCurrentEcmaContext()->FindOrCreateUnsharedConstpool(cp); - return ConstantPool::GetLiteralFromCache( - thread_, unsharedCp, cpIdx, recordName_); + JSTaggedValue unsharedCp = compilationEnv_->FindOrCreateUnsharedConstpool(cp); + return compilationEnv_->GetArrayLiteralFromCache(unsharedCp, cpIdx, recordName_); } Circuit *circuit_ {nullptr}; GateAccessor acc_; - JSThread *thread_ {nullptr}; + CompilationEnv *compilationEnv_ {nullptr}; CircuitBuilder builder_; GateRef dependEntry_; const JSPandaFile *jsPandaFile_ {nullptr}; diff --git a/ecmascript/compiler/object_access_helper.cpp b/ecmascript/compiler/object_access_helper.cpp index cf1dc94a37..987e59ccbf 100644 --- a/ecmascript/compiler/object_access_helper.cpp +++ b/ecmascript/compiler/object_access_helper.cpp @@ -21,6 +21,7 @@ namespace panda::ecmascript::kungfu { bool ObjectAccessHelper::Compute(ChunkVector &infos) { + ASSERT(compilationEnv_->IsAotCompiler()); ASSERT(infos.empty()); bool result = false; ObjectAccessInfo info(type_); @@ -55,7 +56,7 @@ bool ObjectAccessHelper::ComputeForClassInstance(ObjectAccessInfo &info) return false; } - PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(thread_, hclass, key_); + PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(compilationEnv_->GetJSThread(), hclass, key_); info.Set(hclassIndex, plr); if (IsLoading()) { @@ -80,7 +81,7 @@ bool ObjectAccessHelper::ComputeForClassOrObject(ObjectAccessInfo &info) } JSHClass *hclass = JSHClass::Cast(tsManager_->GetAOTHClassInfoByIndex(hclassIndex).GetTaggedObject()); - PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(thread_, hclass, key_); + PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(compilationEnv_->GetJSThread(), hclass, key_); info.Set(hclassIndex, plr); if (IsLoading()) { @@ -128,7 +129,7 @@ bool ObjectAccessHelper::ComputePolymorphism(ChunkVector &info bool PGOObjectAccessHelper::ComputeForClassInstance(PGOObjectAccessInfo &info) { auto type = info.Type(); - PGOTypeManager *ptManager = thread_->GetCurrentEcmaContext()->GetPTManager(); + PGOTypeManager *ptManager = compilationEnv_->GetPTManager(); int hclassIndex = static_cast(ptManager->GetHClassIndexByProfileType(type)); if (hclassIndex == -1) { return false; @@ -136,7 +137,7 @@ bool PGOObjectAccessHelper::ComputeForClassInstance(PGOObjectAccessInfo &info) JSHClass *hclass = JSHClass::Cast(ptManager->QueryHClass(type.first, type.second).GetTaggedObject()); - PropertyLookupResult plr = JSHClass::LookupPropertyInPGOHClass(thread_, hclass, key_); + PropertyLookupResult plr = JSHClass::LookupPropertyInPGOHClass(compilationEnv_->GetJSThread(), hclass, key_); info.Set(hclassIndex, plr); if (IsLoading()) { @@ -149,7 +150,7 @@ bool PGOObjectAccessHelper::ComputeForClassInstance(PGOObjectAccessInfo &info) bool PGOObjectAccessHelper::ClassInstanceIsCallable(PGOObjectAccessInfo &info) { auto type = info.Type(); - PGOTypeManager *ptManager = thread_->GetCurrentEcmaContext()->GetPTManager(); + PGOTypeManager *ptManager = compilationEnv_->GetPTManager(); int hclassIndex = static_cast(ptManager->GetHClassIndexByProfileType(type)); if (hclassIndex == -1) { return false; diff --git a/ecmascript/compiler/object_access_helper.h b/ecmascript/compiler/object_access_helper.h index 81de21e6c3..7037a3a37b 100644 --- a/ecmascript/compiler/object_access_helper.h +++ b/ecmascript/compiler/object_access_helper.h @@ -99,10 +99,10 @@ public: STORE }; - explicit ObjectAccessHelper(TSManager *tsManager, AccessMode mode, GateRef receiver, GateType type, + explicit ObjectAccessHelper(CompilationEnv *env, AccessMode mode, GateRef receiver, GateType type, JSTaggedValue key, GateRef value) - : tsManager_(tsManager), - thread_(tsManager_->GetThread()), + : tsManager_(env->GetTSManager()), + compilationEnv_(env), mode_(mode), receiver_(receiver), type_(type), @@ -139,7 +139,7 @@ private: bool ComputePolymorphism(ChunkVector &infos); TSManager *tsManager_ {nullptr}; - const JSThread *thread_ {nullptr}; + const CompilationEnv *compilationEnv_ {nullptr}; AccessMode mode_ {}; GateRef receiver_ {Circuit::NullGate()}; GateType type_ {GateType::AnyType()}; @@ -156,10 +156,10 @@ public: STORE }; - explicit PGOObjectAccessHelper(TSManager *tsManager, AccessMode mode, GateRef receiver, ProfileTyper type, + explicit PGOObjectAccessHelper(CompilationEnv *env, AccessMode mode, GateRef receiver, ProfileTyper type, JSTaggedValue key, GateRef value) - : tsManager_(tsManager), - thread_(tsManager_->GetThread()), + : tsManager_(env->GetTSManager()), + compilationEnv_(env), mode_(mode), receiver_(receiver), holder_(receiver), @@ -204,7 +204,7 @@ public: private: TSManager *tsManager_ {nullptr}; - const JSThread *thread_ {nullptr}; + const CompilationEnv *compilationEnv_ {nullptr}; AccessMode mode_ {}; GateRef receiver_ {Circuit::NullGate()}; GateRef holder_ {Circuit::NullGate()}; diff --git a/ecmascript/compiler/pass.h b/ecmascript/compiler/pass.h index 36984b0557..868ce8a3fd 100644 --- a/ecmascript/compiler/pass.h +++ b/ecmascript/compiler/pass.h @@ -16,6 +16,8 @@ #ifndef ECMASCRIPT_COMPILER_PASS_H #define ECMASCRIPT_COMPILER_PASS_H +#include "ecmascript/compiler/aot_compilation_env.h" +#include "ecmascript/compiler/jit_compilation_env.h" #include "ecmascript/compiler/async_function_lowering.h" #include "ecmascript/compiler/bytecode_circuit_builder.h" #include "ecmascript/compiler/codegen/llvm/llvm_codegen.h" @@ -282,7 +284,8 @@ public: 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->GetMethodName(), &chunk, enableLog, + data->GetPassContext()->GetCompilationEnv()); pgoTypeInfer.Run(); return true; } @@ -309,7 +312,7 @@ public: } TimeScope timescope("EscapeAnalysisPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); bool enableLog = data->GetLog()->EnableMethodCIRLog(); - JSRuntimeOptions runtimeOption = data->GetPassContext()->GetEcmaVM()->GetJSOptions(); + JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions(); Chunk chunk(data->GetNativeAreaAllocator()); CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); EscapeAnalysis escapeAnalysis(data->GetCircuit(), &visitor, &chunk, runtimeOption.GetTraceEscapeAnalysis()); @@ -336,7 +339,7 @@ public: TimeScope timescope("InductionVariableAnalysisPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); bool enableLog = data->GetLog()->EnableMethodCIRLog(); - JSRuntimeOptions runtimeOption = data->GetPassContext()->GetEcmaVM()->GetJSOptions(); + JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions(); Chunk chunk(data->GetNativeAreaAllocator()); InductionVariableAnalysis inductionVariableAnalysis(data->GetCircuit(), data->GetPassContext(), enableLog, data->GetMethodName(), &chunk, @@ -442,6 +445,7 @@ public: Chunk chunk(data->GetNativeAreaAllocator()); CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); TypedHCRLowering lowering(data->GetCircuit(), + data->GetPassContext()->GetCompilationEnv(), &visitor, data->GetCompilerConfig(), data->GetTSManager(), @@ -686,7 +690,7 @@ public: bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog(); Chunk chunk(data->GetNativeAreaAllocator()); CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); - JSRuntimeOptions runtimeOption = data->GetPassContext()->GetEcmaVM()->GetJSOptions(); + JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions(); EarlyElimination earlyElimination(data->GetCircuit(), &visitor, &chunk, runtimeOption.IsEnableMemoryAnalysis()); visitor.AddPass(&earlyElimination); visitor.VisitGraph(); @@ -724,7 +728,7 @@ public: if (!passOptions->EnableTypeLowering() || !passOptions->EnableValueNumbering()) { return false; } - JSRuntimeOptions runtimeOption = data->GetPassContext()->GetEcmaVM()->GetJSOptions(); + JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions(); TimeScope timescope("ValueNumberingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); Chunk chunk(data->GetNativeAreaAllocator()); bool enableLog = data->GetLog()->EnableMethodCIRLog(); @@ -743,7 +747,7 @@ class InstructionCombinePass { public: bool Run(PassData *data) { - JSRuntimeOptions runtimeOption = data->GetPassContext()->GetEcmaVM()->GetJSOptions(); + JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions(); if (runtimeOption.IsEnableInstrcutionCombine()) { TimeScope timescope("InstructionCombinePass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); @@ -799,7 +803,7 @@ public: Chunk chunk(data->GetNativeAreaAllocator()); bool enableLog = data->GetLog()->EnableMethodCIRLog(); bool licm = data->GetPassOptions()->EnableOptLoopInvariantCodeMotion(); - bool liteCG = data->GetPassContext()->GetEcmaVM()->GetJSOptions().IsCompilerEnableLiteCG(); + bool liteCG = data->GetPassContext()->GetCompilationEnv()->GetJSOptions().IsCompilerEnableLiteCG(); GraphLinearizer(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, false, licm, liteCG) .Run(data->GetCfg()); PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk).Run(data->GetCfg()); diff --git a/ecmascript/compiler/pass_manager.cpp b/ecmascript/compiler/pass_manager.cpp index ec41790e49..7617b11c16 100644 --- a/ecmascript/compiler/pass_manager.cpp +++ b/ecmascript/compiler/pass_manager.cpp @@ -22,27 +22,25 @@ #include "ecmascript/log.h" #include "ecmascript/log_wrapper.h" #include "ecmascript/pgo_profiler/pgo_profiler_manager.h" +#include "ecmascript/jit/jit.h" namespace panda::ecmascript::kungfu { using PGOProfilerManager = pgo::PGOProfilerManager; -bool JitPassManager::Compile(JSHandle &jsFunction, AOTFileGenerator &gen, int32_t osrOffset) +bool JitPassManager::Compile(AOTFileGenerator &gen, int32_t osrOffset) { - [[maybe_unused]] EcmaHandleScope handleScope(vm_->GetJSThread()); - const JSPandaFile *jsPandaFile = Method::Cast(jsFunction->GetMethod().GetTaggedObject())->GetJSPandaFile(); + const JSPandaFile *jsPandaFile = compilationEnv_->GetJSPandaFile(); + MethodLiteral *methodLiteral = compilationEnv_->GetMethodLiteral(); - collector_ = new BytecodeInfoCollector(vm_, const_cast(jsPandaFile), - jsFunction, profilerDecoder_, passOptions_->EnableCollectLiteralInfo()); + collector_ = new BytecodeInfoCollector(compilationEnv_, const_cast(jsPandaFile), + profilerDecoder_, passOptions_->EnableCollectLiteralInfo()); std::string fileName = jsPandaFile->GetFileName(); - if (!IsReleasedPandaFile(jsPandaFile)) { - LOG_COMPILER(ERROR) << "The input panda file [" << fileName << "] is debuggable version."; - } gen.SetCurrentCompileFileName(jsPandaFile->GetNormalizedFileDesc()); lOptions_ = new LOptions(optLevel_, FPFlag::RESERVE_FP, relocMode_); cmpDriver_ = new JitCompilationDriver(profilerDecoder_, collector_, - vm_->GetJSOptions().GetCompilerSelectMethods(), - vm_->GetJSOptions().GetCompilerSkipMethods(), + compilationEnv_->GetJSOptions().GetCompilerSelectMethods(), + compilationEnv_->GetJSOptions().GetCompilerSkipMethods(), &gen, fileName, triple_, @@ -50,15 +48,15 @@ bool JitPassManager::Compile(JSHandle &jsFunction, AOTFileGenerator log_, log_->OutputASM(), maxMethodsInModule_, - vm_->GetJSOptions().GetCompilerMethodsRange()); - cmpDriver_->CompileMethod(jsFunction, [this, &fileName, &osrOffset] (const CString recordName, + compilationEnv_->GetJSOptions().GetCompilerMethodsRange()); + cmpDriver_->CompileMethod(jsPandaFile, methodLiteral, [this, &fileName, &osrOffset] (const CString recordName, const std::string &methodName, MethodLiteral *methodLiteral, uint32_t methodOffset, const MethodPcInfo &methodPCInfo, MethodInfo &methodInfo, Module *m) { - if (vm_->GetJSOptions().GetTraceJIT()) { + if (compilationEnv_->GetJSOptions().GetTraceJIT()) { LOG_COMPILER(INFO) << "JIT Compile Method Start: " << methodName << ", " << methodOffset << "\n"; } ctx_ = new PassContext(triple_, log_, collector_, m->GetModule(), &profilerDecoder_); @@ -79,13 +77,14 @@ bool JitPassManager::Compile(JSHandle &jsFunction, AOTFileGenerator LOG_COMPILER(INFO) << "record: " << recordName << " has no types"; } - circuit_ = new Circuit(vm_->GetNativeAreaAllocator(), ctx_->GetAOTModule()->GetDebugInfo(), + circuit_ = new Circuit(compilationEnv_->GetNativeAreaAllocator(), ctx_->GetAOTModule()->GetDebugInfo(), fullName.c_str(), cmpCfg->Is64Bit(), FrameType::OPTIMIZED_JS_FUNCTION_FRAME); PGOProfilerDecoder *decoder = passOptions_->EnableOptPGOType() ? &profilerDecoder_ : nullptr; builder_ = new BytecodeCircuitBuilder(jsPandaFile, methodLiteral, methodPCInfo, circuit_, ctx_->GetByteCodes(), enableMethodLog && log_->OutputCIR(), passOptions_->EnableTypeLowering(), fullName, recordName, decoder, false); + builder_->SetOsrOffset(osrOffset); { TimeScope timeScope("BytecodeToCircuit", methodName, methodOffset, log_); @@ -94,31 +93,38 @@ bool JitPassManager::Compile(JSHandle &jsFunction, AOTFileGenerator data_ = new PassData(builder_, circuit_, ctx_, log_, fullName, &methodInfo, hasTypes, recordName, methodLiteral, methodOffset, nullptr, CVector {}, - vm_->GetNativeAreaAllocator(), decoder, passOptions_); + compilationEnv_->GetNativeAreaAllocator(), decoder, passOptions_); PassRunner pipeline(data_); - if (data_->GetMethodLiteral()->HasDebuggerStmt()) { - data_->AbortCompilation(); - return; - } + pipeline.RunPass(); pipeline.RunPass(); if (builder_->EnableLoopOptimization()) { pipeline.RunPass(); pipeline.RunPass(); } - pipeline.RunPass(); - pipeline.RunPass(); - pipeline.RunPass(); + // support when remove tsmanager in pass + const bool enablepass = false; + if (enablepass) { + { + Jit::JitLockHolder lock(compilationEnv_, "PGOTypeInferPass"); + pipeline.RunPass(); + } + { + Jit::JitLockHolder lock(compilationEnv_, "TSClassAnalysisPass"); + pipeline.RunPass(); + } + { + Jit::JitLockHolder lock(compilationEnv_, "TSInlineLoweringPass"); + pipeline.RunPass(); + } + } + pipeline.RunPass(); pipeline.RunPass(); pipeline.RunPass(); pipeline.RunPass(); pipeline.RunPass(); pipeline.RunPass(); - if (data_->IsTypeAbort()) { - data_->AbortCompilation(); - return; - } pipeline.RunPass(); pipeline.RunPass(); pipeline.RunPass(); @@ -152,41 +158,41 @@ bool JitPassManager::RunCg() JitPassManager::~JitPassManager() { - if (collector_ != nullptr) { - delete collector_; - collector_ = nullptr; - } - if (lOptions_ != nullptr) { - delete lOptions_; - lOptions_ = nullptr; - } - if (cmpDriver_ != nullptr) { - delete cmpDriver_; - cmpDriver_ = nullptr; - } - if (ctx_ != nullptr) { - delete ctx_; - ctx_ = nullptr; - } - if (circuit_ != nullptr) { - delete circuit_; - circuit_ = nullptr; + if (data_ != nullptr) { + delete data_; + data_ = nullptr; } if (builder_ != nullptr) { delete builder_; builder_ = nullptr; } - if (data_ != nullptr) { - delete data_; - data_ = nullptr; + if (circuit_ != nullptr) { + delete circuit_; + circuit_ = nullptr; + } + if (ctx_ != nullptr) { + delete ctx_; + ctx_ = nullptr; + } + if (cmpDriver_ != nullptr) { + delete cmpDriver_; + cmpDriver_ = nullptr; + } + if (lOptions_ != nullptr) { + delete lOptions_; + lOptions_ = nullptr; + } + if (collector_ != nullptr) { + delete collector_; + collector_ = nullptr; } } bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName, AOTFileGenerator &gen) { - [[maybe_unused]] EcmaHandleScope handleScope(vm_->GetJSThread()); + [[maybe_unused]] EcmaHandleScope handleScope(compilationEnv_->GetJSThread()); - BytecodeInfoCollector collector(vm_, jsPandaFile, profilerDecoder_, + BytecodeInfoCollector collector(compilationEnv_, jsPandaFile, profilerDecoder_, maxAotMethodSize_, passOptions_->EnableCollectLiteralInfo()); // Checking released/debuggable pandafile uses method literals, which are initialized in BytecodeInfoCollector, // should after it. @@ -198,8 +204,8 @@ bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName, LOptions lOptions(optLevel_, FPFlag::RESERVE_FP, relocMode_); CompilationDriver cmpDriver(profilerDecoder_, &collector, - vm_->GetJSOptions().GetCompilerSelectMethods(), - vm_->GetJSOptions().GetCompilerSkipMethods(), + compilationEnv_->GetJSOptions().GetCompilerSelectMethods(), + compilationEnv_->GetJSOptions().GetCompilerSkipMethods(), &gen, fileName, triple_, @@ -207,7 +213,7 @@ bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName, log_, log_->OutputASM(), maxMethodsInModule_, - vm_->GetJSOptions().GetCompilerMethodsRange()); + compilationEnv_->GetJSOptions().GetCompilerMethodsRange()); cmpDriver.Run([this, &fileName, &collector](const CString recordName, const std::string &methodName, @@ -233,7 +239,7 @@ bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName, LOG_COMPILER(INFO) << "record: " << recordName << " has no types"; } - Circuit circuit(vm_->GetNativeAreaAllocator(), ctx.GetAOTModule()->GetDebugInfo(), + Circuit circuit(compilationEnv_->GetNativeAreaAllocator(), ctx.GetAOTModule()->GetDebugInfo(), fullName.c_str(), cmpCfg->Is64Bit(), FrameType::OPTIMIZED_JS_FUNCTION_FRAME); PGOProfilerDecoder *decoder = passOptions_->EnableOptPGOType() ? &profilerDecoder_ : nullptr; @@ -248,7 +254,7 @@ bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName, PassData data(&builder, &circuit, &ctx, log_, fullName, &methodInfo, hasTypes, recordName, methodLiteral, methodOffset, callMethodFlagMap_, fileInfos_, - vm_->GetNativeAreaAllocator(), decoder, passOptions_, + compilationEnv_->GetNativeAreaAllocator(), decoder, passOptions_, optBCRange_); PassRunner pipeline(&data); if (data.GetMethodLiteral()->HasDebuggerStmt()) { diff --git a/ecmascript/compiler/pass_manager.h b/ecmascript/compiler/pass_manager.h index 637e85da6f..2284722c2e 100644 --- a/ecmascript/compiler/pass_manager.h +++ b/ecmascript/compiler/pass_manager.h @@ -17,6 +17,7 @@ #define ECMASCRIPT_COMPILER_PASS_MANAGER_H #include "ecmascript/compiler/aot_compiler_preprocessor.h" +#include "ecmascript/compiler/jit_compilation_env.h" #include "ecmascript/compiler/bytecode_info_collector.h" #include "ecmascript/compiler/compiler_log.h" #include "ecmascript/compiler/file_generators.h" @@ -34,17 +35,16 @@ class CompilationConfig; class PassData; class CallMethodFlagMap; struct AbcFileInfo; - class PassContext { public: PassContext(const std::string &triple, CompilerLog *log, BytecodeInfoCollector* collector, IRModule *aotModule, PGOProfilerDecoder *decoder) - : vm_(collector->GetVM()), + : compilationEnv_(collector->GetCompilationEnv()), bcInfoCollector_(collector), - tsManager_(vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()), + tsManager_(compilationEnv_->GetTSManager()), bytecodes_(collector->GetByteCodes()), lexEnvManager_(bcInfoCollector_->GetEnvManager()), - cmpCfg_(triple, &vm_->GetJSOptions()), + cmpCfg_(triple, &compilationEnv_->GetJSOptions()), log_(log), jsPandaFile_(collector->GetJSPandaFile()), aotModule_(aotModule), @@ -59,7 +59,7 @@ public: PGOTypeManager* GetPTManager() const { - return vm_->GetJSThread()->GetCurrentEcmaContext()->GetPTManager(); + return compilationEnv_->GetPTManager(); } Bytecodes* GetByteCodes() @@ -114,12 +114,12 @@ public: NativeAreaAllocator *GetNativeAreaAllocator() const { - return vm_->GetNativeAreaAllocator(); + return compilationEnv_->GetNativeAreaAllocator(); } - EcmaVM *GetEcmaVM() const + CompilationEnv *GetCompilationEnv() const { - return vm_; + return compilationEnv_; } PGOProfilerDecoder *GetPfDecoder() const @@ -128,7 +128,7 @@ public: } private: - EcmaVM *vm_ {nullptr}; + CompilationEnv *compilationEnv_ {nullptr}; BytecodeInfoCollector *bcInfoCollector_ {nullptr}; TSManager *tsManager_ {nullptr}; Bytecodes *bytecodes_ {nullptr}; @@ -142,15 +142,15 @@ private: class PassManager { public: - explicit PassManager(EcmaVM* vm, std::string &triple, size_t optLevel, size_t relocMode, + explicit PassManager(CompilationEnv *env, std::string &triple, size_t optLevel, size_t relocMode, CompilerLog *log, AotMethodLogList *logList, size_t maxAotMethodSize, size_t maxMethodsInModule, PGOProfilerDecoder &profilerDecoder, PassOptions *passOptions, const CallMethodFlagMap *callMethodFlagMap, const CVector &fileInfos, std::string optBCRange) - : vm_(vm), triple_(triple), optLevel_(optLevel), relocMode_(relocMode), log_(log), + : compilationEnv_(env), triple_(triple), optLevel_(optLevel), relocMode_(relocMode), log_(log), logList_(logList), maxAotMethodSize_(maxAotMethodSize), maxMethodsInModule_(maxMethodsInModule), profilerDecoder_(profilerDecoder), passOptions_(passOptions), callMethodFlagMap_(callMethodFlagMap), fileInfos_(fileInfos), optBCRange_(optBCRange) { - enableJITLog_ = vm_->GetJSOptions().GetTraceJIT(); + enableJITLog_ = compilationEnv_->GetJSOptions().GetTraceJIT(); }; virtual ~PassManager() = default; @@ -159,7 +159,7 @@ public: protected: bool IsReleasedPandaFile(const JSPandaFile *jsPandaFile) const; - EcmaVM *vm_ {nullptr}; + CompilationEnv *compilationEnv_ {nullptr}; std::string triple_ {}; size_t optLevel_ {3}; // 3 : default backend optimization level size_t relocMode_ {2}; // 2 : default relocation mode-- PIC @@ -177,13 +177,13 @@ protected: class JitPassManager : public PassManager { public: - JitPassManager(EcmaVM* vm, std::string &triple, size_t optLevel, size_t relocMode, + JitPassManager(JitCompilationEnv *env, std::string &triple, size_t optLevel, size_t relocMode, CompilerLog *log, AotMethodLogList *logList, PGOProfilerDecoder &profilerDecoder, PassOptions *passOptions) - : PassManager(vm, triple, optLevel, relocMode, log, logList, 1, 1, profilerDecoder, passOptions, + : PassManager(env, triple, optLevel, relocMode, log, logList, 1, 1, profilerDecoder, passOptions, nullptr, CVector {}, "") { }; - bool Compile(JSHandle &jsFunction, AOTFileGenerator &gen, int32_t osrOffset = -1); + bool Compile(AOTFileGenerator &gen, int32_t osrOffset = -1); bool RunCg(); virtual ~JitPassManager(); diff --git a/ecmascript/compiler/slowpath_lowering.cpp b/ecmascript/compiler/slowpath_lowering.cpp index 83a46e31d1..ce5bf128ae 100644 --- a/ecmascript/compiler/slowpath_lowering.cpp +++ b/ecmascript/compiler/slowpath_lowering.cpp @@ -1544,7 +1544,7 @@ GateRef SlowPathLowering::LowerUpdateArrayHClass(GateRef gate, GateRef array) { ElementsKind kind = acc_.TryGetElementsKind(gate); if (!Elements::IsGeneric(kind)) { - size_t hclassIndex = static_cast(thread_->GetArrayHClassIndexMap().at(kind)); + size_t hclassIndex = static_cast(compilationEnv_->GetArrayHClassIndexMap().at(kind)); GateRef gConstAddr = builder_.Load(VariableType::JS_POINTER(), glue_, builder_.IntPtr(JSThread::GlueData::GetGlobalConstOffset(false))); GateRef constantIndex = builder_.IntPtr(JSTaggedValue::TaggedTypeSize() * hclassIndex); diff --git a/ecmascript/compiler/slowpath_lowering.h b/ecmascript/compiler/slowpath_lowering.h index 6789c70745..a5c2f0fe6f 100644 --- a/ecmascript/compiler/slowpath_lowering.h +++ b/ecmascript/compiler/slowpath_lowering.h @@ -112,7 +112,7 @@ public: SlowPathLowering(Circuit *circuit, CompilationConfig *cmpCfg, PassContext *ctx, const MethodLiteral *methodLiteral, bool enableLog, const std::string& name) - : thread_(ctx->GetEcmaVM()->GetJSThread()), methodLiteral_(methodLiteral), + : compilationEnv_(ctx->GetCompilationEnv()), methodLiteral_(methodLiteral), circuit_(circuit), acc_(circuit), argAcc_(circuit), builder_(circuit, cmpCfg), enableLog_(enableLog), methodName_(name), glue_(acc_.GetGlueFromArgList()) @@ -320,7 +320,7 @@ private: void LowerLdStr(GateRef gate); void LowerGetConstPool(GateRef gate); - JSThread *thread_; + CompilationEnv *compilationEnv_; const MethodLiteral *methodLiteral_ {nullptr}; Circuit *circuit_; GateAccessor acc_; diff --git a/ecmascript/compiler/tests/typed_array_lowering_test.cpp b/ecmascript/compiler/tests/typed_array_lowering_test.cpp index 28bf3edf90..d11a1a6acc 100644 --- a/ecmascript/compiler/tests/typed_array_lowering_test.cpp +++ b/ecmascript/compiler/tests/typed_array_lowering_test.cpp @@ -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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, 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, &visitor, nullptr, nullptr, &chunk, false); + TypedHCRLowering lowering(&circuit, nullptr, &visitor, nullptr, nullptr, &chunk, false); visitor.AddPass(&lowering); visitor.VisitGraph(); EXPECT_TRUE(Verifier::Run(&circuit)); diff --git a/ecmascript/compiler/ts_hcr_opt_pass.cpp b/ecmascript/compiler/ts_hcr_opt_pass.cpp index fd0f553e1c..75cff2406d 100644 --- a/ecmascript/compiler/ts_hcr_opt_pass.cpp +++ b/ecmascript/compiler/ts_hcr_opt_pass.cpp @@ -14,6 +14,7 @@ */ #include "ecmascript/compiler/ts_hcr_opt_pass.h" +#include "ecmascript/jit/jit.h" namespace panda::ecmascript::kungfu { @@ -41,8 +42,10 @@ GateRef TSHCROptPass::VisitStringBinOp(GateRef gate) { TypedBinOp op = acc_.GetTypedBinaryOp(gate); switch (op) { - case TypedBinOp::TYPED_EQ: + case TypedBinOp::TYPED_EQ: { + Jit::JitLockHolder lock(compilationEnv_, "VisitStringEqual"); return VisitStringEqual(gate); + } default: return Circuit::NullGate(); } @@ -79,10 +82,9 @@ GateRef TSHCROptPass::ConvertStringEqualToConst(GateRef left, GateRef right) auto leftMethodOffset = acc_.TryGetMethodOffset(left); auto rightMethodOffset = acc_.TryGetMethodOffset(right); - JSHandle leftStr(thread_, GetStringFromConstantPool(leftMethodOffset, leftId)); - JSHandle rightStr(thread_, GetStringFromConstantPool(rightMethodOffset, rightId)); - bool isEqual = EcmaStringAccessor::StringsAreEqual(thread_->GetEcmaVM(), leftStr, rightStr); - if (isEqual) { + JSTaggedValue leftStr = GetStringFromConstantPool(leftMethodOffset, leftId); + JSTaggedValue rightStr = GetStringFromConstantPool(rightMethodOffset, rightId); + if (leftStr == rightStr) { return builder_.Boolean(true); } return builder_.Boolean(false); diff --git a/ecmascript/compiler/ts_hcr_opt_pass.h b/ecmascript/compiler/ts_hcr_opt_pass.h index e59e36d864..0230412a86 100644 --- a/ecmascript/compiler/ts_hcr_opt_pass.h +++ b/ecmascript/compiler/ts_hcr_opt_pass.h @@ -27,8 +27,7 @@ public: PassContext *ctx, bool enableLog, const std::string &name) : PassVisitor(circuit, chunk, visitor), builder_(circuit, ctx->GetCompilerConfig()), - ptManager_(ctx->GetPTManager()), - thread_(ctx->GetEcmaVM()->GetJSThread()), + compilationEnv_(ctx->GetCompilationEnv()), enableLog_(enableLog), methodName_(name) {} @@ -49,7 +48,7 @@ private: JSTaggedValue GetStringFromConstantPool(uint32_t methodOffset, uint32_t cpIdx) const { - return ptManager_->GetStringFromConstantPool(methodOffset, cpIdx); + return compilationEnv_->GetStringFromConstantPool(methodOffset, cpIdx); } GateRef VisitTypedBinaryOp(GateRef gate); @@ -63,8 +62,7 @@ private: GateRef ConvertToSingleCharComparison(GateRef left, GateRef right); CircuitBuilder builder_; - PGOTypeManager *ptManager_ {nullptr}; - const JSThread *thread_ {nullptr}; + const CompilationEnv *compilationEnv_ {nullptr}; bool enableLog_ {false}; std::string methodName_; }; diff --git a/ecmascript/compiler/ts_inline_lowering.cpp b/ecmascript/compiler/ts_inline_lowering.cpp index 55a19f9bab..87798f0042 100644 --- a/ecmascript/compiler/ts_inline_lowering.cpp +++ b/ecmascript/compiler/ts_inline_lowering.cpp @@ -329,7 +329,7 @@ GateRef TSInlineLowering::BuildAccessor(InlineTypeInfoAccessor &info) ASSERT(pgoTypes->GetCount() == 1); auto pgoType = pgoTypes->GetObjectInfo(0); ProfileTyper holderType = std::make_pair(pgoType.GetHoldRootType(), pgoType.GetHoldType()); - PGOTypeManager *ptManager = thread_->GetCurrentEcmaContext()->GetPTManager(); + PGOTypeManager *ptManager = compilationEnv_->GetPTManager(); int holderHCIndex = static_cast(ptManager->GetHClassIndexByProfileType(holderType)); ASSERT(ptManager->QueryHClass(holderType.first, holderType.second).IsJSHClass()); ArgumentAccessor argAcc(circuit_); @@ -526,7 +526,7 @@ void TSInlineLowering::InlineAccessorCheck(const InlineTypeInfoAccessor &info) ASSERT(pgoTypes->GetCount() == 1); auto pgoType = pgoTypes->GetObjectInfo(0); ProfileTyper receiverType = std::make_pair(pgoType.GetReceiverRootType(), pgoType.GetReceiverType()); - PGOTypeManager *ptManager = thread_->GetCurrentEcmaContext()->GetPTManager(); + PGOTypeManager *ptManager = compilationEnv_->GetPTManager(); int receiverHCIndex = static_cast(ptManager->GetHClassIndexByProfileType(receiverType)); ASSERT(ptManager->QueryHClass(receiverType.first, receiverType.second).IsJSHClass()); @@ -644,9 +644,9 @@ bool TSInlineLowering::IsRecursiveFunc(InlineTypeInfoAccessor &info, size_t call void TSInlineLowering::CandidateAccessor(GateRef gate, ChunkQueue &workList, CallKind kind) { GateRef receiver = GetAccessorReceiver(gate); - InlineTypeInfoAccessor tacc(thread_, circuit_, gate, receiver, kind); + InlineTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, receiver, kind); if (tacc.IsEnableAccessorInline()) { - workList.emplace(thread_, circuit_, gate, receiver, kind); + workList.emplace(compilationEnv_, circuit_, gate, receiver, kind); lastCallId_ = acc_.GetId(gate); } } @@ -655,7 +655,7 @@ void TSInlineLowering::CandidateNormalCall(GateRef gate, ChunkQueueGetEcmaVM()->GetJSThread()), + compilationEnv_(ctx->GetCompilationEnv()), acc_(circuit), glue_(acc_.GetGlueFromArgList()), builder_(circuit, ctx->GetCompilerConfig()), @@ -55,11 +55,11 @@ public: passOptions_(options), enableLog_(enableLog), methodName_(name), - enableTypeLowering_(ctx->GetEcmaVM()->GetJSOptions().IsEnableTypeLowering()), - traceInline_(ctx->GetEcmaVM()->GetJSOptions().GetTraceInline()), - maxInlineBytecodesCount_(ctx->GetEcmaVM()->GetJSOptions().GetMaxInlineBytecodes()), + enableTypeLowering_(ctx->GetCompilationEnv()->GetJSOptions().IsEnableTypeLowering()), + traceInline_(ctx->GetCompilationEnv()->GetJSOptions().GetTraceInline()), + maxInlineBytecodesCount_(ctx->GetCompilationEnv()->GetJSOptions().GetMaxInlineBytecodes()), nativeAreaAllocator_(nativeAreaAllocator), - noCheck_(ctx->GetEcmaVM()->GetJSOptions().IsCompilerNoCheck()), + noCheck_(ctx->GetCompilationEnv()->GetJSOptions().IsCompilerNoCheck()), chunk_(circuit->chunk()), inlinedCallMap_(circuit->chunk()), argAcc_(circuit), @@ -138,7 +138,7 @@ private: uint32_t GetAccessorConstpoolId(InlineTypeInfoAccessor &info); Circuit *circuit_ {nullptr}; - JSThread *thread_ {nullptr}; + CompilationEnv *compilationEnv_ {nullptr}; GateAccessor acc_; GateRef glue_; CircuitBuilder builder_; diff --git a/ecmascript/compiler/type_inference/pgo_type_infer.cpp b/ecmascript/compiler/type_inference/pgo_type_infer.cpp index 18ebf39bd9..ec5d3e4313 100644 --- a/ecmascript/compiler/type_inference/pgo_type_infer.cpp +++ b/ecmascript/compiler/type_inference/pgo_type_infer.cpp @@ -262,7 +262,7 @@ void PGOTypeInfer::UpdateTypeForRWOp(GateRef gate, GateRef receiver, uint32_t pr JSTaggedValue prop = JSTaggedValue::Undefined(); if (propIndex != INVALID_INDEX) { auto methodOffset = acc_.TryGetMethodOffset(gate); - prop = ptManager_->GetStringFromConstantPool(methodOffset, propIndex); + prop = compilationEnv_->GetStringFromConstantPool(methodOffset, propIndex); } ChunkSet inferTypes = helper_.GetInferTypes(chunk_, types, prop); AddProfiler(gate, tsType, *pgoRwTypes, inferTypes); diff --git a/ecmascript/compiler/type_inference/pgo_type_infer.h b/ecmascript/compiler/type_inference/pgo_type_infer.h index e99d2f4c43..bb07a36c65 100644 --- a/ecmascript/compiler/type_inference/pgo_type_infer.h +++ b/ecmascript/compiler/type_inference/pgo_type_infer.h @@ -26,10 +26,10 @@ struct CollectedType; class PGOTypeInfer { public: PGOTypeInfer(Circuit *circuit, TSManager *tsManager, PGOTypeManager *ptManager, BytecodeCircuitBuilder *builder, - const std::string &name, Chunk *chunk, bool enableLog) + 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) {} + enableLog_(enableLog), profiler_(chunk), compilationEnv_(env) {} ~PGOTypeInfer() = default; void Run(); @@ -89,13 +89,14 @@ private: GateAccessor acc_; ArgumentAccessor argAcc_; TSManager *tsManager_ {nullptr}; - PGOTypeManager *ptManager_ {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 diff --git a/ecmascript/compiler/type_info_accessors.cpp b/ecmascript/compiler/type_info_accessors.cpp index c55eb484ff..6e60a1a97a 100644 --- a/ecmascript/compiler/type_info_accessors.cpp +++ b/ecmascript/compiler/type_info_accessors.cpp @@ -23,11 +23,6 @@ #include "ecmascript/ts_types/ts_type_accessor.h" namespace panda::ecmascript::kungfu { -JSTaggedValue TypeInfoAccessor::GetStringFromConstantPool(const JSThread *thread, uint32_t methodId, uint32_t index) -{ - return thread->GetCurrentEcmaContext()->GetPTManager()->GetStringFromConstantPool(methodId, index); -} - ParamType TypeInfoAccessor::PGOSampleTypeToParamType() const { if (pgoType_.IsPGOSampleType()) { @@ -200,7 +195,7 @@ bool TypeInfoAccessor::IsTrustedNumberType(GateAccessor acc, GateRef gate) } bool TypeInfoAccessor::IsTrustedStringType( - const JSThread *thread, Circuit *circuit, Chunk *chunk, GateAccessor acc, GateRef gate) + const CompilationEnv *env, Circuit *circuit, Chunk *chunk, GateAccessor acc, GateRef gate) { auto op = acc.GetOpCode(gate); if (op == OpCode::LOAD_ELEMENT) { @@ -216,7 +211,7 @@ bool TypeInfoAccessor::IsTrustedStringType( return true; case EcmaOpcode::LDOBJBYVALUE_IMM8_V8: case EcmaOpcode::LDOBJBYVALUE_IMM16_V8: { - LoadBulitinObjTypeInfoAccessor tacc(thread, circuit, gate, chunk); + LoadBulitinObjTypeInfoAccessor tacc(env, circuit, gate, chunk); if (tacc.IsMono()) { return tacc.IsBuiltinsString(); } @@ -248,8 +243,8 @@ bool TypeOfTypeInfoAccessor::IsIllegalType() const return true; } -SuperCallTypeInfoAccessor::SuperCallTypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate) - : TypeInfoAccessor(thread, circuit, gate) +SuperCallTypeInfoAccessor::SuperCallTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate) + : TypeInfoAccessor(env, circuit, gate) { ctor_ = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC); } @@ -266,56 +261,56 @@ BuiltinsStubCSigns::ID CallTypeInfoAccessor::TryGetPGOBuiltinMethodId() const return BuiltinsStubCSigns::ID::NONE; } -GetIteratorTypeInfoAccessor::GetIteratorTypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate, +GetIteratorTypeInfoAccessor::GetIteratorTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile, const CallMethodFlagMap *callMethodFlagMap) - : CallTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap) + : CallTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap) { argc_ = 0; // 0: number of argc func_ = acc_.GetValueIn(gate, 0); // 1: func } -CallArg0TypeInfoAccessor::CallArg0TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate, +CallArg0TypeInfoAccessor::CallArg0TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile, const CallMethodFlagMap *callMethodFlagMap) - : CallTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap) + : CallTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap) { argc_ = 0; // 0: number of argc func_ = acc_.GetValueIn(gate, 0); // 0: func } -CallArg1TypeInfoAccessor::CallArg1TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate, +CallArg1TypeInfoAccessor::CallArg1TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile, const CallMethodFlagMap *callMethodFlagMap) - : CallTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap) + : CallTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap) { argc_ = 1; // 1: number of argc value_ = acc_.GetValueIn(gate, 0); // 0: value func_ = acc_.GetValueIn(gate, 1); // 1: func } -CallArg2TypeInfoAccessor::CallArg2TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate, +CallArg2TypeInfoAccessor::CallArg2TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile, const CallMethodFlagMap *callMethodFlagMap) - : CallTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap) + : CallTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap) { argc_ = 2; // 2: number of argc func_ = acc_.GetValueIn(gate, 2); // 2: func } -CallArg3TypeInfoAccessor::CallArg3TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate, +CallArg3TypeInfoAccessor::CallArg3TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile, const CallMethodFlagMap *callMethodFlagMap) - : CallTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap) + : CallTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap) { argc_ = 3; // 3: number of argc func_ = acc_.GetValueIn(gate, 3); // 3: func } -CallRangeTypeInfoAccessor::CallRangeTypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate, +CallRangeTypeInfoAccessor::CallRangeTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile, const CallMethodFlagMap *callMethodFlagMap) - : CallTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap) + : CallTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap) { size_t numArgs = acc_.GetNumValueIn(gate); constexpr size_t callTargetIndex = 1; // acc @@ -339,38 +334,38 @@ bool CallThisTypeInfoAccessor::CanOptimizeAsFastCall() return false; } -CallThis0TypeInfoAccessor::CallThis0TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate, +CallThis0TypeInfoAccessor::CallThis0TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile, const CallMethodFlagMap *callMethodFlagMap) - : CallThisTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap) + : CallThisTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap) { argc_ = 0; // 0: number of argc func_ = acc_.GetValueIn(gate, 1); // 1: func } -CallThis1TypeInfoAccessor::CallThis1TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate, +CallThis1TypeInfoAccessor::CallThis1TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile, const CallMethodFlagMap *callMethodFlagMap) - : CallThisTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap) + : CallThisTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap) { argc_ = 1; // 1: number of argc func_ = acc_.GetValueIn(gate, 2); // 2: func a0_ = acc_.GetValueIn(gate, 1); // 1: arg0 } -CallThis2TypeInfoAccessor::CallThis2TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate, +CallThis2TypeInfoAccessor::CallThis2TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile, const CallMethodFlagMap *callMethodFlagMap) - : CallThisTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap) + : CallThisTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap) { argc_ = 2; // 2: number of argc func_ = acc_.GetValueIn(gate, 3); // 3: func } -CallThis3TypeInfoAccessor::CallThis3TypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate, +CallThis3TypeInfoAccessor::CallThis3TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile, const CallMethodFlagMap *callMethodFlagMap) - : CallThisTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap) + : CallThisTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap) { argc_ = 3; // 3: number of argc func_ = acc_.GetValueIn(gate, 4); // 4: func @@ -379,10 +374,10 @@ CallThis3TypeInfoAccessor::CallThis3TypeInfoAccessor(const JSThread *thread, Cir a2_ = acc_.GetValueIn(gate, 3); // 3: arg2 } -CallThisRangeTypeInfoAccessor::CallThisRangeTypeInfoAccessor(const JSThread *thread, Circuit *circuit, GateRef gate, +CallThisRangeTypeInfoAccessor::CallThisRangeTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile, const CallMethodFlagMap *callMethodFlagMap) - : CallThisTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap) + : CallThisTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap) { constexpr size_t fixedInputsNum = 1; constexpr size_t callTargetIndex = 1; // 1: acc @@ -393,8 +388,8 @@ CallThisRangeTypeInfoAccessor::CallThisRangeTypeInfoAccessor(const JSThread *thr } InlineTypeInfoAccessor::InlineTypeInfoAccessor( - const JSThread *thread, Circuit *circuit, GateRef gate, GateRef receiver, CallKind kind) - : TypeInfoAccessor(thread, circuit, gate), receiver_(receiver), kind_(kind) + const CompilationEnv *env, Circuit *circuit, GateRef gate, GateRef receiver, CallKind kind) + : TypeInfoAccessor(env, circuit, gate), receiver_(receiver), kind_(kind) { if (IsCallAccessor()) { plr_ = GetAccessorPlr(); @@ -411,7 +406,7 @@ GlobalTSTypeRef InlineTypeInfoAccessor::GetAccessorFuncGT() const GateRef constData = acc_.GetValueIn(gate_, 1); uint16_t propIndex = acc_.GetConstantValue(constData); auto methodOffset = acc_.TryGetMethodOffset(gate_); - auto prop = tsManager_->GetStringFromConstantPool(methodOffset, propIndex); + auto prop = compilationEnv_->GetStringFromConstantPool(methodOffset, propIndex); GlobalTSTypeRef funcGT = tsTypeAcc.GetAccessorGT(prop, IsCallSetter()); return funcGT; } @@ -421,7 +416,7 @@ PropertyLookupResult InlineTypeInfoAccessor::GetAccessorPlr() const GateRef constData = acc_.GetValueIn(gate_, 1); uint16_t propIndex = acc_.GetConstantValue(constData); auto methodOffset = acc_.TryGetMethodOffset(gate_); - auto prop = ptManager_->GetStringFromConstantPool(methodOffset, propIndex); + auto prop = compilationEnv_->GetStringFromConstantPool(methodOffset, propIndex); // PGO currently does not support call, so GT is still used to support inline operations. // However, the original GT solution cannot support accessing the property of prototype, so it is filtered here if (EcmaStringAccessor(prop).ToStdString() == "prototype") { @@ -436,7 +431,7 @@ PropertyLookupResult InlineTypeInfoAccessor::GetAccessorPlr() const ProfileTyper receiverType = std::make_pair(pgoType.GetReceiverRootType(), pgoType.GetReceiverType()); ProfileTyper holderType = std::make_pair(pgoType.GetHoldRootType(), pgoType.GetHoldType()); - PGOTypeManager *ptManager = thread_->GetCurrentEcmaContext()->GetPTManager(); + PGOTypeManager *ptManager = compilationEnv_->GetPTManager(); JSHClass *hclass = nullptr; if (receiverType == holderType) { int hclassIndex = static_cast(ptManager->GetHClassIndexByProfileType(receiverType)); @@ -452,7 +447,7 @@ PropertyLookupResult InlineTypeInfoAccessor::GetAccessorPlr() const hclass = JSHClass::Cast(ptManager->QueryHClass(holderType.first, holderType.second).GetTaggedObject()); } - PropertyLookupResult plr = JSHClass::LookupPropertyInPGOHClass(thread_, hclass, prop); + PropertyLookupResult plr = JSHClass::LookupPropertyInPGOHClass(compilationEnv_->GetJSThread(), hclass, prop); return plr; } @@ -480,7 +475,7 @@ JSTaggedValue ObjectAccessTypeInfoAccessor::GetKeyTaggedValue() const { uint16_t index = acc_.GetConstantValue(key_); auto methodOffset = acc_.TryGetMethodOffset(GetGate()); - return TypeInfoAccessor::GetStringFromConstantPool(thread_, methodOffset, index); + return compilationEnv_->GetStringFromConstantPool(methodOffset, index); } bool ObjAccByNameTypeInfoAccessor::GeneratePlr(ProfileTyper type, ObjectAccessInfo &info, JSTaggedValue key) const @@ -490,7 +485,7 @@ bool ObjAccByNameTypeInfoAccessor::GeneratePlr(ProfileTyper type, ObjectAccessIn return false; } JSHClass *hclass = JSHClass::Cast(ptManager_->QueryHClass(type.first, type.second).GetTaggedObject()); - PropertyLookupResult plr = JSHClass::LookupPropertyInPGOHClass(thread_, hclass, key); + PropertyLookupResult plr = JSHClass::LookupPropertyInPGOHClass(compilationEnv_->GetJSThread(), hclass, key); info.Set(hclassIndex, plr); if (mode_ == AccessMode::LOAD) { @@ -500,9 +495,9 @@ bool ObjAccByNameTypeInfoAccessor::GeneratePlr(ProfileTyper type, ObjectAccessIn return (plr.IsFound() && !plr.IsFunction()); } -LoadObjByNameTypeInfoAccessor::LoadObjByNameTypeInfoAccessor(const JSThread *thread, Circuit *circuit, +LoadObjByNameTypeInfoAccessor::LoadObjByNameTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk) - : ObjAccByNameTypeInfoAccessor(thread, circuit, gate, chunk, AccessMode::LOAD), types_(chunk_) + : ObjAccByNameTypeInfoAccessor(env, circuit, gate, chunk, AccessMode::LOAD), types_(chunk_) { key_ = acc_.GetValueIn(gate, 1); // 1: key receiver_ = acc_.GetValueIn(gate, 2); // 2: receiver @@ -555,9 +550,9 @@ bool LoadObjByNameTypeInfoAccessor::GenerateObjectAccessInfo() return true; } -StoreObjByNameTypeInfoAccessor::StoreObjByNameTypeInfoAccessor(const JSThread *thread, Circuit *circuit, +StoreObjByNameTypeInfoAccessor::StoreObjByNameTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk) - : ObjAccByNameTypeInfoAccessor(thread, circuit, gate, chunk, AccessMode::STORE), types_(chunk_) + : ObjAccByNameTypeInfoAccessor(env, circuit, gate, chunk, AccessMode::STORE), types_(chunk_) { EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate); switch (ecmaOpcode) { @@ -640,9 +635,9 @@ bool StoreObjByNameTypeInfoAccessor::GenerateObjectAccessInfo() return true; } -InstanceOfTypeInfoAccessor::InstanceOfTypeInfoAccessor(const JSThread *thread, Circuit *circuit, +InstanceOfTypeInfoAccessor::InstanceOfTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk) - : ObjAccByNameTypeInfoAccessor(thread, circuit, gate, chunk, AccessMode::LOAD), types_(chunk_) + : ObjAccByNameTypeInfoAccessor(env, circuit, gate, chunk, AccessMode::LOAD), types_(chunk_) { receiver_ = acc_.GetValueIn(gate, 1); // 2: receiver target_ = acc_.GetValueIn(gate, 2); // 2: the third parameter @@ -653,7 +648,7 @@ InstanceOfTypeInfoAccessor::InstanceOfTypeInfoAccessor(const JSThread *thread, C JSTaggedValue InstanceOfTypeInfoAccessor::GetKeyTaggedValue() const { - JSHandle globalEnv = thread_->GetEcmaVM()->GetGlobalEnv(); + JSHandle globalEnv = compilationEnv_->GetGlobalEnv(); auto hasInstanceEnvIndex = static_cast(GlobalEnvField::HASINSTANCE_SYMBOL_INDEX); return globalEnv->GetGlobalEnvObjectByIndex(hasInstanceEnvIndex).GetTaggedValue(); } @@ -710,9 +705,9 @@ bool InstanceOfTypeInfoAccessor::GenerateObjectAccessInfo() return true; } -LoadBulitinObjTypeInfoAccessor::LoadBulitinObjTypeInfoAccessor(const JSThread *thread, Circuit *circuit, +LoadBulitinObjTypeInfoAccessor::LoadBulitinObjTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk) - : AccBuiltinObjTypeInfoAccessor(thread, circuit, gate, chunk, AccessMode::LOAD) + : AccBuiltinObjTypeInfoAccessor(env, circuit, gate, chunk, AccessMode::LOAD) { EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate); switch (ecmaOpcode) { @@ -795,9 +790,9 @@ bool AccBuiltinObjTypeInfoAccessor::CheckDuplicatedBuiltinType(ProfileType newTy return false; } -StoreBulitinObjTypeInfoAccessor::StoreBulitinObjTypeInfoAccessor(const JSThread *thread, Circuit *circuit, +StoreBulitinObjTypeInfoAccessor::StoreBulitinObjTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk) - : AccBuiltinObjTypeInfoAccessor(thread, circuit, gate, chunk, AccessMode::STORE) + : AccBuiltinObjTypeInfoAccessor(env, circuit, gate, chunk, AccessMode::STORE) { EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate); switch (ecmaOpcode) { @@ -824,35 +819,36 @@ StoreBulitinObjTypeInfoAccessor::StoreBulitinObjTypeInfoAccessor(const JSThread FetchBuiltinsTypes(); } -CreateObjWithBufferTypeInfoAccessor::CreateObjWithBufferTypeInfoAccessor(const JSThread *thread, Circuit *circuit, +CreateObjWithBufferTypeInfoAccessor::CreateObjWithBufferTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const CString &recordName) - : TypeInfoAccessor(thread, circuit, gate), recordName_(recordName), objHandle_(thread, JSTaggedValue::Undefined()) + : TypeInfoAccessor(env, circuit, gate), recordName_(recordName) { ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: number of value ins index_ = acc_.GetValueIn(gate, 0); - Init(); } -void CreateObjWithBufferTypeInfoAccessor::Init() +JSTaggedValue CreateObjWithBufferTypeInfoAccessor::GetObject() const { auto imm = acc_.GetConstantValue(index_); auto methodOffset = acc_.TryGetMethodOffset(GetGate()); - JSTaggedValue cp = ptManager_->GetConstantPoolByMethodOffset(methodOffset); - JSTaggedValue unsharedCp = thread_->GetCurrentEcmaContext()->FindOrCreateUnsharedConstpool(cp); - JSTaggedValue obj = ConstantPool::GetLiteralFromCache( - tsManager_->GetEcmaVM()->GetJSThread(), unsharedCp, imm, recordName_); - objHandle_ = JSHandle(thread_, obj); + JSTaggedValue unsharedCp = compilationEnv_->FindOrCreateUnsharedConstpool(methodOffset); + return compilationEnv_->GetObjectLiteralFromCache(unsharedCp, imm, recordName_); } JSTaggedValue CreateObjWithBufferTypeInfoAccessor::GetHClass() const { + JSTaggedValue obj = GetObject(); + if (obj.IsUndefined()) { + return JSTaggedValue::Undefined(); + } auto sampleType = acc_.TryGetPGOType(gate_).GetPGODefineOpType(); auto type = std::make_pair(sampleType->GetProfileType(), sampleType->GetProfileType()); int hclassIndex = static_cast(ptManager_->GetHClassIndexByProfileType(type)); - JSHClass *oldClass = objHandle_->GetClass(); + JSObject *jsObj = JSObject::Cast(obj); + JSHClass *oldClass = jsObj->GetClass(); if (hclassIndex == -1) { - if (objHandle_->ElementsAndPropertiesIsEmpty()) { + if (jsObj->ElementsAndPropertiesIsEmpty()) { return JSTaggedValue(oldClass); } return JSTaggedValue::Undefined(); diff --git a/ecmascript/compiler/type_info_accessors.h b/ecmascript/compiler/type_info_accessors.h index a424068439..51886dc81d 100644 --- a/ecmascript/compiler/type_info_accessors.h +++ b/ecmascript/compiler/type_info_accessors.h @@ -28,16 +28,16 @@ namespace panda::ecmascript::kungfu { class TypeInfoAccessor { public: - TypeInfoAccessor(const JSThread *thread, Circuit* circuit, GateRef gate) - : thread_(thread), + TypeInfoAccessor(const CompilationEnv *env, Circuit* circuit, GateRef gate) + : compilationEnv_(env), acc_(circuit), argAcc_(circuit), gate_(gate) { pgoType_ = acc_.TryGetPGOType(gate); // NOTICE-PGO: wx delete in part3 - tsManager_ = thread_->GetCurrentEcmaContext()->GetTSManager(); - ptManager_ = thread_->GetCurrentEcmaContext()->GetPTManager(); + tsManager_ = compilationEnv_->GetTSManager(); + ptManager_ = compilationEnv_->GetPTManager(); } inline GateRef GetGate() const @@ -50,15 +50,13 @@ public: static bool IsTrustedNumberType(GateAccessor acc, GateRef gate); static bool IsTrustedStringType( - const JSThread *thread, Circuit *circuit, Chunk *chunk, GateAccessor acc, GateRef gate); - - static JSTaggedValue GetStringFromConstantPool(const JSThread *thread, uint32_t methodId, uint32_t index); + const CompilationEnv *env, Circuit *circuit, Chunk *chunk, GateAccessor acc, GateRef gate); protected: ParamType PGOSampleTypeToParamType() const; static ParamType PGOBuiltinTypeToParamType(ProfileType pgoType); - const JSThread *thread_ {nullptr}; + const CompilationEnv *compilationEnv_ {nullptr}; GateAccessor acc_; ArgumentAccessor argAcc_; GateRef gate_; @@ -70,10 +68,10 @@ protected: class BinOpTypeInfoAccessor final : public TypeInfoAccessor { public: - BinOpTypeInfoAccessor(const JSThread *thread, + BinOpTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate) - : TypeInfoAccessor(thread, circuit, gate) + : TypeInfoAccessor(env, circuit, gate) { left_ = acc_.GetValueIn(gate, 0); // 0: left right_ = acc_.GetValueIn(gate, 1); // 1: right @@ -118,10 +116,10 @@ private: class UnOpTypeInfoAccessor : public TypeInfoAccessor { public: - UnOpTypeInfoAccessor(const JSThread *thread, + UnOpTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate) - : TypeInfoAccessor(thread, circuit, gate) + : TypeInfoAccessor(env, circuit, gate) { value_ = acc_.GetValueIn(gate, 0); // 0: value } @@ -159,10 +157,10 @@ protected: class ConditionJumpTypeInfoAccessor final : public UnOpTypeInfoAccessor { public: - ConditionJumpTypeInfoAccessor(const JSThread *thread, + ConditionJumpTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate) - : UnOpTypeInfoAccessor(thread, circuit, gate) {} + : UnOpTypeInfoAccessor(env, circuit, gate) {} NO_COPY_SEMANTIC(ConditionJumpTypeInfoAccessor); NO_MOVE_SEMANTIC(ConditionJumpTypeInfoAccessor); @@ -174,10 +172,10 @@ public: class NewObjRangeTypeInfoAccessor final : public UnOpTypeInfoAccessor { public: - NewObjRangeTypeInfoAccessor(const JSThread *thread, + NewObjRangeTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate) - : UnOpTypeInfoAccessor(thread, circuit, gate), hclassIndex_(-1) {} + : UnOpTypeInfoAccessor(env, circuit, gate), hclassIndex_(-1) {} NO_COPY_SEMANTIC(NewObjRangeTypeInfoAccessor); NO_MOVE_SEMANTIC(NewObjRangeTypeInfoAccessor); @@ -194,10 +192,10 @@ private: class NewBuiltinCtorTypeInfoAccessor final : public UnOpTypeInfoAccessor { public: - NewBuiltinCtorTypeInfoAccessor(const JSThread *thread, + NewBuiltinCtorTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate) - : UnOpTypeInfoAccessor(thread, circuit, gate) {} + : UnOpTypeInfoAccessor(env, circuit, gate) {} NO_COPY_SEMANTIC(NewBuiltinCtorTypeInfoAccessor); NO_MOVE_SEMANTIC(NewBuiltinCtorTypeInfoAccessor); @@ -208,6 +206,9 @@ public: bool IsBuiltinConstructor(BuiltinTypeId type) { + if (compilationEnv_->IsJitCompiler()) { + return false; + } return tsManager_->IsBuiltinConstructor(type, GetCtorGT()); } @@ -220,10 +221,10 @@ private: class TypeOfTypeInfoAccessor final : public UnOpTypeInfoAccessor { public: - TypeOfTypeInfoAccessor(const JSThread *thread, + TypeOfTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate) - : UnOpTypeInfoAccessor(thread, circuit, gate) {} + : UnOpTypeInfoAccessor(env, circuit, gate) {} NO_COPY_SEMANTIC(TypeOfTypeInfoAccessor); NO_MOVE_SEMANTIC(TypeOfTypeInfoAccessor); @@ -232,7 +233,7 @@ public: class SuperCallTypeInfoAccessor final : public TypeInfoAccessor { public: - SuperCallTypeInfoAccessor(const JSThread *thread, + SuperCallTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate); NO_COPY_SEMANTIC(SuperCallTypeInfoAccessor); @@ -240,6 +241,9 @@ public: bool IsClassTypeKind() const { + if (compilationEnv_->IsJitCompiler()) { + return false; + } return tsManager_->IsClassTypeKind(acc_.GetGateType(ctor_)); } @@ -259,12 +263,12 @@ private: class CallTypeInfoAccessor : public TypeInfoAccessor { public: - CallTypeInfoAccessor(const JSThread *thread, + CallTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile = nullptr, const CallMethodFlagMap *callMethodFlagMap = nullptr) - : TypeInfoAccessor(thread, circuit, gate), + : TypeInfoAccessor(env, circuit, gate), argc_(0), func_(Circuit::NullGate()), jsPandaFile_(jsPandaFile), @@ -348,8 +352,8 @@ public: panda_file::IndexAccessor indexAccessor(*(jsPandaFile_->GetPandaFile()), panda_file::File::EntityId(methodId)); uint32_t cpId = static_cast(indexAccessor.GetHeaderIndex()); - JSHandle constpoolHandle(thread_, - thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile_, cpId)); + ConstantPool *constpoolHandle = + ConstantPool::Cast(compilationEnv_->FindConstpool(jsPandaFile_, cpId).GetTaggedObject()); return constpoolHandle->GetMethodIndexByEntityId(panda_file::File::EntityId(methodId)); } return 0; @@ -403,7 +407,7 @@ protected: class GetIteratorTypeInfoAccessor final : public CallTypeInfoAccessor { public: - GetIteratorTypeInfoAccessor(const JSThread *thread, + GetIteratorTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile = nullptr, @@ -419,7 +423,7 @@ public: class CallArg0TypeInfoAccessor final : public CallTypeInfoAccessor { public: - CallArg0TypeInfoAccessor(const JSThread *thread, + CallArg0TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile = nullptr, @@ -430,7 +434,7 @@ public: class CallArg1TypeInfoAccessor final : public CallTypeInfoAccessor { public: - CallArg1TypeInfoAccessor(const JSThread *thread, + CallArg1TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile = nullptr, @@ -454,7 +458,7 @@ private: class CallArg2TypeInfoAccessor final : public CallTypeInfoAccessor { public: - CallArg2TypeInfoAccessor(const JSThread *thread, + CallArg2TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile = nullptr, @@ -465,7 +469,7 @@ public: class CallArg3TypeInfoAccessor final : public CallTypeInfoAccessor { public: - CallArg3TypeInfoAccessor(const JSThread *thread, + CallArg3TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile = nullptr, @@ -476,7 +480,7 @@ public: class CallRangeTypeInfoAccessor final : public CallTypeInfoAccessor { public: - CallRangeTypeInfoAccessor(const JSThread *thread, + CallRangeTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile = nullptr, @@ -487,12 +491,12 @@ public: class CallThisTypeInfoAccessor : public CallTypeInfoAccessor { public: - CallThisTypeInfoAccessor(const JSThread *thread, + CallThisTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile = nullptr, const CallMethodFlagMap *callMethodFlagMap = nullptr) - : CallTypeInfoAccessor(thread, circuit, gate, jsPandaFile, callMethodFlagMap) + : CallTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap) { thisObj_ = acc_.GetValueIn(gate, 0); } @@ -511,7 +515,7 @@ protected: class CallThis0TypeInfoAccessor final : public CallThisTypeInfoAccessor { public: - CallThis0TypeInfoAccessor(const JSThread *thread, + CallThis0TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile = nullptr, @@ -522,7 +526,7 @@ public: class CallThis1TypeInfoAccessor final : public CallThisTypeInfoAccessor { public: - CallThis1TypeInfoAccessor(const JSThread *thread, + CallThis1TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile = nullptr, @@ -546,7 +550,7 @@ private: class CallThis2TypeInfoAccessor final : public CallThisTypeInfoAccessor { public: - CallThis2TypeInfoAccessor(const JSThread *thread, + CallThis2TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile = nullptr, @@ -557,7 +561,7 @@ public: class CallThis3TypeInfoAccessor final : public CallThisTypeInfoAccessor { public: - CallThis3TypeInfoAccessor(const JSThread *thread, + CallThis3TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile = nullptr, @@ -578,7 +582,7 @@ private: class CallThisRangeTypeInfoAccessor final : public CallThisTypeInfoAccessor { public: - CallThisRangeTypeInfoAccessor(const JSThread *thread, + CallThisRangeTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const JSPandaFile *jsPandaFile = nullptr, @@ -598,7 +602,7 @@ enum CallKind : uint8_t { class InlineTypeInfoAccessor final : public TypeInfoAccessor { public: - InlineTypeInfoAccessor(const JSThread *thread, + InlineTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, GateRef receiver, @@ -623,6 +627,9 @@ public: bool IsClassInstanceTypeKind() const { + if (compilationEnv_->IsJitCompiler()) { + return false; + } return tsManager_->IsClassInstanceTypeKind(acc_.GetGateType(receiver_)); } @@ -733,12 +740,12 @@ public: STORE }; - ObjectAccessTypeInfoAccessor(const JSThread *thread, + ObjectAccessTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk, AccessMode mode) - : TypeInfoAccessor(thread, circuit, gate), + : TypeInfoAccessor(env, circuit, gate), chunk_(chunk), mode_(mode), key_(Circuit::NullGate()), @@ -761,6 +768,9 @@ public: GateType GetReceiverGateType() const { + if (compilationEnv_->IsJitCompiler()) { + return acc_.GetGateType(receiver_); + } return tsManager_->TryNarrowUnionType(acc_.GetGateType(receiver_)); } @@ -773,12 +783,12 @@ protected: class ObjAccByNameTypeInfoAccessor : public ObjectAccessTypeInfoAccessor { public: - ObjAccByNameTypeInfoAccessor(const JSThread *thread, + ObjAccByNameTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk, AccessMode mode) - : ObjectAccessTypeInfoAccessor(thread, circuit, gate, chunk, mode), + : ObjectAccessTypeInfoAccessor(env, circuit, gate, chunk, mode), hasIllegalType_(false), accessInfos_(chunk), checkerInfos_(chunk) @@ -814,7 +824,7 @@ protected: class LoadObjByNameTypeInfoAccessor final : public ObjAccByNameTypeInfoAccessor { public: - LoadObjByNameTypeInfoAccessor(const JSThread *thread, + LoadObjByNameTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk); @@ -852,7 +862,7 @@ private: class StoreObjByNameTypeInfoAccessor final : public ObjAccByNameTypeInfoAccessor { public: - StoreObjByNameTypeInfoAccessor(const JSThread *thread, + StoreObjByNameTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk); @@ -905,7 +915,7 @@ private: class InstanceOfTypeInfoAccessor final : public ObjAccByNameTypeInfoAccessor { public: - InstanceOfTypeInfoAccessor(const JSThread *thread, + InstanceOfTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk); @@ -947,12 +957,12 @@ private: class AccBuiltinObjTypeInfoAccessor : public ObjectAccessTypeInfoAccessor { public: - AccBuiltinObjTypeInfoAccessor(const JSThread *thread, + AccBuiltinObjTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk, AccessMode mode) - : ObjectAccessTypeInfoAccessor(thread, circuit, gate, chunk, mode), types_(chunk_) + : ObjectAccessTypeInfoAccessor(env, circuit, gate, chunk, mode), types_(chunk_) {} NO_COPY_SEMANTIC(AccBuiltinObjTypeInfoAccessor); NO_MOVE_SEMANTIC(AccBuiltinObjTypeInfoAccessor); @@ -1047,6 +1057,9 @@ public: bool IsBuiltinInstanceType(BuiltinTypeId type) const { + if (compilationEnv_->IsJitCompiler()) { + return false; + } return tsManager_->IsBuiltinInstanceType(type, GetReceiverGateType()); } @@ -1085,7 +1098,7 @@ protected: class LoadBulitinObjTypeInfoAccessor final : public AccBuiltinObjTypeInfoAccessor { public: - LoadBulitinObjTypeInfoAccessor(const JSThread *thread, + LoadBulitinObjTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk); @@ -1095,7 +1108,7 @@ public: class StoreBulitinObjTypeInfoAccessor final : public AccBuiltinObjTypeInfoAccessor { public: - StoreBulitinObjTypeInfoAccessor(const JSThread *thread, + StoreBulitinObjTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk); @@ -1118,11 +1131,11 @@ private: class GlobalObjAccTypeInfoAccessor : public ObjectAccessTypeInfoAccessor { public: - GlobalObjAccTypeInfoAccessor(const JSThread *thread, + GlobalObjAccTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, AccessMode mode) - : ObjectAccessTypeInfoAccessor(thread, circuit, gate, nullptr, mode) {} + : ObjectAccessTypeInfoAccessor(env, circuit, gate, nullptr, mode) {} NO_COPY_SEMANTIC(GlobalObjAccTypeInfoAccessor); NO_MOVE_SEMANTIC(GlobalObjAccTypeInfoAccessor); @@ -1130,10 +1143,10 @@ public: class LoadGlobalObjByNameTypeInfoAccessor final : public GlobalObjAccTypeInfoAccessor { public: - LoadGlobalObjByNameTypeInfoAccessor(const JSThread *thread, + LoadGlobalObjByNameTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate) - : GlobalObjAccTypeInfoAccessor(thread, circuit, gate, AccessMode::LOAD) + : GlobalObjAccTypeInfoAccessor(env, circuit, gate, AccessMode::LOAD) { key_ = acc_.GetValueIn(gate, 1); } @@ -1143,7 +1156,7 @@ public: class CreateObjWithBufferTypeInfoAccessor : public TypeInfoAccessor { public: - CreateObjWithBufferTypeInfoAccessor(const JSThread *thread, + CreateObjWithBufferTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, const CString &recordName); @@ -1153,10 +1166,7 @@ public: JSTaggedValue GetHClass() const; - JSHandle GetObjHandle() const - { - return objHandle_; - } + JSTaggedValue GetObject() const; GateRef GetIndex() const { @@ -1165,8 +1175,13 @@ public: bool CanOptimize() const { - TaggedArray *properties = TaggedArray::Cast(objHandle_->GetProperties()); - TaggedArray *elements = TaggedArray::Cast(objHandle_->GetElements()); + JSTaggedValue obj = GetObject(); + if (obj.IsUndefined()) { + return false; + } + JSObject *jsObj = JSObject::Cast(obj); + TaggedArray *properties = TaggedArray::Cast(jsObj->GetProperties()); + TaggedArray *elements = TaggedArray::Cast(jsObj->GetElements()); return properties->GetLength() == 0 && elements->GetLength() == 0; } @@ -1174,7 +1189,6 @@ private: void Init(); const CString &recordName_; - JSHandle objHandle_; GateRef index_; }; } // panda::ecmascript::kungfu diff --git a/ecmascript/compiler/typed_bytecode_lowering.cpp b/ecmascript/compiler/typed_bytecode_lowering.cpp index adb0bfeb3e..e247f570e4 100644 --- a/ecmascript/compiler/typed_bytecode_lowering.cpp +++ b/ecmascript/compiler/typed_bytecode_lowering.cpp @@ -31,6 +31,7 @@ #include "ecmascript/jspandafile/js_pandafile.h" #include "ecmascript/jspandafile/js_pandafile_manager.h" #include "ecmascript/jspandafile/program_object.h" +#include "ecmascript/jit/jit.h" namespace panda::ecmascript::kungfu { bool TypedBytecodeLowering::RunTypedBytecodeLowering() @@ -51,7 +52,7 @@ bool TypedBytecodeLowering::RunTypedBytecodeLowering() auto allTypedOpCount = allJSBcCount_ - allNonTypedOpCount_; if (allTypedOpCount != 0) { typeHitRate = static_cast(hitTypedOpCount_) / static_cast(allTypedOpCount); - auto typeThreshold = tsManager_->GetTypeThreshold(); + auto typeThreshold = const_cast(compilationEnv_)->GetJSOptions().GetTypeThreshold(); if (typeHitRate <= typeThreshold) { success = false; } @@ -141,8 +142,10 @@ void TypedBytecodeLowering::Lower(GateRef gate) case EcmaOpcode::GETITERATOR_IMM16: LowerGetIterator(gate); break; - case EcmaOpcode::CREATEEMPTYOBJECT: - LowerCreateEmptyObject(gate); + case EcmaOpcode::CREATEEMPTYOBJECT: { + Jit::JitLockHolder lock(compilationEnv_, "LowerCreateEmptyObject"); + LowerCreateEmptyObject(gate); + } break; case EcmaOpcode::CALLTHIS0_IMM8_V8: LowerTypedCallthis0(gate); @@ -154,13 +157,17 @@ void TypedBytecodeLowering::Lower(GateRef gate) LowerTypedCallthis2(gate); break; case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16: - case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: - LowerCreateObjectWithBuffer(gate); + case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: { + Jit::JitLockHolder lock(compilationEnv_, "LowerCreateObjectWithBuffer"); + LowerCreateObjectWithBuffer(gate); + } break; case EcmaOpcode::NEWOBJRANGE_IMM8_IMM8_V8: case EcmaOpcode::NEWOBJRANGE_IMM16_IMM8_V8: - case EcmaOpcode::WIDE_NEWOBJRANGE_PREF_IMM16_V8: - LowerTypedNewObjRange(gate); + case EcmaOpcode::WIDE_NEWOBJRANGE_PREF_IMM16_V8: { + Jit::JitLockHolder lock(compilationEnv_, "LowerTypedNewObjRange"); + LowerTypedNewObjRange(gate); + } break; case EcmaOpcode::ADD2_IMM8_V8: LowerTypedBinOp(gate); @@ -272,15 +279,19 @@ void TypedBytecodeLowering::Lower(GateRef gate) case EcmaOpcode::LDOBJBYNAME_IMM8_ID16: case EcmaOpcode::LDOBJBYNAME_IMM16_ID16: case EcmaOpcode::LDTHISBYNAME_IMM8_ID16: - case EcmaOpcode::LDTHISBYNAME_IMM16_ID16: - LowerTypedLdObjByName(gate); + case EcmaOpcode::LDTHISBYNAME_IMM16_ID16: { + Jit::JitLockHolder lock(compilationEnv_, "LowerTypedLdObjByName"); + LowerTypedLdObjByName(gate); + } break; case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8: case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8: case EcmaOpcode::STTHISBYNAME_IMM8_ID16: case EcmaOpcode::STTHISBYNAME_IMM16_ID16: - case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8: - LowerTypedStObjByName(gate); + case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8: { + Jit::JitLockHolder lock(compilationEnv_, "LowerTypedStObjByName"); + LowerTypedStObjByName(gate); + } break; case EcmaOpcode::LDOBJBYVALUE_IMM8_V8: case EcmaOpcode::LDOBJBYVALUE_IMM16_V8: @@ -358,7 +369,7 @@ int32_t TypedBytecodeLowering::GetEcmaOpCodeListIndex(EcmaOpcode ecmaOpCode) template void TypedBytecodeLowering::LowerTypedBinOp(GateRef gate) { - BinOpTypeInfoAccessor tacc(thread_, circuit_, gate); + BinOpTypeInfoAccessor tacc(compilationEnv_, circuit_, gate); if (tacc.HasNumberType()) { SpeculateNumbers(tacc); } else if (tacc.IsStringType()) { @@ -369,7 +380,7 @@ void TypedBytecodeLowering::LowerTypedBinOp(GateRef gate) template void TypedBytecodeLowering::LowerTypedUnOp(GateRef gate) { - UnOpTypeInfoAccessor tacc(thread_, circuit_, gate); + UnOpTypeInfoAccessor tacc(compilationEnv_, circuit_, gate); // NOTICE-PGO: wx add support for PrimitiveNumberType if (tacc.HasNumberType()) { SpeculateNumber(tacc); @@ -379,7 +390,7 @@ void TypedBytecodeLowering::LowerTypedUnOp(GateRef gate) template void TypedBytecodeLowering::LowerTypedEqOrNotEq(GateRef gate) { - BinOpTypeInfoAccessor tacc(thread_, circuit_, gate); + BinOpTypeInfoAccessor tacc(compilationEnv_, circuit_, gate); if (tacc.LeftOrRightIsUndefinedOrNull()) { AddProfiling(gate); GateRef left = tacc.GetLeftGate(); @@ -398,10 +409,10 @@ void TypedBytecodeLowering::SpeculateStrings(const BinOpTypeInfoAccessor &tacc) AddProfiling(tacc.GetGate()); GateRef left = tacc.GetLeftGate(); GateRef right = tacc.GetReightGate(); - if (!TypeInfoAccessor::IsTrustedStringType(thread_, circuit_, chunk_, acc_, left)) { + if (!TypeInfoAccessor::IsTrustedStringType(compilationEnv_, circuit_, chunk_, acc_, left)) { builder_.EcmaStringCheck(left); } - if (!TypeInfoAccessor::IsTrustedStringType(thread_, circuit_, chunk_, acc_, right)) { + if (!TypeInfoAccessor::IsTrustedStringType(compilationEnv_, circuit_, chunk_, acc_, right)) { builder_.EcmaStringCheck(right); } GateRef result = builder_.TypedBinaryOp(left, right, tacc.GetParamType()); @@ -431,7 +442,7 @@ void TypedBytecodeLowering::SpeculateNumber(const UnOpTypeInfoAccessor &tacc) void TypedBytecodeLowering::LowerTypeToNumeric(GateRef gate) { - UnOpTypeInfoAccessor tacc(thread_, circuit_, gate); + UnOpTypeInfoAccessor tacc(compilationEnv_, circuit_, gate); if (tacc.HasNumberType()) { AddProfiling(gate); LowerPrimitiveTypeToNumber(tacc); @@ -446,7 +457,7 @@ void TypedBytecodeLowering::LowerPrimitiveTypeToNumber(const UnOpTypeInfoAccesso void TypedBytecodeLowering::LowerConditionJump(GateRef gate, bool flag) { - ConditionJumpTypeInfoAccessor tacc(thread_, circuit_, gate); + ConditionJumpTypeInfoAccessor tacc(compilationEnv_, circuit_, gate); if (TypeInfoAccessor::IsTrustedBooleanType(acc_, tacc.GetValue())) { AddProfiling(gate); SpeculateConditionJump(tacc, flag); @@ -479,7 +490,7 @@ void TypedBytecodeLowering::DeleteConstDataIfNoUser(GateRef gate) void TypedBytecodeLowering::LowerTypedLdObjByName(GateRef gate) { DISALLOW_GARBAGE_COLLECTION; - LoadObjByNameTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_); + LoadObjByNameTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, chunk_); if (TryLowerTypedLdobjBynameFromGloablBuiltin(gate)) { return; @@ -579,7 +590,7 @@ void TypedBytecodeLowering::LowerTypedLdObjByName(GateRef gate) void TypedBytecodeLowering::LowerTypedStObjByName(GateRef gate) { DISALLOW_GARBAGE_COLLECTION; - StoreObjByNameTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_); + StoreObjByNameTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, chunk_); if (tacc.TypesIsEmpty() || tacc.HasIllegalType()) { return; } @@ -778,7 +789,7 @@ GateRef TypedBytecodeLowering::BuildNamedPropertyAccess( bool TypedBytecodeLowering::TryLowerTypedLdObjByNameForBuiltin(GateRef gate) { - LoadBulitinObjTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_); + LoadBulitinObjTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, chunk_); // Just supported mono. if (tacc.IsMono()) { if (tacc.IsBuiltinsType()) { @@ -808,7 +819,8 @@ bool TypedBytecodeLowering::TryLowerTypedLdObjByNameForBuiltin(const LoadBulitin { EcmaString *propString = EcmaString::Cast(tacc.GetKeyTaggedValue().GetTaggedObject()); // (1) get length - EcmaString *lengthString = EcmaString::Cast(thread_->GlobalConstants()->GetLengthString().GetTaggedObject()); + EcmaString *lengthString = + EcmaString::Cast(compilationEnv_->GlobalConstants()->GetLengthString().GetTaggedObject()); if (propString == lengthString) { if (tacc.IsBuiltinsArray()) { LowerTypedLdArrayLength(tacc); @@ -836,9 +848,9 @@ bool TypedBytecodeLowering::TryLowerTypedLdObjByNameForGlobalsId(const LoadBulit GateRef frameState = acc_.FindNearestFrameState(gate); if (globalsId.IsGlobalConstId()) { ConstantIndex index = static_cast(globalsId.GetGlobalConstId()); - JSHClass *hclass = JSHClass::Cast(thread_->GlobalConstants()->GetGlobalConstantObject( + JSHClass *hclass = JSHClass::Cast(compilationEnv_->GlobalConstants()->GetGlobalConstantObject( static_cast(index)).GetTaggedObject()); - PropertyLookupResult plr = JSHClass::LookupPropertyInBuiltinHClass(thread_, hclass, key); + PropertyLookupResult plr = JSHClass::LookupPropertyInBuiltinHClass(compilationEnv_->GetJSThread(), hclass, key); if (!plr.IsFound() || plr.IsAccessor()) { return false; } @@ -857,9 +869,9 @@ bool TypedBytecodeLowering::TryLowerTypedLdObjByNameForGlobalsId(const LoadBulit return true; } else if (globalsId.IsGlobalEnvId()) { // ctor Hclass GlobalEnvField index = static_cast(globalsId.GetGlobalEnvId()); - JSHClass *hclass = JSHClass::Cast(thread_->GetGlobalEnv()->GetGlobalEnvObjectByIndex( + JSHClass *hclass = JSHClass::Cast(compilationEnv_->GetGlobalEnv()->GetGlobalEnvObjectByIndex( static_cast(index))->GetTaggedObject()->GetClass()); - PropertyLookupResult plr = JSHClass::LookupPropertyInBuiltinHClass(thread_, hclass, key); + PropertyLookupResult plr = JSHClass::LookupPropertyInBuiltinHClass(compilationEnv_->GetJSThread(), hclass, key); if (!plr.IsFound() || plr.IsAccessor()) { return false; } @@ -881,19 +893,19 @@ bool TypedBytecodeLowering::TryLowerTypedLdObjByNameForGlobalsId(const LoadBulit bool TypedBytecodeLowering::TryLowerTypedLdobjBynameFromGloablBuiltin(GateRef gate) { - LoadBulitinObjTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_); + LoadBulitinObjTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, chunk_); GateRef receiver = tacc.GetReceiver(); if (acc_.GetOpCode(receiver) != OpCode::LOAD_BUILTIN_OBJECT) { return false; } - JSHandle globalEnv = thread_->GetEcmaVM()->GetGlobalEnv(); + JSHandle globalEnv = compilationEnv_->GetGlobalEnv(); uint64_t index = acc_.TryGetValue(receiver); BuiltinType type = static_cast(index); if (type == BuiltinType::BT_MATH) { auto math = globalEnv->GetMathFunction(); JSHClass *hclass = math.GetTaggedValue().GetTaggedObject()->GetClass(); JSTaggedValue key = tacc.GetKeyTaggedValue(); - PropertyLookupResult plr = JSHClass::LookupPropertyInBuiltinHClass(thread_, hclass, key); + PropertyLookupResult plr = JSHClass::LookupPropertyInBuiltinHClass(compilationEnv_->GetJSThread(), hclass, key); if (!plr.IsFound() || plr.IsAccessor()) { return false; } @@ -959,9 +971,10 @@ bool TypedBytecodeLowering::TryLowerTypedLdObjByNameForBuiltinMethod(const LoadB return false; } size_t protoFieldIndex = static_cast(*protoField); - JSHandle globalEnv = thread_->GetEcmaVM()->GetGlobalEnv(); + JSHandle globalEnv = compilationEnv_->GetGlobalEnv(); JSHClass *prototypeHClass = globalEnv->GetGlobalEnvObjectByIndex(protoFieldIndex)->GetTaggedObject()->GetClass(); - PropertyLookupResult plr = JSHClass::LookupPropertyInBuiltinPrototypeHClass(thread_, prototypeHClass, key); + PropertyLookupResult plr = JSHClass::LookupPropertyInBuiltinPrototypeHClass(compilationEnv_->GetJSThread(), + prototypeHClass, key); bool isPrototypeOfPrototype = false; // Unable to handle accessor at the moment if (!plr.IsFound() || plr.IsAccessor()) { @@ -972,7 +985,8 @@ bool TypedBytecodeLowering::TryLowerTypedLdObjByNameForBuiltinMethod(const LoadB } protoFieldIndex = static_cast(*protoField); prototypeHClass = globalEnv->GetGlobalEnvObjectByIndex(protoFieldIndex)->GetTaggedObject()->GetClass(); - plr = JSHClass::LookupPropertyInBuiltinPrototypeHClass(thread_, prototypeHClass, key); + plr = JSHClass::LookupPropertyInBuiltinPrototypeHClass(compilationEnv_->GetJSThread(), + prototypeHClass, key); if (!plr.IsFound() || plr.IsAccessor()) { return false; } else { @@ -1007,7 +1021,7 @@ bool TypedBytecodeLowering::TryLowerTypedLdObjByNameForBuiltinMethod(const LoadB bool TypedBytecodeLowering::TryLowerTypedLdObjByIndexForBuiltin(GateRef gate) { - LoadBulitinObjTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_); + LoadBulitinObjTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, chunk_); GateRef result = Circuit::NullGate(); // Just supported mono. if (tacc.IsMono()) { @@ -1030,7 +1044,7 @@ void TypedBytecodeLowering::LowerTypedLdObjByIndex(GateRef gate) bool TypedBytecodeLowering::TryLowerTypedStObjByIndexForBuiltin(GateRef gate) { - StoreBulitinObjTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_); + StoreBulitinObjTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, chunk_); if (tacc.GetBuiltinsJSType() != JSType::JS_FLOAT32_ARRAY) { return false; } @@ -1062,7 +1076,7 @@ void TypedBytecodeLowering::LowerTypedStObjByIndex(GateRef gate) bool TypedBytecodeLowering::TryLowerTypedLdObjByValueForBuiltin(GateRef gate) { - LoadBulitinObjTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_); + LoadBulitinObjTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, chunk_); GateRef result = Circuit::NullGate(); // Just supported mono. if (tacc.IsMono()) { @@ -1249,7 +1263,7 @@ void TypedBytecodeLowering::StoreTypedArrayByIndex(const StoreBulitinObjTypeInfo bool TypedBytecodeLowering::TryLowerTypedStObjByValueForBuiltin(GateRef gate) { - StoreBulitinObjTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_); + StoreBulitinObjTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, chunk_); // Just supported mono. if (tacc.IsMono()) { if (tacc.IsBuiltinsArray()) { @@ -1277,7 +1291,7 @@ void TypedBytecodeLowering::LowerTypedStObjByValue(GateRef gate) void TypedBytecodeLowering::LowerTypedIsTrueOrFalse(GateRef gate, bool flag) { - UnOpTypeInfoAccessor tacc(thread_, circuit_, gate); + UnOpTypeInfoAccessor tacc(compilationEnv_, circuit_, gate); ParamType paramType; if (TypeInfoAccessor::IsTrustedBooleanType(acc_, tacc.GetValue())) { paramType = ParamType::BooleanType(); @@ -1302,7 +1316,7 @@ void TypedBytecodeLowering::LowerTypedNewObjRange(GateRef gate) if (TryLowerNewBuiltinConstructor(gate)) { return; } - NewObjRangeTypeInfoAccessor tacc(thread_, circuit_, gate); + NewObjRangeTypeInfoAccessor tacc(compilationEnv_, circuit_, gate); if (!tacc.FindHClass()) { return; } @@ -1328,7 +1342,7 @@ void TypedBytecodeLowering::LowerTypedNewObjRange(GateRef gate) bool TypedBytecodeLowering::TryLowerNewBuiltinConstructor(GateRef gate) { - NewBuiltinCtorTypeInfoAccessor tacc(thread_, circuit_, gate); + NewBuiltinCtorTypeInfoAccessor tacc(compilationEnv_, circuit_, gate); if (!tacc.IsBuiltinModule()) { return false; } @@ -1358,7 +1372,7 @@ bool TypedBytecodeLowering::TryLowerNewBuiltinConstructor(GateRef gate) void TypedBytecodeLowering::LowerTypedSuperCall(GateRef gate) { - SuperCallTypeInfoAccessor tacc(thread_, circuit_, gate); + SuperCallTypeInfoAccessor tacc(compilationEnv_, circuit_, gate); if (!tacc.IsClassTypeKind() && !tacc.IsValidCallMethodId()) { return; } @@ -1600,7 +1614,7 @@ const JSPandaFile* TypedBytecodeLowering::GetCalleePandaFile(GateRef gate) void TypedBytecodeLowering::LowerTypedCallArg0(GateRef gate) { - CallArg0TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); + CallArg0TypeInfoAccessor tacc(compilationEnv_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); if (!tacc.IsValidCallMethodId()) { return; } @@ -1609,7 +1623,7 @@ void TypedBytecodeLowering::LowerTypedCallArg0(GateRef gate) void TypedBytecodeLowering::LowerTypedCallArg1(GateRef gate) { - CallArg1TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); + CallArg1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); GateRef func = tacc.GetFunc(); GateRef a0Value = tacc.GetValue(); BuiltinsStubCSigns::ID id = tacc.TryGetPGOBuiltinMethodId(); @@ -1626,7 +1640,7 @@ void TypedBytecodeLowering::LowerTypedCallArg1(GateRef gate) void TypedBytecodeLowering::LowerTypedCallArg2(GateRef gate) { - CallArg2TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); + CallArg2TypeInfoAccessor tacc(compilationEnv_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); if (!tacc.IsValidCallMethodId()) { return; } @@ -1635,7 +1649,7 @@ void TypedBytecodeLowering::LowerTypedCallArg2(GateRef gate) void TypedBytecodeLowering::LowerTypedCallArg3(GateRef gate) { - CallArg3TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); + CallArg3TypeInfoAccessor tacc(compilationEnv_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); if (!tacc.IsValidCallMethodId()) { return; } @@ -1644,7 +1658,7 @@ void TypedBytecodeLowering::LowerTypedCallArg3(GateRef gate) void TypedBytecodeLowering::LowerTypedCallrange(GateRef gate) { - CallRangeTypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); + CallRangeTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); if (!tacc.IsValidCallMethodId()) { return; } @@ -1717,7 +1731,7 @@ void TypedBytecodeLowering::LowerTypedThisCall(const TypeAccessor &tacc) void TypedBytecodeLowering::LowerTypedCallthis0(GateRef gate) { - CallThis0TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); + CallThis0TypeInfoAccessor tacc(compilationEnv_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); BuiltinsStubCSigns::ID pgoFuncId = tacc.TryGetPGOBuiltinMethodId(); if (IS_TYPED_BUILTINS_ID_CALL_THIS0(pgoFuncId)) { AddProfiling(gate); @@ -1732,7 +1746,7 @@ void TypedBytecodeLowering::LowerTypedCallthis0(GateRef gate) void TypedBytecodeLowering::LowerTypedCallthis1(GateRef gate) { - CallThis1TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); + CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); BuiltinsStubCSigns::ID pgoFuncId = tacc.TryGetPGOBuiltinMethodId(); if (IS_TYPED_BUILTINS_ID_CALL_THIS1(pgoFuncId)) { AddProfiling(gate); @@ -1747,7 +1761,7 @@ void TypedBytecodeLowering::LowerTypedCallthis1(GateRef gate) void TypedBytecodeLowering::LowerTypedCallthis2(GateRef gate) { - CallThis2TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); + CallThis2TypeInfoAccessor tacc(compilationEnv_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); if (!tacc.CanOptimizeAsFastCall()) { return; } @@ -1756,7 +1770,7 @@ void TypedBytecodeLowering::LowerTypedCallthis2(GateRef gate) void TypedBytecodeLowering::LowerTypedCallthis3(GateRef gate) { - CallThis3TypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); + CallThis3TypeInfoAccessor tacc(compilationEnv_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); BuiltinsStubCSigns::ID pgoFuncId = tacc.TryGetPGOBuiltinMethodId(); if (IS_TYPED_BUILTINS_ID_CALL_THIS3(pgoFuncId)) { AddProfiling(gate); @@ -1771,7 +1785,7 @@ void TypedBytecodeLowering::LowerTypedCallthis3(GateRef gate) void TypedBytecodeLowering::LowerTypedCallthisrange(GateRef gate) { - CallThisRangeTypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); + CallThisRangeTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); if (!tacc.CanOptimizeAsFastCall()) { return; } @@ -1862,7 +1876,7 @@ void TypedBytecodeLowering::AddHitBytecodeCount() void TypedBytecodeLowering::LowerTypedTypeOf(GateRef gate) { - TypeOfTypeInfoAccessor tacc(thread_, circuit_, gate); + TypeOfTypeInfoAccessor tacc(compilationEnv_, circuit_, gate); if (tacc.IsIllegalType()) { return; } @@ -1876,7 +1890,7 @@ void TypedBytecodeLowering::LowerTypedTypeOf(GateRef gate) void TypedBytecodeLowering::LowerGetIterator(GateRef gate) { - GetIteratorTypeInfoAccessor tacc(thread_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); + GetIteratorTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, GetCalleePandaFile(gate), callMethodFlagMap_); BuiltinsStubCSigns::ID id = tacc.TryGetPGOBuiltinMethodId(); if (id == BuiltinsStubCSigns::ID::NONE) { return; @@ -1892,7 +1906,7 @@ void TypedBytecodeLowering::LowerTypedTryLdGlobalByName(GateRef gate) return; } DISALLOW_GARBAGE_COLLECTION; - LoadGlobalObjByNameTypeInfoAccessor tacc(thread_, circuit_, gate); + LoadGlobalObjByNameTypeInfoAccessor tacc(compilationEnv_, circuit_, gate); JSTaggedValue key = tacc.GetKeyTaggedValue(); BuiltinIndex& builtin = BuiltinIndex::GetInstance(); @@ -1908,7 +1922,7 @@ void TypedBytecodeLowering::LowerTypedTryLdGlobalByName(GateRef gate) void TypedBytecodeLowering::LowerInstanceOf(GateRef gate) { - InstanceOfTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_); + InstanceOfTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, chunk_); if (tacc.TypesIsEmpty() || tacc.HasIllegalType()) { return; } @@ -1939,7 +1953,7 @@ void TypedBytecodeLowering::LowerCreateEmptyObject(GateRef gate) GateRef globalEnv = builder_.GetGlobalEnv(); GateRef hclass = builder_.GetGlobalEnvObjHClass(globalEnv, GlobalEnv::OBJECT_FUNCTION_INDEX); - JSHandle objectFunc(tsManager_->GetEcmaVM()->GetGlobalEnv()->GetObjectFunction()); + JSHandle objectFunc(compilationEnv_->GetGlobalEnv()->GetObjectFunction()); JSTaggedValue protoOrHClass = objectFunc->GetProtoOrHClass(); JSHClass *objectHC = JSHClass::Cast(protoOrHClass.GetTaggedObject()); size_t objectSize = objectHC->GetObjectSize(); @@ -1976,7 +1990,8 @@ void TypedBytecodeLowering::LowerTypedStOwnByValue(GateRef gate) void TypedBytecodeLowering::LowerCreateObjectWithBuffer(GateRef gate) { - CreateObjWithBufferTypeInfoAccessor tacc(thread_, circuit_, gate, recordName_); + DISALLOW_GARBAGE_COLLECTION; + CreateObjWithBufferTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, recordName_); if (!tacc.CanOptimize()) { return; } @@ -1984,9 +1999,9 @@ void TypedBytecodeLowering::LowerCreateObjectWithBuffer(GateRef gate) if (hclassVal.IsUndefined()) { return; } - JSHandle newClass(thread_, hclassVal); + JSHClass *newClass = JSHClass::Cast(hclassVal.GetTaggedObject()); GateRef index = tacc.GetIndex(); - JSHandle objhandle = tacc.GetObjHandle(); + JSObject *objhandle = JSObject::Cast(tacc.GetObject()); std::vector inlinedProps; auto layout = LayoutInfo::Cast(newClass->GetLayout().GetTaggedObject()); for (uint32_t i = 0; i < newClass->GetInlinedProperties(); i++) { @@ -2009,7 +2024,7 @@ void TypedBytecodeLowering::LowerCreateObjectWithBuffer(GateRef gate) std::vector valueIn; valueIn.emplace_back(builder_.IntPtr(size)); valueIn.emplace_back(index); - valueIn.emplace_back(builder_.Int64(newClass.GetTaggedValue().GetRawData())); + valueIn.emplace_back(builder_.Int64(JSTaggedValue(newClass).GetRawData())); valueIn.emplace_back(acc_.GetValueIn(gate, 1)); for (uint32_t i = 0; i < newClass->GetInlinedProperties(); i++) { auto attr = layout->GetAttr(i); diff --git a/ecmascript/compiler/typed_bytecode_lowering.h b/ecmascript/compiler/typed_bytecode_lowering.h index 771e2d9dda..6cb8f7f55d 100644 --- a/ecmascript/compiler/typed_bytecode_lowering.h +++ b/ecmascript/compiler/typed_bytecode_lowering.h @@ -57,8 +57,8 @@ public: glue_(acc_.GetGlueFromArgList()), argAcc_(circuit), pgoTypeLog_(circuit), - noCheck_(ctx->GetEcmaVM()->GetJSOptions().IsCompilerNoCheck()), - thread_(ctx->GetEcmaVM()->GetJSThread()), + noCheck_(ctx->GetCompilationEnv()->GetJSOptions().IsCompilerNoCheck()), + compilationEnv_(ctx->GetCompilationEnv()), enableLoweringBuiltin_(enableLoweringBuiltin), recordName_(recordName), callMethodFlagMap_(callMethodFlagMap), @@ -248,7 +248,7 @@ private: std::unordered_map bytecodeMap_; std::unordered_map bytecodeHitTimeMap_; bool noCheck_ {false}; - const JSThread *thread_ {nullptr}; + const CompilationEnv *compilationEnv_ {nullptr}; bool enableLoweringBuiltin_ {false}; const CString &recordName_; const CallMethodFlagMap *callMethodFlagMap_; diff --git a/ecmascript/compiler/typed_hcr_lowering.cpp b/ecmascript/compiler/typed_hcr_lowering.cpp index 4b2b1fe32d..7f86ce1a73 100644 --- a/ecmascript/compiler/typed_hcr_lowering.cpp +++ b/ecmascript/compiler/typed_hcr_lowering.cpp @@ -540,10 +540,9 @@ void TypedHCRLowering::BuiltinInstanceHClassCheck(Environment *env, GateRef gate GateRef glue = acc_.GetGlueFromArgList(); GateRef receiver = acc_.GetValueIn(gate, 0); GateRef ihcMatches = Circuit::NullGate(); - JSThread *thread = tsManager_->GetThread(); if (type == BuiltinTypeId::ARRAY) { if (Elements::IsGeneric(kind)) { - auto arrayHClassIndexMap = thread->GetArrayHClassIndexMap(); + auto arrayHClassIndexMap = compilationEnv_->GetArrayHClassIndexMap(); auto iter = arrayHClassIndexMap.find(kind); ASSERT(iter != arrayHClassIndexMap.end()); GateRef initialIhcAddress = builder_.GetGlobalConstantValue(iter->second); @@ -582,9 +581,8 @@ void TypedHCRLowering::BuiltinPrototypeHClassCheck(Environment *env, GateRef gat GateRef frameState = GetFrameState(gate); GateRef glue = acc_.GetGlueFromArgList(); GateRef receiver = acc_.GetValueIn(gate, 0); - JSThread *thread = tsManager_->GetThread(); // Only HClasses recorded in the JSThread during builtin initialization are available - [[maybe_unused]] JSHClass *initialPrototypeHClass = thread->GetBuiltinPrototypeHClass(type); + [[maybe_unused]] JSHClass *initialPrototypeHClass = compilationEnv_->GetBuiltinPrototypeHClass(type); ASSERT(initialPrototypeHClass != nullptr); // Phc = PrototypeHClass diff --git a/ecmascript/compiler/typed_hcr_lowering.h b/ecmascript/compiler/typed_hcr_lowering.h index 62c79e59b0..f016466253 100644 --- a/ecmascript/compiler/typed_hcr_lowering.h +++ b/ecmascript/compiler/typed_hcr_lowering.h @@ -21,6 +21,7 @@ #include "ecmascript/compiler/circuit_builder-inl.h" #include "ecmascript/compiler/combined_pass_visitor.h" #include "ecmascript/compiler/type_info_accessors.h" +#include "ecmascript/compiler/pass_manager.h" namespace panda::ecmascript::kungfu { // TypeHCRLowering Process @@ -100,13 +101,15 @@ namespace panda::ecmascript::kungfu { class TypedHCRLowering : public PassVisitor { public: TypedHCRLowering(Circuit* circuit, - RPOVisitor* visitor, - CompilationConfig* cmpCfg, - TSManager* tsManager, - Chunk* chunk, - bool enableLoweringBuiltin) + CompilationEnv *env, + RPOVisitor* visitor, + CompilationConfig* cmpCfg, + TSManager* tsManager, + Chunk* chunk, + bool enableLoweringBuiltin) : PassVisitor(circuit, chunk, visitor), circuit_(circuit), + compilationEnv_(env), acc_(circuit), builder_(circuit, cmpCfg), dependEntry_(circuit->GetDependRoot()), @@ -267,6 +270,7 @@ private: } Circuit *circuit_; + CompilationEnv *compilationEnv_ {nullptr}; GateAccessor acc_; CircuitBuilder builder_; GateRef dependEntry_; diff --git a/ecmascript/compiler/typed_native_inline_lowering.h b/ecmascript/compiler/typed_native_inline_lowering.h index a84a0313a3..413f79a4f8 100644 --- a/ecmascript/compiler/typed_native_inline_lowering.h +++ b/ecmascript/compiler/typed_native_inline_lowering.h @@ -34,7 +34,7 @@ public: circuit_(circuit), acc_(circuit), builder_(circuit, cmpCfg), - isLiteCG_(ctx->GetEcmaVM()->GetJSOptions().IsCompilerEnableLiteCG()) {} + isLiteCG_(ctx->GetCompilationEnv()->GetJSOptions().IsCompilerEnableLiteCG()) {} ~TypedNativeInlineLowering() = default; GateRef VisitGate(GateRef gate) override; private: diff --git a/ecmascript/ecma_context.cpp b/ecmascript/ecma_context.cpp index e6111624d1..129fd95f04 100644 --- a/ecmascript/ecma_context.cpp +++ b/ecmascript/ecma_context.cpp @@ -47,6 +47,7 @@ #include "ecmascript/snapshot/mem/snapshot.h" #include "ecmascript/platform/log.h" #include "ecmascript/global_index_map.h" +#include "ecmascript/jit/persistent_handles.h" namespace panda::ecmascript { using PathHelper = base::PathHelper; @@ -130,6 +131,8 @@ bool EcmaContext::Initialize() if (vm_->GetJSOptions().GetTypedOpProfiler()) { typedOpProfiler_ = new TypedOpProfiler(); } + + persistentHandlesList_ = new PersistentHandlesList(); initialized_ = true; return true; } @@ -197,6 +200,12 @@ EcmaContext::~EcmaContext() currentHandleStorageIndex_ = -1; handleScopeCount_ = 0; handleScopeStorageNext_ = handleScopeStorageEnd_ = nullptr; + + if (vm_->IsEnableJit()) { + // clear jit task + vm_->GetJit()->ClearTask(this); + } + ClearBufferData(); // clear c_address: c++ pointer delete if (!vm_->IsBundlePack()) { @@ -244,6 +253,10 @@ EcmaContext::~EcmaContext() delete propertiesCache_; propertiesCache_ = nullptr; } + if (persistentHandlesList_ != nullptr) { + delete persistentHandlesList_; + persistentHandlesList_ = nullptr; + } // clear join stack joinStack_.clear(); @@ -445,15 +458,25 @@ void EcmaContext::CJSExecution(JSHandle &func, JSHandleGetUnsharedConstpoolIndex(); // unshared constpool index is default INT32_MAX. ASSERT(0 <= constpoolIndex && constpoolIndex != ConstantPool::CONSTPOOL_TYPE_FLAG && constpoolIndex < UNSHARED_CONSTANTPOOL_COUNT); - JSTaggedValue unsharedConstpool = unsharedConstpools_[constpoolIndex]; + return unsharedConstpools_[constpoolIndex]; +} + +JSTaggedValue EcmaContext::FindOrCreateUnsharedConstpool(JSTaggedValue sharedConstpool) +{ + JSTaggedValue unsharedConstpool = FindUnsharedConstpool(sharedConstpool); if (unsharedConstpool.IsHole()) { + ConstantPool *shareCp = ConstantPool::Cast(sharedConstpool.GetTaggedObject()); + int32_t constpoolIndex = shareCp->GetUnsharedConstpoolIndex(); + // unshared constpool index is default INT32_MAX. + ASSERT(0 <= constpoolIndex && constpoolIndex != ConstantPool::CONSTPOOL_TYPE_FLAG && + constpoolIndex < UNSHARED_CONSTANTPOOL_COUNT); ASSERT(constpoolIndex != INT32_MAX); JSHandle unshareCp = ConstantPool::CreateUnSharedConstPoolBySharedConstpool(vm_, shareCp->GetJSPandaFile(), shareCp); @@ -901,6 +924,10 @@ void EcmaContext::Iterate(const RootVisitor &v, const RootRangeVisitor &rv) } } + if (persistentHandlesList_) { + persistentHandlesList_->Iterate(rv); + } + if (!joinStack_.empty()) { rv(Root::ROOT_VM, ObjectSlot(ToUintPtr(&joinStack_.front())), ObjectSlot(ToUintPtr(&joinStack_.back()) + JSTaggedValue::TaggedTypeSize())); @@ -1084,4 +1111,18 @@ std::tuple EcmaContext: callSiteInfo = thread_->GetEcmaVM()->GetHeap()->CalCallSiteInfo(retAddr); return callSiteInfo; } + +void EcmaContext::AddPersistentHandles(PersistentHandles *persistentHandle) +{ + if (persistentHandlesList_) { + persistentHandlesList_->AddPersistentHandles(persistentHandle); + } +} + +void EcmaContext::RemovePersistentHandles(PersistentHandles *persistentHandle) +{ + if (persistentHandlesList_) { + persistentHandlesList_->RemovePersistentHandles(persistentHandle); + } +} } // namespace panda::ecmascript diff --git a/ecmascript/ecma_context.h b/ecmascript/ecma_context.h index ce865b81d4..af8883c5eb 100644 --- a/ecmascript/ecma_context.h +++ b/ecmascript/ecma_context.h @@ -49,6 +49,8 @@ class JSPromise; class RegExpExecResultCache; class EcmaHandleScope; class GlobalIndexMap; +class PersistentHandlesList; +class PersistentHandles; enum class PromiseRejectionEvent : uint8_t; template @@ -269,6 +271,7 @@ public: // For new version instruction. JSTaggedValue PUBLIC_API FindConstpool(const JSPandaFile *jsPandaFile, panda_file::File::EntityId id); JSTaggedValue PUBLIC_API FindOrCreateUnsharedConstpool(JSTaggedValue sharedConstpool); + JSTaggedValue PUBLIC_API FindUnsharedConstpool(JSTaggedValue sharedConstpool); JSHandle CreateConstpoolPair(JSPandaFile *jsPandaFile, EntityId methodId); JSTaggedValue FindConstpoolWithAOT(const JSPandaFile *jsPandaFile, int32_t index); void EraseUnusedConstpool(const JSPandaFile *jsPandaFile, int32_t index, int32_t constpoolIndex); @@ -506,6 +509,9 @@ public: } std::tuple CalCallSiteInfo(uintptr_t retAddr) const; + + void AddPersistentHandles(PersistentHandles*); + void RemovePersistentHandles(PersistentHandles*); private: void CJSExecution(JSHandle &func, JSHandle &thisArg, const JSPandaFile *jsPandaFile, std::string_view entryPoint); @@ -620,6 +626,9 @@ private: std::array>, STRINGIFY_CACHE_SIZE> stringifyCache_ {}; bool isAotEntry_ { false }; + // PersistentHandlesList for jit compile hold ref + PersistentHandlesList *persistentHandlesList_ {nullptr}; + friend class EcmaHandleScope; friend class JSPandaFileExecutor; friend class ObjectFactory; diff --git a/ecmascript/ecma_handle_scope.cpp b/ecmascript/ecma_handle_scope.cpp index 0ae003996f..480e10364a 100644 --- a/ecmascript/ecma_handle_scope.cpp +++ b/ecmascript/ecma_handle_scope.cpp @@ -16,6 +16,7 @@ #include "ecmascript/ecma_handle_scope.h" #include "ecmascript/ecma_context.h" +#include "ecmascript/mem/assert_scope.h" namespace panda::ecmascript { EcmaHandleScope::EcmaHandleScope(JSThread *thread) : thread_(thread) @@ -48,6 +49,7 @@ EcmaHandleScope::~EcmaHandleScope() uintptr_t EcmaHandleScope::NewHandle(JSThread *thread, JSTaggedType value) { + CHECK_NO_HANDLE_ALLOC; auto context = thread->GetCurrentEcmaContext(); #ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK // Each Handle must be managed by HandleScope, otherwise it may cause Handle leakage. diff --git a/ecmascript/ecma_param_configuration.h b/ecmascript/ecma_param_configuration.h index a02b438d46..2190e3aa57 100644 --- a/ecmascript/ecma_param_configuration.h +++ b/ecmascript/ecma_param_configuration.h @@ -36,6 +36,7 @@ public: SHARED_HEAP }; + EcmaParamConfiguration() = default; EcmaParamConfiguration(HeapType heapType, size_t poolSize, size_t heapSize = 1_MB) { switch (heapType) { diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 47b50a52f6..02cfa65c5c 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -35,7 +35,7 @@ #include "ecmascript/compiler/common_stubs.h" #include "ecmascript/compiler/interpreter_stub.h" #include "ecmascript/compiler/rt_call_signature.h" -#include "ecmascript/jit/jit.h" +#include "ecmascript/jit/jit_task.h" #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER) #include "ecmascript/dfx/cpu_profiler/cpu_profiler.h" #endif @@ -193,6 +193,22 @@ EcmaVM::EcmaVM(JSRuntimeOptions options, EcmaParamConfiguration config) SetEnableOsr(options_.IsEnableOSR() && options_.IsEnableJIT() && options_.GetEnableAsmInterpreter()); } +// for jit +EcmaVM::EcmaVM() + : nativeAreaAllocator_(std::make_unique()), + heapRegionAllocator_(nullptr), + chunk_(nativeAreaAllocator_.get()) {} + +void EcmaVM::InitializeForJit(JitThread *jitThread) +{ + thread_ = jitThread; + stringTable_ = Runtime::GetInstance()->GetEcmaStringTable(); + ASSERT(stringTable_); + // ObjectFactory only sypport alloc string in sharedheap + factory_ = chunk_.New(thread_, nullptr, SharedHeap::GetInstance()); + SetIsJitCompileVM(true); +} + void EcmaVM::InitializePGOProfiler() { bool isEnablePGOProfiler = IsEnablePGOProfiler(); @@ -290,6 +306,15 @@ bool EcmaVM::Initialize() EcmaVM::~EcmaVM() { + if (isJitCompileVM_) { + if (factory_ != nullptr) { + delete factory_; + factory_ = nullptr; + } + stringTable_ = nullptr; + thread_ = nullptr; + return; + } ASSERT(thread_->IsInRunningStateOrProfiling()); initialized_ = false; #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER) @@ -304,6 +329,9 @@ EcmaVM::~EcmaVM() #if defined(ECMASCRIPT_SUPPORT_HEAPPROFILER) DeleteHeapProfile(); #endif + if (IsEnableJit()) { + GetJit()->ClearTaskWithVm(this); + } heap_->WaitAllTasksFinished(); Taskpool::GetCurrentTaskpool()->Destroy(thread_->GetThreadId()); diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index bdb7208f49..6a6110a510 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -91,6 +91,7 @@ class FunctionCallTimer; class EcmaStringTable; class JSObjectResizingStrategy; class Jit; +class JitThread; using NativePtrGetter = void* (*)(void* info); using SourceMapCallback = std::function; @@ -113,7 +114,7 @@ public: EcmaVM(); - ~EcmaVM(); + virtual ~EcmaVM(); void SetLoop(void *loop) { @@ -142,6 +143,7 @@ public: bool PUBLIC_API IsEnableElementsKind() const; bool Initialize(); + void InitializeForJit(JitThread *thread); GCStats *GetEcmaGCStats() const { @@ -670,6 +672,16 @@ public: return nativePointerCallbacks_; } + void SetIsJitCompileVM(bool isJitCompileVM) + { + isJitCompileVM_ = isJitCompileVM; + } + + bool IsJitCompileVM() const + { + return isJitCompileVM_; + } + static void InitializeIcuData(const JSRuntimeOptions &options); std::vector>> &GetSharedNativePointerCallbacks() @@ -800,9 +812,11 @@ private: friend class panda::JSNApi; friend class JSPandaFileExecutor; friend class EcmaContext; + friend class JitVM; CMap workerList_ {}; Mutex mutex_; bool isEnableOsr_ {false}; + bool isJitCompileVM_ {false}; bool overLimit_ {false}; void *env_ = nullptr; }; diff --git a/ecmascript/frames.cpp b/ecmascript/frames.cpp index 05cac382a3..e89f150a9f 100644 --- a/ecmascript/frames.cpp +++ b/ecmascript/frames.cpp @@ -111,6 +111,15 @@ JSTaggedValue FrameIterator::GetFunction() const AOTFileInfo::CallSiteInfo FrameIterator::CalCallSiteInfo(uintptr_t retAddr) const { + JSTaggedValue func = GetFunction(); + if (func.IsJSFunction()) { + JSFunction *jsfunc = JSFunction::Cast(func.GetTaggedObject()); + JSTaggedValue machineCode = jsfunc->GetMachineCode(); + if (machineCode.IsMachineCodeObject() && MachineCode::Cast(machineCode.GetTaggedObject())->IsInText(retAddr)) { + return MachineCode::Cast(machineCode.GetTaggedObject())->CalCallSiteInfo(retAddr); + } + } + return const_cast(thread_)->GetCurrentEcmaContext()->CalCallSiteInfo(retAddr); } diff --git a/ecmascript/jit/jit.cpp b/ecmascript/jit/jit.cpp index 7a514b2c61..f1ca2cfeec 100644 --- a/ecmascript/jit/jit.cpp +++ b/ecmascript/jit/jit.cpp @@ -19,8 +19,6 @@ #include "ecmascript/platform/file.h" namespace panda::ecmascript { -std::deque Jit::asyncCompileJitTasks_; -Mutex Jit::asyncCompileJitTasksMtx_; void (*Jit::initJitCompiler_)(JSRuntimeOptions options) = nullptr; bool(*Jit::jitCompile_)(void*, JitTask*) = nullptr; bool(*Jit::jitFinalize_)(void*, JitTask*) = nullptr; @@ -36,6 +34,7 @@ Jit *Jit::GetInstance() void Jit::SetEnableOrDisable(const JSRuntimeOptions &options, bool isEnable) { + LockHolder holder(setEnableLock_); if (options.IsEnableAPPJIT()) { // temporary for app jit options test. LOG_JIT(DEBUG) << (isEnable ? "jit is enable" : "jit is disable"); @@ -51,6 +50,24 @@ void Jit::SetEnableOrDisable(const JSRuntimeOptions &options, bool isEnable) if (initialized_ && !jitEnable_) { jitEnable_ = true; initJitCompiler_(options); + JitTaskpool::GetCurrentTaskpool()->Initialize(); + } +} + +void Jit::Destroy() +{ + if (!initialized_) { + return; + } + + LockHolder holder(setEnableLock_); + + JitTaskpool::GetCurrentTaskpool()->Destroy(); + initialized_ = false; + jitEnable_ = false; + if (libHandle_ != nullptr) { + CloseLib(libHandle_); + libHandle_ = nullptr; } } @@ -109,10 +126,6 @@ void Jit::Initialize() Jit::~Jit() { - if (libHandle_ != nullptr) { - CloseLib(libHandle_); - libHandle_ = nullptr; - } } bool Jit::SupportJIT(Method *method) @@ -146,93 +159,71 @@ void Jit::Compile(EcmaVM *vm, JSHandle &jsFunction, int32_t offset, Method *method = Method::Cast(jsFunction->GetMethod().GetTaggedObject()); CString fileDesc = method->GetJSPandaFile()->GetJSPandaFileDesc(); - FunctionKind kind = method->GetFunctionKind(); - CString methodName = method->GetRecordNameStr() + "." + CString(method->GetMethodName()) + ", at:" + fileDesc; - if (!jit->SupportJIT(method)) { - LOG_JIT(INFO) << "method does not support jit:" << methodName << ", kind:" << static_cast(kind); + uint32_t codeSize = method->GetCodeSize(); + CString methodInfo = method->GetRecordNameStr() + "." + CString(method->GetMethodName()) + ", at:" + fileDesc + + ", code size:" + ToCString(codeSize); + + constexpr uint32_t maxSize = 9000; + if (codeSize > maxSize) { + LOG_JIT(DEBUG) << "skip jit task, as too large:" << methodInfo; + return; + } + if (vm->GetJSThread()->IsMachineCodeLowMemory()) { + LOG_JIT(DEBUG) << "skip jit task, as low code memory:" << methodInfo; + return; + } + bool isJSSharedFunction = jsFunction.GetTaggedValue().IsJSSharedFunction(); + if (!jit->SupportJIT(method) || jsFunction.GetTaggedValue().IsJSSharedFunction()) { + FunctionKind kind = method->GetFunctionKind(); + LOG_JIT(DEBUG) << "method does not support jit:" << methodInfo << ", kind:" << static_cast(kind) + <<", JSSharedFunction:" << isJSSharedFunction; return; } if (jsFunction->GetMachineCode() == JSTaggedValue::Hole()) { - LOG_JIT(DEBUG) << "skip method, as it compiling:" << methodName; + LOG_JIT(DEBUG) << "skip method, as it compiling:" << methodInfo; return; } if (jsFunction->GetMachineCode() != JSTaggedValue::Undefined()) { MachineCode *machineCode = MachineCode::Cast(jsFunction->GetMachineCode().GetTaggedObject()); if (machineCode->GetOSROffset() == MachineCode::INVALID_OSR_OFFSET) { - LOG_JIT(DEBUG) << "skip method, as it has been jit compiled:" << methodName; + LOG_JIT(DEBUG) << "skip method, as it has been jit compiled:" << methodInfo; return; } } // using hole value to indecate compiling. todo: reset when failed jsFunction->SetMachineCode(vm->GetJSThread(), JSTaggedValue::Hole()); - - LOG_JIT(DEBUG) << "start compile:" << methodName << ", kind:" << static_cast(kind) << - ", mode:" << ((mode == SYNC) ? "sync" : "async") << - (offset == MachineCode::INVALID_OSR_OFFSET ? "" : ", OSR offset: " + std::to_string(offset)); - { - CString msg = "compile method:" + methodName + ", in work thread"; - Scope scope(msg); - - JitTask *jitTask = new JitTask(vm, jit, jsFunction, methodName, offset, vm->GetJSThread()->GetThreadId()); + CString msg = "compile method:" + methodInfo + ", in work thread"; + TimeScope scope(msg); + JitTaskpool::GetCurrentTaskpool()->WaitForJitTaskPoolReady(); + EcmaVM *compilerVm = JitTaskpool::GetCurrentTaskpool()->GetCompilerVm(); + std::shared_ptr jitTask = std::make_shared(vm->GetJSThread(), compilerVm->GetJSThread(), + jit, jsFunction, methodInfo, offset, vm->GetJSThread()->GetThreadId(), mode); jitTask->PrepareCompile(); - - jitTask->Optimize(); - + JitTaskpool::GetCurrentTaskpool()->PostTask( + std::make_unique(jitTask, vm->GetJSThread()->GetThreadId())); if (mode == SYNC) { - // cg - jitTask->Finalize(); + // sync mode, also compile in taskpool as litecg unsupport parallel compile, + // wait task compile finish then install code + jitTask->WaitFinish(); jitTask->InstallCode(); - // free - delete jitTask; - } else { - jit->AddAsyncCompileTask(jitTask); } } } -JitTask *Jit::GetAsyncCompileTask() -{ - LockHolder holder(asyncCompileJitTasksMtx_); - if (asyncCompileJitTasks_.empty()) { - return nullptr; - } else { - auto jitTask = asyncCompileJitTasks_.front(); - return jitTask; - } -} - -void Jit::AddAsyncCompileTask(JitTask *jitTask) -{ - LockHolder holder(asyncCompileJitTasksMtx_); - if (asyncCompileJitTasks_.empty()) { - Taskpool::GetCurrentTaskpool()->PostTask( - std::make_unique(jitTask, jitTask->GetVM()->GetJSThread()->GetThreadId())); - } - asyncCompileJitTasks_.push_back(jitTask); -} - -void Jit::RemoveAsyncCompileTask([[maybe_unused]] JitTask *jitTask) -{ - LockHolder holder(asyncCompileJitTasksMtx_); - ASSERT(!asyncCompileJitTasks_.empty()); - ASSERT(asyncCompileJitTasks_.front() == jitTask); - asyncCompileJitTasks_.pop_front(); -} - -void Jit::RequestInstallCode(JitTask *jitTask) +void Jit::RequestInstallCode(std::shared_ptr jitTask) { LockHolder holder(installJitTasksDequeMtx_); auto &taskQueue = installJitTasks_[jitTask->GetTaskThreadId()]; taskQueue.push_back(jitTask); // set - jitTask->GetVM()->GetJSThread()->SetInstallMachineCode(true); - jitTask->GetVM()->GetJSThread()->SetCheckSafePointStatus(); + jitTask->GetHostThread()->SetInstallMachineCode(true); + jitTask->GetHostThread()->SetCheckSafePointStatus(); } void Jit::InstallTasks(uint32_t threadId) @@ -240,10 +231,9 @@ void Jit::InstallTasks(uint32_t threadId) LockHolder holder(installJitTasksDequeMtx_); auto &taskQueue = installJitTasks_[threadId]; for (auto it = taskQueue.begin(); it != taskQueue.end(); it++) { - JitTask *task = *it; + std::shared_ptr task = *it; // check task state task->InstallCode(); - delete task; } taskQueue.clear(); } @@ -266,8 +256,54 @@ void *Jit::CreateJitCompilerTask(JitTask *jitTask) return createJitCompilerTask_(jitTask); } -Jit::Scope::~Scope() +void Jit::ClearTask(const std::function &checkClear) { - LOG_JIT(INFO) << message_ << ": " << TotalSpentTime() << "ms"; + JitTaskpool::GetCurrentTaskpool()->ForEachTask([&checkClear](Task *task) { + JitTask::AsyncTask *asyncTask = static_cast(task); + if (checkClear(asyncTask)) { + asyncTask->Terminated(); + } + + if (asyncTask->IsRunning()) { + asyncTask->WaitFinish(); + } + }); +} + +void Jit::ClearTask(EcmaContext *ecmaContext) +{ + ClearTask([ecmaContext](Task *task) { + JitTask::AsyncTask *asyncTask = static_cast(task); + return ecmaContext == asyncTask->GetEcmaContext(); + }); +} + +void Jit::ClearTaskWithVm(EcmaVM *vm) +{ + ClearTask([vm](Task *task) { + JitTask::AsyncTask *asyncTask = static_cast(task); + return vm == asyncTask->GetHostVM(); + }); + + LockHolder holder(installJitTasksDequeMtx_); + auto &taskQueue = installJitTasks_[vm->GetJSThread()->GetThreadId()]; + taskQueue.clear(); +} + +void Jit::CheckMechineCodeSpaceMemory(JSThread *thread, int remainSize) +{ + if (!thread->IsMachineCodeLowMemory()) { + return; + } + if (remainSize > MIN_CODE_SPACE_SIZE) { + thread->SetMachineCodeLowMemory(false); + } +} + +Jit::TimeScope::~TimeScope() +{ + if (outPutLog_) { + LOG_JIT(INFO) << message_ << ": " << TotalSpentTime() << "ms"; + } } } // namespace panda::ecmascript diff --git a/ecmascript/jit/jit.h b/ecmascript/jit/jit.h index 866ac0ef58..a5d826131f 100644 --- a/ecmascript/jit/jit.h +++ b/ecmascript/jit/jit.h @@ -21,6 +21,7 @@ #include "ecmascript/ecma_vm.h" #include "ecmascript/mem/clock_scope.h" #include "ecmascript/compiler/compiler_log.h" +#include "ecmascript/jit/jit_thread.h" namespace panda::ecmascript { class JitTask; @@ -32,9 +33,9 @@ class Jit { public: Jit() {} ~Jit(); - static Jit *GetInstance(); + static PUBLIC_API Jit *GetInstance(); void SetEnableOrDisable(const JSRuntimeOptions &options, bool isEnable); - bool IsEnable(); + bool PUBLIC_API IsEnable(); void Initialize(); static void Compile(EcmaVM *vm, JSHandle &jsFunction, @@ -49,22 +50,91 @@ public: void DeleteJitCompile(void *compiler); - void RequestInstallCode(JitTask *jitTask); + void RequestInstallCode(std::shared_ptr jitTask); void InstallTasks(uint32_t threadId); - - JitTask *GetAsyncCompileTask(); - void AddAsyncCompileTask(JitTask *jitTask); - void RemoveAsyncCompileTask(JitTask *jitTask); + void ClearTask(const std::function &checkClear); + void ClearTask(EcmaContext *ecmaContext); + void ClearTaskWithVm(EcmaVM *vm); + void Destroy(); + void CheckMechineCodeSpaceMemory(JSThread *thread, int remainSize); NO_COPY_SEMANTIC(Jit); NO_MOVE_SEMANTIC(Jit); - class Scope : public ClockScope { + class TimeScope : public ClockScope { public: - Scope(CString message) : message_(message) {} - ~Scope(); + explicit TimeScope(CString message, bool outPutLog = true) : message_(message), outPutLog_(outPutLog) {} + explicit TimeScope() : message_(""), outPutLog_(false) {} + PUBLIC_API ~TimeScope(); private: CString message_; + bool outPutLog_; + }; + + class JitLockHolder { + public: + explicit JitLockHolder(const CompilationEnv *env) : thread_(nullptr), scope_() + { + if (env->IsJitCompiler()) { + JSThread *thread = env->GetJSThread(); + ASSERT(thread->IsJitThread()); + thread_ = static_cast(thread); + thread_->ManagedCodeBegin(); + thread_->GetHostThread()->GetJitLock()->Lock(); + } + } + + explicit JitLockHolder(const CompilationEnv *env, CString message) : thread_(nullptr), + scope_("Jit Compile Pass: " + message + ", Time:", false) + { + if (env->IsJitCompiler()) { + JSThread *thread = env->GetJSThread(); + ASSERT(thread->IsJitThread()); + thread_ = static_cast(thread); + thread_->ManagedCodeBegin(); + thread_->GetHostThread()->GetJitLock()->Lock(); + } + } + + ~JitLockHolder() + { + if (thread_ != nullptr) { + thread_->GetHostThread()->GetJitLock()->Unlock(); + thread_->ManagedCodeEnd(); + } + } + JitThread *thread_ {nullptr}; + TimeScope scope_; + ALLOW_HEAP_ACCESS + NO_COPY_SEMANTIC(JitLockHolder); + NO_MOVE_SEMANTIC(JitLockHolder); + }; + + class JitGCLockHolder { + public: + explicit JitGCLockHolder(JSThread *thread) : thread_(thread) + { + ASSERT(!thread->IsJitThread()); + if (Jit::GetInstance()->IsEnable()) { + thread_->GetJitLock()->Lock(); + locked_ = true; + } + } + + ~JitGCLockHolder() + { + if (locked_) { + thread_->GetJitLock()->Unlock(); + locked_ = false; + } + } + + private: + JSThread *thread_; + bool locked_ { false }; + + NO_COPY_SEMANTIC(JitGCLockHolder); + NO_MOVE_SEMANTIC(JitGCLockHolder); }; private: @@ -72,10 +142,10 @@ private: bool initialized_ { false }; bool jitEnable_ { false }; - std::unordered_map> installJitTasks_; - static std::deque asyncCompileJitTasks_; + std::unordered_map>> installJitTasks_; Mutex installJitTasksDequeMtx_; - static Mutex asyncCompileJitTasksMtx_; + Mutex setEnableLock_; + static constexpr int MIN_CODE_SPACE_SIZE = 1_KB; static void (*initJitCompiler_)(JSRuntimeOptions); static bool(*jitCompile_)(void*, JitTask*); diff --git a/ecmascript/jit/jit_task.cpp b/ecmascript/jit/jit_task.cpp index 1b8b7cf5ed..acd39522fb 100644 --- a/ecmascript/jit/jit_task.cpp +++ b/ecmascript/jit/jit_task.cpp @@ -18,12 +18,53 @@ #include "ecmascript/global_env.h" #include "ecmascript/compiler/aot_file/func_entry_des.h" #include "ecmascript/ic/profile_type_info.h" +#include "ecmascript/jspandafile/program_object.h" namespace panda::ecmascript { + +JitTaskpool *JitTaskpool::GetCurrentTaskpool() +{ + static JitTaskpool *taskpool = new JitTaskpool(); + return taskpool; +} + +uint32_t JitTaskpool::TheMostSuitableThreadNum([[maybe_unused]]uint32_t threadNum) const +{ + return 1; +} + +JitTask::JitTask(JSThread *hostThread, JSThread *compilerThread, Jit *jit, JSHandle &jsFunction, + CString &methodName, int32_t offset, uint32_t taskThreadId, JitCompileMode mode) + : hostThread_(hostThread), + compilerThread_(compilerThread), + jit_(jit), + jsFunction_(jsFunction), + compilerTask_(nullptr), + state_(CompileState::SUCCESS), + methodInfo_(methodName), + offset_(offset), + taskThreadId_(taskThreadId), + ecmaContext_(nullptr), + jitCompileMode_(mode), + runState_(RunState::INIT) +{ + ecmaContext_ = hostThread->GetCurrentEcmaContext(); + persistentHandles_ = std::make_unique(hostThread->GetEcmaVM()); +} + void JitTask::PrepareCompile() { + CloneProfileTypeInfo(); PersistentHandle(); compilerTask_ = jit_->CreateJitCompilerTask(this); + + Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); + JSTaggedValue constpool = method->GetConstantPool(); + if (!ConstantPool::CheckUnsharedConstpool(constpool)) { + hostThread_->GetCurrentEcmaContext()->FindOrCreateUnsharedConstpool(constpool); + } + + SetRunState(RunState::INIT); } void JitTask::Optimize() @@ -55,30 +96,29 @@ void JitTask::InstallOsrCode(JSHandle &method, JSHandle &co } FuncEntryDes *funcEntryDes = reinterpret_cast(codeObj->GetFuncEntryDes()); method->SetIsFastCall(funcEntryDes->isFastCall_); - JSThread* thread = vm_->GetJSThread(); JSHandle profileInfoHandle = - JSHandle::Cast(JSHandle(thread, profile)); + JSHandle::Cast(JSHandle(hostThread_, profile)); uint32_t slotId = profileInfoHandle->GetCacheLength() - 1; // 1 : get last slot auto profileData = profileInfoHandle->Get(slotId); - auto factory = vm_->GetFactory(); + auto factory = hostThread_->GetEcmaVM()->GetFactory(); if (!profileData.IsTaggedArray()) { const uint32_t initLen = 1; JSHandle newArr = factory->NewTaggedArray(initLen); - newArr->Set(thread, 0, codeObj.GetTaggedValue()); - profileInfoHandle->Set(thread, slotId, newArr.GetTaggedValue()); + newArr->Set(hostThread_, 0, codeObj.GetTaggedValue()); + profileInfoHandle->Set(hostThread_, slotId, newArr.GetTaggedValue()); LOG_JIT(DEBUG) << "[OSR] Install machine code:" << GetMethodInfo() << ", code address: " << reinterpret_cast(codeObj->GetFuncAddr()) << ", index: " << newArr->GetLength() - 1; return; } - JSHandle arr(thread, profileData); + JSHandle arr(hostThread_, profileData); JSHandle newArr = factory->NewTaggedArray(arr->GetLength() + 1); // 1 : added for current codeObj uint32_t i = 0; for (; i < arr->GetLength(); i++) { - newArr->Set(thread, i, arr->Get(i)); + newArr->Set(hostThread_, i, arr->Get(i)); } - newArr->Set(thread, i, codeObj.GetTaggedValue()); - profileInfoHandle->Set(thread, slotId, newArr.GetTaggedValue()); + newArr->Set(hostThread_, i, codeObj.GetTaggedValue()); + profileInfoHandle->Set(hostThread_, slotId, newArr.GetTaggedValue()); LOG_JIT(DEBUG) << "[OSR] Install machine code:" << GetMethodInfo() << ", code address: " << reinterpret_cast(codeObj->GetFuncAddr()) << ", index: " << newArr->GetLength() - 1; @@ -90,7 +130,9 @@ void JitTask::InstallCode() if (!IsCompileSuccess()) { return; } - JSHandle methodHandle(vm_->GetJSThread(), Method::Cast(jsFunction_->GetMethod().GetTaggedObject())); + [[maybe_unused]] EcmaHandleScope handleScope(hostThread_); + + JSHandle methodHandle(hostThread_, Method::Cast(jsFunction_->GetMethod().GetTaggedObject())); size_t funcEntryDesSizeAlign = AlignUp(codeDesc_.funcEntryDesSize, MachineCode::TEXT_ALIGN); @@ -103,35 +145,68 @@ void JitTask::InstallCode() size_t size = funcEntryDesSizeAlign + rodataSizeBeforeTextAlign + codeSizeAlign + rodataSizeAfterTextAlign + stackMapSizeAlign; - JSHandle machineCodeObj = vm_->GetFactory()->NewMachineCodeObject(size, &codeDesc_, methodHandle); + methodHandle = hostThread_->GetEcmaVM()->GetFactory()->CloneMethod(methodHandle); + jsFunction_->SetMethod(hostThread_, methodHandle); + JSHandle machineCodeObj = + hostThread_->GetEcmaVM()->GetFactory()->NewMachineCodeObject(size, &codeDesc_, methodHandle); machineCodeObj->SetOSROffset(offset_); + + if (hostThread_->HasPendingException()) { + // check is oom exception + hostThread_->SetMachineCodeLowMemory(true); + hostThread_->ClearException(); + } + if (IsOsrTask()) { InstallOsrCode(methodHandle, machineCodeObj); return; } - // oom? + uintptr_t codeAddr = machineCodeObj->GetFuncAddr(); FuncEntryDes *funcEntryDes = reinterpret_cast(machineCodeObj->GetFuncEntryDes()); jsFunction_->SetCompiledFuncEntry(codeAddr, funcEntryDes->isFastCall_); - methodHandle->SetDeoptThreshold(vm_->GetJSOptions().GetDeoptThreshold()); - jsFunction_->SetMachineCode(vm_->GetJSThread(), machineCodeObj); + methodHandle->SetDeoptThreshold(hostThread_->GetEcmaVM()->GetJSOptions().GetDeoptThreshold()); + jsFunction_->SetMachineCode(hostThread_, machineCodeObj); LOG_JIT(DEBUG) << "Install machine code:" << GetMethodInfo(); } void JitTask::PersistentHandle() { - // transfer to global ref - GlobalHandleCollection globalHandleCollection(vm_->GetJSThread()); - JSHandle persistentHandle = - globalHandleCollection.NewHandle(jsFunction_.GetTaggedType()); - SetJsFunction(persistentHandle); + // transfer to persistent handle + JSHandle persistentJsFunctionHandle = persistentHandles_->NewHandle(jsFunction_); + SetJsFunction(persistentJsFunctionHandle); + + JSHandle profileTypeInfo = persistentHandles_->NewHandle(profileTypeInfo_); + SetProfileTypeInfo(profileTypeInfo); } void JitTask::ReleasePersistentHandle() { - GlobalHandleCollection globalHandleCollection(vm_->GetJSThread()); - globalHandleCollection.Dispose(jsFunction_); +} + +void JitTask::CloneProfileTypeInfo() +{ + [[maybe_unused]] EcmaHandleScope handleScope(hostThread_); + + Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); + uint32_t slotSize = method->GetSlotSize(); + JSTaggedValue profileTypeInfoVal = jsFunction_->GetProfileTypeInfo(); + JSHandle newProfileTypeInfo; + ObjectFactory *factory = hostThread_->GetEcmaVM()->GetFactory(); + if (profileTypeInfoVal.IsUndefined() || slotSize == 0) { + slotSize = slotSize == 0 ? 1 : slotSize; // there's no profiletypeinfo, just generate a temp profiletypeinfo + newProfileTypeInfo = factory->NewProfileTypeInfo(slotSize); + } else { + JSHandle profileTypeInfo(hostThread_, + ProfileTypeInfo::Cast(profileTypeInfoVal.GetTaggedObject())); + newProfileTypeInfo = factory->NewProfileTypeInfo(slotSize); + for (uint32_t i = 0; i < slotSize; i++) { + JSTaggedValue value = profileTypeInfo->Get(i); + newProfileTypeInfo->Set(hostThread_, i, value); + } + } + SetProfileTypeInfo(newProfileTypeInfo); } JitTask::~JitTask() @@ -140,23 +215,47 @@ JitTask::~JitTask() jit_->DeleteJitCompile(compilerTask_); } +void JitTask::WaitFinish() +{ + LockHolder lock(runStateMutex_); + if (!IsFinish()) { + runStateCondition_.Wait(&runStateMutex_); + } +} + bool JitTask::AsyncTask::Run([[maybe_unused]] uint32_t threadIndex) { - CString info = jitTask_->GetMethodInfo() + ", in task pool, id:" + ToCString(threadIndex) + ", time:"; - Jit::Scope scope(info); - - jitTask_->Finalize(); - - // info main thread compile complete - jitTask_->RequestInstallCode(); - - // as now litecg has global value, so only compile one task at a time - jitTask_->GetJit()->RemoveAsyncCompileTask(jitTask_); - JitTask *jitTask = jitTask_->GetJit()->GetAsyncCompileTask(); - if (jitTask != nullptr) { - Taskpool::GetCurrentTaskpool()->PostTask( - std::make_unique(jitTask, jitTask->GetVM()->GetJSThread()->GetThreadId())); + if (IsTerminate()) { + return false; } + DISALLOW_HEAP_ACCESS; + + // JitCompileMode ASYNC + // check init ok + jitTask_->SetRunState(RunState::RUNNING); + + JSThread *compilerThread = jitTask_->GetCompilerThread(); + ASSERT(compilerThread->IsJitThread()); + JitThread *jitThread = static_cast(compilerThread); + JitVM *jitvm = jitThread->GetJitVM(); + jitvm->SetHostVM(jitTask_->GetHostThread()); + + if (jitTask_->GetJsFunction().GetAddress() == 0) { + // for unit test + } else { + CString info = "compile method:" + jitTask_->GetMethodInfo() + ", in jit thread"; + Jit::TimeScope scope(info); + + jitTask_->Optimize(); + jitTask_->Finalize(); + + if (jitTask_->IsAsyncTask()) { + // info main thread compile complete + jitTask_->jit_->RequestInstallCode(jitTask_); + } + } + jitvm->ReSetHostVM(); + jitTask_->SetRunStateFinish(); return true; } } // namespace panda::ecmascript diff --git a/ecmascript/jit/jit_task.h b/ecmascript/jit/jit_task.h index c3b3f03403..e70760c916 100644 --- a/ecmascript/jit/jit_task.h +++ b/ecmascript/jit/jit_task.h @@ -21,6 +21,8 @@ #include "ecmascript/ecma_vm.h" #include "ecmascript/jit/jit.h" +#include "ecmascript/jit/jit_thread.h" +#include "ecmascript/jit/persistent_handles.h" namespace panda::ecmascript { enum CompileState : uint8_t { @@ -28,18 +30,71 @@ enum CompileState : uint8_t { FAIL, }; +enum RunState : uint8_t { + INIT = 0, + RUNNING, + FINISH +}; + +class JitTaskpool : public Taskpool { +public: + PUBLIC_API static JitTaskpool *GetCurrentTaskpool(); + JitTaskpool() = default; + NO_COPY_SEMANTIC(JitTaskpool); + NO_MOVE_SEMANTIC(JitTaskpool); + + EcmaVM *GetCompilerVm() + { + return compilerVm_; + } + + void SetCompilerVm(EcmaVM *vm) + { + LockHolder lock(jitTaskPoolMutex_); + compilerVm_ = vm; + jitTaskPoolCV_.SignalAll(); + } + + void WaitForJitTaskPoolReady() + { + LockHolder lock(jitTaskPoolMutex_); + if (compilerVm_ == nullptr) { + jitTaskPoolCV_.Wait(&jitTaskPoolMutex_); + } + } + + void Initialize() + { + RegisterRunnerHook([](os::thread::native_handle_type thread) { + os::thread::SetThreadName(thread, "OS_JIT_Thread"); + auto jitVm = JitVM::Create(); + JitTaskpool::GetCurrentTaskpool()->SetCompilerVm(jitVm); + }, []([[maybe_unused]] os::thread::native_handle_type thread) { + EcmaVM *compilerVm = JitTaskpool::GetCurrentTaskpool()->GetCompilerVm(); + JitVM::Destroy(compilerVm); + }); + Taskpool::Initialize(); + } + + void Destroy() + { + Taskpool::Destroy(compilerVm_->GetJSThread()->GetThreadId()); + } + +private: + uint32_t TheMostSuitableThreadNum(uint32_t threadNum) const override; + EcmaVM *compilerVm_; + Mutex jitTaskPoolMutex_; + ConditionVariable jitTaskPoolCV_; +}; + class JitTask { public: - JitTask(EcmaVM *vm, Jit *jit, JSHandle &jsFunction, CString &methodName, int32_t offset, - uint32_t taskThreadId) - : vm_(vm), - jit_(jit), - jsFunction_(jsFunction), - compilerTask_(nullptr), - state_(CompileState::SUCCESS), - methodInfo_(methodName), - offset_(offset), - taskThreadId_(taskThreadId) { } + JitTask(JSThread *hostThread, JSThread *compilerThread, Jit *jit, + JSHandle &jsFunction, CString &methodName, int32_t offset, + uint32_t taskThreadId, JitCompileMode mode); + // for ut + JitTask(EcmaVM *hVm, EcmaVM *cVm, Jit *jit, uint32_t taskThreadId, JitCompileMode mode); ~JitTask(); void Optimize(); void Finalize(); @@ -62,11 +117,6 @@ public: return offset_; } - void RequestInstallCode() - { - jit_->RequestInstallCode(this); - } - bool IsCompileSuccess() const { return state_ == CompileState::SUCCESS; @@ -87,9 +137,24 @@ public: return jit_; } - EcmaVM *GetVM() + JSThread *GetHostThread() { - return vm_; + return hostThread_; + } + + EcmaVM *GetHostVM() + { + return hostThread_->GetEcmaVM(); + } + + JSThread *GetCompilerThread() + { + return compilerThread_; + } + + JitVM *GetCompilerVM() + { + return static_cast(compilerThread_->GetEcmaVM()); } CString GetMethodInfo() const @@ -106,32 +171,106 @@ public: { return taskThreadId_; } + + EcmaContext *GetEcmaContext() const + { + return ecmaContext_; + } + + void SetRunState(RunState s) + { + runState_.store(s, std::memory_order_release); + } + + void SetRunStateFinish() + { + LockHolder lock(runStateMutex_); + runState_.store(RunState::FINISH); + runStateCondition_.SignalAll(); + } + + bool IsFinish() const + { + return runState_.load(std::memory_order_acquire) == RunState::FINISH; + } + bool IsRunning() const + { + return runState_.load(std::memory_order_acquire) == RunState::RUNNING; + } + void WaitFinish(); + bool IsAsyncTask() const + { + return jitCompileMode_ == JitCompileMode::ASYNC; + } + + void Terminated() + { + persistentHandles_->SetTerminated(); + } + class AsyncTask : public Task { public: - explicit AsyncTask(JitTask *jitTask, int32_t id) : Task(id), jitTask_(jitTask) { } + explicit AsyncTask(std::shared_ptrjitTask, int32_t id) : Task(id), jitTask_(jitTask) { } virtual ~AsyncTask() override = default; bool Run(uint32_t threadIndex) override; + EcmaContext *GetEcmaContext() const + { + return jitTask_->GetEcmaContext(); + } + EcmaVM *GetHostVM() const + { + return jitTask_->GetHostThread()->GetEcmaVM(); + } + bool IsRunning() const + { + return jitTask_->IsRunning(); + } + void WaitFinish() const + { + jitTask_->WaitFinish(); + } + + void Terminated() + { + Task::Terminated(); + jitTask_->Terminated(); + } private: - JitTask *jitTask_; + std::shared_ptr jitTask_ { nullptr }; }; private: void PersistentHandle(); void ReleasePersistentHandle(); + void CloneProfileTypeInfo(); void SetJsFunction(JSHandle &jsFunction) { jsFunction_ = jsFunction; } - EcmaVM *vm_; + void SetProfileTypeInfo(JSHandle &profileTypeInfo) + { + profileTypeInfo_ = profileTypeInfo; + } + + JSThread *hostThread_; + JSThread *compilerThread_; Jit *jit_; JSHandle jsFunction_; + JSHandle profileTypeInfo_; void *compilerTask_; MachineCodeDesc codeDesc_; CompileState state_; CString methodInfo_; int32_t offset_; uint32_t taskThreadId_; + std::unique_ptr persistentHandles_; + EcmaContext *ecmaContext_; + JitCompileMode jitCompileMode_; + + std::atomic runState_; + Mutex runStateMutex_; + ConditionVariable runStateCondition_; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_JIT_TASK_H diff --git a/ecmascript/jit/jit_thread.cpp b/ecmascript/jit/jit_thread.cpp new file mode 100644 index 0000000000..56d87405f6 --- /dev/null +++ b/ecmascript/jit/jit_thread.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecmascript/jit/jit_thread.h" +#include "ecmascript/ecma_vm.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/runtime.h" + +namespace panda::ecmascript { +JitThread::JitThread(JitVM *jitVM) : JSThread(jitVM, true) {}; + +JSThread *JitThread::GetHostThread() const +{ + return hostThread_; +} + +void JitThread::SetHostThread(JSThread *thread) +{ + hostThread_ = thread; +} + +JitVM *JitThread::GetJitVM() const +{ + return static_cast(JSThread::GetEcmaVM()); +} + +JitVM *JitVM::Create() +{ + auto vm = new JitVM(); + JitThread *thread = new JitThread(vm); + vm->jitThread_ = thread; + + // super ecmavm + vm->InitializeForJit(thread); + return vm; +} + +void JitVM::Destroy(EcmaVM *compilerVm) +{ + JitVM *jitVM = static_cast(compilerVm); + delete jitVM->jitThread_; + jitVM->jitThread_ = nullptr; + + delete jitVM; +} + +void JitVM::SetHostVM(JSThread *hostThread) +{ + hostVm_ = hostThread->GetEcmaVM(); + jitThread_->SetHostThread(hostThread); + + const GlobalEnvConstants *constants = hostThread->GlobalConstants(); + jitThread_->SetGlobalConstants(constants); +} + +void JitVM::ReSetHostVM() +{ + hostVm_ = nullptr; + jitThread_->SetHostThread(nullptr); + jitThread_->SetGlobalConstants(nullptr); +} + +} // namespace panda::ecmascript diff --git a/ecmascript/jit/jit_thread.h b/ecmascript/jit/jit_thread.h new file mode 100644 index 0000000000..e8ddc19340 --- /dev/null +++ b/ecmascript/jit/jit_thread.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_JIT_JIT_THREAD_H +#define ECMASCRIPT_JIT_JIT_THREAD_H + +#include "ecmascript/js_thread.h" +#include "ecmascript/ecma_vm.h" +#include "ecmascript/mem/heap.h" + +namespace panda::ecmascript { +class JitVM; +class JitThread final : public JSThread { +public: + JitThread(JitVM *jitVM); + EcmaVM *GetEcmaVM() const; + JSThread * PUBLIC_API GetHostThread() const; + void SetHostThread(JSThread *thread); + JitVM *GetJitVM() const; + +private: + JSThread *hostThread_ {nullptr}; +}; + +class JitVM final : public EcmaVM { +public: + JitVM() : EcmaVM() {} + static JitVM *Create(); + static void Destroy(EcmaVM *jitvm); + + EcmaVM *GetHostVm() const + { + return hostVm_; + } + + void SetHostVM(JSThread *hostThread); + void ReSetHostVM(); + +private: + EcmaVM *hostVm_ {nullptr}; + JitThread *jitThread_ {nullptr}; +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_JIT_TASK_H diff --git a/ecmascript/jit/persistent_handles.cpp b/ecmascript/jit/persistent_handles.cpp new file mode 100644 index 0000000000..101f9f3b4b --- /dev/null +++ b/ecmascript/jit/persistent_handles.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecmascript/jit/persistent_handles.h" + +namespace panda::ecmascript { +void PersistentHandles::Init() +{ + EcmaContext *context = vm_->GetJSThread()->GetCurrentEcmaContext(); + context->AddPersistentHandles(this); +} + +PersistentHandles::~PersistentHandles() +{ + if (!isTerminate_) { + EcmaContext *context = vm_->GetJSThread()->GetCurrentEcmaContext(); + context->RemovePersistentHandles(this); + } + for (auto block : handleBlocks_) { + delete block; + } + handleBlocks_.clear(); +} + +uintptr_t PersistentHandles::GetJsHandleSlot(JSTaggedType value) +{ + if (blockNext_ == blockLimit_) { + Expand(); + } + ASSERT(blockNext_ != blockLimit_); + + *blockNext_ = value; + uintptr_t slot = reinterpret_cast(blockNext_); + blockNext_++; + return slot; +} + +uintptr_t PersistentHandles::Expand() +{ + auto block = new std::array(); + handleBlocks_.push_back(block); + + blockNext_ = &block->data()[0]; + blockLimit_ = &block->data()[BLOCK_SIZE]; + return reinterpret_cast(blockNext_); +} + +void PersistentHandles::Iterate(const RootRangeVisitor &rv) +{ + size_t size = handleBlocks_.size(); + for (size_t i = 0; i < size; ++i) { + auto block = handleBlocks_.at(i); + auto start = block->data(); + auto end = (i != (size - 1)) ? &(block->data()[BLOCK_SIZE]) : blockNext_; + rv(ecmascript::Root::ROOT_HANDLE, ObjectSlot(ToUintPtr(start)), ObjectSlot(ToUintPtr(end))); + } +} + +void PersistentHandlesList::AddPersistentHandles(PersistentHandles *persistentHandles) +{ + LockHolder lock(mutex_); + if (persistentHandles == nullptr) { + return; + } + + if (listHead_ == nullptr) { + listHead_ = persistentHandles; + return; + } + persistentHandles->next_ = listHead_; + listHead_->pre_ = persistentHandles; + listHead_ = persistentHandles; +} + +void PersistentHandlesList::RemovePersistentHandles(PersistentHandles *persistentHandles) +{ + LockHolder lock(mutex_); + if (persistentHandles == nullptr) { + return; + } + + auto next = persistentHandles->next_; + auto pre = persistentHandles->pre_; + if (pre != nullptr) { + pre->next_ = next; + } + if (next != nullptr) { + next->pre_ = pre; + } + + if (listHead_ == persistentHandles) { + listHead_ = persistentHandles->next_; + } +} + +void PersistentHandlesList::Iterate(const RootRangeVisitor &rv) +{ + LockHolder lock(mutex_); + for (auto handles = listHead_; handles != nullptr; handles = handles->next_) { + handles->Iterate(rv); + } +} +} // namespace panda::ecmascript diff --git a/ecmascript/jit/persistent_handles.h b/ecmascript/jit/persistent_handles.h new file mode 100644 index 0000000000..2d00008e91 --- /dev/null +++ b/ecmascript/jit/persistent_handles.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_PERSISTENT_HANDLES_H +#define ECMASCRIPT_PERSISTENT_HANDLES_H + +#include "ecmascript/common.h" +#include "ecmascript/platform/mutex.h" +#include "ecmascript/ecma_vm.h" + +namespace panda::ecmascript { + +class PersistentHandles { +public: + PersistentHandles(EcmaVM *vm) : vm_(vm) + { + Init(); + } + ~PersistentHandles(); + template + JSHandle NewHandle(JSHandle value) + { + return JSHandle(GetJsHandleSlot(value.GetTaggedType())); + } + + template + JSHandle NewHandle(JSTaggedType value) + { + return JSHandle(GetJsHandleSlot(value)); + } + + void Iterate(const RootRangeVisitor &rv); + + void SetTerminated() + { + isTerminate_ = true; + } +private: + void Init(); + uintptr_t GetJsHandleSlot(JSTaggedType value); + uintptr_t Expand(); + + EcmaVM *vm_ { nullptr }; + + JSTaggedType *blockNext_ { nullptr }; + JSTaggedType *blockLimit_ { nullptr }; + PersistentHandles *pre_ { nullptr }; + PersistentHandles *next_ { nullptr }; + std::atomic_bool isTerminate_ {false}; + + static constexpr uint32_t BLOCK_SIZE = 256L; + std::vector*> handleBlocks_; + friend class PersistentHandlesList; +}; + +class PersistentHandlesList { +public: + void AddPersistentHandles(PersistentHandles *persistentHandles); + void RemovePersistentHandles(PersistentHandles *persistentHandles); + void Iterate(const RootRangeVisitor &rv); + +private: + PersistentHandles *listHead_ { nullptr }; + Mutex mutex_; +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_PERSISTENT_HANDLES_H diff --git a/ecmascript/js_handle.h b/ecmascript/js_handle.h index 81fcee1efd..a6ee0a1c1f 100644 --- a/ecmascript/js_handle.h +++ b/ecmascript/js_handle.h @@ -20,6 +20,7 @@ #include "ecmascript/ecma_handle_scope.h" #include "ecmascript/js_tagged_value.h" +#include "ecmascript/mem/assert_scope.h" /* * JSHandle: A JSHandle provides a reference to an object that survives relocation by the garbage collector. @@ -107,6 +108,7 @@ public: inline JSTaggedValue GetTaggedValue() const { + CHECK_NO_DEREF_HANDLE; if (GetAddress() == 0U) { return JSTaggedValue::Undefined(); } @@ -115,6 +117,7 @@ public: inline JSTaggedType GetTaggedType() const { + CHECK_NO_DEREF_HANDLE; if (GetAddress() == 0U) { return JSTaggedValue::Undefined().GetRawData(); } diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index 4c6c38411d..9919ef0494 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -44,6 +44,7 @@ #include "ecmascript/platform/file.h" #include "ecmascript/stackmap/llvm/llvm_stackmap_parser.h" #include "ecmascript/builtin_entries.h" +#include "ecmascript/jit/jit.h" namespace panda::ecmascript { using CommonStubCSigns = panda::ecmascript::kungfu::CommonStubCSigns; @@ -56,6 +57,30 @@ JSThread *JSThread::GetCurrent() return currentThread; } +// static +void JSThread::RegisterThread(JSThread *jsThread) +{ + Runtime::GetInstance()->RegisterThread(jsThread); + // If it is not true, we created a new thread for future fork + if (currentThread == nullptr) { + currentThread = jsThread; + jsThread->UpdateState(ThreadState::NATIVE); + } +} + +void JSThread::UnregisterThread(JSThread *jsThread) +{ + if (currentThread == jsThread) { + jsThread->UpdateState(ThreadState::TERMINATED); + currentThread = nullptr; + } else { + // We have created this JSThread instance but hadn't forked it. + ASSERT(jsThread->GetState() == ThreadState::CREATED); + jsThread->UpdateState(ThreadState::TERMINATED); + } + Runtime::GetInstance()->UnregisterThread(jsThread); +} + // static JSThread *JSThread::Create(EcmaVM *vm) { @@ -78,12 +103,7 @@ JSThread *JSThread::Create(EcmaVM *vm) jsThread->glueData_.stackLimit_ = GetAsmStackLimit(); jsThread->glueData_.stackStart_ = GetCurrentStackPosition(); - Runtime::GetInstance()->RegisterThread(jsThread); - // If it is not true, we created a new thread for future fork - if (currentThread == nullptr) { - currentThread = jsThread; - jsThread->UpdateState(ThreadState::NATIVE); - } + RegisterThread(jsThread); return jsThread; } @@ -115,6 +135,12 @@ JSThread::JSThread(EcmaVM *vm) : id_(os::thread::GetCurrentThreadId()), vm_(vm) SetBCStubStatus(BCStubStatus::NORMAL_BC_STUB); } +JSThread::JSThread(EcmaVM *vm, bool isJit) : id_(os::thread::GetCurrentThreadId()), vm_(vm), isJitThread_(isJit) +{ + ASSERT(isJit); + RegisterThread(this); +}; + JSThread::~JSThread() { readyForGCIterating_ = false; @@ -144,15 +170,7 @@ JSThread::~JSThread() delete vmThreadControl_; vmThreadControl_ = nullptr; } - if (currentThread == this) { - UpdateState(ThreadState::TERMINATED); - currentThread = nullptr; - } else { - // We have created this JSThread instance but hadn't forked it. - ASSERT(GetState() == ThreadState::CREATED); - UpdateState(ThreadState::TERMINATED); - } - Runtime::GetInstance()->UnregisterThread(this); + UnregisterThread(this); } void JSThread::SetException(JSTaggedValue exception) @@ -684,7 +702,7 @@ bool JSThread::CheckSafepoint() interruptMutex_.Unlock(); } - if (vm_->IsEnableJit() && HasInstallMachineCode()) { + if (HasInstallMachineCode()) { vm_->GetJit()->InstallTasks(GetThreadId()); SetInstallMachineCode(false); } diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 22a404051c..bc0baf3eaa 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -128,6 +128,8 @@ public: }; explicit JSThread(EcmaVM *vm); + // only used in jit thread + explicit JSThread(EcmaVM *vm, bool isJit); PUBLIC_API ~JSThread(); @@ -264,6 +266,11 @@ public: return glueData_.globalConst_; } + void SetGlobalConstants(const GlobalEnvConstants *constants) + { + glueData_.globalConst_ = const_cast(constants); + } + const BuiltinEntries GetBuiltinEntries() const { return glueData_.builtinEntries_; @@ -1236,6 +1243,28 @@ public: { finalizeTaskCallback_ = callback; } + + static void RegisterThread(JSThread *jsThread); + static void UnregisterThread(JSThread *jsThread); + bool IsJitThread() const + { + return isJitThread_; + } + + RecursiveMutex *GetJitLock() + { + return &jitMutex_; + } + + void SetMachineCodeLowMemory(bool isLow) + { + machineCodeLowMemory_ = isLow; + } + + bool IsMachineCodeLowMemory() + { + return machineCodeLowMemory_; + } private: NO_COPY_SEMANTIC(JSThread); NO_MOVE_SEMANTIC(JSThread); @@ -1336,6 +1365,9 @@ private: int32_t suspendCount_ {0}; ConditionVariable suspendCondVar_; + bool isJitThread_ {false}; + RecursiveMutex jitMutex_; + bool machineCodeLowMemory_ {false}; #ifndef NDEBUG MutatorLock::MutatorLockState mutatorLockState_ = MutatorLock::MutatorLockState::UNLOCKED; #endif @@ -1343,6 +1375,7 @@ private: friend class GlobalHandleCollection; friend class EcmaVM; friend class EcmaContext; + friend class JitVM; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_JS_THREAD_H diff --git a/ecmascript/jspandafile/js_pandafile.h b/ecmascript/jspandafile/js_pandafile.h index 3e7424da06..0439e79703 100644 --- a/ecmascript/jspandafile/js_pandafile.h +++ b/ecmascript/jspandafile/js_pandafile.h @@ -438,7 +438,7 @@ public: static FunctionKind PUBLIC_API GetFunctionKind(panda_file::FunctionKind funcKind); static FunctionKind GetFunctionKind(ConstPoolType type); - bool IsFirstMergedAbc() const; + bool PUBLIC_API IsFirstMergedAbc() const; const void *GetBase() const { return static_cast(pf_->GetBase()); diff --git a/ecmascript/jspandafile/program_object.h b/ecmascript/jspandafile/program_object.h index 16676d7af2..e7902a438a 100644 --- a/ecmascript/jspandafile/program_object.h +++ b/ecmascript/jspandafile/program_object.h @@ -616,6 +616,20 @@ public: return false; } + template + static JSTaggedValue GetLiteralFromCache(JSTaggedValue constpool, uint32_t index, [[maybe_unused]] CString entry) + { + const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); + auto val = taggedPool->GetObjectFromCache(index); + JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile(); + + bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); + if (isLoadedAOT && val.IsAOTLiteralInfo()) { + val = JSTaggedValue::Hole(); + } + return val.IsHole() ? JSTaggedValue::Undefined() : val; + } + static panda_file::File::EntityId GetIdFromCache(JSTaggedValue constpool, uint32_t index) { const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); @@ -631,6 +645,24 @@ public: return GetLiteralFromCache(thread, constpool, index, entry); } + static JSTaggedValue PUBLIC_API GetStringFromCacheForJit(JSThread *thread, JSTaggedValue constpool, uint32_t index) + { + const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); + auto val = taggedPool->Get(index); + if (val.IsHole()) { + JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile(); + panda_file::File::EntityId id = taggedPool->GetEntityId(index); + auto foundStr = jsPandaFile->GetStringData(id); + + EcmaVM *vm = thread->GetEcmaVM(); + ObjectFactory *factory = vm->GetFactory(); + auto string = factory->GetRawStringFromStringTable(foundStr, MemSpaceType::SHARED_OLD_SPACE, + jsPandaFile->IsFirstMergedAbc(), id.GetOffset()); + val = JSTaggedValue(string); + } + return val; + } + static JSTaggedValue PUBLIC_API GetStringFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index) { const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); diff --git a/ecmascript/layout_info-inl.h b/ecmascript/layout_info-inl.h index 64e013ca4f..c8e6d46e12 100644 --- a/ecmascript/layout_info-inl.h +++ b/ecmascript/layout_info-inl.h @@ -109,6 +109,11 @@ inline int LayoutInfo::FindElementWithCache(const JSThread *thread, JSHClass *cl return -1; } + // jit compile thread not use cache + if (thread->IsJitThread()) { + return BinarySearch(key, propertiesNumber); + } + PropertiesCache *cache = thread->GetPropertiesCache(); int index = cache->Get(cls, key); if (index == PropertiesCache::NOT_FOUND) { diff --git a/ecmascript/mem/assert_scope.h b/ecmascript/mem/assert_scope.h index 787a5e393d..b71eedd2f1 100644 --- a/ecmascript/mem/assert_scope.h +++ b/ecmascript/mem/assert_scope.h @@ -26,6 +26,8 @@ static thread_local size_t currentAssertData(~0); using AssertGarbageCollectBit = panda::BitField; using AssertHeapAllocBit = AssertGarbageCollectBit::NextFlag; +using AssertHandleAllocBit = AssertHeapAllocBit::NextFlag; +using AssertDeRefHandleBit = AssertHandleAllocBit::NextFlag; #ifndef NDEBUG constexpr bool IS_ALLOW_CHECK = true; @@ -33,7 +35,13 @@ constexpr bool IS_ALLOW_CHECK = true; constexpr bool IS_ALLOW_CHECK = false; #endif -enum class AssertType : uint8_t { GARBAGE_COLLECTION_ASSERT = 0, HEAP_ALLOC_ASSERT, LAST_ASSERT_TYPE }; +enum class AssertType : uint8_t { + GARBAGE_COLLECTION_ASSERT = 0, + HEAP_ALLOC_ASSERT, + HANDLE_ALLOC_ASSERT, + DEREF_HANDLE_ASSERT, + LAST_ASSERT_TYPE +}; template class AssertScopeT { @@ -56,6 +64,12 @@ public: case AssertType::HEAP_ALLOC_ASSERT: currentAssertData = AssertHeapAllocBit::Update(oldData_.value(), isAllow); break; + case AssertType::HANDLE_ALLOC_ASSERT: + currentAssertData = AssertHandleAllocBit::Update(oldData_.value(), isAllow); + break; + case AssertType::DEREF_HANDLE_ASSERT: + currentAssertData = AssertDeRefHandleBit::Update(oldData_.value(), isAllow); + break; default: break; } @@ -78,6 +92,12 @@ public: return AssertGarbageCollectBit::Decode(currentAssertData); case AssertType::HEAP_ALLOC_ASSERT: return AssertHeapAllocBit::Decode(currentAssertData); + case AssertType::HANDLE_ALLOC_ASSERT: + return AssertHandleAllocBit::Decode(currentAssertData); + break; + case AssertType::DEREF_HANDLE_ASSERT: + return AssertDeRefHandleBit::Decode(currentAssertData); + break; default: return true; } @@ -94,7 +114,10 @@ using DisallowGarbageCollection = AssertScopeT; using DisAllowHeapAlloc = AssertScopeT; using AllowHeapAlloc = AssertScopeT; - +using DisAllowHandleAllocation = AssertScopeT; +using AllowHandleAllocation = AssertScopeT; +using DisAllowDeRefHandle = AssertScopeT; +using AllowDeRefHandle = AssertScopeT; #if (!defined NDEBUG) || (defined RUN_TEST) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define DISALLOW_GARBAGE_COLLECTION [[maybe_unused]] DisallowGarbageCollection noGc @@ -104,18 +127,48 @@ using AllowHeapAlloc = AssertScopeTGetJSThread()); { ASSERT(thread_->IsInRunningStateOrProfiling()); RecursionScope recurScope(this); @@ -800,6 +802,12 @@ void Heap::CollectGarbage(TriggerGCType gcType, GCReason reason) #endif ASSERT(thread_->IsPropertyCacheCleared()); ProcessGCListeners(); + + if (GetEcmaVM()->IsEnableJit()) { + // check machine code space if enough + int remainSize = config_.GetDefaultMachineCodeSpaceSize() - GetMachineCodeSpace()->GetHeapObjectSize(); + Jit::GetInstance()->CheckMechineCodeSpaceMemory(GetEcmaVM()->GetJSThread(), remainSize); + } } void BaseHeap::ThrowOutOfMemoryError(JSThread *thread, size_t size, std::string functionName, diff --git a/ecmascript/mem/machine_code.cpp b/ecmascript/mem/machine_code.cpp index 03fa07723f..ca2dbce6aa 100644 --- a/ecmascript/mem/machine_code.cpp +++ b/ecmascript/mem/machine_code.cpp @@ -146,7 +146,10 @@ std::tuple MachineCode:: } tmpFuncEntryDes++; } - ASSERT(funcEntryDes != nullptr); + + if (funcEntryDes == nullptr) { + return {}; + } int delta = funcEntryDes->fpDeltaPrevFrameSp_; kungfu::CalleeRegAndOffsetVec calleeRegInfo; diff --git a/ecmascript/mem/shared_heap/shared_space.cpp b/ecmascript/mem/shared_heap/shared_space.cpp index 370db63510..9c6f5c4ddf 100644 --- a/ecmascript/mem/shared_heap/shared_space.cpp +++ b/ecmascript/mem/shared_heap/shared_space.cpp @@ -64,8 +64,10 @@ uintptr_t SharedSparseSpace::Allocate(JSThread *thread, size_t size, bool allowG { ASSERT(thread->IsInRunningStateOrProfiling()); thread->CheckSafepointIfSuspended(); + auto localHeap = const_cast(thread->GetEcmaVM()->GetHeap()); + // jit thread no heap + allowGC = allowGC && (localHeap != nullptr); if (allowGC) { - auto localHeap = const_cast(thread->GetEcmaVM()->GetHeap()); localHeap->TryTriggerFullMarkBySharedSize(size); } uintptr_t object = TryAllocate(thread, size); @@ -505,7 +507,9 @@ void SharedHugeObjectSpace::CheckAndTriggerLocalFullMark(JSThread *thread, size_ reinterpret_cast(heap_)->TryTriggerLocalConcurrentMarking(thread); } else { auto localHeap = const_cast(thread->GetEcmaVM()->GetHeap()); - localHeap->TryTriggerFullMarkBySharedSize(size); + if (localHeap != nullptr) { + localHeap->TryTriggerFullMarkBySharedSize(size); + } } } } // namespace panda::ecmascript diff --git a/ecmascript/mem/space.h b/ecmascript/mem/space.h index 11eed4f29d..195828be63 100644 --- a/ecmascript/mem/space.h +++ b/ecmascript/mem/space.h @@ -224,8 +224,7 @@ public: bool IsOOMDumpSpace() { - return spaceType_ == OLD_SPACE || spaceType_ == NON_MOVABLE || spaceType_ == HUGE_OBJECT_SPACE || - spaceType_ == MACHINE_CODE_SPACE; + return spaceType_ == OLD_SPACE || spaceType_ == NON_MOVABLE || spaceType_ == HUGE_OBJECT_SPACE; } // methods for allocation inspector diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index 9bbe661607..9dd37c2284 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -3254,6 +3254,7 @@ JSHandle ObjectFactory::NewBigInt(uint32_t length) // static void ObjectFactory::NewObjectHook() const { + CHECK_NO_HEAP_ALLOC; #ifndef NDEBUG if (vm_->GetJSOptions().EnableForceGC() && vm_->IsInitialized() && thread_->IsAllContextsInitialized()) { if (vm_->GetJSOptions().ForceFullGC()) { @@ -5109,4 +5110,20 @@ void ObjectFactory::FillFreeMemoryRange(uintptr_t start, uintptr_t end) start += sizeof(JSTaggedType); } } + +JSHandle ObjectFactory::CloneMethod(JSHandle method) +{ + TaggedObject *header = nullptr; + header = heap_->AllocateOldOrHugeObject( + JSHClass::Cast(thread_->GlobalConstants()->GetMethodClass().GetTaggedObject())); + JSHandle newmethod(thread_, header); + + newmethod->SetCallField(method->GetCallField()); + newmethod->SetLiteralInfo(method->GetLiteralInfo()); + newmethod->SetNativePointerOrBytecodeArray(method->GetNativePointerOrBytecodeArray()); + newmethod->SetExtraLiteralInfo(method->GetExtraLiteralInfo()); + newmethod->SetCodeEntryOrLiteral(method->GetCodeEntryOrLiteral()); + newmethod->SetConstantPool(thread_, method->GetConstantPool()); + return newmethod; +} } // namespace panda::ecmascript diff --git a/ecmascript/object_factory.h b/ecmascript/object_factory.h index 8023aff0bc..22a600fa4c 100644 --- a/ecmascript/object_factory.h +++ b/ecmascript/object_factory.h @@ -863,6 +863,7 @@ public: JSHandle NewSWellKnownSymbolWithChar(std::string_view description); JSHandle NewSPublicSymbolWithChar(std::string_view description); JSHandle NewSPublicSymbol(const JSHandle &name); + JSHandle CloneMethod(JSHandle method); private: friend class GlobalEnv; diff --git a/ecmascript/runtime.cpp b/ecmascript/runtime.cpp index c3786dcc3d..e15ec27cd6 100644 --- a/ecmascript/runtime.cpp +++ b/ecmascript/runtime.cpp @@ -67,8 +67,6 @@ void Runtime::CreateIfFirstVm(const JSRuntimeOptions &options) MemMapAllocator::GetInstance()->Initialize(ecmascript::DEFAULT_REGION_SIZE); PGOProfilerManager::GetInstance()->Initialize(options.GetPGOProfilerPath(), options.GetPGOHotnessThreshold()); - bool isEnableJit = options.IsEnableJIT() && options.GetEnableAsmInterpreter(); - Jit::GetInstance()->SetEnableOrDisable(options, isEnableJit); ASSERT(instance_ == nullptr); instance_ = new Runtime(); firstVmCreated_ = true; @@ -82,6 +80,8 @@ void Runtime::InitializeIfFirstVm(EcmaVM *vm) if (++vmCount_ == 1) { ThreadManagedScope managedScope(vm->GetAssociatedJSThread()); PreInitialization(vm); + bool isEnableJit = vm->GetJSOptions().IsEnableJIT() && vm->GetJSOptions().GetEnableAsmInterpreter(); + Jit::GetInstance()->SetEnableOrDisable(vm->GetJSOptions(), isEnableJit); vm->Initialize(); PostInitialization(vm); } diff --git a/ecmascript/taskpool/runner.cpp b/ecmascript/taskpool/runner.cpp index 4623c899e5..d41619e8a5 100644 --- a/ecmascript/taskpool/runner.cpp +++ b/ecmascript/taskpool/runner.cpp @@ -22,7 +22,11 @@ #endif namespace panda::ecmascript { -Runner::Runner(uint32_t threadNum) : totalThreadNum_(threadNum) +Runner::Runner(uint32_t threadNum, const std::function prologueHook, + const std::function epilogueHook) + : totalThreadNum_(threadNum), + prologueHook_(prologueHook), + epilogueHook_(epilogueHook) { for (uint32_t i = 0; i < threadNum; i++) { // main thread is 0; @@ -65,6 +69,17 @@ void Runner::TerminateThread() threadPool_.clear(); } +void Runner::ForEachTask(const std::function &f) +{ + taskQueue_.ForEachTask(f); + LockHolder holder(mtx_); + for (uint32_t i = 0; i < runningTask_.size(); i++) { + if (runningTask_[i] != nullptr) { + f(runningTask_[i]); + } + } +} + void Runner::SetQosPriority([[maybe_unused]] bool isForeground) { #ifdef ENABLE_QOS @@ -96,11 +111,13 @@ void Runner::Run(uint32_t threadId) { os::thread::native_handle_type thread = os::thread::GetNativeHandle(); os::thread::SetThreadName(thread, "OS_GC_Thread"); + PrologueHook(thread); RecordThreadId(); while (std::unique_ptr task = taskQueue_.PopTask()) { SetRunTask(threadId, task.get()); task->Run(threadId); SetRunTask(threadId, nullptr); } + EpilogueHook(thread); } } // namespace panda::ecmascript diff --git a/ecmascript/taskpool/runner.h b/ecmascript/taskpool/runner.h index c3b8e7f5ac..51fadd8796 100644 --- a/ecmascript/taskpool/runner.h +++ b/ecmascript/taskpool/runner.h @@ -20,10 +20,12 @@ #include #include #include +#include #include "ecmascript/common.h" #include "ecmascript/taskpool/task_queue.h" #include "ecmascript/platform/mutex.h" +#include "libpandabase/os/thread.h" namespace panda::ecmascript { static constexpr uint32_t MIN_TASKPOOL_THREAD_NUM = 3; @@ -32,7 +34,8 @@ static constexpr uint32_t DEFAULT_TASKPOOL_THREAD_NUM = 0; class Runner { public: - explicit Runner(uint32_t threadNum); + explicit Runner(uint32_t threadNum, const std::function prologueHook, + const std::function epilogueHook); ~Runner() = default; NO_COPY_SEMANTIC(Runner); @@ -64,6 +67,20 @@ public: return false; } + void PrologueHook(os::thread::native_handle_type thread) + { + if (prologueHook_ != nullptr) { + prologueHook_(thread); + } + } + void EpilogueHook(os::thread::native_handle_type thread) + { + if (epilogueHook_ != nullptr) { + epilogueHook_(thread); + } + } + void ForEachTask(const std::function &f); + private: void Run(uint32_t threadId); void SetRunTask(uint32_t threadId, Task *task); @@ -75,6 +92,9 @@ private: std::vector gcThreadId_ {}; Mutex mtx_; Mutex mtxPool_; + + std::function prologueHook_; + std::function epilogueHook_; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_TASKPOOL_RUNNER_H diff --git a/ecmascript/taskpool/task_queue.cpp b/ecmascript/taskpool/task_queue.cpp index 5d6121dc4c..c034996306 100644 --- a/ecmascript/taskpool/task_queue.cpp +++ b/ecmascript/taskpool/task_queue.cpp @@ -61,4 +61,14 @@ void TaskQueue::Terminate() terminate_ = true; cv_.SignalAll(); } + +void TaskQueue::ForEachTask(const std::function &f) +{ + LockHolder holder(mtx_); + for (auto &task : tasks_) { + if (task.get() != nullptr) { + f(task.get()); + } + } +} } // namespace panda::ecmascript diff --git a/ecmascript/taskpool/task_queue.h b/ecmascript/taskpool/task_queue.h index ce4895879b..aacf5d9616 100644 --- a/ecmascript/taskpool/task_queue.h +++ b/ecmascript/taskpool/task_queue.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "ecmascript/taskpool/task.h" #include "ecmascript/platform/mutex.h" @@ -38,6 +39,7 @@ public: void Terminate(); void TerminateTask(int32_t id, TaskType type); + void ForEachTask(const std::function &f); private: std::deque> tasks_; diff --git a/ecmascript/taskpool/taskpool.cpp b/ecmascript/taskpool/taskpool.cpp index 3487c0f8b3..1dabddf458 100644 --- a/ecmascript/taskpool/taskpool.cpp +++ b/ecmascript/taskpool/taskpool.cpp @@ -28,7 +28,8 @@ void Taskpool::Initialize(int threadNum) { LockHolder lock(mutex_); if (isInitialized_++ <= 0) { - runner_ = std::make_unique(TheMostSuitableThreadNum(threadNum)); + runner_ = std::make_unique(TheMostSuitableThreadNum(threadNum), + prologueRunnerHook_, epilogueRunnerHook_); } } @@ -62,4 +63,12 @@ uint32_t Taskpool::TheMostSuitableThreadNum(uint32_t threadNum) const uint32_t numOfThreads = std::min(NumberOfCpuCore() / 2, MAX_TASKPOOL_THREAD_NUM); return std::max(numOfThreads, MIN_TASKPOOL_THREAD_NUM); } + +void Taskpool::ForEachTask(const std::function &f) +{ + if (isInitialized_ <= 0) { + return; + } + runner_->ForEachTask(f); +} } // namespace panda::ecmascript diff --git a/ecmascript/taskpool/taskpool.h b/ecmascript/taskpool/taskpool.h index 0553f71e77..951935ce35 100644 --- a/ecmascript/taskpool/taskpool.h +++ b/ecmascript/taskpool/taskpool.h @@ -23,7 +23,7 @@ #include "ecmascript/platform/mutex.h" namespace panda::ecmascript { -class Taskpool { +class PUBLIC_API Taskpool { public: PUBLIC_API static Taskpool *GetCurrentTaskpool(); @@ -66,12 +66,23 @@ public: runner_->SetQosPriority(isForeground); } + void RegisterRunnerHook(const std::function &prologueHook, + const std::function &epilogueHook) + { + prologueRunnerHook_ = prologueHook; + epilogueRunnerHook_ = epilogueHook; + } + void ForEachTask(const std::function &f); + private: - uint32_t TheMostSuitableThreadNum(uint32_t threadNum) const; + virtual uint32_t TheMostSuitableThreadNum(uint32_t threadNum) const; std::unique_ptr runner_; volatile int isInitialized_ = 0; Mutex mutex_; + + std::function prologueRunnerHook_ { nullptr }; + std::function epilogueRunnerHook_ { nullptr }; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_PALTFORM_PLATFORM_H diff --git a/libark_jsruntime.map b/libark_jsruntime.map index a27cea2aa8..254a57705c 100644 --- a/libark_jsruntime.map +++ b/libark_jsruntime.map @@ -10,6 +10,7 @@ vtable?for?panda::ecmascript::kungfu::MethodSnapshotInfo; vtable?for?panda::ecmascript::kungfu::ObjectLiteralSnapshotInfo; vtable?for?panda::ecmascript::kungfu::StringSnapshotInfo; + vtable?for?panda::ecmascript::Taskpool; panda::ecmascript::COMMON_HELP_HEAD_MSG*; panda::ecmascript::HELP_OPTION_MSG*; @@ -119,6 +120,7 @@ panda::ecmascript::EcmaContext::FindConstpool*; panda::ecmascript::EcmaContext::FindOrCreateConstPool*; panda::ecmascript::EcmaContext::FindOrCreateUnsharedConstpool*; + panda::ecmascript::EcmaContext::FindUnsharedConstpool*; panda::ecmascript::EcmaContext::SetTSManager*; panda::ecmascript::EcmaRuntimeStat::StartCount*; panda::ecmascript::EcmaRuntimeStat::StopCount*; @@ -178,9 +180,12 @@ panda::ecmascript::JSPandaFile::GetFunctionKind*; panda::ecmascript::JSPandaFile::GetNormalizedFileDesc*; panda::ecmascript::JSPandaFile::GetRecordNameWithBundlePack*; + panda::ecmascript::JSPandaFile::IsFirstMergedAbc*; panda::ecmascript::JSProxy::IsArray*; panda::ecmascript::JSTaggedValue::IsJSCOWArray*; panda::ecmascript::JSTaggedValue::IsInSharedHeap*; + panda::ecmascript::JitThread::GetHostThread*; + panda::ecmascript::Jit::TimeScope::~TimeScope*; panda::ecmascript::Heap::AddGCListener*; panda::ecmascript::Heap::RemoveGCListener*; panda::ecmascript::JSTaggedValue::SetProperty*; @@ -236,6 +241,7 @@ panda::ecmascript::ObjectFactory::NewSharedOldSpaceJSObjectWithInit*; panda::ecmascript::ObjectFactory::NewSTaggedArray*; panda::ecmascript::ObjectFactory::NewSEcmaHClassDictMode*; + panda::ecmascript::ObjectFactory::GetRawStringFromStringTable*; panda::ecmascript::SendableClassDefiner::AddFieldTypeToHClass*; panda::ecmascript::ObjectFactory::NewJSSArray*; panda::ecmascript::ObjectFactory::NewSJsonFixedArray*;