1 /* 2 * Copyright (c) 2021 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/interpreter/interpreter.h" 21 #include "ecmascript/js_tagged_value.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 explicit FrameHandler(const JSThread *thread, void *fp); 39 ~FrameHandler() = default; 40 41 DEFAULT_COPY_SEMANTIC(FrameHandler); 42 DEFAULT_MOVE_SEMANTIC(FrameHandler); 43 HasFrame()44 bool HasFrame() const 45 { 46 return sp_ != nullptr; 47 } 48 GetFrameType(const JSTaggedType * sp)49 inline static FrameType GetFrameType(const JSTaggedType *sp) 50 { 51 ASSERT(sp != nullptr); 52 FrameType *typeAddr = reinterpret_cast<FrameType *>(reinterpret_cast<uintptr_t>(sp) - sizeof(FrameType)); 53 return *typeAddr; 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 FrameIterator it(sp_); 66 InterpretedFrame *state = it.GetFrame<InterpretedFrame>(); 67 return state->GetPc() == nullptr; 68 } 69 IsInterpretedFrame()70 bool IsInterpretedFrame() const 71 { 72 FrameType type = GetFrameType(); 73 return IsInterpretedFrame(type); 74 } 75 IsInterpretedFrame(FrameType type)76 bool IsInterpretedFrame(FrameType type) const 77 { 78 return (type >= FrameType::INTERPRETER_FIRST) && (type <= FrameType::INTERPRETER_LAST); 79 } 80 IsJSFrame()81 bool IsJSFrame() const 82 { 83 FrameType type = GetFrameType(); 84 return IsJSFrame(type); 85 } 86 IsJSFrame(FrameType type)87 bool IsJSFrame(FrameType type) const 88 { 89 return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type); 90 } 91 IsOptimizedJSFunctionFrame(FrameType type)92 bool IsOptimizedJSFunctionFrame(FrameType type) const 93 { 94 return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME; 95 } 96 IsAsmInterpretedFrame()97 bool IsAsmInterpretedFrame() const 98 { 99 FrameIterator it(sp_, thread_); 100 FrameType type = it.GetFrameType(); 101 return (type == FrameType::ASM_INTERPRETER_FRAME) || 102 (type == FrameType::INTERPRETER_CONSTRUCTOR_FRAME); 103 } 104 IsAsmInterpretedFrame(FrameType type)105 bool IsAsmInterpretedFrame(FrameType type) const 106 { 107 return (type == FrameType::ASM_INTERPRETER_FRAME) || 108 (type == FrameType::INTERPRETER_CONSTRUCTOR_FRAME); 109 } IsBuiltinFrame()110 bool IsBuiltinFrame() const 111 { 112 FrameType type = GetFrameType(); 113 return (type >= FrameType::BUILTIN_FIRST) && (type <= FrameType::BUILTIN_LAST); 114 } IsBuiltinEntryFrame()115 bool IsBuiltinEntryFrame() const 116 { 117 return (GetFrameType() == FrameType::BUILTIN_ENTRY_FRAME); 118 } 119 IsInterpretedEntryFrame()120 bool IsInterpretedEntryFrame() const 121 { 122 if (thread_->IsAsmInterpreter()) { 123 FrameType type = GetFrameType(); 124 return (type == FrameType::ASM_INTERPRETER_ENTRY_FRAME || type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME); 125 } 126 return (GetFrameType() == FrameType::INTERPRETER_ENTRY_FRAME); 127 } 128 IsInterpretedEntryFrame(FrameType type)129 bool IsInterpretedEntryFrame(FrameType type) const 130 { 131 if (thread_->IsAsmInterpreter()) { 132 return (type == FrameType::ASM_INTERPRETER_ENTRY_FRAME || type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME); 133 } 134 return (type == FrameType::INTERPRETER_ENTRY_FRAME); 135 } 136 IsAsmInterpretedEntryFrame()137 bool IsAsmInterpretedEntryFrame() const 138 { 139 FrameType type = GetFrameType(); 140 return IsAsmInterpretedEntryFrame(type); 141 } 142 IsAsmInterpretedEntryFrame(FrameType type)143 bool IsAsmInterpretedEntryFrame(FrameType type) const 144 { 145 return (type == FrameType::ASM_INTERPRETER_ENTRY_FRAME || type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME); 146 } 147 IsCInterpretedEntryFrame()148 bool IsCInterpretedEntryFrame() const 149 { 150 return (GetFrameType() == FrameType::INTERPRETER_ENTRY_FRAME); 151 } 152 IsCInterpretedEntryFrame(FrameType type)153 bool IsCInterpretedEntryFrame(FrameType type) const 154 { 155 return (type == FrameType::INTERPRETER_ENTRY_FRAME); 156 } 157 IsOptimizedEntryFrame(FrameType type)158 bool IsOptimizedEntryFrame(FrameType type) const 159 { 160 return type == FrameType::OPTIMIZED_ENTRY_FRAME; 161 } 162 IsJSEntryFrame(FrameType type)163 bool IsJSEntryFrame(FrameType type) const 164 { 165 return IsAsmInterpretedEntryFrame(type) || IsOptimizedEntryFrame(type); 166 } 167 IsLeaveFrame()168 bool IsLeaveFrame() const 169 { 170 FrameType type = GetFrameType(); 171 return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV); 172 } 173 GetSp()174 JSTaggedType *GetSp() const 175 { 176 return sp_; 177 } 178 GetFp()179 JSTaggedType *GetFp() const 180 { 181 return fp_; 182 } 183 184 void PrevJSFrame(); 185 JSTaggedType *GetPrevJSFrame(); 186 187 // for InterpretedFrame. 188 JSTaggedValue GetVRegValue(size_t index) const; 189 void SetVRegValue(size_t index, JSTaggedValue value); 190 191 JSTaggedValue GetEnv() const; 192 JSTaggedValue GetAcc() const; 193 uint32_t GetNumberArgs(); 194 uint32_t GetBytecodeOffset() const; 195 Method *GetMethod() const; 196 Method *CheckAndGetMethod() const; 197 JSTaggedValue GetThis() const; 198 JSTaggedValue GetFunction() const; 199 const uint8_t *GetPc() const; 200 ConstantPool *GetConstpool() const; 201 202 void DumpStack(std::ostream &os) const; DumpStack()203 void DumpStack() const 204 { 205 DumpStack(std::cout); 206 } 207 208 void DumpPC(std::ostream &os, const uint8_t *pc) const; DumpPC(const uint8_t * pc)209 void DumpPC(const uint8_t *pc) const 210 { 211 DumpPC(std::cout, pc); 212 } 213 214 // for Frame GC. 215 void Iterate(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 216 const RootBaseAndDerivedVisitor &derivedVisitor); 217 void IterateFrameChain(JSTaggedType *start, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 218 const RootBaseAndDerivedVisitor &derivedVisitor) const; 219 void IterateAssembleStack(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 220 const RootBaseAndDerivedVisitor &derivedVisitor); 221 void IterateEcmaRuntimeCallInfo(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor); 222 223 private: GetFrameType()224 FrameType GetFrameType() const 225 { 226 ASSERT(HasFrame()); 227 FrameType *typeAddr = reinterpret_cast<FrameType *>(reinterpret_cast<uintptr_t>(sp_) - sizeof(FrameType)); 228 return *typeAddr; 229 } 230 231 void AdvanceToJSFrame(); 232 uintptr_t GetInterpretedFrameEnd(JSTaggedType *prevSp) const; 233 private: 234 JSTaggedType *sp_ {nullptr}; 235 JSTaggedType *fp_ {nullptr}; 236 const JSThread *thread_ {nullptr}; 237 const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr}; 238 }; 239 240 class StackAssertScope { 241 public: StackAssertScope(JSThread * thread)242 explicit StackAssertScope(JSThread *thread) : thread_(thread), oldSp_(thread->GetCurrentSPFrame()) {} 243 ~StackAssertScope()244 ~StackAssertScope() 245 { 246 if (!thread_->HasPendingException()) { 247 DASSERT_PRINT(oldSp_ == thread_->GetCurrentSPFrame(), 248 "StackAssertScope assert failed, sp did not restore as expeted"); 249 } 250 } 251 252 private: 253 [[maybe_unused]] JSThread *thread_ {nullptr}; 254 const JSTaggedType *oldSp_ {nullptr}; 255 }; 256 257 class FrameBcCollector { 258 public: FrameBcCollector(const JSThread * thread)259 explicit FrameBcCollector(const JSThread *thread) : thread_(thread) 260 { 261 } 262 ~FrameBcCollector() = default; 263 // for collecting bc offset in aot 264 void CollectBCOffsetInfo(); 265 private: 266 std::string GetAotExceptionFuncName(JSTaggedType* fp) const; 267 const JSThread *thread_ {nullptr}; 268 }; 269 }; // namespace ecmascript 270 } // namespace panda 271 #endif // ECMASCRIPT_INTERPRETER_FRAME_HANDLER_H 272