• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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 "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/include/panda_vm.h"
22 #include "runtime/interpreter/interpreter.h"
23 #include "bytecode_instruction.h"
24 #include "bytecode_instruction-inl.h"
25 
26 namespace panda {
27 // Actualy it is wrong signature but it is 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 extern "C" void DefaultConflictMethodStub();
32 
GetCompiledCodeToInterpreterBridge(const Method * method)33 const void *GetCompiledCodeToInterpreterBridge(const Method *method)
34 {
35     ASSERT(method != nullptr);
36     const void *bridge = nullptr;
37 
38     if (method->GetClass() == nullptr) {
39         bridge = reinterpret_cast<const void *>(CompiledCodeToInterpreterBridgeDyn);
40     } else {
41         if (panda::panda_file::IsDynamicLanguage(method->GetClass()->GetSourceLang())) {
42             bridge = reinterpret_cast<const void *>(CompiledCodeToInterpreterBridgeDyn);
43         } else {
44             bridge = reinterpret_cast<const void *>(CompiledCodeToInterpreterBridge);
45         }
46     }
47     return bridge;
48 }
49 
GetCompiledCodeToInterpreterBridge()50 const void *GetCompiledCodeToInterpreterBridge()
51 {
52     return reinterpret_cast<const void *>(CompiledCodeToInterpreterBridge);
53 }
54 
GetCompiledCodeToInterpreterBridgeDyn()55 const void *GetCompiledCodeToInterpreterBridgeDyn()
56 {
57     return reinterpret_cast<const void *>(CompiledCodeToInterpreterBridgeDyn);
58 }
59 
60 template <class VRegRef>
GetVRegValue(VRegRef reg)61 static inline int64_t GetVRegValue(VRegRef reg)
62 {
63     return reg.HasObject() ? static_cast<int64_t>(bit_cast<uintptr_t>(reg.GetReference())) : reg.GetLong();
64 }
65 
66 /**
67  * This function supposed to be called from the deoptimization code. It aims to call interpreter for given frame from
68  * specific pc. Note, that it releases input interpreter's frame at the exit.
69  */
InvokeInterpreter(ManagedThread * thread,const uint8_t * pc,Frame * frame,Frame * last_frame)70 extern "C" int64_t InvokeInterpreter(ManagedThread *thread, const uint8_t *pc, Frame *frame, Frame *last_frame)
71 {
72     bool prev_frame_kind = thread->IsCurrentFrameCompiled();
73     thread->SetCurrentFrame(frame);
74     thread->SetCurrentFrameIsCompiled(false);
75     LOG(DEBUG, INTEROP) << "InvokeInterpreter for method: " << frame->GetMethod()->GetFullName();
76 
77     interpreter::Execute(thread, pc, frame, thread->HasPendingException());
78 
79     int64_t res;
80     auto acc = frame->GetAcc();
81     if (frame->IsDynamic()) {
82         res = GetVRegValue(acc.template AsVRegRef<true>());
83     } else {
84         res = GetVRegValue(acc.AsVRegRef());
85     }
86 
87     auto prev_frame = frame->GetPrevFrame();
88     thread->SetCurrentFrame(prev_frame);
89     thread->GetVM()->GetLanguageContext().DeoptimizeEnd();
90     FreeFrame(frame);
91 
92     // We need to execute(find catch block) in all inlined methods. For this we use number of inlined method
93     // Else we can execute previus interpreter frames and we will FreeFrames in incorrect order
94     while (prev_frame != nullptr && last_frame != frame) {
95         ASSERT(!StackWalker::IsBoundaryFrame<FrameKind::INTERPRETER>(prev_frame));
96         frame = prev_frame;
97         LOG(DEBUG, INTEROP) << "InvokeInterpreter for method: " << frame->GetMethod()->GetFullName();
98         prev_frame = frame->GetPrevFrame();
99         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
100         pc = frame->GetMethod()->GetInstructions() + frame->GetBytecodeOffset();
101         if (!thread->HasPendingException()) {
102             auto bc_inst = BytecodeInstruction(pc);
103             auto opcode = bc_inst.GetOpcode();
104             // Compiler splites InitObj to NewObject + CallStatic
105             // if we have an deoptimization occurred in the CallStatic, we must not copy acc from CallStatic,
106             // because acc contain result of the NewObject
107             if (opcode != BytecodeInstruction::Opcode::INITOBJ_SHORT_V4_V4_ID16 &&
108                 opcode != BytecodeInstruction::Opcode::INITOBJ_V4_V4_V4_V4_ID16 &&
109                 opcode != BytecodeInstruction::Opcode::INITOBJ_RANGE_V8_ID16) {
110                 frame->GetAcc() = acc;
111             }
112             pc = bc_inst.GetNext().GetAddress();
113         } else {
114             frame->GetAcc() = acc;
115         }
116         interpreter::Execute(thread, pc, frame, thread->HasPendingException());
117 
118         acc = frame->GetAcc();
119         if (frame->IsDynamic()) {
120             res = GetVRegValue(acc.template AsVRegRef<true>());
121         } else {
122             res = GetVRegValue(acc.AsVRegRef());
123         }
124 
125         thread->SetCurrentFrame(prev_frame);
126         thread->GetVM()->GetLanguageContext().DeoptimizeEnd();
127         FreeFrame(frame);
128     }
129     thread->SetCurrentFrameIsCompiled(prev_frame_kind);
130 
131     return res;
132 }
133 
GetAbstractMethodStub()134 const void *GetAbstractMethodStub()
135 {
136     return reinterpret_cast<const void *>(AbstractMethodStub);
137 }
138 
GetDefaultConflictMethodStub()139 const void *GetDefaultConflictMethodStub()
140 {
141     return reinterpret_cast<const void *>(DefaultConflictMethodStub);
142 }
143 }  // namespace panda
144