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/interpreter/interpreter.h" 20 #include "ecmascript/js_method.h" 21 #include "ecmascript/js_tagged_value.h" 22 #include "ecmascript/mem/heap.h" 23 #include "ecmascript/mem/object_xray.h" 24 #include "ecmascript/frames.h" 25 26 namespace panda { 27 namespace ecmascript { 28 class JSThread; 29 class JSFunction; 30 class ConstantPool; 31 32 class FrameHandler { 33 public: FrameHandler(const JSThread * thread)34 explicit FrameHandler(const JSThread *thread) 35 : sp_(const_cast<JSTaggedType *>(thread->GetCurrentSPFrame())) {} FrameHandler(JSTaggedType * sp)36 explicit FrameHandler(JSTaggedType *sp) : sp_(sp) {} 37 ~FrameHandler() = default; 38 DEFAULT_COPY_SEMANTIC(FrameHandler); 39 DEFAULT_MOVE_SEMANTIC(FrameHandler); 40 static constexpr uintptr_t kFrameTypeOffset = -sizeof(FrameType); 41 HasFrame()42 bool HasFrame() const 43 { 44 // Breakframe also is a frame 45 return sp_ != nullptr; 46 } IsBreakFrame()47 bool IsBreakFrame() const 48 { 49 ASSERT(HasFrame()); 50 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 51 InterpretedFrame *state = InterpretedFrame::GetFrameFromSp(sp_); 52 return state->sp == nullptr; 53 } 54 void PrevFrame(); 55 GetFrameType()56 FrameType GetFrameType() const 57 { 58 ASSERT(HasFrame()); 59 FrameType* typeAddr = reinterpret_cast<FrameType*>(reinterpret_cast<uintptr_t>(sp_) + kFrameTypeOffset); 60 return *typeAddr; 61 } 62 IsInterpretedFrame()63 bool IsInterpretedFrame() const 64 { 65 FrameType type = GetFrameType(); 66 return (type == FrameType::INTERPRETER_FRAME) || (type == FrameType::INTERPRETER_FAST_NEW_FRAME); 67 } 68 IsOptimizedLeaveFrame()69 bool IsOptimizedLeaveFrame() const 70 { 71 return GetFrameType() == FrameType::OPTIMIZED_LEAVE_FRAME; 72 } 73 GetOptimizedLeaveFrame()74 OptimizedLeaveFrame* GetOptimizedLeaveFrame() const 75 { 76 assert(IsOptimizedLeaveFrame()); 77 return OptimizedLeaveFrame::GetFrameFromSp(sp_); 78 } 79 80 protected: 81 JSTaggedType *sp_ {nullptr}; 82 }; 83 84 class InterpretedFrameHandler : public FrameHandler { 85 public: 86 explicit InterpretedFrameHandler(JSThread *thread); InterpretedFrameHandler(JSTaggedType * sp)87 explicit InterpretedFrameHandler(JSTaggedType *sp) : FrameHandler(sp) {} 88 DEFAULT_COPY_SEMANTIC(InterpretedFrameHandler); 89 DEFAULT_MOVE_SEMANTIC(InterpretedFrameHandler); 90 91 void PrevFrame(); 92 void PrevInterpretedFrame(); 93 InterpretedFrameHandler GetPrevFrame() const; 94 95 JSTaggedValue GetVRegValue(size_t index) const; 96 void SetVRegValue(size_t index, JSTaggedValue value); 97 98 JSTaggedValue GetAcc() const; 99 uint32_t GetSize() const; 100 uint32_t GetBytecodeOffset() const; 101 JSMethod *GetMethod() const; 102 JSTaggedValue GetFunction() const; 103 const uint8_t *GetPc() const; 104 JSTaggedType *GetSp() const; 105 ConstantPool *GetConstpool() const; 106 JSTaggedValue GetEnv() const; 107 108 void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1); 109 110 void DumpStack(std::ostream &os) const; DumpStack()111 void DumpStack() const 112 { 113 DumpStack(std::cout); 114 } 115 void DumpPC(std::ostream &os, const uint8_t *pc) const; DumpPC(const uint8_t * pc)116 void DumpPC(const uint8_t *pc) const 117 { 118 DumpPC(std::cout, pc); 119 } 120 }; 121 122 class OptimizedFrameHandler : public FrameHandler { 123 public: OptimizedFrameHandler(uintptr_t * sp)124 explicit OptimizedFrameHandler(uintptr_t *sp) 125 : FrameHandler(reinterpret_cast<JSTaggedType *>(sp)) {} 126 explicit OptimizedFrameHandler(const JSThread *thread); 127 ~OptimizedFrameHandler() = default; 128 void PrevFrame(); 129 void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1, 130 ChunkMap<DerivedDataKey, uintptr_t> *derivedPointers, 131 bool isVerifying) const; 132 }; 133 134 class OptimizedEntryFrameHandler : public FrameHandler { 135 public: OptimizedEntryFrameHandler(uintptr_t * sp)136 explicit OptimizedEntryFrameHandler(uintptr_t *sp) 137 : FrameHandler(reinterpret_cast<JSTaggedType *>(sp)) {} 138 explicit OptimizedEntryFrameHandler(const JSThread *thread); 139 ~OptimizedEntryFrameHandler() = default; 140 void PrevFrame(); 141 void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1, 142 ChunkMap<DerivedDataKey, uintptr_t> *derivedPointers, 143 bool isVerifying) const; 144 }; 145 146 class OptimizedLeaveFrameHandler : public FrameHandler { 147 public: OptimizedLeaveFrameHandler(uintptr_t * sp)148 explicit OptimizedLeaveFrameHandler(uintptr_t *sp) 149 : FrameHandler(reinterpret_cast<JSTaggedType *>(sp)) {} 150 explicit OptimizedLeaveFrameHandler(const JSThread *thread); 151 ~OptimizedLeaveFrameHandler() = default; 152 void PrevFrame(); 153 void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1, 154 ChunkMap<DerivedDataKey, uintptr_t> *derivedPointers, 155 bool isVerifying) const; 156 }; 157 158 class FrameIterator { 159 public: FrameIterator(JSTaggedType * sp,const JSThread * thread)160 explicit FrameIterator(JSTaggedType *sp, const JSThread *thread) : sp_(sp), thread_(thread) {} 161 ~FrameIterator() = default; 162 void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; 163 void IterateStackMapAfterGC() const; 164 private: 165 JSTaggedType *sp_ {nullptr}; 166 const JSThread *thread_ {nullptr}; 167 }; 168 } // namespace ecmascript 169 } // namespace panda 170 #endif // ECMASCRIPT_INTERPRETER_FRAME_HANDLER_H 171