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