summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/io/marshalls.cpp12
-rw-r--r--core/io/resource_format_binary.cpp2
-rw-r--r--core/io/resource_loader.cpp2
-rw-r--r--core/io/resource_saver.cpp2
-rw-r--r--core/object.cpp179
-rw-r--r--core/object.h76
-rw-r--r--core/object_id.h1
-rw-r--r--core/os/main_loop.cpp4
-rw-r--r--core/ref_ptr.cpp103
-rw-r--r--core/ref_ptr.h62
-rw-r--r--core/reference.cpp3
-rw-r--r--core/reference.h100
-rw-r--r--core/resource.h1
-rw-r--r--core/type_info.h18
-rw-r--r--core/variant.cpp127
-rw-r--r--core/variant.h14
-rw-r--r--core/variant_call.cpp22
-rw-r--r--core/variant_op.cpp66
18 files changed, 338 insertions, 456 deletions
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index fdce9db2a0..17edc4982c 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -802,10 +802,10 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
}
} break;
case Variant::OBJECT: {
-#ifdef DEBUG_ENABLED
+
// Test for potential wrong values sent by the debugger when it breaks.
- Object *obj = p_variant;
- if (!obj || !ObjectDB::instance_validate(obj)) {
+ Object *obj = p_variant.get_validated_object();
+ if (!obj) {
// Object is invalid, send a NULL instead.
if (buf) {
encode_uint32(Variant::NIL, buf);
@@ -813,7 +813,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 4;
return OK;
}
-#endif // DEBUG_ENABLED
+
if (!p_full_objects) {
flags |= ENCODE_FLAG_OBJECT_AS_ID;
}
@@ -1127,9 +1127,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
} else {
if (buf) {
- Object *obj = p_variant;
+ Object *obj = p_variant.get_validated_object();
ObjectID id;
- if (obj && ObjectDB::instance_validate(obj)) {
+ if (obj) {
id = obj->get_instance_id();
}
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 4a2bea3182..02ae5788fc 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -1573,7 +1573,7 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
switch (p_variant.get_type()) {
case Variant::OBJECT: {
- RES res = p_variant.operator RefPtr();
+ RES res = p_variant;
if (res.is_null() || external_resources.has(res))
return;
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 0ee6478fa2..6877f816e1 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -955,7 +955,7 @@ bool ResourceLoader::add_custom_resource_format_loader(String script_path) {
ERR_FAIL_COND_V_MSG(obj == NULL, false, "Cannot instance script as custom resource loader, expected 'ResourceFormatLoader' inheritance, got: " + String(ibt) + ".");
ResourceFormatLoader *crl = Object::cast_to<ResourceFormatLoader>(obj);
- crl->set_script(s.get_ref_ptr());
+ crl->set_script(s);
ResourceLoader::add_resource_format_loader(crl);
return true;
diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp
index b468685e4d..685d21107f 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -221,7 +221,7 @@ bool ResourceSaver::add_custom_resource_format_saver(String script_path) {
ERR_FAIL_COND_V_MSG(obj == NULL, false, "Cannot instance script as custom resource saver, expected 'ResourceFormatSaver' inheritance, got: " + String(ibt) + ".");
ResourceFormatSaver *crl = Object::cast_to<ResourceFormatSaver>(obj);
- crl->set_script(s.get_ref_ptr());
+ crl->set_script(s);
ResourceSaver::add_resource_format_saver(crl);
return true;
diff --git a/core/object.cpp b/core/object.cpp
index dc1dc2c41f..9a5cfe5c22 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -968,7 +968,7 @@ void Object::cancel_delete() {
_predelete_ok = true;
}
-void Object::set_script_and_instance(const RefPtr &p_script, ScriptInstance *p_instance) {
+void Object::set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance) {
//this function is not meant to be used in any of these ways
ERR_FAIL_COND(p_script.is_null());
@@ -979,7 +979,7 @@ void Object::set_script_and_instance(const RefPtr &p_script, ScriptInstance *p_i
script_instance = p_instance;
}
-void Object::set_script(const RefPtr &p_script) {
+void Object::set_script(const Variant &p_script) {
if (script == p_script)
return;
@@ -990,7 +990,7 @@ void Object::set_script(const RefPtr &p_script) {
}
script = p_script;
- Ref<Script> s(script);
+ Ref<Script> s = script;
if (!s.is_null()) {
if (s->can_instance()) {
@@ -1017,12 +1017,12 @@ void Object::set_script_instance(ScriptInstance *p_instance) {
script_instance = p_instance;
if (p_instance)
- script = p_instance->get_script().get_ref_ptr();
+ script = p_instance->get_script();
else
- script = RefPtr();
+ script = Variant();
}
-RefPtr Object::get_script() const {
+Variant Object::get_script() const {
return script;
}
@@ -1911,8 +1911,8 @@ void Object::set_script_instance_binding(int p_script_language_index, void *p_da
_script_instance_bindings[p_script_language_index] = p_data;
}
-Object::Object() {
-
+void Object::_construct_object(bool p_reference) {
+ type_is_reference = p_reference;
_class_ptr = NULL;
_block_signals = false;
_predelete_ok = 0;
@@ -1933,6 +1933,14 @@ Object::Object() {
_lock_index.init(1);
#endif
}
+Object::Object(bool p_reference) {
+ _construct_object(p_reference);
+}
+
+Object::Object() {
+
+ _construct_object(false);
+}
Object::~Object() {
@@ -1993,96 +2001,139 @@ void postinitialize_handler(Object *p_object) {
p_object->_postinitialize();
}
-HashMap<ObjectID, Object *> ObjectDB::instances;
-uint64_t ObjectDB::instance_counter = 1;
-HashMap<Object *, ObjectID, ObjectDB::ObjectPtrHash> ObjectDB::instance_checks;
-ObjectID ObjectDB::add_instance(Object *p_object) {
-
- ERR_FAIL_COND_V(p_object->get_instance_id().is_valid(), ObjectID());
-
- rw_lock->write_lock();
- ObjectID instance_id = ObjectID(++instance_counter);
- instances[instance_id] = p_object;
- instance_checks[p_object] = instance_id;
-
- rw_lock->write_unlock();
+void ObjectDB::debug_objects(DebugFunc p_func) {
- return instance_id;
+ spin_lock.lock();
+ for (uint32_t i = 0; i < slot_count; i++) {
+ uint32_t slot = object_slots[i].next_free;
+ p_func(object_slots[slot].object);
+ }
+ spin_lock.unlock();
}
-void ObjectDB::remove_instance(Object *p_object) {
+void Object::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
+}
- rw_lock->write_lock();
+SpinLock ObjectDB::spin_lock;
+uint32_t ObjectDB::slot_count = 0;
+uint32_t ObjectDB::slot_max = 0;
+ObjectDB::ObjectSlot *ObjectDB::object_slots = nullptr;
+uint64_t ObjectDB::validator_counter = 0;
- instances.erase(p_object->get_instance_id());
- instance_checks.erase(p_object);
+int ObjectDB::get_object_count() {
- rw_lock->write_unlock();
+ return slot_count;
}
-Object *ObjectDB::get_instance(ObjectID p_instance_id) {
- rw_lock->read_lock();
- Object **obj = instances.getptr(p_instance_id);
- rw_lock->read_unlock();
+ObjectID ObjectDB::add_instance(Object *p_object) {
- if (!obj)
- return NULL;
- return *obj;
-}
+ spin_lock.lock();
+ if (unlikely(slot_count == slot_max)) {
-void ObjectDB::debug_objects(DebugFunc p_func) {
+ CRASH_COND(slot_count == (1 << OBJECTDB_SLOT_MAX_COUNT_BITS));
+
+ uint32_t new_slot_max = slot_max > 0 ? slot_max * 2 : 1;
+ object_slots = (ObjectSlot *)memrealloc(object_slots, sizeof(ObjectSlot) * new_slot_max);
+ for (uint32_t i = slot_max; i < new_slot_max; i++) {
+ object_slots[i].object = nullptr;
+ object_slots[i].is_reference = false;
+ object_slots[i].next_free = i;
+ object_slots[i].validator = 0;
+ }
+ slot_max = new_slot_max;
+ }
- rw_lock->read_lock();
+ uint32_t slot = object_slots[slot_count].next_free;
+ if (object_slots[slot].object != nullptr) {
+ spin_lock.unlock();
+ ERR_FAIL_COND_V(object_slots[slot].object != nullptr, ObjectID());
+ }
+ object_slots[slot].object = p_object;
+ object_slots[slot].is_reference = p_object->is_reference();
+ validator_counter = (validator_counter + 1) & OBJECTDB_VALIDATOR_MASK;
+ if (unlikely(validator_counter == 0)) {
+ validator_counter = 1;
+ }
+ object_slots[slot].validator = validator_counter;
- const ObjectID *K = NULL;
- while ((K = instances.next(K))) {
+ uint64_t id = validator_counter;
+ id <<= OBJECTDB_SLOT_MAX_COUNT_BITS;
+ id |= uint64_t(slot);
- p_func(instances[*K]);
+ if (p_object->is_reference()) {
+ id |= OBJECTDB_REFERENCE_BIT;
}
- rw_lock->read_unlock();
-}
+ slot_count++;
-void Object::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
+ spin_lock.unlock();
+
+ return ObjectID(id);
}
-int ObjectDB::get_object_count() {
+void ObjectDB::remove_instance(Object *p_object) {
+ uint64_t t = p_object->get_instance_id();
+ uint32_t slot = t & OBJECTDB_SLOT_MAX_COUNT_MASK; //slot is always valid on valid object
- rw_lock->read_lock();
- int count = instances.size();
- rw_lock->read_unlock();
+ spin_lock.lock();
- return count;
-}
+#ifdef DEBUG_ENABLED
-RWLock *ObjectDB::rw_lock = NULL;
+ if (object_slots[slot].object != p_object) {
+ spin_lock.unlock();
+ ERR_FAIL_COND(object_slots[slot].object != p_object);
+ }
+ {
+ uint64_t validator = (t >> OBJECTDB_SLOT_MAX_COUNT_BITS) & OBJECTDB_VALIDATOR_MASK;
+ if (object_slots[slot].validator != validator) {
+ spin_lock.unlock();
+ ERR_FAIL_COND(object_slots[slot].validator != validator);
+ }
+ }
+
+#endif
+ //decrease slot count
+ slot_count--;
+ //set the free slot properly
+ object_slots[slot_count].next_free = slot;
+ //invalidate, so checks against it fail
+ object_slots[slot].validator = 0;
+ object_slots[slot].is_reference = false;
+ object_slots[slot].object = nullptr;
+
+ spin_lock.unlock();
+}
void ObjectDB::setup() {
- rw_lock = RWLock::create();
+ //nothing to do now
}
void ObjectDB::cleanup() {
- rw_lock->write_lock();
- if (instances.size()) {
+ if (slot_count > 0) {
+ spin_lock.lock();
WARN_PRINT("ObjectDB Instances still exist!");
if (OS::get_singleton()->is_stdout_verbose()) {
- const ObjectID *K = NULL;
- while ((K = instances.next(K))) {
+ for (uint32_t i = 0; i < slot_count; i++) {
+ uint32_t slot = object_slots[i].next_free;
+ Object *obj = object_slots[slot].object;
String node_name;
- if (instances[*K]->is_class("Node"))
- node_name = " - Node name: " + String(instances[*K]->call("get_name"));
- if (instances[*K]->is_class("Resource"))
- node_name = " - Resource name: " + String(instances[*K]->call("get_name")) + " Path: " + String(instances[*K]->call("get_path"));
- print_line("Leaked instance: " + String(instances[*K]->get_class()) + ":" + itos(*K) + node_name);
+ if (obj->is_class("Node"))
+ node_name = " - Node name: " + String(obj->call("get_name"));
+ if (obj->is_class("Resource"))
+ node_name = " - Resource name: " + String(obj->call("get_name")) + " Path: " + String(obj->call("get_path"));
+
+ uint64_t id = uint64_t(slot) | (uint64_t(object_slots[slot].validator) << OBJECTDB_VALIDATOR_BITS) | (object_slots[slot].is_reference ? OBJECTDB_REFERENCE_BIT : 0);
+ print_line("Leaked instance: " + String(obj->get_class()) + ":" + itos(id) + node_name);
}
}
+ spin_lock.unlock();
+ }
+
+ if (object_slots) {
+ memfree(object_slots);
}
- instances.clear();
- instance_checks.clear();
- rw_lock->write_unlock();
- memdelete(rw_lock);
}
diff --git a/core/object.h b/core/object.h
index 312fe07a17..6a229afaea 100644
--- a/core/object.h
+++ b/core/object.h
@@ -37,6 +37,7 @@
#include "core/object_id.h"
#include "core/os/rw_lock.h"
#include "core/set.h"
+#include "core/spin_lock.h"
#include "core/variant.h"
#include "core/vmap.h"
@@ -488,7 +489,7 @@ private:
Set<String> editor_section_folding;
#endif
ScriptInstance *script_instance;
- RefPtr script;
+ Variant script; //reference does not yet exist, store it in a
Dictionary metadata;
mutable StringName _class_name;
mutable const StringName *_class_ptr;
@@ -506,9 +507,13 @@ private:
void property_list_changed_notify();
+ _FORCE_INLINE_ void _construct_object(bool p_reference);
+
friend class Reference;
+ bool type_is_reference = false;
uint32_t instance_binding_count;
void *_script_instance_bindings[MAX_SCRIPT_INSTANCE_BINDINGS];
+ Object(bool p_reference);
protected:
virtual void _initialize_classv() { initialize_class(); }
@@ -680,8 +685,8 @@ public:
/* SCRIPT */
- void set_script(const RefPtr &p_script);
- RefPtr get_script() const;
+ void set_script(const Variant &p_script);
+ Variant get_script() const;
/* SCRIPT */
@@ -700,7 +705,7 @@ public:
void set_script_instance(ScriptInstance *p_instance);
_FORCE_INLINE_ ScriptInstance *get_script_instance() const { return script_instance; }
- void set_script_and_instance(const RefPtr &p_script, ScriptInstance *p_instance); //some script languages can't control instance creation, so this function eases the process
+ void set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance); //some script languages can't control instance creation, so this function eases the process
void add_user_signal(const MethodInfo &p_signal);
Error emit_signal(const StringName &p_name, VARIANT_ARG_LIST);
@@ -751,6 +756,7 @@ public:
void clear_internal_resource_paths();
+ _ALWAYS_INLINE_ bool is_reference() const { return type_is_reference; }
Object();
virtual ~Object();
};
@@ -760,49 +766,63 @@ void postinitialize_handler(Object *p_object);
class ObjectDB {
- struct ObjectPtrHash {
-
- static _FORCE_INLINE_ uint32_t hash(const Object *p_obj) {
-
- union {
- const Object *p;
- unsigned long i;
- } u;
- u.p = p_obj;
- return HashMapHasherDefault::hash((uint64_t)u.i);
- }
+//this needs to add up to 63, 1 bit is for reference
+#define OBJECTDB_VALIDATOR_BITS 39
+#define OBJECTDB_VALIDATOR_MASK ((uint64_t(1) << OBJECTDB_VALIDATOR_BITS) - 1)
+#define OBJECTDB_SLOT_MAX_COUNT_BITS 24
+#define OBJECTDB_SLOT_MAX_COUNT_MASK ((uint64_t(1) << OBJECTDB_SLOT_MAX_COUNT_BITS) - 1)
+#define OBJECTDB_REFERENCE_BIT (uint64_t(1) << (OBJECTDB_SLOT_MAX_COUNT_BITS + OBJECTDB_VALIDATOR_BITS))
+
+ struct ObjectSlot { //128 bits per slot
+ uint64_t validator : OBJECTDB_VALIDATOR_BITS;
+ uint64_t next_free : OBJECTDB_SLOT_MAX_COUNT_BITS;
+ uint64_t is_reference : 1;
+ Object *object;
};
- static HashMap<ObjectID, Object *> instances;
- static HashMap<Object *, ObjectID, ObjectPtrHash> instance_checks;
+ static SpinLock spin_lock;
+ static uint32_t slot_count;
+ static uint32_t slot_max;
+ static ObjectSlot *object_slots;
+ static uint64_t validator_counter;
- static uint64_t instance_counter;
friend class Object;
friend void unregister_core_types();
-
- static RWLock *rw_lock;
static void cleanup();
+
static ObjectID add_instance(Object *p_object);
static void remove_instance(Object *p_object);
+
friend void register_core_types();
static void setup();
public:
typedef void (*DebugFunc)(Object *p_obj);
- static Object *get_instance(ObjectID p_instance_id);
- static void debug_objects(DebugFunc p_func);
- static int get_object_count();
+ _ALWAYS_INLINE_ static Object *get_instance(ObjectID p_instance_id) {
+
+ uint64_t id = p_instance_id;
+ uint32_t slot = id & OBJECTDB_SLOT_MAX_COUNT_MASK;
+
+ ERR_FAIL_COND_V(slot >= slot_max, nullptr); //this should never happen unless RID is corrupted
+
+ spin_lock.lock();
- _FORCE_INLINE_ static bool instance_validate(Object *p_ptr) {
- rw_lock->read_lock();
+ uint64_t validator = (id >> OBJECTDB_SLOT_MAX_COUNT_BITS) & OBJECTDB_VALIDATOR_MASK;
- bool exists = instance_checks.has(p_ptr);
+ if (unlikely(object_slots[slot].validator != validator)) {
+ spin_lock.unlock();
+ return nullptr;
+ }
+
+ Object *object = object_slots[slot].object;
- rw_lock->read_unlock();
+ spin_lock.unlock();
- return exists;
+ return object;
}
+ static void debug_objects(DebugFunc p_func);
+ static int get_object_count();
};
//needed by macros
diff --git a/core/object_id.h b/core/object_id.h
index f0ff2a24f5..6ab1a3031a 100644
--- a/core/object_id.h
+++ b/core/object_id.h
@@ -12,6 +12,7 @@ class ObjectID {
uint64_t id = 0;
public:
+ _ALWAYS_INLINE_ bool is_reference() const { return (id & (uint64_t(1) << 63)) != 0; }
_ALWAYS_INLINE_ bool is_valid() const { return id != 0; }
_ALWAYS_INLINE_ bool is_null() const { return id == 0; }
_ALWAYS_INLINE_ operator uint64_t() const { return id; }
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
index 5ecdd74a4b..6020c4b219 100644
--- a/core/os/main_loop.cpp
+++ b/core/os/main_loop.cpp
@@ -95,7 +95,7 @@ void MainLoop::input_event(const Ref<InputEvent> &p_event) {
void MainLoop::init() {
if (init_script.is_valid())
- set_script(init_script.get_ref_ptr());
+ set_script(init_script);
if (get_script_instance())
get_script_instance()->call("_initialize");
@@ -131,6 +131,6 @@ void MainLoop::finish() {
if (get_script_instance()) {
get_script_instance()->call("_finalize");
- set_script(RefPtr()); //clear script
+ set_script(Variant()); //clear script
}
}
diff --git a/core/ref_ptr.cpp b/core/ref_ptr.cpp
deleted file mode 100644
index 7e35bcc56c..0000000000
--- a/core/ref_ptr.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/*************************************************************************/
-/* ref_ptr.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "ref_ptr.h"
-
-#include "core/reference.h"
-#include "core/resource.h"
-
-void RefPtr::operator=(const RefPtr &p_other) {
-
- Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
- Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0]));
-
- *ref = *ref_other;
-}
-
-bool RefPtr::operator==(const RefPtr &p_other) const {
-
- Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
- Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0]));
-
- return *ref == *ref_other;
-}
-
-bool RefPtr::operator!=(const RefPtr &p_other) const {
-
- Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
- Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0]));
-
- return *ref != *ref_other;
-}
-
-RefPtr::RefPtr(const RefPtr &p_other) {
-
- memnew_placement(&data[0], Ref<Reference>);
-
- Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
- Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0]));
-
- *ref = *ref_other;
-}
-
-bool RefPtr::is_null() const {
-
- Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
- return ref->is_null();
-}
-
-RID RefPtr::get_rid() const {
-
- Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
- if (ref->is_null())
- return RID();
- Resource *res = Object::cast_to<Resource>(ref->ptr());
- if (res)
- return res->get_rid();
- return RID();
-}
-
-void RefPtr::unref() {
-
- Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
- ref->unref();
-}
-
-RefPtr::RefPtr() {
-
- ERR_FAIL_COND(sizeof(Ref<Reference>) > DATASIZE);
- memnew_placement(&data[0], Ref<Reference>);
-}
-
-RefPtr::~RefPtr() {
-
- Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
- ref->~Ref<Reference>();
-}
diff --git a/core/ref_ptr.h b/core/ref_ptr.h
deleted file mode 100644
index 4736106b4f..0000000000
--- a/core/ref_ptr.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*************************************************************************/
-/* ref_ptr.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef REF_PTR_H
-#define REF_PTR_H
-/**
- @author Juan Linietsky <reduzio@gmail.com>
- * This class exists to workaround a limitation in C++ but keep the design OK.
- * It's basically an opaque container of a Reference reference, so Variant can use it.
-*/
-
-#include "core/rid.h"
-
-class RefPtr {
-
- enum {
-
- DATASIZE = sizeof(void *) //*4 -ref was shrunk
- };
-
- mutable char data[DATASIZE]; // too much probably, virtual class + pointer
-public:
- bool is_null() const;
- void operator=(const RefPtr &p_other);
- bool operator==(const RefPtr &p_other) const;
- bool operator!=(const RefPtr &p_other) const;
- RID get_rid() const;
- void unref();
- _FORCE_INLINE_ void *get_data() const { return data; }
- RefPtr(const RefPtr &p_other);
- RefPtr();
- ~RefPtr();
-};
-
-#endif // REF_PTR_H
diff --git a/core/reference.cpp b/core/reference.cpp
index 5c211fe301..dd65ccce69 100644
--- a/core/reference.cpp
+++ b/core/reference.cpp
@@ -102,7 +102,8 @@ bool Reference::unreference() {
return die;
}
-Reference::Reference() {
+Reference::Reference() :
+ Object(true) {
refcount.init();
refcount_init.init();
diff --git a/core/reference.h b/core/reference.h
index d2314005b9..b01e0035a7 100644
--- a/core/reference.h
+++ b/core/reference.h
@@ -33,7 +33,6 @@
#include "core/class_db.h"
#include "core/object.h"
-#include "core/ref_ptr.h"
#include "core/safe_refcount.h"
class Reference : public Object {
@@ -133,17 +132,9 @@ public:
return reference;
}
- RefPtr get_ref_ptr() const {
-
- RefPtr refptr;
- Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data());
- *irr = *this;
- return refptr;
- };
-
operator Variant() const {
- return Variant(get_ref_ptr());
+ return Variant(reference);
}
void operator=(const Ref &p_from) {
@@ -165,33 +156,24 @@ public:
r.reference = NULL;
}
- void operator=(const RefPtr &p_refptr) {
+ void operator=(const Variant &p_variant) {
- Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(p_refptr.get_data());
- Reference *refb = irr->ptr();
- if (!refb) {
- unref();
+ Object *object = p_variant.get_validated_object();
+
+ if (object == reference) {
return;
}
- Ref r;
- r.reference = Object::cast_to<T>(refb);
- ref(r);
- r.reference = NULL;
- }
- void operator=(const Variant &p_variant) {
+ unref();
- RefPtr refptr = p_variant;
- Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data());
- Reference *refb = irr->ptr();
- if (!refb) {
- unref();
+ if (!object) {
return;
}
- Ref r;
- r.reference = Object::cast_to<T>(refb);
- ref(r);
- r.reference = NULL;
+
+ Reference *r = Object::cast_to<Reference>(object);
+ if (r && r->reference()) {
+ reference = static_cast<T *>(r);
+ }
}
template <class T_Other>
@@ -237,33 +219,19 @@ public:
Ref(const Variant &p_variant) {
- RefPtr refptr = p_variant;
- Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data());
- reference = NULL;
- Reference *refb = irr->ptr();
- if (!refb) {
- unref();
+ Object *object = p_variant.get_validated_object();
+
+ if (!object) {
+ reference = nullptr;
return;
}
- Ref r;
- r.reference = Object::cast_to<T>(refb);
- ref(r);
- r.reference = NULL;
- }
-
- Ref(const RefPtr &p_refptr) {
- Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(p_refptr.get_data());
- reference = NULL;
- Reference *refb = irr->ptr();
- if (!refb) {
- unref();
- return;
+ Reference *r = Object::cast_to<Reference>(object);
+ if (r && r->reference()) {
+ reference = static_cast<T *>(r);
+ } else {
+ reference = nullptr;
}
- Ref r;
- r.reference = Object::cast_to<T>(refb);
- ref(r);
- r.reference = NULL;
}
inline bool is_valid() const { return reference != NULL; }
@@ -340,32 +308,6 @@ struct PtrToArg<const Ref<T> &> {
}
};
-//this is for RefPtr
-
-template <>
-struct PtrToArg<RefPtr> {
-
- _FORCE_INLINE_ static RefPtr convert(const void *p_ptr) {
-
- return Ref<Reference>(const_cast<Reference *>(reinterpret_cast<const Reference *>(p_ptr))).get_ref_ptr();
- }
-
- _FORCE_INLINE_ static void encode(RefPtr p_val, const void *p_ptr) {
-
- Ref<Reference> r = p_val;
- *(Ref<Reference> *)p_ptr = r;
- }
-};
-
-template <>
-struct PtrToArg<const RefPtr &> {
-
- _FORCE_INLINE_ static RefPtr convert(const void *p_ptr) {
-
- return Ref<Reference>(const_cast<Reference *>(reinterpret_cast<const Reference *>(p_ptr))).get_ref_ptr();
- }
-};
-
#endif // PTRCALL_ENABLED
#ifdef DEBUG_METHODS_ENABLED
diff --git a/core/resource.h b/core/resource.h
index 00d330a094..b30788010b 100644
--- a/core/resource.h
+++ b/core/resource.h
@@ -33,7 +33,6 @@
#include "core/class_db.h"
#include "core/object.h"
-#include "core/ref_ptr.h"
#include "core/reference.h"
#include "core/safe_refcount.h"
#include "core/self_list.h"
diff --git a/core/type_info.h b/core/type_info.h
index b9e5b61a6a..9ca6d7fe73 100644
--- a/core/type_info.h
+++ b/core/type_info.h
@@ -169,24 +169,6 @@ MAKE_TYPE_INFO(IP_Address, Variant::STRING)
class BSP_Tree;
MAKE_TYPE_INFO(BSP_Tree, Variant::DICTIONARY)
-//for RefPtr
-template <>
-struct GetTypeInfo<RefPtr> {
- static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
- static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
- static inline PropertyInfo get_class_info() {
- return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, "Reference");
- }
-};
-template <>
-struct GetTypeInfo<const RefPtr &> {
- static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
- static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
- static inline PropertyInfo get_class_info() {
- return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, "Reference");
- }
-};
-
//objectID
template <>
struct GetTypeInfo<ObjectID> {
diff --git a/core/variant.cpp b/core/variant.cpp
index 0f04710d13..c2ffe3721f 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -908,6 +908,14 @@ bool Variant::is_one() const {
return false;
}
+bool Variant::is_null() const {
+ if (type == OBJECT && _get_obj().obj) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
void Variant::reference(const Variant &p_variant) {
switch (type) {
@@ -999,7 +1007,20 @@ void Variant::reference(const Variant &p_variant) {
} break;
case OBJECT: {
- memnew_placement(_data._mem, ObjData(p_variant._get_obj()));
+ memnew_placement(_data._mem, ObjData);
+
+ if (p_variant._get_obj().obj && p_variant._get_obj().id.is_reference()) {
+ Reference *reference = static_cast<Reference *>(p_variant._get_obj().obj);
+ if (!reference->reference()) {
+ _get_obj().obj = nullptr;
+ _get_obj().id = ObjectID();
+ break;
+ }
+ }
+
+ _get_obj().obj = const_cast<Object *>(p_variant._get_obj().obj);
+ _get_obj().id = p_variant._get_obj().id;
+
} break;
case NODE_PATH: {
@@ -1114,8 +1135,15 @@ void Variant::clear() {
} break;
case OBJECT: {
+ if (_get_obj().id.is_reference()) {
+ //we are safe that there is a reference here
+ Reference *reference = static_cast<Reference *>(_get_obj().obj);
+ if (reference->unreference()) {
+ memdelete(reference);
+ }
+ }
_get_obj().obj = NULL;
- _get_obj().ref.unref();
+ _get_obj().id = ObjectID();
} break;
case _RID: {
// not much need probably
@@ -1589,14 +1617,11 @@ String Variant::stringify(List<const void *> &stack) const {
case OBJECT: {
if (_get_obj().obj) {
-#ifdef DEBUG_ENABLED
- if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) {
- //only if debugging!
- if (!ObjectDB::instance_validate(_get_obj().obj)) {
- return "[Deleted Object]";
- };
+
+ if (!_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
+ return "[Freed Object]";
};
-#endif
+
return _get_obj().obj->to_string();
} else
return "[Object:null]";
@@ -1739,24 +1764,16 @@ Variant::operator NodePath() const {
return NodePath();
}
-Variant::operator RefPtr() const {
-
- if (type == OBJECT)
- return _get_obj().ref;
- else
- return RefPtr();
-}
-
Variant::operator RID() const {
if (type == _RID)
return *reinterpret_cast<const RID *>(_data._mem);
- else if (type == OBJECT && !_get_obj().ref.is_null()) {
- return _get_obj().ref.get_rid();
+ else if (type == OBJECT && _get_obj().obj == nullptr) {
+ return RID();
} else if (type == OBJECT && _get_obj().obj) {
#ifdef DEBUG_ENABLED
if (ScriptDebugger::get_singleton()) {
- ERR_FAIL_COND_V_MSG(!ObjectDB::instance_validate(_get_obj().obj), RID(), "Invalid pointer (object was deleted).");
+ ERR_FAIL_COND_V_MSG(ObjectDB::get_instance(_get_obj().id) == nullptr, RID(), "Invalid pointer (object was freed).");
};
#endif
Variant::CallError ce;
@@ -1777,6 +1794,25 @@ Variant::operator Object *() const {
else
return NULL;
}
+
+Object *Variant::get_validated_object_with_check(bool &r_previously_freed) const {
+ if (type == OBJECT) {
+ Object *instance = ObjectDB::get_instance(_get_obj().id);
+ r_previously_freed = !instance && _get_obj().id != ObjectID();
+ return instance;
+ } else {
+ r_previously_freed = false;
+ return NULL;
+ }
+}
+
+Object *Variant::get_validated_object() const {
+ if (type == OBJECT)
+ return ObjectDB::get_instance(_get_obj().id);
+ else
+ return NULL;
+}
+
Variant::operator Node *() const {
if (type == OBJECT)
@@ -2289,15 +2325,6 @@ Variant::Variant(const NodePath &p_node_path) {
memnew_placement(_data._mem, NodePath(p_node_path));
}
-Variant::Variant(const RefPtr &p_resource) {
-
- type = OBJECT;
- memnew_placement(_data._mem, ObjData);
- REF *ref = reinterpret_cast<REF *>(p_resource.get_data());
- _get_obj().obj = ref->ptr();
- _get_obj().ref = p_resource;
-}
-
Variant::Variant(const RID &p_rid) {
type = _RID;
@@ -2309,7 +2336,24 @@ Variant::Variant(const Object *p_object) {
type = OBJECT;
memnew_placement(_data._mem, ObjData);
- _get_obj().obj = const_cast<Object *>(p_object);
+
+ if (p_object) {
+
+ if (p_object->is_reference()) {
+ Reference *reference = const_cast<Reference *>(static_cast<const Reference *>(p_object));
+ if (!reference->init_ref()) {
+ _get_obj().obj = nullptr;
+ _get_obj().id = ObjectID();
+ return;
+ }
+ }
+
+ _get_obj().obj = const_cast<Object *>(p_object);
+ _get_obj().id = p_object->get_instance_id();
+ } else {
+ _get_obj().obj = nullptr;
+ _get_obj().id = ObjectID();
+ }
}
Variant::Variant(const Dictionary &p_dictionary) {
@@ -2620,7 +2664,26 @@ void Variant::operator=(const Variant &p_variant) {
} break;
case OBJECT: {
- *reinterpret_cast<ObjData *>(_data._mem) = p_variant._get_obj();
+ if (_get_obj().id.is_reference()) {
+ //we are safe that there is a reference here
+ Reference *reference = static_cast<Reference *>(_get_obj().obj);
+ if (reference->unreference()) {
+ memdelete(reference);
+ }
+ }
+
+ if (p_variant._get_obj().obj && p_variant._get_obj().id.is_reference()) {
+ Reference *reference = static_cast<Reference *>(p_variant._get_obj().obj);
+ if (!reference->reference()) {
+ _get_obj().obj = nullptr;
+ _get_obj().id = ObjectID();
+ break;
+ }
+ }
+
+ _get_obj().obj = const_cast<Object *>(p_variant._get_obj().obj);
+ _get_obj().id = p_variant._get_obj().id;
+
} break;
case NODE_PATH: {
@@ -3131,7 +3194,7 @@ bool Variant::hash_compare(const Variant &p_variant) const {
bool Variant::is_ref() const {
- return type == OBJECT && !_get_obj().ref.is_null();
+ return type == OBJECT && _get_obj().id.is_reference();
}
Vector<Variant> varray() {
diff --git a/core/variant.h b/core/variant.h
index d8007f9e12..bb3840932d 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -46,11 +46,9 @@
#include "core/node_path.h"
#include "core/object_id.h"
#include "core/pool_vector.h"
-#include "core/ref_ptr.h"
#include "core/rid.h"
#include "core/ustring.h"
-class RefPtr;
class Object;
class Node; // helper
class Control; // helper
@@ -128,12 +126,12 @@ private:
struct ObjData {
+ ObjectID id;
Object *obj;
- RefPtr ref;
};
- _FORCE_INLINE_ ObjData &_get_obj();
- _FORCE_INLINE_ const ObjData &_get_obj() const;
+ _ALWAYS_INLINE_ ObjData &_get_obj();
+ _ALWAYS_INLINE_ const ObjData &_get_obj() const;
union {
bool _bool;
@@ -162,6 +160,7 @@ public:
bool is_shared() const;
bool is_zero() const;
bool is_one() const;
+ bool is_null() const;
operator bool() const;
operator signed int() const;
@@ -197,7 +196,6 @@ public:
operator Color() const;
operator NodePath() const;
- operator RefPtr() const;
operator RID() const;
operator Object *() const;
@@ -235,6 +233,9 @@ public:
operator IP_Address() const;
+ Object *get_validated_object() const;
+ Object *get_validated_object_with_check(bool &r_previously_freed) const;
+
Variant(bool p_bool);
Variant(signed int p_int); // real one
Variant(unsigned int p_int);
@@ -267,7 +268,6 @@ public:
Variant(const Transform &p_transform);
Variant(const Color &p_color);
Variant(const NodePath &p_node_path);
- Variant(const RefPtr &p_resource);
Variant(const RID &p_rid);
Variant(const Object *p_object);
Variant(const Dictionary &p_dictionary);
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index f088705cdd..ac995d1c78 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -1099,12 +1099,9 @@ void Variant::call_ptr(const StringName &p_method, const Variant **p_args, int p
return;
}
#ifdef DEBUG_ENABLED
- if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) {
- //only if debugging!
- if (!ObjectDB::instance_validate(obj)) {
- r_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
- return;
- }
+ if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
+ r_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
+ return;
}
#endif
@@ -1274,18 +1271,11 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i
bool Variant::has_method(const StringName &p_method) const {
if (type == OBJECT) {
- Object *obj = operator Object *();
+ Object *obj = get_validated_object();
if (!obj)
return false;
-#ifdef DEBUG_ENABLED
- if (ScriptDebugger::get_singleton()) {
- if (ObjectDB::instance_validate(obj)) {
-#endif
- return obj->has_method(p_method);
-#ifdef DEBUG_ENABLED
- }
- }
-#endif
+
+ return obj->has_method(p_method);
}
const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[type];
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 6caa224cfe..c7a52b0347 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -1515,7 +1515,7 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool
#ifdef DEBUG_ENABLED
if (!_get_obj().obj) {
break;
- } else if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
+ } else if (ScriptDebugger::get_singleton() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
break;
}
@@ -1684,7 +1684,7 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
return "Instance base is null.";
} else {
- if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
+ if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
if (r_valid)
*r_valid = false;
return "Attempted use of stray pointer object.";
@@ -2172,13 +2172,11 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
if (obj) {
#ifdef DEBUG_ENABLED
- if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) {
+ if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
- if (!ObjectDB::instance_validate(obj)) {
- WARN_PRINT("Attempted use of stray pointer object.");
- valid = false;
- return;
- }
+ WARN_PRINT("Attempted use of previously freed pointer object.");
+ valid = false;
+ return;
}
#endif
@@ -2546,12 +2544,10 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
if (obj) {
#ifdef DEBUG_ENABLED
- if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) {
- //only if debugging!
- if (!ObjectDB::instance_validate(obj)) {
- valid = false;
- return "Attempted get on stray pointer.";
- }
+
+ if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
+ valid = false;
+ return "Attempted get on previously freed instance.";
}
#endif
@@ -2611,15 +2607,14 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
bool valid = false;
#ifdef DEBUG_ENABLED
- if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) {
- //only if debugging!
- if (!ObjectDB::instance_validate(obj)) {
- if (r_valid) {
- *r_valid = false;
- }
- return true; // Attempted get on stray pointer.
+
+ if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
+ if (r_valid) {
+ *r_valid = false;
}
+ return true; // Attempted get on stray pointer.
}
+
#endif
if (p_index.get_type() != Variant::STRING) {
@@ -2883,13 +2878,12 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
Object *obj = _get_obj().obj;
if (obj) {
#ifdef DEBUG_ENABLED
- if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) {
- //only if debugging!
- if (!ObjectDB::instance_validate(obj)) {
- WARN_PRINT("Attempted get_property list on stray pointer.");
- return;
- }
+
+ if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
+ WARN_PRINT("Attempted get_property list on previously freed instance.");
+ return;
}
+
#endif
obj->get_property_list(p_list);
@@ -2961,16 +2955,18 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
} break;
case OBJECT: {
-#ifdef DEBUG_ENABLED
if (!_get_obj().obj) {
valid = false;
return false;
}
- if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
+#ifdef DEBUG_ENABLED
+
+ if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
valid = false;
return false;
}
+
#endif
Variant::CallError ce;
ce.error = Variant::CallError::CALL_OK;
@@ -3129,16 +3125,18 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
} break;
case OBJECT: {
-#ifdef DEBUG_ENABLED
if (!_get_obj().obj) {
valid = false;
return false;
}
- if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
+#ifdef DEBUG_ENABLED
+
+ if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
valid = false;
return false;
}
+
#endif
Variant::CallError ce;
ce.error = Variant::CallError::CALL_OK;
@@ -3288,16 +3286,16 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
} break;
case OBJECT: {
-#ifdef DEBUG_ENABLED
if (!_get_obj().obj) {
r_valid = false;
return Variant();
}
-
- if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
+#ifdef DEBUG_ENABLED
+ if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
r_valid = false;
return Variant();
}
+
#endif
Variant::CallError ce;
ce.error = Variant::CallError::CALL_OK;