1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#ifndef ECMASCRIPT_COMPILER_TS_INLINE_LOWERING_H 17#define ECMASCRIPT_COMPILER_TS_INLINE_LOWERING_H 18 19#include "ecmascript/compiler/argument_accessor.h" 20#include "ecmascript/compiler/bytecode_circuit_builder.h" 21#include "ecmascript/compiler/bytecode_info_collector.h" 22#include "ecmascript/compiler/pass_manager.h" 23#include "ecmascript/compiler/type_info_accessors.h" 24 25namespace panda::ecmascript::kungfu { 26class CircuitRootScope { 27public: 28 explicit CircuitRootScope(Circuit *circuit) 29 : circuit_(circuit), root_(circuit->GetRoot()) 30 { 31 } 32 33 ~CircuitRootScope() 34 { 35 circuit_->SetRoot(root_); 36 } 37 38private: 39 Circuit *circuit_ {nullptr}; 40 GateRef root_ { 0 }; 41}; 42 43class TSInlineLowering { 44public: 45 static constexpr size_t MAX_INLINE_CALL_ALLOWED = 6; 46 TSInlineLowering(Circuit *circuit, PassContext *ctx, bool enableLog, const std::string &name, 47 NativeAreaAllocator *nativeAreaAllocator, PassOptions *options, uint32_t methodOffset, 48 CallMethodFlagMap *callMethodFlagMap) 49 : circuit_(circuit), 50 compilationEnv_(ctx->GetCompilationEnv()), 51 acc_(circuit), 52 glue_(acc_.GetGlueFromArgList()), 53 builder_(circuit, ctx->GetCompilerConfig()), 54 ptManager_(ctx->GetPTManager()), 55 ctx_(ctx), 56 passOptions_(options), 57 enableLog_(enableLog), 58 methodName_(name), 59 enableTypeLowering_(ctx->GetCompilationEnv()->GetJSOptions().IsEnableTypeLowering()), 60 traceInline_(ctx->GetCompilationEnv()->GetJSOptions().GetTraceInline()), 61 maxInlineBytecodesCount_(ctx->GetCompilationEnv()->GetJSOptions().GetMaxInlineBytecodes()), 62 nativeAreaAllocator_(nativeAreaAllocator), 63 noCheck_(ctx->GetCompilationEnv()->GetJSOptions().IsCompilerNoCheck()), 64 chunk_(circuit->chunk()), 65 inlinedCallMap_(circuit->chunk()), 66 argAcc_(circuit), 67 initMethodOffset_(methodOffset), 68 callMethodFlagMap_(callMethodFlagMap) {} 69 70 ~TSInlineLowering() = default; 71 72 void RunTSInlineLowering(); 73 74private: 75 bool IsLogEnabled() const 76 { 77 return enableLog_; 78 } 79 80 const std::string& GetMethodName() const 81 { 82 return methodName_; 83 } 84 85 bool IsSmallMethod(size_t bcSize) const 86 { 87 return bcSize <= maxInlineBytecodesCount_; 88 } 89 90 bool IsInlineCountsOverflow(size_t inlineCount) const 91 { 92 return inlineCount >= MAX_INLINE_CALL_ALLOWED; 93 } 94 95 void UpdateInlineCounts(GateRef frameArgs, size_t inlineCallCounts) 96 { 97 inlinedCallMap_[frameArgs] = ++inlineCallCounts; 98 } 99 100 bool IsCallSetter(CallKind kind) const 101 { 102 return kind == CallKind::CALL_SETTER; 103 } 104 105 void CollectInlineInfo(); 106 void GetInlinedMethodId(GateRef gate); 107 void CandidateInlineCall(GateRef gate, ChunkQueue<InlineTypeInfoAccessor> &workList); 108 void TryInline(InlineTypeInfoAccessor &info, ChunkQueue<InlineTypeInfoAccessor> &workList); 109 bool FilterInlinedMethod(MethodLiteral* method, std::vector<const uint8_t*> pcOffsets); 110 bool FilterCallInTryCatch(GateRef gate); 111 void InlineCall( 112 MethodInfo &methodInfo, MethodPcInfo &methodPCInfo, MethodLiteral *method, InlineTypeInfoAccessor &info); 113 void ReplaceCallInput(InlineTypeInfoAccessor &info, GateRef glue, MethodLiteral *method); 114 void ReplaceEntryGate(GateRef callGate, GateRef callerFunc, GateRef inlineFunc, GateRef glue); 115 void ReplaceReturnGate(GateRef callGate); 116 void ReplaceHirAndDeleteState(GateRef gate, GateRef state, GateRef depend, GateRef value); 117 GateRef MergeAllReturn(const std::vector<GateRef> &returnVector, GateRef &state, GateRef &depend); 118 bool CheckParameter(GateRef gate, InlineTypeInfoAccessor &info, MethodLiteral* method); 119 void LowerToInlineCall(InlineTypeInfoAccessor &info, const std::vector<GateRef> &args, MethodLiteral* method); 120 void RemoveRoot(); 121 void BuildFrameStateChain(InlineTypeInfoAccessor &info, BytecodeCircuitBuilder &builder); 122 GateRef TraceInlineFunction(GateRef glue, GateRef depend, std::vector<GateRef> &args, GateRef callGate); 123 void InlineFuncCheck(const InlineTypeInfoAccessor &info); 124 void SupplementType(GateRef callGate, GateRef targetGate); 125 void UpdateWorkList(ChunkQueue<InlineTypeInfoAccessor> &workList); 126 size_t GetOrInitialInlineCounts(GateRef frameArgs); 127 bool IsRecursiveFunc(InlineTypeInfoAccessor &info, size_t calleeMethodOffset); 128 void CandidateAccessor(GateRef gate, ChunkQueue<InlineTypeInfoAccessor> &workList, CallKind kind); 129 void CandidateNormalCall(GateRef gate, ChunkQueue<InlineTypeInfoAccessor> &workList, CallKind kind); 130 void InlineAccessorCheck(const InlineTypeInfoAccessor &info); 131 void InlineAccessorCheckInJIT(const InlineTypeInfoAccessor &info); 132 void InlineCheck(InlineTypeInfoAccessor &info); 133 GateRef GetAccessorReceiver(GateRef gate); 134 GateRef GetFrameArgs(InlineTypeInfoAccessor &info); 135 void ReplaceAccessorInput(InlineTypeInfoAccessor &info, GateRef glue, MethodLiteral *method); 136 void ReplaceInput(InlineTypeInfoAccessor &info, GateRef glue, MethodLiteral *method); 137 GateRef BuildAccessor(InlineTypeInfoAccessor &info); 138 GateRef GetCallSetterValue(GateRef gate); 139 GateRef GetFrameState(InlineTypeInfoAccessor &info); 140 void SetInitCallTargetAndConstPoolId(InlineTypeInfoAccessor &info); 141 uint32_t GetAccessorConstpoolId(InlineTypeInfoAccessor &info); 142 bool CalleePFIProcess(uint32_t methodOffset); 143 void UpdateCallMethodFlagMap(uint32_t methodOffset, const MethodLiteral *method); 144 145 Circuit *circuit_ {nullptr}; 146 CompilationEnv *compilationEnv_ {nullptr}; 147 GateAccessor acc_; 148 GateRef glue_; 149 CircuitBuilder builder_; 150 PGOTypeManager *ptManager_ {nullptr}; 151 PassContext *ctx_ {nullptr}; 152 PassOptions *passOptions_ {nullptr}; 153 bool enableLog_ {false}; 154 std::string methodName_; 155 bool enableTypeLowering_ {false}; 156 bool inlineSuccess_ {false}; 157 bool traceInline_ {false}; 158 size_t maxInlineBytecodesCount_ {0}; 159 NativeAreaAllocator *nativeAreaAllocator_ {nullptr}; 160 bool noCheck_ {false}; 161 Chunk* chunk_ {nullptr}; 162 ChunkMap<GateRef, size_t> inlinedCallMap_; 163 size_t lastCallId_ {0}; 164 ArgumentAccessor argAcc_; 165 uint32_t initMethodOffset_ {0}; 166 uint32_t initConstantPoolId_ {0}; 167 GateRef initCallTarget_ {Circuit::NullGate()}; 168 CallMethodFlagMap *callMethodFlagMap_; 169}; 170} // panda::ecmascript::kungfu 171#endif // ECMASCRIPT_COMPILER_TS_INLINE_LOWERING_H 172