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