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/core/core_language_context.h"
17
18 #include "runtime/core/core_itable_builder.h"
19 #include "runtime/core/core_vtable_builder.h"
20 #include "runtime/include/vtable_builder_standard-inl.h"
21 #include "runtime/handle_scope-inl.h"
22
23 namespace ark {
24
GetExceptionClass(const uint8_t * mutf8Name,ManagedThread * thread,ClassLinker * classLinker)25 static Class *GetExceptionClass(const uint8_t *mutf8Name, ManagedThread *thread, ClassLinker *classLinker)
26 {
27 auto runtime = Runtime::GetCurrent();
28 LanguageContext ctx = runtime->GetLanguageContext(panda_file::SourceLang::PANDA_ASSEMBLY);
29 auto *extension = classLinker->GetExtension(ctx);
30 auto *cls = classLinker->GetClass(mutf8Name, true, extension->GetBootContext());
31 if (cls == nullptr) {
32 LOG(ERROR, CORE) << "Class " << utf::Mutf8AsCString(mutf8Name) << " not found";
33 return nullptr;
34 }
35
36 if (!classLinker->InitializeClass(thread, cls)) {
37 LOG(ERROR, CORE) << "Class " << utf::Mutf8AsCString(mutf8Name) << " cannot be initialized";
38 return nullptr;
39 }
40 return cls;
41 }
42
ThrowException(ManagedThread * thread,const uint8_t * mutf8Name,const uint8_t * mutf8Msg) const43 void CoreLanguageContext::ThrowException(ManagedThread *thread, const uint8_t *mutf8Name, const uint8_t *mutf8Msg) const
44 {
45 ASSERT(thread == ManagedThread::GetCurrent());
46
47 if (thread->IsUsePreAllocObj()) {
48 thread->SetUsePreAllocObj(false);
49 auto *oom = thread->GetVM()->GetOOMErrorObject();
50 thread->SetException(oom);
51 return;
52 }
53
54 [[maybe_unused]] HandleScope<ObjectHeader *> scope(thread);
55 VMHandle<ObjectHeader> cause(thread, thread->GetException());
56 thread->ClearException();
57
58 auto runtime = Runtime::GetCurrent();
59 LanguageContext ctx = runtime->GetLanguageContext(panda_file::SourceLang::PANDA_ASSEMBLY);
60 auto *classLinker = runtime->GetClassLinker();
61 auto *cls = GetExceptionClass(mutf8Name, thread, classLinker);
62 if (cls == nullptr) {
63 return;
64 }
65
66 VMHandle<ObjectHeader> excHandle(thread, ObjectHeader::Create(cls));
67
68 coretypes::String *msg;
69 if (mutf8Msg != nullptr) {
70 msg = coretypes::String::CreateFromMUtf8(mutf8Msg, ctx, Runtime::GetCurrent()->GetPandaVM());
71 if (UNLIKELY(msg == nullptr)) {
72 // OOM happened during msg allocation
73 ASSERT(thread->HasPendingException());
74 return;
75 }
76 } else {
77 msg = nullptr;
78 }
79 VMHandle<ObjectHeader> msgHandle(thread, msg);
80
81 Method::Proto proto(Method::Proto::ShortyVector {panda_file::Type(panda_file::Type::TypeId::VOID),
82 panda_file::Type(panda_file::Type::TypeId::REFERENCE),
83 panda_file::Type(panda_file::Type::TypeId::REFERENCE)},
84 Method::Proto::RefTypeVector {utf::Mutf8AsCString(ctx.GetStringClassDescriptor()),
85 utf::Mutf8AsCString(ctx.GetObjectClassDescriptor())});
86 auto *ctorName = ctx.GetCtorName();
87 auto *ctor = cls->GetDirectMethod(ctorName, proto);
88 if (ctor == nullptr) {
89 LOG(ERROR, CORE) << "No method " << utf::Mutf8AsCString(ctorName) << " in class "
90 << utf::Mutf8AsCString(mutf8Name);
91 return;
92 }
93
94 constexpr size_t NARGS = 3;
95 std::array<Value, NARGS> args {Value(excHandle.GetPtr()), Value(msgHandle.GetPtr()), Value(cause.GetPtr())};
96 ctor->InvokeVoid(thread, args.data());
97 if (LIKELY(!thread->HasPendingException())) {
98 thread->SetException(excHandle.GetPtr());
99 }
100 }
101
CreateITableBuilder(ClassLinkerErrorHandler * errHandler) const102 PandaUniquePtr<ITableBuilder> CoreLanguageContext::CreateITableBuilder(
103 [[maybe_unused]] ClassLinkerErrorHandler *errHandler) const // CC-OFF(G.FMT.06) false positive
104 {
105 return MakePandaUnique<CoreITableBuilder>();
106 }
107
CreateVTableBuilder(ClassLinkerErrorHandler * errHandler) const108 PandaUniquePtr<VTableBuilder> CoreLanguageContext::CreateVTableBuilder(ClassLinkerErrorHandler *errHandler) const
109 {
110 return MakePandaUnique<CoreVTableBuilder>(errHandler);
111 }
112
CreateVM(Runtime * runtime,const RuntimeOptions & options) const113 PandaVM *CoreLanguageContext::CreateVM(Runtime *runtime, const RuntimeOptions &options) const
114 {
115 auto coreVm = core::PandaCoreVM::Create(runtime, options);
116 if (!coreVm) {
117 LOG(ERROR, CORE) << coreVm.Error();
118 return nullptr;
119 }
120 return coreVm.Value();
121 }
122
CreateGC(mem::GCType gcType,mem::ObjectAllocatorBase * objectAllocator,const mem::GCSettings & settings) const123 mem::GC *CoreLanguageContext::CreateGC(mem::GCType gcType, mem::ObjectAllocatorBase *objectAllocator,
124 const mem::GCSettings &settings) const
125 {
126 return mem::CreateGC<PandaAssemblyLanguageConfig>(gcType, objectAllocator, settings);
127 }
128
ThrowStackOverflowException(ManagedThread * thread) const129 void CoreLanguageContext::ThrowStackOverflowException(ManagedThread *thread) const
130 {
131 auto runtime = Runtime::GetCurrent();
132 auto *classLinker = runtime->GetClassLinker();
133 LanguageContext ctx = runtime->GetLanguageContext(panda_file::SourceLang::PANDA_ASSEMBLY);
134 auto *extension = classLinker->GetExtension(ctx);
135 auto *cls = classLinker->GetClass(ctx.GetStackOverflowErrorClassDescriptor(), true, extension->GetBootContext());
136
137 HandleScope<ObjectHeader *> scope(thread);
138 VMHandle<ObjectHeader> exc(thread, ObjectHeader::Create(cls));
139 thread->SetException(exc.GetPtr());
140 }
141
GetVerificationInitAPI() const142 VerificationInitAPI CoreLanguageContext::GetVerificationInitAPI() const
143 {
144 VerificationInitAPI vApi;
145 vApi.primitiveRootsForVerification = {
146 panda_file::Type::TypeId::TAGGED, panda_file::Type::TypeId::VOID, panda_file::Type::TypeId::U1,
147 panda_file::Type::TypeId::U8, panda_file::Type::TypeId::U16, panda_file::Type::TypeId::U32,
148 panda_file::Type::TypeId::U64, panda_file::Type::TypeId::I8, panda_file::Type::TypeId::I16,
149 panda_file::Type::TypeId::I32, panda_file::Type::TypeId::I64, panda_file::Type::TypeId::F32,
150 panda_file::Type::TypeId::F64};
151
152 vApi.arrayElementsForVerification = {reinterpret_cast<const uint8_t *>("[Z"),
153 reinterpret_cast<const uint8_t *>("[B"),
154 reinterpret_cast<const uint8_t *>("[S"),
155 reinterpret_cast<const uint8_t *>("[C"),
156 reinterpret_cast<const uint8_t *>("[I"),
157 reinterpret_cast<const uint8_t *>("[J"),
158 reinterpret_cast<const uint8_t *>("[F"),
159 reinterpret_cast<const uint8_t *>("[D")
160
161 };
162
163 vApi.isNeedClassSyntheticClass = true;
164 vApi.isNeedObjectSyntheticClass = true;
165 vApi.isNeedStringSyntheticClass = true;
166
167 return vApi;
168 }
169
170 } // namespace ark
171