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