• 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) << "Unknown frame type: " << static_cast<uintptr_t>(type);
107             UNREACHABLE();
108         }
109     }
110 }
111 
CalCallSiteInfo(uintptr_t retAddr) const112 AOTFileInfo::CallSiteInfo FrameIterator::CalCallSiteInfo(uintptr_t retAddr) const
113 {
114     return const_cast<JSThread *>(thread_)->GetCurrentEcmaContext()->CalCallSiteInfo(retAddr);
115 }
116 
117 template <GCVisitedFlag GCVisit>
Advance()118 void FrameIterator::Advance()
119 {
120     ASSERT(!Done());
121     FrameType t = GetFrameType();
122     bool needCalCallSiteInfo = false;
123     switch (t) {
124         case FrameType::OPTIMIZED_FRAME : {
125             auto frame = GetFrame<OptimizedFrame>();
126             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
127                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
128                 optimizedReturnAddr_ = frame->GetReturnAddr();
129                 needCalCallSiteInfo = true;
130             }
131             current_ = frame->GetPrevFrameFp();
132             break;
133         }
134         case FrameType::OPTIMIZED_ENTRY_FRAME : {
135             auto frame = GetFrame<OptimizedEntryFrame>();
136             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
137                 optimizedReturnAddr_ = 0;
138                 optimizedCallSiteSp_ = 0;
139             }
140             current_ = frame->GetPrevFrameFp();
141             break;
142         }
143         case FrameType::ASM_BRIDGE_FRAME : {
144             auto frame = GetFrame<AsmBridgeFrame>();
145             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
146                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
147                 optimizedReturnAddr_ = frame->GetReturnAddr();
148                 needCalCallSiteInfo = true;
149             }
150             current_ = frame->GetPrevFrameFp();
151             break;
152         }
153         case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
154             auto frame = GetFrame<OptimizedJSFunctionUnfoldArgVFrame>();
155             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
156                 optimizedCallSiteSp_ = frame->GetPrevFrameSp();
157                 optimizedReturnAddr_ = frame->GetReturnAddr();
158                 needCalCallSiteInfo = true;
159             }
160             current_ = frame->GetPrevFrameFp();
161             break;
162         }
163         case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME: {
164             auto frame = GetFrame<OptimizedJSFunctionFrame>();
165             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
166                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
167                 optimizedReturnAddr_ = frame->GetReturnAddr();
168                 needCalCallSiteInfo = true;
169             }
170             current_ = frame->GetPrevFrameFp();
171             break;
172         }
173         case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
174         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
175             auto frame = GetFrame<OptimizedJSFunctionFrame>();
176             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
177                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
178                 optimizedReturnAddr_ = frame->GetReturnAddr();
179                 needCalCallSiteInfo = true;
180             }
181             current_ = frame->GetPrevFrameFp();
182             break;
183         }
184         case FrameType::LEAVE_FRAME : {
185             auto frame = GetFrame<OptimizedLeaveFrame>();
186             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
187                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
188                 optimizedReturnAddr_ = frame->GetReturnAddr();
189                 needCalCallSiteInfo = true;
190             }
191             current_ = frame->GetPrevFrameFp();
192             break;
193         }
194         case FrameType::LEAVE_FRAME_WITH_ARGV : {
195             auto frame = GetFrame<OptimizedWithArgvLeaveFrame>();
196             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
197                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
198                 optimizedReturnAddr_ = frame->GetReturnAddr();
199                 needCalCallSiteInfo = true;
200             }
201             current_ = frame->GetPrevFrameFp();
202             break;
203         }
204         case FrameType::BUILTIN_CALL_LEAVE_FRAME : {
205             auto frame = GetFrame<OptimizedBuiltinLeaveFrame>();
206             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
207                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
208                 optimizedReturnAddr_ = frame->GetReturnAddr();
209                 needCalCallSiteInfo = true;
210             }
211             current_ = frame->GetPrevFrameFp();
212             break;
213         }
214         case FrameType::INTERPRETER_FRAME:
215         case FrameType::INTERPRETER_FAST_NEW_FRAME : {
216             auto frame = GetFrame<InterpretedFrame>();
217             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
218                 optimizedReturnAddr_ = 0;
219                 optimizedCallSiteSp_ = 0;
220             }
221             current_ = frame->GetPrevFrameFp();
222             break;
223         }
224         case FrameType::INTERPRETER_BUILTIN_FRAME: {
225             auto frame = GetFrame<InterpretedBuiltinFrame>();
226             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
227                 optimizedReturnAddr_ = 0;
228                 optimizedCallSiteSp_ = 0;
229             }
230             current_ = frame->GetPrevFrameFp();
231             break;
232         }
233         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
234         case FrameType::ASM_INTERPRETER_FRAME : {
235             auto frame = GetFrame<AsmInterpretedFrame>();
236             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
237                 optimizedReturnAddr_ = 0;
238                 optimizedCallSiteSp_ = 0;
239             }
240             current_ = frame->GetPrevFrameFp();
241             break;
242         }
243         case FrameType::BUILTIN_FRAME:
244         case FrameType::BUILTIN_ENTRY_FRAME : {
245             auto frame = GetFrame<BuiltinFrame>();
246             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
247                 optimizedReturnAddr_ = frame->GetReturnAddr();
248                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
249                 needCalCallSiteInfo = true;
250             }
251             current_ = frame->GetPrevFrameFp();
252             break;
253         }
254         case FrameType::BUILTIN_FRAME_WITH_ARGV : {
255             auto frame = GetFrame<BuiltinWithArgvFrame>();
256             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
257                 optimizedReturnAddr_ = frame->GetReturnAddr();
258                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
259                 needCalCallSiteInfo = true;
260             }
261             current_ = frame->GetPrevFrameFp();
262             break;
263         }
264         case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME : {
265             auto frame = GetFrame<BuiltinWithArgvFrame>();
266             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
267                 optimizedReturnAddr_ = frame->GetReturnAddr();
268                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
269                 needCalCallSiteInfo = true;
270             }
271             current_ = frame->GetPrevFrameFp();
272             break;
273         }
274         case FrameType::INTERPRETER_ENTRY_FRAME : {
275             auto frame = GetFrame<InterpretedEntryFrame>();
276             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
277                 optimizedReturnAddr_ = 0;
278                 optimizedCallSiteSp_ = 0;
279             }
280             current_ = frame->GetPrevFrameFp();
281             break;
282         }
283         case FrameType::ASM_INTERPRETER_ENTRY_FRAME : {
284             auto frame = GetFrame<AsmInterpretedEntryFrame>();
285             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
286                 optimizedReturnAddr_ = 0;
287                 optimizedCallSiteSp_ = 0;
288             }
289             current_ = frame->GetPrevFrameFp();
290             break;
291         }
292         case FrameType::ASM_INTERPRETER_BRIDGE_FRAME : {
293             auto frame = GetFrame<AsmInterpretedBridgeFrame>();
294             if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
295                 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
296                 optimizedReturnAddr_ = frame->GetReturnAddr();
297                 needCalCallSiteInfo = true;
298             }
299             current_ = frame->GetPrevFrameFp();
300             break;
301         }
302         default: {
303             if (GCVisit == GCVisitedFlag::HYBRID_STACK) {
304                 current_ = nullptr;
305                 break;
306             }
307             LOG_ECMA(FATAL) << "this branch is unreachable";
308             UNREACHABLE();
309         }
310     }
311     if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
312         if (!needCalCallSiteInfo) {
313             return;
314         }
315         uint64_t textStart = 0;
316         std::tie(textStart, stackMapAddr_, fpDeltaPrevFrameSp_, calleeRegInfo_) = CalCallSiteInfo(optimizedReturnAddr_);
317         ASSERT(optimizedReturnAddr_ >= textStart);
318         optimizedReturnAddr_ = optimizedReturnAddr_ - textStart;
319     }
320 }
321 template void FrameIterator::Advance<GCVisitedFlag::VISITED>();
322 template void FrameIterator::Advance<GCVisitedFlag::IGNORED>();
323 
GetPrevFrameCallSiteSp() const324 uintptr_t FrameIterator::GetPrevFrameCallSiteSp() const
325 {
326     if (Done()) {
327         return 0;
328     }
329     auto type = GetFrameType();
330     switch (type) {
331         case FrameType::LEAVE_FRAME: {
332             auto frame = GetFrame<OptimizedLeaveFrame>();
333             return frame->GetCallSiteSp();
334         }
335         case FrameType::LEAVE_FRAME_WITH_ARGV: {
336             auto frame = GetFrame<OptimizedWithArgvLeaveFrame>();
337             return frame->GetCallSiteSp();
338         }
339         case FrameType::BUILTIN_CALL_LEAVE_FRAME: {
340             auto frame = GetFrame<OptimizedBuiltinLeaveFrame>();
341             return frame->GetCallSiteSp();
342         }
343         case FrameType::BUILTIN_FRAME_WITH_ARGV: {
344             auto frame = GetFrame<BuiltinWithArgvFrame>();
345             return frame->GetCallSiteSp();
346         }
347         case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME: {
348             auto frame = GetFrame<BuiltinWithArgvFrame>();
349             return frame->GetCallSiteSp();
350         }
351         case FrameType::BUILTIN_FRAME: {
352             auto frame = GetFrame<BuiltinFrame>();
353             return frame->GetCallSiteSp();
354         }
355         case FrameType::ASM_INTERPRETER_BRIDGE_FRAME: {
356             auto frame = GetFrame<AsmInterpretedBridgeFrame>();
357             return frame->GetCallSiteSp();
358         }
359         case FrameType::OPTIMIZED_FRAME:
360         case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
361         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
362             ASSERT(thread_ != nullptr);
363             auto callSiteSp = reinterpret_cast<uintptr_t>(current_) + fpDeltaPrevFrameSp_;
364             return callSiteSp;
365         }
366         case FrameType::ASM_BRIDGE_FRAME: {
367             auto frame = GetFrame<AsmBridgeFrame>();
368             return frame->GetCallSiteSp();
369         }
370         case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
371             auto frame = GetFrame<OptimizedJSFunctionUnfoldArgVFrame>();
372             return frame->GetPrevFrameSp();
373         }
374         case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME : {
375             auto callSiteSp = OptimizedJSFunctionFrame::ComputeArgsConfigFrameSp(current_);
376             return callSiteSp;
377         }
378         case FrameType::BUILTIN_ENTRY_FRAME:
379         case FrameType::ASM_INTERPRETER_FRAME:
380         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
381         case FrameType::INTERPRETER_FRAME:
382         case FrameType::INTERPRETER_FAST_NEW_FRAME:
383         case FrameType::OPTIMIZED_ENTRY_FRAME:
384         case FrameType::INTERPRETER_BUILTIN_FRAME:
385         case FrameType::INTERPRETER_ENTRY_FRAME:
386         case FrameType::ASM_INTERPRETER_ENTRY_FRAME: {
387             break;
388         }
389         default: {
390             LOG_FULL(FATAL) << "Unknown frame type: " << static_cast<uintptr_t>(type);
391         }
392     }
393     return 0;
394 }
395 
GetInlinedMethodInfo()396 std::map<uint32_t, uint32_t> FrameIterator::GetInlinedMethodInfo()
397 {
398     std::map<uint32_t, uint32_t> inlineMethodInfos;
399     FrameType type = this->GetFrameType();
400     switch (type) {
401         case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
402         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
403             CollectMethodOffsetInfo(inlineMethodInfos);
404             break;
405         }
406         default: {
407             break;
408         }
409     }
410     return inlineMethodInfos;
411 }
412 
GetBytecodeOffset() const413 uint32_t FrameIterator::GetBytecodeOffset() const
414 {
415     FrameType type = this->GetFrameType();
416     switch (type) {
417         case FrameType::ASM_INTERPRETER_FRAME:
418         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
419             auto *frame = this->GetFrame<AsmInterpretedFrame>();
420             Method *method = ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget();
421             auto offset = frame->GetPc() - method->GetBytecodeArray();
422             return static_cast<uint32_t>(offset);
423         }
424         case FrameType::INTERPRETER_FRAME:
425         case FrameType::INTERPRETER_FAST_NEW_FRAME: {
426             auto *frame = this->GetFrame<InterpretedFrame>();
427             Method *method = ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget();
428             auto offset = frame->GetPc() - method->GetBytecodeArray();
429             return static_cast<uint32_t>(offset);
430         }
431         case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
432         case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
433             auto frame = this->GetFrame<OptimizedJSFunctionFrame>();
434             ConstInfo constInfo;
435             frame->CollectPcOffsetInfo(*this, constInfo);
436             if (!constInfo.empty()) {
437                 return constInfo[0];
438             }
439             [[fallthrough]];
440         }
441         default: {
442             break;
443         }
444     }
445     return 0;
446 }
447 
GetPrevFrame() const448 uintptr_t FrameIterator::GetPrevFrame() const
449 {
450     FrameType type = GetFrameType();
451     uintptr_t end = 0U;
452     switch (type) {
453         case FrameType::INTERPRETER_FRAME:
454         case FrameType::INTERPRETER_FAST_NEW_FRAME: {
455             auto prevFrame = GetFrame<InterpretedFrame>();
456             end = ToUintPtr(prevFrame);
457             break;
458         }
459         case FrameType::INTERPRETER_ENTRY_FRAME: {
460             auto prevFrame = GetFrame<InterpretedEntryFrame>();
461             end = ToUintPtr(prevFrame);
462             break;
463         }
464         case FrameType::INTERPRETER_BUILTIN_FRAME: {
465             auto prevFrame = GetFrame<InterpretedBuiltinFrame>();
466             end = ToUintPtr(prevFrame);
467             break;
468         }
469         default: {
470             LOG_FULL(FATAL) << "Unknown frame type: " << static_cast<uintptr_t>(type);
471         }
472     }
473     return end;
474 }
475 
IteratorStackMap(const RootVisitor & visitor,const RootBaseAndDerivedVisitor & derivedVisitor) const476 bool FrameIterator::IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const
477 {
478     ASSERT(arkStackMapParser_ != nullptr);
479     if (!stackMapAddr_) {  // enter by assembler, no stack map
480         return true;
481     }
482 
483     return arkStackMapParser_->IteratorStackMap(visitor, derivedVisitor, optimizedReturnAddr_,
484         reinterpret_cast<uintptr_t>(current_), optimizedCallSiteSp_, stackMapAddr_);
485 }
486 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor) const487 ARK_INLINE void OptimizedFrame::GCIterate(const FrameIterator &it,
488     const RootVisitor &visitor,
489     [[maybe_unused]] const RootRangeVisitor &rangeVisitor,
490     const RootBaseAndDerivedVisitor &derivedVisitor) const
491 {
492     bool ret = it.IteratorStackMap(visitor, derivedVisitor);
493     if (!ret) {
494 #ifndef NDEBUG
495         LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
496 #endif
497     }
498 }
499 
CollectPcOffsetInfo(ConstInfo & info) const500 void FrameIterator::CollectPcOffsetInfo(ConstInfo &info) const
501 {
502     arkStackMapParser_->GetConstInfo(optimizedReturnAddr_, info, stackMapAddr_);
503 }
504 
CollectMethodOffsetInfo(std::map<uint32_t,uint32_t> & info) const505 void FrameIterator::CollectMethodOffsetInfo(std::map<uint32_t, uint32_t> &info) const
506 {
507     arkStackMapParser_->GetMethodOffsetInfo(optimizedReturnAddr_, info, stackMapAddr_);
508 }
509 
CollectArkDeopt(std::vector<kungfu::ARKDeopt> & deopts) const510 void FrameIterator::CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const
511 {
512     arkStackMapParser_->GetArkDeopt(optimizedReturnAddr_, stackMapAddr_, deopts);
513 }
514 
GetArgv(const FrameIterator & it) const515 ARK_INLINE JSTaggedType* OptimizedJSFunctionFrame::GetArgv(const FrameIterator &it) const
516 {
517     uintptr_t *preFrameSp = ComputePrevFrameSp(it);
518     return GetArgv(preFrameSp);
519 }
520 
ComputePrevFrameSp(const FrameIterator & it) const521 ARK_INLINE uintptr_t* OptimizedJSFunctionFrame::ComputePrevFrameSp(const FrameIterator &it) const
522 {
523     const JSTaggedType *sp = it.GetSp();
524     int delta = it.ComputeDelta();
525     ASSERT((delta > 0) && (delta % sizeof(uintptr_t) == 0));
526     uintptr_t *preFrameSp = reinterpret_cast<uintptr_t *>(const_cast<JSTaggedType *>(sp)) + delta / sizeof(uintptr_t);
527     return preFrameSp;
528 }
529 
530 
CollectPcOffsetInfo(const FrameIterator & it,ConstInfo & info) const531 void OptimizedJSFunctionFrame::CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const
532 {
533     it.CollectPcOffsetInfo(info);
534 }
535 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor,FrameType frameType) const536 ARK_INLINE void OptimizedJSFunctionFrame::GCIterate(const FrameIterator &it,
537     const RootVisitor &visitor,
538     [[maybe_unused]] const RootRangeVisitor &rangeVisitor,
539     const RootBaseAndDerivedVisitor &derivedVisitor, FrameType frameType) const
540 {
541     OptimizedJSFunctionFrame *frame = OptimizedJSFunctionFrame::GetFrameFromSp(it.GetSp());
542     uintptr_t *jsFuncPtr = reinterpret_cast<uintptr_t *>(frame);
543     uintptr_t jsFuncSlot = ToUintPtr(jsFuncPtr);
544     visitor(Root::ROOT_FRAME, ObjectSlot(jsFuncSlot));
545     if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) {
546         uintptr_t *preFrameSp = frame->ComputePrevFrameSp(it);
547         auto argc = frame->GetArgc(preFrameSp);
548         JSTaggedType *argv = frame->GetArgv(reinterpret_cast<uintptr_t *>(preFrameSp));
549         if (argc > 0) {
550             uintptr_t start = ToUintPtr(argv); // argv
551             uintptr_t end = ToUintPtr(argv + argc);
552             rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
553         }
554     }
555 
556     bool ret = it.IteratorStackMap(visitor, derivedVisitor);
557     if (!ret) {
558 #ifndef NDEBUG
559         LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
560 #endif
561     }
562 }
563 
GetDeoptBundleInfo(const FrameIterator & it,std::vector<kungfu::ARKDeopt> & deopts) const564 void OptimizedJSFunctionFrame::GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const
565 {
566     it.CollectArkDeopt(deopts);
567 }
568 
GetFuncCalleeRegAndOffset(const FrameIterator & it,kungfu::CalleeRegAndOffsetVec & ret) const569 void OptimizedJSFunctionFrame::GetFuncCalleeRegAndOffset(
570     const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const
571 {
572     it.GetCalleeRegAndOffsetVec(ret);
573 }
574 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor) const575 ARK_INLINE void AsmInterpretedFrame::GCIterate(const FrameIterator &it,
576     const RootVisitor &visitor,
577     const RootRangeVisitor &rangeVisitor,
578     const RootBaseAndDerivedVisitor &derivedVisitor) const
579 {
580     AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(it.GetSp());
581     uintptr_t start = ToUintPtr(it.GetSp());
582     uintptr_t end = ToUintPtr(frame->GetCurrentFramePointer());
583     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
584     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
585     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->thisObj)));
586     if (frame->pc != nullptr) {
587         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->acc)));
588         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->env)));
589     }
590 
591     bool ret = it.IteratorStackMap(visitor, derivedVisitor);
592     if (!ret) {
593 #ifndef NDEBUG
594         LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
595 #endif
596     }
597 }
598 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const599 ARK_INLINE void InterpretedFrame::GCIterate(const FrameIterator &it,
600                                             const RootVisitor &visitor,
601                                             const RootRangeVisitor &rangeVisitor) const
602 {
603     auto sp = it.GetSp();
604     InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp);
605     if (frame->function.IsHole()) {
606         return;
607     }
608 
609     JSTaggedType *prevSp = frame->GetPrevFrameFp();
610     uintptr_t start = ToUintPtr(sp);
611     const JSThread *thread = it.GetThread();
612     FrameIterator prevIt(prevSp, thread);
613     uintptr_t end = prevIt.GetPrevFrame();
614 
615     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
616     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
617     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->thisObj)));
618 
619     // pc == nullptr, init InterpretedFrame & native InterpretedFrame.
620     if (frame->pc != nullptr) {
621         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->acc)));
622         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->constpool)));
623         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->env)));
624         visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->profileTypeInfo)));
625     }
626 }
627 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const628 ARK_INLINE void InterpretedBuiltinFrame::GCIterate(const FrameIterator &it,
629                                                    const RootVisitor &visitor,
630                                                    const RootRangeVisitor &rangeVisitor) const
631 {
632     auto sp = it.GetSp();
633     InterpretedBuiltinFrame *frame = InterpretedBuiltinFrame::GetFrameFromSp(sp);
634     JSTaggedType *prevSp = frame->GetPrevFrameFp();
635     const JSThread *thread = it.GetThread();
636     FrameIterator prevIt(prevSp, thread);
637 
638     uintptr_t start = ToUintPtr(sp + 2); // 2: numArgs & thread.
639     uintptr_t end = prevIt.GetPrevFrame();
640     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
641     visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
642 }
643 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const644 ARK_INLINE void OptimizedLeaveFrame::GCIterate(const FrameIterator &it,
645     [[maybe_unused]] const RootVisitor &visitor,
646     const RootRangeVisitor &rangeVisitor) const
647 {
648     const JSTaggedType *sp = it.GetSp();
649     OptimizedLeaveFrame *frame = OptimizedLeaveFrame::GetFrameFromSp(sp);
650     if (frame->argc > 0) {
651         JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(&frame->argc + 1);
652         uintptr_t start = ToUintPtr(argv); // argv
653         uintptr_t end = ToUintPtr(argv + frame->argc);
654         rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
655     }
656 }
657 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const658 ARK_INLINE void OptimizedWithArgvLeaveFrame::GCIterate(const FrameIterator &it,
659     [[maybe_unused]] const RootVisitor &visitor,
660     const RootRangeVisitor &rangeVisitor) const
661 {
662     const JSTaggedType *sp = it.GetSp();
663     OptimizedWithArgvLeaveFrame *frame = OptimizedWithArgvLeaveFrame::GetFrameFromSp(sp);
664     if (frame->argc > 0) {
665         uintptr_t* argvPtr = reinterpret_cast<uintptr_t *>(&frame->argc + 1);
666         JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(*argvPtr);
667         uintptr_t start = ToUintPtr(argv); // argv
668         uintptr_t end = ToUintPtr(argv + frame->argc);
669         rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
670     }
671 }
672 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const673 ARK_INLINE void OptimizedBuiltinLeaveFrame::GCIterate(const FrameIterator &it,
674     [[maybe_unused]] const RootVisitor &visitor,
675     const RootRangeVisitor &rangeVisitor) const
676 {
677     const JSTaggedType *sp = it.GetSp();
678     OptimizedBuiltinLeaveFrame *frame = OptimizedBuiltinLeaveFrame::GetFrameFromSp(sp);
679     if (frame->argc > 0) {
680         JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(&frame->argc + 1);
681         uintptr_t start = ToUintPtr(argv); // argv
682         uintptr_t end = ToUintPtr(argv + frame->argc);
683         rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
684     }
685 }
686 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const687 ARK_INLINE void BuiltinWithArgvFrame::GCIterate(const FrameIterator &it,
688     [[maybe_unused]] const RootVisitor &visitor,
689     const RootRangeVisitor &rangeVisitor) const
690 {
691     const JSTaggedType *sp = it.GetSp();
692     auto frame = BuiltinWithArgvFrame::GetFrameFromSp(sp);
693     auto argc = static_cast<uint32_t>(frame->GetNumArgs()) + NUM_MANDATORY_JSFUNC_ARGS;
694     JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(frame->GetStackArgsAddress());
695     uintptr_t start = ToUintPtr(argv);
696     uintptr_t end = ToUintPtr(argv + argc);
697     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
698 }
699 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const700 ARK_INLINE void BuiltinFrame::GCIterate(const FrameIterator &it,
701     const RootVisitor &visitor,
702     const RootRangeVisitor &rangeVisitor) const
703 {
704     const JSTaggedType *sp = it.GetSp();
705     auto frame = BuiltinFrame::GetFrameFromSp(sp);
706     // no need to visit stack map for entry frame
707     if (frame->type == FrameType::BUILTIN_ENTRY_FRAME) {
708         // only visit function
709         visitor(Root::ROOT_FRAME, ObjectSlot(frame->GetStackArgsAddress()));
710         return;
711     }
712     JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(frame->GetStackArgsAddress());
713     auto argc = frame->GetNumArgs();
714     uintptr_t start = ToUintPtr(argv);
715     uintptr_t end = ToUintPtr(argv + argc);
716     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
717 }
718 
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const719 ARK_INLINE void InterpretedEntryFrame::GCIterate(const FrameIterator &it,
720     [[maybe_unused]] const RootVisitor &visitor,
721     const RootRangeVisitor &rangeVisitor) const
722 {
723     const JSTaggedType* sp = it.GetSp();
724     InterpretedEntryFrame *frame = InterpretedEntryFrame::GetFrameFromSp(sp);
725     JSTaggedType *prevSp = frame->GetPrevFrameFp();
726     if (prevSp == nullptr) {
727         return;
728     }
729 
730     const JSThread *thread = it.GetThread();
731     FrameIterator prevIt(prevSp, thread);
732     uintptr_t start = ToUintPtr(sp + 2); // 2: numArgs & thread.
733     uintptr_t end = prevIt.GetPrevFrame();
734     rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
735 }
736 }  // namespace panda::ecmascript
737