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