Browse Source

Store arrays inside of Variant as shared.

Arrays inside of Variant are unique and use reference counting.
When you assign a variant containing a packed array to another, or
when you call non const functions to arrays, this will work even
if the array is inside a dictionary, so they will from now pass
as reference.

The difference with regular variant arrays is that, once passed
to a function in the C++ API, they are no longer shared. This is
required for security and thread safety, as those arrays are
mainly used to pass data back and forth even between threads.
Juan Linietsky 5 years ago
parent
commit
88f84c78ca
4 changed files with 325 additions and 183 deletions
  1. 71 49
      core/variant.cpp
  2. 72 4
      core/variant.h
  3. 109 84
      core/variant_call.cpp
  4. 73 46
      core/variant_op.cpp

+ 71 - 49
core/variant.cpp

@@ -1005,37 +1005,37 @@ bool Variant::is_zero() const {
 		// arrays
 		case PACKED_BYTE_ARRAY: {
 
-			return reinterpret_cast<const Vector<uint8_t> *>(_data._mem)->size() == 0;
+			return PackedArrayRef<uint8_t>::get_array(_data.packed_array).size() == 0;
 
 		} break;
 		case PACKED_INT_ARRAY: {
 
-			return reinterpret_cast<const Vector<int> *>(_data._mem)->size() == 0;
+			return PackedArrayRef<int32_t>::get_array(_data.packed_array).size() == 0;
 
 		} break;
 		case PACKED_REAL_ARRAY: {
 
-			return reinterpret_cast<const Vector<real_t> *>(_data._mem)->size() == 0;
+			return PackedArrayRef<real_t>::get_array(_data.packed_array).size() == 0;
 
 		} break;
 		case PACKED_STRING_ARRAY: {
 
-			return reinterpret_cast<const Vector<String> *>(_data._mem)->size() == 0;
+			return PackedArrayRef<String>::get_array(_data.packed_array).size() == 0;
 
 		} break;
 		case PACKED_VECTOR2_ARRAY: {
 
-			return reinterpret_cast<const Vector<Vector2> *>(_data._mem)->size() == 0;
+			return PackedArrayRef<Vector2>::get_array(_data.packed_array).size() == 0;
 
 		} break;
 		case PACKED_VECTOR3_ARRAY: {
 
-			return reinterpret_cast<const Vector<Vector3> *>(_data._mem)->size() == 0;
+			return PackedArrayRef<Vector3>::get_array(_data.packed_array).size() == 0;
 
 		} break;
 		case PACKED_COLOR_ARRAY: {
 
-			return reinterpret_cast<const Vector<Color> *>(_data._mem)->size() == 0;
+			return PackedArrayRef<Color>::get_array(_data.packed_array).size() == 0;
 
 		} break;
 		default: {
@@ -1275,37 +1275,58 @@ void Variant::reference(const Variant &p_variant) {
 		// arrays
 		case PACKED_BYTE_ARRAY: {
 
-			memnew_placement(_data._mem, Vector<uint8_t>(*reinterpret_cast<const Vector<uint8_t> *>(p_variant._data._mem)));
+			_data.packed_array = static_cast<PackedArrayRef<uint8_t> *>(p_variant._data.packed_array)->reference();
+			if (!_data.packed_array) {
+				_data.packed_array = PackedArrayRef<uint8_t>::create();
+			}
 
 		} break;
 		case PACKED_INT_ARRAY: {
 
-			memnew_placement(_data._mem, Vector<int>(*reinterpret_cast<const Vector<int> *>(p_variant._data._mem)));
+			_data.packed_array = static_cast<PackedArrayRef<int32_t> *>(p_variant._data.packed_array)->reference();
+			if (!_data.packed_array) {
+				_data.packed_array = PackedArrayRef<int32_t>::create();
+			}
 
 		} break;
 		case PACKED_REAL_ARRAY: {
 
-			memnew_placement(_data._mem, Vector<real_t>(*reinterpret_cast<const Vector<real_t> *>(p_variant._data._mem)));
+			_data.packed_array = static_cast<PackedArrayRef<real_t> *>(p_variant._data.packed_array)->reference();
+			if (!_data.packed_array) {
+				_data.packed_array = PackedArrayRef<real_t>::create();
+			}
 
 		} break;
 		case PACKED_STRING_ARRAY: {
 
-			memnew_placement(_data._mem, Vector<String>(*reinterpret_cast<const Vector<String> *>(p_variant._data._mem)));
+			_data.packed_array = static_cast<PackedArrayRef<String> *>(p_variant._data.packed_array)->reference();
+			if (!_data.packed_array) {
+				_data.packed_array = PackedArrayRef<String>::create();
+			}
 
 		} break;
 		case PACKED_VECTOR2_ARRAY: {
 
-			memnew_placement(_data._mem, Vector<Vector2>(*reinterpret_cast<const Vector<Vector2> *>(p_variant._data._mem)));
+			_data.packed_array = static_cast<PackedArrayRef<Vector2> *>(p_variant._data.packed_array)->reference();
+			if (!_data.packed_array) {
+				_data.packed_array = PackedArrayRef<Vector2>::create();
+			}
 
 		} break;
 		case PACKED_VECTOR3_ARRAY: {
 
-			memnew_placement(_data._mem, Vector<Vector3>(*reinterpret_cast<const Vector<Vector3> *>(p_variant._data._mem)));
+			_data.packed_array = static_cast<PackedArrayRef<Vector3> *>(p_variant._data.packed_array)->reference();
+			if (!_data.packed_array) {
+				_data.packed_array = PackedArrayRef<Vector3>::create();
+			}
 
 		} break;
 		case PACKED_COLOR_ARRAY: {
 
-			memnew_placement(_data._mem, Vector<Color>(*reinterpret_cast<const Vector<Color> *>(p_variant._data._mem)));
+			_data.packed_array = static_cast<PackedArrayRef<Color> *>(p_variant._data.packed_array)->reference();
+			if (!_data.packed_array) {
+				_data.packed_array = PackedArrayRef<Color>::create();
+			}
 
 		} break;
 		default: {
@@ -1409,31 +1430,31 @@ void Variant::clear() {
 		// arrays
 		case PACKED_BYTE_ARRAY: {
 
-			reinterpret_cast<Vector<uint8_t> *>(_data._mem)->~Vector<uint8_t>();
+			PackedArrayRefBase::destroy(_data.packed_array);
 		} break;
 		case PACKED_INT_ARRAY: {
 
-			reinterpret_cast<Vector<int> *>(_data._mem)->~Vector<int>();
+			PackedArrayRefBase::destroy(_data.packed_array);
 		} break;
 		case PACKED_REAL_ARRAY: {
 
-			reinterpret_cast<Vector<real_t> *>(_data._mem)->~Vector<real_t>();
+			PackedArrayRefBase::destroy(_data.packed_array);
 		} break;
 		case PACKED_STRING_ARRAY: {
 
-			reinterpret_cast<Vector<String> *>(_data._mem)->~Vector<String>();
+			PackedArrayRefBase::destroy(_data.packed_array);
 		} break;
 		case PACKED_VECTOR2_ARRAY: {
 
-			reinterpret_cast<Vector<Vector2> *>(_data._mem)->~Vector<Vector2>();
+			PackedArrayRefBase::destroy(_data.packed_array);
 		} break;
 		case PACKED_VECTOR3_ARRAY: {
 
-			reinterpret_cast<Vector<Vector3> *>(_data._mem)->~Vector<Vector3>();
+			PackedArrayRefBase::destroy(_data.packed_array);
 		} break;
 		case PACKED_COLOR_ARRAY: {
 
-			reinterpret_cast<Vector<Color> *>(_data._mem)->~Vector<Color>();
+			PackedArrayRefBase::destroy(_data.packed_array);
 		} break;
 		default: {
 		} /* not needed */
@@ -2230,21 +2251,21 @@ Variant::operator Array() const {
 Variant::operator Vector<uint8_t>() const {
 
 	if (type == PACKED_BYTE_ARRAY)
-		return *reinterpret_cast<const Vector<uint8_t> *>(_data._mem);
+		return static_cast<PackedArrayRef<uint8_t> *>(_data.packed_array)->array;
 	else
 		return _convert_array_from_variant<Vector<uint8_t> >(*this);
 }
 Variant::operator Vector<int>() const {
 
 	if (type == PACKED_INT_ARRAY)
-		return *reinterpret_cast<const Vector<int> *>(_data._mem);
+		return static_cast<PackedArrayRef<int32_t> *>(_data.packed_array)->array;
 	else
 		return _convert_array_from_variant<Vector<int> >(*this);
 }
 Variant::operator Vector<real_t>() const {
 
 	if (type == PACKED_REAL_ARRAY)
-		return *reinterpret_cast<const Vector<real_t> *>(_data._mem);
+		return static_cast<PackedArrayRef<real_t> *>(_data.packed_array)->array;
 	else
 		return _convert_array_from_variant<Vector<real_t> >(*this);
 }
@@ -2252,21 +2273,21 @@ Variant::operator Vector<real_t>() const {
 Variant::operator Vector<String>() const {
 
 	if (type == PACKED_STRING_ARRAY)
-		return *reinterpret_cast<const Vector<String> *>(_data._mem);
+		return static_cast<PackedArrayRef<String> *>(_data.packed_array)->array;
 	else
 		return _convert_array_from_variant<Vector<String> >(*this);
 }
 Variant::operator Vector<Vector3>() const {
 
 	if (type == PACKED_VECTOR3_ARRAY)
-		return *reinterpret_cast<const Vector<Vector3> *>(_data._mem);
+		return static_cast<PackedArrayRef<Vector3> *>(_data.packed_array)->array;
 	else
 		return _convert_array_from_variant<Vector<Vector3> >(*this);
 }
 Variant::operator Vector<Vector2>() const {
 
 	if (type == PACKED_VECTOR2_ARRAY)
-		return *reinterpret_cast<const Vector<Vector2> *>(_data._mem);
+		return static_cast<PackedArrayRef<Vector2> *>(_data.packed_array)->array;
 	else
 		return _convert_array_from_variant<Vector<Vector2> >(*this);
 }
@@ -2274,7 +2295,7 @@ Variant::operator Vector<Vector2>() const {
 Variant::operator Vector<Color>() const {
 
 	if (type == PACKED_COLOR_ARRAY)
-		return *reinterpret_cast<const Vector<Color> *>(_data._mem);
+		return static_cast<PackedArrayRef<Color> *>(_data.packed_array)->array;
 	else
 		return _convert_array_from_variant<Vector<Color> >(*this);
 }
@@ -2650,38 +2671,39 @@ Variant::Variant(const Vector<RID> &p_array) {
 Variant::Variant(const Vector<uint8_t> &p_raw_array) {
 
 	type = PACKED_BYTE_ARRAY;
-	memnew_placement(_data._mem, Vector<uint8_t>(p_raw_array));
+
+	_data.packed_array = PackedArrayRef<uint8_t>::create(p_raw_array);
 }
 Variant::Variant(const Vector<int> &p_int_array) {
 
 	type = PACKED_INT_ARRAY;
-	memnew_placement(_data._mem, Vector<int>(p_int_array));
+	_data.packed_array = PackedArrayRef<int32_t>::create(p_int_array);
 }
 Variant::Variant(const Vector<real_t> &p_real_array) {
 
 	type = PACKED_REAL_ARRAY;
-	memnew_placement(_data._mem, Vector<real_t>(p_real_array));
+	_data.packed_array = PackedArrayRef<real_t>::create(p_real_array);
 }
 Variant::Variant(const Vector<String> &p_string_array) {
 
 	type = PACKED_STRING_ARRAY;
-	memnew_placement(_data._mem, Vector<String>(p_string_array));
+	_data.packed_array = PackedArrayRef<String>::create(p_string_array);
 }
 Variant::Variant(const Vector<Vector3> &p_vector3_array) {
 
 	type = PACKED_VECTOR3_ARRAY;
-	memnew_placement(_data._mem, Vector<Vector3>(p_vector3_array));
+	_data.packed_array = PackedArrayRef<Vector3>::create(p_vector3_array);
 }
 
 Variant::Variant(const Vector<Vector2> &p_vector2_array) {
 
 	type = PACKED_VECTOR2_ARRAY;
-	memnew_placement(_data._mem, Vector<Vector2>(p_vector2_array));
+	_data.packed_array = PackedArrayRef<Vector2>::create(p_vector2_array);
 }
 Variant::Variant(const Vector<Color> &p_color_array) {
 
 	type = PACKED_COLOR_ARRAY;
-	memnew_placement(_data._mem, Vector<Color>(p_color_array));
+	_data.packed_array = PackedArrayRef<Color>::create(p_color_array);
 }
 
 Variant::Variant(const Vector<Face3> &p_face_array) {
@@ -2874,31 +2896,31 @@ void Variant::operator=(const Variant &p_variant) {
 		// arrays
 		case PACKED_BYTE_ARRAY: {
 
-			*reinterpret_cast<Vector<uint8_t> *>(_data._mem) = *reinterpret_cast<const Vector<uint8_t> *>(p_variant._data._mem);
+			_data.packed_array = PackedArrayRef<uint8_t>::reference_from(_data.packed_array, p_variant._data.packed_array);
 		} break;
 		case PACKED_INT_ARRAY: {
 
-			*reinterpret_cast<Vector<int> *>(_data._mem) = *reinterpret_cast<const Vector<int> *>(p_variant._data._mem);
+			_data.packed_array = PackedArrayRef<int32_t>::reference_from(_data.packed_array, p_variant._data.packed_array);
 		} break;
 		case PACKED_REAL_ARRAY: {
 
-			*reinterpret_cast<Vector<real_t> *>(_data._mem) = *reinterpret_cast<const Vector<real_t> *>(p_variant._data._mem);
+			_data.packed_array = PackedArrayRef<real_t>::reference_from(_data.packed_array, p_variant._data.packed_array);
 		} break;
 		case PACKED_STRING_ARRAY: {
 
-			*reinterpret_cast<Vector<String> *>(_data._mem) = *reinterpret_cast<const Vector<String> *>(p_variant._data._mem);
+			_data.packed_array = PackedArrayRef<String>::reference_from(_data.packed_array, p_variant._data.packed_array);
 		} break;
 		case PACKED_VECTOR2_ARRAY: {
 
-			*reinterpret_cast<Vector<Vector2> *>(_data._mem) = *reinterpret_cast<const Vector<Vector2> *>(p_variant._data._mem);
+			_data.packed_array = PackedArrayRef<Vector2>::reference_from(_data.packed_array, p_variant._data.packed_array);
 		} break;
 		case PACKED_VECTOR3_ARRAY: {
 
-			*reinterpret_cast<Vector<Vector3> *>(_data._mem) = *reinterpret_cast<const Vector<Vector3> *>(p_variant._data._mem);
+			_data.packed_array = PackedArrayRef<Vector3>::reference_from(_data.packed_array, p_variant._data.packed_array);
 		} break;
 		case PACKED_COLOR_ARRAY: {
 
-			*reinterpret_cast<Vector<Color> *>(_data._mem) = *reinterpret_cast<const Vector<Color> *>(p_variant._data._mem);
+			_data.packed_array = PackedArrayRef<Color>::reference_from(_data.packed_array, p_variant._data.packed_array);
 		} break;
 		default: {
 		}
@@ -3106,7 +3128,7 @@ uint32_t Variant::hash() const {
 		} break;
 		case PACKED_BYTE_ARRAY: {
 
-			const Vector<uint8_t> &arr = *reinterpret_cast<const Vector<uint8_t> *>(_data._mem);
+			const Vector<uint8_t> &arr = PackedArrayRef<uint8_t>::get_array(_data.packed_array);
 			int len = arr.size();
 			if (likely(len)) {
 				const uint8_t *r = arr.ptr();
@@ -3118,7 +3140,7 @@ uint32_t Variant::hash() const {
 		} break;
 		case PACKED_INT_ARRAY: {
 
-			const Vector<int> &arr = *reinterpret_cast<const Vector<int> *>(_data._mem);
+			const Vector<int32_t> &arr = PackedArrayRef<int32_t>::get_array(_data.packed_array);
 			int len = arr.size();
 			if (likely(len)) {
 				const int *r = arr.ptr();
@@ -3130,7 +3152,7 @@ uint32_t Variant::hash() const {
 		} break;
 		case PACKED_REAL_ARRAY: {
 
-			const Vector<real_t> &arr = *reinterpret_cast<const Vector<real_t> *>(_data._mem);
+			const Vector<real_t> &arr = PackedArrayRef<real_t>::get_array(_data.packed_array);
 			int len = arr.size();
 
 			if (likely(len)) {
@@ -3144,7 +3166,7 @@ uint32_t Variant::hash() const {
 		case PACKED_STRING_ARRAY: {
 
 			uint32_t hash = 5831;
-			const Vector<String> &arr = *reinterpret_cast<const Vector<String> *>(_data._mem);
+			const Vector<String> &arr = PackedArrayRef<String>::get_array(_data.packed_array);
 			int len = arr.size();
 
 			if (likely(len)) {
@@ -3160,7 +3182,7 @@ uint32_t Variant::hash() const {
 		case PACKED_VECTOR2_ARRAY: {
 
 			uint32_t hash = 5831;
-			const Vector<Vector2> &arr = *reinterpret_cast<const Vector<Vector2> *>(_data._mem);
+			const Vector<Vector2> &arr = PackedArrayRef<Vector2>::get_array(_data.packed_array);
 			int len = arr.size();
 
 			if (likely(len)) {
@@ -3177,7 +3199,7 @@ uint32_t Variant::hash() const {
 		case PACKED_VECTOR3_ARRAY: {
 
 			uint32_t hash = 5831;
-			const Vector<Vector3> &arr = *reinterpret_cast<const Vector<Vector3> *>(_data._mem);
+			const Vector<Vector3> &arr = PackedArrayRef<Vector3>::get_array(_data.packed_array);
 			int len = arr.size();
 
 			if (likely(len)) {
@@ -3195,7 +3217,7 @@ uint32_t Variant::hash() const {
 		case PACKED_COLOR_ARRAY: {
 
 			uint32_t hash = 5831;
-			const Vector<Color> &arr = *reinterpret_cast<const Vector<Color> *>(_data._mem);
+			const Vector<Color> &arr = PackedArrayRef<Color>::get_array(_data.packed_array);
 			int len = arr.size();
 
 			if (likely(len)) {

+ 72 - 4
core/variant.h

@@ -136,6 +136,65 @@ private:
 		Object *obj;
 	};
 
+	/* array helpers */
+	struct PackedArrayRefBase {
+		SafeRefCount refcount;
+		_FORCE_INLINE_ PackedArrayRefBase *reference() {
+			if (this->refcount.ref()) {
+				return this;
+			} else {
+				return nullptr;
+			}
+		}
+		static _FORCE_INLINE_ PackedArrayRefBase *reference_from(PackedArrayRefBase *p_base, PackedArrayRefBase *p_from) {
+			if (p_base == p_from) {
+				return p_base; //same thing, do nothing
+			}
+
+			if (p_from->reference()) {
+				if (p_base->refcount.unref()) {
+					memdelete(p_base);
+				}
+				return p_from;
+			} else {
+				return p_base; //keep, could not reference new
+			}
+		}
+		static _FORCE_INLINE_ void destroy(PackedArrayRefBase *p_array) {
+			if (p_array->refcount.unref()) {
+				memdelete(p_array);
+			}
+		}
+		_FORCE_INLINE_ virtual ~PackedArrayRefBase() {} //needs virtual destructor, but make inline
+	};
+
+	template <class T>
+	struct PackedArrayRef : public PackedArrayRefBase {
+		Vector<T> array;
+		static _FORCE_INLINE_ PackedArrayRef<T> *create() {
+			return memnew(PackedArrayRef<T>);
+		}
+		static _FORCE_INLINE_ PackedArrayRef<T> *create(const Vector<T> &p_from) {
+			return memnew(PackedArrayRef<T>(p_from));
+		}
+
+		static _FORCE_INLINE_ const Vector<T> &get_array(PackedArrayRefBase *p_base) {
+			return static_cast<PackedArrayRef<T> *>(p_base)->array;
+		}
+		static _FORCE_INLINE_ Vector<T> *get_array_ptr(const PackedArrayRefBase *p_base) {
+			return &const_cast<PackedArrayRef<T> *>(static_cast<const PackedArrayRef<T> *>(p_base))->array;
+		}
+
+		_FORCE_INLINE_ PackedArrayRef(const Vector<T> &p_from) {
+			array = p_from;
+			refcount.init();
+		}
+		_FORCE_INLINE_ PackedArrayRef() {
+			refcount.init();
+		}
+	};
+
+	/* end of array helpers */
 	_ALWAYS_INLINE_ ObjData &_get_obj();
 	_ALWAYS_INLINE_ const ObjData &_get_obj() const;
 
@@ -147,6 +206,7 @@ private:
 		::AABB *_aabb;
 		Basis *_basis;
 		Transform *_transform;
+		PackedArrayRefBase *packed_array;
 		void *_ptr; //generic pointer
 		uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)];
 	} _data GCC_ALIGNED_8;
@@ -155,14 +215,20 @@ private:
 	void clear();
 
 public:
-	_FORCE_INLINE_ Type get_type() const { return type; }
+	_FORCE_INLINE_ Type get_type() const {
+		return type;
+	}
 	static String get_type_name(Variant::Type p_type);
 	static bool can_convert(Type p_type_from, Type p_type_to);
 	static bool can_convert_strict(Type p_type_from, Type p_type_to);
 
 	bool is_ref() const;
-	_FORCE_INLINE_ bool is_num() const { return type == INT || type == REAL; };
-	_FORCE_INLINE_ bool is_array() const { return type >= ARRAY; };
+	_FORCE_INLINE_ bool is_num() const {
+		return type == INT || type == REAL;
+	};
+	_FORCE_INLINE_ bool is_array() const {
+		return type >= ARRAY;
+	};
 	bool is_shared() const;
 	bool is_zero() const;
 	bool is_one() const;
@@ -405,7 +471,9 @@ public:
 
 	void operator=(const Variant &p_variant); // only this is enough for all the other types
 	Variant(const Variant &p_variant);
-	_FORCE_INLINE_ Variant() { type = NIL; }
+	_FORCE_INLINE_ Variant() {
+		type = NIL;
+	}
 	_FORCE_INLINE_ ~Variant() {
 		if (type != Variant::NIL) clear();
 	}

+ 109 - 84
core/variant_call.cpp

@@ -666,90 +666,115 @@ struct _VariantCall {
 		r_ret = s;
 	}
 
-	VCALL_LOCALMEM0R(PackedByteArray, size);
-	VCALL_LOCALMEM0R(PackedByteArray, empty);
-	VCALL_LOCALMEM2(PackedByteArray, set);
-	VCALL_LOCALMEM1R(PackedByteArray, get);
-	VCALL_LOCALMEM1(PackedByteArray, push_back);
-	VCALL_LOCALMEM1(PackedByteArray, resize);
-	VCALL_LOCALMEM2R(PackedByteArray, insert);
-	VCALL_LOCALMEM1(PackedByteArray, remove);
-	VCALL_LOCALMEM1(PackedByteArray, append);
-	VCALL_LOCALMEM1(PackedByteArray, append_array);
-	VCALL_LOCALMEM0(PackedByteArray, invert);
-	VCALL_LOCALMEM2R(PackedByteArray, subarray);
-
-	VCALL_LOCALMEM0R(PackedIntArray, size);
-	VCALL_LOCALMEM0R(PackedIntArray, empty);
-	VCALL_LOCALMEM2(PackedIntArray, set);
-	VCALL_LOCALMEM1R(PackedIntArray, get);
-	VCALL_LOCALMEM1(PackedIntArray, push_back);
-	VCALL_LOCALMEM1(PackedIntArray, resize);
-	VCALL_LOCALMEM2R(PackedIntArray, insert);
-	VCALL_LOCALMEM1(PackedIntArray, remove);
-	VCALL_LOCALMEM1(PackedIntArray, append);
-	VCALL_LOCALMEM1(PackedIntArray, append_array);
-	VCALL_LOCALMEM0(PackedIntArray, invert);
-
-	VCALL_LOCALMEM0R(PackedRealArray, size);
-	VCALL_LOCALMEM0R(PackedRealArray, empty);
-	VCALL_LOCALMEM2(PackedRealArray, set);
-	VCALL_LOCALMEM1R(PackedRealArray, get);
-	VCALL_LOCALMEM1(PackedRealArray, push_back);
-	VCALL_LOCALMEM1(PackedRealArray, resize);
-	VCALL_LOCALMEM2R(PackedRealArray, insert);
-	VCALL_LOCALMEM1(PackedRealArray, remove);
-	VCALL_LOCALMEM1(PackedRealArray, append);
-	VCALL_LOCALMEM1(PackedRealArray, append_array);
-	VCALL_LOCALMEM0(PackedRealArray, invert);
-
-	VCALL_LOCALMEM0R(PackedStringArray, size);
-	VCALL_LOCALMEM0R(PackedStringArray, empty);
-	VCALL_LOCALMEM2(PackedStringArray, set);
-	VCALL_LOCALMEM1R(PackedStringArray, get);
-	VCALL_LOCALMEM1(PackedStringArray, push_back);
-	VCALL_LOCALMEM1(PackedStringArray, resize);
-	VCALL_LOCALMEM2R(PackedStringArray, insert);
-	VCALL_LOCALMEM1(PackedStringArray, remove);
-	VCALL_LOCALMEM1(PackedStringArray, append);
-	VCALL_LOCALMEM1(PackedStringArray, append_array);
-	VCALL_LOCALMEM0(PackedStringArray, invert);
-
-	VCALL_LOCALMEM0R(PackedVector2Array, size);
-	VCALL_LOCALMEM0R(PackedVector2Array, empty);
-	VCALL_LOCALMEM2(PackedVector2Array, set);
-	VCALL_LOCALMEM1R(PackedVector2Array, get);
-	VCALL_LOCALMEM1(PackedVector2Array, push_back);
-	VCALL_LOCALMEM1(PackedVector2Array, resize);
-	VCALL_LOCALMEM2R(PackedVector2Array, insert);
-	VCALL_LOCALMEM1(PackedVector2Array, remove);
-	VCALL_LOCALMEM1(PackedVector2Array, append);
-	VCALL_LOCALMEM1(PackedVector2Array, append_array);
-	VCALL_LOCALMEM0(PackedVector2Array, invert);
-
-	VCALL_LOCALMEM0R(PackedVector3Array, size);
-	VCALL_LOCALMEM0R(PackedVector3Array, empty);
-	VCALL_LOCALMEM2(PackedVector3Array, set);
-	VCALL_LOCALMEM1R(PackedVector3Array, get);
-	VCALL_LOCALMEM1(PackedVector3Array, push_back);
-	VCALL_LOCALMEM1(PackedVector3Array, resize);
-	VCALL_LOCALMEM2R(PackedVector3Array, insert);
-	VCALL_LOCALMEM1(PackedVector3Array, remove);
-	VCALL_LOCALMEM1(PackedVector3Array, append);
-	VCALL_LOCALMEM1(PackedVector3Array, append_array);
-	VCALL_LOCALMEM0(PackedVector3Array, invert);
-
-	VCALL_LOCALMEM0R(PackedColorArray, size);
-	VCALL_LOCALMEM0R(PackedColorArray, empty);
-	VCALL_LOCALMEM2(PackedColorArray, set);
-	VCALL_LOCALMEM1R(PackedColorArray, get);
-	VCALL_LOCALMEM1(PackedColorArray, push_back);
-	VCALL_LOCALMEM1(PackedColorArray, resize);
-	VCALL_LOCALMEM2R(PackedColorArray, insert);
-	VCALL_LOCALMEM1(PackedColorArray, remove);
-	VCALL_LOCALMEM1(PackedColorArray, append);
-	VCALL_LOCALMEM1(PackedColorArray, append_array);
-	VCALL_LOCALMEM0(PackedColorArray, invert);
+#define VCALL_PARRMEM0(m_type, m_elemtype, m_method) \
+	static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(); }
+#define VCALL_PARRMEM0R(m_type, m_elemtype, m_method) \
+	static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(); }
+#define VCALL_PARRMEM1(m_type, m_elemtype, m_method) \
+	static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0]); }
+#define VCALL_PARRMEM1R(m_type, m_elemtype, m_method) \
+	static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0]); }
+#define VCALL_PARRMEM2(m_type, m_elemtype, m_method) \
+	static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1]); }
+#define VCALL_PARRMEM2R(m_type, m_elemtype, m_method) \
+	static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1]); }
+#define VCALL_PARRMEM3(m_type, m_elemtype, m_method) \
+	static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2]); }
+#define VCALL_PARRMEM3R(m_type, m_elemtype, m_method) \
+	static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2]); }
+#define VCALL_PARRMEM4(m_type, m_elemtype, m_method) \
+	static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); }
+#define VCALL_PARRMEM4R(m_type, m_elemtype, m_method) \
+	static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); }
+#define VCALL_PARRMEM5(m_type, m_elemtype, m_method) \
+	static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3], *p_args[4]); }
+#define VCALL_PARRMEM5R(m_type, m_elemtype, m_method) \
+	static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3], *p_args[4]); }
+
+	VCALL_PARRMEM0R(PackedByteArray, uint8_t, size);
+	VCALL_PARRMEM0R(PackedByteArray, uint8_t, empty);
+	VCALL_PARRMEM2(PackedByteArray, uint8_t, set);
+	VCALL_PARRMEM1R(PackedByteArray, uint8_t, get);
+	VCALL_PARRMEM1(PackedByteArray, uint8_t, push_back);
+	VCALL_PARRMEM1(PackedByteArray, uint8_t, resize);
+	VCALL_PARRMEM2R(PackedByteArray, uint8_t, insert);
+	VCALL_PARRMEM1(PackedByteArray, uint8_t, remove);
+	VCALL_PARRMEM1(PackedByteArray, uint8_t, append);
+	VCALL_PARRMEM1(PackedByteArray, uint8_t, append_array);
+	VCALL_PARRMEM0(PackedByteArray, uint8_t, invert);
+	VCALL_PARRMEM2R(PackedByteArray, uint8_t, subarray);
+
+	VCALL_PARRMEM0R(PackedIntArray, int32_t, size);
+	VCALL_PARRMEM0R(PackedIntArray, int32_t, empty);
+	VCALL_PARRMEM2(PackedIntArray, int32_t, set);
+	VCALL_PARRMEM1R(PackedIntArray, int32_t, get);
+	VCALL_PARRMEM1(PackedIntArray, int32_t, push_back);
+	VCALL_PARRMEM1(PackedIntArray, int32_t, resize);
+	VCALL_PARRMEM2R(PackedIntArray, int32_t, insert);
+	VCALL_PARRMEM1(PackedIntArray, int32_t, remove);
+	VCALL_PARRMEM1(PackedIntArray, int32_t, append);
+	VCALL_PARRMEM1(PackedIntArray, int32_t, append_array);
+	VCALL_PARRMEM0(PackedIntArray, int32_t, invert);
+
+	VCALL_PARRMEM0R(PackedRealArray, real_t, size);
+	VCALL_PARRMEM0R(PackedRealArray, real_t, empty);
+	VCALL_PARRMEM2(PackedRealArray, real_t, set);
+	VCALL_PARRMEM1R(PackedRealArray, real_t, get);
+	VCALL_PARRMEM1(PackedRealArray, real_t, push_back);
+	VCALL_PARRMEM1(PackedRealArray, real_t, resize);
+	VCALL_PARRMEM2R(PackedRealArray, real_t, insert);
+	VCALL_PARRMEM1(PackedRealArray, real_t, remove);
+	VCALL_PARRMEM1(PackedRealArray, real_t, append);
+	VCALL_PARRMEM1(PackedRealArray, real_t, append_array);
+	VCALL_PARRMEM0(PackedRealArray, real_t, invert);
+
+	VCALL_PARRMEM0R(PackedStringArray, String, size);
+	VCALL_PARRMEM0R(PackedStringArray, String, empty);
+	VCALL_PARRMEM2(PackedStringArray, String, set);
+	VCALL_PARRMEM1R(PackedStringArray, String, get);
+	VCALL_PARRMEM1(PackedStringArray, String, push_back);
+	VCALL_PARRMEM1(PackedStringArray, String, resize);
+	VCALL_PARRMEM2R(PackedStringArray, String, insert);
+	VCALL_PARRMEM1(PackedStringArray, String, remove);
+	VCALL_PARRMEM1(PackedStringArray, String, append);
+	VCALL_PARRMEM1(PackedStringArray, String, append_array);
+	VCALL_PARRMEM0(PackedStringArray, String, invert);
+
+	VCALL_PARRMEM0R(PackedVector2Array, Vector2, size);
+	VCALL_PARRMEM0R(PackedVector2Array, Vector2, empty);
+	VCALL_PARRMEM2(PackedVector2Array, Vector2, set);
+	VCALL_PARRMEM1R(PackedVector2Array, Vector2, get);
+	VCALL_PARRMEM1(PackedVector2Array, Vector2, push_back);
+	VCALL_PARRMEM1(PackedVector2Array, Vector2, resize);
+	VCALL_PARRMEM2R(PackedVector2Array, Vector2, insert);
+	VCALL_PARRMEM1(PackedVector2Array, Vector2, remove);
+	VCALL_PARRMEM1(PackedVector2Array, Vector2, append);
+	VCALL_PARRMEM1(PackedVector2Array, Vector2, append_array);
+	VCALL_PARRMEM0(PackedVector2Array, Vector2, invert);
+
+	VCALL_PARRMEM0R(PackedVector3Array, Vector3, size);
+	VCALL_PARRMEM0R(PackedVector3Array, Vector3, empty);
+	VCALL_PARRMEM2(PackedVector3Array, Vector3, set);
+	VCALL_PARRMEM1R(PackedVector3Array, Vector3, get);
+	VCALL_PARRMEM1(PackedVector3Array, Vector3, push_back);
+	VCALL_PARRMEM1(PackedVector3Array, Vector3, resize);
+	VCALL_PARRMEM2R(PackedVector3Array, Vector3, insert);
+	VCALL_PARRMEM1(PackedVector3Array, Vector3, remove);
+	VCALL_PARRMEM1(PackedVector3Array, Vector3, append);
+	VCALL_PARRMEM1(PackedVector3Array, Vector3, append_array);
+	VCALL_PARRMEM0(PackedVector3Array, Vector3, invert);
+
+	VCALL_PARRMEM0R(PackedColorArray, Color, size);
+	VCALL_PARRMEM0R(PackedColorArray, Color, empty);
+	VCALL_PARRMEM2(PackedColorArray, Color, set);
+	VCALL_PARRMEM1R(PackedColorArray, Color, get);
+	VCALL_PARRMEM1(PackedColorArray, Color, push_back);
+	VCALL_PARRMEM1(PackedColorArray, Color, resize);
+	VCALL_PARRMEM2R(PackedColorArray, Color, insert);
+	VCALL_PARRMEM1(PackedColorArray, Color, remove);
+	VCALL_PARRMEM1(PackedColorArray, Color, append);
+	VCALL_PARRMEM1(PackedColorArray, Color, append_array);
+	VCALL_PARRMEM0(PackedColorArray, Color, invert);
 
 #define VCALL_PTR0(m_type, m_method) \
 	static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(); }

