• 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 <cctype>
17 #include "assembly-type.h"
18 #include "ets_coroutine.h"
19 #include "handle_scope.h"
20 #include "include/mem/panda_containers.h"
21 #include "macros.h"
22 #include "mem/mem.h"
23 #include "mem/vm_handle.h"
24 #include "types/ets_array.h"
25 #include "types/ets_box_primitive.h"
26 #include "types/ets_class.h"
27 #include "types/ets_method.h"
28 #include "types/ets_object.h"
29 #include "types/ets_type.h"
30 #include "types/ets_box_primitive-inl.h"
31 #include "types/ets_type_comptime_traits.h"
32 #include "types/ets_typeapi_create_panda_constants.h"
33 #include "types/ets_typeapi_method.h"
34 #include "runtime/include/value-inl.h"
35 
36 namespace ark::ets::intrinsics {
37 
38 namespace {
39 // NOTE: requires parent handle scope
TypeAPIMethodInvokeImplementation(EtsCoroutine * coro,EtsMethod * meth,EtsObject * recv,EtsArray * args)40 EtsObject *TypeAPIMethodInvokeImplementation(EtsCoroutine *coro, EtsMethod *meth, EtsObject *recv, EtsArray *args)
41 {
42     if (meth->IsAbstract()) {
43         ASSERT(recv != nullptr);
44         meth = recv->GetClass()->ResolveVirtualMethod(meth);
45     }
46     size_t methArgsCount = meth->GetNumArgs();
47     PandaVector<Value> realArgs {methArgsCount};
48     size_t firstRealArg = 0;
49     if (!meth->IsStatic()) {
50         realArgs[0] = Value(recv->GetCoreType());
51         firstRealArg = 1;
52     }
53 
54     size_t argsLength = args->GetLength();
55     if (methArgsCount - firstRealArg != argsLength) {
56         UNREACHABLE();
57     }
58 
59     for (size_t i = 0; i < argsLength; i++) {
60         // issue #14003
61         // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
62         auto arg = args->GetCoreType()->Get<ObjectHeader *>(i);
63         auto argType = meth->GetArgType(firstRealArg + i);
64         if (argType == EtsType::OBJECT) {
65             realArgs[firstRealArg + i] = Value(arg);
66             continue;
67         }
68         EtsPrimitiveTypeEnumToComptimeConstant(argType, [&](auto type) -> void {
69             using T = EtsTypeEnumToCppType<decltype(type)::value>;
70             realArgs[firstRealArg + i] =
71                 Value(EtsBoxPrimitive<T>::FromCoreType(EtsObject::FromCoreType(arg))->GetValue());
72         });
73     }
74 
75     ASSERT(meth->GetPandaMethod()->GetNumArgs() == realArgs.size());
76     auto res = meth->GetPandaMethod()->Invoke(coro, realArgs.data());
77     if (res.IsReference()) {
78         return EtsObject::FromCoreType(res.GetAs<ObjectHeader *>());
79     }
80 
81     if (meth->GetReturnValueType() == EtsType::VOID) {
82         // NOTE(kprokopenko): remove reinterpret_cast when void is synced with runtime
83         return reinterpret_cast<EtsObject *>(EtsCoroutine::GetCurrent()->GetUndefinedObject());
84     }
85 
86     ASSERT(res.IsPrimitive());
87     // CC-OFFNXT(G.FMT.14-CPP) project code style
88     return EtsPrimitiveTypeEnumToComptimeConstant(meth->GetReturnValueType(), [&](auto type) -> EtsObject * {
89         using T = EtsTypeEnumToCppType<decltype(type)::value>;
90         return EtsBoxPrimitive<T>::Create(coro, res.GetAs<T>());
91     });
92 }
93 }  // namespace
94 
95 extern "C" {
TypeAPIMethodInvoke(EtsString * desc,EtsObject * recv,EtsArray * args)96 EtsObject *TypeAPIMethodInvoke(EtsString *desc, EtsObject *recv, EtsArray *args)
97 {
98     auto coro = EtsCoroutine::GetCurrent();
99     [[maybe_unused]] HandleScope<ObjectHeader *> scope {coro};
100     VMHandle<EtsObject> recvHandle {coro, recv->GetCoreType()};
101     VMHandle<EtsArray> argsHandle {coro, args->GetCoreType()};
102     // this method shouldn't trigger gc, because class is loaded,
103     // however static analyzer blames this line
104     auto meth = EtsMethod::FromTypeDescriptor(desc->GetMutf8());
105     return TypeAPIMethodInvokeImplementation(coro, meth, recvHandle.GetPtr(), argsHandle.GetPtr());
106 }
107 
TypeAPIMethodInvokeConstructor(EtsString * desc,EtsArray * args)108 EtsObject *TypeAPIMethodInvokeConstructor(EtsString *desc, EtsArray *args)
109 {
110     auto coro = EtsCoroutine::GetCurrent();
111     [[maybe_unused]] HandleScope<ObjectHeader *> scope {coro};
112     VMHandle<EtsArray> argsHandle {coro, args->GetCoreType()};
113     VMHandle<EtsString> descHandle {coro, desc->GetCoreType()};
114 
115     auto meth = EtsMethod::FromTypeDescriptor(desc->GetMutf8());
116     ASSERT(meth->IsConstructor());
117     auto klass = meth->GetClass()->GetRuntimeClass();
118     auto initedObj = ObjectHeader::Create(coro, klass);
119     ASSERT(initedObj->ClassAddr<Class>() == klass);
120     VMHandle<EtsObject> ret {coro, initedObj};
121     TypeAPIMethodInvokeImplementation(coro, meth, ret.GetPtr(), argsHandle.GetPtr());
122     return ret.GetPtr();
123 }
124 }
125 
126 }  // namespace ark::ets::intrinsics
127