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