+ 73 - 46
core/variant_op.cpp

@@ -392,8 +392,8 @@ bool Variant::booleanize() const {
 	if (p_a.type != p_b.type)                                                                                    \
 		_RETURN_FAIL                                                                                             \
                                                                                                                  \
-	const Vector<m_type> &array_a = *reinterpret_cast<const Vector<m_type> *>(p_a._data._mem);                   \
-	const Vector<m_type> &array_b = *reinterpret_cast<const Vector<m_type> *>(p_b._data._mem);                   \
+	const Vector<m_type> &array_a = PackedArrayRef<m_type>::get_array(p_a._data.packed_array);                   \
+	const Vector<m_type> &array_b = PackedArrayRef<m_type>::get_array(p_b._data.packed_array);                   \
                                                                                                                  \
 	int a_len = array_a.size();                                                                                  \
 	if (a_len m_opa array_b.size()) {                                                                            \
@@ -416,8 +416,8 @@ bool Variant::booleanize() const {
 		if (p_a.type != p_b.type)                                                                  \
 			_RETURN_FAIL;                                                                          \
                                                                                                    \
-		const Vector<m_type> &array_a = *reinterpret_cast<const Vector<m_type> *>(p_a._data._mem); \
-		const Vector<m_type> &array_b = *reinterpret_cast<const Vector<m_type> *>(p_b._data._mem); \
+		const Vector<m_type> &array_a = PackedArrayRef<m_type>::get_array(p_a._data.packed_array); \
+		const Vector<m_type> &array_b = PackedArrayRef<m_type>::get_array(p_b._data.packed_array); \
 		Vector<m_type> sum = array_a;                                                              \
 		sum.append_array(array_b);                                                                 \
 		_RETURN(sum);                                                                              \
@@ -1951,11 +1951,38 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
 		}                                                                                \
 	} break;
 
-#define DEFAULT_OP_DVECTOR_SET(m_name, dv_type, skip_cond) \
-	DEFAULT_OP_ARRAY_CMD(m_name, Vector<dv_type>, if (skip_cond) return;, arr->set(index, p_value); return )
+#define DEFAULT_OP_DVECTOR_SET(m_name, m_type, skip_cond)                                    \
+	case m_name: {                                                                           \
+		if (skip_cond) return;                                                               \
+                                                                                             \
+		if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {     \
+			int index = p_index;                                                             \
+			Vector<m_type> *arr = PackedArrayRef<m_type>::get_array_ptr(_data.packed_array); \
+                                                                                             \
+			if (index < 0)                                                                   \
+				index += arr->size();                                                        \
+			if (index >= 0 && index < arr->size()) {                                         \
+				valid = true;                                                                \
+				arr->set(index, p_value);                                                    \
+			}                                                                                \
+		}                                                                                    \
+	} break;
 
-#define DEFAULT_OP_DVECTOR_GET(m_name, dv_type) \
-	DEFAULT_OP_ARRAY_CMD(m_name, const Vector<dv_type>, ;, return arr->get(index))
+#define DEFAULT_OP_DVECTOR_GET(m_name, m_type)                                                  \
+	case m_name: {                                                                              \
+                                                                                                \
+		if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {        \
+			int index = p_index;                                                                \
+			const Vector<m_type> *arr = &PackedArrayRef<m_type>::get_array(_data.packed_array); \
+                                                                                                \
+			if (index < 0)                                                                      \
+				index += arr->size();                                                           \
+			if (index >= 0 && index < arr->size()) {                                            \
+				valid = true;                                                                   \
+				return arr->get(index);                                                         \
+			}                                                                                   \
+		}                                                                                       \
+	} break;
 
 void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) {
 
@@ -3062,7 +3089,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
 			if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
 
 				int index = p_index;
-				const Vector<uint8_t> *arr = reinterpret_cast<const Vector<uint8_t> *>(_data._mem);
+				const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array);
 				int l = arr->size();
 				if (l) {
 					const uint8_t *r = arr->ptr();
@@ -3080,7 +3107,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
 			if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
 
 				int index = p_index;
-				const Vector<int> *arr = reinterpret_cast<const Vector<int> *>(_data._mem);
+				const Vector<int> *arr = &PackedArrayRef<int>::get_array(_data.packed_array);
 				int l = arr->size();
 				if (l) {
 					const int *r = arr->ptr();
@@ -3098,7 +3125,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
 			if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
 
 				real_t index = p_index;
-				const Vector<real_t> *arr = reinterpret_cast<const Vector<real_t> *>(_data._mem);
+				const Vector<real_t> *arr = &PackedArrayRef<real_t>::get_array(_data.packed_array);
 				int l = arr->size();
 				if (l) {
 					const real_t *r = arr->ptr();
@@ -3116,7 +3143,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
 			if (p_index.get_type() == Variant::STRING) {
 
 				String index = p_index;
-				const Vector<String> *arr = reinterpret_cast<const Vector<String> *>(_data._mem);
+				const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array);
 
 				int l = arr->size();
 				if (l) {
@@ -3135,7 +3162,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
 			if (p_index.get_type() == Variant::VECTOR2) {
 
 				Vector2 index = p_index;
-				const Vector<Vector2> *arr = reinterpret_cast<const Vector<Vector2> *>(_data._mem);
+				const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array);
 
 				int l = arr->size();
 				if (l) {
@@ -3154,7 +3181,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
 			if (p_index.get_type() == Variant::VECTOR3) {
 
 				Vector3 index = p_index;
-				const Vector<Vector3> *arr = reinterpret_cast<const Vector<Vector3> *>(_data._mem);
+				const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array);
 
 				int l = arr->size();
 				if (l) {
@@ -3174,7 +3201,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
 			if (p_index.get_type() == Variant::COLOR) {
 
 				Color index = p_index;
-				const Vector<Color> *arr = reinterpret_cast<const Vector<Color> *>(_data._mem);
+				const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array);
 
 				int l = arr->size();
 				if (l) {
@@ -3442,7 +3469,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
 			return true;
 		} break;
 		case PACKED_BYTE_ARRAY: {
-			const Vector<uint8_t> *arr = reinterpret_cast<const Vector<uint8_t> *>(_data._mem);
+			const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array);
 			if (arr->size() == 0)
 				return false;
 			r_iter = 0;
@@ -3450,7 +3477,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
 
 		} break;
 		case PACKED_INT_ARRAY: {
-			const Vector<int> *arr = reinterpret_cast<const Vector<int> *>(_data._mem);
+			const Vector<int> *arr = &PackedArrayRef<int>::get_array(_data.packed_array);
 			if (arr->size() == 0)
 				return false;
 			r_iter = 0;
@@ -3458,7 +3485,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
 
 		} break;
 		case PACKED_REAL_ARRAY: {
-			const Vector<real_t> *arr = reinterpret_cast<const Vector<real_t> *>(_data._mem);
+			const Vector<real_t> *arr = &PackedArrayRef<real_t>::get_array(_data.packed_array);
 			if (arr->size() == 0)
 				return false;
 			r_iter = 0;
@@ -3466,7 +3493,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
 
 		} break;
 		case PACKED_STRING_ARRAY: {
-			const Vector<String> *arr = reinterpret_cast<const Vector<String> *>(_data._mem);
+			const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array);
 			if (arr->size() == 0)
 				return false;
 			r_iter = 0;
@@ -3474,7 +3501,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
 		} break;
 		case PACKED_VECTOR2_ARRAY: {
 
-			const Vector<Vector2> *arr = reinterpret_cast<const Vector<Vector2> *>(_data._mem);
+			const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array);
 			if (arr->size() == 0)
 				return false;
 			r_iter = 0;
@@ -3482,7 +3509,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
 		} break;
 		case PACKED_VECTOR3_ARRAY: {
 
-			const Vector<Vector3> *arr = reinterpret_cast<const Vector<Vector3> *>(_data._mem);
+			const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array);
 			if (arr->size() == 0)
 				return false;
 			r_iter = 0;
@@ -3490,7 +3517,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
 		} break;
 		case PACKED_COLOR_ARRAY: {
 
-			const Vector<Color> *arr = reinterpret_cast<const Vector<Color> *>(_data._mem);
+			const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array);
 			if (arr->size() == 0)
 				return false;
 			r_iter = 0;
@@ -3617,7 +3644,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
 			return true;
 		} break;
 		case PACKED_BYTE_ARRAY: {
-			const Vector<uint8_t> *arr = reinterpret_cast<const Vector<uint8_t> *>(_data._mem);
+			const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array);
 			int idx = r_iter;
 			idx++;
 			if (idx >= arr->size())
@@ -3627,7 +3654,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
 
 		} break;
 		case PACKED_INT_ARRAY: {
-			const Vector<int> *arr = reinterpret_cast<const Vector<int> *>(_data._mem);
+			const Vector<int> *arr = &PackedArrayRef<int>::get_array(_data.packed_array);
 			int idx = r_iter;
 			idx++;
 			if (idx >= arr->size())
@@ -3637,7 +3664,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
 
 		} break;
 		case PACKED_REAL_ARRAY: {
-			const Vector<real_t> *arr = reinterpret_cast<const Vector<real_t> *>(_data._mem);
+			const Vector<real_t> *arr = &PackedArrayRef<real_t>::get_array(_data.packed_array);
 			int idx = r_iter;
 			idx++;
 			if (idx >= arr->size())
@@ -3647,7 +3674,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
 
 		} break;
 		case PACKED_STRING_ARRAY: {
-			const Vector<String> *arr = reinterpret_cast<const Vector<String> *>(_data._mem);
+			const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array);
 			int idx = r_iter;
 			idx++;
 			if (idx >= arr->size())
