• 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_DEOPTIMIZER_DEOPTIMIZER_H
17 #define ECMASCRIPT_DEOPTIMIZER_DEOPTIMIZER_H
18 
19 #include "ecmascript/base/aligned_struct.h"
20 #include "ecmascript/compiler/argument_accessor.h"
21 #include "ecmascript/deoptimizer/calleeReg.h"
22 #include "ecmascript/js_handle.h"
23 #include "ecmascript/js_tagged_value.h"
24 #include "ecmascript/stackmap/llvm_stackmap_type.h"
25 
26 // todo:place to Deoptimizier class
27 #define LLVM_DEOPT_RELOCATE_SYMBOL "__llvm_deoptimize"
28 namespace panda::ecmascript {
29 class JSThread;
30 enum class SpecVregIndex: int {
31     PC_INDEX = -1,
32     ACC_INDEX = -2,
33     BC_OFFSET_INDEX = -3,
34     ENV_INDEX = -4,
35 };
36 
37 struct Context {
38     uintptr_t callsiteSp;
39     uintptr_t callsiteFp;
40     kungfu::CalleeRegAndOffsetVec calleeRegAndOffset;
41 };
42 
43 struct AsmStackContext : public base::AlignedStruct<base::AlignedPointer::Size(),
44                                                     base::AlignedPointer,
45                                                     base::AlignedPointer,
46                                                     base::AlignedPointer,
47                                                     base::AlignedPointer> {
48     enum class Index : size_t {
49         OUTPUT_COUNT_INDEX = 0,
50         CALLFRAME_TOP_INDEX,
51         RETURN_ADDRESS_INDEX,
52         CALLERFRAME_POINTER_INDEX,
53         NUM_OF_MEMBER
54     };
55 
56     static_assert(static_cast<size_t>(Index::NUM_OF_MEMBER) == NumOfTypes);
57 
GetOutputCountOffsetAsmStackContext58     static size_t GetOutputCountOffset(bool isArch32)
59     {
60         return GetOffset<static_cast<size_t>(Index::OUTPUT_COUNT_INDEX)>(isArch32);
61     }
62 
GetCallFrameTopOffsetAsmStackContext63     static size_t GetCallFrameTopOffset(bool isArch32)
64     {
65         return GetOffset<static_cast<size_t>(Index::CALLFRAME_TOP_INDEX)>(isArch32);
66     }
67 
GetReturnAddressOffsetAsmStackContext68     static size_t GetReturnAddressOffset(bool isArch32)
69     {
70         return GetOffset<static_cast<size_t>(Index::RETURN_ADDRESS_INDEX)>(isArch32);
71     }
72 
GetCallerFpOffsetAsmStackContext73     static size_t GetCallerFpOffset(bool isArch32)
74     {
75         return GetOffset<static_cast<size_t>(Index::CALLERFRAME_POINTER_INDEX)>(isArch32);
76     }
77 
GetSizeAsmStackContext78     static constexpr size_t GetSize(bool isArch32)
79     {
80         return isArch32 ? AsmStackContext::SizeArch32 : AsmStackContext::SizeArch64;
81     }
82 
83     alignas(EAS) size_t outputCount_ {0};
84     alignas(EAS) uintptr_t callFrameTop_{0};
85     alignas(EAS) uintptr_t returnAddr_{0};
86     alignas(EAS) uintptr_t callerFp_{0};
87     // out put data
88 };
89 
90 class FrameWriter;
91 class Deoptimizier {
92 public:
Deoptimizier(JSThread * thread)93     explicit Deoptimizier(JSThread * thread) : thread_(thread)
94     {
95         kungfu::CalleeReg callreg;
96         numCalleeRegs_ = static_cast<size_t>(callreg.GetCallRegNum());
97         JSRuntimeOptions options = thread_->GetEcmaVM()->GetJSOptions();
98         traceDeopt_= options.GetTraceDeopt();
99     }
100     void CollectVregs(const std::vector<kungfu::ARKDeopt>& deoptBundle);
101     void CollectDeoptBundleVec(std::vector<kungfu::ARKDeopt>& deoptBundle);
102     JSTaggedType ConstructAsmInterpretFrame(kungfu::DeoptType type);
103     static std::string DisplayItems(kungfu::DeoptType type);
104 
GetThread()105     JSThread *GetThread() const
106     {
107         return thread_;
108     }
109 
110 private:
GetFrameIndex(kungfu::CommonArgIdx index)111     size_t GetFrameIndex(kungfu::CommonArgIdx index)
112     {
113         return static_cast<size_t>(index) - static_cast<size_t>(kungfu::CommonArgIdx::FUNC);
114     }
GetFrameArgv(size_t idx)115     JSTaggedValue GetFrameArgv(size_t idx)
116     {
117         ASSERT(frameArgvs_ != nullptr);
118         ASSERT(idx < frameArgc_);
119         return JSTaggedValue(frameArgvs_[idx]);
120     }
GetFrameArgv(kungfu::CommonArgIdx index)121     JSTaggedValue GetFrameArgv(kungfu::CommonArgIdx index)
122     {
123         return GetFrameArgv(GetFrameIndex(index));
124     }
GetActualFrameArgs(int32_t index)125     JSTaggedValue GetActualFrameArgs(int32_t index)
126     {
127         index += NUM_MANDATORY_JSFUNC_ARGS;
128         return GetFrameArgv(static_cast<size_t>(index));
129     }
130     bool CollectVirtualRegisters(Method* method, FrameWriter *frameWriter);
HasDeoptValue(int32_t index)131     bool HasDeoptValue(int32_t index) const
132     {
133         return deoptVregs_.find(static_cast<kungfu::OffsetType>(index)) != deoptVregs_.end();
134     }
GetDeoptValue(int32_t index)135     JSTaggedValue GetDeoptValue(int32_t index) const
136     {
137         if (!HasDeoptValue(index)) {
138             return JSTaggedValue::Undefined();
139         }
140         return deoptVregs_.at(static_cast<kungfu::OffsetType>(index));
141     }
142     Method* GetMethod(JSTaggedValue &target);
143     void RelocateCalleeSave();
144     void Dump(Method* method, kungfu::DeoptType type);
145     JSThread *thread_ {nullptr};
146     uintptr_t *calleeRegAddr_ {nullptr};
147     size_t numCalleeRegs_ {0};
148     AsmStackContext stackContext_;
149 
150     std::unordered_map<kungfu::OffsetType, JSTaggedValue> deoptVregs_;
151     struct Context context_ {0, 0, {}};
152     uint32_t pc_ {0};
153     JSTaggedValue env_ {JSTaggedValue::Undefined()};
154     size_t frameArgc_ {0};
155     JSTaggedType *frameArgvs_ {nullptr};
156     bool traceDeopt_{false};
157 };
158 
159 }  // namespace panda::ecmascript
160 #endif // ECMASCRIPT_DEOPTIMIZER_DEOPTIMIZER_H