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/aot_file_manager.h"
19 #include "ecmascript/ecma_vm.h"
20 #include "ecmascript/interpreter/frame_handler.h"
21 #include "ecmascript/js_thread.h"
22 #include "ecmascript/stackmap/ark_stackmap_parser.h"
23 #include "ecmascript/stackmap/llvm_stackmap_parser.h"
24
25 #include "ecmascript/platform/os.h"
26
27 namespace panda::ecmascript {
FrameIterator(JSTaggedType * sp,const JSThread * thread)28 FrameIterator::FrameIterator(JSTaggedType *sp, const JSThread *thread) : current_(sp), thread_(thread)
29 {
30 if (thread != nullptr) {
31 arkStackMapParser_ = thread->GetEcmaVM()->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_FUNCTION_FRAME: {
61 auto frame = GetFrame<OptimizedJSFunctionFrame>();
62 return frame->GetFunction();
63 }
64 case FrameType::ASM_INTERPRETER_FRAME:
65 case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
66 auto frame = GetFrame<AsmInterpretedFrame>();
67 return frame->function;
68 }
69 case FrameType::INTERPRETER_FRAME:
70 case FrameType::INTERPRETER_FAST_NEW_FRAME: {
71 auto frame = GetFrame<InterpretedFrame>();
72 return frame->function;
73 }
74 case FrameType::INTERPRETER_BUILTIN_FRAME: {
75 auto frame = GetFrame<InterpretedBuiltinFrame>();
76 return frame->function;
77 }
78 case FrameType::BUILTIN_FRAME_WITH_ARGV: {
79 auto *frame = BuiltinWithArgvFrame::GetFrameFromSp(GetSp());
80 return frame->GetFunction();
81 }
82 case FrameType::BUILTIN_ENTRY_FRAME:
83 case FrameType::BUILTIN_FRAME: {
84 auto *frame = BuiltinFrame::GetFrameFromSp(GetSp());
85 return frame->GetFunction();
86 }
87 case FrameType::BUILTIN_CALL_LEAVE_FRAME: {
88 auto *frame = OptimizedBuiltinLeaveFrame::GetFrameFromSp(GetSp());
89 return JSTaggedValue(*(frame->GetArgv()));
90 }
91 case FrameType::OPTIMIZED_FRAME:
92 case FrameType::OPTIMIZED_ENTRY_FRAME:
93 case FrameType::LEAVE_FRAME:
94 case FrameType::LEAVE_FRAME_WITH_ARGV:
95 case FrameType::INTERPRETER_ENTRY_FRAME:
96 case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
97 case FrameType::ASM_INTERPRETER_BRIDGE_FRAME:
98 case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME:
99 case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
100 return JSTaggedValue::Undefined();
101 }
102 default: {
103 LOG_FULL(FATAL) << "frame type error!";
104 UNREACHABLE();
105 }
106 }
107 }
108
CalCallSiteInfo(uintptr_t retAddr) const109 AOTFileInfo::CallSiteInfo FrameIterator::CalCallSiteInfo(uintptr_t retAddr) const
110 {
111 auto loader = thread_->GetEcmaVM()->GetAOTFileManager();
112 return loader->CalCallSiteInfo(retAddr);
113 }
114
115 template <GCVisitedFlag GCVisit>
Advance()116 void FrameIterator::Advance()
117 {
118 ASSERT(!Done());
119 FrameType t = GetFrameType();
120 [[maybe_unused]] bool needCalCallSiteInfo = false;
121 switch (t) {
122 case FrameType::OPTIMIZED_FRAME : {
123 auto frame = GetFrame<OptimizedFrame>();
124 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
125 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp(optimizedReturnAddr_);
126 optimizedReturnAddr_ = frame->GetReturnAddr();
127 needCalCallSiteInfo = true;
128 }
129 current_ = frame->GetPrevFrameFp();
130 break;
131 }
132 case FrameType::OPTIMIZED_ENTRY_FRAME : {
133 auto frame = GetFrame<OptimizedEntryFrame>();
134 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
135 optimizedReturnAddr_ = 0;
136 optimizedCallSiteSp_ = 0;
137 }
138 current_ = frame->GetPrevFrameFp();
139 break;
140 }
141 case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
142 auto frame = GetFrame<OptimizedJSFunctionUnfoldArgVFrame>();
143 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
144 optimizedCallSiteSp_ = frame->GetPrevFrameSp();
145 optimizedReturnAddr_ = frame->GetReturnAddr();
146 needCalCallSiteInfo = true;
147 }
148 current_ = frame->GetPrevFrameFp();
149 break;
150 }
151 case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME: {
152 auto frame = GetFrame<OptimizedJSFunctionFrame>();
153 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
154 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
155 optimizedReturnAddr_ = frame->GetReturnAddr();
156 needCalCallSiteInfo = true;
157 }
158 current_ = frame->GetPrevFrameFp();
159 break;
160 }
161 case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
162 auto frame = GetFrame<OptimizedJSFunctionFrame>();
163 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
164 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp(optimizedReturnAddr_);
165 optimizedReturnAddr_ = frame->GetReturnAddr();
166 needCalCallSiteInfo = true;
167 }
168 current_ = frame->GetPrevFrameFp();
169 break;
170 }
171 case FrameType::LEAVE_FRAME : {
172 auto frame = GetFrame<OptimizedLeaveFrame>();
173 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
174 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
175 optimizedReturnAddr_ = frame->GetReturnAddr();
176 needCalCallSiteInfo = true;
177 }
178 current_ = frame->GetPrevFrameFp();
179 break;
180 }
181 case FrameType::LEAVE_FRAME_WITH_ARGV : {
182 auto frame = GetFrame<OptimizedWithArgvLeaveFrame>();
183 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
184 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
185 optimizedReturnAddr_ = frame->GetReturnAddr();
186 needCalCallSiteInfo = true;
187 }
188 current_ = frame->GetPrevFrameFp();
189 break;
190 }
191 case FrameType::BUILTIN_CALL_LEAVE_FRAME : {
192 auto frame = GetFrame<OptimizedBuiltinLeaveFrame>();
193 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
194 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
195 optimizedReturnAddr_ = frame->GetReturnAddr();
196 needCalCallSiteInfo = true;
197 }
198 current_ = frame->GetPrevFrameFp();
199 break;
200 }
201 case FrameType::INTERPRETER_FRAME:
202 case FrameType::INTERPRETER_FAST_NEW_FRAME : {
203 auto frame = GetFrame<InterpretedFrame>();
204 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
205 optimizedReturnAddr_ = 0;
206 optimizedCallSiteSp_ = 0;
207 }
208 current_ = frame->GetPrevFrameFp();
209 break;
210 }
211 case FrameType::INTERPRETER_BUILTIN_FRAME: {
212 auto frame = GetFrame<InterpretedBuiltinFrame>();
213 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
214 optimizedReturnAddr_ = 0;
215 optimizedCallSiteSp_ = 0;
216 }
217 current_ = frame->GetPrevFrameFp();
218 break;
219 }
220 case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
221 case FrameType::ASM_INTERPRETER_FRAME : {
222 auto frame = GetFrame<AsmInterpretedFrame>();
223 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
224 optimizedReturnAddr_ = 0;
225 optimizedCallSiteSp_ = 0;
226 }
227 current_ = frame->GetPrevFrameFp();
228 break;
229 }
230 case FrameType::BUILTIN_FRAME:
231 case FrameType::BUILTIN_ENTRY_FRAME : {
232 auto frame = GetFrame<BuiltinFrame>();
233 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
234 optimizedReturnAddr_ = frame->GetReturnAddr();
235 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
236 needCalCallSiteInfo = true;
237 }
238 current_ = frame->GetPrevFrameFp();
239 break;
240 }
241 case FrameType::BUILTIN_FRAME_WITH_ARGV : {
242 auto frame = GetFrame<BuiltinWithArgvFrame>();
243 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
244 optimizedReturnAddr_ = frame->GetReturnAddr();
245 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
246 needCalCallSiteInfo = true;
247 }
248 current_ = frame->GetPrevFrameFp();
249 break;
250 }
251 case FrameType::INTERPRETER_ENTRY_FRAME : {
252 auto frame = GetFrame<InterpretedEntryFrame>();
253 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
254 optimizedReturnAddr_ = 0;
255 optimizedCallSiteSp_ = 0;
256 }
257 current_ = frame->GetPrevFrameFp();
258 break;
259 }
260 case FrameType::ASM_INTERPRETER_ENTRY_FRAME : {
261 auto frame = GetFrame<AsmInterpretedEntryFrame>();
262 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
263 optimizedReturnAddr_ = 0;
264 optimizedCallSiteSp_ = 0;
265 }
266 current_ = frame->GetPrevFrameFp();
267 break;
268 }
269 case FrameType::ASM_INTERPRETER_BRIDGE_FRAME : {
270 auto frame = GetFrame<AsmInterpretedBridgeFrame>();
271 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
272 optimizedCallSiteSp_ = GetPrevFrameCallSiteSp(optimizedReturnAddr_);
273 optimizedReturnAddr_ = frame->GetReturnAddr();
274 needCalCallSiteInfo = true;
275 }
276 current_ = frame->GetPrevFrameFp();
277 break;
278 }
279 default: {
280 UNREACHABLE();
281 }
282 }
283 if constexpr (GCVisit == GCVisitedFlag::VISITED) {
284 if (!needCalCallSiteInfo) {
285 return;
286 }
287 uint64_t textStart = 0;
288 std::tie(textStart, stackMapAddr_, fpDeltaPrevFrameSp_, calleeRegInfo_) = CalCallSiteInfo(optimizedReturnAddr_);
289 ASSERT(optimizedReturnAddr_ >= textStart);
290 optimizedReturnAddr_ = optimizedReturnAddr_ - textStart;
291 if (t == FrameType::LEAVE_FRAME && fpDeltaPrevFrameSp_ == 0) {
292 // it may be asm code stub's leave frame.
293 fpDeltaPrevFrameSp_ = 2 * sizeof(uintptr_t); // 2: skip prev and return addr
294 }
295 }
296 }
297 template void FrameIterator::Advance<GCVisitedFlag::VISITED>();
298 template void FrameIterator::Advance<GCVisitedFlag::IGNORED>();
299
GetPrevFrameCallSiteSp(uintptr_t curPc) const300 uintptr_t FrameIterator::GetPrevFrameCallSiteSp([[maybe_unused]] uintptr_t curPc) const
301 {
302 if (Done()) {
303 return 0;
304 }
305 auto type = GetFrameType();
306 switch (type) {
307 case FrameType::LEAVE_FRAME: {
308 auto frame = GetFrame<OptimizedLeaveFrame>();
309 return frame->GetCallSiteSp();
310 }
311 case FrameType::LEAVE_FRAME_WITH_ARGV: {
312 auto frame = GetFrame<OptimizedWithArgvLeaveFrame>();
313 return frame->GetCallSiteSp();
314 }
315 case FrameType::BUILTIN_CALL_LEAVE_FRAME: {
316 auto frame = GetFrame<OptimizedBuiltinLeaveFrame>();
317 return frame->GetCallSiteSp();
318 }
319 case FrameType::BUILTIN_FRAME_WITH_ARGV: {
320 auto frame = GetFrame<BuiltinWithArgvFrame>();
321 return frame->GetCallSiteSp();
322 }
323 case FrameType::BUILTIN_FRAME: {
324 auto frame = GetFrame<BuiltinFrame>();
325 return frame->GetCallSiteSp();
326 }
327 case FrameType::ASM_INTERPRETER_BRIDGE_FRAME: {
328 auto frame = GetFrame<AsmInterpretedBridgeFrame>();
329 return frame->GetCallSiteSp();
330 }
331 case FrameType::OPTIMIZED_FRAME:
332 case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
333 ASSERT(thread_ != nullptr);
334 auto callSiteSp = reinterpret_cast<uintptr_t>(current_) + fpDeltaPrevFrameSp_;
335 return callSiteSp;
336 }
337 case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
338 auto frame = GetFrame<OptimizedJSFunctionUnfoldArgVFrame>();
339 return frame->GetPrevFrameSp();
340 }
341 case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME : {
342 auto callSiteSp = OptimizedJSFunctionFrame::ComputeArgsConfigFrameSp(current_);
343 return callSiteSp;
344 }
345 case FrameType::BUILTIN_ENTRY_FRAME:
346 case FrameType::ASM_INTERPRETER_FRAME:
347 case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
348 case FrameType::INTERPRETER_FRAME:
349 case FrameType::INTERPRETER_FAST_NEW_FRAME:
350 case FrameType::OPTIMIZED_ENTRY_FRAME:
351 case FrameType::INTERPRETER_BUILTIN_FRAME:
352 case FrameType::INTERPRETER_ENTRY_FRAME:
353 case FrameType::ASM_INTERPRETER_ENTRY_FRAME: {
354 return 0;
355 }
356 default: {
357 LOG_FULL(FATAL) << "frame type error!";
358 }
359 }
360 }
361
GetBytecodeOffset() const362 uint32_t FrameIterator::GetBytecodeOffset() const
363 {
364 FrameType type = this->GetFrameType();
365 switch (type) {
366 case FrameType::ASM_INTERPRETER_FRAME:
367 case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
368 auto *frame = this->GetFrame<AsmInterpretedFrame>();
369 Method *method = ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget();
370 auto offset = frame->GetPc() - method->GetBytecodeArray();
371 return static_cast<uint32_t>(offset);
372 }
373 case FrameType::INTERPRETER_FRAME:
374 case FrameType::INTERPRETER_FAST_NEW_FRAME: {
375 auto *frame = this->GetFrame<InterpretedFrame>();
376 Method *method = ECMAObject::Cast(frame->function.GetTaggedObject())->GetCallTarget();
377 auto offset = frame->GetPc() - method->GetBytecodeArray();
378 return static_cast<uint32_t>(offset);
379 }
380 default: {
381 return 0;
382 }
383 }
384 }
385
GetPrevFrame() const386 uintptr_t FrameIterator::GetPrevFrame() const
387 {
388 FrameType type = GetFrameType();
389 uintptr_t end = 0U;
390 switch (type) {
391 case FrameType::INTERPRETER_FRAME:
392 case FrameType::INTERPRETER_FAST_NEW_FRAME: {
393 auto prevFrame = GetFrame<InterpretedFrame>();
394 end = ToUintPtr(prevFrame);
395 break;
396 }
397 case FrameType::INTERPRETER_ENTRY_FRAME: {
398 auto prevFrame = GetFrame<InterpretedEntryFrame>();
399 end = ToUintPtr(prevFrame);
400 break;
401 }
402 case FrameType::INTERPRETER_BUILTIN_FRAME: {
403 auto prevFrame = GetFrame<InterpretedBuiltinFrame>();
404 end = ToUintPtr(prevFrame);
405 break;
406 }
407 default: {
408 LOG_FULL(FATAL) << "frame type error!";
409 }
410 }
411 return end;
412 }
413
IteratorStackMap(const RootVisitor & visitor,const RootBaseAndDerivedVisitor & derivedVisitor) const414 bool FrameIterator::IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const
415 {
416 ASSERT(arkStackMapParser_ != nullptr);
417 if (!stackMapAddr_) { // enter by assembler, no stack map
418 return true;
419 }
420
421 return arkStackMapParser_->IteratorStackMap(visitor, derivedVisitor, optimizedReturnAddr_,
422 reinterpret_cast<uintptr_t>(current_), optimizedCallSiteSp_, stackMapAddr_);
423 }
424
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor) const425 ARK_INLINE void OptimizedFrame::GCIterate(const FrameIterator &it,
426 [[maybe_unused]] const RootVisitor &visitor,
427 [[maybe_unused]] const RootRangeVisitor &rangeVisitor,
428 const RootBaseAndDerivedVisitor &derivedVisitor) const
429 {
430 bool ret = it.IteratorStackMap(visitor, derivedVisitor);
431 if (!ret) {
432 #ifndef NDEBUG
433 LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
434 #endif
435 }
436 }
437
CollectBCOffsetInfo(kungfu::ConstInfo & info) const438 void FrameIterator::CollectBCOffsetInfo(kungfu::ConstInfo &info) const
439 {
440 arkStackMapParser_->GetConstInfo(optimizedReturnAddr_, info, stackMapAddr_);
441 }
442
CollectArkDeopt(std::vector<kungfu::ARKDeopt> & deopts) const443 void FrameIterator::CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const
444 {
445 arkStackMapParser_->GetArkDeopt(optimizedReturnAddr_, stackMapAddr_, deopts);
446 }
447
GetArgv(const FrameIterator & it) const448 ARK_INLINE JSTaggedType* OptimizedJSFunctionFrame::GetArgv(const FrameIterator &it) const
449 {
450 uintptr_t *preFrameSp = ComputePrevFrameSp(it);
451 return GetArgv(preFrameSp);
452 }
453
ComputePrevFrameSp(const FrameIterator & it) const454 ARK_INLINE uintptr_t* OptimizedJSFunctionFrame::ComputePrevFrameSp(const FrameIterator &it) const
455 {
456 const JSTaggedType *sp = it.GetSp();
457 int delta = it.ComputeDelta();
458 ASSERT((delta > 0) && (delta % sizeof(uintptr_t) == 0));
459 uintptr_t *preFrameSp = reinterpret_cast<uintptr_t *>(const_cast<JSTaggedType *>(sp))
460 + delta / sizeof(uintptr_t);
461 return preFrameSp;
462 }
463
464
CollectBCOffsetInfo(const FrameIterator & it,kungfu::ConstInfo & info) const465 void OptimizedJSFunctionFrame::CollectBCOffsetInfo(const FrameIterator &it, kungfu::ConstInfo &info) const
466 {
467 it.CollectBCOffsetInfo(info);
468 }
469
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor) const470 ARK_INLINE void OptimizedJSFunctionFrame::GCIterate(const FrameIterator &it,
471 const RootVisitor &visitor,
472 const RootRangeVisitor &rangeVisitor,
473 const RootBaseAndDerivedVisitor &derivedVisitor) const
474 {
475 OptimizedJSFunctionFrame *frame = OptimizedJSFunctionFrame::GetFrameFromSp(it.GetSp());
476 uintptr_t *jsFuncPtr = reinterpret_cast<uintptr_t *>(frame);
477 uintptr_t jsFuncSlot = ToUintPtr(jsFuncPtr);
478 visitor(Root::ROOT_FRAME, ObjectSlot(jsFuncSlot));
479
480 uintptr_t *preFrameSp = frame->ComputePrevFrameSp(it);
481 uintptr_t envSlot = ToUintPtr(preFrameSp);
482 visitor(Root::ROOT_FRAME, ObjectSlot(envSlot));
483
484 auto argc = frame->GetArgc(preFrameSp);
485 JSTaggedType *argv = frame->GetArgv(reinterpret_cast<uintptr_t *>(preFrameSp));
486 if (argc > 0) {
487 uintptr_t start = ToUintPtr(argv); // argv
488 uintptr_t end = ToUintPtr(argv + argc);
489 rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
490 }
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
GetDeoptBundleInfo(const FrameIterator & it,std::vector<kungfu::ARKDeopt> & deopts) const500 void OptimizedJSFunctionFrame::GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const
501 {
502 it.CollectArkDeopt(deopts);
503 }
504
GetFuncCalleeRegAndOffset(const FrameIterator & it,kungfu::CalleeRegAndOffsetVec & ret) const505 void OptimizedJSFunctionFrame::GetFuncCalleeRegAndOffset(
506 const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const
507 {
508 it.GetCalleeRegAndOffsetVec(ret);
509 }
510
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor) const511 ARK_INLINE void AsmInterpretedFrame::GCIterate(const FrameIterator &it,
512 const RootVisitor &visitor,
513 const RootRangeVisitor &rangeVisitor,
514 const RootBaseAndDerivedVisitor &derivedVisitor) const
515 {
516 AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(it.GetSp());
517 uintptr_t start = ToUintPtr(it.GetSp());
518 uintptr_t end = ToUintPtr(frame->GetCurrentFramePointer());
519 rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
520 visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
521 visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->thisObj)));
522 if (frame->pc != nullptr) {
523 visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->acc)));
524 visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->env)));
525 }
526
527 bool ret = it.IteratorStackMap(visitor, derivedVisitor);
528 if (!ret) {
529 #ifndef NDEBUG
530 LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << it.GetOptimizedReturnAddr();
531 #endif
532 }
533 }
534
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const535 ARK_INLINE void InterpretedFrame::GCIterate(const FrameIterator &it,
536 const RootVisitor &visitor,
537 const RootRangeVisitor &rangeVisitor) const
538 {
539 auto sp = it.GetSp();
540 InterpretedFrame *frame = InterpretedFrame::GetFrameFromSp(sp);
541 if (frame->function == JSTaggedValue::Hole()) {
542 return;
543 }
544
545 JSTaggedType *prevSp = frame->GetPrevFrameFp();
546 uintptr_t start = ToUintPtr(sp);
547 const JSThread *thread = it.GetThread();
548 FrameIterator prevIt(prevSp, thread);
549 uintptr_t end = prevIt.GetPrevFrame();
550
551 rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
552 visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
553 visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->thisObj)));
554
555 // pc == nullptr, init InterpretedFrame & native InterpretedFrame.
556 if (frame->pc != nullptr) {
557 visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->acc)));
558 visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->constpool)));
559 visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->env)));
560 visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->profileTypeInfo)));
561 }
562 }
563
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const564 ARK_INLINE void InterpretedBuiltinFrame::GCIterate(const FrameIterator &it,
565 const RootVisitor &visitor,
566 const RootRangeVisitor &rangeVisitor) const
567 {
568 auto sp = it.GetSp();
569 InterpretedBuiltinFrame *frame = InterpretedBuiltinFrame::GetFrameFromSp(sp);
570 JSTaggedType *prevSp = frame->GetPrevFrameFp();
571 const JSThread *thread = it.GetThread();
572 FrameIterator prevIt(prevSp, thread);
573
574 uintptr_t start = ToUintPtr(sp + 2); // 2: numArgs & thread.
575 uintptr_t end = prevIt.GetPrevFrame();
576 rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
577 visitor(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function)));
578 }
579
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const580 ARK_INLINE void OptimizedLeaveFrame::GCIterate(const FrameIterator &it,
581 [[maybe_unused]] const RootVisitor &visitor,
582 const RootRangeVisitor &rangeVisitor) const
583 {
584 const JSTaggedType *sp = it.GetSp();
585 OptimizedLeaveFrame *frame = OptimizedLeaveFrame::GetFrameFromSp(sp);
586 if (frame->argc > 0) {
587 JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(&frame->argc + 1);
588 uintptr_t start = ToUintPtr(argv); // argv
589 uintptr_t end = ToUintPtr(argv + frame->argc);
590 rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
591 }
592 }
593
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const594 ARK_INLINE void OptimizedWithArgvLeaveFrame::GCIterate(const FrameIterator &it,
595 [[maybe_unused]] const RootVisitor &visitor,
596 const RootRangeVisitor &rangeVisitor) const
597 {
598 const JSTaggedType *sp = it.GetSp();
599 OptimizedWithArgvLeaveFrame *frame = OptimizedWithArgvLeaveFrame::GetFrameFromSp(sp);
600 if (frame->argc > 0) {
601 uintptr_t* argvPtr = reinterpret_cast<uintptr_t *>(&frame->argc + 1);
602 JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(*argvPtr);
603 uintptr_t start = ToUintPtr(argv); // argv
604 uintptr_t end = ToUintPtr(argv + frame->argc);
605 rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
606 }
607 }
608
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const609 ARK_INLINE void OptimizedBuiltinLeaveFrame::GCIterate(const FrameIterator &it,
610 [[maybe_unused]] const RootVisitor &visitor,
611 const RootRangeVisitor &rangeVisitor) const
612 {
613 const JSTaggedType *sp = it.GetSp();
614 OptimizedBuiltinLeaveFrame *frame = OptimizedBuiltinLeaveFrame::GetFrameFromSp(sp);
615 if (frame->argc > 0) {
616 JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(&frame->argc + 1);
617 uintptr_t start = ToUintPtr(argv); // argv
618 uintptr_t end = ToUintPtr(argv + frame->argc);
619 rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
620 }
621 }
622
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const623 ARK_INLINE void BuiltinWithArgvFrame::GCIterate(const FrameIterator &it,
624 [[maybe_unused]] const RootVisitor &visitor,
625 const RootRangeVisitor &rangeVisitor) const
626 {
627 const JSTaggedType *sp = it.GetSp();
628 auto frame = BuiltinWithArgvFrame::GetFrameFromSp(sp);
629 auto argc = static_cast<uint32_t>(frame->GetNumArgs()) + NUM_MANDATORY_JSFUNC_ARGS;
630 JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(frame->GetStackArgsAddress());
631 uintptr_t start = ToUintPtr(argv);
632 uintptr_t end = ToUintPtr(argv + argc);
633 rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
634 }
635
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const636 ARK_INLINE void BuiltinFrame::GCIterate(const FrameIterator &it,
637 const RootVisitor &visitor,
638 const RootRangeVisitor &rangeVisitor) const
639 {
640 const JSTaggedType *sp = it.GetSp();
641 auto frame = BuiltinFrame::GetFrameFromSp(sp);
642 // no need to visit stack map for entry frame
643 if (frame->type == FrameType::BUILTIN_ENTRY_FRAME) {
644 // only visit function
645 visitor(Root::ROOT_FRAME, ObjectSlot(frame->GetStackArgsAddress()));
646 return;
647 }
648 JSTaggedType *argv = reinterpret_cast<JSTaggedType *>(frame->GetStackArgsAddress());
649 auto argc = frame->GetNumArgs();
650 uintptr_t start = ToUintPtr(argv);
651 uintptr_t end = ToUintPtr(argv + argc);
652 rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
653 }
654
GCIterate(const FrameIterator & it,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor) const655 ARK_INLINE void InterpretedEntryFrame::GCIterate(const FrameIterator &it,
656 [[maybe_unused]] const RootVisitor &visitor,
657 const RootRangeVisitor &rangeVisitor) const
658 {
659 const JSTaggedType* sp = it.GetSp();
660 InterpretedEntryFrame *frame = InterpretedEntryFrame::GetFrameFromSp(sp);
661 JSTaggedType *prevSp = frame->GetPrevFrameFp();
662 if (prevSp == nullptr) {
663 return;
664 }
665
666 const JSThread *thread = it.GetThread();
667 FrameIterator prevIt(prevSp, thread);
668 uintptr_t start = ToUintPtr(sp + 2); // 2: numArgs & thread.
669 uintptr_t end = prevIt.GetPrevFrame();
670 rangeVisitor(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end));
671 }
672
ReadUintptrFromAddr(int pid,uintptr_t addr,uintptr_t & value)673 bool ReadUintptrFromAddr(int pid, uintptr_t addr, uintptr_t &value)
674 {
675 if (pid == getpid()) {
676 value = *(reinterpret_cast<uintptr_t *>(addr));
677 return true;
678 }
679 long *retAddr = reinterpret_cast<long *>(&value);
680 // note: big endian
681 for (size_t i = 0; i < sizeof(uintptr_t) / sizeof(long); i++) {
682 *retAddr = PtracePeektext(pid, addr);
683 if (*retAddr == -1) {
684 LOG_ECMA(ERROR) << "ReadFromAddr ERROR, addr: " << addr;
685 return false;
686 }
687 addr += sizeof(long);
688 retAddr++;
689 }
690 return true;
691 }
692
GetTypeOffsetAndPrevOffsetFromFrameType(uintptr_t frameType,uintptr_t & typeOffset,uintptr_t & prevOffset)693 bool GetTypeOffsetAndPrevOffsetFromFrameType(uintptr_t frameType, uintptr_t &typeOffset, uintptr_t &prevOffset)
694 {
695 FrameType type = static_cast<FrameType>(frameType);
696 switch (type) {
697 case FrameType::OPTIMIZED_FRAME:
698 typeOffset = OptimizedFrame::GetTypeOffset();
699 prevOffset = OptimizedFrame::GetPrevOffset();
700 break;
701 case FrameType::OPTIMIZED_ENTRY_FRAME:
702 typeOffset = OptimizedEntryFrame::GetTypeOffset();
703 prevOffset = OptimizedEntryFrame::GetLeaveFrameFpOffset();
704 break;
705 case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME:
706 typeOffset = OptimizedJSFunctionUnfoldArgVFrame::GetTypeOffset();
707 prevOffset = OptimizedJSFunctionUnfoldArgVFrame::GetPrevOffset();
708 break;
709 case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME:
710 case FrameType::OPTIMIZED_JS_FUNCTION_FRAME:
711 typeOffset = OptimizedJSFunctionFrame::GetTypeOffset();
712 prevOffset = OptimizedJSFunctionFrame::GetPrevOffset();
713 break;
714 case FrameType::LEAVE_FRAME:
715 typeOffset = MEMBER_OFFSET(OptimizedLeaveFrame, type);
716 prevOffset = MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp);
717 break;
718 case FrameType::LEAVE_FRAME_WITH_ARGV:
719 typeOffset = MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, type);
720 prevOffset = MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp);
721 break;
722 case FrameType::BUILTIN_CALL_LEAVE_FRAME:
723 typeOffset = OptimizedBuiltinLeaveFrame::GetTypeOffset();
724 prevOffset = OptimizedBuiltinLeaveFrame::GetPrevOffset();
725 break;
726 case FrameType::INTERPRETER_FRAME:
727 case FrameType::INTERPRETER_FAST_NEW_FRAME:
728 typeOffset = MEMBER_OFFSET(InterpretedFrame, base) +
729 MEMBER_OFFSET(InterpretedFrameBase, type);
730 prevOffset = MEMBER_OFFSET(InterpretedFrame, base) +
731 MEMBER_OFFSET(InterpretedFrameBase, prev);
732 break;
733 case FrameType::INTERPRETER_BUILTIN_FRAME:
734 typeOffset = MEMBER_OFFSET(InterpretedBuiltinFrame, base) +
735 MEMBER_OFFSET(InterpretedFrameBase, type);
736 prevOffset = MEMBER_OFFSET(InterpretedBuiltinFrame, base) +
737 MEMBER_OFFSET(InterpretedFrameBase, prev);
738 break;
739 case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
740 case FrameType::ASM_INTERPRETER_FRAME:
741 typeOffset = MEMBER_OFFSET(AsmInterpretedFrame, base) +
742 MEMBER_OFFSET(InterpretedFrameBase, type);
743 prevOffset = MEMBER_OFFSET(AsmInterpretedFrame, base) +
744 MEMBER_OFFSET(InterpretedFrameBase, prev);
745 break;
746 case FrameType::BUILTIN_FRAME:
747 case FrameType::BUILTIN_ENTRY_FRAME:
748 typeOffset = MEMBER_OFFSET(BuiltinFrame, type);
749 prevOffset = MEMBER_OFFSET(BuiltinFrame, prevFp);
750 break;
751 case FrameType::BUILTIN_FRAME_WITH_ARGV:
752 typeOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, type);
753 prevOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, prevFp);
754 break;
755 case FrameType::INTERPRETER_ENTRY_FRAME:
756 typeOffset = MEMBER_OFFSET(InterpretedEntryFrame, base) +
757 MEMBER_OFFSET(InterpretedFrameBase, type);
758 prevOffset = MEMBER_OFFSET(InterpretedEntryFrame, base) +
759 MEMBER_OFFSET(InterpretedFrameBase, prev);
760 break;
761 case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
762 typeOffset = MEMBER_OFFSET(AsmInterpretedEntryFrame, base) +
763 MEMBER_OFFSET(InterpretedFrameBase, type);
764 prevOffset = MEMBER_OFFSET(AsmInterpretedEntryFrame, base) +
765 MEMBER_OFFSET(InterpretedFrameBase, prev);
766 break;
767 case FrameType::ASM_INTERPRETER_BRIDGE_FRAME:
768 typeOffset = MEMBER_OFFSET(AsmInterpretedBridgeFrame, entry) +
769 MEMBER_OFFSET(AsmInterpretedEntryFrame, base) +
770 MEMBER_OFFSET(InterpretedFrameBase, type);
771 prevOffset = MEMBER_OFFSET(AsmInterpretedBridgeFrame, entry) +
772 MEMBER_OFFSET(AsmInterpretedEntryFrame, base) +
773 MEMBER_OFFSET(InterpretedFrameBase, prev);
774 break;
775 default:
776 return false;
777 }
778 return true;
779 }
780
StepArkManagedNativeFrame(int pid,uintptr_t * pc,uintptr_t * fp,uintptr_t * sp,char * buf,size_t bufSize)781 bool StepArkManagedNativeFrame(int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t *sp,
782 [[maybe_unused]] char *buf, [[maybe_unused]] size_t bufSize)
783 {
784 uintptr_t currentPtr = *fp;
785 while (true) {
786 currentPtr -= sizeof(FrameType);
787 uintptr_t frameType = 0;
788 if (!ReadUintptrFromAddr(pid, currentPtr, frameType)) {
789 return false;
790 }
791 uintptr_t typeOffset = 0;
792 uintptr_t prevOffset = 0;
793 if (!GetTypeOffsetAndPrevOffsetFromFrameType(frameType, typeOffset, prevOffset)) {
794 LOG_ECMA(ERROR) << "FrameType ERROR, addr: " << currentPtr << ", frameType: " << frameType;
795 return false;
796 }
797 if (frameType == (uintptr_t)(FrameType::ASM_INTERPRETER_ENTRY_FRAME)) {
798 break;
799 }
800 currentPtr -= typeOffset;
801 currentPtr += prevOffset;
802 if (!ReadUintptrFromAddr(pid, currentPtr, currentPtr)) {
803 return false;
804 }
805 }
806 currentPtr += sizeof(FrameType);
807 *fp = currentPtr;
808 currentPtr += 8; // 8: size of fp
809 if (!ReadUintptrFromAddr(pid, currentPtr, *pc)) {
810 return false;
811 }
812 currentPtr += 8; // 8: size of lr
813 *sp = currentPtr;
814 return true;
815 }
816 } // namespace panda::ecmascript
817
step_ark_managed_native_frame(int pid,uintptr_t * pc,uintptr_t * fp,uintptr_t * sp,char * buf,size_t buf_sz)818 __attribute__((visibility("default"))) int step_ark_managed_native_frame(
819 int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t *sp, char *buf, size_t buf_sz)
820 {
821 if (panda::ecmascript::StepArkManagedNativeFrame(pid, pc, fp, sp, buf, buf_sz)) {
822 return 1;
823 }
824 return -1;
825 }
826