• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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/dfx/stackinfo/js_stackinfo.h"
19 #include "ecmascript/stackmap/ark_stackmap_parser.h"
20 
21 namespace panda::ecmascript {
FrameIterator(JSTaggedType * sp,const JSThread * thread)22 FrameIterator::FrameIterator(JSTaggedType *sp, const JSThread *thread) : current_(sp), thread_(thread)
23 {
24     if (thread != nullptr) {
25         arkStackMapParser_ =
26             const_cast<JSThread *>(thread)->GetEcmaVM()->GetAOTFileManager()->GetStackMapParser();
27     }
28 }
29 
ComputeDelta(const Method * method) const30 int FrameIterator::ComputeDelta(const Method *method) const
31 {
32     if (method == nullptr || isJITFrame_) {
33         return fpDeltaPrevFrameSp_;
34     }
35     return method->GetFpDelta();
36 }
37 
CheckAndGetMethod() const38 Method *FrameIterator::CheckAndGetMethod() const
39 {
40     auto function = GetFunction();
41     if (function.CheckIsJSFunctionBase() || function.CheckIsJSProxy()) {
42         return ECMAObject::Cast(function.GetTaggedObject())->GetCallTarget(thread_);
43     }
44     return nullptr;
45 }
46 
GetFunction() const47 JSTaggedValue FrameIterator::GetFunction() const
48 {
49     FrameType type = GetFrameType();
50     switch (type) {
51         case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
52         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
53             auto frame = GetFrame<OptimizedJSFunctionFrame>();
54             return frame->GetFunction();
55         }
56         case FrameType::ASM_INTERPRETER_FRAME:
57         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
58             auto frame = GetFrame<AsmInterpretedFrame>();
59             return frame->function;
60         }
61         case FrameType::INTERPRETER_FRAME:
62         case FrameType::INTERPRETER_FAST_NEW_FRAME: {
63             auto frame = GetFrame<InterpretedFrame>();
64             return frame->function;
65         }
66         case FrameType::INTERPRETER_BUILTIN_FRAME: {
67             auto frame = GetFrame<InterpretedBuiltinFrame>();
68             return frame->function;
69         }
70         case FrameType::BUILTIN_FRAME_WITH_ARGV: {
71             auto *frame = BuiltinWithArgvFrame::GetFrameFromSp(GetSp());
72             return frame->GetFunction();
73         }
74         case FrameType::BUILTIN_ENTRY_FRAME:
75         case FrameType::BUILTIN_FRAME: {
76             auto *frame = BuiltinFrame::GetFrameFromSp(GetSp());
77             return frame->GetFunction();
78         }
79         case FrameType::BUILTIN_CALL_LEAVE_FRAME: {
80             auto *frame = OptimizedBuiltinLeaveFrame::GetFrameFromSp(GetSp());
81             return JSTaggedValue(*(frame->GetArgv()));
82         }
83         case FrameType::FASTJIT_FUNCTION_FRAME:
84         case FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME: {
85             auto frame = FASTJITFunctionFrame::GetFrameFromSp(GetSp());
86             return frame->GetFunction();
87         }
88         case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME :
89         case FrameType::OPTIMIZED_FRAME:
90         case FrameType::OPTIMIZED_ENTRY_FRAME:
91         case FrameType::ASM_BRIDGE_FRAME:
92         case FrameType::LEAVE_FRAME:
93         case FrameType::BASELINE_BUILTIN_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) << "Unknown frame type: " << static_cast<uintptr_t>(type);
104             UNREACHABLE();
105         }
106     }
107 }
108 
TryCalCallSiteInfoFromMachineCode(uintptr_t retAddr) const109 AOTFileInfo::CallSiteInfo FrameIterator::TryCalCallSiteInfoFromMachineCode(uintptr_t retAddr) const
110 {
111     FrameType type = GetFrameType();
112     if (type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME ||
113         type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME ||
114         type == FrameType::FASTJIT_FUNCTION_FRAME ||
115         type == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME) {
116         auto machineCode = thread_->GetEcmaVM()->GetHeap()->GetMachineCodeObject(retAddr);
117         ASSERT(machineCode != nullptr);
118         const_cast<FrameIterator*>(this)->machineCode_ = reinterpret_cast<JSTaggedType>(machineCode);
119         return reinterpret_cast<MachineCode*>(machineCode_)->CalCallSiteInfo();
120     }
121     return {};
122 }
123 
CalCallSiteInfo(uintptr_t retAddr,bool isDeopt) const124 std::pair<AOTFileInfo::CallSiteInfo, bool> FrameIterator::CalCallSiteInfo(uintptr_t retAddr, bool isDeopt) const
125 {
126     auto callSiteInfo = const_cast<JSThread*>(thread_)->GetEcmaVM()->CalCallSiteInfo(retAddr, isDeopt);
127     if (std::get<1>(callSiteInfo) != nullptr) { // 1 : stackMapAddr
128         return std::make_pair(callSiteInfo, false);
129     }
130     // try get jit code
131     callSiteInfo = TryCalCallSiteInfoFromMachineCode(retAddr);
132     return std::make_pair(callSiteInfo, true);
133 }
134 
135 template <GCVisitedFlag GCVisit>
Advance()136 void FrameIterator::Advance()
137 {
138     ASSERT(!Done());
139     FrameType rawT = GetRawFrameType();
140     FrameType t = GetFrameType();
141     bool needCalCallSiteInfo = false;
142     // If need to get return addr from frame, the flag euqal true.
143     bool needCheckLazyDeoptFrame = false;
144     constexpr bool GCVisitFlag = (GCVisit == GCVisitedFlag::VISITED ||
145                                  GCVisit == GCVisitedFlag::HYBRID_STACK ||
146                                  GCVisit == GCVisitedFlag::DEOPT);
147     switch (t) {
148         case FrameType::OPTIMIZED_FRAME : {
149             auto frame = GetFrame<OptimizedFrame>();
150             if constexpr (GCVisitFlag) {
151                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
152                 optimizedReturnAddr_ = frame->GetReturnAddr();
153                 needCalCallSiteInfo = true;
154                 needCheckLazyDeoptFrame = true;
155             }
156             current_ = frame->GetPrevFrameFp();
157             break;
158         }
159         case FrameType::OPTIMIZED_ENTRY_FRAME : {
160             auto frame = GetFrame<OptimizedEntryFrame>();
161             if constexpr (GCVisitFlag) {
162                 optimizedReturnAddr_ = 0;
163                 optimizedCallSiteSp_ = 0;
164             }
165             current_ = frame->GetPrevFrameFp();
166             break;
167         }
168         case FrameType::BASELINE_BUILTIN_FRAME: {
169             auto frame = GetFrame<BaselineBuiltinFrame>();
170             if constexpr (GCVisitFlag) {
171                 optimizedCallSiteSp_ = 0;
172                 optimizedReturnAddr_ = 0;
173             }
174             current_ = frame->GetPrevFrameFp();
175             break;
176         }
177         case FrameType::ASM_BRIDGE_FRAME : {
178             auto frame = GetFrame<AsmBridgeFrame>();
179             if constexpr (GCVisitFlag) {
180                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
181                 optimizedReturnAddr_ = frame->GetReturnAddr();
182                 needCalCallSiteInfo = true;
183                 needCheckLazyDeoptFrame = true;
184             }
185             current_ = frame->GetPrevFrameFp();
186             break;
187         }
188         case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
189             auto frame = GetFrame<OptimizedJSFunctionUnfoldArgVFrame>();
190             if constexpr (GCVisitFlag) {
191                 optimizedCallSiteSp_ = frame->GetPrevFrameSp();
192                 optimizedReturnAddr_ = frame->GetReturnAddr();
193                 needCalCallSiteInfo = true;
194                 needCheckLazyDeoptFrame = true;
195             }
196             current_ = frame->GetPrevFrameFp();
197             break;
198         }
199         case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME: {
200             auto frame = GetFrame<OptimizedJSFunctionFrame>();
201             if constexpr (GCVisitFlag) {
202                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
203                 optimizedReturnAddr_ = frame->GetReturnAddr();
204                 needCalCallSiteInfo = true;
205                 needCheckLazyDeoptFrame = true;
206             }
207             current_ = frame->GetPrevFrameFp();
208             break;
209         }
210         case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
211         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
212             auto frame = GetFrame<OptimizedJSFunctionFrame>();
213             if constexpr (GCVisitFlag) {
214                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
215                 optimizedReturnAddr_ = frame->GetReturnAddr();
216                 needCalCallSiteInfo = true;
217                 needCheckLazyDeoptFrame = true;
218             }
219             current_ = frame->GetPrevFrameFp();
220             break;
221         }
222         case FrameType::LEAVE_FRAME : {
223             auto frame = GetFrame<OptimizedLeaveFrame>();
224             if constexpr (GCVisitFlag) {
225                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
226                 optimizedReturnAddr_ = frame->GetReturnAddr();
227                 needCalCallSiteInfo = true;
228                 needCheckLazyDeoptFrame = true;
229             }
230             current_ = frame->GetPrevFrameFp();
231             break;
232         }
233         case FrameType::LEAVE_FRAME_WITH_ARGV : {
234             auto frame = GetFrame<OptimizedWithArgvLeaveFrame>();
235             if constexpr (GCVisitFlag) {
236                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
237                 optimizedReturnAddr_ = frame->GetReturnAddr();
238                 needCalCallSiteInfo = true;
239                 needCheckLazyDeoptFrame = true;
240             }
241             current_ = frame->GetPrevFrameFp();
242             break;
243         }
244         case FrameType::BUILTIN_CALL_LEAVE_FRAME : {
245             auto frame = GetFrame<OptimizedBuiltinLeaveFrame>();
246             if constexpr (GCVisitFlag) {
247                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
248                 optimizedReturnAddr_ = frame->GetReturnAddr();
249                 needCalCallSiteInfo = true;
250                 needCheckLazyDeoptFrame = true;
251             }
252             current_ = frame->GetPrevFrameFp();
253             break;
254         }
255         case FrameType::INTERPRETER_FRAME:
256         case FrameType::INTERPRETER_FAST_NEW_FRAME : {
257             auto frame = GetFrame<InterpretedFrame>();
258             if constexpr (GCVisitFlag) {
259                 optimizedReturnAddr_ = 0;
260                 optimizedCallSiteSp_ = 0;
261             }
262             current_ = frame->GetPrevFrameFp();
263             break;
264         }
265         case FrameType::INTERPRETER_BUILTIN_FRAME: {
266             auto frame = GetFrame<InterpretedBuiltinFrame>();
267             if constexpr (GCVisitFlag) {
268                 optimizedReturnAddr_ = 0;
269                 optimizedCallSiteSp_ = 0;
270             }
271             current_ = frame->GetPrevFrameFp();
272             break;
273         }
274         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
275         case FrameType::ASM_INTERPRETER_FRAME : {
276             auto frame = GetFrame<AsmInterpretedFrame>();
277             if constexpr (GCVisitFlag) {
278                 optimizedReturnAddr_ = 0;
279                 optimizedCallSiteSp_ = 0;
280             }
281             current_ = frame->GetPrevFrameFp();
282             break;
283         }
284         case FrameType::BUILTIN_FRAME : {
285             auto frame = GetFrame<BuiltinFrame>();
286             if constexpr (GCVisitFlag) {
287                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
288                 optimizedReturnAddr_ = frame->GetReturnAddr();
289                 needCalCallSiteInfo = true;
290                 needCheckLazyDeoptFrame = true;
291             }
292             current_ = frame->GetPrevFrameFp();
293             break;
294         }
295         case FrameType::BUILTIN_ENTRY_FRAME : {
296             auto frame = GetFrame<BuiltinFrame>();
297             if constexpr (GCVisitFlag) {
298                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
299                 optimizedReturnAddr_ = frame->GetReturnAddr();
300                 needCalCallSiteInfo = false;
301                 needCheckLazyDeoptFrame = true;
302             }
303             current_ = frame->GetPrevFrameFp();
304             break;
305         }
306         case FrameType::BUILTIN_FRAME_WITH_ARGV : {
307             auto frame = GetFrame<BuiltinWithArgvFrame>();
308             if constexpr (GCVisitFlag) {
309                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
310                 optimizedReturnAddr_ = frame->GetReturnAddr();
311                 needCalCallSiteInfo = true;
312                 needCheckLazyDeoptFrame = true;
313             }
314             current_ = frame->GetPrevFrameFp();
315             break;
316         }
317         case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME : {
318             auto frame = GetFrame<BuiltinWithArgvFrame>();
319             if constexpr (GCVisitFlag) {
320                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
321                 optimizedReturnAddr_ = frame->GetReturnAddr();
322                 needCalCallSiteInfo = true;
323                 needCheckLazyDeoptFrame = true;
324             }
325             current_ = frame->GetPrevFrameFp();
326             break;
327         }
328         case FrameType::INTERPRETER_ENTRY_FRAME : {
329             auto frame = GetFrame<InterpretedEntryFrame>();
330             if constexpr (GCVisitFlag) {
331                 optimizedReturnAddr_ = 0;
332                 optimizedCallSiteSp_ = 0;
333             }
334             current_ = frame->GetPrevFrameFp();
335             break;
336         }
337         case FrameType::ASM_INTERPRETER_ENTRY_FRAME : {
338             auto frame = GetFrame<AsmInterpretedEntryFrame>();
339             if constexpr (GCVisitFlag) {
340                 optimizedReturnAddr_ = 0;
341                 optimizedCallSiteSp_ = 0;
342             }
343             current_ = frame->GetPrevFrameFp();
344             break;
345         }
346         case FrameType::ASM_INTERPRETER_BRIDGE_FRAME : {
347             auto frame = GetFrame<AsmInterpretedBridgeFrame>();
348             if constexpr (GCVisitFlag) {
349                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
350                 optimizedReturnAddr_ = frame->GetReturnAddr();
351                 needCalCallSiteInfo = true;
352                 needCheckLazyDeoptFrame = true;
353             }
354             current_ = frame->GetPrevFrameFp();
355             break;
356         }
357         case FrameType::FASTJIT_FUNCTION_FRAME:
358         case FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME: {
359             auto frame = GetFrame<FASTJITFunctionFrame>();
360             if constexpr (GCVisitFlag) {
361                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
362                 optimizedReturnAddr_ = frame->GetReturnAddr();
363                 needCalCallSiteInfo = true;
364                 needCheckLazyDeoptFrame = true;
365             }
366             current_ = frame->GetPrevFrameFp();
367             break;
368         }
369         default: {
370             if constexpr (GCVisit == GCVisitedFlag::HYBRID_STACK) {
371                 current_ = nullptr;
372                 break;
373             }
374             LOG_ECMA(FATAL) << "this branch is unreachable";
375             UNREACHABLE();
376         }
377     }
378 
379     needCheckLazyDeoptFrame &= IsLazyDeoptFrameType(rawT);
380     if (UNLIKELY(needCheckLazyDeoptFrame)) {
381         optimizedReturnAddr_ = const_cast<JSThread *>(thread_)->GetCallSiteReturnAddr(optimizedCallSiteSp_);
382     }
383 
384     if constexpr (GCVisitFlag) {
385         if (!needCalCallSiteInfo) {
386             return;
387         }
388         uint64_t textStart = 0;
389         AOTFileInfo::CallSiteInfo callSiteInfo;
390         if constexpr (GCVisit == GCVisitedFlag::DEOPT) {
391             std::tie(callSiteInfo, isJITFrame_) = CalCallSiteInfo(optimizedReturnAddr_, true);
392         } else {
393             std::tie(callSiteInfo, isJITFrame_) = CalCallSiteInfo(optimizedReturnAddr_, false);
394         }
395         std::tie(textStart, stackMapAddr_, fpDeltaPrevFrameSp_, calleeRegInfo_) = callSiteInfo;
396         ASSERT(optimizedReturnAddr_ >= textStart);
397         optimizedReturnAddr_ = optimizedReturnAddr_ - textStart;
398     }
399 }
400 template void FrameIterator::Advance<GCVisitedFlag::VISITED>();
401 template void FrameIterator::Advance<GCVisitedFlag::IGNORED>();
402 template void FrameIterator::Advance<GCVisitedFlag::HYBRID_STACK>();
403 template void FrameIterator::Advance<GCVisitedFlag::DEOPT>();
404 
GetReturnAddrAddress() const405 uintptr_t *FrameIterator::GetReturnAddrAddress() const
406 {
407     FrameType type = GetFrameType();
408     switch (type) {
409         case FrameType::OPTIMIZED_FRAME : {
410             auto frame = GetFrame<OptimizedFrame>();
411             return const_cast<uintptr_t *>(frame->GetReturnAddrAddress());
412         }
413         case FrameType::BASELINE_BUILTIN_FRAME: {
414             auto frame = GetFrame<BaselineBuiltinFrame>();
415             return const_cast<uintptr_t *>(frame->GetReturnAddrAddress());
416         }
417         case FrameType::ASM_BRIDGE_FRAME : {
418             auto frame = GetFrame<AsmBridgeFrame>();
419             return const_cast<uintptr_t *>(frame->GetReturnAddrAddress());
420         }
421         case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
422             auto frame = GetFrame<OptimizedJSFunctionUnfoldArgVFrame>();
423             return const_cast<uintptr_t *>(frame->GetReturnAddrAddress());
424         }
425         case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME:
426         case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
427         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
428             auto frame = GetFrame<OptimizedJSFunctionFrame>();
429             return const_cast<uintptr_t *>(frame->GetReturnAddrAddress());
430         }
431         case FrameType::LEAVE_FRAME : {
432             auto frame = GetFrame<OptimizedLeaveFrame>();
433             return const_cast<uintptr_t *>(frame->GetReturnAddrAddress());
434         }
435         case FrameType::LEAVE_FRAME_WITH_ARGV : {
436             auto frame = GetFrame<OptimizedWithArgvLeaveFrame>();
437             return const_cast<uintptr_t *>(frame->GetReturnAddrAddress());
438         }
439         case FrameType::BUILTIN_CALL_LEAVE_FRAME : {
440             auto frame = GetFrame<OptimizedBuiltinLeaveFrame>();
441             return const_cast<uintptr_t *>(frame->GetReturnAddrAddress());
442         }
443         case FrameType::BUILTIN_FRAME:
444         case FrameType::BUILTIN_ENTRY_FRAME : {
445             auto frame = GetFrame<BuiltinFrame>();
446             return const_cast<uintptr_t *>(frame->GetReturnAddrAddress());
447         }
448         case FrameType::BUILTIN_FRAME_WITH_ARGV :
449         case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME : {
450             auto frame = GetFrame<BuiltinWithArgvFrame>();
451             return const_cast<uintptr_t *>(frame->GetReturnAddrAddress());
452         }
453         case FrameType::ASM_INTERPRETER_BRIDGE_FRAME : {
454             auto frame = GetFrame<AsmInterpretedBridgeFrame>();
455             return const_cast<uintptr_t *>(frame->GetReturnAddrAddress());
456         }
457         default:
458             break;
459     }
460     return nullptr;
461 }
462 
GetPrevFrameCallSiteSp() const463 uintptr_t FrameIterator::GetPrevFrameCallSiteSp() const
464 {
465     if (Done()) {
466         return 0;
467     }
468     auto type = GetFrameType();
469     switch (type) {
470         case FrameType::LEAVE_FRAME: {
471             auto frame = GetFrame<OptimizedLeaveFrame>();
472             return frame->GetCallSiteSp();
473         }
474         case FrameType::LEAVE_FRAME_WITH_ARGV: {
475             auto frame = GetFrame<OptimizedWithArgvLeaveFrame>();
476             return frame->GetCallSiteSp();
477         }
478         case FrameType::BUILTIN_CALL_LEAVE_FRAME: {
479             auto frame = GetFrame<OptimizedBuiltinLeaveFrame>();
480             return frame->GetCallSiteSp();
481         }
482         case FrameType::BUILTIN_FRAME_WITH_ARGV: {
483             auto frame = GetFrame<BuiltinWithArgvFrame>();
484             return frame->GetCallSiteSp();
485         }
486         case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME: {
487             auto frame = GetFrame<BuiltinWithArgvFrame>();
488             return frame->GetCallSiteSp();
489         }
490         case FrameType::BUILTIN_FRAME: {
491             auto frame = GetFrame<BuiltinFrame>();
492             return frame->GetCallSiteSp();
493         }
494         case FrameType::ASM_INTERPRETER_BRIDGE_FRAME: {
495             auto frame = GetFrame<AsmInterpretedBridgeFrame>();
496             return frame->GetCallSiteSp();
497         }
498         case FrameType::OPTIMIZED_FRAME:
499         case FrameType::BASELINE_BUILTIN_FRAME:  // maybe we can store fpDelta somewhere else for these 2 cases
500         case FrameType::FASTJIT_FUNCTION_FRAME:
501         case FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME: {
502             ASSERT(thread_ != nullptr);
503             auto callSiteSp = reinterpret_cast<uintptr_t>(current_) + fpDeltaPrevFrameSp_;
504             return callSiteSp;
505         }
506         case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
507         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
508             ASSERT(thread_ != nullptr);
509             auto method = CheckAndGetMethod();
510             ASSERT(method != nullptr);
511             int delta = ComputeDelta(method);
512             auto callSiteSp = reinterpret_cast<uintptr_t>(current_) + delta;
513             return callSiteSp;
514         }
515         case FrameType::ASM_BRIDGE_FRAME: {
516             auto frame = GetFrame<AsmBridgeFrame>();
517             return frame->GetCallSiteSp();
518         }
519         case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
520             auto frame = GetFrame<OptimizedJSFunctionUnfoldArgVFrame>();
521             return frame->GetPrevFrameSp();
522         }
523         case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME : {
524             auto callSiteSp = OptimizedJSFunctionFrame::ComputeArgsConfigFrameSp(current_);
525             return callSiteSp;
526         }
527         case FrameType::BUILTIN_ENTRY_FRAME:
528         case FrameType::ASM_INTERPRETER_FRAME:
529         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
530         case FrameType::INTERPRETER_FRAME:
531         case FrameType::INTERPRETER_FAST_NEW_FRAME:
532         case FrameType::OPTIMIZED_ENTRY_FRAME:
533         case FrameType::INTERPRETER_BUILTIN_FRAME:
534         case FrameType::INTERPRETER_ENTRY_FRAME:
535         case FrameType::ASM_INTERPRETER_ENTRY_FRAME: {
536             break;
537         }
538         default: {
539             LOG_FULL(FATAL) << "Unknown frame type: " << static_cast<uintptr_t>(type);
540         }
541     }
542     return 0;
543 }
544 
GetBytecodeOffset() const545 uint32_t FrameIterator::GetBytecodeOffset() const
546 {
547     FrameType type = this->GetFrameType();
548     switch (type) {
549         case FrameType::ASM_INTERPRETER_FRAME:
550         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
551             auto *frame = this->GetFrame<AsmInterpretedFrame>();
552             Method *method = ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget(thread_);
553             auto offset = frame->GetPc() - method->GetBytecodeArray();
554             return static_cast<uint32_t>(offset);
555         }
556         case FrameType::INTERPRETER_FRAME:
557         case FrameType::INTERPRETER_FAST_NEW_FRAME: {
558             auto *frame = this->GetFrame<InterpretedFrame>();
559             Method *method = ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget(thread_);
560             auto offset = frame->GetPc() - method->GetBytecodeArray();
561             return static_cast<uint32_t>(offset);
562         }
563         case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
564         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
565             [[fallthrough]];
566         }
567         case FrameType::FASTJIT_FUNCTION_FRAME:
568         case FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME: {
569             [[fallthrough]];
570         }
571         default: {
572             break;
573         }
574     }
575     return 0;
576 }
577 
GetStackTraceInfos(std::vector<std::pair<JSTaggedType,uint32_t>> & stackTraceInfos,bool needBaselineSpecialHandling,uint32_t pcOffset) const578 void FrameIterator::GetStackTraceInfos(std::vector<std::pair<JSTaggedType, uint32_t>> &stackTraceInfos,
579                                        bool needBaselineSpecialHandling, uint32_t pcOffset) const
580 {
581     FrameType type = this->GetFrameType();
582     switch (type) {
583         case FrameType::ASM_INTERPRETER_FRAME:
584         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
585             auto *frame = this->GetFrame<AsmInterpretedFrame>();
586             uint32_t offset;
587             if (UNLIKELY(needBaselineSpecialHandling)) {
588                 offset = pcOffset;
589             } else {
590                 Method *method = ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget(thread_);
591                 offset = frame->GetPc() - method->GetBytecodeArray();
592             }
593             stackTraceInfos.push_back(std::make_pair(frame->function.GetRawData(), static_cast<uint32_t>(offset)));
594             break;
595         }
596         case FrameType::INTERPRETER_FRAME:
597         case FrameType::INTERPRETER_FAST_NEW_FRAME: {
598             auto *frame = this->GetFrame<InterpretedFrame>();
599             Method *method = ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget(thread_);
600             auto offset = frame->GetPc() - method->GetBytecodeArray();
601             stackTraceInfos.push_back(std::make_pair(frame->function.GetRawData(), static_cast<uint32_t>(offset)));
602             break;
603         }
604         case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
605         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME:
606         case FrameType::FASTJIT_FUNCTION_FRAME:
607         case FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME: {
608             CollectStackTraceInfos(stackTraceInfos);
609             break;
610         }
611         default: {
612             break;
613         }
614     }
615 }
616 
CollectStackTraceInfos(std::vector<std::pair<JSTaggedType,uint32_t>> & info) const617 void FrameIterator::CollectStackTraceInfos(std::vector<std::pair<JSTaggedType, uint32_t>> &info) const
618 {
619     uintptr_t callsiteSp = GetCallSiteSp();
620     uintptr_t callsiteFp = reinterpret_cast<uintptr_t>(GetSp());
621     arkStackMapParser_->CollectStackTraceInfos(optimizedReturnAddr_, info, callsiteSp, callsiteFp, stackMapAddr_);
622 }
623 
GetInlineDepth() const624 size_t FrameIterator::GetInlineDepth() const
625 {
626     return arkStackMapParser_->GetInlineDepth(optimizedReturnAddr_, stackMapAddr_);
627 }
628 
GetPrevFrame() const629 uintptr_t FrameIterator::GetPrevFrame() const
630 {
631     FrameType type = GetFrameType();
632     uintptr_t end = 0U;
633     switch (type) {
634         case FrameType::INTERPRETER_FRAME:
635         case FrameType::INTERPRETER_FAST_NEW_FRAME: {
636             auto prevFrame = GetFrame<InterpretedFrame>();
637             end = ToUintPtr(prevFrame);
638             break;
639         }
640         case FrameType::INTERPRETER_ENTRY_FRAME: {
641             auto prevFrame = GetFrame<InterpretedEntryFrame>();
642             end = ToUintPtr(prevFrame);
643             break;
644         }
645         case FrameType::INTERPRETER_BUILTIN_FRAME: {
646             auto prevFrame = GetFrame<InterpretedBuiltinFrame>();
647             end = ToUintPtr(prevFrame);
648             break;
649         }
650         default: {
651             LOG_FULL(FATAL) << "Unknown frame type: " << static_cast<uintptr_t>(type);
652         }
653     }
654     return end;
655 }
656 
IteratorStackMapAndDeopt(RootVisitor & visitor) const657 bool FrameIterator::IteratorStackMapAndDeopt(RootVisitor &visitor) const
658 {
659     ASSERT(arkStackMapParser_ != nullptr);
660     if (!stackMapAddr_) {  // enter by assembler, no stack map
661         return true;
662     }
663 
664     return arkStackMapParser_->IteratorStackMapAndDeopt(visitor, optimizedReturnAddr_,
665         reinterpret_cast<uintptr_t>(current_), optimizedCallSiteSp_, stackMapAddr_);
666 }
667 
GCIterate(const FrameIterator & it,RootVisitor & visitor) const668 ARK_INLINE void OptimizedFrame::GCIterate(const FrameIterator &it, RootVisitor &visitor) const
669 {
670     bool ret = it.IteratorStackMapAndDeopt(visitor);
671     if (!ret) {
672 #ifndef NDEBUG
673         LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
674 #endif
675     }
676 }
677 
GCIterate(const FrameIterator & it,RootVisitor & visitor) const678 ARK_INLINE void BaselineBuiltinFrame::GCIterate(const FrameIterator &it, RootVisitor &visitor) const
679 {
680     bool ret = it.IteratorStackMapAndDeopt(visitor);
681     if (!ret) {
682 #ifndef NDEBUG
683         LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
684 #endif
685     }
686 }
687 
CollectArkDeopt(std::vector<kungfu::ARKDeopt> & deopts) const688 void FrameIterator::CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const
689 {
690     arkStackMapParser_->GetArkDeopt(optimizedReturnAddr_, stackMapAddr_, deopts);
691 }
692 
GetArgv(const FrameIterator & it) const693 ARK_INLINE JSTaggedType* OptimizedJSFunctionFrame::GetArgv(const FrameIterator &it) const
694 {
695     uintptr_t *preFrameSp = ComputePrevFrameSp(it);
696     return GetArgv(preFrameSp);
697 }
698 
ComputePrevFrameSp(const FrameIterator & it) const699 ARK_INLINE uintptr_t* OptimizedJSFunctionFrame::ComputePrevFrameSp(const FrameIterator &it) const
700 {
701     const JSTaggedType *sp = it.GetSp();
702     Method *method = it.CheckAndGetMethod();
703     ASSERT(method != nullptr);
704     int delta = it.ComputeDelta(method);
705     ASSERT((delta > 0) && (delta % sizeof(uintptr_t) == 0));
706     uintptr_t *preFrameSp = reinterpret_cast<uintptr_t *>(const_cast<JSTaggedType *>(sp)) + delta / sizeof(uintptr_t);
707     return preFrameSp;
708 }
709 
GCIterate(const FrameIterator & it,RootVisitor & visitor,FrameType frameType) const710 ARK_INLINE void OptimizedJSFunctionFrame::GCIterate(const FrameIterator &it,
711     RootVisitor &visitor, FrameType frameType) const
712 {
713     OptimizedJSFunctionFrame *frame = OptimizedJSFunctionFrame::GetFrameFromSp(it.GetSp());
714     uintptr_t *jsFuncPtr = reinterpret_cast<uintptr_t *>(frame);
715     uintptr_t jsFuncSlot = ToUintPtr(jsFuncPtr);
716     visitor.VisitRoot(Root::ROOT_FRAME, ObjectSlot(jsFuncSlot));
717     if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) {
718         uintptr_t *preFrameSp = frame->ComputePrevFrameSp(it);
719         auto argc = frame->GetArgc(preFrameSp);
720         JSTaggedType *argv = frame->GetArgv(reinterpret_cast<uintptr_t *>(preFrameSp));
721         if (argc > 0) {
722             uintptr_t start = ToUintPtr(argv); // argv
723             uintptr_t end = ToUintPtr(argv + argc);
724             visitor.VisitRangeRoot(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
725         }
726     }
727 
728     auto machineCodeSlot = ObjectSlot(ToUintPtr(it.GetMachineCodeSlot()));
729     if (machineCodeSlot.GetTaggedType() != JSTaggedValue::VALUE_UNDEFINED) {
730         visitor.VisitRoot(Root::ROOT_FRAME, machineCodeSlot);
731     }
732 
733     bool ret = it.IteratorStackMapAndDeopt(visitor);
734     if (!ret) {
735 #ifndef NDEBUG
736         LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
737 #endif
738     }
739 }
740 
GetDeoptBundleInfo(const FrameIterator & it,std::vector<kungfu::ARKDeopt> & deopts) const741 void OptimizedJSFunctionFrame::GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const
742 {
743     it.CollectArkDeopt(deopts);
744 }
745 
GetFuncCalleeRegAndOffset(const FrameIterator & it,kungfu::CalleeRegAndOffsetVec & ret) const746 void OptimizedJSFunctionFrame::GetFuncCalleeRegAndOffset(
747     const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const
748 {
749     it.GetCalleeRegAndOffsetVec(ret);
750 }
751 
GetArgv(const FrameIterator & it) const752 ARK_INLINE JSTaggedType* FASTJITFunctionFrame::GetArgv(const FrameIterator &it) const
753 {
754     uintptr_t *preFrameSp = ComputePrevFrameSp(it);
755     return GetArgv(preFrameSp);
756 }
757 
ComputePrevFrameSp(const FrameIterator & it) const758 ARK_INLINE uintptr_t* FASTJITFunctionFrame::ComputePrevFrameSp(const FrameIterator &it) const
759 {
760     const JSTaggedType *sp = it.GetSp();
761     int delta = it.ComputeDelta();
762     ASSERT((delta > 0) && (delta % sizeof(uintptr_t) == 0));
763     uintptr_t *preFrameSp = reinterpret_cast<uintptr_t *>(const_cast<JSTaggedType *>(sp)) + delta / sizeof(uintptr_t);
764     return preFrameSp;
765 }
766 
GCIterate(const FrameIterator & it,RootVisitor & visitor,FrameType frameType) const767 ARK_INLINE void FASTJITFunctionFrame::GCIterate(const FrameIterator &it,
768     RootVisitor &visitor, FrameType frameType) const
769 {
770     FASTJITFunctionFrame *frame = FASTJITFunctionFrame::GetFrameFromSp(it.GetSp());
771     uintptr_t jsFuncSlot = GetFuncAddrFromSp(it.GetSp());
772     visitor.VisitRoot(Root::ROOT_FRAME, ObjectSlot(jsFuncSlot));
773     if (frameType == FrameType::FASTJIT_FUNCTION_FRAME) {
774         uintptr_t *preFrameSp = frame->ComputePrevFrameSp(it);
775         auto argc = frame->GetArgc(preFrameSp);
776         JSTaggedType *argv = frame->GetArgv(reinterpret_cast<uintptr_t *>(preFrameSp));
777         if (argc > 0) {
778             uintptr_t start = ToUintPtr(argv); // argv
779             uintptr_t end = ToUintPtr(argv + argc);
780             visitor.VisitRangeRoot(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
781         }
782     }
783 
784     auto machineCodeSlot = ObjectSlot(ToUintPtr(it.GetMachineCodeSlot()));
785     if (machineCodeSlot.GetTaggedType() != JSTaggedValue::VALUE_UNDEFINED) {
786         visitor.VisitRoot(Root::ROOT_FRAME, machineCodeSlot);
787     }
788 
789     bool ret = it.IteratorStackMapAndDeopt(visitor);
790     if (!ret) {
791 #ifndef NDEBUG
792         LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
793 #endif
794     }
795 }
796 
GetDeoptBundleInfo(const FrameIterator & it,std::vector<kungfu::ARKDeopt> & deopts) const797 void FASTJITFunctionFrame::GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const
798 {
799     it.CollectArkDeopt(deopts);
800 }
801 
GetFuncCalleeRegAndOffset(const FrameIterator & it,kungfu::CalleeRegAndOffsetVec & ret) const802 void FASTJITFunctionFrame::GetFuncCalleeRegAndOffset(
803     const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const
804 {
805     it.GetCalleeRegAndOffsetVec(ret);
806 }
807 
GCIterate(const FrameIterator & it,RootVisitor & visitor,bool isBaselineFrame) const808 ARK_INLINE void AsmInterpretedFrame::GCIterate(const FrameIterator &it,
809     RootVisitor &visitor, bool isBaselineFrame) const
810 {
811     AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(it.GetSp());
812     uintptr_t start = ToUintPtr(it.GetSp());
813     uintptr_t end = ToUintPtr(frame->GetCurrentFramePointer());
814     visitor.VisitRangeRoot(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
815     visitor.VisitRoot(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
816     visitor.VisitRoot(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->thisObj)));
817     if (frame->pc != nullptr || isBaselineFrame) {
818         visitor.VisitRoot(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->acc)));
819         visitor.VisitRoot(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->env)));
820     }
821 
822     if (isBaselineFrame) {
823         return;
824     }
825     bool ret = it.IteratorStackMapAndDeopt(visitor);
826     if (!ret) {
827 #ifndef NDEBUG
828         LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
829 #endif
830     }
831 }
832 
GCIterate(const FrameIterator & it,RootVisitor & visitor) const833 ARK_INLINE void InterpretedFrame::GCIterate(const FrameIterator &it, RootVisitor &visitor) const
834 {
835     auto sp = it.GetSp();
836     InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp);
837     if (frame->function.IsHole()) {
838         return;
839     }
840 
841     JSTaggedType *prevSp = frame->GetPrevFrameFp();
842     uintptr_t start = ToUintPtr(sp);
843     const JSThread *thread = it.GetThread();
844     FrameIterator prevIt(prevSp, thread);
845     uintptr_t end = prevIt.GetPrevFrame();
846 
847     visitor.VisitRangeRoot(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
848     visitor.VisitRoot(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
849     visitor.VisitRoot(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->thisObj)));
850 
851     // pc == nullptr, init InterpretedFrame & native InterpretedFrame.
852     if (frame->pc != nullptr) {
853         visitor.VisitRoot(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->acc)));
854         visitor.VisitRoot(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->constpool)));
855         visitor.VisitRoot(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->env)));
856         visitor.VisitRoot(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->profileTypeInfo)));
857     }
858 }
859 
GCIterate(const FrameIterator & it,RootVisitor & visitor) const860 ARK_INLINE void InterpretedBuiltinFrame::GCIterate(const FrameIterator &it, RootVisitor &visitor) const
861 {
862     auto sp = it.GetSp();
863     InterpretedBuiltinFrame *frame = InterpretedBuiltinFrame::GetFrameFromSp(sp);
864     JSTaggedType *prevSp = frame->GetPrevFrameFp();
865     const JSThread *thread = it.GetThread();
866     FrameIterator prevIt(prevSp, thread);
867 
868     uintptr_t start = ToUintPtr(sp + 2); // 2: numArgs & thread.
869     uintptr_t end = prevIt.GetPrevFrame();
870     visitor.VisitRangeRoot(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
871     visitor.VisitRoot(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
872 }
873 
GCIterate(const FrameIterator & it,RootVisitor & visitor) const874 ARK_INLINE void OptimizedLeaveFrame::GCIterate(const FrameIterator &it, RootVisitor &visitor) const
875 {
876     const JSTaggedType *sp = it.GetSp();
877     OptimizedLeaveFrame *frame = OptimizedLeaveFrame::GetFrameFromSp(sp);
878     if (frame->argc > 0) {
879         JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(&frame->argc + 1);
880         uintptr_t start = ToUintPtr(argv); // argv
881         uintptr_t end = ToUintPtr(argv + frame->argc);
882         visitor.VisitRangeRoot(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
883     }
884 }
885 
GCIterate(const FrameIterator & it,RootVisitor & visitor) const886 ARK_INLINE void OptimizedWithArgvLeaveFrame::GCIterate(const FrameIterator &it, RootVisitor &visitor) const
887 {
888     const JSTaggedType *sp = it.GetSp();
889     OptimizedWithArgvLeaveFrame *frame = OptimizedWithArgvLeaveFrame::GetFrameFromSp(sp);
890     if (frame->argc > 0) {
891         uintptr_t* argvPtr = reinterpret_cast<uintptr_t *>(&frame->argc + 1);
892         JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(*argvPtr);
893         uintptr_t start = ToUintPtr(argv); // argv
894         uintptr_t end = ToUintPtr(argv + frame->argc);
895         visitor.VisitRangeRoot(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
896     }
897 }
898 
GCIterate(const FrameIterator & it,RootVisitor & visitor) const899 ARK_INLINE void OptimizedBuiltinLeaveFrame::GCIterate(const FrameIterator &it, RootVisitor &visitor) const
900 {
901     const JSTaggedType *sp = it.GetSp();
902     OptimizedBuiltinLeaveFrame *frame = OptimizedBuiltinLeaveFrame::GetFrameFromSp(sp);
903     if (frame->argc > 0) {
904         JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(&frame->argc + 1);
905         uintptr_t start = ToUintPtr(argv); // argv
906         uintptr_t end = ToUintPtr(argv + frame->argc);
907         visitor.VisitRangeRoot(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
908     }
909 }
910 
GCIterate(const FrameIterator & it,RootVisitor & visitor) const911 ARK_INLINE void BuiltinWithArgvFrame::GCIterate(const FrameIterator &it, RootVisitor &visitor) const
912 {
913     const JSTaggedType *sp = it.GetSp();
914     auto frame = BuiltinWithArgvFrame::GetFrameFromSp(sp);
915     auto argc = static_cast<uint32_t>(frame->GetNumArgs()) + NUM_MANDATORY_JSFUNC_ARGS;
916     JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(frame->GetStackArgsAddress());
917     uintptr_t start = ToUintPtr(argv);
918     uintptr_t end = ToUintPtr(argv + argc);
919     visitor.VisitRangeRoot(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
920 }
921 
GCIterate(const FrameIterator & it,RootVisitor & visitor) const922 ARK_INLINE void BuiltinFrame::GCIterate(const FrameIterator &it, RootVisitor &visitor) const
923 {
924     const JSTaggedType *sp = it.GetSp();
925     auto frameType = it.GetFrameType();
926     auto frame = BuiltinFrame::GetFrameFromSp(sp);
927     // no need to visit stack map for entry frame
928     if (frameType == FrameType::BUILTIN_ENTRY_FRAME) {
929         // only visit function
930         visitor.VisitRoot(Root::ROOT_FRAME, ObjectSlot(frame->GetStackArgsAddress()));
931         return;
932     }
933     JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(frame->GetStackArgsAddress());
934     auto argc = frame->GetNumArgs();
935     uintptr_t start = ToUintPtr(argv);
936     uintptr_t end = ToUintPtr(argv + argc);
937     visitor.VisitRangeRoot(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
938 }
939 
GCIterate(const FrameIterator & it,RootVisitor & visitor) const940 ARK_INLINE void InterpretedEntryFrame::GCIterate(const FrameIterator &it, RootVisitor &visitor) const
941 {
942     const JSTaggedType* sp = it.GetSp();
943     InterpretedEntryFrame *frame = InterpretedEntryFrame::GetFrameFromSp(sp);
944     JSTaggedType *prevSp = frame->GetPrevFrameFp();
945     if (prevSp == nullptr) {
946         return;
947     }
948 
949     const JSThread *thread = it.GetThread();
950     FrameIterator prevIt(prevSp, thread);
951     uintptr_t start = ToUintPtr(sp + 2); // 2: numArgs & thread.
952     uintptr_t end = prevIt.GetPrevFrame();
953     visitor.VisitRangeRoot(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
954 }
955 }  // namespace panda::ecmascript
956