• 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 #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 ark::ets {
33 
34 enum class AccessLevel { PUBLIC, PROTECTED, DEFAULT, PRIVATE };
35 
36 class EtsMethod;
37 class EtsObject;
38 class EtsString;
39 class EtsArray;
40 class EtsPromise;
41 class EtsErrorOptions;
42 class EtsTypeAPIField;
43 class EtsTypeAPIMethod;
44 class EtsTypeAPIParameter;
45 
46 enum class EtsType;
47 
48 namespace test {
49 class EtsClassTest;
50 }  // namespace test
51 
52 class EtsClass {
53 public:
54     // We shouldn't init header_ here - because it has been memset(0) in object allocation,
55     // 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)56     void InitClass(const uint8_t *descriptor, uint32_t vtableSize, uint32_t imtSize, uint32_t klassSize)
57     {
58         new (&klass_) ark::Class(descriptor, panda_file::SourceLang::ETS, vtableSize, imtSize, klassSize);
59     }
60 
GetDescriptor()61     const char *GetDescriptor() const
62     {
63         return utf::Mutf8AsCString(GetRuntimeClass()->GetDescriptor());
64     }
65 
66     PANDA_PUBLIC_API EtsClass *GetBase();
67 
68     uint32_t GetFieldsNumber();
69 
70     uint32_t GetOwnFieldsNumber();  // Without inherited fields
71 
GetStaticFieldsNumber()72     uint32_t GetStaticFieldsNumber()
73     {
74         return GetRuntimeClass()->GetStaticFields().size();
75     }
76 
GetInstanceFieldsNumber()77     uint32_t GetInstanceFieldsNumber()
78     {
79         return GetRuntimeClass()->GetInstanceFields().size();
80     }
81 
82     uint32_t GetFieldIndexByName(const char *name);
83 
84     PANDA_PUBLIC_API PandaVector<EtsField *> GetFields();
85 
86     EtsField *GetFieldByIndex(uint32_t i);
87 
88     EtsField *GetFieldIDByOffset(uint32_t fieldOffset);
89     PANDA_PUBLIC_API EtsField *GetFieldIDByName(const char *name, const char *sig = nullptr);
90 
91     EtsField *GetOwnFieldByIndex(uint32_t i);
92     EtsField *GetDeclaredFieldIDByName(const char *name);
93 
94     PANDA_PUBLIC_API EtsField *GetStaticFieldIDByName(const char *name, const char *sig = nullptr);
95     EtsField *GetStaticFieldIDByOffset(uint32_t fieldOffset);
96 
97     PANDA_PUBLIC_API EtsMethod *GetDirectMethod(const char *name);
98     PANDA_PUBLIC_API EtsMethod *GetDirectMethod(const uint8_t *name, const char *signature);
99     PANDA_PUBLIC_API EtsMethod *GetDirectMethod(const char *name, const char *signature);
100 
101     PANDA_PUBLIC_API EtsMethod *GetMethod(const char *name);
102     PANDA_PUBLIC_API EtsMethod *GetMethod(const char *name, const char *signature);
103 
GetDirectMethod(const PandaString & name,const PandaString & signature)104     PANDA_PUBLIC_API EtsMethod *GetDirectMethod(const PandaString &name, const PandaString &signature)
105     {
106         return GetDirectMethod(name.c_str(), signature.c_str());
107     }
108 
109     PANDA_PUBLIC_API EtsMethod *GetDirectMethod(const char *name, const Method::Proto &proto) const;
110 
GetMethod(const PandaString & name,const PandaString & signature)111     EtsMethod *GetMethod(const PandaString &name, const PandaString &signature)
112     {
113         return GetMethod(name.c_str(), signature.c_str());
114     }
115 
116     EtsMethod *GetMethodByIndex(uint32_t i);
117 
118     uint32_t GetMethodsNum();
119 
120     PandaVector<EtsMethod *> GetMethods();
121 
122     PANDA_PUBLIC_API PandaVector<EtsMethod *> GetConstructors();
123 
124     template <class T>
GetStaticFieldPrimitive(EtsField * field)125     T GetStaticFieldPrimitive(EtsField *field)
126     {
127         return GetRuntimeClass()->GetFieldPrimitive<T>(*field->GetRuntimeField());
128     }
129 
130     template <class T>
GetStaticFieldPrimitive(int32_t fieldOffset,bool isVolatile)131     T GetStaticFieldPrimitive(int32_t fieldOffset, bool isVolatile)
132     {
133         if (isVolatile) {
134             return GetRuntimeClass()->GetFieldPrimitive<T, true>(fieldOffset);
135         }
136         return GetRuntimeClass()->GetFieldPrimitive<T, false>(fieldOffset);
137     }
138 
139     template <class T>
SetStaticFieldPrimitive(EtsField * field,T value)140     void SetStaticFieldPrimitive(EtsField *field, T value)
141     {
142         GetRuntimeClass()->SetFieldPrimitive<T>(*field->GetRuntimeField(), value);
143     }
144 
145     template <class T>
SetStaticFieldPrimitive(int32_t fieldOffset,bool isVolatile,T value)146     void SetStaticFieldPrimitive(int32_t fieldOffset, bool isVolatile, T value)
147     {
148         if (isVolatile) {
149             GetRuntimeClass()->SetFieldPrimitive<T, true>(fieldOffset, value);
150         }
151         GetRuntimeClass()->SetFieldPrimitive<T, false>(fieldOffset, value);
152     }
153 
154     PANDA_PUBLIC_API EtsObject *GetStaticFieldObject(EtsField *field);
155     EtsObject *GetStaticFieldObject(int32_t fieldOffset, bool isVolatile);
156 
157     void SetStaticFieldObject(EtsField *field, EtsObject *value);
158     void SetStaticFieldObject(int32_t fieldOffset, bool isVolatile, EtsObject *value);
159 
IsEtsObject()160     bool IsEtsObject()
161     {
162         return GetRuntimeClass()->IsObjectClass();
163     }
164 
IsPrimitive()165     bool IsPrimitive() const
166     {
167         return GetRuntimeClass()->IsPrimitive();
168     }
169 
IsAbstract()170     bool IsAbstract()
171     {
172         return GetRuntimeClass()->IsAbstract();
173     }
174 
IsPublic()175     bool IsPublic() const
176     {
177         return GetRuntimeClass()->IsPublic();
178     }
179 
IsFinal()180     bool IsFinal() const
181     {
182         return GetRuntimeClass()->IsFinal();
183     }
184 
IsAnnotation()185     bool IsAnnotation() const
186     {
187         return GetRuntimeClass()->IsAnnotation();
188     }
189 
IsEnum()190     bool IsEnum() const
191     {
192         return GetRuntimeClass()->IsEnum();
193     }
194 
IsStringClass()195     bool IsStringClass() const
196     {
197         return GetRuntimeClass()->IsStringClass();
198     }
199 
IsClassClass()200     bool IsClassClass() const
201     {
202         return GetRuntimeClass()->IsClassClass();
203     }
204 
IsArrayClass()205     bool IsArrayClass() const
206     {
207         return GetRuntimeClass()->IsArrayClass();
208     }
209 
IsInterface()210     bool IsInterface() const
211     {
212         return GetRuntimeClass()->IsInterface();
213     }
214 
IsClass()215     bool IsClass() const
216     {
217         return GetRuntimeClass()->IsClass();
218     }
219 
220     static bool IsInSamePackage(std::string_view className1, std::string_view className2);
221 
222     bool IsInSamePackage(EtsClass *that);
223 
GetComponentSize()224     uint32_t GetComponentSize() const
225     {
226         return GetRuntimeClass()->GetComponentSize();
227     }
228 
GetType()229     panda_file::Type GetType() const
230     {
231         return GetRuntimeClass()->GetType();
232     }
233 
IsSubClass(EtsClass * cls)234     bool IsSubClass(EtsClass *cls)
235     {
236         return GetRuntimeClass()->IsSubClassOf(cls->GetRuntimeClass());
237     }
238 
IsAssignableFrom(EtsClass * clazz)239     bool IsAssignableFrom(EtsClass *clazz) const
240     {
241         return GetRuntimeClass()->IsAssignableFrom(clazz->GetRuntimeClass());
242     }
243 
IsGenerated()244     bool IsGenerated() const
245     {
246         return IsArrayClass() || IsPrimitive();
247     }
248 
CanAccess(EtsClass * that)249     bool CanAccess(EtsClass *that)
250     {
251         return that->IsPublic() || IsInSamePackage(that);
252     }
253 
254     EtsMethod *ResolveVirtualMethod(const EtsMethod *method) const;
255 
256     template <class Callback>
EnumerateMethods(const Callback & callback)257     void EnumerateMethods(const Callback &callback)
258     {
259         for (auto &method : GetRuntimeClass()->GetMethods()) {
260             bool finished = callback(reinterpret_cast<EtsMethod *>(&method));
261             if (finished) {
262                 break;
263             }
264         }
265     }
266 
267     template <class Callback>
EnumerateDirectInterfaces(const Callback & callback)268     void EnumerateDirectInterfaces(const Callback &callback)
269     {
270         for (Class *runtimeInterface : GetRuntimeClass()->GetInterfaces()) {
271             EtsClass *interface = EtsClass::FromRuntimeClass(runtimeInterface);
272             bool finished = callback(interface);
273             if (finished) {
274                 break;
275             }
276         }
277     }
278 
279     void GetInterfaces(PandaUnorderedSet<EtsClass *> &ifaces, EtsClass *iface);
280 
281     template <class Callback>
EnumerateInterfaces(const Callback & callback)282     void EnumerateInterfaces(const Callback &callback)
283     {
284         PandaUnorderedSet<EtsClass *> ifaces;
285         GetInterfaces(ifaces, this);
286         for (auto iface : ifaces) {
287             bool finished = callback(iface);
288             if (finished) {
289                 break;
290             }
291         }
292     }
293 
294     template <class Callback>
EnumerateBaseClasses(const Callback & callback)295     void EnumerateBaseClasses(const Callback &callback)
296     {
297         PandaVector<EtsClass *> inherChain;
298         auto curClass = this;
299         while (curClass != nullptr) {
300             inherChain.push_back(curClass);
301             curClass = curClass->GetBase();
302         }
303         for (auto i = inherChain.rbegin(); i != inherChain.rend(); i++) {
304             bool finished = callback(*i);
305             if (finished) {
306                 break;
307             }
308         }
309     }
310 
GetLoadContext()311     ClassLinkerContext *GetLoadContext() const
312     {
313         return GetRuntimeClass()->GetLoadContext();
314     }
315 
GetRuntimeClass()316     Class *GetRuntimeClass()
317     {
318         return &klass_;
319     }
320 
GetRuntimeClass()321     const Class *GetRuntimeClass() const
322     {
323         return &klass_;
324     }
325 
AsObject()326     EtsObject *AsObject()
327     {
328         return reinterpret_cast<EtsObject *>(this);
329     }
330 
AsObject()331     const EtsObject *AsObject() const
332     {
333         return reinterpret_cast<const EtsObject *>(this);
334     }
335 
IsInitialized()336     bool IsInitialized() const
337     {
338         return GetRuntimeClass()->IsInitialized();
339     }
340 
341     EtsType GetEtsType();
342 
GetSize(uint32_t klassSize)343     static size_t GetSize(uint32_t klassSize)
344     {
345         return GetRuntimeClassOffset() + klassSize;
346     }
347 
GetRuntimeClassOffset()348     static constexpr size_t GetRuntimeClassOffset()
349     {
350         return MEMBER_OFFSET(EtsClass, klass_);
351     }
352 
GetHeaderOffset()353     static constexpr size_t GetHeaderOffset()
354     {
355         return MEMBER_OFFSET(EtsClass, header_);
356     }
357 
FromRuntimeClass(const Class * cls)358     static EtsClass *FromRuntimeClass(const Class *cls)
359     {
360         ASSERT(cls != nullptr);
361         return reinterpret_cast<EtsClass *>(reinterpret_cast<uintptr_t>(cls) - GetRuntimeClassOffset());
362     }
363 
FromClassObject(ObjectHeader * obj)364     static EtsClass *FromClassObject(ObjectHeader *obj)
365     {
366         ASSERT(obj->ClassAddr<Class>()->IsClassClass());
367         return reinterpret_cast<EtsClass *>(obj);
368     }
369 
FromEtsClassObject(EtsObject * obj)370     static EtsClass *FromEtsClassObject(EtsObject *obj)
371     {
372         return FromClassObject(reinterpret_cast<ObjectHeader *>(obj));
373     }
374 
375     static EtsClass *GetPrimitiveClass(EtsString *primitiveName);
376 
377     void Initialize(EtsClass *superClass, uint16_t accessFlags, bool isPrimitiveType);
378 
379     void SetComponentType(EtsClass *componentType);
380 
381     EtsClass *GetComponentType() const;
382 
383     void SetName(EtsString *name);
384 
385     bool CompareAndSetName(EtsString *oldName, EtsString *newName);
386 
387     EtsString *GetName();
388     static EtsString *CreateEtsClassName([[maybe_unused]] const char *descriptor);
389 
SetSuperClass(EtsClass * superClass)390     void SetSuperClass(EtsClass *superClass)
391     {
392         auto obj = reinterpret_cast<ObjectHeader *>(superClass);
393         GetObjectHeader()->SetFieldObject(GetSuperClassOffset(), obj);
394     }
395 
GetSuperClass()396     EtsClass *GetSuperClass() const
397     {
398         return reinterpret_cast<EtsClass *>(GetObjectHeader()->GetFieldObject(GetSuperClassOffset()));
399     }
400 
SetFlags(uint32_t flags)401     void SetFlags(uint32_t flags)
402     {
403         GetObjectHeader()->SetFieldPrimitive(GetFlagsOffset(), flags);
404     }
405 
GetFlags()406     uint32_t GetFlags() const
407     {
408         return GetObjectHeader()->GetFieldPrimitive<uint32_t>(GetFlagsOffset());
409     }
410 
411     void SetWeakReference();
412     void SetFinalizeReference();
413     void SetValueTyped();
414     void SetUndefined();
415     void SetBoxed();
416     void SetFunction();
417     void SetBigInt();
418 
IsWeakReference()419     [[nodiscard]] bool IsWeakReference() const
420     {
421         return (flags_ & IS_WEAK_REFERENCE) != 0;
422     }
423 
IsFinalizerReference()424     [[nodiscard]] bool IsFinalizerReference() const
425     {
426         return (flags_ & IS_FINALIZE_REFERENCE) != 0;
427     }
428 
429     /// True if class inherited from Reference, false otherwise
IsReference()430     [[nodiscard]] bool IsReference() const
431     {
432         return (flags_ & IS_REFERENCE) != 0;
433     }
434 
IsValueTyped()435     [[nodiscard]] bool IsValueTyped() const
436     {
437         return (GetFlags() & IS_VALUE_TYPED) != 0;
438     }
439 
IsUndefined()440     [[nodiscard]] bool IsUndefined() const
441     {
442         return (GetFlags() & IS_UNDEFINED) != 0;
443     }
444 
IsBoxed()445     [[nodiscard]] bool IsBoxed() const
446     {
447         return (GetFlags() & IS_BOXED) != 0;
448     }
449 
IsFunction()450     [[nodiscard]] bool IsFunction() const
451     {
452         return (GetFlags() & IS_FUNCTION) != 0;
453     }
454 
IsBigInt()455     [[nodiscard]] bool IsBigInt() const
456     {
457         return (GetFlags() & IS_BIGINT) != 0;
458     }
459 
460     EtsClass() = delete;
461     ~EtsClass() = delete;
462     NO_COPY_SEMANTIC(EtsClass);
463     NO_MOVE_SEMANTIC(EtsClass);
464 
GetNameOffset()465     static constexpr size_t GetNameOffset()
466     {
467         return MEMBER_OFFSET(EtsClass, name_);
468     }
469 
GetSuperClassOffset()470     static constexpr size_t GetSuperClassOffset()
471     {
472         return MEMBER_OFFSET(EtsClass, superClass_);
473     }
474 
GetFlagsOffset()475     static constexpr size_t GetFlagsOffset()
476     {
477         return MEMBER_OFFSET(EtsClass, flags_);
478     }
479 
GCRefFieldsOffset()480     static constexpr size_t GCRefFieldsOffset()
481     {
482         return GetHeaderOffset() + sizeof(header_);
483     }
484 
GCRefFieldsNum()485     static constexpr size_t GCRefFieldsNum()
486     {
487         return (GetFlagsOffset() - GCRefFieldsOffset()) / sizeof(ObjectPointerType);
488     }
489 
490 private:
GetObjectHeader()491     ObjectHeader *GetObjectHeader()
492     {
493         return &header_;
494     }
495 
GetObjectHeader()496     const ObjectHeader *GetObjectHeader() const
497     {
498         return &header_;
499     }
500 
501     constexpr static uint32_t ETS_ACC_PRIMITIVE = 1U << 16U;
502     /// Class is a WeakReference or successor of this class
503     constexpr static uint32_t IS_WEAK_REFERENCE = 1U << 17U;
504     /// Class is a FinalizerReference or successor of this class
505     constexpr static uint32_t IS_FINALIZE_REFERENCE = 1U << 18U;
506     constexpr static uint32_t IS_REFERENCE = IS_WEAK_REFERENCE | IS_FINALIZE_REFERENCE;
507 
508     // Class is a value-semantic type
509     constexpr static uint32_t IS_VALUE_TYPED = 1U << 19U;
510     // Class is an internal "undefined" class
511     constexpr static uint32_t IS_UNDEFINED = 1U << 20U;
512     // Class is a boxed type
513     constexpr static uint32_t IS_BOXED = 1U << 21U;
514     // Class is Function
515     constexpr static uint32_t IS_FUNCTION = 1U << 22U;
516     // Class is BigInt
517     constexpr static uint32_t IS_BIGINT = 1U << 23U;
518 
519     ark::ObjectHeader header_;  // EtsObject
520 
521     // ets.Class fields BEGIN
522     FIELD_UNUSED ObjectPointer<EtsString> name_;       // String
523     FIELD_UNUSED ObjectPointer<EtsClass> superClass_;  // Class<? super T>
524     FIELD_UNUSED uint32_t flags_;
525     // ets.Class fields END
526 
527     ark::Class klass_;
528 
529     friend class test::EtsClassTest;
530 };
531 
532 // Object header field must be first
533 static_assert(EtsClass::GetHeaderOffset() == 0);
534 
535 // Klass field has variable size so it must be last
536 static_assert(EtsClass::GetRuntimeClassOffset() + sizeof(ark::Class) == sizeof(EtsClass));
537 
538 }  // namespace ark::ets
539 
540 #endif  // PANDA_PLUGINS_ETS_RUNTIME_FFI_CLASSES_ETS_CLASS_H_
541