From 06b885cd29631147665c9a29bf74d988538c2e46 Mon Sep 17 00:00:00 2001 From: duomingliang Date: Tue, 7 May 2024 20:48:37 +0800 Subject: [PATCH] enable jit inline Change-Id: I03a14dc8f94a24b2346e67e1327953c38e7f8397 fix fastcall deopt Change-Id: Icad62a5c93835e2d71197eff03b464f7ed0efd88 bugfix of litecg Change-Id: I0e55efd2bb44e13387a48ad5ca6e6f25bb08e53f close inlining when running apps Change-Id: I1d5e063bc1018090dde0af6095a8a2469c5affe6 codecheck & compile error fix Change-Id: I3f3442c3812d515bc1fa89bc1208ec2acbed6817 bugfix Change-Id: Iddf6fc5cc2cba8b856447896b982aabd175e27d0 comment fix Change-Id: I7be64154e2e7b98550f40522a9caa6b99a31a7e1 --- .../compiler/aot_compiler_preprocessor.cpp | 13 ++ .../compiler/aot_compiler_preprocessor.h | 5 +- .../compiler/bytecode_circuit_builder.cpp | 4 +- .../compiler/bytecode_info_collector.cpp | 31 ++-- ecmascript/compiler/bytecode_info_collector.h | 4 +- .../codegen/maple/maple_be/src/cg/isel.cpp | 10 +- .../maple/mpl2mpl/src/constantfold.cpp | 3 +- ecmascript/compiler/compilation_driver.h | 3 - ecmascript/compiler/jit_compilation_env.cpp | 66 ++++++- ecmascript/compiler/jit_compilation_env.h | 23 +++ ecmascript/compiler/jit_compiler.cpp | 2 +- ecmascript/compiler/pass.h | 9 +- ecmascript/compiler/pass_manager.cpp | 7 +- ecmascript/compiler/pass_manager.h | 4 +- ecmascript/compiler/profiler_stub_builder.cpp | 6 +- ecmascript/compiler/ts_inline_lowering.cpp | 53 +++++- ecmascript/compiler/ts_inline_lowering.h | 11 +- ecmascript/compiler/type_info_accessors.h | 5 +- .../compiler/typed_bytecode_lowering.cpp | 3 + ecmascript/ic/ic_handler.h | 9 +- ecmascript/ic/profile_type_info.cpp | 50 +++--- ecmascript/ic/profile_type_info.h | 15 ++ ecmascript/jit/jit_profiler.cpp | 169 +++++++++++++----- ecmascript/jit/jit_profiler.h | 25 ++- ecmascript/js_function.cpp | 6 - ecmascript/js_function.h | 6 +- ecmascript/js_thread.h | 6 + ecmascript/object_factory.cpp | 1 + ecmascript/pgo_profiler/pgo_profiler.cpp | 12 +- ecmascript/tests/dump_test.cpp | 2 +- test/jittest/BUILD.gn | 1 + test/jittest/ts_inline/BUILD.gn | 19 ++ test/jittest/ts_inline/expect_output.txt | 16 ++ test/jittest/ts_inline/ts_inline.ts | 42 +++++ test/test_helper.gni | 13 +- 35 files changed, 511 insertions(+), 143 deletions(-) create mode 100644 test/jittest/ts_inline/BUILD.gn create mode 100644 test/jittest/ts_inline/expect_output.txt create mode 100644 test/jittest/ts_inline/ts_inline.ts diff --git a/ecmascript/compiler/aot_compiler_preprocessor.cpp b/ecmascript/compiler/aot_compiler_preprocessor.cpp index 01677917e..530fe48de 100644 --- a/ecmascript/compiler/aot_compiler_preprocessor.cpp +++ b/ecmascript/compiler/aot_compiler_preprocessor.cpp @@ -322,6 +322,19 @@ bool CallMethodFlagMap::IsAotCompile(CString fileDesc, uint32_t methodOffset) co return abcIdMethodIdToIsAotCompile_.at(std::pair(fileDesc, methodOffset)); } +void CallMethodFlagMap::SetIsJitCompile(CString fileDesc, uint32_t methodOffset, bool isAotCompile) +{ + abcIdMethodIdToIsJitCompile_[std::pair(fileDesc, methodOffset)] = isAotCompile; +} + +bool CallMethodFlagMap::IsJitCompile(CString fileDesc, uint32_t methodOffset) const +{ + if (!abcIdMethodIdToIsJitCompile_.count(std::pair(fileDesc, methodOffset))) { + return false; + } + return abcIdMethodIdToIsJitCompile_.at(std::pair(fileDesc, methodOffset)); +} + bool AotCompilerPreprocessor::FilterOption(const std::map> &optionMap, const std::string &recordName, const std::string &methodName) const diff --git a/ecmascript/compiler/aot_compiler_preprocessor.h b/ecmascript/compiler/aot_compiler_preprocessor.h index c19dfdf8d..e62feeba2 100644 --- a/ecmascript/compiler/aot_compiler_preprocessor.h +++ b/ecmascript/compiler/aot_compiler_preprocessor.h @@ -42,9 +42,12 @@ public: bool IsFastCall(CString fileDesc, uint32_t methodOffset) const; void SetIsAotCompile(CString fileDesc, uint32_t methodOffset, bool isAotCompile); bool IsAotCompile(CString fileDesc, uint32_t methodOffset) const; + void SetIsJitCompile(CString fileDesc, uint32_t methodOffset, bool isAotCompile); + bool IsJitCompile(CString fileDesc, uint32_t methodOffset) const; private: std::map, bool> abcIdMethodIdToIsFastCall_ {}; std::map, bool> abcIdMethodIdToIsAotCompile_ {}; + std::map, bool> abcIdMethodIdToIsJitCompile_ {}; }; struct CompilationOptions { @@ -172,7 +175,7 @@ public: { return pkgsArgs_; } - const CallMethodFlagMap *GetCallMethodFlagMap() + CallMethodFlagMap *GetCallMethodFlagMap() { return &callMethodFlagMap_; } diff --git a/ecmascript/compiler/bytecode_circuit_builder.cpp b/ecmascript/compiler/bytecode_circuit_builder.cpp index 4c95a3831..19671d87c 100644 --- a/ecmascript/compiler/bytecode_circuit_builder.cpp +++ b/ecmascript/compiler/bytecode_circuit_builder.cpp @@ -208,7 +208,7 @@ void BytecodeCircuitBuilder::BuildRegions(const ExceptionInfo &byteCodeException } RemoveUnreachableRegion(); if (IsLogEnabled()) { - PrintGraph("Update CFG"); + PrintGraph(std::string("Update CFG [" + methodName_ + "]").c_str()); } BuildCircuit(); } @@ -988,7 +988,7 @@ void BytecodeCircuitBuilder::BuildCircuit() BuildSubCircuit(); } if (IsLogEnabled()) { - PrintGraph("Bytecode2Gate"); + PrintGraph(std::string("Bytecode2Gate [" + methodName_ + "]").c_str()); LOG_COMPILER(INFO) << "\033[34m" << "============= " << "After bytecode2circuit lowering [" << methodName_ << "]" diff --git a/ecmascript/compiler/bytecode_info_collector.cpp b/ecmascript/compiler/bytecode_info_collector.cpp index 833d23445..80e5a284a 100644 --- a/ecmascript/compiler/bytecode_info_collector.cpp +++ b/ecmascript/compiler/bytecode_info_collector.cpp @@ -50,7 +50,7 @@ BytecodeInfoCollector::BytecodeInfoCollector(CompilationEnv *env, JSPandaFile *j snapshotCPData_(nullptr) // jit no need { ASSERT(env->IsJitCompiler()); - ProcessMethod(); + ProcessCurrMethod(); } void BytecodeInfoCollector::ProcessClasses() @@ -133,35 +133,38 @@ void BytecodeInfoCollector::ProcessClasses() << methodIdx; } -void BytecodeInfoCollector::ProcessMethod() +void BytecodeInfoCollector::ProcessCurrMethod() { - auto &recordNames = bytecodeInfo_.GetRecordNames(); - auto &methodPcInfos = bytecodeInfo_.GetMethodPcInfos(); - MethodLiteral *methodLiteral = compilationEnv_->GetMethodLiteral(); + ProcessMethod(compilationEnv_->GetMethodLiteral()); +} - const panda_file::File *pf = jsPandaFile_->GetPandaFile(); +void BytecodeInfoCollector::ProcessMethod(MethodLiteral *methodLiteral) +{ panda_file::File::EntityId methodIdx = methodLiteral->GetMethodId(); - panda_file::MethodDataAccessor mda(*pf, methodIdx); + auto methodOffset = methodIdx.GetOffset(); + if (processedMethod_.find(methodOffset) != processedMethod_.end()) { + return; + } + + auto &recordNames = bytecodeInfo_.GetRecordNames(); + auto &methodPcInfos = bytecodeInfo_.GetMethodPcInfos(); const CString recordName = jsPandaFile_->GetRecordNameWithBundlePack(methodIdx); recordNames.emplace_back(recordName); - auto methodId = mda.GetMethodId(); - ASSERT(jsPandaFile_->IsNewVersion()); - auto methodOffset = methodId.GetOffset(); + const panda_file::File *pf = jsPandaFile_->GetPandaFile(); + panda_file::MethodDataAccessor mda(*pf, methodIdx); auto codeId = mda.GetCodeId(); ASSERT(codeId.has_value()); panda_file::CodeDataAccessor codeDataAccessor(*pf, codeId.value()); uint32_t codeSize = codeDataAccessor.GetCodeSize(); const uint8_t *insns = codeDataAccessor.GetInstructions(); - - std::map> processedMethod; std::vector classConstructIndexes; CollectMethodPcsFromBC(codeSize, insns, methodLiteral, recordName, methodOffset, classConstructIndexes); - processedMethod[methodOffset] = std::make_pair(methodPcInfos.size() - 1, methodOffset); - SetMethodPcInfoIndex(methodOffset, processedMethod[methodOffset]); + SetMethodPcInfoIndex(methodOffset, {methodPcInfos.size() - 1, methodOffset}); + processedMethod_.emplace(methodOffset); } void BytecodeInfoCollector::CollectMethodPcsFromBC(const uint32_t insSz, const uint8_t *insArr, diff --git a/ecmascript/compiler/bytecode_info_collector.h b/ecmascript/compiler/bytecode_info_collector.h index 310aed6f3..879434b52 100644 --- a/ecmascript/compiler/bytecode_info_collector.h +++ b/ecmascript/compiler/bytecode_info_collector.h @@ -586,6 +586,7 @@ public: } } + void ProcessMethod(MethodLiteral *methodLiteral); private: inline size_t GetMethodInfoID() { @@ -593,7 +594,7 @@ private: } void ProcessClasses(); - void ProcessMethod(); + void ProcessCurrMethod(); void RearrangeInnerMethods(); void CollectMethodPcsFromBC(const uint32_t insSz, const uint8_t *insArr, MethodLiteral *method, const CString &recordName, uint32_t methodOffset, @@ -625,6 +626,7 @@ private: size_t methodInfoIndex_ {0}; std::set classDefBCIndexes_ {}; Bytecodes bytecodes_; + std::set processedMethod_; }; } // namespace panda::ecmascript::kungfu #endif // ECMASCRIPT_COMPILER_BYTECODE_INFO_COLLECTOR_H diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/isel.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/isel.cpp index 29f145313..ac6fbd774 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/isel.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/isel.cpp @@ -1129,9 +1129,15 @@ void MPISel::SelectCvtInt2Float(RegOperand &resOpnd, Operand &opnd0, PrimType to default: CHECK_FATAL(false, "NYI"); } - RegOperand ®Opnd0 = SelectCopy2Reg(opnd0, fromType); + RegOperand *regOpnd0 = nullptr; + if (!isSigned && fromSize <= k32BitSize && toType == PTY_f64) { + regOpnd0 = &cgFunc->GetOpndBuilder()->CreateVReg(k64BitSize, kRegTyInt); + SelectIntCvt(*regOpnd0, opnd0, maple::PTY_i64, fromType); + } else { + regOpnd0 = &SelectCopy2Reg(opnd0, fromType); + } Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp)); - (void)insn.AddOpndChain(resOpnd).AddOpndChain(regOpnd0); + (void)insn.AddOpndChain(resOpnd).AddOpndChain(*regOpnd0); cgFunc->GetCurBB()->AppendInsn(insn); } diff --git a/ecmascript/compiler/codegen/maple/mpl2mpl/src/constantfold.cpp b/ecmascript/compiler/codegen/maple/mpl2mpl/src/constantfold.cpp index 44f682c83..502256cb1 100644 --- a/ecmascript/compiler/codegen/maple/mpl2mpl/src/constantfold.cpp +++ b/ecmascript/compiler/codegen/maple/mpl2mpl/src/constantfold.cpp @@ -1178,7 +1178,8 @@ MIRConst *ConstantFold::FoldFloorMIRConst(const MIRConst &cst, PrimType fromType return nullptr; } doubleValue = CalIntValueFromFloatValue(doubleValue, resultType); - return GlobalTables::GetIntConstTable().GetOrCreateIntConst(static_cast(doubleValue), resultType); + // gcc/clang have bugs convert double to unsigned long, must convert to signed long first; + return GlobalTables::GetIntConstTable().GetOrCreateIntConst(static_cast(doubleValue), resultType); } } diff --git a/ecmascript/compiler/compilation_driver.h b/ecmascript/compiler/compilation_driver.h index eb6488a18..2d69ec3f6 100644 --- a/ecmascript/compiler/compilation_driver.h +++ b/ecmascript/compiler/compilation_driver.h @@ -385,9 +385,6 @@ public: const panda_file::File::Header *header, ApEntityId abcId, const Callback &cb) { SetCurrentCompilationFile(); - for (auto mi : bytecodeInfo_.GetMethodList()) { - bytecodeInfo_.AddSkippedMethod(mi.first); - } const std::string methodName(MethodLiteral::GetMethodName(jsPandaFile, methodLiteral->GetMethodId())); auto &methodList = bytecodeInfo_.GetMethodList(); diff --git a/ecmascript/compiler/jit_compilation_env.cpp b/ecmascript/compiler/jit_compilation_env.cpp index 0375a9070..8afeccbd8 100644 --- a/ecmascript/compiler/jit_compilation_env.cpp +++ b/ecmascript/compiler/jit_compilation_env.cpp @@ -16,6 +16,8 @@ #include "ecmascript/ecma_context.h" #include "ecmascript/jspandafile/program_object.h" #include "ecmascript/pgo_profiler/pgo_profiler.h" +#include "ecmascript/ic/profile_type_info.h" +#include "ecmascript/ic/ic_handler.h" namespace panda::ecmascript { // jit @@ -162,9 +164,67 @@ JSTaggedValue JitCompilationEnv::GetStringFromConstantPool([[maybe_unused]] cons const uint16_t cpIdx) const { ASSERT(thread_->IsInRunningState()); - Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); - ASSERT(method->GetMethodId().GetOffset() == methodOffset); - JSTaggedValue constpool = method->GetConstantPool(); + JSTaggedValue constpool; + Method *currMethod = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); + if (methodOffset != currMethod->GetMethodId().GetOffset()) { + auto calleeFunc = GetJsFunctionByMethodOffset(methodOffset); + if (!calleeFunc) { + return JSTaggedValue::Undefined(); + } + constpool = Method::Cast(calleeFunc->GetMethod())->GetConstantPool(); + } else { + constpool = currMethod->GetConstantPool(); + } return ConstantPool::GetStringFromCacheForJit(GetJSThread(), constpool, cpIdx); } + +JSFunction *JitCompilationEnv::GetJsFunctionByMethodOffset(uint32_t methodOffset) const +{ + ASSERT(thread_->IsInRunningState()); + Method *currMethod = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); + auto currMethodOffset = currMethod->GetMethodId().GetOffset(); + if (methodOffset == currMethodOffset) { + return *jsFunction_; + } + std::vector> funcSlotChain; + uint32_t calleeOffset = methodOffset; + do { + if (functionSlotIdMap_.find(calleeOffset) == functionSlotIdMap_.end()) { + return nullptr; + } + funcSlotChain.push_back({functionSlotIdMap_.at(calleeOffset), callee2CallerMap_.at(calleeOffset)}); + calleeOffset = callee2CallerMap_.at(calleeOffset); + } while (calleeOffset != currMethodOffset); + JSFunction *currFunc = *jsFunction_; + ProfileTypeInfo *currFuncPTI = *profileTypeInfo_; + for (int i = funcSlotChain.size() - 1; i >= 0; --i) { + uint32_t slotId = funcSlotChain[i].first; + uint32_t callerOffset = funcSlotChain[i].second; + if (Method::Cast(currFunc->GetMethod())->GetMethodId().GetOffset() != callerOffset) { + return nullptr; + } + auto slotValue = currFuncPTI->Get(slotId); + if (slotValue.IsJSFunction()) { + currFunc = JSFunction::Cast(currFuncPTI->Get(slotId).GetTaggedObject()); + } else if (slotValue.IsPrototypeHandler()) { + auto prototypeHandler = PrototypeHandler::Cast(slotValue.GetTaggedObject()); + auto accessorFunction = prototypeHandler->GetAccessorJSFunction(); + if (!accessorFunction.IsJSFunction()) { + return nullptr; + } + currFunc = JSFunction::Cast(accessorFunction.GetTaggedObject()); + } else { + return nullptr; + } + auto profileTypeInfoVal = currFunc->GetProfileTypeInfo(); + if (profileTypeInfoVal.IsUndefined()) { + return nullptr; + } + currFuncPTI = ProfileTypeInfo::Cast(profileTypeInfoVal.GetTaggedObject()); + } + if (Method::Cast(currFunc->GetMethod())->GetMethodId().GetOffset() != methodOffset) { + return nullptr; + } + return currFunc; +} } // namespace panda::ecmascript diff --git a/ecmascript/compiler/jit_compilation_env.h b/ecmascript/compiler/jit_compilation_env.h index dd3c82ead..185c84e83 100644 --- a/ecmascript/compiler/jit_compilation_env.h +++ b/ecmascript/compiler/jit_compilation_env.h @@ -17,6 +17,7 @@ #define ECMASCRIPT_COMPILER_JIT_COMPILATION_ENV_H #include "ecmascript/compiler/compilation_env.h" +#include "ecmascript/ic/profile_type_info.h" namespace panda::ecmascript { class JitCompilationEnv final : public CompilationEnv { @@ -83,6 +84,25 @@ public: { return abcId_; } + + void SetProfileTypeInfo(const JSHandle &info) + { + profileTypeInfo_ = info; + } + + void UpdateFuncSlotIdMap(uint32_t calleeOffset, uint32_t callerOffset, uint32_t slotId) + { + if (functionSlotIdMap_.find(calleeOffset) != functionSlotIdMap_.end()) { + return; + } + if (callee2CallerMap_.find(calleeOffset) != callee2CallerMap_.end()) { + return; + } + functionSlotIdMap_[calleeOffset] = slotId; + callee2CallerMap_[calleeOffset] = callerOffset; + } + + JSFunction *GetJsFunctionByMethodOffset(uint32_t methodOffset) const; private: JSThread *hostThread_ {nullptr}; JSHandle jsFunction_; @@ -90,6 +110,9 @@ private: MethodLiteral *methodLiteral_ {nullptr}; const uint8_t* pcStart_ {nullptr}; pgo::ApEntityId abcId_ {0}; + JSHandle profileTypeInfo_; + std::map functionSlotIdMap_; + std::map callee2CallerMap_; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_COMPILER_JIT_COMPILATION_ENV_H diff --git a/ecmascript/compiler/jit_compiler.cpp b/ecmascript/compiler/jit_compiler.cpp index 9c5024174..cf61b3e1b 100644 --- a/ecmascript/compiler/jit_compiler.cpp +++ b/ecmascript/compiler/jit_compiler.cpp @@ -69,7 +69,7 @@ JitCompilationOptions::JitCompilationOptions(JSRuntimeOptions runtimeOptions) isEnableEarlyElimination_ = runtimeOptions.IsEnableEarlyElimination(); isEnableLaterElimination_ = runtimeOptions.IsEnableLaterElimination(); isEnableValueNumbering_ = runtimeOptions.IsEnableValueNumbering(); - isEnableOptInlining_ = false; + isEnableOptInlining_ = runtimeOptions.IsEnableAPPJIT() ? false : runtimeOptions.IsEnableOptInlining(); isEnableOptString_ = runtimeOptions.IsEnableOptString(); isEnableOptPGOType_ = runtimeOptions.IsEnableOptPGOType(); isEnableOptTrackField_ = runtimeOptions.IsEnableOptTrackField(); diff --git a/ecmascript/compiler/pass.h b/ecmascript/compiler/pass.h index 98e0c02dd..67154c5d6 100644 --- a/ecmascript/compiler/pass.h +++ b/ecmascript/compiler/pass.h @@ -71,7 +71,7 @@ public: PassData(BytecodeCircuitBuilder *builder, Circuit *circuit, PassContext *ctx, CompilerLog *log, std::string methodName, MethodInfo *methodInfo = nullptr, bool hasTypes = false, const CString &recordName = "", MethodLiteral *methodLiteral = nullptr, - uint32_t methodOffset = 0, const CallMethodFlagMap *callMethodFlagMap = nullptr, + uint32_t methodOffset = 0, CallMethodFlagMap *callMethodFlagMap = nullptr, const CVector &fileInfos = CVector{}, NativeAreaAllocator *allocator = nullptr, PGOProfilerDecoder *decoder = nullptr, PassOptions *passOptions = nullptr, std::string optBCRange = "") @@ -190,7 +190,7 @@ public: return optBCRange_; } - const CallMethodFlagMap *GetCallMethodFlagMap() const + CallMethodFlagMap *GetCallMethodFlagMap() { return callMethodFlagMap_; } @@ -240,7 +240,7 @@ private: const CString &recordName_; MethodLiteral *methodLiteral_ {nullptr}; uint32_t methodOffset_; - const CallMethodFlagMap *callMethodFlagMap_ {nullptr}; + CallMethodFlagMap *callMethodFlagMap_ {nullptr}; const CVector &fileInfos_; NativeAreaAllocator *allocator_ {nullptr}; PGOProfilerDecoder *decoder_ {nullptr}; @@ -515,7 +515,8 @@ public: TimeScope timescope("TSInlineLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); bool enableLog = data->GetLog()->EnableMethodCIRLog(); TSInlineLowering inlining(data->GetCircuit(), data->GetPassContext(), enableLog, data->GetMethodName(), - data->GetNativeAreaAllocator(), passOptions, data->GetMethodOffset()); + data->GetNativeAreaAllocator(), passOptions, data->GetMethodOffset(), + data->GetCallMethodFlagMap()); inlining.RunTSInlineLowering(); Chunk chunk(data->GetNativeAreaAllocator()); if (passOptions->EnableLexenvSpecialization()) { diff --git a/ecmascript/compiler/pass_manager.cpp b/ecmascript/compiler/pass_manager.cpp index 2d315ab33..c0f12b5ae 100644 --- a/ecmascript/compiler/pass_manager.cpp +++ b/ecmascript/compiler/pass_manager.cpp @@ -90,7 +90,9 @@ bool JitPassManager::Compile(JSHandle &profileTypeInfo, } if (compilationEnv_->GetJSOptions().IsEnableJITPGO()) { jitProfiler_ = compilationEnv_->GetPGOProfiler()->GetJITProfile(); - jitProfiler_->ProfileBytecode(compilationEnv_->GetJSThread(), profileTypeInfo, + static_cast(compilationEnv_)->SetProfileTypeInfo(profileTypeInfo); + jitProfiler_->SetCompilationEnv(compilationEnv_); + jitProfiler_->ProfileBytecode(compilationEnv_->GetJSThread(), profileTypeInfo, nullptr, methodLiteral->GetMethodId(), abcId, pcStart, methodLiteral->GetCodeSize(jsPandaFile, methodLiteral->GetMethodId()), header); @@ -117,8 +119,9 @@ bool JitPassManager::Compile(JSHandle &profileTypeInfo, builder_->BytecodeToCircuit(); } + CallMethodFlagMap methodFlagMap; data_ = new PassData(builder_, circuit_, ctx_, log_, fullName, &methodInfo, hasTypes, recordName, - methodLiteral, methodOffset, nullptr, CVector {}, + methodLiteral, methodOffset, &methodFlagMap, CVector {}, compilationEnv_->GetNativeAreaAllocator(), decoder, passOptions_); PassRunner pipeline(data_); diff --git a/ecmascript/compiler/pass_manager.h b/ecmascript/compiler/pass_manager.h index 827559ac8..2a9ecd9f2 100644 --- a/ecmascript/compiler/pass_manager.h +++ b/ecmascript/compiler/pass_manager.h @@ -133,7 +133,7 @@ public: 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) + CallMethodFlagMap *callMethodFlagMap, const CVector &fileInfos, std::string optBCRange) : compilationEnv_(env), triple_(triple), optLevel_(optLevel), relocMode_(relocMode), log_(log), logList_(logList), maxAotMethodSize_(maxAotMethodSize), maxMethodsInModule_(maxMethodsInModule), profilerDecoder_(profilerDecoder), passOptions_(passOptions), @@ -158,7 +158,7 @@ protected: size_t maxMethodsInModule_ {0}; PGOProfilerDecoder &profilerDecoder_; PassOptions *passOptions_ {nullptr}; - const CallMethodFlagMap *callMethodFlagMap_ {nullptr}; + CallMethodFlagMap *callMethodFlagMap_ {nullptr}; const CVector &fileInfos_; std::string optBCRange_ {}; bool enableJITLog_ {false}; diff --git a/ecmascript/compiler/profiler_stub_builder.cpp b/ecmascript/compiler/profiler_stub_builder.cpp index b7912256e..c6654b9d1 100644 --- a/ecmascript/compiler/profiler_stub_builder.cpp +++ b/ecmascript/compiler/profiler_stub_builder.cpp @@ -258,8 +258,7 @@ void ProfilerStubBuilder::ProfileCall( { Label change(env); Label resetSlot(env); - GateRef method = env->GetBuilder()->GetMethodFromFunction(target); - BRANCH(Int64Equal(slotValue, method), &exit, &change); + BRANCH(Int64Equal(slotValue, target), &exit, &change); Bind(&change); { BRANCH(Int64Equal(ChangeTaggedPointerToInt64(slotValue), Int64(0)), &exit, &resetSlot); @@ -279,8 +278,7 @@ void ProfilerStubBuilder::ProfileCall( } Bind(&updateSlot); { - GateRef method = env->GetBuilder()->GetMethodFromFunction(target); - SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, method); + SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, target); TryPreDumpInner(glue, func, profileTypeInfo); Jump(&exit); } diff --git a/ecmascript/compiler/ts_inline_lowering.cpp b/ecmascript/compiler/ts_inline_lowering.cpp index ca04f2e71..4538a39d9 100644 --- a/ecmascript/compiler/ts_inline_lowering.cpp +++ b/ecmascript/compiler/ts_inline_lowering.cpp @@ -122,6 +122,10 @@ void TSInlineLowering::TryInline(InlineTypeInfoAccessor &info, ChunkQueueGetBytecodeInfo(); + if (compilationEnv_->IsJitCompiler()) { + ctx_->GetBytecodeInfoCollector()->ProcessMethod(inlinedMethod); + } + ASSERT(bytecodeInfo.GetMethodList().find(methodOffset) != bytecodeInfo.GetMethodList().end()); auto &methodInfo = bytecodeInfo.GetMethodList().at(methodOffset); auto &methodPcInfos = bytecodeInfo.GetMethodPcInfos(); auto &methodPcInfo = methodPcInfos[methodInfo.GetMethodPcInfoIndex()]; @@ -139,6 +143,10 @@ void TSInlineLowering::TryInline(InlineTypeInfoAccessor &info, ChunkQueueInitRoot(); + JITProfiler *profiler = nullptr; + if (compilationEnv_->IsJitCompiler()) { + profiler = compilationEnv_->GetPGOProfiler()->GetJITProfile(); + } BytecodeCircuitBuilder builder(jsPandaFile, method, methodPCInfo, circuit_, ctx_->GetByteCodes(), IsLogEnabled(), - enableTypeLowering_, fullName, recordName, ctx_->GetPfDecoder(), true); + enableTypeLowering_, fullName, recordName, ctx_->GetPfDecoder(), true, profiler); { if (enableTypeLowering_) { BuildFrameStateChain(info, builder); @@ -717,4 +729,43 @@ uint32_t TSInlineLowering::GetAccessorConstpoolId(InlineTypeInfoAccessor &info) uint32_t inlineMethodOffset = info.GetCallMethodId(); return ptManager_->GetConstantPoolIDByMethodOffset(inlineMethodOffset); } + +bool TSInlineLowering::CalleePFIProcess(uint32_t methodOffset) +{ + if (!compilationEnv_->IsJitCompiler()) { + return true; + } + auto jitCompilationEnv = static_cast(compilationEnv_); + JSFunction *calleeFunc = jitCompilationEnv->GetJsFunctionByMethodOffset(methodOffset); + if (!calleeFunc) { + return false; + } + auto calleeMethod = Method::Cast(calleeFunc->GetMethod()); + ASSERT(calleeMethod->GetMethodId().GetOffset() == methodOffset); + auto profileTIVal = calleeFunc->GetProfileTypeInfo(); + if (profileTIVal.IsUndefined()) { + return false; + } + auto profileTypeInfo = ProfileTypeInfo::Cast(profileTIVal.GetTaggedObject()); + + auto calleeLiteral = calleeMethod->GetMethodLiteral(); + auto calleeFile = calleeMethod->GetJSPandaFile(); + auto calleeAbcId = PGOProfiler::GetMethodAbcId(calleeFunc); + auto calleeCodeSize = calleeLiteral->GetCodeSize(calleeFile, calleeMethod->GetMethodId()); + compilationEnv_->GetPGOProfiler()->GetJITProfile()->ProfileBytecode( + compilationEnv_->GetJSThread(), JSHandle(), profileTypeInfo, calleeMethod->GetMethodId(), + calleeAbcId, calleeMethod->GetBytecodeArray(), calleeCodeSize, calleeFile->GetPandaFile()->GetHeader(), true); + return true; +} + +void TSInlineLowering::UpdateCallMethodFlagMap(uint32_t methodOffset, const MethodLiteral *method) +{ + if (!compilationEnv_->IsJitCompiler()) { + return; + } + CString fileDesc = ctx_->GetJSPandaFile()->GetNormalizedFileDesc(); + callMethodFlagMap_->SetIsJitCompile(fileDesc, methodOffset, true); + callMethodFlagMap_->SetIsFastCall(fileDesc, methodOffset, method->IsFastCall()); +} + } // namespace panda::ecmascript diff --git a/ecmascript/compiler/ts_inline_lowering.h b/ecmascript/compiler/ts_inline_lowering.h index aa9c55101..5708f26b1 100644 --- a/ecmascript/compiler/ts_inline_lowering.h +++ b/ecmascript/compiler/ts_inline_lowering.h @@ -43,8 +43,9 @@ private: class TSInlineLowering { public: static constexpr size_t MAX_INLINE_CALL_ALLOWED = 6; - TSInlineLowering(Circuit *circuit, PassContext *ctx, bool enableLog, const std::string& name, - NativeAreaAllocator* nativeAreaAllocator, PassOptions *options, uint32_t methodOffset) + TSInlineLowering(Circuit *circuit, PassContext *ctx, bool enableLog, const std::string &name, + NativeAreaAllocator *nativeAreaAllocator, PassOptions *options, uint32_t methodOffset, + CallMethodFlagMap *callMethodFlagMap) : circuit_(circuit), compilationEnv_(ctx->GetCompilationEnv()), acc_(circuit), @@ -63,7 +64,8 @@ public: chunk_(circuit->chunk()), inlinedCallMap_(circuit->chunk()), argAcc_(circuit), - initMethodOffset_(methodOffset) {} + initMethodOffset_(methodOffset), + callMethodFlagMap_(callMethodFlagMap) {} ~TSInlineLowering() = default; @@ -136,6 +138,8 @@ private: GateRef GetFrameState(InlineTypeInfoAccessor &info); void SetInitCallTargetAndConstPoolId(InlineTypeInfoAccessor &info); uint32_t GetAccessorConstpoolId(InlineTypeInfoAccessor &info); + bool CalleePFIProcess(uint32_t methodOffset); + void UpdateCallMethodFlagMap(uint32_t methodOffset, const MethodLiteral *method); Circuit *circuit_ {nullptr}; CompilationEnv *compilationEnv_ {nullptr}; @@ -160,6 +164,7 @@ private: uint32_t initMethodOffset_ {0}; uint32_t initConstantPoolId_ {0}; GateRef initCallTarget_ {Circuit::NullGate()}; + CallMethodFlagMap *callMethodFlagMap_; }; } // panda::ecmascript::kungfu #endif // ECMASCRIPT_COMPILER_TS_INLINE_LOWERING_H diff --git a/ecmascript/compiler/type_info_accessors.h b/ecmascript/compiler/type_info_accessors.h index dbff79355..f7e8ba6b9 100644 --- a/ecmascript/compiler/type_info_accessors.h +++ b/ecmascript/compiler/type_info_accessors.h @@ -400,8 +400,9 @@ public: if (haveProfileType) { CString fileDesc = jsPandaFile_->GetNormalizedFileDesc(); uint32_t methodId = profileType->GetProfileType().GetId(); - return callMethodFlagMap_->IsAotCompile(fileDesc, methodId) && - callMethodFlagMap_->IsFastCall(fileDesc, methodId); + return (callMethodFlagMap_->IsAotCompile(fileDesc, methodId) || + callMethodFlagMap_->IsJitCompile(fileDesc, methodId)) && + callMethodFlagMap_->IsFastCall(fileDesc, methodId); } return false; } diff --git a/ecmascript/compiler/typed_bytecode_lowering.cpp b/ecmascript/compiler/typed_bytecode_lowering.cpp index 8395c0bf1..e8dc5a43e 100644 --- a/ecmascript/compiler/typed_bytecode_lowering.cpp +++ b/ecmascript/compiler/typed_bytecode_lowering.cpp @@ -1778,6 +1778,9 @@ const JSPandaFile* TypedBytecodeLowering::GetCalleePandaFile(GateRef gate) auto profileType = acc_.TryGetPGOType(gate).GetPGOSampleType(); bool haveProfileType = profileType->IsProfileType() && !profileType->IsProfileTypeNone(); if (haveProfileType) { + if (compilationEnv_->IsJitCompiler()) { + return compilationEnv_->GetJSPandaFile(); + } auto abcId = profileType->GetProfileType().GetAbcId(); CString fileDesc; if (!decoder_->GetAbcNameById(abcId, fileDesc)) { diff --git a/ecmascript/ic/ic_handler.h b/ecmascript/ic/ic_handler.h index 443b9acf8..d352e48cb 100644 --- a/ecmascript/ic/ic_handler.h +++ b/ecmascript/ic/ic_handler.h @@ -413,6 +413,7 @@ public: JSHandle func(thread, getter); uint32_t methodOffset = Method::Cast(func->GetMethod())->GetMethodId().GetOffset(); handler->SetAccessorMethodId(methodOffset); + handler->SetAccessorJSFunction(thread, getter); } } } @@ -438,10 +439,11 @@ public: } AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject()); if (!accessor->IsInternal()) { - JSTaggedValue getter = accessor->GetSetter(); - JSHandle func(thread, getter); + JSTaggedValue setter = accessor->GetSetter(); + JSHandle func(thread, setter); handler->SetAccessorMethodId( Method::Cast(func->GetMethod())->GetMethodId().GetOffset()); + handler->SetAccessorJSFunction(thread, setter); } } // ShareToLocal is prohibited @@ -458,7 +460,8 @@ public: ACCESSORS(ProtoCell, PROTO_CELL_OFFSET, HOLDER_OFFSET) - ACCESSORS(Holder, HOLDER_OFFSET, ACCESSOR_METHOD_ID_OFFSET) + ACCESSORS(Holder, HOLDER_OFFSET, ACCESSOR_JSFUNCTION_OFFSET) + ACCESSORS(AccessorJSFunction, ACCESSOR_JSFUNCTION_OFFSET, ACCESSOR_METHOD_ID_OFFSET) ACCESSORS_PRIMITIVE_FIELD(AccessorMethodId, uint32_t, ACCESSOR_METHOD_ID_OFFSET, LAST_OFFSET) diff --git a/ecmascript/ic/profile_type_info.cpp b/ecmascript/ic/profile_type_info.cpp index ff88807e5..14d99d6b9 100644 --- a/ecmascript/ic/profile_type_info.cpp +++ b/ecmascript/ic/profile_type_info.cpp @@ -22,6 +22,7 @@ namespace panda::ecmascript { void ProfileTypeAccessor::AddElementHandler(JSHandle hclass, JSHandle handler) const { + ProfileTypeAccessorLockScope accessorLockScope(thread_); ALLOW_LOCAL_TO_SHARE_WEAK_REF_HANDLE; if (!IsICSlotValid()) { return; @@ -44,8 +45,34 @@ void ProfileTypeAccessor::AddElementHandler(JSHandle hclass, JSHa AddHandlerWithoutKey(hclass, handler); } +void ProfileTypeAccessor::AddWithoutKeyPoly(JSHandle hclass, JSHandle handler, + uint32_t index, JSTaggedValue profileData) const +{ + ASSERT(profileTypeInfo_->Get(index + 1).IsHole()); + JSHandle arr(thread_, profileData); + const uint32_t step = 2; + uint32_t newLen = arr->GetLength() + step; + if (newLen > CACHE_MAX_LEN) { + profileTypeInfo_->Set(thread_, index, JSTaggedValue::Hole()); + profileTypeInfo_->Set(thread_, index + 1, JSTaggedValue::Hole()); + return; + } + auto factory = thread_->GetEcmaVM()->GetFactory(); + JSHandle newArr = factory->NewTaggedArray(newLen); + uint32_t i = 0; + for (; i < arr->GetLength(); i += step) { + newArr->Set(thread_, i, arr->Get(i)); + newArr->Set(thread_, i + 1, arr->Get(i + 1)); + } + newArr->Set(thread_, i, GetWeakRef(hclass.GetTaggedValue())); + newArr->Set(thread_, i + 1, handler.GetTaggedValue()); + profileTypeInfo_->Set(thread_, index, newArr.GetTaggedValue()); + profileTypeInfo_->Set(thread_, index + 1, JSTaggedValue::Hole()); +} + void ProfileTypeAccessor::AddHandlerWithoutKey(JSHandle hclass, JSHandle handler) const { + ProfileTypeAccessorLockScope accessorLockScope(thread_); ALLOW_LOCAL_TO_SHARE_WEAK_REF_HANDLE; if (!IsICSlotValid()) { return; @@ -64,26 +91,7 @@ void ProfileTypeAccessor::AddHandlerWithoutKey(JSHandle hclass, J return; } if (!profileData.IsWeak() && profileData.IsTaggedArray()) { // POLY - ASSERT(profileTypeInfo_->Get(index + 1).IsHole()); - JSHandle arr(thread_, profileData); - const uint32_t step = 2; - uint32_t newLen = arr->GetLength() + step; - if (newLen > CACHE_MAX_LEN) { - profileTypeInfo_->Set(thread_, index, JSTaggedValue::Hole()); - profileTypeInfo_->Set(thread_, index + 1, JSTaggedValue::Hole()); - return; - } - auto factory = thread_->GetEcmaVM()->GetFactory(); - JSHandle newArr = factory->NewTaggedArray(newLen); - uint32_t i = 0; - for (; i < arr->GetLength(); i += step) { - newArr->Set(thread_, i, arr->Get(i)); - newArr->Set(thread_, i + 1, arr->Get(i + 1)); - } - newArr->Set(thread_, i, GetWeakRef(hclass.GetTaggedValue())); - newArr->Set(thread_, i + 1, handler.GetTaggedValue()); - profileTypeInfo_->Set(thread_, index, newArr.GetTaggedValue()); - profileTypeInfo_->Set(thread_, index + 1, JSTaggedValue::Hole()); + AddWithoutKeyPoly(hclass, handler, index, profileData); return; } // MONO to POLY @@ -102,6 +110,7 @@ void ProfileTypeAccessor::AddHandlerWithoutKey(JSHandle hclass, J void ProfileTypeAccessor::AddHandlerWithKey(JSHandle key, JSHandle hclass, JSHandle handler) const { + ProfileTypeAccessorLockScope accessorLockScope(thread_); ALLOW_LOCAL_TO_SHARE_WEAK_REF_HANDLE; if (!IsICSlotValid()) { return; @@ -165,6 +174,7 @@ void ProfileTypeAccessor::AddHandlerWithKey(JSHandle key, JSHandl void ProfileTypeAccessor::AddGlobalHandlerKey(JSHandle key, JSHandle handler) const { + ProfileTypeAccessorLockScope accessorLockScope(thread_); ALLOW_LOCAL_TO_SHARE_WEAK_REF_HANDLE; if (!IsICSlotValid()) { return; diff --git a/ecmascript/ic/profile_type_info.h b/ecmascript/ic/profile_type_info.h index 2d29792a8..ebdfdd29e 100644 --- a/ecmascript/ic/profile_type_info.h +++ b/ecmascript/ic/profile_type_info.h @@ -303,6 +303,19 @@ private: } }; +class ProfileTypeAccessorLockScope { +public: + ProfileTypeAccessorLockScope(JSThread *thread) + { + if (thread->GetEcmaVM()->IsEnableFastJit() || thread->GetEcmaVM()->IsEnableBaselineJit()) { + lockHolder_.emplace(thread->GetProfileTypeAccessorLock()); + } + } + +private: + std::optional lockHolder_; +}; + class ProfileTypeAccessor { public: static constexpr size_t CACHE_MAX_LEN = 8; @@ -325,6 +338,8 @@ public: ICState GetICState() const; static std::string ICStateToString(ICState state); void AddHandlerWithoutKey(JSHandle hclass, JSHandle handler) const; + void AddWithoutKeyPoly(JSHandle hclass, JSHandle handler, uint32_t index, + JSTaggedValue profileData) const; void AddElementHandler(JSHandle hclass, JSHandle handler) const; void AddHandlerWithKey(JSHandle key, JSHandle hclass, JSHandle handler) const; diff --git a/ecmascript/jit/jit_profiler.cpp b/ecmascript/jit/jit_profiler.cpp index c5bb2055a..6abbef151 100644 --- a/ecmascript/jit/jit_profiler.cpp +++ b/ecmascript/jit/jit_profiler.cpp @@ -19,6 +19,7 @@ #include #include "ecmascript/compiler/codegen/maple/maple_util/include/profile_type.h" +#include "ecmascript/compiler/jit_compilation_env.h" #include "ecmascript/compiler/pgo_type/pgo_type_manager.h" #include "ecmascript/elements.h" #include "ecmascript/enum_conversion.h" @@ -48,11 +49,15 @@ JITProfiler::JITProfiler(EcmaVM *vm) : vm_(vm) { } -void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &profileTypeInfo, - EntityId methodId, ApEntityId abcId, - const uint8_t *pcStart, uint32_t codeSize, const panda_file::File::Header *header) +void JITProfiler::ProfileBytecode(JSThread *thread, const JSHandle &profileTypeInfo, + ProfileTypeInfo *rawProfileTypeInfo, + EntityId methodId, ApEntityId abcId, const uint8_t *pcStart, uint32_t codeSize, + const panda_file::File::Header *header, bool useRawProfileTypeInfo) { Clear(); + if (useRawProfileTypeInfo) { + profileTypeInfo_ = rawProfileTypeInfo; + } abcId_ = abcId; methodId_ = methodId; BytecodeInstruction bcIns(pcStart); @@ -66,7 +71,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p case EcmaOpcode::LDTHISBYNAME_IMM8_ID16: case EcmaOpcode::LDOBJBYNAME_IMM8_ID16: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint8_t slotId = READ_INST_8_0(); CHECK_SLOTID_BREAK(slotId); ConvertICByName(bcOffset, slotId, BCType::LOAD); @@ -75,7 +82,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p case EcmaOpcode::LDTHISBYNAME_IMM16_ID16: case EcmaOpcode::LDOBJBYNAME_IMM16_ID16: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint16_t slotId = READ_INST_16_0(); ConvertICByName(bcOffset, slotId, BCType::LOAD); break; @@ -83,7 +92,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p case EcmaOpcode::LDOBJBYVALUE_IMM8_V8: case EcmaOpcode::LDTHISBYVALUE_IMM8: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint8_t slotId = READ_INST_8_0(); CHECK_SLOTID_BREAK(slotId); ConvertICByValue(bcOffset, slotId, BCType::LOAD); @@ -92,7 +103,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p case EcmaOpcode::LDOBJBYVALUE_IMM16_V8: case EcmaOpcode::LDTHISBYVALUE_IMM16: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint16_t slotId = READ_INST_16_0(); ConvertICByValue(bcOffset, slotId, BCType::LOAD); break; @@ -100,7 +113,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8: case EcmaOpcode::STTHISBYNAME_IMM8_ID16: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint8_t slotId = READ_INST_8_0(); CHECK_SLOTID_BREAK(slotId); ConvertICByName(bcOffset, slotId, BCType::STORE); @@ -109,7 +124,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8: case EcmaOpcode::STTHISBYNAME_IMM16_ID16: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint16_t slotId = READ_INST_16_0(); ConvertICByName(bcOffset, slotId, BCType::STORE); break; @@ -118,7 +135,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p case EcmaOpcode::STOWNBYINDEX_IMM8_V8_IMM16: case EcmaOpcode::STTHISBYVALUE_IMM8_V8: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint8_t slotId = READ_INST_8_0(); CHECK_SLOTID_BREAK(slotId); ConvertICByValue(bcOffset, slotId, BCType::STORE); @@ -128,7 +147,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p case EcmaOpcode::STOWNBYINDEX_IMM16_V8_IMM16: case EcmaOpcode::STTHISBYVALUE_IMM16_V8: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint16_t slotId = READ_INST_16_0(); ConvertICByValue(bcOffset, slotId, BCType::STORE); break; @@ -160,7 +181,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p case EcmaOpcode::STRICTEQ_IMM8_V8: case EcmaOpcode::TONUMERIC_IMM8: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint8_t slotId = READ_INST_8_0(); CHECK_SLOTID_BREAK(slotId); ConvertOpType(slotId, bcOffset); @@ -178,7 +201,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint8_t slotId = READ_INST_8_0(); CHECK_SLOTID_BREAK(slotId); ConvertCall(slotId, bcOffset); @@ -186,7 +211,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p } case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint8_t slotId = READ_INST_8_1(); CHECK_SLOTID_BREAK(slotId); ConvertCall(slotId, bcOffset); @@ -199,7 +226,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p } case EcmaOpcode::NEWOBJRANGE_IMM8_IMM8_V8: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint8_t slotId = READ_INST_8_0(); CHECK_SLOTID_BREAK(slotId); ConvertNewObjRange(slotId, bcOffset); @@ -207,7 +236,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p } case EcmaOpcode::NEWOBJRANGE_IMM16_IMM8_V8: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint16_t slotId = READ_INST_16_0(); ConvertNewObjRange(slotId, bcOffset); break; @@ -241,7 +272,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16: case EcmaOpcode::CREATEEMPTYARRAY_IMM8: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } auto traceId = static_cast(reinterpret_cast(pc) - reinterpret_cast(header)); uint8_t slotId = READ_INST_8_0(); @@ -253,7 +286,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16: case EcmaOpcode::CREATEEMPTYARRAY_IMM16: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } auto traceId = static_cast(reinterpret_cast(pc) - reinterpret_cast(header)); uint16_t slotId = READ_INST_16_0(); @@ -262,7 +297,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p } case EcmaOpcode::GETITERATOR_IMM8: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint8_t slotId = READ_INST_8_0(); CHECK_SLOTID_BREAK(slotId); ConvertGetIterator(slotId, bcOffset); @@ -270,7 +307,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p } case EcmaOpcode::GETITERATOR_IMM16: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint16_t slotId = READ_INST_16_0(); ConvertGetIterator(slotId, bcOffset); break; @@ -278,7 +317,9 @@ void JITProfiler::ProfileBytecode(JSThread *thread, JSHandle &p // Others case EcmaOpcode::INSTANCEOF_IMM8_V8: { Jit::JitLockHolder lock(thread); - profileTypeInfo_ = *profileTypeInfo; + if (!useRawProfileTypeInfo) { + profileTypeInfo_ = *profileTypeInfo; + } uint8_t slotId = READ_INST_8_0(); CHECK_SLOTID_BREAK(slotId); ConvertInstanceof(bcOffset, slotId); @@ -305,18 +346,30 @@ void JITProfiler::ConvertOpType(uint32_t slotId, long bcOffset) void JITProfiler::ConvertCall(uint32_t slotId, long bcOffset) { JSTaggedValue slotValue = profileTypeInfo_->Get(slotId); - if (!slotValue.IsInt()) { - return; - } - int calleeMethodId = slotValue.GetInt(); - if (calleeMethodId == 0) { + ProfileType::Kind kind; + int calleeMethodId = 0; + ApEntityId calleeAbcId = 0; + if (slotValue.IsInt()) { + calleeMethodId = slotValue.GetInt(); + if (calleeMethodId == 0) { + return; + } + calleeAbcId = abcId_; + ASSERT(calleeMethodId <= 0); + kind = ProfileType::Kind::BuiltinFunctionId; + } else if (slotValue.IsJSFunction()) { + JSFunction *callee = JSFunction::Cast(slotValue); + Method *calleeMethod = Method::Cast(callee->GetMethod()); + calleeMethodId = calleeMethod->GetMethodId().GetOffset(); + calleeAbcId = PGOProfiler::GetMethodAbcId(callee); + static_cast(compilationEnv_) + ->UpdateFuncSlotIdMap(calleeMethodId, methodId_.GetOffset(), slotId); + kind = ProfileType::Kind::MethodId; + } else { return; } - ProfileType::Kind kind = (calleeMethodId < 0) ? ProfileType::Kind::BuiltinFunctionId : ProfileType::Kind::MethodId; PGOSampleType* type = new PGOSampleType(ProfileType(abcId_, std::abs(calleeMethodId), kind)); - // Inline will be supported in the future - (void) type; - (void) bcOffset; + UpdatePGOType(bcOffset, type); } void JITProfiler::ConvertNewObjRange(uint32_t slotId, long bcOffset) @@ -325,8 +378,9 @@ void JITProfiler::ConvertNewObjRange(uint32_t slotId, long bcOffset) int ctorMethodId = 0; if (slotValue.IsInt()) { ctorMethodId = slotValue.GetInt(); - } else if (slotValue.IsMethod()) { - Method *calleeMethod = Method::Cast(slotValue); + } else if (slotValue.IsJSFunction()) { + JSFunction *callee = JSFunction::Cast(slotValue); + Method *calleeMethod = Method::Cast(callee->GetMethod()); ctorMethodId = static_cast(calleeMethod->GetMethodId().GetOffset()); } else { return; @@ -350,9 +404,7 @@ void JITProfiler::ConvertGetIterator(uint32_t slotId, long bcOffset) ASSERT(iterKind <= 0); ProfileType::Kind pgoKind = ProfileType::Kind::BuiltinFunctionId; auto type = new PGOSampleType(ProfileType(abcId_, std::abs(iterKind), pgoKind)); - // Inline will be supported in the future - (void) type; - (void) bcOffset; + UpdatePGOType(bcOffset, type); } void JITProfiler::ConvertCreateObject(uint32_t slotId, long bcOffset, int32_t traceId) @@ -390,6 +442,7 @@ void JITProfiler::ConvertCreateObject(uint32_t slotId, long bcOffset, int32_t tr void JITProfiler::ConvertICByName(int32_t bcOffset, uint32_t slotId, BCType type) { + ProfileTypeAccessorLockScope accessorLockScope(vm_->GetJSThread()); JSTaggedValue firstValue = profileTypeInfo_->Get(slotId); if (!firstValue.IsHeapObject()) { if (firstValue.IsHole()) { @@ -403,32 +456,32 @@ void JITProfiler::ConvertICByName(int32_t bcOffset, uint32_t slotId, BCType type if (object->GetClass()->IsHClass()) { JSTaggedValue secondValue = profileTypeInfo_->Get(slotId + 1); JSHClass *hclass = JSHClass::Cast(object); - ConvertICByNameWithHandler(abcId_, bcOffset, hclass, secondValue, type); + ConvertICByNameWithHandler(abcId_, bcOffset, hclass, secondValue, type, slotId + 1); } return; } - ConvertICByNameWithPoly(abcId_, bcOffset, firstValue, type); + ConvertICByNameWithPoly(abcId_, bcOffset, firstValue, type, slotId); } void JITProfiler::ConvertICByNameWithHandler(ApEntityId abcId, int32_t bcOffset, JSHClass *hclass, - JSTaggedValue secondValue, BCType type) + JSTaggedValue secondValue, BCType type, uint32_t slotId) { if (type == BCType::LOAD) { - HandleLoadType(abcId, bcOffset, hclass, secondValue); + HandleLoadType(abcId, bcOffset, hclass, secondValue, slotId); // LoadGlobal return; } - HandleOtherTypes(abcId, bcOffset, hclass, secondValue); + HandleOtherTypes(abcId, bcOffset, hclass, secondValue, slotId); } void JITProfiler::HandleLoadType(ApEntityId &abcId, int32_t &bcOffset, - JSHClass *hclass, JSTaggedValue &secondValue) + JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId) { if (secondValue.IsInt()) { HandleLoadTypeInt(abcId, bcOffset, hclass, secondValue); } else if (secondValue.IsPrototypeHandler()) { - HandleLoadTypePrototypeHandler(abcId, bcOffset, hclass, secondValue); + HandleLoadTypePrototypeHandler(abcId, bcOffset, hclass, secondValue, slotId); } } @@ -446,7 +499,7 @@ void JITProfiler::HandleLoadTypeInt(ApEntityId &abcId, int32_t &bcOffset, } void JITProfiler::HandleLoadTypePrototypeHandler(ApEntityId &abcId, int32_t &bcOffset, - JSHClass *hclass, JSTaggedValue &secondValue) + JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId) { auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject()); auto cellValue = prototypeHandler->GetProtoCell(); @@ -468,13 +521,22 @@ void JITProfiler::HandleLoadTypePrototypeHandler(ApEntityId &abcId, int32_t &bcO return; } auto accessorMethodId = prototypeHandler->GetAccessorMethodId(); + auto accessor = prototypeHandler->GetAccessorJSFunction(); + if (accessor.IsJSFunction()) { + auto accessorFunction = JSFunction::Cast(accessor); + auto methodId = Method::Cast(accessorFunction->GetMethod())->GetMethodId().GetOffset(); + ASSERT(accessorMethodId == methodId); + accessorMethodId = methodId; + static_cast(compilationEnv_) + ->UpdateFuncSlotIdMap(accessorMethodId, methodId_.GetOffset(), slotId); + } if (!AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId)) { return AddBuiltinsInfoByNameInProt(abcId, bcOffset, hclass, holderHClass); } } void JITProfiler::HandleOtherTypes(ApEntityId &abcId, int32_t &bcOffset, - JSHClass *hclass, JSTaggedValue &secondValue) + JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId) { if (secondValue.IsInt()) { AddObjectInfo(abcId, bcOffset, hclass, hclass, hclass); @@ -483,7 +545,7 @@ void JITProfiler::HandleOtherTypes(ApEntityId &abcId, int32_t &bcOffset, } else if (secondValue.IsTransWithProtoHandler()) { HandleTransWithProtoHandler(abcId, bcOffset, hclass, secondValue); } else if (secondValue.IsPrototypeHandler()) { - HandleOtherTypesPrototypeHandler(abcId, bcOffset, hclass, secondValue); + HandleOtherTypesPrototypeHandler(abcId, bcOffset, hclass, secondValue, slotId); } else if (secondValue.IsPropertyBox()) { // StoreGlobal } else if (secondValue.IsStoreTSHandler()) { @@ -520,7 +582,7 @@ void JITProfiler::HandleTransWithProtoHandler(ApEntityId &abcId, int32_t &bcOffs } void JITProfiler::HandleOtherTypesPrototypeHandler(ApEntityId &abcId, int32_t &bcOffset, - JSHClass *hclass, JSTaggedValue &secondValue) + JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId) { auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject()); auto cellValue = prototypeHandler->GetProtoCell(); @@ -534,6 +596,15 @@ void JITProfiler::HandleOtherTypesPrototypeHandler(ApEntityId &abcId, int32_t &b auto holder = prototypeHandler->GetHolder(); auto holderHClass = holder.GetTaggedObject()->GetClass(); auto accessorMethodId = prototypeHandler->GetAccessorMethodId(); + auto accessor = prototypeHandler->GetAccessorJSFunction(); + if (accessor.IsJSFunction()) { + auto accessorFunction = JSFunction::Cast(accessor); + auto methodId = Method::Cast(accessorFunction->GetMethod())->GetMethodId().GetOffset(); + ASSERT(accessorMethodId == methodId); + accessorMethodId = methodId; + static_cast(compilationEnv_) + ->UpdateFuncSlotIdMap(accessorMethodId, methodId_.GetOffset(), slotId); + } AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId); } @@ -552,7 +623,8 @@ void JITProfiler::HandleStoreTSHandler(ApEntityId &abcId, int32_t &bcOffset, AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass); } -void JITProfiler::ConvertICByNameWithPoly(ApEntityId abcId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type) +void JITProfiler::ConvertICByNameWithPoly(ApEntityId abcId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type, + uint32_t slotId) { if (cacheValue.IsWeak()) { return; @@ -571,12 +643,13 @@ void JITProfiler::ConvertICByNameWithPoly(ApEntityId abcId, int32_t bcOffset, JS continue; } JSHClass *hclass = JSHClass::Cast(object); - ConvertICByNameWithHandler(abcId, bcOffset, hclass, handler, type); + ConvertICByNameWithHandler(abcId, bcOffset, hclass, handler, type, slotId); } } void JITProfiler::ConvertICByValue(int32_t bcOffset, uint32_t slotId, BCType type) { + ProfileTypeAccessorLockScope accessorLockScope(vm_->GetJSThread()); JSTaggedValue firstValue = profileTypeInfo_->Get(slotId); if (!firstValue.IsHeapObject()) { if (firstValue.IsHole()) { diff --git a/ecmascript/jit/jit_profiler.h b/ecmascript/jit/jit_profiler.h index 9bb9fdd34..9f8d719bb 100644 --- a/ecmascript/jit/jit_profiler.h +++ b/ecmascript/jit/jit_profiler.h @@ -18,6 +18,7 @@ #include #include "ecmascript/common.h" #include "ecmascript/compiler/bytecodes.h" +#include "ecmascript/compiler/compilation_env.h" #include "ecmascript/elements.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/jspandafile/method_literal.h" @@ -46,9 +47,11 @@ public: JITProfiler(EcmaVM *vm); virtual ~JITProfiler(); - void PUBLIC_API ProfileBytecode(JSThread *thread, JSHandle &profileTypeInfo, + void PUBLIC_API ProfileBytecode(JSThread *thread, const JSHandle &profileTypeInfo, + ProfileTypeInfo *rawProfileTypeInfo, EntityId methodId, ApEntityId abcId, const uint8_t *pcStart, - uint32_t codeSize, const panda_file::File::Header *header); + uint32_t codeSize, const panda_file::File::Header *header, + bool useRawProfileTypeInfo = false); std::unordered_map GetOpTypeMap() { @@ -70,6 +73,10 @@ public: } void ProcessReferences(const WeakRootVisitor &visitor); void UpdateRootProfileType(JSHClass *oldHClass, JSHClass *newHClass); + void SetCompilationEnv(CompilationEnv *env) + { + compilationEnv_ = env; + } private: enum class BCType : uint8_t { STORE, @@ -88,24 +95,25 @@ private: // RwOpType void ConvertICByName(int32_t bcOffset, uint32_t slotId, BCType type); void ConvertICByNameWithHandler(ApEntityId abcId, int32_t bcOffset, JSHClass *hclass, - JSTaggedValue secondValue, BCType type); + JSTaggedValue secondValue, BCType type, uint32_t slotId); void HandleLoadType(ApEntityId &abcId, int32_t &bcOffset, - JSHClass *hclass, JSTaggedValue &secondValue); + JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId); void HandleLoadTypeInt(ApEntityId &abcId, int32_t &bcOffset, JSHClass *hclass, JSTaggedValue &secondValue); void HandleLoadTypePrototypeHandler(ApEntityId &abcId, int32_t &bcOffset, - JSHClass *hclass, JSTaggedValue &secondValue); + JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId); void HandleOtherTypes(ApEntityId &abcId, int32_t &bcOffset, - JSHClass *hclass, JSTaggedValue &secondValue); + JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId); void HandleTransitionHandler(ApEntityId &abcId, int32_t &bcOffset, JSHClass *hclass, JSTaggedValue &secondValue); void HandleTransWithProtoHandler(ApEntityId &abcId, int32_t &bcOffset, JSHClass *hclass, JSTaggedValue &secondValue); void HandleOtherTypesPrototypeHandler(ApEntityId &abcId, int32_t &bcOffset, - JSHClass *hclass, JSTaggedValue &secondValue); + JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId); void HandleStoreTSHandler(ApEntityId &abcId, int32_t &bcOffset, JSHClass *hclass, JSTaggedValue &secondValue); - void ConvertICByNameWithPoly(ApEntityId abcId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type); + void ConvertICByNameWithPoly(ApEntityId abcId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type, + uint32_t slotId); void ConvertICByValue(int32_t bcOffset, uint32_t slotId, BCType type); void ConvertICByValueWithHandler(ApEntityId abcId, int32_t bcOffset, JSHClass *hclass, JSTaggedValue secondValue, BCType type); @@ -179,6 +187,7 @@ private: std::unordered_map bcOffsetPGODefOpTypeMap_{}; CMap tracedProfiles_ {}; RecursiveMutex mutex_; + CompilationEnv *compilationEnv_ {nullptr}; }; } diff --git a/ecmascript/js_function.cpp b/ecmascript/js_function.cpp index 98a6cc154..2c48d4dd9 100644 --- a/ecmascript/js_function.cpp +++ b/ecmascript/js_function.cpp @@ -912,12 +912,6 @@ JSTaggedValue JSFunction::GetRecordName() const return JSTaggedValue::Hole(); } -JSTaggedValue JSFunction::GetProfileTypeInfo() const -{ - JSTaggedValue raw = GetRawProfileTypeInfo(); - return ProfileTypeInfoCell::Cast(raw.GetTaggedObject())->GetValue(); -} - // Those interface below is discarded void JSFunction::InitializeJSFunction(JSThread *thread, [[maybe_unused]] const JSHandle &env, const JSHandle &func, FunctionKind kind) diff --git a/ecmascript/js_function.h b/ecmascript/js_function.h index d97aff6c4..c861a17ab 100644 --- a/ecmascript/js_function.h +++ b/ecmascript/js_function.h @@ -241,7 +241,11 @@ public: JSTaggedValue GetFunctionExtraInfo() const; JSTaggedValue GetNativeFunctionExtraInfo() const; JSTaggedValue GetRecordName() const; - JSTaggedValue GetProfileTypeInfo() const; + JSTaggedValue GetProfileTypeInfo() const + { + JSTaggedValue raw = GetRawProfileTypeInfo(); + return ProfileTypeInfoCell::Cast(raw.GetTaggedObject())->GetValue(); + } void InitializeForConcurrentFunction(JSThread *thread); diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 17578eafd..671240b01 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -1378,6 +1378,11 @@ public: return &jitMutex_; } + RecursiveMutex &GetProfileTypeAccessorLock() + { + return profileTypeAccessorLockMutex_; + } + void SetMachineCodeLowMemory(bool isLow) { machineCodeLowMemory_ = isLow; @@ -1564,6 +1569,7 @@ private: ThreadType threadType_ {ThreadType::JS_THREAD}; RecursiveMutex jitMutex_; bool machineCodeLowMemory_ {false}; + RecursiveMutex profileTypeAccessorLockMutex_; uint64_t jobId_ {0}; diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index d6b465ad4..30ad31715 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -3820,6 +3820,7 @@ JSHandle ObjectFactory::NewPrototypeHandler() handler->SetHandlerInfo(thread_, JSTaggedValue::Undefined()); handler->SetProtoCell(thread_, JSTaggedValue::Undefined()); handler->SetHolder(thread_, JSTaggedValue::Undefined()); + handler->SetAccessorJSFunction(thread_, JSTaggedValue::Undefined()); handler->SetAccessorMethodId(0); return handler; } diff --git a/ecmascript/pgo_profiler/pgo_profiler.cpp b/ecmascript/pgo_profiler/pgo_profiler.cpp index 2f89084b1..dce738b79 100644 --- a/ecmascript/pgo_profiler/pgo_profiler.cpp +++ b/ecmascript/pgo_profiler/pgo_profiler.cpp @@ -1264,10 +1264,11 @@ void PGOProfiler::DumpCall(ApEntityId abcId, const CString &recordName, EntityId return; } kind = ProfileType::Kind::BuiltinFunctionId; - } else if (slotValue.IsMethod()) { - Method *calleeMethod = Method::Cast(slotValue); + } else if (slotValue.IsJSFunction()) { + JSFunction *callee = JSFunction::Cast(slotValue); + Method *calleeMethod = Method::Cast(callee->GetMethod()); calleeMethodId = static_cast(calleeMethod->GetMethodId().GetOffset()); - calleeAbcId = GetMethodAbcId(slotValue); + calleeAbcId = GetMethodAbcId(callee->GetMethod()); kind = ProfileType::Kind::MethodId; } else { return; @@ -1302,8 +1303,9 @@ void PGOProfiler::DumpNewObjRange(ApEntityId abcId, const CString &recordName, E int ctorMethodId = 0; if (slotValue.IsInt()) { ctorMethodId = slotValue.GetInt(); - } else if (slotValue.IsMethod()) { - Method *calleeMethod = Method::Cast(slotValue); + } else if (slotValue.IsJSFunction()) { + JSFunction *callee = JSFunction::Cast(slotValue); + Method *calleeMethod = Method::Cast(callee->GetMethod()); ctorMethodId = static_cast(calleeMethod->GetMethodId().GetOffset()); } else { return; diff --git a/ecmascript/tests/dump_test.cpp b/ecmascript/tests/dump_test.cpp index 717a00684..c0c7d4fd6 100644 --- a/ecmascript/tests/dump_test.cpp +++ b/ecmascript/tests/dump_test.cpp @@ -991,7 +991,7 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump) break; } case JSType::PROTOTYPE_HANDLER: { - CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), PrototypeHandler::SIZE, 4U); + CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), PrototypeHandler::SIZE, 5U); JSHandle protoHandler = factory->NewPrototypeHandler(); DUMP_FOR_HANDLE(protoHandler); break; diff --git a/test/jittest/BUILD.gn b/test/jittest/BUILD.gn index d63b72f6d..4c9102223 100644 --- a/test/jittest/BUILD.gn +++ b/test/jittest/BUILD.gn @@ -23,6 +23,7 @@ group("ark_jit_ts_test") { "construct_with_normal_function", "addition_assignment", "catch_with_osr", + "ts_inline", ] deps = [] diff --git a/test/jittest/ts_inline/BUILD.gn b/test/jittest/ts_inline/BUILD.gn new file mode 100644 index 000000000..692bd7837 --- /dev/null +++ b/test/jittest/ts_inline/BUILD.gn @@ -0,0 +1,19 @@ +# 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. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_jit_test_action("ts_inline") { + deps = [] + extra_option = " --log-info=trace --compiler-trace-inline=true" +} diff --git a/test/jittest/ts_inline/expect_output.txt b/test/jittest/ts_inline/expect_output.txt new file mode 100644 index 000000000..caee0cf8b --- /dev/null +++ b/test/jittest/ts_inline/expect_output.txt @@ -0,0 +1,16 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[trace] aot inline function name: #*#func@ts_inline caller function name: #*#Test@ts_inline +28 +true diff --git a/test/jittest/ts_inline/ts_inline.ts b/test/jittest/ts_inline/ts_inline.ts new file mode 100644 index 000000000..a38eefe6f --- /dev/null +++ b/test/jittest/ts_inline/ts_inline.ts @@ -0,0 +1,42 @@ +/* + * 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. + */ + +function func(arg1 : number, arg2 : number) { + let a3 = 0; + let a1 = arg1 + arg2; + if (a1 > 0) { + a1 = a1 * 2; + } else { + a1++; + } + let a2 = arg1 * arg2; + if (a2 > 0) { + a2 = a2 / 2; + } else { + a2++; + } + a3 = a1 + a2; + return a3; +} + +function Test() { + return func(8, 2); +} + +Test(); +ArkTools.jitCompileAsync(Test); +let res = ArkTools.waitJitCompileFinish(Test); +print(Test()); +print(res); diff --git a/test/test_helper.gni b/test/test_helper.gni index 0a2ab5a02..97399edfb 100644 --- a/test/test_helper.gni +++ b/test/test_helper.gni @@ -4568,16 +4568,19 @@ template("host_jit_test_action") { _host_jsvm_target_ = "//arkcompiler/ets_runtime/ecmascript/js_vm:ark_js_vm(${host_toolchain})" _host_jsoptimizer_lib_ = "//arkcompiler/ets_runtime/ecmascript/compiler:libark_jsoptimizer(${host_toolchain})" _root_out_dir_ = get_label_info(_host_jsvm_target_, "root_out_dir") - _osr_run_options_ = + _jit_run_options_ = " --asm-interpreter=true" + " --compiler-enable-jit=true" + " --compiler-enable-jit-pgo=true" + " --compiler-jit-hotness-threshold=5" + " --enable-pgo-profiler=true" + " --compiler-enable-litecg=true" + " --entry-point=${_target_name_} " - _osr_run_options_ += common_options + _jit_run_options_ += common_options if (defined(invoker.enable_osr) && invoker.enable_osr) { - _osr_run_options_ += " --compiler-enable-osr=true " - _osr_run_options_ += " --compiler-osr-hotness-threshold=1 " + _jit_run_options_ += " --compiler-enable-osr=true " + _jit_run_options_ += " --compiler-osr-hotness-threshold=1 " + } + if (defined(invoker.extra_option)) { + _jit_run_options_ += invoker.extra_option } deps = [ @@ -4591,7 +4594,7 @@ template("host_jit_test_action") { "--script-file", rebase_path(_root_out_dir_) + "/arkcompiler/ets_runtime/ark_js_vm", "--script-options", - _osr_run_options_, + _jit_run_options_, "--script-args", _script_args_, "--expect-file", -- Gitee