1 /** 2 * Copyright (c) 2021-2022 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_PLUGINS_ETS_RUNTIME_FFI_CLASSES_ETS_CLASS_H 17 #define PANDA_PLUGINS_ETS_RUNTIME_FFI_CLASSES_ETS_CLASS_H 18 19 #include <cstdint> 20 #include "include/mem/panda_containers.h" 21 #include "include/object_header.h" 22 #include "include/runtime.h" 23 #include "libpandabase/mem/object_pointer.h" 24 #include "runtime/class_linker_context.h" 25 #include "runtime/include/class-inl.h" 26 #include "runtime/include/thread.h" 27 #include "runtime/include/class_linker.h" 28 #include "plugins/ets/runtime/types/ets_field.h" 29 #include "plugins/ets/runtime/types/ets_type.h" 30 #include "plugins/ets/runtime/ets_panda_file_items.h" 31 32 namespace panda::ets { 33 34 enum class AccessLevel { PUBLIC, PROTECTED, DEFAULT, PRIVATE }; 35 36 class EtsMethod; 37 class EtsObject; 38 class EtsVoid; 39 class EtsString; 40 class EtsArray; 41 class EtsPromise; 42 class EtsTypeAPIField; 43 class EtsTypeAPIMethod; 44 class EtsTypeAPIParameter; 45 46 enum class EtsType; 47 48 class EtsClass { 49 public: 50 // We shouldn't init header_ here - because it has been memset(0) in object allocation, 51 // otherwise it may cause data race while visiting object's class concurrently in gc. InitClass(const uint8_t * descriptor,uint32_t vtableSize,uint32_t imtSize,uint32_t klassSize)52 void InitClass(const uint8_t *descriptor, uint32_t vtableSize, uint32_t imtSize, uint32_t klassSize) 53 { 54 new (&klass_) panda::Class(descriptor, panda_file::SourceLang::ETS, vtableSize, imtSize, klassSize); 55 } 56 GetDescriptor()57 const char *GetDescriptor() const 58 { 59 return reinterpret_cast<const char *>(GetRuntimeClass()->GetDescriptor()); 60 } 61 62 PANDA_PUBLIC_API EtsClass *GetBase(); 63 64 uint32_t GetFieldsNumber(); 65 66 uint32_t GetOwnFieldsNumber(); // Without inherited fields 67 GetStaticFieldsNumber()68 uint32_t GetStaticFieldsNumber() 69 { 70 return GetRuntimeClass()->GetStaticFields().size(); 71 } 72 GetInstanceFieldsNumber()73 uint32_t GetInstanceFieldsNumber() 74 { 75 return GetRuntimeClass()->GetInstanceFields().size(); 76 } 77 78 uint32_t GetFieldIndexByName(const char *name); 79 80 PANDA_PUBLIC_API PandaVector<EtsField *> GetFields(); 81 82 EtsField *GetFieldByIndex(uint32_t i); 83 84 EtsField *GetFieldIDByOffset(uint32_t fieldOffset); 85 EtsField *GetFieldByName(EtsString *name); 86 PANDA_PUBLIC_API EtsField *GetFieldIDByName(const char *name, const char *sig = nullptr); 87 88 EtsField *GetOwnFieldByIndex(uint32_t i); 89 EtsField *GetDeclaredFieldIDByName(const char *name); 90 91 PANDA_PUBLIC_API EtsField *GetStaticFieldIDByName(const char *name, const char *sig = nullptr); 92 EtsField *GetStaticFieldIDByOffset(uint32_t fieldOffset); 93 94 PANDA_PUBLIC_API EtsMethod *GetDirectMethod(const char *name); 95 PANDA_PUBLIC_API EtsMethod *GetDirectMethod(const uint8_t *name, const char *signature); 96 PANDA_PUBLIC_API EtsMethod *GetDirectMethod(const char *name, const char *signature); 97 98 PANDA_PUBLIC_API EtsMethod *GetMethod(const char *name); 99 PANDA_PUBLIC_API EtsMethod *GetMethod(const char *name, const char *signature); 100 GetDirectMethod(const PandaString & name,const PandaString & signature)101 PANDA_PUBLIC_API EtsMethod *GetDirectMethod(const PandaString &name, const PandaString &signature) 102 { 103 return GetDirectMethod(name.c_str(), signature.c_str()); 104 } 105 106 PANDA_PUBLIC_API EtsMethod *GetDirectMethod(const char *name, const Method::Proto &proto) const; 107 GetMethod(const PandaString & name,const PandaString & signature)108 EtsMethod *GetMethod(const PandaString &name, const PandaString &signature) 109 { 110 return GetMethod(name.c_str(), signature.c_str()); 111 } 112 113 EtsMethod *GetMethodByIndex(uint32_t i); 114 115 uint32_t GetMethodsNum(); 116 117 PandaVector<EtsMethod *> GetMethods(); 118 119 PANDA_PUBLIC_API PandaVector<EtsMethod *> GetConstructors(); 120 121 template <class T> GetStaticFieldPrimitive(EtsField * field)122 T GetStaticFieldPrimitive(EtsField *field) 123 { 124 return GetRuntimeClass()->GetFieldPrimitive<T>(*field->GetRuntimeField()); 125 } 126 127 template <class T> GetStaticFieldPrimitive(int32_t fieldOffset,bool isVolatile)128 T GetStaticFieldPrimitive(int32_t fieldOffset, bool isVolatile) 129 { 130 if (isVolatile) { 131 return GetRuntimeClass()->GetFieldPrimitive<T, true>(fieldOffset); 132 } 133 return GetRuntimeClass()->GetFieldPrimitive<T, false>(fieldOffset); 134 } 135 136 template <class T> SetStaticFieldPrimitive(EtsField * field,T value)137 void SetStaticFieldPrimitive(EtsField *field, T value) 138 { 139 GetRuntimeClass()->SetFieldPrimitive<T>(*field->GetRuntimeField(), value); 140 } 141 142 template <class T> SetStaticFieldPrimitive(int32_t fieldOffset,bool isVolatile,T value)143 void SetStaticFieldPrimitive(int32_t fieldOffset, bool isVolatile, T value) 144 { 145 if (isVolatile) { 146 GetRuntimeClass()->SetFieldPrimitive<T, true>(fieldOffset, value); 147 } 148 GetRuntimeClass()->SetFieldPrimitive<T, false>(fieldOffset, value); 149 } 150 151 PANDA_PUBLIC_API EtsObject *GetStaticFieldObject(EtsField *field); 152 EtsObject *GetStaticFieldObject(int32_t fieldOffset, bool isVolatile); 153 154 void SetStaticFieldObject(EtsField *field, EtsObject *value); 155 void SetStaticFieldObject(int32_t fieldOffset, bool isVolatile, EtsObject *value); 156 IsEtsObject()157 bool IsEtsObject() 158 { 159 return GetRuntimeClass()->IsObjectClass(); 160 } 161 IsPrimitive()162 bool IsPrimitive() const 163 { 164 return GetRuntimeClass()->IsPrimitive(); 165 } 166 IsAbstract()167 bool IsAbstract() 168 { 169 return GetRuntimeClass()->IsAbstract(); 170 } 171 IsPublic()172 bool IsPublic() const 173 { 174 return GetRuntimeClass()->IsPublic(); 175 } 176 IsFinal()177 bool IsFinal() const 178 { 179 return GetRuntimeClass()->IsFinal(); 180 } 181 182 bool IsAnnotation() const; 183 bool IsEnum() const; 184 PANDA_PUBLIC_API bool IsStringClass() const; 185 bool IsLambdaClass() const; 186 bool IsUnionClass() const; 187 bool IsUndefined() const; 188 bool IsClassClass(); 189 bool IsInterface() const; 190 PANDA_PUBLIC_API bool IsArrayClass() const; 191 bool IsTupleClass() const; 192 bool IsBoxedClass() const; 193 194 static bool IsInSamePackage(std::string_view className1, std::string_view className2); 195 196 bool IsInSamePackage(EtsClass *that); 197 198 PandaVector<EtsClass *> GetInterfaces() const; 199 GetComponentSize()200 uint32_t GetComponentSize() const 201 { 202 return GetRuntimeClass()->GetComponentSize(); 203 } 204 GetType()205 panda_file::Type GetType() const 206 { 207 return GetRuntimeClass()->GetType(); 208 } 209 IsSubClass(EtsClass * cls)210 bool IsSubClass(EtsClass *cls) 211 { 212 return GetRuntimeClass()->IsSubClassOf(cls->GetRuntimeClass()); 213 } 214 IsAssignableFrom(EtsClass * clazz)215 bool IsAssignableFrom(EtsClass *clazz) const 216 { 217 return GetRuntimeClass()->IsAssignableFrom(clazz->GetRuntimeClass()); 218 } 219 IsGenerated()220 bool IsGenerated() const 221 { 222 return IsArrayClass() || IsPrimitive(); 223 } 224 CanAccess(EtsClass * that)225 bool CanAccess(EtsClass *that) 226 { 227 return that->IsPublic() || IsInSamePackage(that); 228 } 229 230 EtsMethod *ResolveVirtualMethod(const EtsMethod *method) const; 231 232 template <class Callback> EnumerateMethods(const Callback & callback)233 void EnumerateMethods(const Callback &callback) 234 { 235 for (auto &method : GetRuntimeClass()->GetMethods()) { 236 bool finished = callback(reinterpret_cast<EtsMethod *>(&method)); 237 if (finished) { 238 break; 239 } 240 } 241 } 242 243 template <class Callback> EnumerateDirectInterfaces(const Callback & callback)244 void EnumerateDirectInterfaces(const Callback &callback) 245 { 246 for (Class *runtimeInterface : GetRuntimeClass()->GetInterfaces()) { 247 EtsClass *interface = EtsClass::FromRuntimeClass(runtimeInterface); 248 bool finished = callback(interface); 249 if (finished) { 250 break; 251 } 252 } 253 } 254 255 void GetInterfaces(PandaUnorderedSet<EtsClass *> &ifaces, EtsClass *iface); 256 257 template <class Callback> EnumerateInterfaces(const Callback & callback)258 void EnumerateInterfaces(const Callback &callback) 259 { 260 PandaUnorderedSet<EtsClass *> ifaces; 261 GetInterfaces(ifaces, this); 262 for (auto iface : ifaces) { 263 bool finished = callback(iface); 264 if (finished) { 265 break; 266 } 267 } 268 } 269 270 template <class Callback> EnumerateBaseClasses(const Callback & callback)271 void EnumerateBaseClasses(const Callback &callback) 272 { 273 PandaVector<EtsClass *> inherChain; 274 auto curClass = this; 275 while (curClass != nullptr) { 276 inherChain.push_back(curClass); 277 curClass = curClass->GetBase(); 278 } 279 for (auto i = inherChain.rbegin(); i != inherChain.rend(); i++) { 280 bool finished = callback(*i); 281 if (finished) { 282 break; 283 } 284 } 285 } 286 GetClassLoader()287 ClassLinkerContext *GetClassLoader() const 288 { 289 return GetRuntimeClass()->GetLoadContext(); 290 } 291 GetRuntimeClass()292 Class *GetRuntimeClass() 293 { 294 return &klass_; 295 } 296 GetRuntimeClass()297 const Class *GetRuntimeClass() const 298 { 299 return &klass_; 300 } 301 AsObject()302 EtsObject *AsObject() 303 { 304 return reinterpret_cast<EtsObject *>(this); 305 } 306 AsObject()307 const EtsObject *AsObject() const 308 { 309 return reinterpret_cast<const EtsObject *>(this); 310 } 311 IsInitialized()312 bool IsInitialized() const 313 { 314 return GetRuntimeClass()->IsInitialized(); 315 } 316 317 EtsType GetEtsType(); 318 GetSize(uint32_t klassSize)319 static size_t GetSize(uint32_t klassSize) 320 { 321 return GetRuntimeClassOffset() + klassSize; 322 } 323 GetRuntimeClassOffset()324 static constexpr size_t GetRuntimeClassOffset() 325 { 326 return MEMBER_OFFSET(EtsClass, klass_); 327 } 328 GetHeaderOffset()329 static constexpr size_t GetHeaderOffset() 330 { 331 return MEMBER_OFFSET(EtsClass, header_); 332 } 333 FromRuntimeClass(const Class * cls)334 static EtsClass *FromRuntimeClass(const Class *cls) 335 { 336 ASSERT(cls != nullptr); 337 return reinterpret_cast<EtsClass *>(reinterpret_cast<uintptr_t>(cls) - GetRuntimeClassOffset()); 338 } 339 340 static EtsClass *GetPrimitiveClass(EtsString *primitiveName); 341 342 void Initialize(EtsArray *ifTable, EtsClass *superClass, uint16_t accessFlags, bool isPrimitiveType); 343 344 void SetComponentType(EtsClass *componentType); 345 346 EtsClass *GetComponentType() const; 347 348 void SetIfTable(EtsArray *array); 349 350 void SetName(EtsString *name); 351 352 bool CompareAndSetName(EtsString *oldName, EtsString *newName); 353 354 EtsString *GetName(); 355 static EtsString *CreateEtsClassName([[maybe_unused]] const char *descriptor); 356 SetSuperClass(EtsClass * superClass)357 void SetSuperClass(EtsClass *superClass) 358 { 359 ObjectHeader *obj = superClass != nullptr ? reinterpret_cast<ObjectHeader *>(superClass->AsObject()) : nullptr; 360 GetObjectHeader()->SetFieldObject(GetSuperClassOffset(), obj); 361 } 362 GetSuperClass()363 EtsClass *GetSuperClass() const 364 { 365 return reinterpret_cast<EtsClass *>(GetObjectHeader()->GetFieldObject(GetSuperClassOffset())); 366 } 367 SetFlags(uint32_t flags)368 void SetFlags(uint32_t flags) 369 { 370 GetObjectHeader()->SetFieldPrimitive(GetFlagsOffset(), flags); 371 } 372 GetFlags()373 uint32_t GetFlags() const 374 { 375 return GetObjectHeader()->GetFieldPrimitive<uint32_t>(GetFlagsOffset()); 376 } 377 378 /// Return true if given class has .finalize() method, false otherwise 379 static bool IsClassFinalizable(EtsClass *klass); 380 381 void SetSoftReference(); 382 void SetWeakReference(); 383 void SetFinalizeReference(); 384 void SetPhantomReference(); 385 void SetFinalizable(); 386 387 [[nodiscard]] bool IsSoftReference() const; 388 [[nodiscard]] bool IsWeakReference() const; 389 [[nodiscard]] bool IsFinalizerReference() const; 390 [[nodiscard]] bool IsPhantomReference() const; 391 [[nodiscard]] bool IsFinalizable() const; 392 393 /// True if class inherited from Reference, false otherwise 394 [[nodiscard]] bool IsReference() const; 395 396 EtsClass() = delete; 397 ~EtsClass() = delete; 398 NO_COPY_SEMANTIC(EtsClass); 399 NO_MOVE_SEMANTIC(EtsClass); 400 GetIfTableOffset()401 static constexpr size_t GetIfTableOffset() 402 { 403 return MEMBER_OFFSET(EtsClass, ifTable_); 404 } 405 GetNameOffset()406 static constexpr size_t GetNameOffset() 407 { 408 return MEMBER_OFFSET(EtsClass, name_); 409 } 410 GetSuperClassOffset()411 static constexpr size_t GetSuperClassOffset() 412 { 413 return MEMBER_OFFSET(EtsClass, superClass_); 414 } 415 GetFlagsOffset()416 static constexpr size_t GetFlagsOffset() 417 { 418 return MEMBER_OFFSET(EtsClass, flags_); 419 } 420 421 private: GetObjectHeader()422 ObjectHeader *GetObjectHeader() 423 { 424 return &header_; 425 } 426 GetObjectHeader()427 const ObjectHeader *GetObjectHeader() const 428 { 429 return &header_; 430 } 431 432 constexpr static uint32_t ETS_ACC_PRIMITIVE = 1U << 16U; 433 /// Class is a SoftReference or successor of this class 434 constexpr static uint32_t IS_SOFT_REFERENCE = 1U << 18U; 435 /// Class is a WeakReference or successor of this class 436 constexpr static uint32_t IS_WEAK_REFERENCE = 1U << 19U; 437 /// Class is a FinalizerReference or successor of this class 438 constexpr static uint32_t IS_FINALIZE_REFERENCE = 1U << 20U; 439 /// Class is a PhantomReference or successor of this class 440 constexpr static uint32_t IS_PHANTOM_REFERENCE = 1U << 21U; 441 /// Class is a Reference or successor of this class 442 constexpr static uint32_t IS_REFERENCE = 443 IS_SOFT_REFERENCE | IS_WEAK_REFERENCE | IS_FINALIZE_REFERENCE | IS_PHANTOM_REFERENCE; 444 /// Class override Object.finalize() or any of his ancestors, and implementation is not trivial. 445 constexpr static uint32_t IS_CLASS_FINALIZABLE = 1U << 22U; 446 447 panda::ObjectHeader header_; // EtsObject 448 449 // ets.Class fields BEGIN 450 FIELD_UNUSED ObjectPointer<EtsArray> ifTable_; // Class[] 451 FIELD_UNUSED ObjectPointer<EtsString> name_; // String 452 FIELD_UNUSED ObjectPointer<EtsClass> superClass_; // Class<? super T> 453 454 FIELD_UNUSED uint32_t flags_; 455 // ets.Class fields END 456 457 panda::Class klass_; 458 }; 459 460 // Object header field must be first 461 static_assert(EtsClass::GetHeaderOffset() == 0); 462 463 // Klass field has variable size so it must be last 464 static_assert(EtsClass::GetRuntimeClassOffset() + sizeof(panda::Class) == sizeof(EtsClass)); 465 466 } // namespace panda::ets 467 468 #endif // PANDA_PLUGINS_ETS_RUNTIME_FFI_CLASSES_ETS_CLASS_H 469