• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "runtime/bridge/bridge.h"
17 
18 #include "libpandafile/bytecode_instruction-inl.h"
19 #include "runtime/entrypoints/entrypoints.h"
20 #include "runtime/include/managed_thread.h"
21 #include "runtime/interpreter/interpreter.h"
22 #include "bytecode_instruction.h"
23 #include "bytecode_instruction-inl.h"
24 
25 namespace panda {
26 
27 // Actually it is wrong signature but it is the only way to make linker don't remove this function
28 extern "C" void CompiledCodeToInterpreterBridge(Method *);
29 extern "C" void CompiledCodeToInterpreterBridgeDyn(Method *);
30 extern "C" void AbstractMethodStub();
31 
GetCompiledCodeToInterpreterBridge(const Method * method)32 const void *GetCompiledCodeToInterpreterBridge(const Method *method)
33 {
34     ASSERT(method != nullptr);
35     const void *bridge = nullptr;
36 
37     if (method->GetClass() == nullptr) {
38         bridge = reinterpret_cast<const void *>(CompiledCodeToInterpreterBridgeDyn);
39     } else {
40         if (method->GetClass()->GetSourceLang() == panda_file::SourceLang::ECMASCRIPT) {
41             bridge = reinterpret_cast<const void *>(CompiledCodeToInterpreterBridgeDyn);
42         } else {
43             bridge = reinterpret_cast<const void *>(CompiledCodeToInterpreterBridge);
44         }
45     }
46     return bridge;
47 }
48 
49 /**
50  * This function is supposed to be called from the deoptimization code. It aims to call interpreter for given frame
51  * from specific pc. Note, that it releases input interpreter's frame at the exit.
52  */
InvokeInterpreter(ManagedThread * thread,const uint8_t * pc,Frame * frame,Frame * last_frame)53 extern "C" int64_t InvokeInterpreter(ManagedThread *thread, const uint8_t *pc, Frame *frame, Frame *last_frame)
54 {
55     bool prev_frame_kind = thread->IsCurrentFrameCompiled();
56     thread->SetCurrentFrame(frame);
57     thread->SetCurrentFrameIsCompiled(false);
58     LOG(DEBUG, INTEROP) << "InvokeInterpreter for method: " << frame->GetMethod()->GetFullName();
59 
60     interpreter::Execute(thread, pc, frame, thread->HasPendingException());
61 
62     auto acc = frame->GetAcc();
63     auto res = acc.HasObject() ? static_cast<int64_t>(bit_cast<uintptr_t>(acc.GetReference())) : acc.GetLong();
64 
65     auto prev_frame = frame->GetPrevFrame();
66     thread->SetCurrentFrame(prev_frame);
67     FreeFrame(frame);
68 
69     // We need to execute (find catch block) in all inlined methods. For this we use the number of inlined method.
70     // Else we can execute previous interpreter frames and we will FreeFrames in incorrect order.
71     while (prev_frame != nullptr && last_frame != frame) {
72         ASSERT(!StackWalker::IsBoundaryFrame<FrameKind::INTERPRETER>(prev_frame));
73         frame = prev_frame;
74         LOG(DEBUG, INTEROP) << "InvokeInterpreter for method: " << frame->GetMethod()->GetFullName();
75         prev_frame = frame->GetPrevFrame();
76         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
77         pc = frame->GetMethod()->GetInstructions() + frame->GetBytecodeOffset();
78         if (!thread->HasPendingException()) {
79             auto bc_inst = BytecodeInstruction(pc);
80             auto opcode = bc_inst.GetOpcode();
81             // Compiler splits InitObj to NewObject + CallStatic
82             // if we have a deoptimization occurred in the CallStatic, we must not copy acc from CallStatic,
83             // because acc contains result of the NewObject
84             if (opcode != BytecodeInstruction::Opcode::INITOBJ_SHORT_V4_V4_ID16 &&
85                 opcode != BytecodeInstruction::Opcode::INITOBJ_V4_V4_V4_V4_ID16 &&
86                 opcode != BytecodeInstruction::Opcode::INITOBJ_RANGE_V8_ID16) {
87                 frame->GetAcc() = acc;
88             }
89             pc = bc_inst.GetNext().GetAddress();
90         } else {
91             frame->GetAcc() = acc;
92         }
93         interpreter::Execute(thread, pc, frame, thread->HasPendingException());
94 
95         acc = frame->GetAcc();
96         res = acc.HasObject() ? static_cast<int64_t>(bit_cast<uintptr_t>(acc.GetReference())) : acc.GetLong();
97 
98         thread->SetCurrentFrame(prev_frame);
99         FreeFrame(frame);
100     }
101     thread->SetCurrentFrameIsCompiled(prev_frame_kind);
102 
103     return res;
104 }
105 
106 }  // namespace panda
107