1 /* 2 * Copyright (c) 2021 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_INCLUDE_CORETYPES_CLASS_H_ 17 #define PANDA_RUNTIME_INCLUDE_CORETYPES_CLASS_H_ 18 19 #include <cstddef> 20 #include <cstdint> 21 #include <cstring> 22 23 #include "libpandabase/utils/utf.h" 24 #include "runtime/include/class.h" 25 #include "runtime/include/object_header.h" 26 27 namespace panda::coretypes { 28 29 class Class : public ObjectHeader { 30 public: Class(const uint8_t * descriptor,uint32_t vtable_size,uint32_t imt_size,uint32_t klass_size)31 Class(const uint8_t *descriptor, uint32_t vtable_size, uint32_t imt_size, uint32_t klass_size) 32 : ObjectHeader(), klass_(descriptor, panda_file::SourceLang::PANDA_ASSEMBLY, vtable_size, imt_size, klass_size) 33 { 34 } 35 36 // We shouldn't init header_ here - because it has been memset(0) in object allocation, 37 // otherwise it may cause data race while visiting object's class concurrently in gc. InitClass(const uint8_t * descriptor,uint32_t vtable_size,uint32_t imt_size,uint32_t klass_size)38 void InitClass(const uint8_t *descriptor, uint32_t vtable_size, uint32_t imt_size, uint32_t klass_size) 39 { 40 // CODECHECK-NOLINTNEXTLINE(CPP_RULE_ID_SMARTPOINTER_INSTEADOF_ORIGINPOINTER) 41 new (&klass_) 42 panda::Class(descriptor, panda_file::SourceLang::PANDA_ASSEMBLY, vtable_size, imt_size, klass_size); 43 } 44 GetRuntimeClass()45 panda::Class *GetRuntimeClass() 46 { 47 return &klass_; 48 } 49 GetRuntimeClass()50 const panda::Class *GetRuntimeClass() const 51 { 52 return &klass_; 53 } 54 55 template <class T> GetFieldPrimitive(const Field & field)56 T GetFieldPrimitive(const Field &field) const 57 { 58 return klass_.GetFieldPrimitive<T>(field); 59 } 60 61 template <class T> SetFieldPrimitive(const Field & field,T value)62 void SetFieldPrimitive(const Field &field, T value) 63 { 64 klass_.SetFieldPrimitive(field, value); 65 } 66 67 template <bool need_read_barrier = true> GetFieldObject(const Field & field)68 ObjectHeader *GetFieldObject(const Field &field) const 69 { 70 return klass_.GetFieldObject<need_read_barrier>(field); 71 } 72 73 template <bool need_write_barrier = true> SetFieldObject(const Field & field,ObjectHeader * value)74 void SetFieldObject(const Field &field, ObjectHeader *value) 75 { 76 klass_.SetFieldObject<need_write_barrier>(field, value); 77 } 78 GetSize(uint32_t klass_size)79 static size_t GetSize(uint32_t klass_size) 80 { 81 return GetRuntimeClassOffset() + klass_size; 82 } 83 GetRuntimeClassOffset()84 static constexpr size_t GetRuntimeClassOffset() 85 { 86 return MEMBER_OFFSET(Class, klass_); 87 } 88 FromRuntimeClass(panda::Class * klass)89 static Class *FromRuntimeClass(panda::Class *klass) 90 { 91 return reinterpret_cast<Class *>(reinterpret_cast<uintptr_t>(klass) - GetRuntimeClassOffset()); 92 } 93 94 ~Class() = default; 95 96 NO_COPY_SEMANTIC(Class); 97 NO_MOVE_SEMANTIC(Class); 98 99 private: 100 panda::Class klass_; 101 }; 102 103 // Klass field has variable size so it must be the last 104 static_assert(Class::GetRuntimeClassOffset() + sizeof(panda::Class) == sizeof(Class)); 105 106 } // namespace panda::coretypes 107 108 #endif // PANDA_RUNTIME_INCLUDE_CORETYPES_CLASS_H_ 109