• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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 #ifndef PANDA_RUNTIME_ETS_FFI_CLASSES_ETS_METHOD_H_
17 #define PANDA_RUNTIME_ETS_FFI_CLASSES_ETS_METHOD_H_
18 
19 #include <string_view>
20 #include "libpandabase/macros.h"
21 #include "libpandabase/utils/utf.h"
22 #include "libpandafile/file_items.h"
23 #include "runtime/include/class_linker.h"
24 #include "runtime/include/method.h"
25 #include "runtime/include/thread.h"
26 #include "plugins/ets/runtime/ets_modifiers.h"
27 #include "plugins/ets/runtime/ets_vm.h"
28 #include "plugins/ets/runtime/types/ets_class.h"
29 #include "plugins/ets/runtime/types/ets_runtime_linker.h"
30 #include "plugins/ets/runtime/types/ets_string.h"
31 #include "plugins/ets/runtime/types/ets_type.h"
32 #include "plugins/ets/runtime/types/ets_value.h"
33 
34 namespace ark {
35 class Value;
36 }  // namespace ark
37 
38 namespace ark::ets {
39 namespace ani {
40 class ScopedManagedCodeFix;
41 }  // namespace ani
42 namespace napi {
43 class ScopedManagedCodeFix;
44 }  // namespace napi
45 
46 class PandaEtsEnv;
47 
48 class EtsMethod {
49 public:
50     PANDA_PUBLIC_API static EtsMethod *FromTypeDescriptor(const PandaString &td, EtsRuntimeLinker *contextLinker);
51 
52     PANDA_PUBLIC_API static bool IsMethod(const PandaString &td);
53 
54     PANDA_PUBLIC_API EtsValue Invoke(napi::ScopedManagedCodeFix *s, Value *args);
55     PANDA_PUBLIC_API ani_status Invoke(ani::ScopedManagedCodeFix &s, Value *args, EtsValue *result);
56 
InvokeVoid(napi::ScopedManagedCodeFix * s,Value * args)57     void InvokeVoid(napi::ScopedManagedCodeFix *s, Value *args)
58     {
59         Invoke(s, args);
60     }
61 
GetParametersNum()62     uint32_t GetParametersNum() const
63     {
64         if (IsStatic()) {
65             return GetNumArgs();
66         }
67         return GetNumArgs() - 1;
68     }
69 
GetNumArgs()70     uint32_t GetNumArgs() const
71     {
72         return GetPandaMethod()->GetNumArgs();
73     }
74 
75     PANDA_PUBLIC_API uint32_t GetNumArgSlots() const;
76 
77     uint32_t GetNumMandatoryArgs();
78 
GetArgType(size_t idx)79     EtsType GetArgType(size_t idx) const
80     {
81         EtsType etsType = ConvertPandaTypeToEtsType(GetPandaMethod()->GetArgType(idx));
82         if (etsType == EtsType::VOID) {
83             LOG(FATAL, RUNTIME) << "VOID parameter";
84         }
85         return etsType;
86     }
87 
GetReturnValueType()88     EtsType GetReturnValueType() const
89     {
90         panda_file::Type pandaType = GetPandaMethod()->GetReturnType();
91         return ConvertPandaTypeToEtsType(pandaType);
92     }
93 
GetEffectiveArgType(size_t idx)94     EtsType GetEffectiveArgType(size_t idx) const
95     {
96         EtsType etsType = ConvertPandaTypeToEtsType(GetPandaMethod()->GetEffectiveArgType(idx));
97         if (etsType == EtsType::VOID) {
98             LOG(FATAL, RUNTIME) << "VOID parameter";
99         }
100         return etsType;
101     }
102 
GetEffectiveReturnValueType()103     EtsType GetEffectiveReturnValueType() const
104     {
105         panda_file::Type pandaType = GetPandaMethod()->GetEffectiveReturnType();
106         return ConvertPandaTypeToEtsType(pandaType);
107     }
108 
GetRefArgType(size_t idx)109     const char *GetRefArgType(size_t idx) const
110     {
111         return utf::Mutf8AsCString(GetPandaMethod()->GetRefArgType(idx).data);
112     }
113 
GetName()114     const char *GetName() const
115     {
116         return utf::Mutf8AsCString(GetPandaMethod()->GetName().data);
117     }
118 
119     PandaString GetFullName(bool withSignature = false) const
120     {
121         return GetPandaMethod()->GetFullName(withSignature);
122     }
123 
GetNameString()124     EtsString *GetNameString()
125     {
126         auto nameData = GetPandaMethod()->GetName();
127         return EtsString::Resolve(nameData.data, nameData.utf16Length);
128     }
129 
IsStatic()130     bool IsStatic() const
131     {
132         return GetPandaMethod()->IsStatic();
133     }
134 
IsSynthetic()135     bool IsSynthetic() const
136     {
137         return GetPandaMethod()->IsSynthetic();
138     }
139 
140     PANDA_PUBLIC_API bool IsEqualParametersType(EtsArray *params) const;
141 
GetClass()142     EtsClass *GetClass() const
143     {
144         return EtsClass::FromRuntimeClass(GetPandaMethod()->GetClass());
145     }
146 
147     PANDA_PUBLIC_API EtsClass *ResolveArgType(uint32_t idx);
148 
ResolveReturnType()149     EtsClass *ResolveReturnType()
150     {
151         Method::Proto proto = GetPandaMethod()->GetProto();
152         const char *descriptor = proto.GetReturnTypeDescriptor().data();
153         Runtime::GetCurrent()->GetClassLinker();
154         return EtsClass::FromRuntimeClass(Runtime::GetCurrent()->GetClassLinker()->GetClass(
155             utf::CStringAsMutf8(descriptor), false, GetClass()->GetLoadContext()));
156     }
157 
GetVTableID()158     size_t GetVTableID() const
159     {
160         return GetPandaMethod()->GetVTableIndex();
161     }
162 
IsPublic()163     bool IsPublic() const
164     {
165         return GetPandaMethod()->IsPublic();
166     }
167 
IsProtected()168     bool IsProtected() const
169     {
170         return GetPandaMethod()->IsProtected();
171     }
172 
IsPrivate()173     bool IsPrivate() const
174     {
175         return GetPandaMethod()->IsPrivate();
176     }
177 
IsNative()178     bool IsNative() const
179     {
180         return GetPandaMethod()->IsNative();
181     }
182 
IsFastNative()183     bool IsFastNative() const
184     {
185         return (GetAccessFlags() & ACC_FAST_NATIVE) != 0;
186     }
187 
IsCriticalNative()188     bool IsCriticalNative() const
189     {
190         return (GetAccessFlags() & ACC_CRITICAL_NATIVE) != 0;
191     }
192 
IsBoundNativeFunction()193     bool IsBoundNativeFunction() const
194     {
195         ASSERT(!IsIntrinsic());
196         return GetPandaMethod()->GetNativePointer() != nullptr;
197     }
198 
IsFunction()199     bool IsFunction() const
200     {
201         return GetClass()->IsModule();
202     }
203 
IsIntrinsic()204     bool IsIntrinsic() const
205     {
206         return GetPandaMethod()->IsIntrinsic();
207     }
208 
IsDeprecatedNativeAPI()209     bool IsDeprecatedNativeAPI() const
210     {
211         return (GetAccessFlags() & ACC_DEPRECATED_NATIVE_API) != 0;
212     }
213 
IsConstructor()214     bool IsConstructor() const
215     {
216         return GetPandaMethod()->IsConstructor();
217     }
218 
IsInstanceConstructor()219     bool IsInstanceConstructor() const
220     {
221         return GetPandaMethod()->IsInstanceConstructor();
222     }
223 
IsAbstract()224     bool IsAbstract() const
225     {
226         return GetPandaMethod()->IsAbstract();
227     }
228 
IsDeclaredIn(const EtsClass * klass)229     bool IsDeclaredIn(const EtsClass *klass) const
230     {
231         return GetClass() == klass;
232     }
233 
IsGetter()234     bool IsGetter()
235     {
236         auto name = GetNameString();
237         return name->GetMutf8().rfind(GETTER_BEGIN, 0) == 0;
238     }
239 
IsSetter()240     bool IsSetter()
241     {
242         auto name = GetNameString();
243         return name->GetMutf8().rfind(SETTER_BEGIN, 0) == 0;
244     }
245 
RegisterNative(const void * ptr)246     void RegisterNative(const void *ptr)
247     {
248         ASSERT(!IsIntrinsic());
249         ASSERT(IsNative());
250         ASSERT(!IsBoundNativeFunction());
251 
252         Method *m = GetPandaMethod();
253 
254         m->SetNativePointer(const_cast<void *>(ptr));
255     }
256 
RegisterNativeDeprecated(void * impl)257     bool RegisterNativeDeprecated(void *impl)
258     {
259         ASSERT(!IsIntrinsic());
260         ASSERT(IsNative());
261         if (IsBoundNativeFunction()) {
262             return false;
263         }
264 
265         Method *m = GetPandaMethod();
266         m->SetAccessFlags(m->GetAccessFlags() | ACC_DEPRECATED_NATIVE_API);
267         m->SetNativePointer(impl);
268         return true;
269     }
270 
UnregisterNativeDeprecated()271     bool UnregisterNativeDeprecated()
272     {
273         ASSERT(!IsIntrinsic());
274         ASSERT(IsNative());
275         if (!IsBoundNativeFunction()) {
276             return false;
277         }
278 
279         Method *m = GetPandaMethod();
280         m->SetNativePointer(nullptr);
281         m->SetAccessFlags(m->GetAccessFlags() & ~ACC_DEPRECATED_NATIVE_API);
282         return true;
283     }
284 
GetAccessFlags()285     uint32_t GetAccessFlags() const
286     {
287         return GetPandaMethod()->GetAccessFlags();
288     }
289 
GetAccessLevel()290     AccessLevel GetAccessLevel()
291     {
292         if (GetPandaMethod()->IsPublic()) {
293             return AccessLevel::PUBLIC;
294         }
295         if (GetPandaMethod()->IsProtected()) {
296             return AccessLevel::PROTECTED;
297         }
298         if (GetPandaMethod()->IsPrivate()) {
299             return AccessLevel::PRIVATE;
300         }
301         return AccessLevel::DEFAULT;
302     }
303 
GetMethodId()304     uint32_t GetMethodId() const
305     {
306         return GetPandaMethod()->GetFileId().GetOffset();
307     }
308 
309     PANDA_PUBLIC_API EtsMethod *GetOverriddenMethod();
310 
GetLineNumFromBytecodeOffset(uint32_t bcOffset)311     int32_t GetLineNumFromBytecodeOffset(uint32_t bcOffset) const
312     {
313         if (IsNative()) {
314             return -2;  // -2
315         }
316 
317         if (IsAbstract()) {
318             return -1;
319         }
320 
321         return GetPandaMethod()->GetLineNumFromBytecodeOffset(bcOffset);
322     }
323 
GetClassSourceFile()324     panda_file::File::StringData GetClassSourceFile() const
325     {
326         return GetPandaMethod()->GetClassSourceFile();
327     }
328 
FromRuntimeMethod(const Method * method)329     static const EtsMethod *FromRuntimeMethod(const Method *method)
330     {
331         return reinterpret_cast<const EtsMethod *>(method);
332     }
333 
FromRuntimeMethod(Method * method)334     static EtsMethod *FromRuntimeMethod(Method *method)
335     {
336         return reinterpret_cast<EtsMethod *>(method);
337     }
338 
ToRuntimeMethod(EtsMethod * etsMethod)339     static Method *ToRuntimeMethod(EtsMethod *etsMethod)
340     {
341         return reinterpret_cast<Method *>(etsMethod);
342     }
343 
344     EtsMethod() = delete;
345     ~EtsMethod() = delete;
346 
GetPandaMethod()347     const Method *GetPandaMethod() const
348     {
349         return reinterpret_cast<const Method *>(this);
350     }
351 
GetPandaMethod()352     Method *GetPandaMethod()
353     {
354         return reinterpret_cast<Method *>(this);
355     }
356 
GetReturnTypeDescriptor()357     std::string_view GetReturnTypeDescriptor()
358     {
359         return GetPandaMethod()->GetProto().GetReturnTypeDescriptor();
360     }
361 
362     PANDA_PUBLIC_API PandaString GetMethodSignature(bool includeReturnType = true) const;
363 
364     PANDA_PUBLIC_API PandaString GetDescriptor() const;
365 
366     NO_COPY_SEMANTIC(EtsMethod);
367     NO_MOVE_SEMANTIC(EtsMethod);
368 
369 private:
370     std::optional<uint32_t> TryGetMinArgCount();
371 };
372 
373 }  // namespace ark::ets
374 
375 #endif  // PANDA_RUNTIME_ETS_FFI_CLASSES_ETS_METHOD_H_
376