@@ -3657,7 +3684,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
 		} break;
 		case PACKED_VECTOR2_ARRAY: {
 
-			const Vector<Vector2> *arr = reinterpret_cast<const Vector<Vector2> *>(_data._mem);
+			const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array);
 			int idx = r_iter;
 			idx++;
 			if (idx >= arr->size())
@@ -3667,7 +3694,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
 		} break;
 		case PACKED_VECTOR3_ARRAY: {
 
-			const Vector<Vector3> *arr = reinterpret_cast<const Vector<Vector3> *>(_data._mem);
+			const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array);
 			int idx = r_iter;
 			idx++;
 			if (idx >= arr->size())
@@ -3677,7 +3704,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
 		} break;
 		case PACKED_COLOR_ARRAY: {
 
-			const Vector<Color> *arr = reinterpret_cast<const Vector<Color> *>(_data._mem);
+			const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array);
 			int idx = r_iter;
 			idx++;
 			if (idx >= arr->size())
@@ -3764,7 +3791,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
 			return arr->get(idx);
 		} break;
 		case PACKED_BYTE_ARRAY: {
-			const Vector<uint8_t> *arr = reinterpret_cast<const Vector<uint8_t> *>(_data._mem);
+			const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array);
 			int idx = r_iter;
 #ifdef DEBUG_ENABLED
 			if (idx < 0 || idx >= arr->size()) {
@@ -3775,7 +3802,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
 			return arr->get(idx);
 		} break;
 		case PACKED_INT_ARRAY: {
-			const Vector<int> *arr = reinterpret_cast<const Vector<int> *>(_data._mem);
+			const Vector<int> *arr = &PackedArrayRef<int>::get_array(_data.packed_array);
 			int idx = r_iter;
 #ifdef DEBUG_ENABLED
 			if (idx < 0 || idx >= arr->size()) {
@@ -3786,7 +3813,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
 			return arr->get(idx);
 		} break;
 		case PACKED_REAL_ARRAY: {
-			const Vector<real_t> *arr = reinterpret_cast<const Vector<real_t> *>(_data._mem);
+			const Vector<real_t> *arr = &PackedArrayRef<real_t>::get_array(_data.packed_array);
 			int idx = r_iter;
 #ifdef DEBUG_ENABLED
 			if (idx < 0 || idx >= arr->size()) {
@@ -3797,7 +3824,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
 			return arr->get(idx);
 		} break;
 		case PACKED_STRING_ARRAY: {
-			const Vector<String> *arr = reinterpret_cast<const Vector<String> *>(_data._mem);
+			const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array);
 			int idx = r_iter;
 #ifdef DEBUG_ENABLED
 			if (idx < 0 || idx >= arr->size()) {
@@ -3809,7 +3836,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
 		} break;
 		case PACKED_VECTOR2_ARRAY: {
 
-			const Vector<Vector2> *arr = reinterpret_cast<const Vector<Vector2> *>(_data._mem);
+			const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array);
 			int idx = r_iter;
 #ifdef DEBUG_ENABLED
 			if (idx < 0 || idx >= arr->size()) {
@@ -3821,7 +3848,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
 		} break;
 		case PACKED_VECTOR3_ARRAY: {
 
-			const Vector<Vector3> *arr = reinterpret_cast<const Vector<Vector3> *>(_data._mem);
+			const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array);
 			int idx = r_iter;
 #ifdef DEBUG_ENABLED
 			if (idx < 0 || idx >= arr->size()) {
@@ -3833,7 +3860,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
 		} break;
 		case PACKED_COLOR_ARRAY: {
 
-			const Vector<Color> *arr = reinterpret_cast<const Vector<Color> *>(_data._mem);
+			const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array);
 			int idx = r_iter;
 #ifdef DEBUG_ENABLED
 			if (idx < 0 || idx >= arr->size()) {
@@ -4167,8 +4194,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
 		}
 			return;
 		case PACKED_INT_ARRAY: {
-			const Vector<int> *arr_a = reinterpret_cast<const Vector<int> *>(a._data._mem);
-			const Vector<int> *arr_b = reinterpret_cast<const Vector<int> *>(b._data._mem);
+			const Vector<int> *arr_a = &PackedArrayRef<int>::get_array(a._data.packed_array);
+			const Vector<int> *arr_b = &PackedArrayRef<int>::get_array(b._data.packed_array);
 			int sz = arr_a->size();
 			if (sz == 0 || arr_b->size() != sz) {
 
@@ -4193,8 +4220,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
 		}
 			return;
 		case PACKED_REAL_ARRAY: {
-			const Vector<real_t> *arr_a = reinterpret_cast<const Vector<real_t> *>(a._data._mem);
-			const Vector<real_t> *arr_b = reinterpret_cast<const Vector<real_t> *>(b._data._mem);
+			const Vector<real_t> *arr_a = &PackedArrayRef<real_t>::get_array(a._data.packed_array);
+			const Vector<real_t> *arr_b = &PackedArrayRef<real_t>::get_array(b._data.packed_array);
 			int sz = arr_a->size();
 			if (sz == 0 || arr_b->size() != sz) {
 
@@ -4223,8 +4250,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
 		}
 			return;
 		case PACKED_VECTOR2_ARRAY: {
-			const Vector<Vector2> *arr_a = reinterpret_cast<const Vector<Vector2> *>(a._data._mem);
-			const Vector<Vector2> *arr_b = reinterpret_cast<const Vector<Vector2> *>(b._data._mem);
+			const Vector<Vector2> *arr_a = &PackedArrayRef<Vector2>::get_array(a._data.packed_array);
+			const Vector<Vector2> *arr_b = &PackedArrayRef<Vector2>::get_array(b._data.packed_array);
 			int sz = arr_a->size();
 			if (sz == 0 || arr_b->size() != sz) {
 
@@ -4248,8 +4275,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
 			return;
 		case PACKED_VECTOR3_ARRAY: {
 
-			const Vector<Vector3> *arr_a = reinterpret_cast<const Vector<Vector3> *>(a._data._mem);
-			const Vector<Vector3> *arr_b = reinterpret_cast<const Vector<Vector3> *>(b._data._mem);
+			const Vector<Vector3> *arr_a = &PackedArrayRef<Vector3>::get_array(a._data.packed_array);
+			const Vector<Vector3> *arr_b = &PackedArrayRef<Vector3>::get_array(b._data.packed_array);
 			int sz = arr_a->size();
 			if (sz == 0 || arr_b->size() != sz) {
 
@@ -4272,8 +4299,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
 		}
 			return;
 		case PACKED_COLOR_ARRAY: {
-			const Vector<Color> *arr_a = reinterpret_cast<const Vector<Color> *>(a._data._mem);
-			const Vector<Color> *arr_b = reinterpret_cast<const Vector<Color> *>(b._data._mem);
+			const Vector<Color> *arr_a = &PackedArrayRef<Color>::get_array(a._data.packed_array);
+			const Vector<Color> *arr_b = &PackedArrayRef<Color>::get_array(b._data.packed_array);
 			int sz = arr_a->size();
 			if (sz == 0 || arr_b->size() != sz) {