Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/modules/gdscript/gdscript_vm.cpp
11351 views
1
/**************************************************************************/
2
/* gdscript_vm.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "gdscript.h"
32
#include "gdscript_function.h"
33
#include "gdscript_lambda_callable.h"
34
35
#include "core/os/os.h"
36
37
#ifdef DEBUG_ENABLED
38
39
static bool _profile_count_as_native(const Object *p_base_obj, const StringName &p_methodname) {
40
if (!p_base_obj) {
41
return false;
42
}
43
StringName cname = p_base_obj->get_class_name();
44
if ((p_methodname == "new" && cname == "GDScript") || p_methodname == "call") {
45
return false;
46
}
47
return ClassDB::class_exists(cname) && ClassDB::has_method(cname, p_methodname, false);
48
}
49
50
static String _get_element_type(Variant::Type builtin_type, const StringName &native_type, const Ref<Script> &script_type) {
51
if (script_type.is_valid() && script_type->is_valid()) {
52
return GDScript::debug_get_script_name(script_type);
53
} else if (native_type != StringName()) {
54
return native_type.operator String();
55
} else {
56
return Variant::get_type_name(builtin_type);
57
}
58
}
59
60
static String _get_var_type(const Variant *p_var) {
61
String basestr;
62
63
if (p_var->get_type() == Variant::OBJECT) {
64
bool was_freed;
65
Object *bobj = p_var->get_validated_object_with_check(was_freed);
66
if (!bobj) {
67
if (was_freed) {
68
basestr = "previously freed";
69
} else {
70
basestr = "null instance";
71
}
72
} else {
73
if (bobj->is_class_ptr(GDScriptNativeClass::get_class_ptr_static())) {
74
basestr = Object::cast_to<GDScriptNativeClass>(bobj)->get_name();
75
} else {
76
basestr = bobj->get_class();
77
if (bobj->get_script_instance()) {
78
basestr += " (" + GDScript::debug_get_script_name(bobj->get_script_instance()->get_script()) + ")";
79
}
80
}
81
}
82
83
} else {
84
if (p_var->get_type() == Variant::ARRAY) {
85
basestr = "Array";
86
const Array *p_array = VariantInternal::get_array(p_var);
87
if (p_array->is_typed()) {
88
basestr += "[" + _get_element_type((Variant::Type)p_array->get_typed_builtin(), p_array->get_typed_class_name(), p_array->get_typed_script()) + "]";
89
}
90
} else if (p_var->get_type() == Variant::DICTIONARY) {
91
basestr = "Dictionary";
92
const Dictionary *p_dictionary = VariantInternal::get_dictionary(p_var);
93
if (p_dictionary->is_typed()) {
94
basestr += "[" + _get_element_type((Variant::Type)p_dictionary->get_typed_key_builtin(), p_dictionary->get_typed_key_class_name(), p_dictionary->get_typed_key_script()) +
95
", " + _get_element_type((Variant::Type)p_dictionary->get_typed_value_builtin(), p_dictionary->get_typed_value_class_name(), p_dictionary->get_typed_value_script()) + "]";
96
}
97
} else {
98
basestr = Variant::get_type_name(p_var->get_type());
99
}
100
}
101
102
return basestr;
103
}
104
105
void GDScriptFunction::_profile_native_call(uint64_t p_t_taken, const String &p_func_name, const String &p_instance_class_name) {
106
HashMap<String, Profile::NativeProfile>::Iterator inner_prof = profile.native_calls.find(p_func_name);
107
if (inner_prof) {
108
inner_prof->value.call_count += 1;
109
} else {
110
String sig = vformat("%s::0::%s%s%s", get_script()->get_script_path(), p_instance_class_name, p_instance_class_name.is_empty() ? "" : ".", p_func_name);
111
inner_prof = profile.native_calls.insert(p_func_name, Profile::NativeProfile{ 1, 0, sig });
112
}
113
inner_prof->value.total_time += p_t_taken;
114
}
115
116
#endif // DEBUG_ENABLED
117
118
Variant GDScriptFunction::_get_default_variant_for_data_type(const GDScriptDataType &p_data_type) {
119
if (p_data_type.kind == GDScriptDataType::BUILTIN) {
120
if (p_data_type.builtin_type == Variant::ARRAY) {
121
Array array;
122
// Typed array.
123
if (p_data_type.has_container_element_type(0)) {
124
const GDScriptDataType &element_type = p_data_type.get_container_element_type(0);
125
array.set_typed(element_type.builtin_type, element_type.native_type, element_type.script_type);
126
}
127
128
return array;
129
} else if (p_data_type.builtin_type == Variant::DICTIONARY) {
130
Dictionary dict;
131
// Typed dictionary.
132
if (p_data_type.has_container_element_types()) {
133
const GDScriptDataType &key_type = p_data_type.get_container_element_type_or_variant(0);
134
const GDScriptDataType &value_type = p_data_type.get_container_element_type_or_variant(1);
135
dict.set_typed(key_type.builtin_type, key_type.native_type, key_type.script_type, value_type.builtin_type, value_type.native_type, value_type.script_type);
136
}
137
138
return dict;
139
} else {
140
Callable::CallError ce;
141
Variant variant;
142
Variant::construct(p_data_type.builtin_type, variant, nullptr, 0, ce);
143
144
ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, Variant());
145
146
return variant;
147
}
148
}
149
150
return Variant();
151
}
152
153
String GDScriptFunction::_get_call_error(const String &p_where, const Variant **p_argptrs, int p_argcount, const Variant &p_ret, const Callable::CallError &p_err) const {
154
switch (p_err.error) {
155
case Callable::CallError::CALL_OK:
156
return String();
157
case Callable::CallError::CALL_ERROR_INVALID_METHOD:
158
if (p_ret.get_type() == Variant::STRING && !p_ret.operator String().is_empty()) {
159
return "Invalid call " + p_where + ": " + p_ret.operator String();
160
}
161
return "Invalid call. Nonexistent " + p_where + ".";
162
case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT:
163
ERR_FAIL_INDEX_V_MSG(p_err.argument, p_argcount, "Bug: Invalid call error argument index.", "Bug: Invalid call error argument index.");
164
ERR_FAIL_NULL_V_MSG(p_argptrs[p_err.argument], "Bug: Argument is null pointer.", "Bug: Argument is null pointer.");
165
// Handle the Object to Object case separately as we don't have further class details.
166
#ifdef DEBUG_ENABLED
167
if (p_err.expected == Variant::OBJECT && p_argptrs[p_err.argument]->get_type() == p_err.expected) {
168
return "Invalid type in " + p_where + ". The Object-derived class of argument " + itos(p_err.argument + 1) + " (" + _get_var_type(p_argptrs[p_err.argument]) + ") is not a subclass of the expected argument class.";
169
}
170
if (p_err.expected == Variant::ARRAY && p_argptrs[p_err.argument]->get_type() == p_err.expected) {
171
return "Invalid type in " + p_where + ". The array of argument " + itos(p_err.argument + 1) + " (" + _get_var_type(p_argptrs[p_err.argument]) + ") does not have the same element type as the expected typed array argument.";
172
}
173
if (p_err.expected == Variant::DICTIONARY && p_argptrs[p_err.argument]->get_type() == p_err.expected) {
174
return "Invalid type in " + p_where + ". The dictionary of argument " + itos(p_err.argument + 1) + " (" + _get_var_type(p_argptrs[p_err.argument]) + ") does not have the same element type as the expected typed dictionary argument.";
175
}
176
#endif // DEBUG_ENABLED
177
return "Invalid type in " + p_where + ". Cannot convert argument " + itos(p_err.argument + 1) + " from " + Variant::get_type_name(p_argptrs[p_err.argument]->get_type()) + " to " + Variant::get_type_name(Variant::Type(p_err.expected)) + ".";
178
case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS:
179
case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS:
180
return "Invalid call to " + p_where + ". Expected " + itos(p_err.expected) + " argument(s).";
181
case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL:
182
return "Attempt to call " + p_where + " on a null instance.";
183
case Callable::CallError::CALL_ERROR_METHOD_NOT_CONST:
184
return "Attempt to call " + p_where + " on a const instance.";
185
}
186
return "Bug: Invalid call error code " + itos(p_err.error) + ".";
187
}
188
189
String GDScriptFunction::_get_callable_call_error(const String &p_where, const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Variant &p_ret, const Callable::CallError &p_err) const {
190
Vector<Variant> binds;
191
p_callable.get_bound_arguments_ref(binds);
192
193
int args_unbound = p_callable.get_unbound_arguments_count();
194
195
if (p_argcount - args_unbound < 0) {
196
return "Callable unbinds " + itos(args_unbound) + " arguments, but called with " + itos(p_argcount);
197
} else {
198
Vector<const Variant *> argptrs;
199
argptrs.resize(p_argcount - args_unbound + binds.size());
200
for (int i = 0; i < p_argcount - args_unbound; i++) {
201
argptrs.write[i] = p_argptrs[i];
202
}
203
for (int i = 0; i < binds.size(); i++) {
204
argptrs.write[i + p_argcount - args_unbound] = &binds[i];
205
}
206
return _get_call_error(p_where, (const Variant **)argptrs.ptr(), argptrs.size(), p_ret, p_err);
207
}
208
}
209
210
void (*type_init_function_table[])(Variant *) = {
211
nullptr, // NIL (shouldn't be called).
212
&VariantInitializer<bool>::init, // BOOL.
213
&VariantInitializer<int64_t>::init, // INT.
214
&VariantInitializer<double>::init, // FLOAT.
215
&VariantInitializer<String>::init, // STRING.
216
&VariantInitializer<Vector2>::init, // VECTOR2.
217
&VariantInitializer<Vector2i>::init, // VECTOR2I.
218
&VariantInitializer<Rect2>::init, // RECT2.
219
&VariantInitializer<Rect2i>::init, // RECT2I.
220
&VariantInitializer<Vector3>::init, // VECTOR3.
221
&VariantInitializer<Vector3i>::init, // VECTOR3I.
222
&VariantInitializer<Transform2D>::init, // TRANSFORM2D.
223
&VariantInitializer<Vector4>::init, // VECTOR4.
224
&VariantInitializer<Vector4i>::init, // VECTOR4I.
225
&VariantInitializer<Plane>::init, // PLANE.
226
&VariantInitializer<Quaternion>::init, // QUATERNION.
227
&VariantInitializer<AABB>::init, // AABB.
228
&VariantInitializer<Basis>::init, // BASIS.
229
&VariantInitializer<Transform3D>::init, // TRANSFORM3D.
230
&VariantInitializer<Projection>::init, // PROJECTION.
231
&VariantInitializer<Color>::init, // COLOR.
232
&VariantInitializer<StringName>::init, // STRING_NAME.
233
&VariantInitializer<NodePath>::init, // NODE_PATH.
234
&VariantInitializer<RID>::init, // RID.
235
&VariantInitializer<Object *>::init, // OBJECT.
236
&VariantInitializer<Callable>::init, // CALLABLE.
237
&VariantInitializer<Signal>::init, // SIGNAL.
238
&VariantInitializer<Dictionary>::init, // DICTIONARY.
239
&VariantInitializer<Array>::init, // ARRAY.
240
&VariantInitializer<PackedByteArray>::init, // PACKED_BYTE_ARRAY.
241
&VariantInitializer<PackedInt32Array>::init, // PACKED_INT32_ARRAY.
242
&VariantInitializer<PackedInt64Array>::init, // PACKED_INT64_ARRAY.
243
&VariantInitializer<PackedFloat32Array>::init, // PACKED_FLOAT32_ARRAY.
244
&VariantInitializer<PackedFloat64Array>::init, // PACKED_FLOAT64_ARRAY.
245
&VariantInitializer<PackedStringArray>::init, // PACKED_STRING_ARRAY.
246
&VariantInitializer<PackedVector2Array>::init, // PACKED_VECTOR2_ARRAY.
247
&VariantInitializer<PackedVector3Array>::init, // PACKED_VECTOR3_ARRAY.
248
&VariantInitializer<PackedColorArray>::init, // PACKED_COLOR_ARRAY.
249
&VariantInitializer<PackedVector4Array>::init, // PACKED_VECTOR4_ARRAY.
250
};
251
252
#if defined(__GNUC__) || defined(__clang__)
253
#define OPCODES_TABLE \
254
static const void *switch_table_ops[] = { \
255
&&OPCODE_OPERATOR, \
256
&&OPCODE_OPERATOR_VALIDATED, \
257
&&OPCODE_TYPE_TEST_BUILTIN, \
258
&&OPCODE_TYPE_TEST_ARRAY, \
259
&&OPCODE_TYPE_TEST_DICTIONARY, \
260
&&OPCODE_TYPE_TEST_NATIVE, \
261
&&OPCODE_TYPE_TEST_SCRIPT, \
262
&&OPCODE_SET_KEYED, \
263
&&OPCODE_SET_KEYED_VALIDATED, \
264
&&OPCODE_SET_INDEXED_VALIDATED, \
265
&&OPCODE_GET_KEYED, \
266
&&OPCODE_GET_KEYED_VALIDATED, \
267
&&OPCODE_GET_INDEXED_VALIDATED, \
268
&&OPCODE_SET_NAMED, \
269
&&OPCODE_SET_NAMED_VALIDATED, \
270
&&OPCODE_GET_NAMED, \
271
&&OPCODE_GET_NAMED_VALIDATED, \
272
&&OPCODE_SET_MEMBER, \
273
&&OPCODE_GET_MEMBER, \
274
&&OPCODE_SET_STATIC_VARIABLE, \
275
&&OPCODE_GET_STATIC_VARIABLE, \
276
&&OPCODE_ASSIGN, \
277
&&OPCODE_ASSIGN_NULL, \
278
&&OPCODE_ASSIGN_TRUE, \
279
&&OPCODE_ASSIGN_FALSE, \
280
&&OPCODE_ASSIGN_TYPED_BUILTIN, \
281
&&OPCODE_ASSIGN_TYPED_ARRAY, \
282
&&OPCODE_ASSIGN_TYPED_DICTIONARY, \
283
&&OPCODE_ASSIGN_TYPED_NATIVE, \
284
&&OPCODE_ASSIGN_TYPED_SCRIPT, \
285
&&OPCODE_CAST_TO_BUILTIN, \
286
&&OPCODE_CAST_TO_NATIVE, \
287
&&OPCODE_CAST_TO_SCRIPT, \
288
&&OPCODE_CONSTRUCT, \
289
&&OPCODE_CONSTRUCT_VALIDATED, \
290
&&OPCODE_CONSTRUCT_ARRAY, \
291
&&OPCODE_CONSTRUCT_TYPED_ARRAY, \
292
&&OPCODE_CONSTRUCT_DICTIONARY, \
293
&&OPCODE_CONSTRUCT_TYPED_DICTIONARY, \
294
&&OPCODE_CALL, \
295
&&OPCODE_CALL_RETURN, \
296
&&OPCODE_CALL_ASYNC, \
297
&&OPCODE_CALL_UTILITY, \
298
&&OPCODE_CALL_UTILITY_VALIDATED, \
299
&&OPCODE_CALL_GDSCRIPT_UTILITY, \
300
&&OPCODE_CALL_BUILTIN_TYPE_VALIDATED, \
301
&&OPCODE_CALL_SELF_BASE, \
302
&&OPCODE_CALL_METHOD_BIND, \
303
&&OPCODE_CALL_METHOD_BIND_RET, \
304
&&OPCODE_CALL_BUILTIN_STATIC, \
305
&&OPCODE_CALL_NATIVE_STATIC, \
306
&&OPCODE_CALL_NATIVE_STATIC_VALIDATED_RETURN, \
307
&&OPCODE_CALL_NATIVE_STATIC_VALIDATED_NO_RETURN, \
308
&&OPCODE_CALL_METHOD_BIND_VALIDATED_RETURN, \
309
&&OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN, \
310
&&OPCODE_AWAIT, \
311
&&OPCODE_AWAIT_RESUME, \
312
&&OPCODE_CREATE_LAMBDA, \
313
&&OPCODE_CREATE_SELF_LAMBDA, \
314
&&OPCODE_JUMP, \
315
&&OPCODE_JUMP_IF, \
316
&&OPCODE_JUMP_IF_NOT, \
317
&&OPCODE_JUMP_TO_DEF_ARGUMENT, \
318
&&OPCODE_JUMP_IF_SHARED, \
319
&&OPCODE_RETURN, \
320
&&OPCODE_RETURN_TYPED_BUILTIN, \
321
&&OPCODE_RETURN_TYPED_ARRAY, \
322
&&OPCODE_RETURN_TYPED_DICTIONARY, \
323
&&OPCODE_RETURN_TYPED_NATIVE, \
324
&&OPCODE_RETURN_TYPED_SCRIPT, \
325
&&OPCODE_ITERATE_BEGIN, \
326
&&OPCODE_ITERATE_BEGIN_INT, \
327
&&OPCODE_ITERATE_BEGIN_FLOAT, \
328
&&OPCODE_ITERATE_BEGIN_VECTOR2, \
329
&&OPCODE_ITERATE_BEGIN_VECTOR2I, \
330
&&OPCODE_ITERATE_BEGIN_VECTOR3, \
331
&&OPCODE_ITERATE_BEGIN_VECTOR3I, \
332
&&OPCODE_ITERATE_BEGIN_STRING, \
333
&&OPCODE_ITERATE_BEGIN_DICTIONARY, \
334
&&OPCODE_ITERATE_BEGIN_ARRAY, \
335
&&OPCODE_ITERATE_BEGIN_PACKED_BYTE_ARRAY, \
336
&&OPCODE_ITERATE_BEGIN_PACKED_INT32_ARRAY, \
337
&&OPCODE_ITERATE_BEGIN_PACKED_INT64_ARRAY, \
338
&&OPCODE_ITERATE_BEGIN_PACKED_FLOAT32_ARRAY, \
339
&&OPCODE_ITERATE_BEGIN_PACKED_FLOAT64_ARRAY, \
340
&&OPCODE_ITERATE_BEGIN_PACKED_STRING_ARRAY, \
341
&&OPCODE_ITERATE_BEGIN_PACKED_VECTOR2_ARRAY, \
342
&&OPCODE_ITERATE_BEGIN_PACKED_VECTOR3_ARRAY, \
343
&&OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY, \
344
&&OPCODE_ITERATE_BEGIN_PACKED_VECTOR4_ARRAY, \
345
&&OPCODE_ITERATE_BEGIN_OBJECT, \
346
&&OPCODE_ITERATE_BEGIN_RANGE, \
347
&&OPCODE_ITERATE, \
348
&&OPCODE_ITERATE_INT, \
349
&&OPCODE_ITERATE_FLOAT, \
350
&&OPCODE_ITERATE_VECTOR2, \
351
&&OPCODE_ITERATE_VECTOR2I, \
352
&&OPCODE_ITERATE_VECTOR3, \
353
&&OPCODE_ITERATE_VECTOR3I, \
354
&&OPCODE_ITERATE_STRING, \
355
&&OPCODE_ITERATE_DICTIONARY, \
356
&&OPCODE_ITERATE_ARRAY, \
357
&&OPCODE_ITERATE_PACKED_BYTE_ARRAY, \
358
&&OPCODE_ITERATE_PACKED_INT32_ARRAY, \
359
&&OPCODE_ITERATE_PACKED_INT64_ARRAY, \
360
&&OPCODE_ITERATE_PACKED_FLOAT32_ARRAY, \
361
&&OPCODE_ITERATE_PACKED_FLOAT64_ARRAY, \
362
&&OPCODE_ITERATE_PACKED_STRING_ARRAY, \
363
&&OPCODE_ITERATE_PACKED_VECTOR2_ARRAY, \
364
&&OPCODE_ITERATE_PACKED_VECTOR3_ARRAY, \
365
&&OPCODE_ITERATE_PACKED_COLOR_ARRAY, \
366
&&OPCODE_ITERATE_PACKED_VECTOR4_ARRAY, \
367
&&OPCODE_ITERATE_OBJECT, \
368
&&OPCODE_ITERATE_RANGE, \
369
&&OPCODE_STORE_GLOBAL, \
370
&&OPCODE_STORE_NAMED_GLOBAL, \
371
&&OPCODE_TYPE_ADJUST_BOOL, \
372
&&OPCODE_TYPE_ADJUST_INT, \
373
&&OPCODE_TYPE_ADJUST_FLOAT, \
374
&&OPCODE_TYPE_ADJUST_STRING, \
375
&&OPCODE_TYPE_ADJUST_VECTOR2, \
376
&&OPCODE_TYPE_ADJUST_VECTOR2I, \
377
&&OPCODE_TYPE_ADJUST_RECT2, \
378
&&OPCODE_TYPE_ADJUST_RECT2I, \
379
&&OPCODE_TYPE_ADJUST_VECTOR3, \
380
&&OPCODE_TYPE_ADJUST_VECTOR3I, \
381
&&OPCODE_TYPE_ADJUST_TRANSFORM2D, \
382
&&OPCODE_TYPE_ADJUST_VECTOR4, \
383
&&OPCODE_TYPE_ADJUST_VECTOR4I, \
384
&&OPCODE_TYPE_ADJUST_PLANE, \
385
&&OPCODE_TYPE_ADJUST_QUATERNION, \
386
&&OPCODE_TYPE_ADJUST_AABB, \
387
&&OPCODE_TYPE_ADJUST_BASIS, \
388
&&OPCODE_TYPE_ADJUST_TRANSFORM3D, \
389
&&OPCODE_TYPE_ADJUST_PROJECTION, \
390
&&OPCODE_TYPE_ADJUST_COLOR, \
391
&&OPCODE_TYPE_ADJUST_STRING_NAME, \
392
&&OPCODE_TYPE_ADJUST_NODE_PATH, \
393
&&OPCODE_TYPE_ADJUST_RID, \
394
&&OPCODE_TYPE_ADJUST_OBJECT, \
395
&&OPCODE_TYPE_ADJUST_CALLABLE, \
396
&&OPCODE_TYPE_ADJUST_SIGNAL, \
397
&&OPCODE_TYPE_ADJUST_DICTIONARY, \
398
&&OPCODE_TYPE_ADJUST_ARRAY, \
399
&&OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY, \
400
&&OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY, \
401
&&OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY, \
402
&&OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY, \
403
&&OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY, \
404
&&OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY, \
405
&&OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY, \
406
&&OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY, \
407
&&OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY, \
408
&&OPCODE_TYPE_ADJUST_PACKED_VECTOR4_ARRAY, \
409
&&OPCODE_ASSERT, \
410
&&OPCODE_BREAKPOINT, \
411
&&OPCODE_LINE, \
412
&&OPCODE_END \
413
}; \
414
static_assert(std_size(switch_table_ops) == (OPCODE_END + 1), "Opcodes in jump table aren't the same as opcodes in enum.");
415
416
#define OPCODE(m_op) \
417
m_op:
418
#define OPCODE_WHILE(m_test)
419
#define OPCODES_END \
420
OPSEXIT:
421
#define OPCODES_OUT \
422
OPSOUT:
423
#define OPCODE_SWITCH(m_test) goto *switch_table_ops[m_test];
424
425
#ifdef DEBUG_ENABLED
426
#define DISPATCH_OPCODE \
427
last_opcode = _code_ptr[ip]; \
428
goto *switch_table_ops[last_opcode]
429
#else // !DEBUG_ENABLED
430
#define DISPATCH_OPCODE goto *switch_table_ops[_code_ptr[ip]]
431
#endif // DEBUG_ENABLED
432
433
#define OPCODE_BREAK goto OPSEXIT
434
#define OPCODE_OUT goto OPSOUT
435
#else // !(defined(__GNUC__) || defined(__clang__))
436
#define OPCODES_TABLE
437
#define OPCODE(m_op) case m_op:
438
#define OPCODE_WHILE(m_test) while (m_test)
439
#define OPCODES_END
440
#define OPCODES_OUT
441
#define DISPATCH_OPCODE continue
442
443
#ifdef _MSC_VER
444
#define OPCODE_SWITCH(m_test) \
445
__assume(m_test <= OPCODE_END); \
446
switch (m_test)
447
#else // !_MSC_VER
448
#define OPCODE_SWITCH(m_test) switch (m_test)
449
#endif // _MSC_VER
450
451
#define OPCODE_BREAK break
452
#define OPCODE_OUT break
453
#endif // defined(__GNUC__) || defined(__clang__)
454
455
// Helpers for VariantInternal methods in macros.
456
#define OP_GET_BOOL get_bool
457
#define OP_GET_INT get_int
458
#define OP_GET_FLOAT get_float
459
#define OP_GET_VECTOR2 get_vector2
460
#define OP_GET_VECTOR2I get_vector2i
461
#define OP_GET_VECTOR3 get_vector3
462
#define OP_GET_VECTOR3I get_vector3i
463
#define OP_GET_RECT2 get_rect2
464
#define OP_GET_VECTOR4 get_vector4
465
#define OP_GET_VECTOR4I get_vector4i
466
#define OP_GET_RECT2I get_rect2i
467
#define OP_GET_QUATERNION get_quaternion
468
#define OP_GET_COLOR get_color
469
#define OP_GET_STRING get_string
470
#define OP_GET_STRING_NAME get_string_name
471
#define OP_GET_NODE_PATH get_node_path
472
#define OP_GET_CALLABLE get_callable
473
#define OP_GET_SIGNAL get_signal
474
#define OP_GET_ARRAY get_array
475
#define OP_GET_DICTIONARY get_dictionary
476
#define OP_GET_PACKED_BYTE_ARRAY get_byte_array
477
#define OP_GET_PACKED_INT32_ARRAY get_int32_array
478
#define OP_GET_PACKED_INT64_ARRAY get_int64_array
479
#define OP_GET_PACKED_FLOAT32_ARRAY get_float32_array
480
#define OP_GET_PACKED_FLOAT64_ARRAY get_float64_array
481
#define OP_GET_PACKED_STRING_ARRAY get_string_array
482
#define OP_GET_PACKED_VECTOR2_ARRAY get_vector2_array
483
#define OP_GET_PACKED_VECTOR3_ARRAY get_vector3_array
484
#define OP_GET_PACKED_COLOR_ARRAY get_color_array
485
#define OP_GET_PACKED_VECTOR4_ARRAY get_vector4_array
486
#define OP_GET_TRANSFORM3D get_transform
487
#define OP_GET_TRANSFORM2D get_transform2d
488
#define OP_GET_PROJECTION get_projection
489
#define OP_GET_PLANE get_plane
490
#define OP_GET_AABB get_aabb
491
#define OP_GET_BASIS get_basis
492
#define OP_GET_RID get_rid
493
494
#define METHOD_CALL_ON_NULL_VALUE_ERROR(method_pointer) "Cannot call method '" + (method_pointer)->get_name() + "' on a null value."
495
#define METHOD_CALL_ON_FREED_INSTANCE_ERROR(method_pointer) "Cannot call method '" + (method_pointer)->get_name() + "' on a previously freed instance."
496
497
Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Callable::CallError &r_err, CallState *p_state) {
498
OPCODES_TABLE;
499
500
if (!_code_ptr) {
501
return _get_default_variant_for_data_type(return_type);
502
}
503
504
r_err.error = Callable::CallError::CALL_OK;
505
506
static thread_local int call_depth = 0;
507
if (unlikely(++call_depth > MAX_CALL_DEPTH)) {
508
call_depth--;
509
#ifdef DEBUG_ENABLED
510
String err_file;
511
if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && !p_instance->script->path.is_empty()) {
512
err_file = p_instance->script->path;
513
} else if (_script) {
514
err_file = _script->path;
515
}
516
if (err_file.is_empty()) {
517
err_file = "<built-in>";
518
}
519
String err_func = name;
520
if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->local_name != StringName()) {
521
err_func = p_instance->script->local_name.operator String() + "." + err_func;
522
}
523
int err_line = _initial_line;
524
const char *err_text = "Stack overflow. Check for infinite recursion in your script.";
525
_err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, err_text, false, ERR_HANDLER_SCRIPT);
526
GDScriptLanguage::get_singleton()->debug_break(err_text, false);
527
#endif
528
return _get_default_variant_for_data_type(return_type);
529
}
530
531
Variant retvalue;
532
Variant *stack = nullptr;
533
Variant **instruction_args = nullptr;
534
int defarg = 0;
535
536
uint32_t alloca_size = 0;
537
GDScript *script;
538
int ip = 0;
539
int line = _initial_line;
540
541
if (p_state) {
542
//use existing (supplied) state (awaited)
543
stack = (Variant *)p_state->stack.ptr();
544
instruction_args = (Variant **)&p_state->stack.ptr()[sizeof(Variant) * p_state->stack_size]; //ptr() to avoid bounds check
545
line = p_state->line;
546
ip = p_state->ip;
547
alloca_size = p_state->stack.size();
548
script = p_state->script;
549
p_instance = p_state->instance;
550
defarg = p_state->defarg;
551
552
} else {
553
if (p_argcount != _argument_count) {
554
if (p_argcount > _argument_count) {
555
if (!is_vararg()) {
556
r_err.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
557
r_err.expected = _argument_count;
558
call_depth--;
559
return _get_default_variant_for_data_type(return_type);
560
}
561
} else if (p_argcount < _argument_count - _default_arg_count) {
562
r_err.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
563
r_err.expected = _argument_count - _default_arg_count;
564
call_depth--;
565
return _get_default_variant_for_data_type(return_type);
566
} else {
567
defarg = _argument_count - p_argcount;
568
}
569
}
570
571
alloca_size = sizeof(Variant *) * FIXED_ADDRESSES_MAX + sizeof(Variant *) * _instruction_args_size + sizeof(Variant) * _stack_size;
572
573
uint8_t *aptr = (uint8_t *)alloca(alloca_size);
574
stack = (Variant *)aptr;
575
576
const int non_vararg_arg_count = MIN(p_argcount, _argument_count);
577
for (int i = 0; i < non_vararg_arg_count; i++) {
578
if (!argument_types[i].has_type()) {
579
memnew_placement(&stack[i + FIXED_ADDRESSES_MAX], Variant(*p_args[i]));
580
continue;
581
}
582
// If types already match, don't call Variant::construct(). Constructors of some types
583
// (e.g. packed arrays) do copies, whereas they pass by reference when inside a Variant.
584
if (argument_types[i].is_type(*p_args[i], false)) {
585
memnew_placement(&stack[i + FIXED_ADDRESSES_MAX], Variant(*p_args[i]));
586
continue;
587
}
588
if (!argument_types[i].is_type(*p_args[i], true)) {
589
r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
590
r_err.argument = i;
591
r_err.expected = argument_types[i].builtin_type;
592
call_depth--;
593
return _get_default_variant_for_data_type(return_type);
594
}
595
if (argument_types[i].kind == GDScriptDataType::BUILTIN) {
596
if (argument_types[i].builtin_type == Variant::DICTIONARY && argument_types[i].has_container_element_types()) {
597
const GDScriptDataType &arg_key_type = argument_types[i].get_container_element_type_or_variant(0);
598
const GDScriptDataType &arg_value_type = argument_types[i].get_container_element_type_or_variant(1);
599
Dictionary dict(p_args[i]->operator Dictionary(), arg_key_type.builtin_type, arg_key_type.native_type, arg_key_type.script_type, arg_value_type.builtin_type, arg_value_type.native_type, arg_value_type.script_type);
600
memnew_placement(&stack[i + FIXED_ADDRESSES_MAX], Variant(dict));
601
} else if (argument_types[i].builtin_type == Variant::ARRAY && argument_types[i].has_container_element_type(0)) {
602
const GDScriptDataType &arg_type = argument_types[i].container_element_types[0];
603
Array array(p_args[i]->operator Array(), arg_type.builtin_type, arg_type.native_type, arg_type.script_type);
604
memnew_placement(&stack[i + FIXED_ADDRESSES_MAX], Variant(array));
605
} else {
606
Variant variant;
607
Variant::construct(argument_types[i].builtin_type, variant, &p_args[i], 1, r_err);
608
if (unlikely(r_err.error)) {
609
r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
610
r_err.argument = i;
611
r_err.expected = argument_types[i].builtin_type;
612
call_depth--;
613
return _get_default_variant_for_data_type(return_type);
614
}
615
memnew_placement(&stack[i + FIXED_ADDRESSES_MAX], Variant(variant));
616
}
617
} else {
618
memnew_placement(&stack[i + FIXED_ADDRESSES_MAX], Variant(*p_args[i]));
619
}
620
}
621
for (int i = non_vararg_arg_count + FIXED_ADDRESSES_MAX; i < _stack_size; i++) {
622
memnew_placement(&stack[i], Variant);
623
}
624
625
if (is_vararg()) {
626
Array vararg;
627
stack[_vararg_index] = vararg;
628
if (p_argcount > _argument_count) {
629
vararg.resize(p_argcount - _argument_count);
630
for (int i = 0; i < p_argcount - _argument_count; i++) {
631
vararg[i] = *p_args[i + _argument_count];
632
}
633
}
634
}
635
636
if (_instruction_args_size) {
637
instruction_args = (Variant **)&aptr[sizeof(Variant) * _stack_size];
638
} else {
639
instruction_args = nullptr;
640
}
641
642
for (const KeyValue<int, Variant::Type> &E : temporary_slots) {
643
type_init_function_table[E.value](&stack[E.key]);
644
}
645
}
646
647
if (p_instance) {
648
memnew_placement(&stack[ADDR_STACK_SELF], Variant(p_instance->owner));
649
script = p_instance->script.ptr();
650
} else {
651
memnew_placement(&stack[ADDR_STACK_SELF], Variant);
652
script = _script;
653
}
654
memnew_placement(&stack[ADDR_STACK_CLASS], Variant(script));
655
memnew_placement(&stack[ADDR_STACK_NIL], Variant);
656
657
String err_text;
658
659
GDScriptLanguage::CallLevel call_level;
660
GDScriptLanguage::get_singleton()->enter_function(&call_level, p_instance, this, stack, &ip, &line);
661
662
#ifdef DEBUG_ENABLED
663
#define GD_ERR_BREAK(m_cond) \
664
{ \
665
if (unlikely(m_cond)) { \
666
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Breaking..:"); \
667
OPCODE_BREAK; \
668
} \
669
}
670
671
#define CHECK_SPACE(m_space) \
672
GD_ERR_BREAK((ip + m_space) > _code_size)
673
674
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
675
Variant *m_v; \
676
{ \
677
int address = _code_ptr[ip + 1 + (m_code_ofs)]; \
678
int address_type = (address & ADDR_TYPE_MASK) >> ADDR_BITS; \
679
if (unlikely(address_type < 0 || address_type >= ADDR_TYPE_MAX)) { \
680
err_text = "Bad address type."; \
681
OPCODE_BREAK; \
682
} \
683
int address_index = address & ADDR_MASK; \
684
if (unlikely(address_index < 0 || address_index >= variant_address_limits[address_type])) { \
685
if (address_type == ADDR_TYPE_MEMBER && !p_instance) { \
686
err_text = "Cannot access member without instance."; \
687
} else { \
688
err_text = "Bad address index."; \
689
} \
690
OPCODE_BREAK; \
691
} \
692
m_v = &variant_addresses[address_type][address_index]; \
693
if (unlikely(!m_v)) \
694
OPCODE_BREAK; \
695
}
696
697
#else // !DEBUG_ENABLED
698
#define GD_ERR_BREAK(m_cond)
699
#define CHECK_SPACE(m_space)
700
701
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
702
Variant *m_v; \
703
{ \
704
int address = _code_ptr[ip + 1 + (m_code_ofs)]; \
705
m_v = &variant_addresses[(address & ADDR_TYPE_MASK) >> ADDR_BITS][address & ADDR_MASK]; \
706
if (unlikely(!m_v)) \
707
OPCODE_BREAK; \
708
}
709
710
#endif // DEBUG_ENABLED
711
712
#define LOAD_INSTRUCTION_ARGS \
713
int instr_arg_count = _code_ptr[ip + 1]; \
714
for (int i = 0; i < instr_arg_count; i++) { \
715
GET_VARIANT_PTR(v, i + 1); \
716
instruction_args[i] = v; \
717
} \
718
ip += 1; // Offset to skip instruction argcount.
719
720
#define GET_INSTRUCTION_ARG(m_v, m_idx) \
721
Variant *m_v = instruction_args[m_idx]
722
723
#ifdef DEBUG_ENABLED
724
uint64_t function_start_time = 0;
725
uint64_t function_call_time = 0;
726
727
if (GDScriptLanguage::get_singleton()->profiling) {
728
function_start_time = OS::get_singleton()->get_ticks_usec();
729
function_call_time = 0;
730
profile.call_count.increment();
731
profile.frame_call_count.increment();
732
}
733
bool exit_ok = false;
734
int variant_address_limits[ADDR_TYPE_MAX] = { _stack_size, _constant_count, p_instance ? (int)p_instance->members.size() : 0 };
735
#endif
736
737
bool awaited = false;
738
Variant *variant_addresses[ADDR_TYPE_MAX] = { stack, _constants_ptr, p_instance ? p_instance->members.ptrw() : nullptr };
739
740
#ifdef DEBUG_ENABLED
741
OPCODE_WHILE(ip < _code_size) {
742
int last_opcode = _code_ptr[ip];
743
#else
744
OPCODE_WHILE(true) {
745
#endif
746
747
OPCODE_SWITCH(_code_ptr[ip]) {
748
OPCODE(OPCODE_OPERATOR) {
749
constexpr int _pointer_size = sizeof(Variant::ValidatedOperatorEvaluator) / sizeof(*_code_ptr);
750
CHECK_SPACE(7 + _pointer_size);
751
752
bool valid;
753
Variant::Operator op = (Variant::Operator)_code_ptr[ip + 4];
754
GD_ERR_BREAK(op >= Variant::OP_MAX);
755
756
GET_VARIANT_PTR(a, 0);
757
GET_VARIANT_PTR(b, 1);
758
GET_VARIANT_PTR(dst, 2);
759
// Compute signatures (types of operands) so it can be optimized when matching.
760
uint32_t op_signature = _code_ptr[ip + 5];
761
uint32_t actual_signature = (a->get_type() << 8) | (b->get_type());
762
763
#ifdef DEBUG_ENABLED
764
if (op == Variant::OP_DIVIDE || op == Variant::OP_MODULE) {
765
// Don't optimize division and modulo since there's not check for division by zero with validated calls.
766
op_signature = 0xFFFF;
767
_code_ptr[ip + 5] = op_signature;
768
}
769
#endif
770
771
// Check if this is the first run. If so, store the current signature for the optimized path.
772
if (unlikely(op_signature == 0)) {
773
static Mutex initializer_mutex;
774
initializer_mutex.lock();
775
Variant::Type a_type = (Variant::Type)((actual_signature >> 8) & 0xFF);
776
Variant::Type b_type = (Variant::Type)(actual_signature & 0xFF);
777
778
Variant::ValidatedOperatorEvaluator op_func = Variant::get_validated_operator_evaluator(op, a_type, b_type);
779
780
if (unlikely(!op_func)) {
781
#ifdef DEBUG_ENABLED
782
err_text = "Invalid operands '" + Variant::get_type_name(a->get_type()) + "' and '" + Variant::get_type_name(b->get_type()) + "' in operator '" + Variant::get_operator_name(op) + "'.";
783
#endif
784
initializer_mutex.unlock();
785
OPCODE_BREAK;
786
} else {
787
Variant::Type ret_type = Variant::get_operator_return_type(op, a_type, b_type);
788
VariantInternal::initialize(dst, ret_type);
789
op_func(a, b, dst);
790
791
// Check again in case another thread already set it.
792
if (_code_ptr[ip + 5] == 0) {
793
_code_ptr[ip + 5] = actual_signature;
794
_code_ptr[ip + 6] = static_cast<int>(ret_type);
795
Variant::ValidatedOperatorEvaluator *tmp = reinterpret_cast<Variant::ValidatedOperatorEvaluator *>(&_code_ptr[ip + 7]);
796
*tmp = op_func;
797
}
798
}
799
initializer_mutex.unlock();
800
} else if (likely(op_signature == actual_signature)) {
801
// If the signature matches, we can use the optimized path.
802
Variant::Type ret_type = static_cast<Variant::Type>(_code_ptr[ip + 6]);
803
Variant::ValidatedOperatorEvaluator op_func = *reinterpret_cast<Variant::ValidatedOperatorEvaluator *>(&_code_ptr[ip + 7]);
804
805
// Make sure the return value has the correct type.
806
VariantInternal::initialize(dst, ret_type);
807
op_func(a, b, dst);
808
} else {
809
// If the signature doesn't match, we have to use the slow path.
810
#ifdef DEBUG_ENABLED
811
812
Variant ret;
813
Variant::evaluate(op, *a, *b, ret, valid);
814
#else
815
Variant::evaluate(op, *a, *b, *dst, valid);
816
#endif
817
#ifdef DEBUG_ENABLED
818
if (!valid) {
819
if (ret.get_type() == Variant::STRING) {
820
//return a string when invalid with the error
821
err_text = ret;
822
err_text += " in operator '" + Variant::get_operator_name(op) + "'.";
823
} else {
824
err_text = "Invalid operands '" + Variant::get_type_name(a->get_type()) + "' and '" + Variant::get_type_name(b->get_type()) + "' in operator '" + Variant::get_operator_name(op) + "'.";
825
}
826
OPCODE_BREAK;
827
}
828
*dst = ret;
829
#endif
830
}
831
ip += 7 + _pointer_size;
832
}
833
DISPATCH_OPCODE;
834
835
OPCODE(OPCODE_OPERATOR_VALIDATED) {
836
CHECK_SPACE(5);
837
838
int operator_idx = _code_ptr[ip + 4];
839
GD_ERR_BREAK(operator_idx < 0 || operator_idx >= _operator_funcs_count);
840
Variant::ValidatedOperatorEvaluator operator_func = _operator_funcs_ptr[operator_idx];
841
842
GET_VARIANT_PTR(a, 0);
843
GET_VARIANT_PTR(b, 1);
844
GET_VARIANT_PTR(dst, 2);
845
846
operator_func(a, b, dst);
847
848
ip += 5;
849
}
850
DISPATCH_OPCODE;
851
852
OPCODE(OPCODE_TYPE_TEST_BUILTIN) {
853
CHECK_SPACE(4);
854
855
GET_VARIANT_PTR(dst, 0);
856
GET_VARIANT_PTR(value, 1);
857
858
Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 3];
859
GD_ERR_BREAK(builtin_type < 0 || builtin_type >= Variant::VARIANT_MAX);
860
861
*dst = value->get_type() == builtin_type;
862
ip += 4;
863
}
864
DISPATCH_OPCODE;
865
866
OPCODE(OPCODE_TYPE_TEST_ARRAY) {
867
CHECK_SPACE(6);
868
869
GET_VARIANT_PTR(dst, 0);
870
GET_VARIANT_PTR(value, 1);
871
872
GET_VARIANT_PTR(script_type, 2);
873
Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 4];
874
int native_type_idx = _code_ptr[ip + 5];
875
GD_ERR_BREAK(native_type_idx < 0 || native_type_idx >= _global_names_count);
876
const StringName native_type = _global_names_ptr[native_type_idx];
877
878
bool result = false;
879
if (value->get_type() == Variant::ARRAY) {
880
Array *array = VariantInternal::get_array(value);
881
result = array->get_typed_builtin() == ((uint32_t)builtin_type) && array->get_typed_class_name() == native_type && array->get_typed_script() == *script_type;
882
}
883
884
*dst = result;
885
ip += 6;
886
}
887
DISPATCH_OPCODE;
888
889
OPCODE(OPCODE_TYPE_TEST_DICTIONARY) {
890
CHECK_SPACE(9);
891
892
GET_VARIANT_PTR(dst, 0);
893
GET_VARIANT_PTR(value, 1);
894
895
GET_VARIANT_PTR(key_script_type, 2);
896
Variant::Type key_builtin_type = (Variant::Type)_code_ptr[ip + 5];
897
int key_native_type_idx = _code_ptr[ip + 6];
898
GD_ERR_BREAK(key_native_type_idx < 0 || key_native_type_idx >= _global_names_count);
899
const StringName key_native_type = _global_names_ptr[key_native_type_idx];
900
901
GET_VARIANT_PTR(value_script_type, 3);
902
Variant::Type value_builtin_type = (Variant::Type)_code_ptr[ip + 7];
903
int value_native_type_idx = _code_ptr[ip + 8];
904
GD_ERR_BREAK(value_native_type_idx < 0 || value_native_type_idx >= _global_names_count);
905
const StringName value_native_type = _global_names_ptr[value_native_type_idx];
906
907
bool result = false;
908
if (value->get_type() == Variant::DICTIONARY) {
909
Dictionary *dictionary = VariantInternal::get_dictionary(value);
910
result = dictionary->get_typed_key_builtin() == ((uint32_t)key_builtin_type) && dictionary->get_typed_key_class_name() == key_native_type && dictionary->get_typed_key_script() == *key_script_type &&
911
dictionary->get_typed_value_builtin() == ((uint32_t)value_builtin_type) && dictionary->get_typed_value_class_name() == value_native_type && dictionary->get_typed_value_script() == *value_script_type;
912
}
913
914
*dst = result;
915
ip += 9;
916
}
917
DISPATCH_OPCODE;
918
919
OPCODE(OPCODE_TYPE_TEST_NATIVE) {
920
CHECK_SPACE(4);
921
922
GET_VARIANT_PTR(dst, 0);
923
GET_VARIANT_PTR(value, 1);
924
925
int native_type_idx = _code_ptr[ip + 3];
926
GD_ERR_BREAK(native_type_idx < 0 || native_type_idx >= _global_names_count);
927
const StringName native_type = _global_names_ptr[native_type_idx];
928
929
bool was_freed = false;
930
Object *object = value->get_validated_object_with_check(was_freed);
931
if (was_freed) {
932
err_text = "Left operand of 'is' is a previously freed instance.";
933
OPCODE_BREAK;
934
}
935
936
*dst = object && ClassDB::is_parent_class(object->get_class_name(), native_type);
937
ip += 4;
938
}
939
DISPATCH_OPCODE;
940
941
OPCODE(OPCODE_TYPE_TEST_SCRIPT) {
942
CHECK_SPACE(4);
943
944
GET_VARIANT_PTR(dst, 0);
945
GET_VARIANT_PTR(value, 1);
946
947
GET_VARIANT_PTR(type, 2);
948
Script *script_type = Object::cast_to<Script>(type->operator Object *());
949
GD_ERR_BREAK(!script_type);
950
951
bool was_freed = false;
952
Object *object = value->get_validated_object_with_check(was_freed);
953
if (was_freed) {
954
err_text = "Left operand of 'is' is a previously freed instance.";
955
OPCODE_BREAK;
956
}
957
958
bool result = false;
959
if (object && object->get_script_instance()) {
960
Script *script_ptr = object->get_script_instance()->get_script().ptr();
961
while (script_ptr) {
962
if (script_ptr == script_type) {
963
result = true;
964
break;
965
}
966
script_ptr = script_ptr->get_base_script().ptr();
967
}
968
}
969
970
*dst = result;
971
ip += 4;
972
}
973
DISPATCH_OPCODE;
974
975
OPCODE(OPCODE_SET_KEYED) {
976
CHECK_SPACE(3);
977
978
GET_VARIANT_PTR(dst, 0);
979
GET_VARIANT_PTR(index, 1);
980
GET_VARIANT_PTR(value, 2);
981
982
bool valid;
983
#ifdef DEBUG_ENABLED
984
Variant::VariantSetError err_code;
985
dst->set(*index, *value, &valid, &err_code);
986
#else
987
dst->set(*index, *value, &valid);
988
#endif
989
#ifdef DEBUG_ENABLED
990
if (!valid) {
991
if (dst->is_read_only()) {
992
err_text = "Invalid assignment on read-only value (on base: '" + _get_var_type(dst) + "').";
993
} else {
994
Object *obj = dst->get_validated_object();
995
String v = index->operator String();
996
bool read_only_property = false;
997
if (obj) {
998
read_only_property = ClassDB::has_property(obj->get_class_name(), v) && (ClassDB::get_property_setter(obj->get_class_name(), v) == StringName());
999
}
1000
if (read_only_property) {
1001
err_text = vformat(R"(Cannot set value into property "%s" (on base "%s") because it is read-only.)", v, _get_var_type(dst));
1002
} else {
1003
if (!v.is_empty()) {
1004
v = "'" + v + "'";
1005
} else {
1006
v = "of type '" + _get_var_type(index) + "'";
1007
}
1008
err_text = "Invalid assignment of property or key " + v + " with value of type '" + _get_var_type(value) + "' on a base object of type '" + _get_var_type(dst) + "'.";
1009
if (err_code == Variant::VariantSetError::SET_INDEXED_ERR) {
1010
err_text = "Invalid assignment of index " + v + " (on base: '" + _get_var_type(dst) + "') with value of type '" + _get_var_type(value) + "'.";
1011
}
1012
}
1013
}
1014
OPCODE_BREAK;
1015
}
1016
#endif
1017
ip += 4;
1018
}
1019
DISPATCH_OPCODE;
1020
1021
OPCODE(OPCODE_SET_KEYED_VALIDATED) {
1022
CHECK_SPACE(4);
1023
1024
GET_VARIANT_PTR(dst, 0);
1025
GET_VARIANT_PTR(index, 1);
1026
GET_VARIANT_PTR(value, 2);
1027
1028
int index_setter = _code_ptr[ip + 4];
1029
GD_ERR_BREAK(index_setter < 0 || index_setter >= _keyed_setters_count);
1030
const Variant::ValidatedKeyedSetter setter = _keyed_setters_ptr[index_setter];
1031
1032
bool valid;
1033
setter(dst, index, value, &valid);
1034
1035
#ifdef DEBUG_ENABLED
1036
if (!valid) {
1037
if (dst->is_read_only()) {
1038
err_text = "Invalid assignment on read-only value (on base: '" + _get_var_type(dst) + "').";
1039
} else {
1040
String v = index->operator String();
1041
if (!v.is_empty()) {
1042
v = "'" + v + "'";
1043
} else {
1044
v = "of type '" + _get_var_type(index) + "'";
1045
}
1046
err_text = "Invalid assignment of property or key " + v + " with value of type '" + _get_var_type(value) + "' on a base object of type '" + _get_var_type(dst) + "'.";
1047
}
1048
OPCODE_BREAK;
1049
}
1050
#endif
1051
ip += 5;
1052
}
1053
DISPATCH_OPCODE;
1054
1055
OPCODE(OPCODE_SET_INDEXED_VALIDATED) {
1056
CHECK_SPACE(4);
1057
1058
GET_VARIANT_PTR(dst, 0);
1059
GET_VARIANT_PTR(index, 1);
1060
GET_VARIANT_PTR(value, 2);
1061
1062
int index_setter = _code_ptr[ip + 4];
1063
GD_ERR_BREAK(index_setter < 0 || index_setter >= _indexed_setters_count);
1064
const Variant::ValidatedIndexedSetter setter = _indexed_setters_ptr[index_setter];
1065
1066
int64_t int_index = *VariantInternal::get_int(index);
1067
1068
bool oob;
1069
setter(dst, int_index, value, &oob);
1070
1071
#ifdef DEBUG_ENABLED
1072
if (oob) {
1073
if (dst->is_read_only()) {
1074
err_text = "Invalid assignment on read-only value (on base: '" + _get_var_type(dst) + "').";
1075
} else {
1076
String v = index->operator String();
1077
if (!v.is_empty()) {
1078
v = "'" + v + "'";
1079
} else {
1080
v = "of type '" + _get_var_type(index) + "'";
1081
}
1082
err_text = "Out of bounds set index " + v + " (on base: '" + _get_var_type(dst) + "')";
1083
}
1084
OPCODE_BREAK;
1085
}
1086
#endif
1087
ip += 5;
1088
}
1089
DISPATCH_OPCODE;
1090
1091
OPCODE(OPCODE_GET_KEYED) {
1092
CHECK_SPACE(3);
1093
1094
GET_VARIANT_PTR(src, 0);
1095
GET_VARIANT_PTR(index, 1);
1096
GET_VARIANT_PTR(dst, 2);
1097
1098
bool valid;
1099
#ifdef DEBUG_ENABLED
1100
// Allow better error message in cases where src and dst are the same stack position.
1101
Variant::VariantGetError err_code;
1102
Variant ret = src->get(*index, &valid, &err_code);
1103
#else
1104
*dst = src->get(*index, &valid);
1105
1106
#endif
1107
#ifdef DEBUG_ENABLED
1108
if (!valid) {
1109
String v = index->operator String();
1110
if (!v.is_empty()) {
1111
v = "'" + v + "'";
1112
} else {
1113
v = "of type '" + _get_var_type(index) + "'";
1114
}
1115
err_text = "Invalid access to property or key " + v + " on a base object of type '" + _get_var_type(src) + "'.";
1116
if (err_code == Variant::VariantGetError::GET_INDEXED_ERR) {
1117
err_text = "Invalid access of index " + v + " on a base object of type: '" + _get_var_type(src) + "'.";
1118
}
1119
OPCODE_BREAK;
1120
}
1121
*dst = ret;
1122
#endif
1123
ip += 4;
1124
}
1125
DISPATCH_OPCODE;
1126
1127
OPCODE(OPCODE_GET_KEYED_VALIDATED) {
1128
CHECK_SPACE(4);
1129
1130
GET_VARIANT_PTR(src, 0);
1131
GET_VARIANT_PTR(key, 1);
1132
GET_VARIANT_PTR(dst, 2);
1133
1134
int index_getter = _code_ptr[ip + 4];
1135
GD_ERR_BREAK(index_getter < 0 || index_getter >= _keyed_getters_count);
1136
const Variant::ValidatedKeyedGetter getter = _keyed_getters_ptr[index_getter];
1137
1138
bool valid;
1139
#ifdef DEBUG_ENABLED
1140
// Allow better error message in cases where src and dst are the same stack position.
1141
Variant ret;
1142
getter(src, key, &ret, &valid);
1143
#else
1144
getter(src, key, dst, &valid);
1145
#endif
1146
#ifdef DEBUG_ENABLED
1147
if (!valid) {
1148
String v = key->operator String();
1149
if (!v.is_empty()) {
1150
v = "'" + v + "'";
1151
} else {
1152
v = "of type '" + _get_var_type(key) + "'";
1153
}
1154
err_text = "Invalid access to property or key " + v + " on a base object of type '" + _get_var_type(src) + "'.";
1155
OPCODE_BREAK;
1156
}
1157
*dst = ret;
1158
#endif
1159
ip += 5;
1160
}
1161
DISPATCH_OPCODE;
1162
1163
OPCODE(OPCODE_GET_INDEXED_VALIDATED) {
1164
CHECK_SPACE(4);
1165
1166
GET_VARIANT_PTR(src, 0);
1167
GET_VARIANT_PTR(index, 1);
1168
GET_VARIANT_PTR(dst, 2);
1169
1170
int index_getter = _code_ptr[ip + 4];
1171
GD_ERR_BREAK(index_getter < 0 || index_getter >= _indexed_getters_count);
1172
const Variant::ValidatedIndexedGetter getter = _indexed_getters_ptr[index_getter];
1173
1174
int64_t int_index = *VariantInternal::get_int(index);
1175
1176
bool oob;
1177
getter(src, int_index, dst, &oob);
1178
1179
#ifdef DEBUG_ENABLED
1180
if (oob) {
1181
String v = index->operator String();
1182
if (!v.is_empty()) {
1183
v = "'" + v + "'";
1184
} else {
1185
v = "of type '" + _get_var_type(index) + "'";
1186
}
1187
err_text = "Out of bounds get index " + v + " (on base: '" + _get_var_type(src) + "')";
1188
OPCODE_BREAK;
1189
}
1190
#endif
1191
ip += 5;
1192
}
1193
DISPATCH_OPCODE;
1194
1195
OPCODE(OPCODE_SET_NAMED) {
1196
CHECK_SPACE(3);
1197
1198
GET_VARIANT_PTR(dst, 0);
1199
GET_VARIANT_PTR(value, 1);
1200
1201
int indexname = _code_ptr[ip + 3];
1202
1203
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
1204
const StringName *index = &_global_names_ptr[indexname];
1205
1206
bool valid;
1207
dst->set_named(*index, *value, valid);
1208
1209
#ifdef DEBUG_ENABLED
1210
if (!valid) {
1211
if (dst->is_read_only()) {
1212
err_text = "Invalid assignment on read-only value (on base: '" + _get_var_type(dst) + "').";
1213
} else {
1214
Object *obj = dst->get_validated_object();
1215
bool read_only_property = false;
1216
if (obj) {
1217
read_only_property = ClassDB::has_property(obj->get_class_name(), *index) && (ClassDB::get_property_setter(obj->get_class_name(), *index) == StringName());
1218
}
1219
if (read_only_property) {
1220
err_text = vformat(R"(Cannot set value into property "%s" (on base "%s") because it is read-only.)", String(*index), _get_var_type(dst));
1221
} else {
1222
err_text = "Invalid assignment of property or key '" + String(*index) + "' with value of type '" + _get_var_type(value) + "' on a base object of type '" + _get_var_type(dst) + "'.";
1223
}
1224
}
1225
OPCODE_BREAK;
1226
}
1227
#endif
1228
ip += 4;
1229
}
1230
DISPATCH_OPCODE;
1231
1232
OPCODE(OPCODE_SET_NAMED_VALIDATED) {
1233
CHECK_SPACE(3);
1234
1235
GET_VARIANT_PTR(dst, 0);
1236
GET_VARIANT_PTR(value, 1);
1237
1238
int index_setter = _code_ptr[ip + 3];
1239
GD_ERR_BREAK(index_setter < 0 || index_setter >= _setters_count);
1240
const Variant::ValidatedSetter setter = _setters_ptr[index_setter];
1241
1242
setter(dst, value);
1243
ip += 4;
1244
}
1245
DISPATCH_OPCODE;
1246
1247
OPCODE(OPCODE_GET_NAMED) {
1248
CHECK_SPACE(4);
1249
1250
GET_VARIANT_PTR(src, 0);
1251
GET_VARIANT_PTR(dst, 1);
1252
1253
int indexname = _code_ptr[ip + 3];
1254
1255
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
1256
const StringName *index = &_global_names_ptr[indexname];
1257
1258
bool valid;
1259
#ifdef DEBUG_ENABLED
1260
//allow better error message in cases where src and dst are the same stack position
1261
Variant ret = src->get_named(*index, valid);
1262
1263
#else
1264
*dst = src->get_named(*index, valid);
1265
#endif
1266
#ifdef DEBUG_ENABLED
1267
if (!valid) {
1268
err_text = "Invalid access to property or key '" + index->operator String() + "' on a base object of type '" + _get_var_type(src) + "'.";
1269
OPCODE_BREAK;
1270
}
1271
*dst = ret;
1272
#endif
1273
ip += 4;
1274
}
1275
DISPATCH_OPCODE;
1276
1277
OPCODE(OPCODE_GET_NAMED_VALIDATED) {
1278
CHECK_SPACE(3);
1279
1280
GET_VARIANT_PTR(src, 0);
1281
GET_VARIANT_PTR(dst, 1);
1282
1283
int index_getter = _code_ptr[ip + 3];
1284
GD_ERR_BREAK(index_getter < 0 || index_getter >= _getters_count);
1285
const Variant::ValidatedGetter getter = _getters_ptr[index_getter];
1286
1287
getter(src, dst);
1288
ip += 4;
1289
}
1290
DISPATCH_OPCODE;
1291
1292
OPCODE(OPCODE_SET_MEMBER) {
1293
CHECK_SPACE(3);
1294
GET_VARIANT_PTR(src, 0);
1295
int indexname = _code_ptr[ip + 2];
1296
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
1297
const StringName *index = &_global_names_ptr[indexname];
1298
1299
bool valid;
1300
#ifndef DEBUG_ENABLED
1301
ClassDB::set_property(p_instance->owner, *index, *src, &valid);
1302
#else
1303
bool ok = ClassDB::set_property(p_instance->owner, *index, *src, &valid);
1304
if (!ok) {
1305
err_text = "Internal error setting property: " + String(*index);
1306
OPCODE_BREAK;
1307
} else if (!valid) {
1308
err_text = "Error setting property '" + String(*index) + "' with value of type " + Variant::get_type_name(src->get_type()) + ".";
1309
OPCODE_BREAK;
1310
}
1311
#endif
1312
ip += 3;
1313
}
1314
DISPATCH_OPCODE;
1315
1316
OPCODE(OPCODE_GET_MEMBER) {
1317
CHECK_SPACE(3);
1318
GET_VARIANT_PTR(dst, 0);
1319
int indexname = _code_ptr[ip + 2];
1320
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
1321
const StringName *index = &_global_names_ptr[indexname];
1322
#ifndef DEBUG_ENABLED
1323
ClassDB::get_property(p_instance->owner, *index, *dst);
1324
#else
1325
bool ok = ClassDB::get_property(p_instance->owner, *index, *dst);
1326
if (!ok) {
1327
err_text = "Internal error getting property: " + String(*index);
1328
OPCODE_BREAK;
1329
}
1330
#endif
1331
ip += 3;
1332
}
1333
DISPATCH_OPCODE;
1334
1335
OPCODE(OPCODE_SET_STATIC_VARIABLE) {
1336
CHECK_SPACE(4);
1337
1338
GET_VARIANT_PTR(value, 0);
1339
1340
GET_VARIANT_PTR(_class, 1);
1341
GDScript *gdscript = Object::cast_to<GDScript>(_class->operator Object *());
1342
GD_ERR_BREAK(!gdscript);
1343
1344
int index = _code_ptr[ip + 3];
1345
GD_ERR_BREAK(index < 0 || index >= gdscript->static_variables.size());
1346
1347
gdscript->static_variables.write[index] = *value;
1348
1349
ip += 4;
1350
}
1351
DISPATCH_OPCODE;
1352
1353
OPCODE(OPCODE_GET_STATIC_VARIABLE) {
1354
CHECK_SPACE(4);
1355
1356
GET_VARIANT_PTR(target, 0);
1357
1358
GET_VARIANT_PTR(_class, 1);
1359
GDScript *gdscript = Object::cast_to<GDScript>(_class->operator Object *());
1360
GD_ERR_BREAK(!gdscript);
1361
1362
int index = _code_ptr[ip + 3];
1363
GD_ERR_BREAK(index < 0 || index >= gdscript->static_variables.size());
1364
1365
*target = gdscript->static_variables[index];
1366
1367
ip += 4;
1368
}
1369
DISPATCH_OPCODE;
1370
1371
OPCODE(OPCODE_ASSIGN) {
1372
CHECK_SPACE(3);
1373
GET_VARIANT_PTR(dst, 0);
1374
GET_VARIANT_PTR(src, 1);
1375
1376
*dst = *src;
1377
1378
ip += 3;
1379
}
1380
DISPATCH_OPCODE;
1381
1382
OPCODE(OPCODE_ASSIGN_NULL) {
1383
CHECK_SPACE(2);
1384
GET_VARIANT_PTR(dst, 0);
1385
1386
*dst = Variant();
1387
1388
ip += 2;
1389
}
1390
DISPATCH_OPCODE;
1391
1392
OPCODE(OPCODE_ASSIGN_TRUE) {
1393
CHECK_SPACE(2);
1394
GET_VARIANT_PTR(dst, 0);
1395
1396
*dst = true;
1397
1398
ip += 2;
1399
}
1400
DISPATCH_OPCODE;
1401
1402
OPCODE(OPCODE_ASSIGN_FALSE) {
1403
CHECK_SPACE(2);
1404
GET_VARIANT_PTR(dst, 0);
1405
1406
*dst = false;
1407
1408
ip += 2;
1409
}
1410
DISPATCH_OPCODE;
1411
1412
OPCODE(OPCODE_ASSIGN_TYPED_BUILTIN) {
1413
CHECK_SPACE(4);
1414
GET_VARIANT_PTR(dst, 0);
1415
GET_VARIANT_PTR(src, 1);
1416
1417
Variant::Type var_type = (Variant::Type)_code_ptr[ip + 3];
1418
GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX);
1419
1420
if (src->get_type() != var_type) {
1421
#ifdef DEBUG_ENABLED
1422
if (Variant::can_convert_strict(src->get_type(), var_type)) {
1423
#endif // DEBUG_ENABLED
1424
Callable::CallError ce;
1425
Variant::construct(var_type, *dst, const_cast<const Variant **>(&src), 1, ce);
1426
} else {
1427
#ifdef DEBUG_ENABLED
1428
err_text = "Trying to assign value of type '" + Variant::get_type_name(src->get_type()) +
1429
"' to a variable of type '" + Variant::get_type_name(var_type) + "'.";
1430
OPCODE_BREAK;
1431
}
1432
} else {
1433
#endif // DEBUG_ENABLED
1434
*dst = *src;
1435
}
1436
1437
ip += 4;
1438
}
1439
DISPATCH_OPCODE;
1440
1441
OPCODE(OPCODE_ASSIGN_TYPED_ARRAY) {
1442
CHECK_SPACE(6);
1443
GET_VARIANT_PTR(dst, 0);
1444
GET_VARIANT_PTR(src, 1);
1445
1446
GET_VARIANT_PTR(script_type, 2);
1447
Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 4];
1448
int native_type_idx = _code_ptr[ip + 5];
1449
GD_ERR_BREAK(native_type_idx < 0 || native_type_idx >= _global_names_count);
1450
const StringName native_type = _global_names_ptr[native_type_idx];
1451
1452
if (src->get_type() != Variant::ARRAY) {
1453
#ifdef DEBUG_ENABLED
1454
err_text = vformat(R"(Trying to assign a value of type "%s" to a variable of type "Array[%s]".)",
1455
_get_var_type(src), _get_element_type(builtin_type, native_type, *script_type));
1456
#endif // DEBUG_ENABLED
1457
OPCODE_BREAK;
1458
}
1459
1460
Array *array = VariantInternal::get_array(src);
1461
1462
if (array->get_typed_builtin() != ((uint32_t)builtin_type) || array->get_typed_class_name() != native_type || array->get_typed_script() != *script_type) {
1463
#ifdef DEBUG_ENABLED
1464
err_text = vformat(R"(Trying to assign an array of type "%s" to a variable of type "Array[%s]".)",
1465
_get_var_type(src), _get_element_type(builtin_type, native_type, *script_type));
1466
#endif // DEBUG_ENABLED
1467
OPCODE_BREAK;
1468
}
1469
1470
*dst = *src;
1471
1472
ip += 6;
1473
}
1474
DISPATCH_OPCODE;
1475
1476
OPCODE(OPCODE_ASSIGN_TYPED_DICTIONARY) {
1477
CHECK_SPACE(9);
1478
GET_VARIANT_PTR(dst, 0);
1479
GET_VARIANT_PTR(src, 1);
1480
1481
GET_VARIANT_PTR(key_script_type, 2);
1482
Variant::Type key_builtin_type = (Variant::Type)_code_ptr[ip + 5];
1483
int key_native_type_idx = _code_ptr[ip + 6];
1484
GD_ERR_BREAK(key_native_type_idx < 0 || key_native_type_idx >= _global_names_count);
1485
const StringName key_native_type = _global_names_ptr[key_native_type_idx];
1486
1487
GET_VARIANT_PTR(value_script_type, 3);
1488
Variant::Type value_builtin_type = (Variant::Type)_code_ptr[ip + 7];
1489
int value_native_type_idx = _code_ptr[ip + 8];
1490
GD_ERR_BREAK(value_native_type_idx < 0 || value_native_type_idx >= _global_names_count);
1491
const StringName value_native_type = _global_names_ptr[value_native_type_idx];
1492
1493
if (src->get_type() != Variant::DICTIONARY) {
1494
#ifdef DEBUG_ENABLED
1495
err_text = vformat(R"(Trying to assign a value of type "%s" to a variable of type "Dictionary[%s, %s]".)",
1496
_get_var_type(src), _get_element_type(key_builtin_type, key_native_type, *key_script_type),
1497
_get_element_type(value_builtin_type, value_native_type, *value_script_type));
1498
#endif // DEBUG_ENABLED
1499
OPCODE_BREAK;
1500
}
1501
1502
Dictionary *dictionary = VariantInternal::get_dictionary(src);
1503
1504
if (dictionary->get_typed_key_builtin() != ((uint32_t)key_builtin_type) || dictionary->get_typed_key_class_name() != key_native_type || dictionary->get_typed_key_script() != *key_script_type ||
1505
dictionary->get_typed_value_builtin() != ((uint32_t)value_builtin_type) || dictionary->get_typed_value_class_name() != value_native_type || dictionary->get_typed_value_script() != *value_script_type) {
1506
#ifdef DEBUG_ENABLED
1507
err_text = vformat(R"(Trying to assign a dictionary of type "%s" to a variable of type "Dictionary[%s, %s]".)",
1508
_get_var_type(src), _get_element_type(key_builtin_type, key_native_type, *key_script_type),
1509
_get_element_type(value_builtin_type, value_native_type, *value_script_type));
1510
#endif // DEBUG_ENABLED
1511
OPCODE_BREAK;
1512
}
1513
1514
*dst = *src;
1515
1516
ip += 9;
1517
}
1518
DISPATCH_OPCODE;
1519
1520
OPCODE(OPCODE_ASSIGN_TYPED_NATIVE) {
1521
CHECK_SPACE(4);
1522
GET_VARIANT_PTR(dst, 0);
1523
GET_VARIANT_PTR(src, 1);
1524
1525
#ifdef DEBUG_ENABLED
1526
GET_VARIANT_PTR(type, 2);
1527
GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(type->operator Object *());
1528
GD_ERR_BREAK(!nc);
1529
if (src->get_type() != Variant::OBJECT && src->get_type() != Variant::NIL) {
1530
err_text = "Trying to assign value of type '" + Variant::get_type_name(src->get_type()) +
1531
"' to a variable of type '" + nc->get_name() + "'.";
1532
OPCODE_BREAK;
1533
}
1534
1535
if (src->get_type() == Variant::OBJECT) {
1536
bool was_freed = false;
1537
Object *src_obj = src->get_validated_object_with_check(was_freed);
1538
if (!src_obj && was_freed) {
1539
err_text = "Trying to assign invalid previously freed instance.";
1540
OPCODE_BREAK;
1541
}
1542
1543
if (src_obj && !ClassDB::is_parent_class(src_obj->get_class_name(), nc->get_name())) {
1544
err_text = "Trying to assign value of type '" + src_obj->get_class_name() +
1545
"' to a variable of type '" + nc->get_name() + "'.";
1546
OPCODE_BREAK;
1547
}
1548
}
1549
#endif // DEBUG_ENABLED
1550
*dst = *src;
1551
1552
ip += 4;
1553
}
1554
DISPATCH_OPCODE;
1555
1556
OPCODE(OPCODE_ASSIGN_TYPED_SCRIPT) {
1557
CHECK_SPACE(4);
1558
GET_VARIANT_PTR(dst, 0);
1559
GET_VARIANT_PTR(src, 1);
1560
1561
#ifdef DEBUG_ENABLED
1562
GET_VARIANT_PTR(type, 2);
1563
Script *base_type = Object::cast_to<Script>(type->operator Object *());
1564
1565
GD_ERR_BREAK(!base_type);
1566
1567
if (src->get_type() != Variant::OBJECT && src->get_type() != Variant::NIL) {
1568
err_text = "Trying to assign a non-object value to a variable of type '" + base_type->get_path().get_file() + "'.";
1569
OPCODE_BREAK;
1570
}
1571
1572
if (src->get_type() == Variant::OBJECT) {
1573
bool was_freed = false;
1574
Object *val_obj = src->get_validated_object_with_check(was_freed);
1575
if (!val_obj && was_freed) {
1576
err_text = "Trying to assign invalid previously freed instance.";
1577
OPCODE_BREAK;
1578
}
1579
1580
if (val_obj) { // src is not null
1581
ScriptInstance *scr_inst = val_obj->get_script_instance();
1582
if (!scr_inst) {
1583
err_text = "Trying to assign value of type '" + val_obj->get_class_name() +
1584
"' to a variable of type '" + base_type->get_path().get_file() + "'.";
1585
OPCODE_BREAK;
1586
}
1587
1588
Script *src_type = scr_inst->get_script().ptr();
1589
bool valid = false;
1590
1591
while (src_type) {
1592
if (src_type == base_type) {
1593
valid = true;
1594
break;
1595
}
1596
src_type = src_type->get_base_script().ptr();
1597
}
1598
1599
if (!valid) {
1600
err_text = "Trying to assign value of type '" + val_obj->get_script_instance()->get_script()->get_path().get_file() +
1601
"' to a variable of type '" + base_type->get_path().get_file() + "'.";
1602
OPCODE_BREAK;
1603
}
1604
}
1605
}
1606
#endif // DEBUG_ENABLED
1607
1608
*dst = *src;
1609
1610
ip += 4;
1611
}
1612
DISPATCH_OPCODE;
1613
1614
OPCODE(OPCODE_CAST_TO_BUILTIN) {
1615
CHECK_SPACE(4);
1616
GET_VARIANT_PTR(src, 0);
1617
GET_VARIANT_PTR(dst, 1);
1618
Variant::Type to_type = (Variant::Type)_code_ptr[ip + 3];
1619
1620
GD_ERR_BREAK(to_type < 0 || to_type >= Variant::VARIANT_MAX);
1621
1622
#ifdef DEBUG_ENABLED
1623
if (src->operator Object *() && !src->get_validated_object()) {
1624
err_text = "Trying to cast a freed object.";
1625
OPCODE_BREAK;
1626
}
1627
#endif
1628
1629
Callable::CallError err;
1630
Variant::construct(to_type, *dst, (const Variant **)&src, 1, err);
1631
1632
#ifdef DEBUG_ENABLED
1633
if (err.error != Callable::CallError::CALL_OK) {
1634
err_text = "Invalid cast: could not convert value to '" + Variant::get_type_name(to_type) + "'.";
1635
OPCODE_BREAK;
1636
}
1637
#endif
1638
1639
ip += 4;
1640
}
1641
DISPATCH_OPCODE;
1642
1643
OPCODE(OPCODE_CAST_TO_NATIVE) {
1644
CHECK_SPACE(4);
1645
GET_VARIANT_PTR(src, 0);
1646
GET_VARIANT_PTR(dst, 1);
1647
GET_VARIANT_PTR(to_type, 2);
1648
1649
GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(to_type->operator Object *());
1650
GD_ERR_BREAK(!nc);
1651
1652
#ifdef DEBUG_ENABLED
1653
if (src->operator Object *() && !src->get_validated_object()) {
1654
err_text = "Trying to cast a freed object.";
1655
OPCODE_BREAK;
1656
}
1657
if (src->get_type() != Variant::OBJECT && src->get_type() != Variant::NIL) {
1658
err_text = "Invalid cast: can't convert a non-object value to an object type.";
1659
OPCODE_BREAK;
1660
}
1661
#endif
1662
Object *src_obj = src->operator Object *();
1663
1664
if (src_obj && !ClassDB::is_parent_class(src_obj->get_class_name(), nc->get_name())) {
1665
*dst = Variant(); // invalid cast, assign NULL
1666
} else {
1667
*dst = *src;
1668
}
1669
1670
ip += 4;
1671
}
1672
DISPATCH_OPCODE;
1673
1674
OPCODE(OPCODE_CAST_TO_SCRIPT) {
1675
CHECK_SPACE(4);
1676
GET_VARIANT_PTR(src, 0);
1677
GET_VARIANT_PTR(dst, 1);
1678
GET_VARIANT_PTR(to_type, 2);
1679
1680
Script *base_type = Object::cast_to<Script>(to_type->operator Object *());
1681
1682
GD_ERR_BREAK(!base_type);
1683
1684
#ifdef DEBUG_ENABLED
1685
if (src->operator Object *() && !src->get_validated_object()) {
1686
err_text = "Trying to cast a freed object.";
1687
OPCODE_BREAK;
1688
}
1689
if (src->get_type() != Variant::OBJECT && src->get_type() != Variant::NIL) {
1690
err_text = "Trying to assign a non-object value to a variable of type '" + base_type->get_path().get_file() + "'.";
1691
OPCODE_BREAK;
1692
}
1693
#endif
1694
1695
bool valid = false;
1696
1697
if (src->get_type() != Variant::NIL && src->operator Object *() != nullptr) {
1698
ScriptInstance *scr_inst = src->operator Object *()->get_script_instance();
1699
1700
if (scr_inst) {
1701
Script *src_type = src->operator Object *()->get_script_instance()->get_script().ptr();
1702
1703
while (src_type) {
1704
if (src_type == base_type) {
1705
valid = true;
1706
break;
1707
}
1708
src_type = src_type->get_base_script().ptr();
1709
}
1710
}
1711
}
1712
1713
if (valid) {
1714
*dst = *src; // Valid cast, copy the source object
1715
} else {
1716
*dst = Variant(); // invalid cast, assign NULL
1717
}
1718
1719
ip += 4;
1720
}
1721
DISPATCH_OPCODE;
1722
1723
OPCODE(OPCODE_CONSTRUCT) {
1724
LOAD_INSTRUCTION_ARGS
1725
CHECK_SPACE(2 + instr_arg_count);
1726
1727
ip += instr_arg_count;
1728
1729
int argc = _code_ptr[ip + 1];
1730
1731
Variant::Type t = Variant::Type(_code_ptr[ip + 2]);
1732
1733
Variant **argptrs = instruction_args;
1734
1735
GET_INSTRUCTION_ARG(dst, argc);
1736
1737
Callable::CallError err;
1738
Variant::construct(t, *dst, (const Variant **)argptrs, argc, err);
1739
1740
#ifdef DEBUG_ENABLED
1741
if (err.error != Callable::CallError::CALL_OK) {
1742
err_text = _get_call_error("'" + Variant::get_type_name(t) + "' constructor", (const Variant **)argptrs, argc, *dst, err);
1743
OPCODE_BREAK;
1744
}
1745
#endif
1746
1747
ip += 3;
1748
}
1749
DISPATCH_OPCODE;
1750
1751
OPCODE(OPCODE_CONSTRUCT_VALIDATED) {
1752
LOAD_INSTRUCTION_ARGS
1753
CHECK_SPACE(2 + instr_arg_count);
1754
ip += instr_arg_count;
1755
1756
int argc = _code_ptr[ip + 1];
1757
1758
int constructor_idx = _code_ptr[ip + 2];
1759
GD_ERR_BREAK(constructor_idx < 0 || constructor_idx >= _constructors_count);
1760
Variant::ValidatedConstructor constructor = _constructors_ptr[constructor_idx];
1761
1762
Variant **argptrs = instruction_args;
1763
1764
GET_INSTRUCTION_ARG(dst, argc);
1765
1766
constructor(dst, (const Variant **)argptrs);
1767
1768
ip += 3;
1769
}
1770
DISPATCH_OPCODE;
1771
1772
OPCODE(OPCODE_CONSTRUCT_ARRAY) {
1773
LOAD_INSTRUCTION_ARGS
1774
CHECK_SPACE(1 + instr_arg_count);
1775
ip += instr_arg_count;
1776
1777
int argc = _code_ptr[ip + 1];
1778
Array array;
1779
array.resize(argc);
1780
1781
for (int i = 0; i < argc; i++) {
1782
array[i] = *(instruction_args[i]);
1783
}
1784
1785
GET_INSTRUCTION_ARG(dst, argc);
1786
*dst = Variant(); // Clear potential previous typed array.
1787
1788
*dst = array;
1789
1790
ip += 2;
1791
}
1792
DISPATCH_OPCODE;
1793
1794
OPCODE(OPCODE_CONSTRUCT_TYPED_ARRAY) {
1795
LOAD_INSTRUCTION_ARGS
1796
CHECK_SPACE(3 + instr_arg_count);
1797
ip += instr_arg_count;
1798
1799
int argc = _code_ptr[ip + 1];
1800
1801
GET_INSTRUCTION_ARG(script_type, argc + 1);
1802
Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 2];
1803
int native_type_idx = _code_ptr[ip + 3];
1804
GD_ERR_BREAK(native_type_idx < 0 || native_type_idx >= _global_names_count);
1805
const StringName native_type = _global_names_ptr[native_type_idx];
1806
1807
Array array;
1808
array.set_typed(builtin_type, native_type, *script_type);
1809
array.resize(argc);
1810
for (int i = 0; i < argc; i++) {
1811
// Use .set instead of operator[] to handle type conversion / validation.
1812
array.set(i, *(instruction_args[i]));
1813
}
1814
1815
GET_INSTRUCTION_ARG(dst, argc);
1816
*dst = Variant(); // Clear potential previous typed array.
1817
1818
*dst = array;
1819
1820
ip += 4;
1821
}
1822
DISPATCH_OPCODE;
1823
1824
OPCODE(OPCODE_CONSTRUCT_DICTIONARY) {
1825
LOAD_INSTRUCTION_ARGS
1826
CHECK_SPACE(2 + instr_arg_count);
1827
1828
ip += instr_arg_count;
1829
1830
int argc = _code_ptr[ip + 1];
1831
Dictionary dict;
1832
1833
for (int i = 0; i < argc; i++) {
1834
GET_INSTRUCTION_ARG(k, i * 2 + 0);
1835
GET_INSTRUCTION_ARG(v, i * 2 + 1);
1836
dict[*k] = *v;
1837
}
1838
1839
GET_INSTRUCTION_ARG(dst, argc * 2);
1840
1841
*dst = Variant(); // Clear potential previous typed dictionary.
1842
1843
*dst = dict;
1844
1845
ip += 2;
1846
}
1847
DISPATCH_OPCODE;
1848
1849
OPCODE(OPCODE_CONSTRUCT_TYPED_DICTIONARY) {
1850
LOAD_INSTRUCTION_ARGS
1851
CHECK_SPACE(6 + instr_arg_count);
1852
ip += instr_arg_count;
1853
1854
int argc = _code_ptr[ip + 1];
1855
1856
GET_INSTRUCTION_ARG(key_script_type, argc * 2 + 1);
1857
Variant::Type key_builtin_type = (Variant::Type)_code_ptr[ip + 2];
1858
int key_native_type_idx = _code_ptr[ip + 3];
1859
GD_ERR_BREAK(key_native_type_idx < 0 || key_native_type_idx >= _global_names_count);
1860
const StringName key_native_type = _global_names_ptr[key_native_type_idx];
1861
1862
GET_INSTRUCTION_ARG(value_script_type, argc * 2 + 2);
1863
Variant::Type value_builtin_type = (Variant::Type)_code_ptr[ip + 4];
1864
int value_native_type_idx = _code_ptr[ip + 5];
1865
GD_ERR_BREAK(value_native_type_idx < 0 || value_native_type_idx >= _global_names_count);
1866
const StringName value_native_type = _global_names_ptr[value_native_type_idx];
1867
1868
Dictionary dict;
1869
dict.set_typed(key_builtin_type, key_native_type, *key_script_type, value_builtin_type, value_native_type, *value_script_type);
1870
1871
for (int i = 0; i < argc; i++) {
1872
GET_INSTRUCTION_ARG(k, i * 2 + 0);
1873
GET_INSTRUCTION_ARG(v, i * 2 + 1);
1874
// Use .set instead of operator[] to handle type conversion / validation.
1875
dict.set(*k, *v);
1876
}
1877
1878
GET_INSTRUCTION_ARG(dst, argc * 2);
1879
1880
*dst = Variant(); // Clear potential previous typed dictionary.
1881
1882
*dst = dict;
1883
1884
ip += 6;
1885
}
1886
DISPATCH_OPCODE;
1887
1888
OPCODE(OPCODE_CALL_ASYNC)
1889
OPCODE(OPCODE_CALL_RETURN)
1890
OPCODE(OPCODE_CALL) {
1891
bool call_ret = (_code_ptr[ip]) != OPCODE_CALL;
1892
#ifdef DEBUG_ENABLED
1893
bool call_async = (_code_ptr[ip]) == OPCODE_CALL_ASYNC;
1894
#endif
1895
LOAD_INSTRUCTION_ARGS
1896
CHECK_SPACE(3 + instr_arg_count);
1897
1898
ip += instr_arg_count;
1899
1900
int argc = _code_ptr[ip + 1];
1901
GD_ERR_BREAK(argc < 0);
1902
1903
int methodname_idx = _code_ptr[ip + 2];
1904
GD_ERR_BREAK(methodname_idx < 0 || methodname_idx >= _global_names_count);
1905
const StringName *methodname = &_global_names_ptr[methodname_idx];
1906
1907
GET_INSTRUCTION_ARG(base, argc);
1908
Variant **argptrs = instruction_args;
1909
1910
#ifdef DEBUG_ENABLED
1911
uint64_t call_time = 0;
1912
1913
if (GDScriptLanguage::get_singleton()->profiling) {
1914
call_time = OS::get_singleton()->get_ticks_usec();
1915
}
1916
Variant::Type base_type = base->get_type();
1917
Object *base_obj = base->get_validated_object();
1918
StringName base_class = base_obj ? base_obj->get_class_name() : StringName();
1919
#endif
1920
1921
Variant temp_ret;
1922
Callable::CallError err;
1923
if (call_ret) {
1924
GET_INSTRUCTION_ARG(ret, argc + 1);
1925
base->callp(*methodname, (const Variant **)argptrs, argc, temp_ret, err);
1926
*ret = temp_ret;
1927
#ifdef DEBUG_ENABLED
1928
if (ret->get_type() == Variant::NIL) {
1929
if (base_type == Variant::OBJECT) {
1930
if (base_obj) {
1931
MethodBind *method = ClassDB::get_method(base_class, *methodname);
1932
if (*methodname == CoreStringName(free_) || (method && !method->has_return())) {
1933
err_text = R"(Trying to get a return value of a method that returns "void")";
1934
OPCODE_BREAK;
1935
}
1936
}
1937
} else if (Variant::has_builtin_method(base_type, *methodname) && !Variant::has_builtin_method_return_value(base_type, *methodname)) {
1938
err_text = R"(Trying to get a return value of a method that returns "void")";
1939
OPCODE_BREAK;
1940
}
1941
}
1942
1943
if (!call_async && ret->get_type() == Variant::OBJECT) {
1944
// Check if getting a function state without await.
1945
bool was_freed = false;
1946
Object *obj = ret->get_validated_object_with_check(was_freed);
1947
1948
if (obj && obj->is_class_ptr(GDScriptFunctionState::get_class_ptr_static())) {
1949
err_text = R"(Trying to call an async function without "await".)";
1950
OPCODE_BREAK;
1951
}
1952
}
1953
#endif
1954
} else {
1955
base->callp(*methodname, (const Variant **)argptrs, argc, temp_ret, err);
1956
}
1957
#ifdef DEBUG_ENABLED
1958
1959
if (GDScriptLanguage::get_singleton()->profiling) {
1960
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
1961
if (GDScriptLanguage::get_singleton()->profile_native_calls && _profile_count_as_native(base_obj, *methodname)) {
1962
_profile_native_call(t_taken, *methodname, base_class);
1963
}
1964
function_call_time += t_taken;
1965
}
1966
1967
if (err.error != Callable::CallError::CALL_OK) {
1968
String methodstr = *methodname;
1969
String basestr = _get_var_type(base);
1970
bool is_callable = false;
1971
1972
if (methodstr == "call") {
1973
if (argc >= 1 && base->get_type() != Variant::CALLABLE) {
1974
methodstr = String(*argptrs[0]) + " (via call)";
1975
if (err.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
1976
err.argument += 1;
1977
}
1978
} else {
1979
methodstr = base->operator String() + " (Callable)";
1980
is_callable = true;
1981
}
1982
} else if (methodstr == "free") {
1983
if (err.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
1984
if (base->is_ref_counted()) {
1985
err_text = "Attempted to free a RefCounted object.";
1986
OPCODE_BREAK;
1987
} else if (base->get_type() == Variant::OBJECT) {
1988
err_text = "Attempted to free a locked object (calling or emitting).";
1989
OPCODE_BREAK;
1990
}
1991
}
1992
} else if (methodstr == "call_recursive" && basestr == "TreeItem") {
1993
if (argc >= 1) {
1994
methodstr = String(*argptrs[0]) + " (via TreeItem.call_recursive)";
1995
if (err.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
1996
err.argument += 1;
1997
}
1998
}
1999
}
2000
2001
if (is_callable) {
2002
err_text = _get_callable_call_error(vformat("function '%s'", methodstr), *base, (const Variant **)argptrs, argc, temp_ret, err);
2003
} else {
2004
err_text = _get_call_error(vformat("function '%s' in base '%s'", methodstr, basestr), (const Variant **)argptrs, argc, temp_ret, err);
2005
}
2006
OPCODE_BREAK;
2007
}
2008
#endif // DEBUG_ENABLED
2009
2010
ip += 3;
2011
}
2012
DISPATCH_OPCODE;
2013
2014
OPCODE(OPCODE_CALL_METHOD_BIND)
2015
OPCODE(OPCODE_CALL_METHOD_BIND_RET) {
2016
bool call_ret = (_code_ptr[ip]) == OPCODE_CALL_METHOD_BIND_RET;
2017
LOAD_INSTRUCTION_ARGS
2018
CHECK_SPACE(3 + instr_arg_count);
2019
2020
ip += instr_arg_count;
2021
2022
int argc = _code_ptr[ip + 1];
2023
GD_ERR_BREAK(argc < 0);
2024
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _methods_count);
2025
MethodBind *method = _methods_ptr[_code_ptr[ip + 2]];
2026
2027
GET_INSTRUCTION_ARG(base, argc);
2028
2029
#ifdef DEBUG_ENABLED
2030
bool freed = false;
2031
Object *base_obj = base->get_validated_object_with_check(freed);
2032
if (freed) {
2033
err_text = METHOD_CALL_ON_FREED_INSTANCE_ERROR(method);
2034
OPCODE_BREAK;
2035
} else if (!base_obj) {
2036
err_text = METHOD_CALL_ON_NULL_VALUE_ERROR(method);
2037
OPCODE_BREAK;
2038
}
2039
#else
2040
Object *base_obj = base->operator Object *();
2041
#endif
2042
Variant **argptrs = instruction_args;
2043
2044
#ifdef DEBUG_ENABLED
2045
uint64_t call_time = 0;
2046
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2047
call_time = OS::get_singleton()->get_ticks_usec();
2048
}
2049
#endif
2050
2051
Variant temp_ret;
2052
Callable::CallError err;
2053
if (call_ret) {
2054
GET_INSTRUCTION_ARG(ret, argc + 1);
2055
temp_ret = method->call(base_obj, (const Variant **)argptrs, argc, err);
2056
*ret = temp_ret;
2057
} else {
2058
temp_ret = method->call(base_obj, (const Variant **)argptrs, argc, err);
2059
}
2060
2061
#ifdef DEBUG_ENABLED
2062
2063
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2064
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
2065
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
2066
function_call_time += t_taken;
2067
}
2068
2069
if (err.error != Callable::CallError::CALL_OK) {
2070
String methodstr = method->get_name();
2071
String basestr = _get_var_type(base);
2072
2073
if (methodstr == "call") {
2074
if (argc >= 1) {
2075
methodstr = String(*argptrs[0]) + " (via call)";
2076
if (err.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
2077
err.argument += 1;
2078
}
2079
}
2080
} else if (methodstr == "free") {
2081
if (err.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
2082
if (base->is_ref_counted()) {
2083
err_text = "Attempted to free a RefCounted object.";
2084
OPCODE_BREAK;
2085
} else if (base->get_type() == Variant::OBJECT) {
2086
err_text = "Attempted to free a locked object (calling or emitting).";
2087
OPCODE_BREAK;
2088
}
2089
}
2090
}
2091
err_text = _get_call_error("function '" + methodstr + "' in base '" + basestr + "'", (const Variant **)argptrs, argc, temp_ret, err);
2092
OPCODE_BREAK;
2093
}
2094
#endif
2095
ip += 3;
2096
}
2097
DISPATCH_OPCODE;
2098
2099
OPCODE(OPCODE_CALL_BUILTIN_STATIC) {
2100
LOAD_INSTRUCTION_ARGS
2101
CHECK_SPACE(4 + instr_arg_count);
2102
2103
ip += instr_arg_count;
2104
2105
GD_ERR_BREAK(_code_ptr[ip + 1] < 0 || _code_ptr[ip + 1] >= Variant::VARIANT_MAX);
2106
Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 1];
2107
2108
int methodname_idx = _code_ptr[ip + 2];
2109
GD_ERR_BREAK(methodname_idx < 0 || methodname_idx >= _global_names_count);
2110
const StringName *methodname = &_global_names_ptr[methodname_idx];
2111
2112
int argc = _code_ptr[ip + 3];
2113
GD_ERR_BREAK(argc < 0);
2114
2115
GET_INSTRUCTION_ARG(ret, argc);
2116
2117
const Variant **argptrs = const_cast<const Variant **>(instruction_args);
2118
2119
Callable::CallError err;
2120
Variant::call_static(builtin_type, *methodname, argptrs, argc, *ret, err);
2121
2122
#ifdef DEBUG_ENABLED
2123
if (err.error != Callable::CallError::CALL_OK) {
2124
err_text = _get_call_error("static function '" + methodname->operator String() + "' in type '" + Variant::get_type_name(builtin_type) + "'", argptrs, argc, *ret, err);
2125
OPCODE_BREAK;
2126
}
2127
#endif
2128
2129
ip += 4;
2130
}
2131
DISPATCH_OPCODE;
2132
2133
OPCODE(OPCODE_CALL_NATIVE_STATIC) {
2134
LOAD_INSTRUCTION_ARGS
2135
CHECK_SPACE(3 + instr_arg_count);
2136
2137
ip += instr_arg_count;
2138
2139
GD_ERR_BREAK(_code_ptr[ip + 1] < 0 || _code_ptr[ip + 1] >= _methods_count);
2140
MethodBind *method = _methods_ptr[_code_ptr[ip + 1]];
2141
2142
int argc = _code_ptr[ip + 2];
2143
GD_ERR_BREAK(argc < 0);
2144
2145
GET_INSTRUCTION_ARG(ret, argc);
2146
2147
const Variant **argptrs = const_cast<const Variant **>(instruction_args);
2148
2149
#ifdef DEBUG_ENABLED
2150
uint64_t call_time = 0;
2151
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2152
call_time = OS::get_singleton()->get_ticks_usec();
2153
}
2154
#endif
2155
2156
Callable::CallError err;
2157
*ret = method->call(nullptr, argptrs, argc, err);
2158
2159
#ifdef DEBUG_ENABLED
2160
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2161
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
2162
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
2163
function_call_time += t_taken;
2164
}
2165
#endif
2166
2167
if (err.error != Callable::CallError::CALL_OK) {
2168
err_text = _get_call_error("static function '" + method->get_name().operator String() + "' in type '" + method->get_instance_class().operator String() + "'", argptrs, argc, *ret, err);
2169
OPCODE_BREAK;
2170
}
2171
2172
ip += 3;
2173
}
2174
DISPATCH_OPCODE;
2175
2176
OPCODE(OPCODE_CALL_NATIVE_STATIC_VALIDATED_RETURN) {
2177
LOAD_INSTRUCTION_ARGS
2178
CHECK_SPACE(3 + instr_arg_count);
2179
2180
ip += instr_arg_count;
2181
2182
int argc = _code_ptr[ip + 1];
2183
GD_ERR_BREAK(argc < 0);
2184
2185
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _methods_count);
2186
MethodBind *method = _methods_ptr[_code_ptr[ip + 2]];
2187
2188
Variant **argptrs = instruction_args;
2189
2190
#ifdef DEBUG_ENABLED
2191
uint64_t call_time = 0;
2192
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2193
call_time = OS::get_singleton()->get_ticks_usec();
2194
}
2195
#endif
2196
2197
GET_INSTRUCTION_ARG(ret, argc);
2198
method->validated_call(nullptr, (const Variant **)argptrs, ret);
2199
2200
#ifdef DEBUG_ENABLED
2201
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2202
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
2203
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
2204
function_call_time += t_taken;
2205
}
2206
#endif
2207
2208
ip += 3;
2209
}
2210
DISPATCH_OPCODE;
2211
2212
OPCODE(OPCODE_CALL_NATIVE_STATIC_VALIDATED_NO_RETURN) {
2213
LOAD_INSTRUCTION_ARGS
2214
CHECK_SPACE(3 + instr_arg_count);
2215
2216
ip += instr_arg_count;
2217
2218
int argc = _code_ptr[ip + 1];
2219
GD_ERR_BREAK(argc < 0);
2220
2221
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _methods_count);
2222
MethodBind *method = _methods_ptr[_code_ptr[ip + 2]];
2223
2224
Variant **argptrs = instruction_args;
2225
#ifdef DEBUG_ENABLED
2226
uint64_t call_time = 0;
2227
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2228
call_time = OS::get_singleton()->get_ticks_usec();
2229
}
2230
#endif
2231
2232
GET_INSTRUCTION_ARG(ret, argc);
2233
VariantInternal::initialize(ret, Variant::NIL);
2234
method->validated_call(nullptr, (const Variant **)argptrs, nullptr);
2235
2236
#ifdef DEBUG_ENABLED
2237
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2238
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
2239
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
2240
function_call_time += t_taken;
2241
}
2242
#endif
2243
2244
ip += 3;
2245
}
2246
DISPATCH_OPCODE;
2247
2248
OPCODE(OPCODE_CALL_METHOD_BIND_VALIDATED_RETURN) {
2249
LOAD_INSTRUCTION_ARGS
2250
CHECK_SPACE(3 + instr_arg_count);
2251
2252
ip += instr_arg_count;
2253
2254
int argc = _code_ptr[ip + 1];
2255
GD_ERR_BREAK(argc < 0);
2256
2257
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _methods_count);
2258
MethodBind *method = _methods_ptr[_code_ptr[ip + 2]];
2259
2260
GET_INSTRUCTION_ARG(base, argc);
2261
2262
#ifdef DEBUG_ENABLED
2263
bool freed = false;
2264
Object *base_obj = base->get_validated_object_with_check(freed);
2265
if (freed) {
2266
err_text = METHOD_CALL_ON_FREED_INSTANCE_ERROR(method);
2267
OPCODE_BREAK;
2268
} else if (!base_obj) {
2269
err_text = METHOD_CALL_ON_NULL_VALUE_ERROR(method);
2270
OPCODE_BREAK;
2271
}
2272
#else
2273
Object *base_obj = *VariantInternal::get_object(base);
2274
#endif
2275
2276
Variant **argptrs = instruction_args;
2277
2278
#ifdef DEBUG_ENABLED
2279
uint64_t call_time = 0;
2280
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2281
call_time = OS::get_singleton()->get_ticks_usec();
2282
}
2283
#endif
2284
2285
GET_INSTRUCTION_ARG(ret, argc + 1);
2286
method->validated_call(base_obj, (const Variant **)argptrs, ret);
2287
2288
#ifdef DEBUG_ENABLED
2289
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2290
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
2291
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
2292
function_call_time += t_taken;
2293
}
2294
#endif
2295
2296
ip += 3;
2297
}
2298
DISPATCH_OPCODE;
2299
2300
OPCODE(OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN) {
2301
LOAD_INSTRUCTION_ARGS
2302
CHECK_SPACE(3 + instr_arg_count);
2303
2304
ip += instr_arg_count;
2305
2306
int argc = _code_ptr[ip + 1];
2307
GD_ERR_BREAK(argc < 0);
2308
2309
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _methods_count);
2310
MethodBind *method = _methods_ptr[_code_ptr[ip + 2]];
2311
2312
GET_INSTRUCTION_ARG(base, argc);
2313
#ifdef DEBUG_ENABLED
2314
bool freed = false;
2315
Object *base_obj = base->get_validated_object_with_check(freed);
2316
if (freed) {
2317
err_text = METHOD_CALL_ON_FREED_INSTANCE_ERROR(method);
2318
OPCODE_BREAK;
2319
} else if (!base_obj) {
2320
err_text = METHOD_CALL_ON_NULL_VALUE_ERROR(method);
2321
OPCODE_BREAK;
2322
}
2323
#else
2324
Object *base_obj = *VariantInternal::get_object(base);
2325
#endif
2326
Variant **argptrs = instruction_args;
2327
#ifdef DEBUG_ENABLED
2328
uint64_t call_time = 0;
2329
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2330
call_time = OS::get_singleton()->get_ticks_usec();
2331
}
2332
#endif
2333
2334
GET_INSTRUCTION_ARG(ret, argc + 1);
2335
VariantInternal::initialize(ret, Variant::NIL);
2336
method->validated_call(base_obj, (const Variant **)argptrs, nullptr);
2337
2338
#ifdef DEBUG_ENABLED
2339
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
2340
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
2341
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
2342
function_call_time += t_taken;
2343
}
2344
#endif
2345
2346
ip += 3;
2347
}
2348
DISPATCH_OPCODE;
2349
2350
OPCODE(OPCODE_CALL_BUILTIN_TYPE_VALIDATED) {
2351
LOAD_INSTRUCTION_ARGS
2352
2353
CHECK_SPACE(3 + instr_arg_count);
2354
2355
ip += instr_arg_count;
2356
2357
int argc = _code_ptr[ip + 1];
2358
GD_ERR_BREAK(argc < 0);
2359
2360
GET_INSTRUCTION_ARG(base, argc);
2361
2362
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _builtin_methods_count);
2363
Variant::ValidatedBuiltInMethod method = _builtin_methods_ptr[_code_ptr[ip + 2]];
2364
Variant **argptrs = instruction_args;
2365
2366
GET_INSTRUCTION_ARG(ret, argc + 1);
2367
method(base, (const Variant **)argptrs, argc, ret);
2368
2369
ip += 3;
2370
}
2371
DISPATCH_OPCODE;
2372
2373
OPCODE(OPCODE_CALL_UTILITY) {
2374
LOAD_INSTRUCTION_ARGS
2375
CHECK_SPACE(3 + instr_arg_count);
2376
2377
ip += instr_arg_count;
2378
2379
int argc = _code_ptr[ip + 1];
2380
GD_ERR_BREAK(argc < 0);
2381
2382
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _global_names_count);
2383
StringName function = _global_names_ptr[_code_ptr[ip + 2]];
2384
2385
Variant **argptrs = instruction_args;
2386
2387
GET_INSTRUCTION_ARG(dst, argc);
2388
2389
Callable::CallError err;
2390
Variant::call_utility_function(function, dst, (const Variant **)argptrs, argc, err);
2391
2392
#ifdef DEBUG_ENABLED
2393
if (err.error != Callable::CallError::CALL_OK) {
2394
String methodstr = function;
2395
if (dst->get_type() == Variant::STRING && !dst->operator String().is_empty()) {
2396
// Call provided error string.
2397
err_text = vformat(R"*(Error calling utility function "%s()": %s)*", methodstr, *dst);
2398
} else {
2399
err_text = _get_call_error(vformat(R"*(utility function "%s()")*", methodstr), (const Variant **)argptrs, argc, *dst, err);
2400
}
2401
OPCODE_BREAK;
2402
}
2403
#endif
2404
ip += 3;
2405
}
2406
DISPATCH_OPCODE;
2407
2408
OPCODE(OPCODE_CALL_UTILITY_VALIDATED) {
2409
LOAD_INSTRUCTION_ARGS
2410
CHECK_SPACE(3 + instr_arg_count);
2411
2412
ip += instr_arg_count;
2413
2414
int argc = _code_ptr[ip + 1];
2415
GD_ERR_BREAK(argc < 0);
2416
2417
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _utilities_count);
2418
Variant::ValidatedUtilityFunction function = _utilities_ptr[_code_ptr[ip + 2]];
2419
2420
Variant **argptrs = instruction_args;
2421
2422
GET_INSTRUCTION_ARG(dst, argc);
2423
2424
function(dst, (const Variant **)argptrs, argc);
2425
2426
ip += 3;
2427
}
2428
DISPATCH_OPCODE;
2429
2430
OPCODE(OPCODE_CALL_GDSCRIPT_UTILITY) {
2431
LOAD_INSTRUCTION_ARGS
2432
CHECK_SPACE(3 + instr_arg_count);
2433
2434
ip += instr_arg_count;
2435
2436
int argc = _code_ptr[ip + 1];
2437
GD_ERR_BREAK(argc < 0);
2438
2439
GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _gds_utilities_count);
2440
GDScriptUtilityFunctions::FunctionPtr function = _gds_utilities_ptr[_code_ptr[ip + 2]];
2441
2442
Variant **argptrs = instruction_args;
2443
2444
GET_INSTRUCTION_ARG(dst, argc);
2445
2446
Callable::CallError err;
2447
function(dst, (const Variant **)argptrs, argc, err);
2448
2449
#ifdef DEBUG_ENABLED
2450
if (err.error != Callable::CallError::CALL_OK) {
2451
String methodstr = gds_utilities_names[_code_ptr[ip + 2]];
2452
if (dst->get_type() == Variant::STRING && !dst->operator String().is_empty()) {
2453
// Call provided error string.
2454
err_text = vformat(R"*(Error calling GDScript utility function "%s()": %s)*", methodstr, *dst);
2455
} else {
2456
err_text = _get_call_error(vformat(R"*(GDScript utility function "%s()")*", methodstr), (const Variant **)argptrs, argc, *dst, err);
2457
}
2458
OPCODE_BREAK;
2459
}
2460
#endif
2461
ip += 3;
2462
}
2463
DISPATCH_OPCODE;
2464
2465
OPCODE(OPCODE_CALL_SELF_BASE) {
2466
LOAD_INSTRUCTION_ARGS
2467
CHECK_SPACE(3 + instr_arg_count);
2468
2469
ip += instr_arg_count;
2470
2471
int argc = _code_ptr[ip + 1];
2472
GD_ERR_BREAK(argc < 0);
2473
2474
int self_fun = _code_ptr[ip + 2];
2475
#ifdef DEBUG_ENABLED
2476
if (self_fun < 0 || self_fun >= _global_names_count) {
2477
err_text = "compiler bug, function name not found";
2478
OPCODE_BREAK;
2479
}
2480
#endif
2481
const StringName *methodname = &_global_names_ptr[self_fun];
2482
2483
Variant **argptrs = instruction_args;
2484
2485
GET_INSTRUCTION_ARG(dst, argc);
2486
2487
const GDScript *gds = _script;
2488
2489
HashMap<StringName, GDScriptFunction *>::ConstIterator E;
2490
while (gds->base.ptr()) {
2491
gds = gds->base.ptr();
2492
E = gds->member_functions.find(*methodname);
2493
if (E) {
2494
break;
2495
}
2496
}
2497
2498
Callable::CallError err;
2499
2500
if (E) {
2501
*dst = E->value->call(p_instance, (const Variant **)argptrs, argc, err);
2502
} else if (gds->native.ptr()) {
2503
if (*methodname != GDScriptLanguage::get_singleton()->strings._init) {
2504
MethodBind *mb = ClassDB::get_method(gds->native->get_name(), *methodname);
2505
if (!mb) {
2506
err.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
2507
} else {
2508
*dst = mb->call(p_instance->owner, (const Variant **)argptrs, argc, err);
2509
}
2510
} else {
2511
err.error = Callable::CallError::CALL_OK;
2512
}
2513
} else {
2514
if (*methodname != GDScriptLanguage::get_singleton()->strings._init) {
2515
err.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
2516
} else {
2517
err.error = Callable::CallError::CALL_OK;
2518
}
2519
}
2520
2521
if (err.error != Callable::CallError::CALL_OK) {
2522
String methodstr = *methodname;
2523
err_text = _get_call_error("function '" + methodstr + "'", (const Variant **)argptrs, argc, *dst, err);
2524
2525
OPCODE_BREAK;
2526
}
2527
2528
ip += 3;
2529
}
2530
DISPATCH_OPCODE;
2531
2532
OPCODE(OPCODE_AWAIT) {
2533
CHECK_SPACE(2);
2534
2535
// Do the one-shot connect.
2536
GET_VARIANT_PTR(argobj, 0);
2537
2538
Signal sig;
2539
bool is_signal = true;
2540
2541
{
2542
Variant result = *argobj;
2543
2544
if (argobj->get_type() == Variant::OBJECT) {
2545
bool was_freed = false;
2546
Object *obj = argobj->get_validated_object_with_check(was_freed);
2547
2548
if (was_freed) {
2549
err_text = "Trying to await on a freed object.";
2550
OPCODE_BREAK;
2551
}
2552
2553
// Is this even possible to be null at this point?
2554
if (obj) {
2555
if (obj->is_class_ptr(GDScriptFunctionState::get_class_ptr_static())) {
2556
result = Signal(obj, SNAME("completed"));
2557
}
2558
}
2559
}
2560
2561
if (result.get_type() != Variant::SIGNAL) {
2562
// Not async, return immediately using the target from OPCODE_AWAIT_RESUME.
2563
GET_VARIANT_PTR(target, 2);
2564
*target = result;
2565
ip += 4; // Skip OPCODE_AWAIT_RESUME and its data.
2566
is_signal = false;
2567
} else {
2568
sig = result;
2569
}
2570
}
2571
2572
if (is_signal) {
2573
Ref<GDScriptFunctionState> gdfs = memnew(GDScriptFunctionState);
2574
gdfs->function = this;
2575
2576
gdfs->state.stack.resize(alloca_size);
2577
2578
// First `FIXED_ADDRESSES_MAX` stack addresses are special, so we just skip them here.
2579
for (int i = FIXED_ADDRESSES_MAX; i < _stack_size; i++) {
2580
memnew_placement(&gdfs->state.stack.write[sizeof(Variant) * i], Variant(stack[i]));
2581
}
2582
gdfs->state.stack_size = _stack_size;
2583
gdfs->state.ip = ip + 2;
2584
gdfs->state.line = line;
2585
gdfs->state.script = _script;
2586
{
2587
MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
2588
_script->pending_func_states.add(&gdfs->scripts_list);
2589
if (p_instance) {
2590
gdfs->state.instance = p_instance;
2591
p_instance->pending_func_states.add(&gdfs->instances_list);
2592
} else {
2593
gdfs->state.instance = nullptr;
2594
}
2595
}
2596
#ifdef DEBUG_ENABLED
2597
gdfs->state.function_name = name;
2598
gdfs->state.script_path = _script->get_script_path();
2599
#endif
2600
gdfs->state.defarg = defarg;
2601
gdfs->function = this;
2602
2603
if (p_state) {
2604
// Pass down the signal from the first state.
2605
gdfs->state.completed = p_state->completed;
2606
} else {
2607
gdfs->state.completed = Signal(gdfs.ptr(), SNAME("completed"));
2608
}
2609
2610
retvalue = gdfs;
2611
2612
Error err = sig.connect(Callable(gdfs.ptr(), "_signal_callback").bind(retvalue), Object::CONNECT_ONE_SHOT);
2613
if (err != OK) {
2614
err_text = "Error connecting to signal: " + sig.get_name() + " during await.";
2615
OPCODE_BREAK;
2616
}
2617
2618
awaited = true;
2619
2620
#ifdef DEBUG_ENABLED
2621
exit_ok = true;
2622
#endif
2623
OPCODE_BREAK;
2624
}
2625
}
2626
DISPATCH_OPCODE; // Needed for synchronous calls (when result is immediately available).
2627
2628
OPCODE(OPCODE_AWAIT_RESUME) {
2629
CHECK_SPACE(2);
2630
#ifdef DEBUG_ENABLED
2631
if (!p_state) {
2632
err_text = ("Invalid Resume (bug?)");
2633
OPCODE_BREAK;
2634
}
2635
#endif
2636
GET_VARIANT_PTR(result, 0);
2637
*result = p_state->result;
2638
ip += 2;
2639
}
2640
DISPATCH_OPCODE;
2641
2642
OPCODE(OPCODE_CREATE_LAMBDA) {
2643
LOAD_INSTRUCTION_ARGS
2644
CHECK_SPACE(2 + instr_arg_count);
2645
2646
ip += instr_arg_count;
2647
2648
int captures_count = _code_ptr[ip + 1];
2649
GD_ERR_BREAK(captures_count < 0);
2650
2651
int lambda_index = _code_ptr[ip + 2];
2652
GD_ERR_BREAK(lambda_index < 0 || lambda_index >= _lambdas_count);
2653
GDScriptFunction *lambda = _lambdas_ptr[lambda_index];
2654
2655
Vector<Variant> captures;
2656
captures.resize(captures_count);
2657
for (int i = 0; i < captures_count; i++) {
2658
GET_INSTRUCTION_ARG(arg, i);
2659
captures.write[i] = *arg;
2660
}
2661
2662
GDScriptLambdaCallable *callable = memnew(GDScriptLambdaCallable(Ref<GDScript>(script), lambda, captures));
2663
2664
GET_INSTRUCTION_ARG(result, captures_count);
2665
*result = Callable(callable);
2666
2667
ip += 3;
2668
}
2669
DISPATCH_OPCODE;
2670
2671
OPCODE(OPCODE_CREATE_SELF_LAMBDA) {
2672
LOAD_INSTRUCTION_ARGS
2673
CHECK_SPACE(2 + instr_arg_count);
2674
2675
GD_ERR_BREAK(p_instance == nullptr);
2676
2677
ip += instr_arg_count;
2678
2679
int captures_count = _code_ptr[ip + 1];
2680
GD_ERR_BREAK(captures_count < 0);
2681
2682
int lambda_index = _code_ptr[ip + 2];
2683
GD_ERR_BREAK(lambda_index < 0 || lambda_index >= _lambdas_count);
2684
GDScriptFunction *lambda = _lambdas_ptr[lambda_index];
2685
2686
Vector<Variant> captures;
2687
captures.resize(captures_count);
2688
for (int i = 0; i < captures_count; i++) {
2689
GET_INSTRUCTION_ARG(arg, i);
2690
captures.write[i] = *arg;
2691
}
2692
2693
GDScriptLambdaSelfCallable *callable;
2694
if (Object::cast_to<RefCounted>(p_instance->owner)) {
2695
callable = memnew(GDScriptLambdaSelfCallable(Ref<RefCounted>(Object::cast_to<RefCounted>(p_instance->owner)), lambda, captures));
2696
} else {
2697
callable = memnew(GDScriptLambdaSelfCallable(p_instance->owner, lambda, captures));
2698
}
2699
2700
GET_INSTRUCTION_ARG(result, captures_count);
2701
*result = Callable(callable);
2702
2703
ip += 3;
2704
}
2705
DISPATCH_OPCODE;
2706
2707
OPCODE(OPCODE_JUMP) {
2708
CHECK_SPACE(2);
2709
int to = _code_ptr[ip + 1];
2710
2711
GD_ERR_BREAK(to < 0 || to > _code_size);
2712
ip = to;
2713
}
2714
DISPATCH_OPCODE;
2715
2716
OPCODE(OPCODE_JUMP_IF) {
2717
CHECK_SPACE(3);
2718
2719
GET_VARIANT_PTR(test, 0);
2720
2721
bool result = test->booleanize();
2722
2723
if (result) {
2724
int to = _code_ptr[ip + 2];
2725
GD_ERR_BREAK(to < 0 || to > _code_size);
2726
ip = to;
2727
} else {
2728
ip += 3;
2729
}
2730
}
2731
DISPATCH_OPCODE;
2732
2733
OPCODE(OPCODE_JUMP_IF_NOT) {
2734
CHECK_SPACE(3);
2735
2736
GET_VARIANT_PTR(test, 0);
2737
2738
bool result = test->booleanize();
2739
2740
if (!result) {
2741
int to = _code_ptr[ip + 2];
2742
GD_ERR_BREAK(to < 0 || to > _code_size);
2743
ip = to;
2744
} else {
2745
ip += 3;
2746
}
2747
}
2748
DISPATCH_OPCODE;
2749
2750
OPCODE(OPCODE_JUMP_TO_DEF_ARGUMENT) {
2751
CHECK_SPACE(2);
2752
ip = _default_arg_ptr[defarg];
2753
}
2754
DISPATCH_OPCODE;
2755
2756
OPCODE(OPCODE_JUMP_IF_SHARED) {
2757
CHECK_SPACE(3);
2758
2759
GET_VARIANT_PTR(val, 0);
2760
2761
if (val->is_shared()) {
2762
int to = _code_ptr[ip + 2];
2763
GD_ERR_BREAK(to < 0 || to > _code_size);
2764
ip = to;
2765
} else {
2766
ip += 3;
2767
}
2768
}
2769
DISPATCH_OPCODE;
2770
2771
OPCODE(OPCODE_RETURN) {
2772
CHECK_SPACE(2);
2773
GET_VARIANT_PTR(r, 0);
2774
retvalue = *r;
2775
#ifdef DEBUG_ENABLED
2776
exit_ok = true;
2777
#endif
2778
OPCODE_BREAK;
2779
}
2780
2781
OPCODE(OPCODE_RETURN_TYPED_BUILTIN) {
2782
CHECK_SPACE(3);
2783
GET_VARIANT_PTR(r, 0);
2784
2785
Variant::Type ret_type = (Variant::Type)_code_ptr[ip + 2];
2786
GD_ERR_BREAK(ret_type < 0 || ret_type >= Variant::VARIANT_MAX);
2787
2788
if (r->get_type() != ret_type) {
2789
if (Variant::can_convert_strict(r->get_type(), ret_type)) {
2790
Callable::CallError ce;
2791
Variant::construct(ret_type, retvalue, const_cast<const Variant **>(&r), 1, ce);
2792
} else {
2793
#ifdef DEBUG_ENABLED
2794
err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
2795
Variant::get_type_name(r->get_type()), Variant::get_type_name(ret_type));
2796
#endif // DEBUG_ENABLED
2797
2798
// Construct a base type anyway so type constraints are met.
2799
Callable::CallError ce;
2800
Variant::construct(ret_type, retvalue, nullptr, 0, ce);
2801
OPCODE_BREAK;
2802
}
2803
} else {
2804
retvalue = *r;
2805
}
2806
#ifdef DEBUG_ENABLED
2807
exit_ok = true;
2808
#endif // DEBUG_ENABLED
2809
OPCODE_BREAK;
2810
}
2811
2812
OPCODE(OPCODE_RETURN_TYPED_ARRAY) {
2813
CHECK_SPACE(5);
2814
GET_VARIANT_PTR(r, 0);
2815
2816
GET_VARIANT_PTR(script_type, 1);
2817
Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 3];
2818
int native_type_idx = _code_ptr[ip + 4];
2819
GD_ERR_BREAK(native_type_idx < 0 || native_type_idx >= _global_names_count);
2820
const StringName native_type = _global_names_ptr[native_type_idx];
2821
2822
if (r->get_type() != Variant::ARRAY) {
2823
#ifdef DEBUG_ENABLED
2824
err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "Array[%s]".)",
2825
Variant::get_type_name(r->get_type()), Variant::get_type_name(builtin_type));
2826
#endif
2827
OPCODE_BREAK;
2828
}
2829
2830
Array *array = VariantInternal::get_array(r);
2831
2832
if (array->get_typed_builtin() != ((uint32_t)builtin_type) || array->get_typed_class_name() != native_type || array->get_typed_script() != *script_type) {
2833
#ifdef DEBUG_ENABLED
2834
err_text = vformat(R"(Trying to return an array of type "%s" where expected return type is "Array[%s]".)",
2835
_get_var_type(r), _get_element_type(builtin_type, native_type, *script_type));
2836
#endif // DEBUG_ENABLED
2837
OPCODE_BREAK;
2838
}
2839
2840
retvalue = *array;
2841
2842
#ifdef DEBUG_ENABLED
2843
exit_ok = true;
2844
#endif // DEBUG_ENABLED
2845
OPCODE_BREAK;
2846
}
2847
2848
OPCODE(OPCODE_RETURN_TYPED_DICTIONARY) {
2849
CHECK_SPACE(8);
2850
GET_VARIANT_PTR(r, 0);
2851
2852
GET_VARIANT_PTR(key_script_type, 1);
2853
Variant::Type key_builtin_type = (Variant::Type)_code_ptr[ip + 4];
2854
int key_native_type_idx = _code_ptr[ip + 5];
2855
GD_ERR_BREAK(key_native_type_idx < 0 || key_native_type_idx >= _global_names_count);
2856
const StringName key_native_type = _global_names_ptr[key_native_type_idx];
2857
2858
GET_VARIANT_PTR(value_script_type, 2);
2859
Variant::Type value_builtin_type = (Variant::Type)_code_ptr[ip + 6];
2860
int value_native_type_idx = _code_ptr[ip + 7];
2861
GD_ERR_BREAK(value_native_type_idx < 0 || value_native_type_idx >= _global_names_count);
2862
const StringName value_native_type = _global_names_ptr[value_native_type_idx];
2863
2864
if (r->get_type() != Variant::DICTIONARY) {
2865
#ifdef DEBUG_ENABLED
2866
err_text = vformat(R"(Trying to return a value of type "%s" where expected return type is "Dictionary[%s, %s]".)",
2867
_get_var_type(r), _get_element_type(key_builtin_type, key_native_type, *key_script_type),
2868
_get_element_type(value_builtin_type, value_native_type, *value_script_type));
2869
#endif // DEBUG_ENABLED
2870
OPCODE_BREAK;
2871
}
2872
2873
Dictionary *dictionary = VariantInternal::get_dictionary(r);
2874
2875
if (dictionary->get_typed_key_builtin() != ((uint32_t)key_builtin_type) || dictionary->get_typed_key_class_name() != key_native_type || dictionary->get_typed_key_script() != *key_script_type ||
2876
dictionary->get_typed_value_builtin() != ((uint32_t)value_builtin_type) || dictionary->get_typed_value_class_name() != value_native_type || dictionary->get_typed_value_script() != *value_script_type) {
2877
#ifdef DEBUG_ENABLED
2878
err_text = vformat(R"(Trying to return a dictionary of type "%s" where expected return type is "Dictionary[%s, %s]".)",
2879
_get_var_type(r), _get_element_type(key_builtin_type, key_native_type, *key_script_type),
2880
_get_element_type(value_builtin_type, value_native_type, *value_script_type));
2881
#endif // DEBUG_ENABLED
2882
OPCODE_BREAK;
2883
}
2884
2885
retvalue = *dictionary;
2886
2887
#ifdef DEBUG_ENABLED
2888
exit_ok = true;
2889
#endif // DEBUG_ENABLED
2890
OPCODE_BREAK;
2891
}
2892
2893
OPCODE(OPCODE_RETURN_TYPED_NATIVE) {
2894
CHECK_SPACE(3);
2895
GET_VARIANT_PTR(r, 0);
2896
2897
GET_VARIANT_PTR(type, 1);
2898
GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(type->operator Object *());
2899
GD_ERR_BREAK(!nc);
2900
2901
if (r->get_type() != Variant::OBJECT && r->get_type() != Variant::NIL) {
2902
err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
2903
Variant::get_type_name(r->get_type()), nc->get_name());
2904
OPCODE_BREAK;
2905
}
2906
2907
#ifdef DEBUG_ENABLED
2908
bool freed = false;
2909
Object *ret_obj = r->get_validated_object_with_check(freed);
2910
2911
if (freed) {
2912
err_text = "Trying to return a previously freed instance.";
2913
OPCODE_BREAK;
2914
}
2915
#else
2916
Object *ret_obj = r->operator Object *();
2917
#endif // DEBUG_ENABLED
2918
if (ret_obj && !ClassDB::is_parent_class(ret_obj->get_class_name(), nc->get_name())) {
2919
#ifdef DEBUG_ENABLED
2920
err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
2921
ret_obj->get_class_name(), nc->get_name());
2922
#endif // DEBUG_ENABLED
2923
OPCODE_BREAK;
2924
}
2925
retvalue = *r;
2926
2927
#ifdef DEBUG_ENABLED
2928
exit_ok = true;
2929
#endif // DEBUG_ENABLED
2930
OPCODE_BREAK;
2931
}
2932
2933
OPCODE(OPCODE_RETURN_TYPED_SCRIPT) {
2934
CHECK_SPACE(3);
2935
GET_VARIANT_PTR(r, 0);
2936
2937
GET_VARIANT_PTR(type, 1);
2938
Script *base_type = Object::cast_to<Script>(type->operator Object *());
2939
GD_ERR_BREAK(!base_type);
2940
2941
if (r->get_type() != Variant::OBJECT && r->get_type() != Variant::NIL) {
2942
#ifdef DEBUG_ENABLED
2943
err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
2944
Variant::get_type_name(r->get_type()), GDScript::debug_get_script_name(Ref<Script>(base_type)));
2945
#endif // DEBUG_ENABLED
2946
OPCODE_BREAK;
2947
}
2948
2949
#ifdef DEBUG_ENABLED
2950
bool freed = false;
2951
Object *ret_obj = r->get_validated_object_with_check(freed);
2952
2953
if (freed) {
2954
err_text = "Trying to return a previously freed instance.";
2955
OPCODE_BREAK;
2956
}
2957
#else
2958
Object *ret_obj = r->operator Object *();
2959
#endif // DEBUG_ENABLED
2960
2961
if (ret_obj) {
2962
ScriptInstance *ret_inst = ret_obj->get_script_instance();
2963
if (!ret_inst) {
2964
#ifdef DEBUG_ENABLED
2965
err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
2966
ret_obj->get_class_name(), GDScript::debug_get_script_name(Ref<GDScript>(base_type)));
2967
#endif // DEBUG_ENABLED
2968
OPCODE_BREAK;
2969
}
2970
2971
Script *ret_type = ret_obj->get_script_instance()->get_script().ptr();
2972
bool valid = false;
2973
2974
while (ret_type) {
2975
if (ret_type == base_type) {
2976
valid = true;
2977
break;
2978
}
2979
ret_type = ret_type->get_base_script().ptr();
2980
}
2981
2982
if (!valid) {
2983
#ifdef DEBUG_ENABLED
2984
err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
2985
GDScript::debug_get_script_name(ret_obj->get_script_instance()->get_script()), GDScript::debug_get_script_name(Ref<GDScript>(base_type)));
2986
#endif // DEBUG_ENABLED
2987
OPCODE_BREAK;
2988
}
2989
}
2990
retvalue = *r;
2991
2992
#ifdef DEBUG_ENABLED
2993
exit_ok = true;
2994
#endif // DEBUG_ENABLED
2995
OPCODE_BREAK;
2996
}
2997
2998
OPCODE(OPCODE_ITERATE_BEGIN) {
2999
CHECK_SPACE(8); // Space for this and a regular iterate.
3000
3001
GET_VARIANT_PTR(counter, 0);
3002
GET_VARIANT_PTR(container, 1);
3003
3004
*counter = Variant();
3005
3006
bool valid;
3007
if (!container->iter_init(*counter, valid)) {
3008
#ifdef DEBUG_ENABLED
3009
if (!valid) {
3010
err_text = "Unable to iterate on object of type '" + Variant::get_type_name(container->get_type()) + "'.";
3011
OPCODE_BREAK;
3012
}
3013
#endif
3014
int jumpto = _code_ptr[ip + 4];
3015
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3016
ip = jumpto;
3017
} else {
3018
GET_VARIANT_PTR(iterator, 2);
3019
3020
*iterator = container->iter_get(*counter, valid);
3021
#ifdef DEBUG_ENABLED
3022
if (!valid) {
3023
err_text = "Unable to obtain iterator object of type '" + Variant::get_type_name(container->get_type()) + "'.";
3024
OPCODE_BREAK;
3025
}
3026
#endif
3027
ip += 5; // Skip regular iterate which is always next.
3028
}
3029
}
3030
DISPATCH_OPCODE;
3031
3032
OPCODE(OPCODE_ITERATE_BEGIN_INT) {
3033
CHECK_SPACE(8); // Check space for iterate instruction too.
3034
3035
GET_VARIANT_PTR(counter, 0);
3036
GET_VARIANT_PTR(container, 1);
3037
3038
int64_t size = *VariantInternal::get_int(container);
3039
3040
VariantInternal::initialize(counter, Variant::INT);
3041
*VariantInternal::get_int(counter) = 0;
3042
3043
if (size > 0) {
3044
GET_VARIANT_PTR(iterator, 2);
3045
VariantInternal::initialize(iterator, Variant::INT);
3046
*VariantInternal::get_int(iterator) = 0;
3047
3048
// Skip regular iterate.
3049
ip += 5;
3050
} else {
3051
// Jump to end of loop.
3052
int jumpto = _code_ptr[ip + 4];
3053
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3054
ip = jumpto;
3055
}
3056
}
3057
DISPATCH_OPCODE;
3058
3059
OPCODE(OPCODE_ITERATE_BEGIN_FLOAT) {
3060
CHECK_SPACE(8); // Check space for iterate instruction too.
3061
3062
GET_VARIANT_PTR(counter, 0);
3063
GET_VARIANT_PTR(container, 1);
3064
3065
double size = *VariantInternal::get_float(container);
3066
3067
VariantInternal::initialize(counter, Variant::FLOAT);
3068
*VariantInternal::get_float(counter) = 0.0;
3069
3070
if (size > 0) {
3071
GET_VARIANT_PTR(iterator, 2);
3072
VariantInternal::initialize(iterator, Variant::FLOAT);
3073
*VariantInternal::get_float(iterator) = 0;
3074
3075
// Skip regular iterate.
3076
ip += 5;
3077
} else {
3078
// Jump to end of loop.
3079
int jumpto = _code_ptr[ip + 4];
3080
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3081
ip = jumpto;
3082
}
3083
}
3084
DISPATCH_OPCODE;
3085
3086
OPCODE(OPCODE_ITERATE_BEGIN_VECTOR2) {
3087
CHECK_SPACE(8); // Check space for iterate instruction too.
3088
3089
GET_VARIANT_PTR(counter, 0);
3090
GET_VARIANT_PTR(container, 1);
3091
3092
Vector2 *bounds = VariantInternal::get_vector2(container);
3093
3094
VariantInternal::initialize(counter, Variant::FLOAT);
3095
*VariantInternal::get_float(counter) = bounds->x;
3096
3097
if (bounds->x < bounds->y) {
3098
GET_VARIANT_PTR(iterator, 2);
3099
VariantInternal::initialize(iterator, Variant::FLOAT);
3100
*VariantInternal::get_float(iterator) = bounds->x;
3101
3102
// Skip regular iterate.
3103
ip += 5;
3104
} else {
3105
// Jump to end of loop.
3106
int jumpto = _code_ptr[ip + 4];
3107
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3108
ip = jumpto;
3109
}
3110
}
3111
DISPATCH_OPCODE;
3112
3113
OPCODE(OPCODE_ITERATE_BEGIN_VECTOR2I) {
3114
CHECK_SPACE(8); // Check space for iterate instruction too.
3115
3116
GET_VARIANT_PTR(counter, 0);
3117
GET_VARIANT_PTR(container, 1);
3118
3119
Vector2i *bounds = VariantInternal::get_vector2i(container);
3120
3121
VariantInternal::initialize(counter, Variant::FLOAT);
3122
*VariantInternal::get_int(counter) = bounds->x;
3123
3124
if (bounds->x < bounds->y) {
3125
GET_VARIANT_PTR(iterator, 2);
3126
VariantInternal::initialize(iterator, Variant::INT);
3127
*VariantInternal::get_int(iterator) = bounds->x;
3128
3129
// Skip regular iterate.
3130
ip += 5;
3131
} else {
3132
// Jump to end of loop.
3133
int jumpto = _code_ptr[ip + 4];
3134
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3135
ip = jumpto;
3136
}
3137
}
3138
DISPATCH_OPCODE;
3139
3140
OPCODE(OPCODE_ITERATE_BEGIN_VECTOR3) {
3141
CHECK_SPACE(8); // Check space for iterate instruction too.
3142
3143
GET_VARIANT_PTR(counter, 0);
3144
GET_VARIANT_PTR(container, 1);
3145
3146
Vector3 *bounds = VariantInternal::get_vector3(container);
3147
double from = bounds->x;
3148
double to = bounds->y;
3149
double step = bounds->z;
3150
3151
VariantInternal::initialize(counter, Variant::FLOAT);
3152
*VariantInternal::get_float(counter) = from;
3153
3154
bool do_continue = from == to ? false : (from < to ? step > 0 : step < 0);
3155
3156
if (do_continue) {
3157
GET_VARIANT_PTR(iterator, 2);
3158
VariantInternal::initialize(iterator, Variant::FLOAT);
3159
*VariantInternal::get_float(iterator) = from;
3160
3161
// Skip regular iterate.
3162
ip += 5;
3163
} else {
3164
// Jump to end of loop.
3165
int jumpto = _code_ptr[ip + 4];
3166
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3167
ip = jumpto;
3168
}
3169
}
3170
DISPATCH_OPCODE;
3171
3172
OPCODE(OPCODE_ITERATE_BEGIN_VECTOR3I) {
3173
CHECK_SPACE(8); // Check space for iterate instruction too.
3174
3175
GET_VARIANT_PTR(counter, 0);
3176
GET_VARIANT_PTR(container, 1);
3177
3178
Vector3i *bounds = VariantInternal::get_vector3i(container);
3179
int64_t from = bounds->x;
3180
int64_t to = bounds->y;
3181
int64_t step = bounds->z;
3182
3183
VariantInternal::initialize(counter, Variant::INT);
3184
*VariantInternal::get_int(counter) = from;
3185
3186
bool do_continue = from == to ? false : (from < to ? step > 0 : step < 0);
3187
3188
if (do_continue) {
3189
GET_VARIANT_PTR(iterator, 2);
3190
VariantInternal::initialize(iterator, Variant::INT);
3191
*VariantInternal::get_int(iterator) = from;
3192
3193
// Skip regular iterate.
3194
ip += 5;
3195
} else {
3196
// Jump to end of loop.
3197
int jumpto = _code_ptr[ip + 4];
3198
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3199
ip = jumpto;
3200
}
3201
}
3202
DISPATCH_OPCODE;
3203
3204
OPCODE(OPCODE_ITERATE_BEGIN_STRING) {
3205
CHECK_SPACE(8); // Check space for iterate instruction too.
3206
3207
GET_VARIANT_PTR(counter, 0);
3208
GET_VARIANT_PTR(container, 1);
3209
3210
String *str = VariantInternal::get_string(container);
3211
3212
VariantInternal::initialize(counter, Variant::INT);
3213
*VariantInternal::get_int(counter) = 0;
3214
3215
if (!str->is_empty()) {
3216
GET_VARIANT_PTR(iterator, 2);
3217
VariantInternal::initialize(iterator, Variant::STRING);
3218
*VariantInternal::get_string(iterator) = str->substr(0, 1);
3219
3220
// Skip regular iterate.
3221
ip += 5;
3222
} else {
3223
// Jump to end of loop.
3224
int jumpto = _code_ptr[ip + 4];
3225
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3226
ip = jumpto;
3227
}
3228
}
3229
DISPATCH_OPCODE;
3230
3231
OPCODE(OPCODE_ITERATE_BEGIN_DICTIONARY) {
3232
CHECK_SPACE(8); // Check space for iterate instruction too.
3233
3234
GET_VARIANT_PTR(counter, 0);
3235
GET_VARIANT_PTR(container, 1);
3236
3237
Dictionary *dict = VariantInternal::get_dictionary(container);
3238
const Variant *next = dict->next(nullptr);
3239
3240
if (!dict->is_empty()) {
3241
GET_VARIANT_PTR(iterator, 2);
3242
*counter = *next;
3243
*iterator = *next;
3244
3245
// Skip regular iterate.
3246
ip += 5;
3247
} else {
3248
// Jump to end of loop.
3249
int jumpto = _code_ptr[ip + 4];
3250
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3251
ip = jumpto;
3252
}
3253
}
3254
DISPATCH_OPCODE;
3255
3256
OPCODE(OPCODE_ITERATE_BEGIN_ARRAY) {
3257
CHECK_SPACE(8); // Check space for iterate instruction too.
3258
3259
GET_VARIANT_PTR(counter, 0);
3260
GET_VARIANT_PTR(container, 1);
3261
3262
Array *array = VariantInternal::get_array(container);
3263
3264
VariantInternal::initialize(counter, Variant::INT);
3265
*VariantInternal::get_int(counter) = 0;
3266
3267
if (!array->is_empty()) {
3268
GET_VARIANT_PTR(iterator, 2);
3269
*iterator = array->get(0);
3270
3271
// Skip regular iterate.
3272
ip += 5;
3273
} else {
3274
// Jump to end of loop.
3275
int jumpto = _code_ptr[ip + 4];
3276
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3277
ip = jumpto;
3278
}
3279
}
3280
DISPATCH_OPCODE;
3281
3282
#define OPCODE_ITERATE_BEGIN_PACKED_ARRAY(m_var_type, m_elem_type, m_get_func, m_var_ret_type, m_ret_type, m_ret_get_func) \
3283
OPCODE(OPCODE_ITERATE_BEGIN_PACKED_##m_var_type##_ARRAY) { \
3284
CHECK_SPACE(8); \
3285
GET_VARIANT_PTR(counter, 0); \
3286
GET_VARIANT_PTR(container, 1); \
3287
Vector<m_elem_type> *array = VariantInternal::m_get_func(container); \
3288
VariantInternal::initialize(counter, Variant::INT); \
3289
*VariantInternal::get_int(counter) = 0; \
3290
if (!array->is_empty()) { \
3291
GET_VARIANT_PTR(iterator, 2); \
3292
VariantInternal::initialize(iterator, Variant::m_var_ret_type); \
3293
m_ret_type *it = VariantInternal::m_ret_get_func(iterator); \
3294
*it = array->get(0); \
3295
ip += 5; \
3296
} else { \
3297
int jumpto = _code_ptr[ip + 4]; \
3298
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size); \
3299
ip = jumpto; \
3300
} \
3301
} \
3302
DISPATCH_OPCODE
3303
3304
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(BYTE, uint8_t, get_byte_array, INT, int64_t, get_int);
3305
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(INT32, int32_t, get_int32_array, INT, int64_t, get_int);
3306
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(INT64, int64_t, get_int64_array, INT, int64_t, get_int);
3307
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(FLOAT32, float, get_float32_array, FLOAT, double, get_float);
3308
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(FLOAT64, double, get_float64_array, FLOAT, double, get_float);
3309
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(STRING, String, get_string_array, STRING, String, get_string);
3310
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(VECTOR2, Vector2, get_vector2_array, VECTOR2, Vector2, get_vector2);
3311
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(VECTOR3, Vector3, get_vector3_array, VECTOR3, Vector3, get_vector3);
3312
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(COLOR, Color, get_color_array, COLOR, Color, get_color);
3313
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(VECTOR4, Vector4, get_vector4_array, VECTOR4, Vector4, get_vector4);
3314
3315
OPCODE(OPCODE_ITERATE_BEGIN_OBJECT) {
3316
CHECK_SPACE(4);
3317
3318
GET_VARIANT_PTR(counter, 0);
3319
GET_VARIANT_PTR(container, 1);
3320
3321
#ifdef DEBUG_ENABLED
3322
bool freed = false;
3323
Object *obj = container->get_validated_object_with_check(freed);
3324
if (freed) {
3325
err_text = "Trying to iterate on a previously freed object.";
3326
OPCODE_BREAK;
3327
} else if (!obj) {
3328
err_text = "Trying to iterate on a null value.";
3329
OPCODE_BREAK;
3330
}
3331
#else
3332
Object *obj = *VariantInternal::get_object(container);
3333
#endif
3334
3335
*counter = Variant();
3336
Array ref = { *counter };
3337
Variant vref;
3338
VariantInternal::initialize(&vref, Variant::ARRAY);
3339
*VariantInternal::get_array(&vref) = ref;
3340
3341
const Variant *args[] = { &vref };
3342
3343
Callable::CallError ce;
3344
Variant has_next = obj->callp(CoreStringName(_iter_init), args, 1, ce);
3345
3346
#ifdef DEBUG_ENABLED
3347
if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
3348
err_text = vformat(R"(There was an error calling "_iter_next" on iterator object of type %s.)", *container);
3349
OPCODE_BREAK;
3350
}
3351
#endif
3352
if (!has_next.booleanize()) {
3353
int jumpto = _code_ptr[ip + 4];
3354
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3355
ip = jumpto;
3356
} else {
3357
*counter = ref[0];
3358
3359
GET_VARIANT_PTR(iterator, 2);
3360
*iterator = obj->callp(CoreStringName(_iter_get), (const Variant **)&counter, 1, ce);
3361
#ifdef DEBUG_ENABLED
3362
if (ce.error != Callable::CallError::CALL_OK) {
3363
err_text = vformat(R"(There was an error calling "_iter_get" on iterator object of type %s.)", *container);
3364
OPCODE_BREAK;
3365
}
3366
#endif
3367
3368
ip += 5; // Loop again.
3369
}
3370
}
3371
DISPATCH_OPCODE;
3372
3373
OPCODE(OPCODE_ITERATE_BEGIN_RANGE) {
3374
CHECK_SPACE(6);
3375
3376
GET_VARIANT_PTR(counter, 0);
3377
GET_VARIANT_PTR(from_ptr, 1);
3378
GET_VARIANT_PTR(to_ptr, 2);
3379
GET_VARIANT_PTR(step_ptr, 3);
3380
3381
int64_t from = *VariantInternal::get_int(from_ptr);
3382
int64_t to = *VariantInternal::get_int(to_ptr);
3383
int64_t step = *VariantInternal::get_int(step_ptr);
3384
3385
VariantInternal::initialize(counter, Variant::INT);
3386
*VariantInternal::get_int(counter) = from;
3387
3388
bool do_continue = from == to ? false : (from < to ? step > 0 : step < 0);
3389
3390
if (do_continue) {
3391
GET_VARIANT_PTR(iterator, 4);
3392
VariantInternal::initialize(iterator, Variant::INT);
3393
*VariantInternal::get_int(iterator) = from;
3394
3395
// Skip regular iterate.
3396
ip += 7;
3397
} else {
3398
// Jump to end of loop.
3399
int jumpto = _code_ptr[ip + 6];
3400
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3401
ip = jumpto;
3402
}
3403
}
3404
DISPATCH_OPCODE;
3405
3406
OPCODE(OPCODE_ITERATE) {
3407
CHECK_SPACE(4);
3408
3409
GET_VARIANT_PTR(counter, 0);
3410
GET_VARIANT_PTR(container, 1);
3411
3412
bool valid;
3413
if (!container->iter_next(*counter, valid)) {
3414
#ifdef DEBUG_ENABLED
3415
if (!valid) {
3416
err_text = "Unable to iterate on object of type '" + Variant::get_type_name(container->get_type()) + "' (type changed since first iteration?).";
3417
OPCODE_BREAK;
3418
}
3419
#endif
3420
int jumpto = _code_ptr[ip + 4];
3421
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3422
ip = jumpto;
3423
} else {
3424
GET_VARIANT_PTR(iterator, 2);
3425
3426
*iterator = container->iter_get(*counter, valid);
3427
#ifdef DEBUG_ENABLED
3428
if (!valid) {
3429
err_text = "Unable to obtain iterator object of type '" + Variant::get_type_name(container->get_type()) + "' (but was obtained on first iteration?).";
3430
OPCODE_BREAK;
3431
}
3432
#endif
3433
ip += 5; //loop again
3434
}
3435
}
3436
DISPATCH_OPCODE;
3437
3438
OPCODE(OPCODE_ITERATE_INT) {
3439
CHECK_SPACE(4);
3440
3441
GET_VARIANT_PTR(counter, 0);
3442
GET_VARIANT_PTR(container, 1);
3443
3444
int64_t size = *VariantInternal::get_int(container);
3445
int64_t *count = VariantInternal::get_int(counter);
3446
3447
(*count)++;
3448
3449
if (*count >= size) {
3450
int jumpto = _code_ptr[ip + 4];
3451
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3452
ip = jumpto;
3453
} else {
3454
GET_VARIANT_PTR(iterator, 2);
3455
*VariantInternal::get_int(iterator) = *count;
3456
3457
ip += 5; // Loop again.
3458
}
3459
}
3460
DISPATCH_OPCODE;
3461
3462
OPCODE(OPCODE_ITERATE_FLOAT) {
3463
CHECK_SPACE(4);
3464
3465
GET_VARIANT_PTR(counter, 0);
3466
GET_VARIANT_PTR(container, 1);
3467
3468
double size = *VariantInternal::get_float(container);
3469
double *count = VariantInternal::get_float(counter);
3470
3471
(*count)++;
3472
3473
if (*count >= size) {
3474
int jumpto = _code_ptr[ip + 4];
3475
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3476
ip = jumpto;
3477
} else {
3478
GET_VARIANT_PTR(iterator, 2);
3479
*VariantInternal::get_float(iterator) = *count;
3480
3481
ip += 5; // Loop again.
3482
}
3483
}
3484
DISPATCH_OPCODE;
3485
3486
OPCODE(OPCODE_ITERATE_VECTOR2) {
3487
CHECK_SPACE(4);
3488
3489
GET_VARIANT_PTR(counter, 0);
3490
GET_VARIANT_PTR(container, 1);
3491
3492
const Vector2 *bounds = VariantInternal::get_vector2((const Variant *)container);
3493
double *count = VariantInternal::get_float(counter);
3494
3495
(*count)++;
3496
3497
if (*count >= bounds->y) {
3498
int jumpto = _code_ptr[ip + 4];
3499
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3500
ip = jumpto;
3501
} else {
3502
GET_VARIANT_PTR(iterator, 2);
3503
*VariantInternal::get_float(iterator) = *count;
3504
3505
ip += 5; // Loop again.
3506
}
3507
}
3508
DISPATCH_OPCODE;
3509
3510
OPCODE(OPCODE_ITERATE_VECTOR2I) {
3511
CHECK_SPACE(4);
3512
3513
GET_VARIANT_PTR(counter, 0);
3514
GET_VARIANT_PTR(container, 1);
3515
3516
const Vector2i *bounds = VariantInternal::get_vector2i((const Variant *)container);
3517
int64_t *count = VariantInternal::get_int(counter);
3518
3519
(*count)++;
3520
3521
if (*count >= bounds->y) {
3522
int jumpto = _code_ptr[ip + 4];
3523
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3524
ip = jumpto;
3525
} else {
3526
GET_VARIANT_PTR(iterator, 2);
3527
*VariantInternal::get_int(iterator) = *count;
3528
3529
ip += 5; // Loop again.
3530
}
3531
}
3532
DISPATCH_OPCODE;
3533
3534
OPCODE(OPCODE_ITERATE_VECTOR3) {
3535
CHECK_SPACE(4);
3536
3537
GET_VARIANT_PTR(counter, 0);
3538
GET_VARIANT_PTR(container, 1);
3539
3540
const Vector3 *bounds = VariantInternal::get_vector3((const Variant *)container);
3541
double *count = VariantInternal::get_float(counter);
3542
3543
*count += bounds->z;
3544
3545
if ((bounds->z < 0 && *count <= bounds->y) || (bounds->z > 0 && *count >= bounds->y)) {
3546
int jumpto = _code_ptr[ip + 4];
3547
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3548
ip = jumpto;
3549
} else {
3550
GET_VARIANT_PTR(iterator, 2);
3551
*VariantInternal::get_float(iterator) = *count;
3552
3553
ip += 5; // Loop again.
3554
}
3555
}
3556
DISPATCH_OPCODE;
3557
3558
OPCODE(OPCODE_ITERATE_VECTOR3I) {
3559
CHECK_SPACE(4);
3560
3561
GET_VARIANT_PTR(counter, 0);
3562
GET_VARIANT_PTR(container, 1);
3563
3564
const Vector3i *bounds = VariantInternal::get_vector3i((const Variant *)container);
3565
int64_t *count = VariantInternal::get_int(counter);
3566
3567
*count += bounds->z;
3568
3569
if ((bounds->z < 0 && *count <= bounds->y) || (bounds->z > 0 && *count >= bounds->y)) {
3570
int jumpto = _code_ptr[ip + 4];
3571
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3572
ip = jumpto;
3573
} else {
3574
GET_VARIANT_PTR(iterator, 2);
3575
*VariantInternal::get_int(iterator) = *count;
3576
3577
ip += 5; // Loop again.
3578
}
3579
}
3580
DISPATCH_OPCODE;
3581
3582
OPCODE(OPCODE_ITERATE_STRING) {
3583
CHECK_SPACE(4);
3584
3585
GET_VARIANT_PTR(counter, 0);
3586
GET_VARIANT_PTR(container, 1);
3587
3588
const String *str = VariantInternal::get_string((const Variant *)container);
3589
int64_t *idx = VariantInternal::get_int(counter);
3590
(*idx)++;
3591
3592
if (*idx >= str->length()) {
3593
int jumpto = _code_ptr[ip + 4];
3594
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3595
ip = jumpto;
3596
} else {
3597
GET_VARIANT_PTR(iterator, 2);
3598
*VariantInternal::get_string(iterator) = str->substr(*idx, 1);
3599
3600
ip += 5; // Loop again.
3601
}
3602
}
3603
DISPATCH_OPCODE;
3604
3605
OPCODE(OPCODE_ITERATE_DICTIONARY) {
3606
CHECK_SPACE(4);
3607
3608
GET_VARIANT_PTR(counter, 0);
3609
GET_VARIANT_PTR(container, 1);
3610
3611
const Dictionary *dict = VariantInternal::get_dictionary((const Variant *)container);
3612
const Variant *next = dict->next(counter);
3613
3614
if (!next) {
3615
int jumpto = _code_ptr[ip + 4];
3616
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3617
ip = jumpto;
3618
} else {
3619
GET_VARIANT_PTR(iterator, 2);
3620
*counter = *next;
3621
*iterator = *next;
3622
3623
ip += 5; // Loop again.
3624
}
3625
}
3626
DISPATCH_OPCODE;
3627
3628
OPCODE(OPCODE_ITERATE_ARRAY) {
3629
CHECK_SPACE(4);
3630
3631
GET_VARIANT_PTR(counter, 0);
3632
GET_VARIANT_PTR(container, 1);
3633
3634
const Array *array = VariantInternal::get_array((const Variant *)container);
3635
int64_t *idx = VariantInternal::get_int(counter);
3636
(*idx)++;
3637
3638
if (*idx >= array->size()) {
3639
int jumpto = _code_ptr[ip + 4];
3640
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3641
ip = jumpto;
3642
} else {
3643
GET_VARIANT_PTR(iterator, 2);
3644
*iterator = array->get(*idx);
3645
3646
ip += 5; // Loop again.
3647
}
3648
}
3649
DISPATCH_OPCODE;
3650
3651
#define OPCODE_ITERATE_PACKED_ARRAY(m_var_type, m_elem_type, m_get_func, m_ret_get_func) \
3652
OPCODE(OPCODE_ITERATE_PACKED_##m_var_type##_ARRAY) { \
3653
CHECK_SPACE(4); \
3654
GET_VARIANT_PTR(counter, 0); \
3655
GET_VARIANT_PTR(container, 1); \
3656
const Vector<m_elem_type> *array = VariantInternal::m_get_func((const Variant *)container); \
3657
int64_t *idx = VariantInternal::get_int(counter); \
3658
(*idx)++; \
3659
if (*idx >= array->size()) { \
3660
int jumpto = _code_ptr[ip + 4]; \
3661
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size); \
3662
ip = jumpto; \
3663
} else { \
3664
GET_VARIANT_PTR(iterator, 2); \
3665
*VariantInternal::m_ret_get_func(iterator) = array->get(*idx); \
3666
ip += 5; \
3667
} \
3668
} \
3669
DISPATCH_OPCODE
3670
3671
OPCODE_ITERATE_PACKED_ARRAY(BYTE, uint8_t, get_byte_array, get_int);
3672
OPCODE_ITERATE_PACKED_ARRAY(INT32, int32_t, get_int32_array, get_int);
3673
OPCODE_ITERATE_PACKED_ARRAY(INT64, int64_t, get_int64_array, get_int);
3674
OPCODE_ITERATE_PACKED_ARRAY(FLOAT32, float, get_float32_array, get_float);
3675
OPCODE_ITERATE_PACKED_ARRAY(FLOAT64, double, get_float64_array, get_float);
3676
OPCODE_ITERATE_PACKED_ARRAY(STRING, String, get_string_array, get_string);
3677
OPCODE_ITERATE_PACKED_ARRAY(VECTOR2, Vector2, get_vector2_array, get_vector2);
3678
OPCODE_ITERATE_PACKED_ARRAY(VECTOR3, Vector3, get_vector3_array, get_vector3);
3679
OPCODE_ITERATE_PACKED_ARRAY(COLOR, Color, get_color_array, get_color);
3680
OPCODE_ITERATE_PACKED_ARRAY(VECTOR4, Vector4, get_vector4_array, get_vector4);
3681
3682
OPCODE(OPCODE_ITERATE_OBJECT) {
3683
CHECK_SPACE(4);
3684
3685
GET_VARIANT_PTR(counter, 0);
3686
GET_VARIANT_PTR(container, 1);
3687
3688
#ifdef DEBUG_ENABLED
3689
bool freed = false;
3690
Object *obj = container->get_validated_object_with_check(freed);
3691
if (freed) {
3692
err_text = "Trying to iterate on a previously freed object.";
3693
OPCODE_BREAK;
3694
} else if (!obj) {
3695
err_text = "Trying to iterate on a null value.";
3696
OPCODE_BREAK;
3697
}
3698
#else
3699
Object *obj = *VariantInternal::get_object(container);
3700
#endif
3701
3702
Array ref = { *counter };
3703
Variant vref;
3704
VariantInternal::initialize(&vref, Variant::ARRAY);
3705
*VariantInternal::get_array(&vref) = ref;
3706
3707
const Variant *args[] = { &vref };
3708
3709
Callable::CallError ce;
3710
Variant has_next = obj->callp(CoreStringName(_iter_next), args, 1, ce);
3711
3712
#ifdef DEBUG_ENABLED
3713
if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
3714
err_text = vformat(R"(There was an error calling "_iter_next" on iterator object of type %s.)", *container);
3715
OPCODE_BREAK;
3716
}
3717
#endif
3718
if (!has_next.booleanize()) {
3719
int jumpto = _code_ptr[ip + 4];
3720
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3721
ip = jumpto;
3722
} else {
3723
*counter = ref[0];
3724
3725
GET_VARIANT_PTR(iterator, 2);
3726
*iterator = obj->callp(CoreStringName(_iter_get), (const Variant **)&counter, 1, ce);
3727
#ifdef DEBUG_ENABLED
3728
if (ce.error != Callable::CallError::CALL_OK) {
3729
err_text = vformat(R"(There was an error calling "_iter_get" on iterator object of type %s.)", *container);
3730
OPCODE_BREAK;
3731
}
3732
#endif
3733
3734
ip += 5; // Loop again.
3735
}
3736
}
3737
DISPATCH_OPCODE;
3738
3739
OPCODE(OPCODE_ITERATE_RANGE) {
3740
CHECK_SPACE(5);
3741
3742
GET_VARIANT_PTR(counter, 0);
3743
GET_VARIANT_PTR(to_ptr, 1);
3744
GET_VARIANT_PTR(step_ptr, 2);
3745
3746
int64_t to = *VariantInternal::get_int(to_ptr);
3747
int64_t step = *VariantInternal::get_int(step_ptr);
3748
3749
int64_t *count = VariantInternal::get_int(counter);
3750
3751
*count += step;
3752
3753
if ((step < 0 && *count <= to) || (step > 0 && *count >= to)) {
3754
int jumpto = _code_ptr[ip + 5];
3755
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
3756
ip = jumpto;
3757
} else {
3758
GET_VARIANT_PTR(iterator, 3);
3759
*VariantInternal::get_int(iterator) = *count;
3760
3761
ip += 6; // Loop again.
3762
}
3763
}
3764
DISPATCH_OPCODE;
3765
3766
OPCODE(OPCODE_STORE_GLOBAL) {
3767
CHECK_SPACE(3);
3768
int global_idx = _code_ptr[ip + 2];
3769
GD_ERR_BREAK(global_idx < 0 || global_idx >= GDScriptLanguage::get_singleton()->get_global_array_size());
3770
3771
GET_VARIANT_PTR(dst, 0);
3772
*dst = GDScriptLanguage::get_singleton()->get_global_array()[global_idx];
3773
3774
ip += 3;
3775
}
3776
DISPATCH_OPCODE;
3777
3778
OPCODE(OPCODE_STORE_NAMED_GLOBAL) {
3779
CHECK_SPACE(3);
3780
int globalname_idx = _code_ptr[ip + 2];
3781
GD_ERR_BREAK(globalname_idx < 0 || globalname_idx >= _global_names_count);
3782
const StringName *globalname = &_global_names_ptr[globalname_idx];
3783
GD_ERR_BREAK(!GDScriptLanguage::get_singleton()->get_named_globals_map().has(*globalname));
3784
3785
GET_VARIANT_PTR(dst, 0);
3786
*dst = GDScriptLanguage::get_singleton()->get_named_globals_map()[*globalname];
3787
3788
ip += 3;
3789
}
3790
DISPATCH_OPCODE;
3791
3792
#define OPCODE_TYPE_ADJUST(m_v_type, m_c_type) \
3793
OPCODE(OPCODE_TYPE_ADJUST_##m_v_type) { \
3794
CHECK_SPACE(2); \
3795
GET_VARIANT_PTR(arg, 0); \
3796
VariantTypeAdjust<m_c_type>::adjust(arg); \
3797
ip += 2; \
3798
} \
3799
DISPATCH_OPCODE
3800
3801
OPCODE_TYPE_ADJUST(BOOL, bool);
3802
OPCODE_TYPE_ADJUST(INT, int64_t);
3803
OPCODE_TYPE_ADJUST(FLOAT, double);
3804
OPCODE_TYPE_ADJUST(STRING, String);
3805
OPCODE_TYPE_ADJUST(VECTOR2, Vector2);
3806
OPCODE_TYPE_ADJUST(VECTOR2I, Vector2i);
3807
OPCODE_TYPE_ADJUST(RECT2, Rect2);
3808
OPCODE_TYPE_ADJUST(RECT2I, Rect2i);
3809
OPCODE_TYPE_ADJUST(VECTOR3, Vector3);
3810
OPCODE_TYPE_ADJUST(VECTOR3I, Vector3i);
3811
OPCODE_TYPE_ADJUST(TRANSFORM2D, Transform2D);
3812
OPCODE_TYPE_ADJUST(VECTOR4, Vector4);
3813
OPCODE_TYPE_ADJUST(VECTOR4I, Vector4i);
3814
OPCODE_TYPE_ADJUST(PLANE, Plane);
3815
OPCODE_TYPE_ADJUST(QUATERNION, Quaternion);
3816
OPCODE_TYPE_ADJUST(AABB, AABB);
3817
OPCODE_TYPE_ADJUST(BASIS, Basis);
3818
OPCODE_TYPE_ADJUST(TRANSFORM3D, Transform3D);
3819
OPCODE_TYPE_ADJUST(PROJECTION, Projection);
3820
OPCODE_TYPE_ADJUST(COLOR, Color);
3821
OPCODE_TYPE_ADJUST(STRING_NAME, StringName);
3822
OPCODE_TYPE_ADJUST(NODE_PATH, NodePath);
3823
OPCODE_TYPE_ADJUST(RID, RID);
3824
OPCODE_TYPE_ADJUST(OBJECT, Object *);
3825
OPCODE_TYPE_ADJUST(CALLABLE, Callable);
3826
OPCODE_TYPE_ADJUST(SIGNAL, Signal);
3827
OPCODE_TYPE_ADJUST(DICTIONARY, Dictionary);
3828
OPCODE_TYPE_ADJUST(ARRAY, Array);
3829
OPCODE_TYPE_ADJUST(PACKED_BYTE_ARRAY, PackedByteArray);
3830
OPCODE_TYPE_ADJUST(PACKED_INT32_ARRAY, PackedInt32Array);
3831
OPCODE_TYPE_ADJUST(PACKED_INT64_ARRAY, PackedInt64Array);
3832
OPCODE_TYPE_ADJUST(PACKED_FLOAT32_ARRAY, PackedFloat32Array);
3833
OPCODE_TYPE_ADJUST(PACKED_FLOAT64_ARRAY, PackedFloat64Array);
3834
OPCODE_TYPE_ADJUST(PACKED_STRING_ARRAY, PackedStringArray);
3835
OPCODE_TYPE_ADJUST(PACKED_VECTOR2_ARRAY, PackedVector2Array);
3836
OPCODE_TYPE_ADJUST(PACKED_VECTOR3_ARRAY, PackedVector3Array);
3837
OPCODE_TYPE_ADJUST(PACKED_COLOR_ARRAY, PackedColorArray);
3838
OPCODE_TYPE_ADJUST(PACKED_VECTOR4_ARRAY, PackedVector4Array);
3839
3840
OPCODE(OPCODE_ASSERT) {
3841
CHECK_SPACE(3);
3842
3843
#ifdef DEBUG_ENABLED
3844
GET_VARIANT_PTR(test, 0);
3845
bool result = test->booleanize();
3846
3847
if (!result) {
3848
String message_str;
3849
if (_code_ptr[ip + 2] != 0) {
3850
GET_VARIANT_PTR(message, 1);
3851
Variant message_var = *message;
3852
if (message->get_type() != Variant::NIL) {
3853
message_str = message_var;
3854
}
3855
}
3856
if (message_str.is_empty()) {
3857
err_text = "Assertion failed.";
3858
} else {
3859
err_text = "Assertion failed: " + message_str;
3860
}
3861
OPCODE_BREAK;
3862
}
3863
3864
#endif
3865
ip += 3;
3866
}
3867
DISPATCH_OPCODE;
3868
3869
OPCODE(OPCODE_BREAKPOINT) {
3870
#ifdef DEBUG_ENABLED
3871
if (EngineDebugger::is_active()) {
3872
GDScriptLanguage::get_singleton()->debug_break("Breakpoint Statement", true);
3873
}
3874
#endif
3875
ip += 1;
3876
}
3877
DISPATCH_OPCODE;
3878
3879
OPCODE(OPCODE_LINE) {
3880
CHECK_SPACE(2);
3881
3882
line = _code_ptr[ip + 1];
3883
ip += 2;
3884
3885
if (EngineDebugger::is_active()) {
3886
// line
3887
bool do_break = false;
3888
3889
if (unlikely(EngineDebugger::get_script_debugger()->get_lines_left() > 0)) {
3890
if (EngineDebugger::get_script_debugger()->get_depth() <= 0) {
3891
EngineDebugger::get_script_debugger()->set_lines_left(EngineDebugger::get_script_debugger()->get_lines_left() - 1);
3892
}
3893
if (EngineDebugger::get_script_debugger()->get_lines_left() <= 0) {
3894
do_break = true;
3895
}
3896
}
3897
3898
if (EngineDebugger::get_script_debugger()->is_breakpoint(line, source)) {
3899
do_break = true;
3900
}
3901
3902
if (unlikely(do_break)) {
3903
GDScriptLanguage::get_singleton()->debug_break("Breakpoint", true);
3904
}
3905
3906
EngineDebugger::get_singleton()->line_poll();
3907
}
3908
}
3909
DISPATCH_OPCODE;
3910
3911
OPCODE(OPCODE_END) {
3912
#ifdef DEBUG_ENABLED
3913
exit_ok = true;
3914
#endif
3915
OPCODE_BREAK;
3916
}
3917
3918
#if 0 // Enable for debugging.
3919
default: {
3920
err_text = "Illegal opcode " + itos(_code_ptr[ip]) + " at address " + itos(ip);
3921
OPCODE_BREAK;
3922
}
3923
#endif
3924
}
3925
3926
OPCODES_END
3927
#ifdef DEBUG_ENABLED
3928
if (exit_ok) {
3929
OPCODE_OUT;
3930
}
3931
//error
3932
// function, file, line, error, explanation
3933
String err_file;
3934
bool instance_valid_with_script = p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid();
3935
if (instance_valid_with_script && !get_script()->path.is_empty()) {
3936
err_file = get_script()->path;
3937
} else if (script) {
3938
err_file = script->path;
3939
}
3940
if (err_file.is_empty()) {
3941
err_file = "<built-in>";
3942
}
3943
String err_func = name;
3944
if (instance_valid_with_script && p_instance->script->local_name != StringName()) {
3945
err_func = p_instance->script->local_name.operator String() + "." + err_func;
3946
}
3947
int err_line = line;
3948
if (err_text.is_empty()) {
3949
err_text = "Internal script error! Opcode: " + itos(last_opcode) + " (please report).";
3950
}
3951
3952
_err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, err_text.utf8().get_data(), false, ERR_HANDLER_SCRIPT);
3953
GDScriptLanguage::get_singleton()->debug_break(err_text, false);
3954
3955
// Get a default return type in case of failure
3956
retvalue = _get_default_variant_for_data_type(return_type);
3957
#endif
3958
3959
OPCODE_OUT;
3960
}
3961
3962
OPCODES_OUT
3963
#ifdef DEBUG_ENABLED
3964
if (GDScriptLanguage::get_singleton()->profiling) {
3965
uint64_t time_taken = OS::get_singleton()->get_ticks_usec() - function_start_time;
3966
profile.total_time.add(time_taken);
3967
profile.self_time.add(time_taken - function_call_time);
3968
profile.frame_total_time.add(time_taken);
3969
profile.frame_self_time.add(time_taken - function_call_time);
3970
if (Thread::get_caller_id() == Thread::get_main_id()) {
3971
GDScriptLanguage::get_singleton()->script_frame_time += time_taken - function_call_time;
3972
}
3973
}
3974
#endif
3975
3976
// Check if this is not the last time it was interrupted by `await` or if it's the first time executing.
3977
// If that is the case then we exit the function as normal. Otherwise we postpone it until the last `await` is completed.
3978
// This ensures the call stack can be properly shown when using `await`, showing what resumed the function.
3979
if (!p_state || awaited) {
3980
GDScriptLanguage::get_singleton()->exit_function();
3981
3982
// Free stack, except reserved addresses.
3983
for (int i = FIXED_ADDRESSES_MAX; i < _stack_size; i++) {
3984
stack[i].~Variant();
3985
}
3986
}
3987
3988
// Always free reserved addresses, since they are never copied.
3989
for (int i = 0; i < FIXED_ADDRESSES_MAX; i++) {
3990
stack[i].~Variant();
3991
}
3992
3993
call_depth--;
3994
3995
if (p_state && !awaited) {
3996
// This means we have finished executing a resumed function and it was not awaited again.
3997
3998
// Signal the next function-state to resume.
3999
const Variant *args[1] = { &retvalue };
4000
p_state->completed.emit(args, 1);
4001
4002
// Exit function only after executing the remaining function states to preserve async call stack.
4003
GDScriptLanguage::get_singleton()->exit_function();
4004
}
4005
4006
return retvalue;
4007
}
4008
4009