diff --git a/core/io/resource.cpp b/core/io/resource.cpp index 805d8ff001f3..9d4c45e9eecc 100644 --- a/core/io/resource.cpp +++ b/core/io/resource.cpp @@ -752,7 +752,9 @@ void Resource::_bind_methods() { } Resource::Resource() : - remapped_list(this) {} + remapped_list(this) { + _define_ancestry(AncestralClass::RESOURCE); +} Resource::~Resource() { if (unlikely(path_cache.is_empty())) { diff --git a/core/object/object.cpp b/core/object/object.cpp index 759525aa9df3..d0b06adf5f24 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -2204,9 +2204,20 @@ void Object::reset_internal_extension(ObjectGDExtension *p_extension) { #endif void Object::_construct_object(bool p_reference) { - type_is_reference = p_reference; + _block_signals = false; + _can_translate = true; + _emitting = false; + + // ObjectDB::add_instance relies on AncestralClass::REF_COUNTED + // being already set in the case of references. + _ancestry = p_reference ? (uint32_t)AncestralClass::REF_COUNTED : 0; + _instance_id = ObjectDB::add_instance(this); +#ifdef TOOLS_ENABLED + _edited = false; +#endif + #ifdef DEBUG_ENABLED _lock_index.init(1); #endif diff --git a/core/object/object.h b/core/object/object.h index 5e826be7c02c..62372218be5d 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -587,6 +587,29 @@ class Object { CONNECT_INHERITED = 32, // Used in editor builds. }; + // Store on each object a bitfield to quickly test whether it is derived from some "key" classes + // that are commonly tested in performance sensitive code. + // Ensure unsigned to bitpack. + enum class AncestralClass : unsigned int { + REF_COUNTED = 1 << 0, + NODE = 1 << 1, + RESOURCE = 1 << 2, + SCRIPT = 1 << 3, + + CANVAS_ITEM = 1 << 4, + CONTROL = 1 << 5, + NODE_2D = 1 << 6, + COLLISION_OBJECT_2D = 1 << 7, + AREA_2D = 1 << 8, + + NODE_3D = 1 << 9, + VISUAL_INSTANCE_3D = 1 << 10, + GEOMETRY_INSTANCE_3D = 1 << 11, + COLLISION_OBJECT_3D = 1 << 12, + PHYSICS_BODY_3D = 1 << 13, + MESH_INSTANCE_3D = 1 << 14, + }; + struct Connection { ::Signal signal; Callable callable; @@ -628,16 +651,19 @@ class Object { #ifdef DEBUG_ENABLED SafeRefCount _lock_index; #endif // DEBUG_ENABLED - bool _block_signals = false; int _predelete_ok = 0; ObjectID _instance_id; bool _predelete(); void _initialize(); void _postinitialize(); - bool _can_translate = true; - bool _emitting = false; + + uint32_t _ancestry : 15; + + bool _block_signals : 1; + bool _can_translate : 1; + bool _emitting : 1; #ifdef TOOLS_ENABLED - bool _edited = false; + bool _edited : 1; uint32_t _edited_version = 0; HashSet editor_section_folding; #endif @@ -663,7 +689,6 @@ class Object { _FORCE_INLINE_ void _construct_object(bool p_reference); friend class RefCounted; - bool type_is_reference = false; BinaryMutex _instance_binding_mutex; struct InstanceBinding { @@ -769,6 +794,7 @@ class Object { static void _get_property_list_from_classdb(const StringName &p_class, List *p_list, bool p_no_inheritance, const Object *p_validator); bool _disconnect(const StringName &p_signal, const Callable &p_callable, bool p_force = false); + void _define_ancestry(AncestralClass p_class) { _ancestry |= (uint32_t)p_class; } virtual bool _uses_signal_mutex() const; @@ -845,6 +871,8 @@ class Object { } virtual bool is_class_ptr(void *p_ptr) const { return get_class_ptr_static() == p_ptr; } + bool has_ancestry(AncestralClass p_class) const { return _ancestry & (uint32_t)p_class; } + const StringName &get_class_name() const; StringName get_class_name_for_extension(const GDExtension *p_library) const; @@ -1003,7 +1031,7 @@ class Object { void clear_internal_resource_paths(); - _ALWAYS_INLINE_ bool is_ref_counted() const { return type_is_reference; } + _ALWAYS_INLINE_ bool is_ref_counted() const { return has_ancestry(AncestralClass::REF_COUNTED); } void cancel_free(); diff --git a/core/object/ref_counted.cpp b/core/object/ref_counted.cpp index 1a43c1e18cd1..3f1fb4ffddc0 100644 --- a/core/object/ref_counted.cpp +++ b/core/object/ref_counted.cpp @@ -95,6 +95,7 @@ bool RefCounted::unreference() { RefCounted::RefCounted() : Object(true) { + _define_ancestry(AncestralClass::REF_COUNTED); refcount.init(); refcount_init.init(); } diff --git a/core/object/script_language.h b/core/object/script_language.h index eb4248087b33..4b9953477519 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -197,7 +197,9 @@ class Script : public Resource { virtual const Variant get_rpc_config() const = 0; - Script() {} + Script() { + _define_ancestry(AncestralClass::SCRIPT); + } }; class ScriptLanguage : public Object { diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index e970656c4af2..9bbeeb28e7db 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -510,3 +510,7 @@ void Node2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "global_skew", PROPERTY_HINT_NONE, "radians_as_degrees", PROPERTY_USAGE_NONE), "set_global_skew", "get_global_skew"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_transform", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform"); } + +Node2D::Node2D() { + _define_ancestry(AncestralClass::NODE_2D); +} diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index 17bba4e4e33c..dadb163baf02 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -115,4 +115,6 @@ class Node2D : public CanvasItem { Transform2D get_relative_transform_to_parent(const Node *p_parent) const; Transform2D get_transform() const override; + + Node2D(); }; diff --git a/scene/2d/physics/area_2d.cpp b/scene/2d/physics/area_2d.cpp index 38a8ae73d904..1e56fc56df9d 100644 --- a/scene/2d/physics/area_2d.cpp +++ b/scene/2d/physics/area_2d.cpp @@ -678,6 +678,8 @@ void Area2D::_bind_methods() { Area2D::Area2D() : CollisionObject2D(PhysicsServer2D::get_singleton()->area_create(), true) { + _define_ancestry(AncestralClass::AREA_2D); + set_gravity(980); set_gravity_direction(Vector2(0, 1)); set_monitoring(true); diff --git a/scene/2d/physics/collision_object_2d.cpp b/scene/2d/physics/collision_object_2d.cpp index c95c84f0d9f5..322f9d1f36a1 100644 --- a/scene/2d/physics/collision_object_2d.cpp +++ b/scene/2d/physics/collision_object_2d.cpp @@ -655,6 +655,8 @@ void CollisionObject2D::_bind_methods() { } CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) { + _define_ancestry(AncestralClass::COLLISION_OBJECT_2D); + rid = p_rid; area = p_area; pickable = true; @@ -672,6 +674,7 @@ CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) { } CollisionObject2D::CollisionObject2D() { + _define_ancestry(AncestralClass::COLLISION_OBJECT_2D); //owner= set_notify_transform(true); diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp index 41977b78d867..4a5054806756 100644 --- a/scene/3d/mesh_instance_3d.cpp +++ b/scene/3d/mesh_instance_3d.cpp @@ -925,6 +925,7 @@ void MeshInstance3D::_bind_methods() { } MeshInstance3D::MeshInstance3D() { + _define_ancestry(AncestralClass::MESH_INSTANCE_3D); } MeshInstance3D::~MeshInstance3D() { diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index 112816c045e6..c4d0fe59010c 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -1529,6 +1529,8 @@ void Node3D::_bind_methods() { Node3D::Node3D() : xform_change(this), _client_physics_interpolation_node_3d_list(this) { + _define_ancestry(AncestralClass::NODE_3D); + // Default member initializer for bitfield is a C++20 extension, so: data.top_level = false; diff --git a/scene/3d/physics/collision_object_3d.cpp b/scene/3d/physics/collision_object_3d.cpp index f181c44134e7..ae29565daf82 100644 --- a/scene/3d/physics/collision_object_3d.cpp +++ b/scene/3d/physics/collision_object_3d.cpp @@ -746,6 +746,8 @@ PackedStringArray CollisionObject3D::get_configuration_warnings() const { } CollisionObject3D::CollisionObject3D() { + _define_ancestry(AncestralClass::COLLISION_OBJECT_3D); + set_notify_transform(true); //owner= @@ -753,6 +755,8 @@ CollisionObject3D::CollisionObject3D() { } CollisionObject3D::~CollisionObject3D() { + _define_ancestry(AncestralClass::COLLISION_OBJECT_3D); + ERR_FAIL_NULL(PhysicsServer3D::get_singleton()); PhysicsServer3D::get_singleton()->free(rid); } diff --git a/scene/3d/physics/physics_body_3d.cpp b/scene/3d/physics/physics_body_3d.cpp index c844e5ddf7a0..8fe61ffea618 100644 --- a/scene/3d/physics/physics_body_3d.cpp +++ b/scene/3d/physics/physics_body_3d.cpp @@ -220,6 +220,10 @@ PackedStringArray PhysicsBody3D::get_configuration_warnings() const { return warnings; } +PhysicsBody3D::PhysicsBody3D() { + _define_ancestry(AncestralClass::PHYSICS_BODY_3D); +} + /////////////////////////////////////// //so, if you pass 45 as limit, avoid numerical precision errors when angle is 45. diff --git a/scene/3d/physics/physics_body_3d.h b/scene/3d/physics/physics_body_3d.h index 5ad4f99e32fb..b9ab0eefd33f 100644 --- a/scene/3d/physics/physics_body_3d.h +++ b/scene/3d/physics/physics_body_3d.h @@ -65,4 +65,6 @@ class PhysicsBody3D : public CollisionObject3D { TypedArray get_collision_exceptions(); void add_collision_exception_with(Node *p_node); //must be physicsbody void remove_collision_exception_with(Node *p_node); + + PhysicsBody3D(); }; diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index 32844531e35a..d5a35658681d 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -204,6 +204,8 @@ RID VisualInstance3D::get_base() const { } VisualInstance3D::VisualInstance3D() { + _define_ancestry(AncestralClass::VISUAL_INSTANCE_3D); + instance = RenderingServer::get_singleton()->instance_create(); RenderingServer::get_singleton()->instance_attach_object_instance_id(instance, get_instance_id()); _set_notify_transform_when_fti_off(true); @@ -645,6 +647,7 @@ void GeometryInstance3D::_bind_methods() { } GeometryInstance3D::GeometryInstance3D() { + _define_ancestry(AncestralClass::GEOMETRY_INSTANCE_3D); } GeometryInstance3D::~GeometryInstance3D() { diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index ba6e2bb1cc37..e11644dc5ce2 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -4399,6 +4399,8 @@ void Control::_bind_methods() { } Control::Control() { + _define_ancestry(AncestralClass::CONTROL); + data.theme_owner = memnew(ThemeOwner(this)); set_physics_interpolation_mode(Node::PHYSICS_INTERPOLATION_MODE_OFF); diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 1aa2d964edac..84898df15065 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -1727,6 +1727,8 @@ CanvasItem::TextureRepeat CanvasItem::get_texture_repeat_in_tree() const { CanvasItem::CanvasItem() : xform_change(this) { + _define_ancestry(AncestralClass::CANVAS_ITEM); + canvas_item = RenderingServer::get_singleton()->canvas_item_create(); } diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 170b3680a47d..18ae9cde68f9 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -4031,6 +4031,8 @@ String Node::_get_name_num_separator() { } Node::Node() { + _define_ancestry(AncestralClass::NODE); + orphan_node_count++; // Default member initializer for bitfield is a C++20 extension, so: