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