• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright (c) 2021 Huawei Device Co., Ltd.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "ecmascript/interpreter/frame_handler.h"
18 
19 #include "ecmascript/aot_file_manager.h"
20 #include "ecmascript/js_function.h"
21 #include "ecmascript/js_thread.h"
22 #include "ecmascript/mem/heap.h"
23 #include "ecmascript/stackmap/llvm_stackmap_parser.h"
24 
25 namespace panda::ecmascript {
FrameHandler(const JSThread * thread)26 FrameHandler::FrameHandler(const JSThread *thread)
27     : sp_(const_cast<JSTaggedType *>(thread->GetCurrentFrame())), thread_(thread)
28 {
29     AdvanceToJSFrame();
30 }
31 
FrameHandler(const JSThread * thread,void * fp)32 FrameHandler::FrameHandler(const JSThread *thread, void *fp)
33     : sp_(reinterpret_cast<JSTaggedType *>(fp)), thread_(thread)
34 {
35     AdvanceToJSFrame();
36 }
37 
AdvanceToJSFrame()38 ARK_INLINE void FrameHandler::AdvanceToJSFrame()
39 {
40     if (!thread_->IsAsmInterpreter()) {
41         return;
42     }
43     FrameIterator it(sp_, thread_);
44     for (; !it.Done(); it.Advance()) {
45         FrameType t = it.GetFrameType();
46         if (IsJSFrame(t) || IsJSEntryFrame(t)) {
47             break;
48         }
49     }
50     sp_ = it.GetSp();
51 }
52 
PrevJSFrame()53 ARK_INLINE void FrameHandler::PrevJSFrame()
54 {
55     if (!thread_->IsAsmInterpreter()) {
56         FrameIterator it(sp_, thread_);
57         it.Advance();
58         sp_ = it.GetSp();
59         return;
60     }
61     AdvanceToJSFrame();
62     FrameIterator it(sp_, thread_);
63     FrameType t = it.GetFrameType();
64     if (t == FrameType::ASM_INTERPRETER_FRAME) {
65         auto frame = it.GetFrame<AsmInterpretedFrame>();
66         if (thread_->IsAsmInterpreter()) {
67             fp_ = frame->GetCurrentFramePointer();
68         }
69     }
70     it.Advance();
71     sp_ = it.GetSp();
72     AdvanceToJSFrame();
73 }
74 
GetPrevJSFrame()75 JSTaggedType* FrameHandler::GetPrevJSFrame()
76 {
77     PrevJSFrame();
78     return GetSp();
79 }
80 
GetNumberArgs()81 uint32_t FrameHandler::GetNumberArgs()
82 {
83     if (thread_->IsAsmInterpreter()) {
84         auto *frame = AsmInterpretedFrame::GetFrameFromSp(sp_);
85         return static_cast<uint32_t>(frame->GetCurrentFramePointer() - sp_);
86     }
87     ASSERT(IsInterpretedFrame());
88     JSTaggedType *prevSp = nullptr;
89     FrameIterator it(sp_, thread_);
90     if (IsAsmInterpretedFrame()) {
91         auto *frame = it.GetFrame<AsmInterpretedFrame>();
92         prevSp = frame->GetPrevFrameFp();
93     } else {
94         auto *frame = it.GetFrame<InterpretedFrame>();
95         prevSp = frame->GetPrevFrameFp();
96     }
97     auto prevSpEnd = reinterpret_cast<JSTaggedType*>(GetInterpretedFrameEnd(prevSp));
98     return static_cast<uint32_t>(prevSpEnd - sp_);
99 }
100 
GetVRegValue(size_t index) const101 JSTaggedValue FrameHandler::GetVRegValue(size_t index) const
102 {
103     ASSERT(IsInterpretedFrame());
104     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
105     return JSTaggedValue(sp_[index]);
106 }
107 
SetVRegValue(size_t index,JSTaggedValue value)108 void FrameHandler::SetVRegValue(size_t index, JSTaggedValue value)
109 {
110     ASSERT(IsInterpretedFrame());
111     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
112     sp_[index] = value.GetRawData();
113 }
114 
GetAcc() const115 JSTaggedValue FrameHandler::GetAcc() const
116 {
117     ASSERT(IsInterpretedFrame());
118     FrameIterator it(sp_, thread_);
119     if (IsAsmInterpretedFrame()) {
120         auto *frame = it.GetFrame<AsmInterpretedFrame>();
121         return frame->acc;
122     } else {
123         auto *frame = it.GetFrame<InterpretedFrame>();
124         return frame->acc;
125     }
126 }
127 
GetBytecodeOffset() const128 uint32_t FrameHandler::GetBytecodeOffset() const
129 {
130     ASSERT(IsJSFrame());
131     Method *method = GetMethod();
132     auto offset = GetPc() - method->GetBytecodeArray();
133     return static_cast<uint32_t>(offset);
134 }
135 
GetMethod() const136 Method *FrameHandler::GetMethod() const
137 {
138     ASSERT(IsJSFrame());
139     auto function = GetFunction();
140     return ECMAObject::Cast(function.GetTaggedObject())->GetCallTarget();
141 }
142 
CheckAndGetMethod() const143 Method *FrameHandler::CheckAndGetMethod() const
144 {
145     ASSERT(IsJSFrame());
146     auto function = GetFunction();
147     if (function.IsJSFunctionBase() || function.IsJSProxy()) {
148         return ECMAObject::Cast(function.GetTaggedObject())->GetCallTarget();
149     }
150     return nullptr;
151 }
152 
GetThis() const153 JSTaggedValue FrameHandler::GetThis() const
154 {
155     ASSERT(IsInterpretedFrame());
156     FrameIterator it(sp_, thread_);
157     if (IsAsmInterpretedFrame()) {
158         auto *frame = it.GetFrame<AsmInterpretedFrame>();
159         return frame->thisObj;
160     } else {
161         auto *frame = it.GetFrame<InterpretedFrame>();
162         return frame->thisObj;
163     }
164 }
165 
GetFunction() const166 JSTaggedValue FrameHandler::GetFunction() const
167 {
168     ASSERT(IsJSFrame());
169     if (thread_->IsAsmInterpreter()) {
170         FrameType type = GetFrameType();
171         switch (type) {
172             case FrameType::ASM_INTERPRETER_FRAME:
173             case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
174                 auto frame = AsmInterpretedFrame::GetFrameFromSp(sp_);
175                 return frame->function;
176             }
177             case FrameType::BUILTIN_FRAME_WITH_ARGV: {
178                 auto *frame = BuiltinWithArgvFrame::GetFrameFromSp(sp_);
179                 return frame->GetFunction();
180             }
181             case FrameType::BUILTIN_ENTRY_FRAME:
182             case FrameType::BUILTIN_FRAME: {
183                 auto *frame = BuiltinFrame::GetFrameFromSp(sp_);
184                 return frame->GetFunction();
185             }
186             case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
187                 auto *frame = OptimizedJSFunctionFrame::GetFrameFromSp(sp_);
188                 return frame->GetFunction();
189             }
190             case FrameType::INTERPRETER_FRAME:
191             case FrameType::INTERPRETER_FAST_NEW_FRAME:
192             case FrameType::INTERPRETER_ENTRY_FRAME:
193             case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
194             case FrameType::ASM_INTERPRETER_BRIDGE_FRAME:
195             case FrameType::INTERPRETER_BUILTIN_FRAME:
196             case FrameType::OPTIMIZED_FRAME:
197             case FrameType::LEAVE_FRAME:
198             case FrameType::LEAVE_FRAME_WITH_ARGV:
199             case FrameType::BUILTIN_CALL_LEAVE_FRAME:
200             case FrameType::OPTIMIZED_ENTRY_FRAME:
201             default: {
202                 LOG_FULL(FATAL) << "frame type error!";
203                 UNREACHABLE();
204             }
205         }
206     } else {
207         FrameType type = GetFrameType();
208         if (type == FrameType::INTERPRETER_FRAME || type == FrameType::INTERPRETER_FAST_NEW_FRAME) {
209             auto *frame = InterpretedFrame::GetFrameFromSp(sp_);
210             return frame->function;
211         } else {
212             auto *frame = InterpretedBuiltinFrame::GetFrameFromSp(sp_);
213             return frame->function;
214         }
215     }
216 }
217 
GetPc() const218 const uint8_t *FrameHandler::GetPc() const
219 {
220     ASSERT(IsJSFrame());
221     FrameIterator it(sp_, thread_);
222     if (IsAsmInterpretedFrame()) {
223         auto *frame = it.GetFrame<AsmInterpretedFrame>();
224         return frame->GetPc();
225     } else {
226         auto *frame = it.GetFrame<InterpretedFrame>();
227         return frame->GetPc();
228     }
229 }
230 
GetConstpool() const231 ConstantPool *FrameHandler::GetConstpool() const
232 {
233     ASSERT(IsInterpretedFrame());
234     auto method = GetMethod();
235     JSTaggedValue constpool = method->GetConstantPool();
236     return ConstantPool::Cast(constpool.GetTaggedObject());
237 }
238 
GetEnv() const239 JSTaggedValue FrameHandler::GetEnv() const
240 {
241     ASSERT(IsInterpretedFrame());
242     FrameIterator it(sp_, thread_);
243     if (IsAsmInterpretedFrame()) {
244         auto *frame = it.GetFrame<AsmInterpretedFrame>();
245         return frame->GetEnv();
246     } else {
247         auto *frame = it.GetFrame<InterpretedFrame>();
248         return frame->env;
249     }
250 }
251 
DumpStack(std::ostream & os) const252 void FrameHandler::DumpStack(std::ostream &os) const
253 {
254     size_t i = 0;
255     FrameHandler frameHandler(thread_);
256     for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) {
257         os << "[" << i++
258         << "]:" << frameHandler.GetMethod()->ParseFunctionName()
259         << "\n";
260     }
261 }
262 
DumpPC(std::ostream & os,const uint8_t * pc) const263 void FrameHandler::DumpPC(std::ostream &os, const uint8_t *pc) const
264 {
265     FrameHandler frameHandler(thread_);
266     ASSERT(frameHandler.HasFrame());
267     // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions, bugprone-narrowing-conversions)
268     int offset = pc - frameHandler.GetMethod()->GetBytecodeArray();
269     os << "offset: " << offset << "\n";
270 }
271 
GetInterpretedFrameEnd(JSTaggedType * prevSp) const272 ARK_INLINE uintptr_t FrameHandler::GetInterpretedFrameEnd(JSTaggedType *prevSp) const
273 {
274     uintptr_t end = 0U;
275     FrameIterator it(prevSp, thread_);
276     FrameType type = it.GetFrameType();
277     switch (type) {
278         case FrameType::ASM_INTERPRETER_FRAME:
279         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
280             auto frame = it.GetFrame<AsmInterpretedFrame>();
281             end = ToUintPtr(frame);
282             break;
283         }
284         case FrameType::INTERPRETER_FRAME:
285         case FrameType::INTERPRETER_FAST_NEW_FRAME: {
286             auto frame = it.GetFrame<InterpretedFrame>();
287             end = ToUintPtr(frame);
288             break;
289         }
290         case FrameType::INTERPRETER_ENTRY_FRAME: {
291             auto frame = it.GetFrame<InterpretedEntryFrame>();
292             end = ToUintPtr(frame);
293             break;
294         }
295         case FrameType::INTERPRETER_BUILTIN_FRAME: {
296             auto frame = it.GetFrame<InterpretedBuiltinFrame>();
297             end = ToUintPtr(frame);
298             break;
299         }
300         case FrameType::BUILTIN_FRAME_WITH_ARGV:
301         case FrameType::BUILTIN_ENTRY_FRAME:
302         case FrameType::BUILTIN_FRAME:
303         case FrameType::OPTIMIZED_FRAME:
304         case FrameType::LEAVE_FRAME:
305         case FrameType::LEAVE_FRAME_WITH_ARGV:
306         case FrameType::BUILTIN_CALL_LEAVE_FRAME:
307         case FrameType::OPTIMIZED_ENTRY_FRAME:
308         case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
309         case FrameType::ASM_INTERPRETER_BRIDGE_FRAME:
310         default: {
311             LOG_FULL(FATAL) << "frame type error!";
312             UNREACHABLE();
313         }
314     }
315     return end;
316 }
317 
IterateAssembleStack(const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor)318 void FrameHandler::IterateAssembleStack(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
319     const RootBaseAndDerivedVisitor &derivedVisitor)
320 {
321     JSTaggedType *current = const_cast<JSTaggedType *>(thread_->GetLastLeaveFrame());
322     IterateFrameChain(current, visitor, rangeVisitor, derivedVisitor);
323 }
324 
325 // We seperate InterpretedEntryFrame from assemble stack when asm interpreter is enable.
326 // To protect EcmaRuntimeCallInfo on InterpretedEntryFrame, we iterate InterpretedEntryFrame on thread sp individually.
327 // And only InterpretedEntryFrame is on thread sp when asm interpreter is enable.
IterateEcmaRuntimeCallInfo(const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor)328 void FrameHandler::IterateEcmaRuntimeCallInfo(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor)
329 {
330     ASSERT(thread_->IsAsmInterpreter());
331     JSTaggedType *current = const_cast<JSTaggedType *>(thread_->GetCurrentSPFrame());
332     for (FrameIterator it(current, thread_); !it.Done(); it.Advance()) {
333         ASSERT(it.GetFrameType() == FrameType::INTERPRETER_ENTRY_FRAME);
334         auto frame = it.GetFrame<InterpretedEntryFrame>();
335         frame->GCIterate(it, visitor, rangeVisitor);
336     }
337 }
338 
Iterate(const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor)339 void FrameHandler::Iterate(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
340     const RootBaseAndDerivedVisitor &derivedVisitor)
341 {
342     if (thread_->IsAsmInterpreter()) {
343         IterateEcmaRuntimeCallInfo(visitor, rangeVisitor);
344         IterateAssembleStack(visitor, rangeVisitor, derivedVisitor);
345         return;
346     }
347     JSTaggedType *current = const_cast<JSTaggedType *>(thread_->GetCurrentSPFrame());
348     FrameType frameType = FrameHandler::GetFrameType(current);
349     if (frameType != FrameType::INTERPRETER_ENTRY_FRAME) {
350         auto leaveFrame = const_cast<JSTaggedType *>(thread_->GetLastLeaveFrame());
351         if (leaveFrame != nullptr) {
352             current = leaveFrame;
353         }
354     }
355     // lazy assignment: only Iterate need arkStackMapParser_ in order to high improve performance
356     if (arkStackMapParser_ == nullptr) {
357         arkStackMapParser_ = thread_->GetEcmaVM()->GetAOTFileManager()->GetStackMapParser();
358     }
359     IterateFrameChain(current, visitor, rangeVisitor, derivedVisitor);
360 }
361 
IterateFrameChain(JSTaggedType * start,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor) const362 void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &visitor,
363     const RootRangeVisitor &rangeVisitor, const RootBaseAndDerivedVisitor &derivedVisitor) const
364 {
365     JSTaggedType *current = start;
366     for (FrameIterator it(current, thread_); !it.Done(); it.Advance<GCVisitedFlag::VISITED>()) {
367         FrameType type = it.GetFrameType();
368         switch (type) {
369             case FrameType::OPTIMIZED_FRAME: {
370                 auto frame = it.GetFrame<OptimizedFrame>();
371                 frame->GCIterate(it, visitor, rangeVisitor, derivedVisitor);
372                 break;
373             }
374             case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
375                 auto frame = it.GetFrame<OptimizedJSFunctionFrame>();
376                 frame->GCIterate(it, visitor, rangeVisitor, derivedVisitor);
377                 break;
378             }
379             case FrameType::ASM_INTERPRETER_FRAME:
380             case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
381                 auto frame = it.GetFrame<AsmInterpretedFrame>();
382                 frame->GCIterate(it, visitor, rangeVisitor, derivedVisitor);
383                 break;
384             }
385             case FrameType::INTERPRETER_FRAME:
386             case FrameType::INTERPRETER_FAST_NEW_FRAME: {
387                 auto frame = it.GetFrame<InterpretedFrame>();
388                 frame->GCIterate(it, visitor, rangeVisitor);
389                 break;
390             }
391             case FrameType::INTERPRETER_BUILTIN_FRAME: {
392                 auto frame = it.GetFrame<InterpretedBuiltinFrame>();
393                 frame->GCIterate(it, visitor, rangeVisitor);
394                 break;
395             }
396             case FrameType::LEAVE_FRAME: {
397                 auto frame = it.GetFrame<OptimizedLeaveFrame>();
398                 frame->GCIterate(it, visitor, rangeVisitor);
399                 break;
400             }
401             case FrameType::LEAVE_FRAME_WITH_ARGV: {
402                 auto frame = it.GetFrame<OptimizedWithArgvLeaveFrame>();
403                 frame->GCIterate(it, visitor, rangeVisitor);
404                 break;
405             }
406             case FrameType::BUILTIN_CALL_LEAVE_FRAME: {
407                 auto frame = it.GetFrame<OptimizedBuiltinLeaveFrame>();
408                 frame->GCIterate(it, visitor, rangeVisitor);
409                 break;
410             }
411             case FrameType::BUILTIN_FRAME_WITH_ARGV: {
412                 auto frame = it.GetFrame<BuiltinWithArgvFrame>();
413                 frame->GCIterate(it, visitor, rangeVisitor);
414                 break;
415             }
416             case FrameType::BUILTIN_ENTRY_FRAME:
417             case FrameType::BUILTIN_FRAME: {
418                 auto frame = it.GetFrame<BuiltinFrame>();
419                 frame->GCIterate(it, visitor, rangeVisitor);
420                 break;
421             }
422             case FrameType::INTERPRETER_ENTRY_FRAME: {
423                 auto frame = it.GetFrame<InterpretedEntryFrame>();
424                 frame->GCIterate(it, visitor, rangeVisitor);
425                 break;
426             }
427             case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME:
428             case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME:
429             case FrameType::OPTIMIZED_ENTRY_FRAME:
430             case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
431             case FrameType::ASM_INTERPRETER_BRIDGE_FRAME: {
432                 break;
433             }
434             default: {
435                 LOG_FULL(FATAL) << "frame type error!";
436                 UNREACHABLE();
437             }
438         }
439     }
440 }
441 
GetAotExceptionFuncName(JSTaggedType * argv) const442 std::string FrameBcCollector::GetAotExceptionFuncName(JSTaggedType* argv) const
443 {
444     JSTaggedValue func = JSTaggedValue(*(argv)); // 3: skip returnaddr and argc
445     Method *method = JSFunction::Cast(func.GetTaggedObject())->GetCallTarget();
446     return method->GetMethodName();
447 }
448 
CollectBCOffsetInfo()449 void FrameBcCollector::CollectBCOffsetInfo()
450 {
451     thread_->GetEcmaVM()->ClearExceptionBCList();
452     JSTaggedType *current = const_cast<JSTaggedType *>(thread_->GetLastLeaveFrame());
453     FrameIterator it(current, thread_);
454     it.Advance<GCVisitedFlag::VISITED>();
455 
456     for (; !it.Done(); it.Advance<GCVisitedFlag::VISITED>()) {
457         FrameType type = it.GetFrameType();
458         switch (type) {
459             case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
460                 auto frame = it.GetFrame<OptimizedJSFunctionFrame>();
461                 kungfu::ConstInfo constInfo;
462                 frame->CollectBCOffsetInfo(it, constInfo);
463                 if (!constInfo.empty()) {
464                     auto name = GetAotExceptionFuncName(frame->GetArgv(it));
465                     thread_->GetEcmaVM()->StoreBCOffsetInfo(name, constInfo[0]);
466                 }
467                 break;
468             }
469             case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME:
470             case FrameType::BUILTIN_CALL_LEAVE_FRAME:
471             case FrameType::LEAVE_FRAME:
472             case FrameType::OPTIMIZED_ENTRY_FRAME:
473             case FrameType::ASM_INTERPRETER_BRIDGE_FRAME:
474             case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
475             case FrameType::ASM_INTERPRETER_FRAME:
476             case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
477             case FrameType::INTERPRETER_FRAME:
478             case FrameType::INTERPRETER_FAST_NEW_FRAME:
479             case FrameType::OPTIMIZED_FRAME:
480             case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME:
481             case FrameType::LEAVE_FRAME_WITH_ARGV:
482             case FrameType::BUILTIN_FRAME_WITH_ARGV:
483             case FrameType::BUILTIN_ENTRY_FRAME:
484             case FrameType::BUILTIN_FRAME:
485             case FrameType::INTERPRETER_ENTRY_FRAME: {
486                 break;
487             }
488             default: {
489                 LOG_FULL(FATAL) << "frame type error!";
490                 UNREACHABLE();
491             }
492         }
493     }
494 }
495 }  // namespace panda::ecmascript
496