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