1 /**
2 * Copyright (c) 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/include/vtable_builder_base-inl.h"
17
18 namespace ark {
19
OnVTableConflict(ClassLinkerErrorHandler * errHandler,ClassLinker::Error error,std::string_view msg,MethodInfo const * info1,MethodInfo const * info2)20 void OnVTableConflict(ClassLinkerErrorHandler *errHandler, ClassLinker::Error error, std::string_view msg,
21 MethodInfo const *info1, MethodInfo const *info2)
22 {
23 if (errHandler == nullptr) {
24 return;
25 }
26 auto res = PandaString(msg) + " ";
27 res += utf::Mutf8AsCString(info1->GetClassName());
28 res += utf::Mutf8AsCString(info1->GetName().data);
29 res += " ";
30 res += utf::Mutf8AsCString(info2->GetClassName());
31 res += utf::Mutf8AsCString(info2->GetName().data);
32 errHandler->OnError(error, res);
33 }
34
OnVTableConflict(ClassLinkerErrorHandler * errHandler,ClassLinker::Error error,std::string_view msg,Method const * info1,Method const * info2)35 void OnVTableConflict(ClassLinkerErrorHandler *errHandler, ClassLinker::Error error, std::string_view msg,
36 Method const *info1, Method const *info2)
37 {
38 if (errHandler == nullptr) {
39 return;
40 }
41 auto res = PandaString(msg) + " ";
42 res += utf::Mutf8AsCString(info1->GetClassName().data);
43 res += utf::Mutf8AsCString(info1->GetName().data);
44 res += " ";
45 res += utf::Mutf8AsCString(info2->GetClassName().data);
46 res += utf::Mutf8AsCString(info2->GetName().data);
47 errHandler->OnError(error, res);
48 }
49
DumpMappings()50 void VTableInfo::DumpMappings()
51 {
52 #ifndef NDEBUG
53 auto const dumpMethodInfo = [](PandaStringStream &ss, MethodInfo const *info) {
54 ss << info << " " << info->GetClassName() << " " << info->GetName().data;
55 };
56
57 for (auto const &[info, entry] : vmethods_) {
58 PandaStringStream ss;
59 ss << "[" << entry.GetIndex() << "] ";
60 dumpMethodInfo(ss, info);
61 if (entry.GetCandidate() != nullptr) {
62 ss << " -> ";
63 dumpMethodInfo(ss, entry.GetCandidate());
64 }
65 LOG(DEBUG, CLASS_LINKER) << "\t" << ss.str() << "\n";
66 }
67 #endif // NDEBUG
68 }
69
DumpVTable(Class * klass)70 void VTableInfo::DumpVTable([[maybe_unused]] Class *klass)
71 {
72 #ifndef NDEBUG
73 LOG(DEBUG, CLASS_LINKER) << "vtable of class " << klass->GetName() << ":";
74 auto vtable = klass->GetVTable();
75 size_t idx = 0;
76 for (auto *method : vtable) {
77 LOG(DEBUG, CLASS_LINKER) << "[" << idx++ << "] " << method->GetFullName();
78 }
79 #endif // NDEBUG
80 }
81
UpdateClass(Class * klass) const82 void VTableInfo::UpdateClass(Class *klass) const
83 {
84 auto vtable = klass->GetVTable();
85 ASSERT(vtable.size() == GetVTableSize());
86
87 auto const setAtIdx = [this, klass, &vtable](MethodInfo const *info, size_t idx) {
88 Method *method = info->GetMethod();
89 if (method == nullptr) {
90 method = &klass->GetVirtualMethods()[info->GetVirtualMethodIndex()];
91 } else if (info->IsInterfaceMethod() && !info->IsBase()) {
92 auto it = copiedMethods_.find(info);
93 ASSERT(it != copiedMethods_.end());
94 method = &klass->GetCopiedMethods()[it->second.GetIndex()];
95 } else if (info->IsBase()) {
96 vtable[idx] = method;
97 return;
98 }
99 method->SetVTableIndex(idx);
100 vtable[idx] = method;
101 };
102
103 for (const auto &[info, entry] : vmethods_) {
104 setAtIdx(entry.CandidateOr(info), entry.GetIndex());
105 }
106 for (const auto &[info, entry] : copiedMethods_) {
107 Method *method = &klass->GetCopiedMethods()[entry.GetIndex()];
108 size_t vtableIdx = vmethods_.size() + entry.GetIndex();
109 method->SetVTableIndex(vtableIdx);
110 vtable[vtableIdx] = method;
111 }
112
113 DumpVTable(klass);
114 }
115
116 } // namespace ark
117