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