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