• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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