diff --git a/core/io/resource.cpp b/core/io/resource.cpp index f2ecdba930b..5762208c9e6 100644 --- a/core/io/resource.cpp +++ b/core/io/resource.cpp @@ -758,7 +758,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 265c2f120d9..a5f6f48b7f8 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -2228,9 +2228,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 0f981243916..c0e33457973 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -582,6 +582,29 @@ public: 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; @@ -623,16 +646,19 @@ private: #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 @@ -658,7 +684,6 @@ private: _FORCE_INLINE_ void _construct_object(bool p_reference); friend class RefCounted; - bool type_is_reference = false; BinaryMutex _instance_binding_mutex; struct InstanceBinding { @@ -764,6 +789,7 @@ protected: 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; @@ -838,6 +864,8 @@ public: } 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; @@ -996,7 +1024,7 @@ public: 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 1a43c1e18cd..3f1fb4ffddc 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 eb4248087b3..4b995347751 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -197,7 +197,9 @@ public: 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 e970656c4af..9bbeeb28e7d 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 17bba4e4e33..dadb163baf0 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -115,4 +115,6 @@ public: 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 38a8ae73d90..1e56fc56df9 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 c95c84f0d9f..322f9d1f36a 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 660d4f7ccb2..e2e07bb2a2b 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 d9e3d33c2a1..60e47a11103 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -1546,6 +1546,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 f181c44134e..ae29565daf8 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 5518c8fd279..49638328c1f 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 5ad4f99e32f..b9ab0eefd33 100644 --- a/scene/3d/physics/physics_body_3d.h +++ b/scene/3d/physics/physics_body_3d.h @@ -65,4 +65,6 @@ public: 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 41903f208a1..a58b21bf042 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -202,6 +202,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(true); @@ -643,6 +645,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 643f0732113..0dc1664d82c 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -4392,6 +4392,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 248d4242f07..aaceb1a3ae0 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -1755,6 +1755,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 7bad977132f..da99df28928 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -4041,6 +4041,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: