• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2022 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 #include "ecmascript/frames.h"
17 
18 #include "ecmascript/aot_file_manager.h"
19 #include "ecmascript/ecma_vm.h"
20 #include "ecmascript/interpreter/frame_handler.h"
21 #include "ecmascript/js_thread.h"
22 #include "ecmascript/stackmap/ark_stackmap_parser.h"
23 #include "ecmascript/stackmap/llvm_stackmap_parser.h"
24 
25 #include "ecmascript/platform/os.h"
26 
27 namespace panda::ecmascript {
FrameIterator(JSTaggedType * sp,const JSThread * thread)28 FrameIterator::FrameIterator(JSTaggedType *sp, const JSThread *thread) : current_(sp), thread_(thread)
29 {
30     if (thread != nullptr) {
31         arkStackMapParser_ = thread->GetEcmaVM()->GetAOTFileManager()->GetStackMapParser();
32     }
33 }
34 
ComputeDelta() const35 int FrameIterator::ComputeDelta() const
36 {
37     return fpDeltaPrevFrameSp_;
38 }
39 
GetCallSiteDelta(uintptr_t returnAddr) const40 int FrameIterator::GetCallSiteDelta(uintptr_t returnAddr) const
41 {
42     auto callsiteInfo = CalCallSiteInfo(returnAddr);
43     int delta = std::get<2>(callsiteInfo); // 2:delta index
44     return delta;
45 }
46 
CheckAndGetMethod() const47 Method *FrameIterator::CheckAndGetMethod() const
48 {
49     auto function = GetFunction();
50     if (function.CheckIsJSFunctionBase() || function.CheckIsJSProxy()) {
51         return ECMAObject::Cast(function.GetTaggedObject())->GetCallTarget();
52     }
53     return nullptr;
54 }
55 
GetFunction() const56 JSTaggedValue FrameIterator::GetFunction() const
57 {
58     FrameType type = GetFrameType();
59     switch (type) {
60         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
61             auto frame = GetFrame<OptimizedJSFunctionFrame>();
62             return frame->GetFunction();
63         }
64         case FrameType::ASM_INTERPRETER_FRAME:
65         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
66             auto frame = GetFrame<AsmInterpretedFrame>();
67             return frame->function;
68         }
69         case FrameType::INTERPRETER_FRAME:
70         case FrameType::INTERPRETER_FAST_NEW_FRAME: {
71             auto frame = GetFrame<InterpretedFrame>();
72             return frame->function;
73         }
74         case FrameType::INTERPRETER_BUILTIN_FRAME: {
75             auto frame = GetFrame<InterpretedBuiltinFrame>();
76             return frame->function;
77         }
78         case FrameType::BUILTIN_FRAME_WITH_ARGV: {
79             auto *frame = BuiltinWithArgvFrame::GetFrameFromSp(GetSp());
80             return frame->GetFunction();
81         }
82         case FrameType::BUILTIN_ENTRY_FRAME:
83         case FrameType::BUILTIN_FRAME: {
84             auto *frame = BuiltinFrame::GetFrameFromSp(GetSp());
85             return frame->GetFunction();
86         }
87         case FrameType::BUILTIN_CALL_LEAVE_FRAME: {
88             auto *frame = OptimizedBuiltinLeaveFrame::GetFrameFromSp(GetSp());
89             return JSTaggedValue(*(frame->GetArgv()));
90         }
91         case FrameType::OPTIMIZED_FRAME:
92         case FrameType::OPTIMIZED_ENTRY_FRAME:
93         case FrameType::LEAVE_FRAME:
94         case FrameType::LEAVE_FRAME_WITH_ARGV:
95         case FrameType::INTERPRETER_ENTRY_FRAME:
96         case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
97         case FrameType::ASM_INTERPRETER_BRIDGE_FRAME:
98         case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME:
99         case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
100             return JSTaggedValue::Undefined();
101         }
102         default: {
103             LOG_FULL(FATAL) << "frame type error!";
104             UNREACHABLE();
105         }
106     }
107 }
108 
CalCallSiteInfo(uintptr_t retAddr) const109 AOTFileInfo::CallSiteInfo FrameIterator::CalCallSiteInfo(uintptr_t retAddr) const
110 {
111     auto loader = thread_->GetEcmaVM()->GetAOTFileManager();
112     return loader->CalCallSiteInfo(retAddr);
113 }
114 
115 template <GCVisitedFlag GCVisit>
Advance()116 void FrameIterator::Advance()
117 {
118     ASSERT(!Done());
119     FrameType t = GetFrameType();
120     [[maybe_unused]] bool needCalCallSiteInfo = false;
121     switch (t) {
122         case FrameType::OPTIMIZED_FRAME : {
123             auto frame = GetFrame<OptimizedFrame>();
124             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
125                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp(optimizedReturnAddr_);
126                 optimizedReturnAddr_ = frame->GetReturnAddr();
127                 needCalCallSiteInfo = true;
128             }
129             current_ = frame->GetPrevFrameFp();
130             break;
131         }
132         case FrameType::OPTIMIZED_ENTRY_FRAME : {
133             auto frame = GetFrame<OptimizedEntryFrame>();
134             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
135                 optimizedReturnAddr_ = 0;
136                 optimizedCallSiteSp_ = 0;
137             }
138             current_ = frame->GetPrevFrameFp();
139             break;
140         }
141         case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
142             auto frame = GetFrame<OptimizedJSFunctionUnfoldArgVFrame>();
143             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
144                 optimizedCallSiteSp_ = frame->GetPrevFrameSp();
145                 optimizedReturnAddr_ = frame->GetReturnAddr();
146                 needCalCallSiteInfo = true;
147             }
148             current_ = frame->GetPrevFrameFp();
149             break;
150         }
151         case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME: {
152             auto frame = GetFrame<OptimizedJSFunctionFrame>();
153             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
154                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
155                 optimizedReturnAddr_ = frame->GetReturnAddr();
156                 needCalCallSiteInfo = true;
157             }
158             current_ = frame->GetPrevFrameFp();
159             break;
160         }
161         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
162             auto frame = GetFrame<OptimizedJSFunctionFrame>();
163             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
164                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp(optimizedReturnAddr_);
165                 optimizedReturnAddr_ = frame->GetReturnAddr();
166                 needCalCallSiteInfo = true;
167             }
168             current_ = frame->GetPrevFrameFp();
169             break;
170         }
171         case FrameType::LEAVE_FRAME : {
172             auto frame = GetFrame<OptimizedLeaveFrame>();
173             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
174                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
175                 optimizedReturnAddr_ = frame->GetReturnAddr();
176                 needCalCallSiteInfo = true;
177             }
178             current_ = frame->GetPrevFrameFp();
179             break;
180         }
181         case FrameType::LEAVE_FRAME_WITH_ARGV : {
182             auto frame = GetFrame<OptimizedWithArgvLeaveFrame>();
183             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
184                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
185                 optimizedReturnAddr_ = frame->GetReturnAddr();
186                 needCalCallSiteInfo = true;
187             }
188             current_ = frame->GetPrevFrameFp();
189             break;
190         }
191         case FrameType::BUILTIN_CALL_LEAVE_FRAME : {
192             auto frame = GetFrame<OptimizedBuiltinLeaveFrame>();
193             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
194                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
195                 optimizedReturnAddr_ = frame->GetReturnAddr();
196                 needCalCallSiteInfo = true;
197             }
198             current_ = frame->GetPrevFrameFp();
199             break;
200         }
201         case FrameType::INTERPRETER_FRAME:
202         case FrameType::INTERPRETER_FAST_NEW_FRAME : {
203             auto frame = GetFrame<InterpretedFrame>();
204             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
205                 optimizedReturnAddr_ = 0;
206                 optimizedCallSiteSp_ = 0;
207             }
208             current_ = frame->GetPrevFrameFp();
209             break;
210         }
211         case FrameType::INTERPRETER_BUILTIN_FRAME: {
212             auto frame = GetFrame<InterpretedBuiltinFrame>();
213             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
214                 optimizedReturnAddr_ = 0;
215                 optimizedCallSiteSp_ = 0;
216             }
217             current_ = frame->GetPrevFrameFp();
218             break;
219         }
220         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
221         case FrameType::ASM_INTERPRETER_FRAME : {
222             auto frame = GetFrame<AsmInterpretedFrame>();
223             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
224                 optimizedReturnAddr_ = 0;
225                 optimizedCallSiteSp_ = 0;
226             }
227             current_ = frame->GetPrevFrameFp();
228             break;
229         }
230         case FrameType::BUILTIN_FRAME:
231         case FrameType::BUILTIN_ENTRY_FRAME : {
232             auto frame = GetFrame<BuiltinFrame>();
233             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
234                 optimizedReturnAddr_ = frame->GetReturnAddr();
235                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
236                 needCalCallSiteInfo = true;
237             }
238             current_ = frame->GetPrevFrameFp();
239             break;
240         }
241         case FrameType::BUILTIN_FRAME_WITH_ARGV : {
242             auto frame = GetFrame<BuiltinWithArgvFrame>();
243             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
244                 optimizedReturnAddr_ = frame->GetReturnAddr();
245                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
246                 needCalCallSiteInfo = true;
247             }
248             current_ = frame->GetPrevFrameFp();
249             break;
250         }
251         case FrameType::INTERPRETER_ENTRY_FRAME : {
252             auto frame = GetFrame<InterpretedEntryFrame>();
253             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
254                 optimizedReturnAddr_ = 0;
255                 optimizedCallSiteSp_ = 0;
256             }
257             current_ = frame->GetPrevFrameFp();
258             break;
259         }
260         case FrameType::ASM_INTERPRETER_ENTRY_FRAME : {
261             auto frame = GetFrame<AsmInterpretedEntryFrame>();
262             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
263                 optimizedReturnAddr_ = 0;
264                 optimizedCallSiteSp_ = 0;
265             }
266             current_ = frame->GetPrevFrameFp();
267             break;
268         }
269         case FrameType::ASM_INTERPRETER_BRIDGE_FRAME : {
270             auto frame = GetFrame<AsmInterpretedBridgeFrame>();
271             if constexpr (GCVisit == GCVisitedFlag::VISITED) {
272                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp(optimizedReturnAddr_);
273                 optimizedReturnAddr_ = frame->GetReturnAddr();
274                 needCalCallSiteInfo = true;
275             }
276             current_ = frame->GetPrevFrameFp();
277             break;
278         }
279         default: {
280             UNREACHABLE();
281         }
282     }
283     if constexpr (GCVisit == GCVisitedFlag::VISITED) {
284         if (!needCalCallSiteInfo) {
285             return;
286         }
287         uint64_t textStart = 0;
288         std::tie(textStart, stackMapAddr_, fpDeltaPrevFrameSp_, calleeRegInfo_) = CalCallSiteInfo(optimizedReturnAddr_);
289         ASSERT(optimizedReturnAddr_ >= textStart);
290         optimizedReturnAddr_ = optimizedReturnAddr_ - textStart;
291         if (t == FrameType::LEAVE_FRAME && fpDeltaPrevFrameSp_ == 0) {
292             // it may be asm code stub's leave frame.
293             fpDeltaPrevFrameSp_ = 2 * sizeof(uintptr_t); // 2: skip prev and return addr
294         }
295     }
296 }
297 template void FrameIterator::Advance<GCVisitedFlag::VISITED>();
298 template void FrameIterator::Advance<GCVisitedFlag::IGNORED>();
299 
GetPrevFrameCallSiteSp(uintptr_t curPc) const300 uintptr_t FrameIterator::GetPrevFrameCallSiteSp([[maybe_unused]] uintptr_t curPc) const
301 {
302     if (Done()) {
303         return 0;
304     }
305     auto type = GetFrameType();
306     switch (type) {
307         case FrameType::LEAVE_FRAME: {
308             auto frame = GetFrame<OptimizedLeaveFrame>();
309             return frame->GetCallSiteSp();
310         }
311         case FrameType::LEAVE_FRAME_WITH_ARGV: {
312             auto frame = GetFrame<OptimizedWithArgvLeaveFrame>();
313             return frame->GetCallSiteSp();
314         }
315         case FrameType::BUILTIN_CALL_LEAVE_FRAME: {
316             auto frame = GetFrame<OptimizedBuiltinLeaveFrame>();
317             return frame->GetCallSiteSp();
318         }
319         case FrameType::BUILTIN_FRAME_WITH_ARGV: {
320             auto frame = GetFrame<BuiltinWithArgvFrame>();
321             return frame->GetCallSiteSp();
322         }
323         case FrameType::BUILTIN_FRAME: {
324             auto frame = GetFrame<BuiltinFrame>();
325             return frame->GetCallSiteSp();
326         }
327         case FrameType::ASM_INTERPRETER_BRIDGE_FRAME: {
328             auto frame = GetFrame<AsmInterpretedBridgeFrame>();
329             return frame->GetCallSiteSp();
330         }
331         case FrameType::OPTIMIZED_FRAME:
332         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
333             ASSERT(thread_ != nullptr);
334             auto callSiteSp = reinterpret_cast<uintptr_t>(current_) + fpDeltaPrevFrameSp_;
335             return callSiteSp;
336         }
337         case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
338             auto frame = GetFrame<OptimizedJSFunctionUnfoldArgVFrame>();
339             return frame->GetPrevFrameSp();
340         }
341         case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME : {
342             auto callSiteSp = OptimizedJSFunctionFrame::ComputeArgsConfigFrameSp(current_);
343             return callSiteSp;
344         }
345         case FrameType::BUILTIN_ENTRY_FRAME:
346         case FrameType::ASM_INTERPRETER_FRAME:
347         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
348         case FrameType::INTERPRETER_FRAME:
349         case FrameType::INTERPRETER_FAST_NEW_FRAME:
350         case FrameType::OPTIMIZED_ENTRY_FRAME:
351         case FrameType::INTERPRETER_BUILTIN_FRAME:
352         case FrameType::INTERPRETER_ENTRY_FRAME:
353         case FrameType::ASM_INTERPRETER_ENTRY_FRAME: {
354             return 0;
355         }
356         default: {
357             LOG_FULL(FATAL) << "frame type error!";
358         }
359     }
360 }
361 
GetBytecodeOffset() const362 uint32_t FrameIterator::GetBytecodeOffset() const
363 {
364     FrameType type = this->GetFrameType();
365     switch (type) {
366         case FrameType::ASM_INTERPRETER_FRAME:
367         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
368             auto *frame = this->GetFrame<AsmInterpretedFrame>();
369             Method *method = ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget();
370             auto offset = frame->GetPc() - method->GetBytecodeArray();
371             return static_cast<uint32_t>(offset);
372         }
373         case FrameType::INTERPRETER_FRAME:
374         case FrameType::INTERPRETER_FAST_NEW_FRAME: {
375             auto *frame = this->GetFrame<InterpretedFrame>();
376             Method *method = ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget();
377             auto offset = frame->GetPc() - method->GetBytecodeArray();
378             return static_cast<uint32_t>(offset);
379         }
380         default: {
381             return 0;
382         }
383     }
384 }
385 
GetPrevFrame() const386 uintptr_t FrameIterator::GetPrevFrame() const
387 {
388     FrameType type = GetFrameType();
389     uintptr_t end = 0U;
390     switch (type) {
391         case FrameType::INTERPRETER_FRAME:
392         case FrameType::INTERPRETER_FAST_NEW_FRAME: {
393             auto prevFrame = GetFrame<InterpretedFrame>();
394             end = ToUintPtr(prevFrame);
395             break;
396         }
397         case FrameType::INTERPRETER_ENTRY_FRAME: {
398             auto prevFrame = GetFrame<InterpretedEntryFrame>();
399             end = ToUintPtr(prevFrame);
400             break;
401         }
402         case FrameType::INTERPRETER_BUILTIN_FRAME: {
403             auto prevFrame = GetFrame<InterpretedBuiltinFrame>();
404             end = ToUintPtr(prevFrame);
405             break;
406         }
407         default: {
408             LOG_FULL(FATAL) << "frame type error!";
409         }
410     }
411     return end;
412 }
413 
IteratorStackMap(const RootVisitor & visitor,const RootBaseAndDerivedVisitor & derivedVisitor) const414 bool FrameIterator::IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const
415 {
416     ASSERT(arkStackMapParser_ != nullptr);
417     if (!stackMapAddr_) {  // enter by assembler, no stack map
418         return true;
419     }
420 
421     return arkStackMapParser_->IteratorStackMap(visitor, derivedVisitor, optimizedReturnAddr_,
422         reinterpret_cast<uintptr_t>(current_), optimizedCallSiteSp_, stackMapAddr_);
423 }
424 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor) const425 ARK_INLINE void OptimizedFrame::GCIterate(const FrameIterator &it,
426     [[maybe_unused]] const RootVisitor &visitor,
427     [[maybe_unused]] const RootRangeVisitor &rangeVisitor,
428     const RootBaseAndDerivedVisitor &derivedVisitor) const
429 {
430     bool ret = it.IteratorStackMap(visitor, derivedVisitor);
431     if (!ret) {
432 #ifndef NDEBUG
433         LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
434 #endif
435     }
436 }
437 
CollectBCOffsetInfo(kungfu::ConstInfo & info) const438 void FrameIterator::CollectBCOffsetInfo(kungfu::ConstInfo &info) const
439 {
440     arkStackMapParser_->GetConstInfo(optimizedReturnAddr_, info, stackMapAddr_);
441 }
442 
CollectArkDeopt(std::vector<kungfu::ARKDeopt> & deopts) const443 void FrameIterator::CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const
444 {
445     arkStackMapParser_->GetArkDeopt(optimizedReturnAddr_, stackMapAddr_, deopts);
446 }
447 
GetArgv(const FrameIterator & it) const448 ARK_INLINE JSTaggedType* OptimizedJSFunctionFrame::GetArgv(const FrameIterator &it) const
449 {
450     uintptr_t *preFrameSp = ComputePrevFrameSp(it);
451     return GetArgv(preFrameSp);
452 }
453 
ComputePrevFrameSp(const FrameIterator & it) const454 ARK_INLINE uintptr_t* OptimizedJSFunctionFrame::ComputePrevFrameSp(const FrameIterator &it) const
455 {
456     const JSTaggedType *sp = it.GetSp();
457     int delta = it.ComputeDelta();
458     ASSERT((delta > 0) && (delta % sizeof(uintptr_t) == 0));
459     uintptr_t *preFrameSp = reinterpret_cast<uintptr_t *>(const_cast<JSTaggedType *>(sp))
460             + delta / sizeof(uintptr_t);
461     return preFrameSp;
462 }
463 
464 
CollectBCOffsetInfo(const FrameIterator & it,kungfu::ConstInfo & info) const465 void OptimizedJSFunctionFrame::CollectBCOffsetInfo(const FrameIterator &it, kungfu::ConstInfo &info) const
466 {
467     it.CollectBCOffsetInfo(info);
468 }
469 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor) const470 ARK_INLINE void OptimizedJSFunctionFrame::GCIterate(const FrameIterator &it,
471     const RootVisitor &visitor,
472     const RootRangeVisitor &rangeVisitor,
473     const RootBaseAndDerivedVisitor &derivedVisitor) const
474 {
475     OptimizedJSFunctionFrame *frame = OptimizedJSFunctionFrame::GetFrameFromSp(it.GetSp());
476     uintptr_t *jsFuncPtr = reinterpret_cast<uintptr_t *>(frame);
477     uintptr_t jsFuncSlot = ToUintPtr(jsFuncPtr);
478     visitor(Root::ROOT_FRAME, ObjectSlot(jsFuncSlot));
479 
480     uintptr_t *preFrameSp = frame->ComputePrevFrameSp(it);
481     uintptr_t envSlot = ToUintPtr(preFrameSp);
482     visitor(Root::ROOT_FRAME, ObjectSlot(envSlot));
483 
484     auto argc = frame->GetArgc(preFrameSp);
485     JSTaggedType *argv = frame->GetArgv(reinterpret_cast<uintptr_t *>(preFrameSp));
486     if (argc > 0) {
487         uintptr_t start = ToUintPtr(argv); // argv
488         uintptr_t end = ToUintPtr(argv + argc);
489         rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
490     }
491 
492     bool ret = it.IteratorStackMap(visitor, derivedVisitor);
493     if (!ret) {
494 #ifndef NDEBUG
495         LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
496 #endif
497     }
498 }
499 
GetDeoptBundleInfo(const FrameIterator & it,std::vector<kungfu::ARKDeopt> & deopts) const500 void OptimizedJSFunctionFrame::GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const
501 {
502     it.CollectArkDeopt(deopts);
503 }
504 
GetFuncCalleeRegAndOffset(const FrameIterator & it,kungfu::CalleeRegAndOffsetVec & ret) const505 void OptimizedJSFunctionFrame::GetFuncCalleeRegAndOffset(
506     const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const
507 {
508     it.GetCalleeRegAndOffsetVec(ret);
509 }
510 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor) const511 ARK_INLINE void AsmInterpretedFrame::GCIterate(const FrameIterator &it,
512     const RootVisitor &visitor,
513     const RootRangeVisitor &rangeVisitor,
514     const RootBaseAndDerivedVisitor &derivedVisitor) const
515 {
516     AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(it.GetSp());
517     uintptr_t start = ToUintPtr(it.GetSp());
518     uintptr_t end = ToUintPtr(frame->GetCurrentFramePointer());
519     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
520     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
521     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->thisObj)));
522     if (frame->pc != nullptr) {
523         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->acc)));
524         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->env)));
525     }
526 
527     bool ret = it.IteratorStackMap(visitor, derivedVisitor);
528     if (!ret) {
529 #ifndef NDEBUG
530         LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
531 #endif
532     }
533 }
534 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const535 ARK_INLINE void InterpretedFrame::GCIterate(const FrameIterator &it,
536                                             const RootVisitor &visitor,
537                                             const RootRangeVisitor &rangeVisitor) const
538 {
539     auto sp = it.GetSp();
540     InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp);
541     if (frame->function == JSTaggedValue::Hole()) {
542         return;
543     }
544 
545     JSTaggedType *prevSp = frame->GetPrevFrameFp();
546     uintptr_t start = ToUintPtr(sp);
547     const JSThread *thread = it.GetThread();
548     FrameIterator prevIt(prevSp, thread);
549     uintptr_t end = prevIt.GetPrevFrame();
550 
551     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
552     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
553     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->thisObj)));
554 
555     // pc == nullptr, init InterpretedFrame & native InterpretedFrame.
556     if (frame->pc != nullptr) {
557         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->acc)));
558         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->constpool)));
559         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->env)));
560         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->profileTypeInfo)));
561     }
562 }
563 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const564 ARK_INLINE void InterpretedBuiltinFrame::GCIterate(const FrameIterator &it,
565                                                    const RootVisitor &visitor,
566                                                    const RootRangeVisitor &rangeVisitor) const
567 {
568     auto sp = it.GetSp();
569     InterpretedBuiltinFrame *frame = InterpretedBuiltinFrame::GetFrameFromSp(sp);
570     JSTaggedType *prevSp = frame->GetPrevFrameFp();
571     const JSThread *thread = it.GetThread();
572     FrameIterator prevIt(prevSp, thread);
573 
574     uintptr_t start = ToUintPtr(sp + 2); // 2: numArgs & thread.
575     uintptr_t end = prevIt.GetPrevFrame();
576     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
577     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
578 }
579 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const580 ARK_INLINE void OptimizedLeaveFrame::GCIterate(const FrameIterator &it,
581     [[maybe_unused]] const RootVisitor &visitor,
582     const RootRangeVisitor &rangeVisitor) const
583 {
584     const JSTaggedType *sp = it.GetSp();
585     OptimizedLeaveFrame *frame = OptimizedLeaveFrame::GetFrameFromSp(sp);
586     if (frame->argc > 0) {
587         JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(&frame->argc + 1);
588         uintptr_t start = ToUintPtr(argv); // argv
589         uintptr_t end = ToUintPtr(argv + frame->argc);
590         rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
591     }
592 }
593 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const594 ARK_INLINE void OptimizedWithArgvLeaveFrame::GCIterate(const FrameIterator &it,
595     [[maybe_unused]] const RootVisitor &visitor,
596     const RootRangeVisitor &rangeVisitor) const
597 {
598     const JSTaggedType *sp = it.GetSp();
599     OptimizedWithArgvLeaveFrame *frame = OptimizedWithArgvLeaveFrame::GetFrameFromSp(sp);
600     if (frame->argc > 0) {
601         uintptr_t* argvPtr = reinterpret_cast<uintptr_t *>(&frame->argc + 1);
602         JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(*argvPtr);
603         uintptr_t start = ToUintPtr(argv); // argv
604         uintptr_t end = ToUintPtr(argv + frame->argc);
605         rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
606     }
607 }
608 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const609 ARK_INLINE void OptimizedBuiltinLeaveFrame::GCIterate(const FrameIterator &it,
610     [[maybe_unused]] const RootVisitor &visitor,
611     const RootRangeVisitor &rangeVisitor) const
612 {
613     const JSTaggedType *sp = it.GetSp();
614     OptimizedBuiltinLeaveFrame *frame = OptimizedBuiltinLeaveFrame::GetFrameFromSp(sp);
615     if (frame->argc > 0) {
616         JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(&frame->argc + 1);
617         uintptr_t start = ToUintPtr(argv); // argv
618         uintptr_t end = ToUintPtr(argv + frame->argc);
619         rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
620     }
621 }
622 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const623 ARK_INLINE void BuiltinWithArgvFrame::GCIterate(const FrameIterator &it,
624     [[maybe_unused]] const RootVisitor &visitor,
625     const RootRangeVisitor &rangeVisitor) const
626 {
627     const JSTaggedType *sp = it.GetSp();
628     auto frame = BuiltinWithArgvFrame::GetFrameFromSp(sp);
629     auto argc = static_cast<uint32_t>(frame->GetNumArgs()) + NUM_MANDATORY_JSFUNC_ARGS;
630     JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(frame->GetStackArgsAddress());
631     uintptr_t start = ToUintPtr(argv);
632     uintptr_t end = ToUintPtr(argv + argc);
633     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
634 }
635 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const636 ARK_INLINE void BuiltinFrame::GCIterate(const FrameIterator &it,
637     const RootVisitor &visitor,
638     const RootRangeVisitor &rangeVisitor) const
639 {
640     const JSTaggedType *sp = it.GetSp();
641     auto frame = BuiltinFrame::GetFrameFromSp(sp);
642     // no need to visit stack map for entry frame
643     if (frame->type == FrameType::BUILTIN_ENTRY_FRAME) {
644         // only visit function
645         visitor(Root::ROOT_FRAME, ObjectSlot(frame->GetStackArgsAddress()));
646         return;
647     }
648     JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(frame->GetStackArgsAddress());
649     auto argc = frame->GetNumArgs();
650     uintptr_t start = ToUintPtr(argv);
651     uintptr_t end = ToUintPtr(argv + argc);
652     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
653 }
654 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const655 ARK_INLINE void InterpretedEntryFrame::GCIterate(const FrameIterator &it,
656     [[maybe_unused]] const RootVisitor &visitor,
657     const RootRangeVisitor &rangeVisitor) const
658 {
659     const JSTaggedType* sp = it.GetSp();
660     InterpretedEntryFrame *frame = InterpretedEntryFrame::GetFrameFromSp(sp);
661     JSTaggedType *prevSp = frame->GetPrevFrameFp();
662     if (prevSp == nullptr) {
663         return;
664     }
665 
666     const JSThread *thread = it.GetThread();
667     FrameIterator prevIt(prevSp, thread);
668     uintptr_t start = ToUintPtr(sp + 2); // 2: numArgs & thread.
669     uintptr_t end = prevIt.GetPrevFrame();
670     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
671 }
672 
ReadUintptrFromAddr(int pid,uintptr_t addr,uintptr_t & value)673 bool ReadUintptrFromAddr(int pid, uintptr_t addr, uintptr_t &value)
674 {
675     if (pid == getpid()) {
676         value = *(reinterpret_cast<uintptr_t *>(addr));
677         return true;
678     }
679     long *retAddr = reinterpret_cast<long *>(&value);
680     // note: big endian
681     for (size_t i = 0; i < sizeof(uintptr_t) / sizeof(long); i++) {
682         *retAddr = PtracePeektext(pid, addr);
683         if (*retAddr == -1) {
684             LOG_ECMA(ERROR) << "ReadFromAddr ERROR, addr: " << addr;
685             return false;
686         }
687         addr += sizeof(long);
688         retAddr++;
689     }
690     return true;
691 }
692 
GetTypeOffsetAndPrevOffsetFromFrameType(uintptr_t frameType,uintptr_t & typeOffset,uintptr_t & prevOffset)693 bool GetTypeOffsetAndPrevOffsetFromFrameType(uintptr_t frameType, uintptr_t &typeOffset, uintptr_t &prevOffset)
694 {
695     FrameType type = static_cast<FrameType>(frameType);
696     switch (type) {
697         case FrameType::OPTIMIZED_FRAME:
698             typeOffset = OptimizedFrame::GetTypeOffset();
699             prevOffset = OptimizedFrame::GetPrevOffset();
700             break;
701         case FrameType::OPTIMIZED_ENTRY_FRAME:
702             typeOffset = OptimizedEntryFrame::GetTypeOffset();
703             prevOffset = OptimizedEntryFrame::GetLeaveFrameFpOffset();
704             break;
705         case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME:
706             typeOffset = OptimizedJSFunctionUnfoldArgVFrame::GetTypeOffset();
707             prevOffset = OptimizedJSFunctionUnfoldArgVFrame::GetPrevOffset();
708             break;
709         case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME:
710         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME:
711             typeOffset = OptimizedJSFunctionFrame::GetTypeOffset();
712             prevOffset = OptimizedJSFunctionFrame::GetPrevOffset();
713             break;
714         case FrameType::LEAVE_FRAME:
715             typeOffset = MEMBER_OFFSET(OptimizedLeaveFrame, type);
716             prevOffset = MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp);
717             break;
718         case FrameType::LEAVE_FRAME_WITH_ARGV:
719             typeOffset = MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, type);
720             prevOffset = MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp);
721             break;
722         case FrameType::BUILTIN_CALL_LEAVE_FRAME:
723             typeOffset = OptimizedBuiltinLeaveFrame::GetTypeOffset();
724             prevOffset = OptimizedBuiltinLeaveFrame::GetPrevOffset();
725             break;
726         case FrameType::INTERPRETER_FRAME:
727         case FrameType::INTERPRETER_FAST_NEW_FRAME:
728             typeOffset = MEMBER_OFFSET(InterpretedFrame, base) +
729                          MEMBER_OFFSET(InterpretedFrameBase, type);
730             prevOffset = MEMBER_OFFSET(InterpretedFrame, base) +
731                          MEMBER_OFFSET(InterpretedFrameBase, prev);
732             break;
733         case FrameType::INTERPRETER_BUILTIN_FRAME:
734             typeOffset = MEMBER_OFFSET(InterpretedBuiltinFrame, base) +
735                          MEMBER_OFFSET(InterpretedFrameBase, type);
736             prevOffset = MEMBER_OFFSET(InterpretedBuiltinFrame, base) +
737                          MEMBER_OFFSET(InterpretedFrameBase, prev);
738             break;
739         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
740         case FrameType::ASM_INTERPRETER_FRAME:
741             typeOffset = MEMBER_OFFSET(AsmInterpretedFrame, base) +
742                          MEMBER_OFFSET(InterpretedFrameBase, type);
743             prevOffset = MEMBER_OFFSET(AsmInterpretedFrame, base) +
744                          MEMBER_OFFSET(InterpretedFrameBase, prev);
745             break;
746         case FrameType::BUILTIN_FRAME:
747         case FrameType::BUILTIN_ENTRY_FRAME:
748             typeOffset = MEMBER_OFFSET(BuiltinFrame, type);
749             prevOffset = MEMBER_OFFSET(BuiltinFrame, prevFp);
750             break;
751         case FrameType::BUILTIN_FRAME_WITH_ARGV:
752             typeOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, type);
753             prevOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, prevFp);
754             break;
755         case FrameType::INTERPRETER_ENTRY_FRAME:
756             typeOffset = MEMBER_OFFSET(InterpretedEntryFrame, base) +
757                          MEMBER_OFFSET(InterpretedFrameBase, type);
758             prevOffset = MEMBER_OFFSET(InterpretedEntryFrame, base) +
759                          MEMBER_OFFSET(InterpretedFrameBase, prev);
760             break;
761         case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
762             typeOffset = MEMBER_OFFSET(AsmInterpretedEntryFrame, base) +
763                          MEMBER_OFFSET(InterpretedFrameBase, type);
764             prevOffset = MEMBER_OFFSET(AsmInterpretedEntryFrame, base) +
765                          MEMBER_OFFSET(InterpretedFrameBase, prev);
766             break;
767         case FrameType::ASM_INTERPRETER_BRIDGE_FRAME:
768             typeOffset = MEMBER_OFFSET(AsmInterpretedBridgeFrame, entry) +
769                          MEMBER_OFFSET(AsmInterpretedEntryFrame, base) +
770                          MEMBER_OFFSET(InterpretedFrameBase, type);
771             prevOffset = MEMBER_OFFSET(AsmInterpretedBridgeFrame, entry) +
772                          MEMBER_OFFSET(AsmInterpretedEntryFrame, base) +
773                          MEMBER_OFFSET(InterpretedFrameBase, prev);
774             break;
775         default:
776             return false;
777     }
778     return true;
779 }
780 
StepArkManagedNativeFrame(int pid,uintptr_t * pc,uintptr_t * fp,uintptr_t * sp,char * buf,size_t bufSize)781 bool StepArkManagedNativeFrame(int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t *sp,
782                                [[maybe_unused]] char *buf, [[maybe_unused]] size_t bufSize)
783 {
784     uintptr_t currentPtr = *fp;
785     while (true) {
786         currentPtr -= sizeof(FrameType);
787         uintptr_t frameType = 0;
788         if (!ReadUintptrFromAddr(pid, currentPtr, frameType)) {
789             return false;
790         }
791         uintptr_t typeOffset = 0;
792         uintptr_t prevOffset = 0;
793         if (!GetTypeOffsetAndPrevOffsetFromFrameType(frameType, typeOffset, prevOffset)) {
794             LOG_ECMA(ERROR) << "FrameType ERROR, addr: " << currentPtr << ", frameType: " << frameType;
795             return false;
796         }
797         if (frameType == (uintptr_t)(FrameType::ASM_INTERPRETER_ENTRY_FRAME)) {
798             break;
799         }
800         currentPtr -= typeOffset;
801         currentPtr += prevOffset;
802         if (!ReadUintptrFromAddr(pid, currentPtr, currentPtr)) {
803             return false;
804         }
805     }
806     currentPtr += sizeof(FrameType);
807     *fp = currentPtr;
808     currentPtr += 8;  // 8: size of fp
809     if (!ReadUintptrFromAddr(pid, currentPtr, *pc)) {
810         return false;
811     }
812     currentPtr += 8;  // 8: size of lr
813     *sp = currentPtr;
814     return true;
815 }
816 }  // namespace panda::ecmascript
817 
step_ark_managed_native_frame(int pid,uintptr_t * pc,uintptr_t * fp,uintptr_t * sp,char * buf,size_t buf_sz)818 __attribute__((visibility("default"))) int step_ark_managed_native_frame(
819     int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t *sp, char *buf, size_t buf_sz)
820 {
821     if (panda::ecmascript::StepArkManagedNativeFrame(pid, pc, fp, sp, buf, buf_sz)) {
822         return 1;
823     }
824     return -1;
825 }
826