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(const JSThread *thread); 37 38 ~FrameHandler() = default; 39 40 DEFAULT_COPY_SEMANTIC(FrameHandler); 41 DEFAULT_MOVE_SEMANTIC(FrameHandler); 42 HasFrame() const43 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 *typeAddr; 53 } 54 IsEntryFrame(const uint8_t *pc)55 inline static bool IsEntryFrame(const uint8_t *pc) 56 { 57 return pc == nullptr; 58 } 59 IsEntryFrame() const60 bool IsEntryFrame() const 61 { 62 ASSERT(HasFrame()); 63 // The structure of InterpretedFrame, AsmInterpretedFrame, InterpretedEntryFrame is the same, order is pc, base. 64 FrameType type = GetFrameType(); 65 if (type == FrameType::BUILTIN_ENTRY_FRAME || 66 type == FrameType::INTERPRETER_ENTRY_FRAME || 67 type == FrameType::ASM_INTERPRETER_ENTRY_FRAME || 68 type == FrameType::OPTIMIZED_ENTRY_FRAME) { 69 return true; 70 } else if (type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME || 71 type == FrameType::INTERPRETER_FRAME) { 72 FrameIterator it(sp_); 73 InterpretedFrame *state = it.GetFrame<InterpretedFrame>(); 74 return state->GetPc() == nullptr; 75 } 76 return false; 77 } 78 IsInterpretedFrame() const79 bool IsInterpretedFrame() const 80 { 81 FrameType type = GetFrameType(); 82 return IsInterpretedFrame(type); 83 } 84 IsInterpretedFrame(FrameType type) const85 bool IsInterpretedFrame(FrameType type) const 86 { 87 return (type >= FrameType::INTERPRETER_FIRST) && (type <= FrameType::INTERPRETER_LAST); 88 } 89 IsJSFrame() const90 bool IsJSFrame() const 91 { 92 FrameType type = GetFrameType(); 93 return IsJSFrame(type); 94 } 95 IsOptimizedJSFunctionFrame() const96 bool IsOptimizedJSFunctionFrame() const 97 { 98 FrameType type = GetFrameType(); 99 return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME || 100 type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME; 101 } 102 IsJSFrame(FrameType type) const103 bool IsJSFrame(FrameType type) const 104 { 105 return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type) || IsFastJitFunctionFrame(type); 106 } 107 IsOptimizedJSFunctionFrame(FrameType type) const108 bool IsOptimizedJSFunctionFrame(FrameType type) const 109 { 110 return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME || 111 type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME; 112 } 113 IsFastJitFunctionFrame(FrameType type) const114 bool IsFastJitFunctionFrame(FrameType type) const 115 { 116 return type == FrameType::FASTJIT_FUNCTION_FRAME || 117 type == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME; 118 } 119 IsAsmInterpretedFrame() const120 bool IsAsmInterpretedFrame() const 121 { 122 FrameIterator it(sp_, thread_); 123 FrameType type = it.GetFrameType(); 124 return (type == FrameType::ASM_INTERPRETER_FRAME) || 125 (type == FrameType::INTERPRETER_CONSTRUCTOR_FRAME); 126 } 127 IsAsmInterpretedFrame(FrameType type) const128 bool IsAsmInterpretedFrame(FrameType type) const 129 { 130 return (type == FrameType::ASM_INTERPRETER_FRAME) || 131 (type == FrameType::INTERPRETER_CONSTRUCTOR_FRAME); 132 } IsBuiltinFrame() const133 bool IsBuiltinFrame() const 134 { 135 FrameType type = GetFrameType(); 136 return (type >= FrameType::BUILTIN_FIRST) && (type <= FrameType::BUILTIN_LAST); 137 } IsBuiltinEntryFrame() const138 bool IsBuiltinEntryFrame() const 139 { 140 return (GetFrameType() == FrameType::BUILTIN_ENTRY_FRAME); 141 } 142 IsInterpretedEntryFrame() const143 bool IsInterpretedEntryFrame() const 144 { 145 if (thread_->IsAsmInterpreter()) { 146 FrameType type = GetFrameType(); 147 return (type == FrameType::ASM_INTERPRETER_ENTRY_FRAME || type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME); 148 } 149 return (GetFrameType() == FrameType::INTERPRETER_ENTRY_FRAME); 150 } 151 IsInterpretedEntryFrame(FrameType type) const152 bool IsInterpretedEntryFrame(FrameType type) const 153 { 154 if (thread_->IsAsmInterpreter()) { 155 return (type == FrameType::ASM_INTERPRETER_ENTRY_FRAME || type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME); 156 } 157 return (type == FrameType::INTERPRETER_ENTRY_FRAME); 158 } 159 IsAsmInterpretedEntryFrame() const160 bool IsAsmInterpretedEntryFrame() const 161 { 162 FrameType type = GetFrameType(); 163 return IsAsmInterpretedEntryFrame(type); 164 } 165 IsAsmInterpretedEntryFrame(FrameType type) const166 bool IsAsmInterpretedEntryFrame(FrameType type) const 167 { 168 return (type == FrameType::ASM_INTERPRETER_ENTRY_FRAME || type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME); 169 } 170 IsCInterpretedEntryFrame() const171 bool IsCInterpretedEntryFrame() const 172 { 173 return (GetFrameType() == FrameType::INTERPRETER_ENTRY_FRAME); 174 } 175 IsCInterpretedEntryFrame(FrameType type) const176 bool IsCInterpretedEntryFrame(FrameType type) const 177 { 178 return (type == FrameType::INTERPRETER_ENTRY_FRAME); 179 } 180 IsOptimizedEntryFrame(FrameType type) const181 bool IsOptimizedEntryFrame(FrameType type) const 182 { 183 return type == FrameType::OPTIMIZED_ENTRY_FRAME; 184 } 185 IsJSEntryFrame(FrameType type) const186 bool IsJSEntryFrame(FrameType type) const 187 { 188 return IsAsmInterpretedEntryFrame(type) || IsOptimizedEntryFrame(type); 189 } 190 IsLeaveFrame() const191 bool IsLeaveFrame() const 192 { 193 FrameType type = GetFrameType(); 194 return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV); 195 } 196 IsInterpreterBuiltinFrame() const197 bool IsInterpreterBuiltinFrame() const 198 { 199 FrameType type = GetFrameType(); 200 return type == FrameType::INTERPRETER_BUILTIN_FRAME; 201 } 202 IsBaselineBuiltinFrame(FrameType type) const203 bool IsBaselineBuiltinFrame(FrameType type) const 204 { 205 return (type == FrameType::BASELINE_BUILTIN_FRAME); 206 } 207 GetSp() const208 JSTaggedType *GetSp() const 209 { 210 return sp_; 211 } 212 GetFp() const213 JSTaggedType *GetFp() const 214 { 215 return fp_; 216 } 217 GetBaselineNativePc() const218 uintptr_t GetBaselineNativePc() const 219 { 220 return baselineNativePc_; 221 } 222 223 void PrevJSFrame(); 224 JSTaggedType *GetPrevJSFrame(); 225 226 // for InterpretedFrame. 227 JSTaggedValue GetVRegValue(size_t index) const; 228 void SetVRegValue(size_t index, JSTaggedValue value); 229 230 // for BaselineBuiltinFrame 231 void FindAndSetBaselineNativePc(FrameIterator it); 232 233 JSTaggedValue GetEnv() const; 234 JSTaggedValue GetAcc() const; 235 uint32_t GetNumberArgs(); 236 uint32_t GetBytecodeOffset() const; 237 Method *GetMethod() const; 238 const JSPandaFile* GetJSPandaFile() const; 239 std::string GetFileName() const; 240 uint32_t GetAbcId() const; 241 uint32_t GetMethodId() const; 242 Method *CheckAndGetMethod() const; 243 JSTaggedValue GetThis() const; 244 JSTaggedValue GetFunction() const; 245 const uint8_t *GetPc() const; 246 ConstantPool *GetConstpool() const; 247 248 void DumpStack(std::ostream &os) const; DumpStack() const249 void DumpStack() const 250 { 251 DumpStack(std::cout); 252 } 253 254 void DumpPC(std::ostream &os, const uint8_t *pc) const; DumpPC(const uint8_t *pc) const255 void DumpPC(const uint8_t *pc) const 256 { 257 DumpPC(std::cout, pc); 258 } 259 260 // for Frame GC. 261 void Iterate(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 262 const RootBaseAndDerivedVisitor &derivedVisitor); 263 void IterateFrameChain(JSTaggedType *start, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 264 const RootBaseAndDerivedVisitor &derivedVisitor) const; 265 void IterateAssembleStack(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 266 const RootBaseAndDerivedVisitor &derivedVisitor); 267 void IterateEcmaRuntimeCallInfo(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor); 268 269 private: GetFrameType() const270 FrameType GetFrameType() const 271 { 272 ASSERT(HasFrame()); 273 FrameType *typeAddr = reinterpret_cast<FrameType *>(reinterpret_cast<uintptr_t>(sp_) - sizeof(FrameType)); 274 return *typeAddr; 275 } 276 277 void AdvanceToJSFrame(); 278 uintptr_t GetInterpretedFrameEnd(JSTaggedType *prevSp) const; 279 private: 280 JSTaggedType *sp_ {nullptr}; 281 JSTaggedType *fp_ {nullptr}; 282 uintptr_t baselineNativePc_ {0}; // For baselineJit upFrame 283 const JSThread *thread_ {nullptr}; 284 const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr}; 285 }; 286 287 class StackAssertScope { 288 public: StackAssertScope(JSThread *thread)289 explicit StackAssertScope(JSThread *thread) : thread_(thread), oldSp_(thread->GetCurrentSPFrame()) {} 290 ~StackAssertScope()291 ~StackAssertScope() 292 { 293 if (!thread_->HasPendingException()) { 294 DASSERT_PRINT(oldSp_ == thread_->GetCurrentSPFrame(), 295 "StackAssertScope assert failed, sp did not restore as expeted"); 296 } 297 } 298 299 private: 300 JSThread *thread_ {nullptr}; 301 const JSTaggedType *oldSp_ {nullptr}; 302 }; 303 }; // namespace ecmascript 304 } // namespace panda 305 #endif // ECMASCRIPT_INTERPRETER_FRAME_HANDLER_H 306