• 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/compiler/aot_file/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(IsInterpretedFrame());
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_FAST_CALL_FUNCTION_FRAME:
187             case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
188                 auto *frame = OptimizedJSFunctionFrame::GetFrameFromSp(sp_);
189                 return frame->GetFunction();
190             }
191             case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME :
192             case FrameType::INTERPRETER_FRAME:
193             case FrameType::INTERPRETER_FAST_NEW_FRAME:
194             case FrameType::INTERPRETER_ENTRY_FRAME:
195             case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
196             case FrameType::ASM_INTERPRETER_BRIDGE_FRAME:
197             case FrameType::INTERPRETER_BUILTIN_FRAME:
198             case FrameType::OPTIMIZED_FRAME:
199             case FrameType::ASM_BRIDGE_FRAME:
200             case FrameType::LEAVE_FRAME:
201             case FrameType::LEAVE_FRAME_WITH_ARGV:
202             case FrameType::BUILTIN_CALL_LEAVE_FRAME:
203             case FrameType::OPTIMIZED_ENTRY_FRAME:
204             default: {
205                 LOG_FULL(FATAL) << "frame type error!";
206                 UNREACHABLE();
207             }
208         }
209     } else {
210         FrameType type = GetFrameType();
211         if (type == FrameType::INTERPRETER_FRAME || type == FrameType::INTERPRETER_FAST_NEW_FRAME) {
212             auto *frame = InterpretedFrame::GetFrameFromSp(sp_);
213             return frame->function;
214         } else {
215             auto *frame = InterpretedBuiltinFrame::GetFrameFromSp(sp_);
216             return frame->function;
217         }
218     }
219 }
220 
GetPc() const221 const uint8_t *FrameHandler::GetPc() const
222 {
223     ASSERT(IsJSFrame());
224     FrameIterator it(sp_, thread_);
225     if (IsAsmInterpretedFrame()) {
226         auto *frame = it.GetFrame<AsmInterpretedFrame>();
227         return frame->GetPc();
228     } else {
229         auto *frame = it.GetFrame<InterpretedFrame>();
230         return frame->GetPc();
231     }
232 }
233 
GetConstpool() const234 ConstantPool *FrameHandler::GetConstpool() const
235 {
236     ASSERT(IsInterpretedFrame());
237     auto method = GetMethod();
238     JSTaggedValue constpool = method->GetConstantPool();
239     return ConstantPool::Cast(constpool.GetTaggedObject());
240 }
241 
GetEnv() const242 JSTaggedValue FrameHandler::GetEnv() const
243 {
244     ASSERT(IsInterpretedFrame());
245     FrameIterator it(sp_, thread_);
246     if (IsAsmInterpretedFrame()) {
247         auto *frame = it.GetFrame<AsmInterpretedFrame>();
248         return frame->GetEnv();
249     } else {
250         auto *frame = it.GetFrame<InterpretedFrame>();
251         return frame->env;
252     }
253 }
254 
DumpStack(std::ostream & os) const255 void FrameHandler::DumpStack(std::ostream &os) const
256 {
257     size_t i = 0;
258     FrameHandler frameHandler(thread_);
259     for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) {
260         os << "[" << i++
261         << "]:" << frameHandler.GetMethod()->ParseFunctionName()
262         << "\n";
263     }
264 }
265 
DumpPC(std::ostream & os,const uint8_t * pc) const266 void FrameHandler::DumpPC(std::ostream &os, const uint8_t *pc) const
267 {
268     FrameHandler frameHandler(thread_);
269     ASSERT(frameHandler.HasFrame());
270     // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions, bugprone-narrowing-conversions)
271     int offset = pc - frameHandler.GetMethod()->GetBytecodeArray();
272     os << "offset: " << offset << "\n";
273 }
274 
GetInterpretedFrameEnd(JSTaggedType * prevSp) const275 ARK_INLINE uintptr_t FrameHandler::GetInterpretedFrameEnd(JSTaggedType *prevSp) const
276 {
277     uintptr_t end = 0U;
278     FrameIterator it(prevSp, thread_);
279     FrameType type = it.GetFrameType();
280     switch (type) {
281         case FrameType::ASM_INTERPRETER_FRAME:
282         case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
283             auto frame = it.GetFrame<AsmInterpretedFrame>();
284             end = ToUintPtr(frame);
285             break;
286         }
287         case FrameType::INTERPRETER_FRAME:
288         case FrameType::INTERPRETER_FAST_NEW_FRAME: {
289             auto frame = it.GetFrame<InterpretedFrame>();
290             end = ToUintPtr(frame);
291             break;
292         }
293         case FrameType::INTERPRETER_ENTRY_FRAME: {
294             auto frame = it.GetFrame<InterpretedEntryFrame>();
295             end = ToUintPtr(frame);
296             break;
297         }
298         case FrameType::INTERPRETER_BUILTIN_FRAME: {
299             auto frame = it.GetFrame<InterpretedBuiltinFrame>();
300             end = ToUintPtr(frame);
301             break;
302         }
303         case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME :
304         case FrameType::BUILTIN_FRAME_WITH_ARGV:
305         case FrameType::BUILTIN_ENTRY_FRAME:
306         case FrameType::BUILTIN_FRAME:
307         case FrameType::OPTIMIZED_FRAME:
308         case FrameType::ASM_BRIDGE_FRAME:
309         case FrameType::LEAVE_FRAME:
310         case FrameType::LEAVE_FRAME_WITH_ARGV:
311         case FrameType::BUILTIN_CALL_LEAVE_FRAME:
312         case FrameType::OPTIMIZED_ENTRY_FRAME:
313         case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
314         case FrameType::ASM_INTERPRETER_BRIDGE_FRAME:
315         default: {
316             LOG_FULL(FATAL) << "frame type error!";
317             UNREACHABLE();
318         }
319     }
320     return end;
321 }
322 
IterateAssembleStack(const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor)323 void FrameHandler::IterateAssembleStack(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
324     const RootBaseAndDerivedVisitor &derivedVisitor)
325 {
326     JSTaggedType *current = const_cast<JSTaggedType *>(thread_->GetLastLeaveFrame());
327     IterateFrameChain(current, visitor, rangeVisitor, derivedVisitor);
328 }
329 
330 // We seperate InterpretedEntryFrame from assemble stack when asm interpreter is enable.
331 // To protect EcmaRuntimeCallInfo on InterpretedEntryFrame, we iterate InterpretedEntryFrame on thread sp individually.
332 // And only InterpretedEntryFrame is on thread sp when asm interpreter is enable.
IterateEcmaRuntimeCallInfo(const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor)333 void FrameHandler::IterateEcmaRuntimeCallInfo(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor)
334 {
335     ASSERT(thread_->IsAsmInterpreter());
336     JSTaggedType *current = const_cast<JSTaggedType *>(thread_->GetCurrentSPFrame());
337     for (FrameIterator it(current, thread_); !it.Done(); it.Advance()) {
338         ASSERT(it.GetFrameType() == FrameType::INTERPRETER_ENTRY_FRAME);
339         auto frame = it.GetFrame<InterpretedEntryFrame>();
340         frame->GCIterate(it, visitor, rangeVisitor);
341     }
342 }
343 
Iterate(const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor)344 void FrameHandler::Iterate(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
345     const RootBaseAndDerivedVisitor &derivedVisitor)
346 {
347     if (thread_->IsAsmInterpreter()) {
348         IterateEcmaRuntimeCallInfo(visitor, rangeVisitor);
349         IterateAssembleStack(visitor, rangeVisitor, derivedVisitor);
350         return;
351     }
352     JSTaggedType *current = const_cast<JSTaggedType *>(thread_->GetCurrentSPFrame());
353     FrameType frameType = FrameHandler::GetFrameType(current);
354     if (frameType != FrameType::INTERPRETER_ENTRY_FRAME) {
355         auto leaveFrame = const_cast<JSTaggedType *>(thread_->GetLastLeaveFrame());
356         if (leaveFrame != nullptr) {
357             current = leaveFrame;
358         }
359     }
360     // lazy assignment: only Iterate need arkStackMapParser_ in order to high improve performance
361     if (arkStackMapParser_ == nullptr) {
362         arkStackMapParser_ =
363             const_cast<JSThread *>(thread_)->GetCurrentEcmaContext()->GetAOTFileManager()->GetStackMapParser();
364     }
365     IterateFrameChain(current, visitor, rangeVisitor, derivedVisitor);
366 }
367 
IterateFrameChain(JSTaggedType * start,const RootVisitor & visitor,const RootRangeVisitor & rangeVisitor,const RootBaseAndDerivedVisitor & derivedVisitor) const368 void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &visitor,
369     const RootRangeVisitor &rangeVisitor, const RootBaseAndDerivedVisitor &derivedVisitor) const
370 {
371     JSTaggedType *current = start;
372     for (FrameIterator it(current, thread_); !it.Done(); it.Advance<GCVisitedFlag::VISITED>()) {
373         FrameType type = it.GetFrameType();
374         switch (type) {
375             case FrameType::OPTIMIZED_FRAME: {
376                 auto frame = it.GetFrame<OptimizedFrame>();
377                 frame->GCIterate(it, visitor, rangeVisitor, derivedVisitor);
378                 break;
379             }
380             case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
381             case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
382                 auto frame = it.GetFrame<OptimizedJSFunctionFrame>();
383                 frame->GCIterate(it, visitor, rangeVisitor, derivedVisitor, type);
384                 break;
385             }
386             case FrameType::ASM_INTERPRETER_FRAME:
387             case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
388                 auto frame = it.GetFrame<AsmInterpretedFrame>();
389                 frame->GCIterate(it, visitor, rangeVisitor, derivedVisitor);
390                 break;
391             }
392             case FrameType::INTERPRETER_FRAME:
393             case FrameType::INTERPRETER_FAST_NEW_FRAME: {
394                 auto frame = it.GetFrame<InterpretedFrame>();
395                 frame->GCIterate(it, visitor, rangeVisitor);
396                 break;
397             }
398             case FrameType::INTERPRETER_BUILTIN_FRAME: {
399                 auto frame = it.GetFrame<InterpretedBuiltinFrame>();
400                 frame->GCIterate(it, visitor, rangeVisitor);
401                 break;
402             }
403             case FrameType::LEAVE_FRAME: {
404                 auto frame = it.GetFrame<OptimizedLeaveFrame>();
405                 frame->GCIterate(it, visitor, rangeVisitor);
406                 break;
407             }
408             case FrameType::LEAVE_FRAME_WITH_ARGV: {
409                 auto frame = it.GetFrame<OptimizedWithArgvLeaveFrame>();
410                 frame->GCIterate(it, visitor, rangeVisitor);
411                 break;
412             }
413             case FrameType::BUILTIN_CALL_LEAVE_FRAME: {
414                 auto frame = it.GetFrame<OptimizedBuiltinLeaveFrame>();
415                 frame->GCIterate(it, visitor, rangeVisitor);
416                 break;
417             }
418             case FrameType::BUILTIN_FRAME_WITH_ARGV: {
419                 auto frame = it.GetFrame<BuiltinWithArgvFrame>();
420                 frame->GCIterate(it, visitor, rangeVisitor);
421                 break;
422             }
423             case FrameType::BUILTIN_ENTRY_FRAME:
424             case FrameType::BUILTIN_FRAME: {
425                 auto frame = it.GetFrame<BuiltinFrame>();
426                 frame->GCIterate(it, visitor, rangeVisitor);
427                 break;
428             }
429             case FrameType::INTERPRETER_ENTRY_FRAME: {
430                 auto frame = it.GetFrame<InterpretedEntryFrame>();
431                 frame->GCIterate(it, visitor, rangeVisitor);
432                 break;
433             }
434             case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME:
435             case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME:
436             case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME:
437             case FrameType::OPTIMIZED_ENTRY_FRAME:
438             case FrameType::ASM_BRIDGE_FRAME:
439             case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
440             case FrameType::ASM_INTERPRETER_BRIDGE_FRAME: {
441                 break;
442             }
443             default: {
444                 LOG_FULL(FATAL) << "frame type error!";
445                 UNREACHABLE();
446             }
447         }
448     }
449 }
450 }  // namespace panda::ecmascript
451