1 /**
2 * Copyright (c) 2023-2025 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 "plugins/ets/runtime/ets_annotation.h"
17 #include "plugins/ets/runtime/ets_class_linker.h"
18 #include "plugins/ets/runtime/ets_class_linker_extension.h"
19 #include "plugins/ets/runtime/ets_coroutine.h"
20 #include "plugins/ets/runtime/ets_exceptions.h"
21 #include "plugins/ets/runtime/ets_panda_file_items.h"
22 #include "plugins/ets/runtime/types/ets_class.h"
23 #include "types/ets_field.h"
24
25 namespace ark::ets {
26
EtsClassLinker(ClassLinker * classLinker)27 EtsClassLinker::EtsClassLinker(ClassLinker *classLinker) : classLinker_(classLinker) {}
28
29 /*static*/
Create(ClassLinker * classLinker)30 Expected<PandaUniquePtr<EtsClassLinker>, PandaString> EtsClassLinker::Create(ClassLinker *classLinker)
31 {
32 PandaUniquePtr<EtsClassLinker> etsClassLinker = MakePandaUnique<EtsClassLinker>(classLinker);
33 return Expected<PandaUniquePtr<EtsClassLinker>, PandaString>(std::move(etsClassLinker));
34 }
35
Initialize()36 bool EtsClassLinker::Initialize()
37 {
38 ClassLinkerExtension *ext = classLinker_->GetExtension(panda_file::SourceLang::ETS);
39 ext_ = EtsClassLinkerExtension::FromCoreType(ext);
40 return true;
41 }
42
InitializeClass(EtsCoroutine * coroutine,EtsClass * klass)43 bool EtsClassLinker::InitializeClass(EtsCoroutine *coroutine, EtsClass *klass)
44 {
45 ASSERT(klass != nullptr);
46 return classLinker_->InitializeClass(coroutine, klass->GetRuntimeClass());
47 }
48
GetClassRoot(EtsClassRoot root) const49 EtsClass *EtsClassLinker::GetClassRoot(EtsClassRoot root) const
50 {
51 return EtsClass::FromRuntimeClass(ext_->GetClassRoot(static_cast<ark::ClassRoot>(root)));
52 }
53
GetClass(const char * name,bool needCopyDescriptor,ClassLinkerContext * classLinkerContext,ClassLinkerErrorHandler * errorHandler)54 EtsClass *EtsClassLinker::GetClass(const char *name, bool needCopyDescriptor, ClassLinkerContext *classLinkerContext,
55 ClassLinkerErrorHandler *errorHandler)
56 {
57 const uint8_t *classDescriptor = utf::CStringAsMutf8(name);
58 Class *cls = ext_->GetClass(classDescriptor, needCopyDescriptor, classLinkerContext, errorHandler);
59 return LIKELY(cls != nullptr) ? EtsClass::FromRuntimeClass(cls) : nullptr;
60 }
61
GetClass(const panda_file::File & pf,panda_file::File::EntityId id,ClassLinkerContext * classLinkerContext,ClassLinkerErrorHandler * errorHandler)62 EtsClass *EtsClassLinker::GetClass(const panda_file::File &pf, panda_file::File::EntityId id,
63 ClassLinkerContext *classLinkerContext, ClassLinkerErrorHandler *errorHandler)
64 {
65 Class *cls = ext_->GetClass(pf, id, classLinkerContext, errorHandler);
66 return LIKELY(cls != nullptr) ? EtsClass::FromRuntimeClass(cls) : nullptr;
67 }
68
GetMethod(const panda_file::File & pf,panda_file::File::EntityId id,ClassLinkerContext * classLinkerContext,ClassLinkerErrorHandler * errorHandler)69 Method *EtsClassLinker::GetMethod(const panda_file::File &pf, panda_file::File::EntityId id,
70 ClassLinkerContext *classLinkerContext, ClassLinkerErrorHandler *errorHandler)
71 {
72 return classLinker_->GetMethod(pf, id, classLinkerContext, errorHandler);
73 }
74
GetAsyncImplMethod(Method * method,EtsCoroutine * coroutine)75 Method *EtsClassLinker::GetAsyncImplMethod(Method *method, EtsCoroutine *coroutine)
76 {
77 ASSERT(method != nullptr);
78 panda_file::File::EntityId asyncAnnId = EtsAnnotation::FindAsyncAnnotation(method);
79 ASSERT(asyncAnnId.IsValid());
80 const panda_file::File &pf = *method->GetPandaFile();
81 panda_file::AnnotationDataAccessor ada(pf, asyncAnnId);
82 auto implMethodId = ada.GetElement(0).GetScalarValue().Get<panda_file::File::EntityId>();
83 auto *ctx = method->GetClass()->GetLoadContext();
84 Method *result = GetMethod(pf, implMethodId, ctx);
85 if (result == nullptr) {
86 panda_file::MethodDataAccessor mda(pf, implMethodId);
87 PandaStringStream out;
88 out << "Cannot resolve async method " << mda.GetFullName();
89 ThrowEtsException(coroutine, panda_file_items::class_descriptors::LINKER_UNRESOLVED_METHOD_ERROR, out.str());
90 }
91 return result;
92 }
93
94 } // namespace ark::ets
95