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/builtins/builtins_call_signature.h" 21 #include "ecmascript/compiler/bytecode_circuit_builder.h" 22 #include "ecmascript/compiler/bytecode_info_collector.h" 23 #include "ecmascript/compiler/circuit_builder-inl.h" 24 #include "ecmascript/compiler/pass_manager.h" 25 #include "ecmascript/compiler/type_info_accessors.h" 26 #include "ecmascript/jspandafile/js_pandafile.h" 27 28 namespace panda::ecmascript::kungfu { 29 class CircuitRootScope { 30 public: CircuitRootScope(Circuit * circuit)31 explicit CircuitRootScope(Circuit *circuit) 32 : circuit_(circuit), root_(circuit->GetRoot()) 33 { 34 } 35 ~CircuitRootScope()36 ~CircuitRootScope() 37 { 38 circuit_->SetRoot(root_); 39 } 40 41 private: 42 Circuit *circuit_ {nullptr}; 43 GateRef root_ { 0 }; 44 }; 45 46 class TSInlineLowering { 47 public: 48 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)49 TSInlineLowering(Circuit *circuit, PassContext *ctx, bool enableLog, const std::string& name, 50 NativeAreaAllocator* nativeAreaAllocator, PassOptions *options, uint32_t methodOffset) 51 : circuit_(circuit), 52 thread_(ctx->GetEcmaVM()->GetJSThread()), 53 acc_(circuit), 54 glue_(acc_.GetGlueFromArgList()), 55 builder_(circuit, ctx->GetCompilerConfig()), 56 tsManager_(ctx->GetTSManager()), 57 ctx_(ctx), 58 passOptions_(options), 59 enableLog_(enableLog), 60 methodName_(name), 61 enableTypeLowering_(ctx->GetEcmaVM()->GetJSOptions().IsEnableTypeLowering()), 62 traceInline_(ctx->GetEcmaVM()->GetJSOptions().GetTraceInline()), 63 maxInlineBytecodesCount_(ctx->GetEcmaVM()->GetJSOptions().GetMaxInlineBytecodes()), 64 nativeAreaAllocator_(nativeAreaAllocator), 65 noCheck_(ctx->GetEcmaVM()->GetJSOptions().IsCompilerNoCheck()), 66 chunk_(circuit->chunk()), 67 inlinedCallMap_(circuit->chunk()), 68 argAcc_(circuit), 69 initMethodOffset_(methodOffset) {} 70 71 ~TSInlineLowering() = default; 72 73 void RunTSInlineLowering(); 74 75 private: IsLogEnabled()76 bool IsLogEnabled() const 77 { 78 return enableLog_; 79 } 80 GetMethodName()81 const std::string& GetMethodName() const 82 { 83 return methodName_; 84 } 85 IsSmallMethod(size_t bcSize)86 bool IsSmallMethod(size_t bcSize) const 87 { 88 return bcSize <= maxInlineBytecodesCount_; 89 } 90 IsInlineCountsOverflow(size_t inlineCount)91 bool IsInlineCountsOverflow(size_t inlineCount) const 92 { 93 return inlineCount >= MAX_INLINE_CALL_ALLOWED; 94 } 95 UpdateInlineCounts(GateRef frameArgs,size_t inlineCallCounts)96 void UpdateInlineCounts(GateRef frameArgs, size_t inlineCallCounts) 97 { 98 inlinedCallMap_[frameArgs] = ++inlineCallCounts; 99 } 100 IsCallSetter(CallKind kind)101 bool IsCallSetter(CallKind kind) const 102 { 103 return kind == CallKind::CALL_SETTER; 104 } 105 106 void CollectInlineInfo(); 107 void GetInlinedMethodId(GateRef gate); 108 void CandidateInlineCall(GateRef gate, ChunkQueue<InlineTypeInfoAccessor> &workList); 109 void TryInline(InlineTypeInfoAccessor &info, ChunkQueue<InlineTypeInfoAccessor> &workList); 110 bool FilterInlinedMethod(MethodLiteral* method, std::vector<const uint8_t*> pcOffsets); 111 bool FilterCallInTryCatch(GateRef gate); 112 void InlineCall( 113 MethodInfo &methodInfo, MethodPcInfo &methodPCInfo, MethodLiteral *method, InlineTypeInfoAccessor &info); 114 void ReplaceCallInput(InlineTypeInfoAccessor &info, GateRef glue, MethodLiteral *method); 115 void ReplaceEntryGate(GateRef callGate, GateRef callerFunc, GateRef inlineFunc, GateRef glue); 116 void ReplaceReturnGate(GateRef callGate); 117 void ReplaceHirAndDeleteState(GateRef gate, GateRef state, GateRef depend, GateRef value); 118 GateRef MergeAllReturn(const std::vector<GateRef> &returnVector, GateRef &state, GateRef &depend); 119 bool CheckParameter(GateRef gate, InlineTypeInfoAccessor &info, MethodLiteral* method); 120 void LowerToInlineCall(InlineTypeInfoAccessor &info, const std::vector<GateRef> &args, MethodLiteral* method); 121 void RemoveRoot(); 122 void BuildFrameStateChain(InlineTypeInfoAccessor &info, BytecodeCircuitBuilder &builder); 123 GateRef TraceInlineFunction(GateRef glue, GateRef depend, std::vector<GateRef> &args, GateRef callGate); 124 void InlineFuncCheck(const InlineTypeInfoAccessor &info); 125 void SupplementType(GateRef callGate, GateRef targetGate); 126 void UpdateWorkList(ChunkQueue<InlineTypeInfoAccessor> &workList); 127 size_t GetOrInitialInlineCounts(GateRef frameArgs); 128 bool IsRecursiveFunc(InlineTypeInfoAccessor &info, size_t calleeMethodOffset); 129 void CandidateAccessor(GateRef gate, ChunkQueue<InlineTypeInfoAccessor> &workList, CallKind kind); 130 void CandidateNormalCall(GateRef gate, ChunkQueue<InlineTypeInfoAccessor> &workList, CallKind kind); 131 void InlineAccessorCheck(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 int32_t GetAccessorConstpoolId(InlineTypeInfoAccessor &info); 142 143 Circuit *circuit_ {nullptr}; 144 JSThread *thread_ {nullptr}; 145 GateAccessor acc_; 146 GateRef glue_; 147 CircuitBuilder builder_; 148 TSManager *tsManager_ {nullptr}; 149 PassContext *ctx_ {nullptr}; 150 PassOptions *passOptions_ {nullptr}; 151 bool enableLog_ {false}; 152 std::string methodName_; 153 bool enableTypeLowering_ {false}; 154 bool inlineSuccess_ {false}; 155 bool traceInline_ {false}; 156 size_t maxInlineBytecodesCount_ {0}; 157 NativeAreaAllocator *nativeAreaAllocator_ {nullptr}; 158 bool noCheck_ {false}; 159 Chunk* chunk_ {nullptr}; 160 ChunkMap<GateRef, size_t> inlinedCallMap_; 161 size_t lastCallId_ {0}; 162 ArgumentAccessor argAcc_; 163 uint32_t initMethodOffset_ {0}; 164 int32_t initConstantPoolId_ {0}; 165 GateRef initCallTarget_ {Circuit::NullGate()}; 166 }; 167 } // panda::ecmascript::kungfu 168 #endif // ECMASCRIPT_COMPILER_TS_INLINE_LOWERING_H 169