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