1 /* 2 * Copyright (c) 2021-2024 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_INTERPRETER_FRAME_HANDLER_H 17 #define ECMASCRIPT_INTERPRETER_FRAME_HANDLER_H 18 19 #include "ecmascript/frames.h" 20 #include "ecmascript/js_tagged_value.h" 21 #include "ecmascript/js_thread.h" 22 #include "ecmascript/mem/heap.h" 23 #include "ecmascript/mem/visitor.h" 24 #include "ecmascript/method.h" 25 26 namespace panda { 27 namespace ecmascript { 28 class JSThread; 29 class ConstantPool; 30 namespace kungfu { 31 class ArkStackMapParser; 32 }; 33 34 class FrameHandler { 35 public: 36 explicit FrameHandler(JSThread *thread); 37 38 ~FrameHandler() = default; 39 40 DEFAULT_COPY_SEMANTIC(FrameHandler); 41 DEFAULT_MOVE_SEMANTIC(FrameHandler); 42 HasFrame()43 bool HasFrame() const 44 { 45 return sp_ != nullptr; 46 } 47 GetFrameType(const JSTaggedType * sp)48 inline static FrameType GetFrameType(const JSTaggedType *sp) 49 { 50 ASSERT(sp != nullptr); 51 FrameType *typeAddr = reinterpret_cast<FrameType *>(reinterpret_cast<uintptr_t>(sp) - sizeof(FrameType)); 52 return static_cast<FrameType> (static_cast<uint32_t>(*typeAddr) & 53 FrameIterator::CLEARD_LAZY_DEOPT_FLAG); 54 } 55 IsEntryFrame(const uint8_t * pc)56 inline static bool IsEntryFrame(const uint8_t *pc) 57 { 58 return pc == nullptr; 59 } 60 IsEntryFrame()61 bool IsEntryFrame() const 62 { 63 ASSERT(HasFrame()); 64 // The structure of InterpretedFrame, AsmInterpretedFrame, InterpretedEntryFrame is the same, order is pc, base. 65 FrameType type = GetFrameType(); 66 if (type == FrameType::BUILTIN_ENTRY_FRAME || 67 type == FrameType::INTERPRETER_ENTRY_FRAME || 68 type == FrameType::ASM_INTERPRETER_ENTRY_FRAME || 69 type == FrameType::OPTIMIZED_ENTRY_FRAME) { 70 return true; 71 } else if (type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME || 72 type == FrameType::INTERPRETER_FRAME) { 73 FrameIterator it(sp_); 74 InterpretedFrame *state = it.GetFrame<InterpretedFrame>(); 75 return state->GetPc() == nullptr; 76 } 77 return false; 78 } 79 IsInterpretedFrame()80 bool IsInterpretedFrame() const 81 { 82 FrameType type = GetFrameType(); 83 return IsInterpretedFrame(type); 84 } 85 IsInterpretedFrame(FrameType type)86 bool IsInterpretedFrame(FrameType type) const 87 { 88 return (type >= FrameType::INTERPRETER_FIRST) && (type <= FrameType::INTERPRETER_LAST); 89 } 90 IsJSFrame()91 bool IsJSFrame() const 92 { 93 FrameType type = GetFrameType(); 94 return IsJSFrame(type); 95 } 96 IsOptimizedJSFunctionFrame()97 bool IsOptimizedJSFunctionFrame() const 98 { 99 FrameType type = GetFrameType(); 100 return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME || 101 type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME; 102 } 103 IsJSFrame(FrameType type)104 bool IsJSFrame(FrameType type) const 105 { 106 return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type) || IsFastJitFunctionFrame(type); 107 } 108 IsOptimizedJSFunctionFrame(FrameType type)109 bool IsOptimizedJSFunctionFrame(FrameType type) const 110 { 111 return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME || 112 type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME; 113 } 114 IsFastJitFunctionFrame(FrameType type)115 bool IsFastJitFunctionFrame(FrameType type) const 116 { 117 return type == FrameType::FASTJIT_FUNCTION_FRAME || 118 type == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME; 119 } 120 IsAsmInterpretedFrame()121 bool IsAsmInterpretedFrame() const 122 { 123 FrameIterator it(sp_, thread_); 124 FrameType type = it.GetFrameType(); 125 return (type == FrameType::ASM_INTERPRETER_FRAME) || 126 (type == FrameType::INTERPRETER_CONSTRUCTOR_FRAME); 127 } 128 IsAsmInterpretedFrame(FrameType type)129 bool IsAsmInterpretedFrame(FrameType type) const 130 { 131 return (type == FrameType::ASM_INTERPRETER_FRAME) || 132 (type == FrameType::INTERPRETER_CONSTRUCTOR_FRAME); 133 } IsBuiltinFrame()134 bool IsBuiltinFrame() const 135 { 136 FrameType type = GetFrameType(); 137 return (type >= FrameType::BUILTIN_FIRST) && (type <= FrameType::BUILTIN_LAST); 138 } IsBuiltinEntryFrame()139 bool IsBuiltinEntryFrame() const 140 { 141 return (GetFrameType() == FrameType::BUILTIN_ENTRY_FRAME); 142 } 143 IsInterpretedEntryFrame()144 bool IsInterpretedEntryFrame() const 145 { 146 if (thread_->IsAsmInterpreter()) { 147 FrameType type = GetFrameType(); 148 return (type == FrameType::ASM_INTERPRETER_ENTRY_FRAME || type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME); 149 } 150 return (GetFrameType() == FrameType::INTERPRETER_ENTRY_FRAME); 151 } 152 IsInterpretedEntryFrame(FrameType type)153 bool IsInterpretedEntryFrame(FrameType type) const 154 { 155 if (thread_->IsAsmInterpreter()) { 156 return (type == FrameType::ASM_INTERPRETER_ENTRY_FRAME || type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME); 157 } 158 return (type == FrameType::INTERPRETER_ENTRY_FRAME); 159 } 160 IsAsmInterpretedEntryFrame()161 bool IsAsmInterpretedEntryFrame() const 162 { 163 FrameType type = GetFrameType(); 164 return IsAsmInterpretedEntryFrame(type); 165 } 166 IsAsmInterpretedEntryFrame(FrameType type)167 bool IsAsmInterpretedEntryFrame(FrameType type) const 168 { 169 return (type == FrameType::ASM_INTERPRETER_ENTRY_FRAME || type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME); 170 } 171 IsCInterpretedEntryFrame()172 bool IsCInterpretedEntryFrame() const 173 { 174 return (GetFrameType() == FrameType::INTERPRETER_ENTRY_FRAME); 175 } 176 IsCInterpretedEntryFrame(FrameType type)177 bool IsCInterpretedEntryFrame(FrameType type) const 178 { 179 return (type == FrameType::INTERPRETER_ENTRY_FRAME); 180 } 181 IsOptimizedEntryFrame(FrameType type)182 bool IsOptimizedEntryFrame(FrameType type) const 183 { 184 return type == FrameType::OPTIMIZED_ENTRY_FRAME; 185 } 186 IsJSEntryFrame(FrameType type)187 bool IsJSEntryFrame(FrameType type) const 188 { 189 return IsAsmInterpretedEntryFrame(type) || IsOptimizedEntryFrame(type); 190 } 191 IsLeaveFrame()192 bool IsLeaveFrame() const 193 { 194 FrameType type = GetFrameType(); 195 return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV); 196 } 197 IsInterpreterBuiltinFrame()198 bool IsInterpreterBuiltinFrame() const 199 { 200 FrameType type = GetFrameType(); 201 return type == FrameType::INTERPRETER_BUILTIN_FRAME; 202 } 203 IsBaselineBuiltinFrame(FrameType type)204 bool IsBaselineBuiltinFrame(FrameType type) const 205 { 206 return (type == FrameType::BASELINE_BUILTIN_FRAME); 207 } 208 GetSp()209 JSTaggedType *GetSp() const 210 { 211 return sp_; 212 } 213 GetFp()214 JSTaggedType *GetFp() const 215 { 216 return fp_; 217 } 218 GetBaselineNativePc()219 uintptr_t GetBaselineNativePc() const 220 { 221 return baselineNativePc_; 222 } 223 224 void PrevJSFrame(); 225 JSTaggedType *GetPrevJSFrame(); 226 227 // for InterpretedFrame. 228 JSTaggedValue GetVRegValue(size_t index) const; 229 void SetVRegValue(size_t index, JSTaggedValue value); 230 231 // for BaselineBuiltinFrame 232 void FindAndSetBaselineNativePc(FrameIterator it); 233 234 JSTaggedValue GetEnv() const; 235 JSTaggedValue GetAcc() const; 236 uint32_t GetNumberArgs(); 237 uint32_t GetBytecodeOffset() const; 238 Method *GetMethod() const; 239 const JSPandaFile* GetJSPandaFile() const; 240 std::string GetFileName() const; 241 uint32_t GetAbcId() const; 242 uint32_t GetMethodId() const; 243 Method *CheckAndGetMethod() const; 244 JSTaggedValue GetThis() const; 245 JSTaggedValue GetFunction() const; 246 const uint8_t *GetPc() const; 247 ConstantPool *GetConstpool() const; 248 249 void DumpStack(std::ostream &os) const; DumpStack()250 void DumpStack() const 251 { 252 DumpStack(std::cout); 253 } 254 255 void DumpPC(std::ostream &os, const uint8_t *pc) const; DumpPC(const uint8_t * pc)256 void DumpPC(const uint8_t *pc) const 257 { 258 DumpPC(std::cout, pc); 259 } 260 261 // for Frame GC. 262 void Iterate(RootVisitor &visitor); 263 void IterateFrameChain(JSTaggedType *start, RootVisitor &visitor) const; 264 void IterateAssembleStack(RootVisitor &visitor); 265 void IterateEcmaRuntimeCallInfo(RootVisitor &visitor); 266 GetJSThread()267 JSThread *GetJSThread() const 268 { 269 return thread_; 270 } 271 272 private: GetFrameType()273 FrameType GetFrameType() const 274 { 275 ASSERT(HasFrame()); 276 FrameType *typeAddr = reinterpret_cast<FrameType *>(reinterpret_cast<uintptr_t>(sp_) - sizeof(FrameType)); 277 return static_cast<FrameType> (static_cast<uint32_t>(*typeAddr) & 278 FrameIterator::CLEARD_LAZY_DEOPT_FLAG); 279 } 280 281 void AdvanceToJSFrame(); 282 uintptr_t GetInterpretedFrameEnd(JSTaggedType *prevSp) const; 283 private: 284 JSTaggedType *sp_ {nullptr}; 285 JSTaggedType *fp_ {nullptr}; 286 uintptr_t baselineNativePc_ {0}; // For baselineJit upFrame 287 JSThread *thread_ {nullptr}; 288 const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr}; 289 }; 290 291 class StackAssertScope { 292 public: StackAssertScope(JSThread * thread)293 explicit StackAssertScope(JSThread *thread) : thread_(thread), oldSp_(thread->GetCurrentSPFrame()) {} 294 ~StackAssertScope()295 ~StackAssertScope() 296 { 297 if (!thread_->HasPendingException()) { 298 DASSERT_PRINT(oldSp_ == thread_->GetCurrentSPFrame(), 299 "StackAssertScope assert failed, sp did not restore as expeted"); 300 } 301 } 302 303 private: 304 JSThread *thread_ {nullptr}; 305 const JSTaggedType *oldSp_ {nullptr}; 306 }; 307 }; // namespace ecmascript 308 } // namespace panda 309 #endif // ECMASCRIPT_INTERPRETER_FRAME_HANDLER_H 310