• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/frames.h"
17 
18 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
19 #include "ecmascript/dfx/stackinfo/js_stackinfo.h"
20 #include "ecmascript/ecma_vm.h"
21 #include "ecmascript/interpreter/frame_handler.h"
22 #include "ecmascript/js_thread.h"
23 #include "ecmascript/stackmap/ark_stackmap_parser.h"
24 #include "ecmascript/stackmap/llvm_stackmap_parser.h"
25 
26 namespace panda::ecmascript {
FrameIterator(JSTaggedType * sp,const JSThread * thread)27 FrameIterator::FrameIterator(JSTaggedType *sp, const JSThread *thread) : current_(sp), thread_(thread)
28 {
29     if (thread != nullptr) {
30         arkStackMapParser_ =
31             const_cast<JSThread *>(thread)->GetCurrentEcmaContext()->GetAOTFileManager()->GetStackMapParser();
32     }
33 }
34 
ComputeDelta() const35 int FrameIterator::ComputeDelta() const
36 {
37     return fpDeltaPrevFrameSp_;
38 }
39 
GetCallSiteDelta(uintptr_t returnAddr) const40 int FrameIterator::GetCallSiteDelta(uintptr_t returnAddr) const
41 {
42     auto callsiteInfo = CalCallSiteInfo(returnAddr);
43     int delta = std::get<2>(callsiteInfo); // 2:delta index
44     return delta;
45 }
46 
CheckAndGetMethod() const47 Method *FrameIterator::CheckAndGetMethod() const
48 {
49     auto function = GetFunction();
50     if (function.CheckIsJSFunctionBase() || function.CheckIsJSProxy()) {
51         return ECMAObject::Cast(function.GetTaggedObject())->GetCallTarget();
52     }
53     return nullptr;
54 }
55 
GetFunction() const56 JSTaggedValue FrameIterator::GetFunction() const
57 {
58     FrameType type = GetFrameType();
59     switch (type) {
60         case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
61         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
62             auto frame = GetFrame<OptimizedJSFunctionFrame>();
63             return frame->GetFunction();
64         }
65         case FrameType::ASM_INTERPRETER_FRAME:
66         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
67             auto frame = GetFrame<AsmInterpretedFrame>();
68             return frame->function;
69         }
70         case FrameType::INTERPRETER_FRAME:
71         case FrameType::INTERPRETER_FAST_NEW_FRAME: {
72             auto frame = GetFrame<InterpretedFrame>();
73             return frame->function;
74         }
75         case FrameType::INTERPRETER_BUILTIN_FRAME: {
76             auto frame = GetFrame<InterpretedBuiltinFrame>();
77             return frame->function;
78         }
79         case FrameType::BUILTIN_FRAME_WITH_ARGV: {
80             auto *frame = BuiltinWithArgvFrame::GetFrameFromSp(GetSp());
81             return frame->GetFunction();
82         }
83         case FrameType::BUILTIN_ENTRY_FRAME:
84         case FrameType::BUILTIN_FRAME: {
85             auto *frame = BuiltinFrame::GetFrameFromSp(GetSp());
86             return frame->GetFunction();
87         }
88         case FrameType::BUILTIN_CALL_LEAVE_FRAME: {
89             auto *frame = OptimizedBuiltinLeaveFrame::GetFrameFromSp(GetSp());
90             return JSTaggedValue(*(frame->GetArgv()));
91         }
92         case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME :
93         case FrameType::OPTIMIZED_FRAME:
94         case FrameType::OPTIMIZED_ENTRY_FRAME:
95         case FrameType::ASM_BRIDGE_FRAME:
96         case FrameType::LEAVE_FRAME:
97         case FrameType::LEAVE_FRAME_WITH_ARGV:
98         case FrameType::INTERPRETER_ENTRY_FRAME:
99         case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
100         case FrameType::ASM_INTERPRETER_BRIDGE_FRAME:
101         case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME:
102         case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
103             return JSTaggedValue::Undefined();
104         }
105         default: {
106             LOG_FULL(FATAL) << "frame type error!";
107             UNREACHABLE();
108         }
109     }
110 }
111 
CalCallSiteInfo(uintptr_t retAddr) const112 AOTFileInfo::CallSiteInfo FrameIterator::CalCallSiteInfo(uintptr_t retAddr) const
113 {
114     auto loader = const_cast<JSThread *>(thread_)->GetCurrentEcmaContext()->GetAOTFileManager();
115     return loader->CalCallSiteInfo(retAddr);
116 }
117 
118 template <GCVisitedFlag GCVisit>
Advance()119 void FrameIterator::Advance()
120 {
121     ASSERT(!Done());
122     FrameType t = GetFrameType();
123     bool needCalCallSiteInfo = false;
124     switch (t) {
125         case FrameType::OPTIMIZED_FRAME : {
126             auto frame = GetFrame<OptimizedFrame>();
127             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
128                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
129                 optimizedReturnAddr_ = frame->GetReturnAddr();
130                 needCalCallSiteInfo = true;
131             }
132             current_ = frame->GetPrevFrameFp();
133             break;
134         }
135         case FrameType::OPTIMIZED_ENTRY_FRAME : {
136             auto frame = GetFrame<OptimizedEntryFrame>();
137             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
138                 optimizedReturnAddr_ = 0;
139                 optimizedCallSiteSp_ = 0;
140             }
141             current_ = frame->GetPrevFrameFp();
142             break;
143         }
144         case FrameType::ASM_BRIDGE_FRAME : {
145             auto frame = GetFrame<AsmBridgeFrame>();
146             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
147                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
148                 optimizedReturnAddr_ = frame->GetReturnAddr();
149                 needCalCallSiteInfo = true;
150             }
151             current_ = frame->GetPrevFrameFp();
152             break;
153         }
154         case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
155             auto frame = GetFrame<OptimizedJSFunctionUnfoldArgVFrame>();
156             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
157                 optimizedCallSiteSp_ = frame->GetPrevFrameSp();
158                 optimizedReturnAddr_ = frame->GetReturnAddr();
159                 needCalCallSiteInfo = true;
160             }
161             current_ = frame->GetPrevFrameFp();
162             break;
163         }
164         case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME: {
165             auto frame = GetFrame<OptimizedJSFunctionFrame>();
166             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
167                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
168                 optimizedReturnAddr_ = frame->GetReturnAddr();
169                 needCalCallSiteInfo = true;
170             }
171             current_ = frame->GetPrevFrameFp();
172             break;
173         }
174         case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
175         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
176             auto frame = GetFrame<OptimizedJSFunctionFrame>();
177             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
178                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
179                 optimizedReturnAddr_ = frame->GetReturnAddr();
180                 needCalCallSiteInfo = true;
181             }
182             current_ = frame->GetPrevFrameFp();
183             break;
184         }
185         case FrameType::LEAVE_FRAME : {
186             auto frame = GetFrame<OptimizedLeaveFrame>();
187             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
188                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
189                 optimizedReturnAddr_ = frame->GetReturnAddr();
190                 needCalCallSiteInfo = true;
191             }
192             current_ = frame->GetPrevFrameFp();
193             break;
194         }
195         case FrameType::LEAVE_FRAME_WITH_ARGV : {
196             auto frame = GetFrame<OptimizedWithArgvLeaveFrame>();
197             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
198                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
199                 optimizedReturnAddr_ = frame->GetReturnAddr();
200                 needCalCallSiteInfo = true;
201             }
202             current_ = frame->GetPrevFrameFp();
203             break;
204         }
205         case FrameType::BUILTIN_CALL_LEAVE_FRAME : {
206             auto frame = GetFrame<OptimizedBuiltinLeaveFrame>();
207             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
208                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
209                 optimizedReturnAddr_ = frame->GetReturnAddr();
210                 needCalCallSiteInfo = true;
211             }
212             current_ = frame->GetPrevFrameFp();
213             break;
214         }
215         case FrameType::INTERPRETER_FRAME:
216         case FrameType::INTERPRETER_FAST_NEW_FRAME : {
217             auto frame = GetFrame<InterpretedFrame>();
218             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
219                 optimizedReturnAddr_ = 0;
220                 optimizedCallSiteSp_ = 0;
221             }
222             current_ = frame->GetPrevFrameFp();
223             break;
224         }
225         case FrameType::INTERPRETER_BUILTIN_FRAME: {
226             auto frame = GetFrame<InterpretedBuiltinFrame>();
227             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
228                 optimizedReturnAddr_ = 0;
229                 optimizedCallSiteSp_ = 0;
230             }
231             current_ = frame->GetPrevFrameFp();
232             break;
233         }
234         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
235         case FrameType::ASM_INTERPRETER_FRAME : {
236             auto frame = GetFrame<AsmInterpretedFrame>();
237             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
238                 optimizedReturnAddr_ = 0;
239                 optimizedCallSiteSp_ = 0;
240             }
241             current_ = frame->GetPrevFrameFp();
242             break;
243         }
244         case FrameType::BUILTIN_FRAME:
245         case FrameType::BUILTIN_ENTRY_FRAME : {
246             auto frame = GetFrame<BuiltinFrame>();
247             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
248                 optimizedReturnAddr_ = frame->GetReturnAddr();
249                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
250                 needCalCallSiteInfo = true;
251             }
252             current_ = frame->GetPrevFrameFp();
253             break;
254         }
255         case FrameType::BUILTIN_FRAME_WITH_ARGV : {
256             auto frame = GetFrame<BuiltinWithArgvFrame>();
257             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
258                 optimizedReturnAddr_ = frame->GetReturnAddr();
259                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
260                 needCalCallSiteInfo = true;
261             }
262             current_ = frame->GetPrevFrameFp();
263             break;
264         }
265         case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME : {
266             auto frame = GetFrame<BuiltinWithArgvFrame>();
267             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
268                 optimizedReturnAddr_ = frame->GetReturnAddr();
269                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
270                 needCalCallSiteInfo = true;
271             }
272             current_ = frame->GetPrevFrameFp();
273             break;
274         }
275         case FrameType::INTERPRETER_ENTRY_FRAME : {
276             auto frame = GetFrame<InterpretedEntryFrame>();
277             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
278                 optimizedReturnAddr_ = 0;
279                 optimizedCallSiteSp_ = 0;
280             }
281             current_ = frame->GetPrevFrameFp();
282             break;
283         }
284         case FrameType::ASM_INTERPRETER_ENTRY_FRAME : {
285             auto frame = GetFrame<AsmInterpretedEntryFrame>();
286             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
287                 optimizedReturnAddr_ = 0;
288                 optimizedCallSiteSp_ = 0;
289             }
290             current_ = frame->GetPrevFrameFp();
291             break;
292         }
293         case FrameType::ASM_INTERPRETER_BRIDGE_FRAME : {
294             auto frame = GetFrame<AsmInterpretedBridgeFrame>();
295             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
296                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
297                 optimizedReturnAddr_ = frame->GetReturnAddr();
298                 needCalCallSiteInfo = true;
299             }
300             current_ = frame->GetPrevFrameFp();
301             break;
302         }
303         default: {
304             if (GCVisit == GCVisitedFlag::HYBRID_STACK) {
305                 current_ = nullptr;
306                 break;
307             }
308             LOG_ECMA(FATAL) << "this branch is unreachable";
309             UNREACHABLE();
310         }
311     }
312     if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
313         if (!needCalCallSiteInfo) {
314             return;
315         }
316         uint64_t textStart = 0;
317         std::tie(textStart, stackMapAddr_, fpDeltaPrevFrameSp_, calleeRegInfo_) = CalCallSiteInfo(optimizedReturnAddr_);
318         ASSERT(optimizedReturnAddr_ >= textStart);
319         optimizedReturnAddr_ = optimizedReturnAddr_ - textStart;
320     }
321 }
322 template void FrameIterator::Advance<GCVisitedFlag::VISITED>();
323 template void FrameIterator::Advance<GCVisitedFlag::IGNORED>();
324 
GetPrevFrameCallSiteSp() const325 uintptr_t FrameIterator::GetPrevFrameCallSiteSp() const
326 {
327     if (Done()) {
328         return 0;
329     }
330     auto type = GetFrameType();
331     switch (type) {
332         case FrameType::LEAVE_FRAME: {
333             auto frame = GetFrame<OptimizedLeaveFrame>();
334             return frame->GetCallSiteSp();
335         }
336         case FrameType::LEAVE_FRAME_WITH_ARGV: {
337             auto frame = GetFrame<OptimizedWithArgvLeaveFrame>();
338             return frame->GetCallSiteSp();
339         }
340         case FrameType::BUILTIN_CALL_LEAVE_FRAME: {
341             auto frame = GetFrame<OptimizedBuiltinLeaveFrame>();
342             return frame->GetCallSiteSp();
343         }
344         case FrameType::BUILTIN_FRAME_WITH_ARGV: {
345             auto frame = GetFrame<BuiltinWithArgvFrame>();
346             return frame->GetCallSiteSp();
347         }
348         case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME: {
349             auto frame = GetFrame<BuiltinWithArgvFrame>();
350             return frame->GetCallSiteSp();
351         }
352         case FrameType::BUILTIN_FRAME: {
353             auto frame = GetFrame<BuiltinFrame>();
354             return frame->GetCallSiteSp();
355         }
356         case FrameType::ASM_INTERPRETER_BRIDGE_FRAME: {
357             auto frame = GetFrame<AsmInterpretedBridgeFrame>();
358             return frame->GetCallSiteSp();
359         }
360         case FrameType::OPTIMIZED_FRAME:
361         case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
362         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
363             ASSERT(thread_ != nullptr);
364             auto callSiteSp = reinterpret_cast<uintptr_t>(current_) + fpDeltaPrevFrameSp_;
365             return callSiteSp;
366         }
367         case FrameType::ASM_BRIDGE_FRAME: {
368             auto frame = GetFrame<AsmBridgeFrame>();
369             return frame->GetCallSiteSp();
370         }
371         case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
372             auto frame = GetFrame<OptimizedJSFunctionUnfoldArgVFrame>();
373             return frame->GetPrevFrameSp();
374         }
375         case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME : {
376             auto callSiteSp = OptimizedJSFunctionFrame::ComputeArgsConfigFrameSp(current_);
377             return callSiteSp;
378         }
379         case FrameType::BUILTIN_ENTRY_FRAME:
380         case FrameType::ASM_INTERPRETER_FRAME:
381         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
382         case FrameType::INTERPRETER_FRAME:
383         case FrameType::INTERPRETER_FAST_NEW_FRAME:
384         case FrameType::OPTIMIZED_ENTRY_FRAME:
385         case FrameType::INTERPRETER_BUILTIN_FRAME:
386         case FrameType::INTERPRETER_ENTRY_FRAME:
387         case FrameType::ASM_INTERPRETER_ENTRY_FRAME: {
388             break;
389         }
390         default: {
391             LOG_FULL(FATAL) << "frame type error!";
392         }
393     }
394     return 0;
395 }
396 
GetBytecodeOffset() const397 uint32_t FrameIterator::GetBytecodeOffset() const
398 {
399     FrameType type = this->GetFrameType();
400     switch (type) {
401         case FrameType::ASM_INTERPRETER_FRAME:
402         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
403             auto *frame = this->GetFrame<AsmInterpretedFrame>();
404             Method *method = ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget();
405             auto offset = frame->GetPc() - method->GetBytecodeArray();
406             return static_cast<uint32_t>(offset);
407         }
408         case FrameType::INTERPRETER_FRAME:
409         case FrameType::INTERPRETER_FAST_NEW_FRAME: {
410             auto *frame = this->GetFrame<InterpretedFrame>();
411             Method *method = ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget();
412             auto offset = frame->GetPc() - method->GetBytecodeArray();
413             return static_cast<uint32_t>(offset);
414         }
415         case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
416         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
417             auto frame = this->GetFrame<OptimizedJSFunctionFrame>();
418             ConstInfo constInfo;
419             frame->CollectPcOffsetInfo(*this, constInfo);
420             if (!constInfo.empty()) {
421                 return constInfo[0];
422             }
423             [[fallthrough]];
424         }
425         default: {
426             break;
427         }
428     }
429     return 0;
430 }
431 
GetPrevFrame() const432 uintptr_t FrameIterator::GetPrevFrame() const
433 {
434     FrameType type = GetFrameType();
435     uintptr_t end = 0U;
436     switch (type) {
437         case FrameType::INTERPRETER_FRAME:
438         case FrameType::INTERPRETER_FAST_NEW_FRAME: {
439             auto prevFrame = GetFrame<InterpretedFrame>();
440             end = ToUintPtr(prevFrame);
441             break;
442         }
443         case FrameType::INTERPRETER_ENTRY_FRAME: {
444             auto prevFrame = GetFrame<InterpretedEntryFrame>();
445             end = ToUintPtr(prevFrame);
446             break;
447         }
448         case FrameType::INTERPRETER_BUILTIN_FRAME: {
449             auto prevFrame = GetFrame<InterpretedBuiltinFrame>();
450             end = ToUintPtr(prevFrame);
451             break;
452         }
453         default: {
454             LOG_FULL(FATAL) << "frame type error!";
455         }
456     }
457     return end;
458 }
459 
IteratorStackMap(const RootVisitor & visitor,const RootBaseAndDerivedVisitor & derivedVisitor) const460 bool FrameIterator::IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const
461 {
462     ASSERT(arkStackMapParser_ != nullptr);
463     if (!stackMapAddr_) {  // enter by assembler, no stack map
464         return true;
465     }
466 
467     return arkStackMapParser_->IteratorStackMap(visitor, derivedVisitor, optimizedReturnAddr_,
468         reinterpret_cast<uintptr_t>(current_), optimizedCallSiteSp_, stackMapAddr_);
469 }
470 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor) const471 ARK_INLINE void OptimizedFrame::GCIterate(const FrameIterator &it,
472     const RootVisitor &visitor,
473     [[maybe_unused]] const RootRangeVisitor &rangeVisitor,
474     const RootBaseAndDerivedVisitor &derivedVisitor) const
475 {
476     bool ret = it.IteratorStackMap(visitor, derivedVisitor);
477     if (!ret) {
478 #ifndef NDEBUG
479         LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
480 #endif
481     }
482 }
483 
CollectPcOffsetInfo(ConstInfo & info) const484 void FrameIterator::CollectPcOffsetInfo(ConstInfo &info) const
485 {
486     arkStackMapParser_->GetConstInfo(optimizedReturnAddr_, info, stackMapAddr_);
487 }
488 
CollectArkDeopt(std::vector<kungfu::ARKDeopt> & deopts) const489 void FrameIterator::CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const
490 {
491     arkStackMapParser_->GetArkDeopt(optimizedReturnAddr_, stackMapAddr_, deopts);
492 }
493 
GetArgv(const FrameIterator & it) const494 ARK_INLINE JSTaggedType* OptimizedJSFunctionFrame::GetArgv(const FrameIterator &it) const
495 {
496     uintptr_t *preFrameSp = ComputePrevFrameSp(it);
497     return GetArgv(preFrameSp);
498 }
499 
ComputePrevFrameSp(const FrameIterator & it) const500 ARK_INLINE uintptr_t* OptimizedJSFunctionFrame::ComputePrevFrameSp(const FrameIterator &it) const
501 {
502     const JSTaggedType *sp = it.GetSp();
503     int delta = it.ComputeDelta();
504     ASSERT((delta > 0) && (delta % sizeof(uintptr_t) == 0));
505     uintptr_t *preFrameSp = reinterpret_cast<uintptr_t *>(const_cast<JSTaggedType *>(sp)) + delta / sizeof(uintptr_t);
506     return preFrameSp;
507 }
508 
509 
CollectPcOffsetInfo(const FrameIterator & it,ConstInfo & info) const510 void OptimizedJSFunctionFrame::CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const
511 {
512     it.CollectPcOffsetInfo(info);
513 }
514 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor,FrameType frameType) const515 ARK_INLINE void OptimizedJSFunctionFrame::GCIterate(const FrameIterator &it,
516     const RootVisitor &visitor,
517     [[maybe_unused]] const RootRangeVisitor &rangeVisitor,
518     const RootBaseAndDerivedVisitor &derivedVisitor, FrameType frameType) const
519 {
520     OptimizedJSFunctionFrame *frame = OptimizedJSFunctionFrame::GetFrameFromSp(it.GetSp());
521     uintptr_t *jsFuncPtr = reinterpret_cast<uintptr_t *>(frame);
522     uintptr_t jsFuncSlot = ToUintPtr(jsFuncPtr);
523     visitor(Root::ROOT_FRAME, ObjectSlot(jsFuncSlot));
524     if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) {
525         uintptr_t *preFrameSp = frame->ComputePrevFrameSp(it);
526         auto argc = frame->GetArgc(preFrameSp);
527         JSTaggedType *argv = frame->GetArgv(reinterpret_cast<uintptr_t *>(preFrameSp));
528         if (argc > 0) {
529             uintptr_t start = ToUintPtr(argv); // argv
530             uintptr_t end = ToUintPtr(argv + argc);
531             rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
532         }
533     }
534 
535     bool ret = it.IteratorStackMap(visitor, derivedVisitor);
536     if (!ret) {
537 #ifndef NDEBUG
538         LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
539 #endif
540     }
541 }
542 
GetDeoptBundleInfo(const FrameIterator & it,std::vector<kungfu::ARKDeopt> & deopts) const543 void OptimizedJSFunctionFrame::GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const
544 {
545     it.CollectArkDeopt(deopts);
546 }
547 
GetFuncCalleeRegAndOffset(const FrameIterator & it,kungfu::CalleeRegAndOffsetVec & ret) const548 void OptimizedJSFunctionFrame::GetFuncCalleeRegAndOffset(
549     const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const
550 {
551     it.GetCalleeRegAndOffsetVec(ret);
552 }
553 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor) const554 ARK_INLINE void AsmInterpretedFrame::GCIterate(const FrameIterator &it,
555     const RootVisitor &visitor,
556     const RootRangeVisitor &rangeVisitor,
557     const RootBaseAndDerivedVisitor &derivedVisitor) const
558 {
559     AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(it.GetSp());
560     uintptr_t start = ToUintPtr(it.GetSp());
561     uintptr_t end = ToUintPtr(frame->GetCurrentFramePointer());
562     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
563     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
564     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->thisObj)));
565     if (frame->pc != nullptr) {
566         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->acc)));
567         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->env)));
568     }
569 
570     bool ret = it.IteratorStackMap(visitor, derivedVisitor);
571     if (!ret) {
572 #ifndef NDEBUG
573         LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
574 #endif
575     }
576 }
577 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const578 ARK_INLINE void InterpretedFrame::GCIterate(const FrameIterator &it,
579                                             const RootVisitor &visitor,
580                                             const RootRangeVisitor &rangeVisitor) const
581 {
582     auto sp = it.GetSp();
583     InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp);
584     if (frame->function.IsHole()) {
585         return;
586     }
587 
588     JSTaggedType *prevSp = frame->GetPrevFrameFp();
589     uintptr_t start = ToUintPtr(sp);
590     const JSThread *thread = it.GetThread();
591     FrameIterator prevIt(prevSp, thread);
592     uintptr_t end = prevIt.GetPrevFrame();
593 
594     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
595     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
596     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->thisObj)));
597 
598     // pc == nullptr, init InterpretedFrame & native InterpretedFrame.
599     if (frame->pc != nullptr) {
600         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->acc)));
601         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->constpool)));
602         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->env)));
603         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->profileTypeInfo)));
604     }
605 }
606 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const607 ARK_INLINE void InterpretedBuiltinFrame::GCIterate(const FrameIterator &it,
608                                                    const RootVisitor &visitor,
609                                                    const RootRangeVisitor &rangeVisitor) const
610 {
611     auto sp = it.GetSp();
612     InterpretedBuiltinFrame *frame = InterpretedBuiltinFrame::GetFrameFromSp(sp);
613     JSTaggedType *prevSp = frame->GetPrevFrameFp();
614     const JSThread *thread = it.GetThread();
615     FrameIterator prevIt(prevSp, thread);
616 
617     uintptr_t start = ToUintPtr(sp + 2); // 2: numArgs & thread.
618     uintptr_t end = prevIt.GetPrevFrame();
619     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
620     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
621 }
622 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const623 ARK_INLINE void OptimizedLeaveFrame::GCIterate(const FrameIterator &it,
624     [[maybe_unused]] const RootVisitor &visitor,
625     const RootRangeVisitor &rangeVisitor) const
626 {
627     const JSTaggedType *sp = it.GetSp();
628     OptimizedLeaveFrame *frame = OptimizedLeaveFrame::GetFrameFromSp(sp);
629     if (frame->argc > 0) {
630         JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(&frame->argc + 1);
631         uintptr_t start = ToUintPtr(argv); // argv
632         uintptr_t end = ToUintPtr(argv + frame->argc);
633         rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
634     }
635 }
636 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const637 ARK_INLINE void OptimizedWithArgvLeaveFrame::GCIterate(const FrameIterator &it,
638     [[maybe_unused]] const RootVisitor &visitor,
639     const RootRangeVisitor &rangeVisitor) const
640 {
641     const JSTaggedType *sp = it.GetSp();
642     OptimizedWithArgvLeaveFrame *frame = OptimizedWithArgvLeaveFrame::GetFrameFromSp(sp);
643     if (frame->argc > 0) {
644         uintptr_t* argvPtr = reinterpret_cast<uintptr_t *>(&frame->argc + 1);
645         JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(*argvPtr);
646         uintptr_t start = ToUintPtr(argv); // argv
647         uintptr_t end = ToUintPtr(argv + frame->argc);
648         rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
649     }
650 }
651 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const652 ARK_INLINE void OptimizedBuiltinLeaveFrame::GCIterate(const FrameIterator &it,
653     [[maybe_unused]] const RootVisitor &visitor,
654     const RootRangeVisitor &rangeVisitor) const
655 {
656     const JSTaggedType *sp = it.GetSp();
657     OptimizedBuiltinLeaveFrame *frame = OptimizedBuiltinLeaveFrame::GetFrameFromSp(sp);
658     if (frame->argc > 0) {
659         JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(&frame->argc + 1);
660         uintptr_t start = ToUintPtr(argv); // argv
661         uintptr_t end = ToUintPtr(argv + frame->argc);
662         rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
663     }
664 }
665 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const666 ARK_INLINE void BuiltinWithArgvFrame::GCIterate(const FrameIterator &it,
667     [[maybe_unused]] const RootVisitor &visitor,
668     const RootRangeVisitor &rangeVisitor) const
669 {
670     const JSTaggedType *sp = it.GetSp();
671     auto frame = BuiltinWithArgvFrame::GetFrameFromSp(sp);
672     auto argc = static_cast<uint32_t>(frame->GetNumArgs()) + NUM_MANDATORY_JSFUNC_ARGS;
673     JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(frame->GetStackArgsAddress());
674     uintptr_t start = ToUintPtr(argv);
675     uintptr_t end = ToUintPtr(argv + argc);
676     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
677 }
678 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const679 ARK_INLINE void BuiltinFrame::GCIterate(const FrameIterator &it,
680     const RootVisitor &visitor,
681     const RootRangeVisitor &rangeVisitor) const
682 {
683     const JSTaggedType *sp = it.GetSp();
684     auto frame = BuiltinFrame::GetFrameFromSp(sp);
685     // no need to visit stack map for entry frame
686     if (frame->type == FrameType::BUILTIN_ENTRY_FRAME) {
687         // only visit function
688         visitor(Root::ROOT_FRAME, ObjectSlot(frame->GetStackArgsAddress()));
689         return;
690     }
691     JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(frame->GetStackArgsAddress());
692     auto argc = frame->GetNumArgs();
693     uintptr_t start = ToUintPtr(argv);
694     uintptr_t end = ToUintPtr(argv + argc);
695     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
696 }
697 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const698 ARK_INLINE void InterpretedEntryFrame::GCIterate(const FrameIterator &it,
699     [[maybe_unused]] const RootVisitor &visitor,
700     const RootRangeVisitor &rangeVisitor) const
701 {
702     const JSTaggedType* sp = it.GetSp();
703     InterpretedEntryFrame *frame = InterpretedEntryFrame::GetFrameFromSp(sp);
704     JSTaggedType *prevSp = frame->GetPrevFrameFp();
705     if (prevSp == nullptr) {
706         return;
707     }
708 
709     const JSThread *thread = it.GetThread();
710     FrameIterator prevIt(prevSp, thread);
711     uintptr_t start = ToUintPtr(sp + 2); // 2: numArgs & thread.
712     uintptr_t end = prevIt.GetPrevFrame();
713     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
714 }
715 }  // namespace panda::ecmascript
716