summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp226
-rw-r--r--modules/gdscript/gdscript_byte_codegen.h18
-rw-r--r--modules/gdscript/gdscript_disassembler.cpp125
-rw-r--r--modules/gdscript/gdscript_function.cpp20
-rw-r--r--modules/gdscript/gdscript_function.h60
-rw-r--r--modules/gdscript/gdscript_vm.cpp293
6 files changed, 361 insertions, 381 deletions
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index cc9e87b882..33e3909e90 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -111,7 +111,7 @@ void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName
}
GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
- append(GDScriptFunction::OPCODE_END);
+ append(GDScriptFunction::OPCODE_END, 0);
if (constant_map.size()) {
function->_constant_count = constant_map.size();
@@ -162,7 +162,7 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
function->stack_debug = stack_debug;
}
function->_stack_size = stack_max;
- function->_call_size = call_max;
+ function->_instruction_args_size = instr_args_max;
ended = true;
return function;
@@ -179,36 +179,36 @@ void GDScriptByteCodeGenerator::set_initial_line(int p_line) {
}
void GDScriptByteCodeGenerator::write_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) {
- append(GDScriptFunction::OPCODE_OPERATOR);
- append(p_operator);
+ append(GDScriptFunction::OPCODE_OPERATOR, 3);
append(p_left_operand);
append(p_right_operand);
append(p_target);
+ append(p_operator);
}
void GDScriptByteCodeGenerator::write_type_test(const Address &p_target, const Address &p_source, const Address &p_type) {
- append(GDScriptFunction::OPCODE_EXTENDS_TEST);
+ append(GDScriptFunction::OPCODE_EXTENDS_TEST, 3);
append(p_source);
append(p_type);
append(p_target);
}
void GDScriptByteCodeGenerator::write_type_test_builtin(const Address &p_target, const Address &p_source, Variant::Type p_type) {
- append(GDScriptFunction::OPCODE_IS_BUILTIN);
+ append(GDScriptFunction::OPCODE_IS_BUILTIN, 3);
append(p_source);
- append(p_type);
append(p_target);
+ append(p_type);
}
void GDScriptByteCodeGenerator::write_and_left_operand(const Address &p_left_operand) {
- append(GDScriptFunction::OPCODE_JUMP_IF_NOT);
+ append(GDScriptFunction::OPCODE_JUMP_IF_NOT, 1);
append(p_left_operand);
logic_op_jump_pos1.push_back(opcodes.size());
append(0); // Jump target, will be patched.
}
void GDScriptByteCodeGenerator::write_and_right_operand(const Address &p_right_operand) {
- append(GDScriptFunction::OPCODE_JUMP_IF_NOT);
+ append(GDScriptFunction::OPCODE_JUMP_IF_NOT, 1);
append(p_right_operand);
logic_op_jump_pos2.push_back(opcodes.size());
append(0); // Jump target, will be patched.
@@ -216,29 +216,29 @@ void GDScriptByteCodeGenerator::write_and_right_operand(const Address &p_right_o
void GDScriptByteCodeGenerator::write_end_and(const Address &p_target) {
// If here means both operands are true.
- append(GDScriptFunction::OPCODE_ASSIGN_TRUE);
+ append(GDScriptFunction::OPCODE_ASSIGN_TRUE, 1);
append(p_target);
// Jump away from the fail condition.
- append(GDScriptFunction::OPCODE_JUMP);
+ append(GDScriptFunction::OPCODE_JUMP, 0);
append(opcodes.size() + 3);
// Here it means one of operands is false.
patch_jump(logic_op_jump_pos1.back()->get());
patch_jump(logic_op_jump_pos2.back()->get());
logic_op_jump_pos1.pop_back();
logic_op_jump_pos2.pop_back();
- append(GDScriptFunction::OPCODE_ASSIGN_FALSE);
+ append(GDScriptFunction::OPCODE_ASSIGN_FALSE, 0);
append(p_target);
}
void GDScriptByteCodeGenerator::write_or_left_operand(const Address &p_left_operand) {
- append(GDScriptFunction::OPCODE_JUMP_IF);
+ append(GDScriptFunction::OPCODE_JUMP_IF, 1);
append(p_left_operand);
logic_op_jump_pos1.push_back(opcodes.size());
append(0); // Jump target, will be patched.
}
void GDScriptByteCodeGenerator::write_or_right_operand(const Address &p_right_operand) {
- append(GDScriptFunction::OPCODE_JUMP_IF);
+ append(GDScriptFunction::OPCODE_JUMP_IF, 1);
append(p_right_operand);
logic_op_jump_pos2.push_back(opcodes.size());
append(0); // Jump target, will be patched.
@@ -246,17 +246,17 @@ void GDScriptByteCodeGenerator::write_or_right_operand(const Address &p_right_op
void GDScriptByteCodeGenerator::write_end_or(const Address &p_target) {
// If here means both operands are false.
- append(GDScriptFunction::OPCODE_ASSIGN_FALSE);
+ append(GDScriptFunction::OPCODE_ASSIGN_FALSE, 1);
append(p_target);
// Jump away from the success condition.
- append(GDScriptFunction::OPCODE_JUMP);
+ append(GDScriptFunction::OPCODE_JUMP, 0);
append(opcodes.size() + 3);
// Here it means one of operands is false.
patch_jump(logic_op_jump_pos1.back()->get());
patch_jump(logic_op_jump_pos2.back()->get());
logic_op_jump_pos1.pop_back();
logic_op_jump_pos2.pop_back();
- append(GDScriptFunction::OPCODE_ASSIGN_TRUE);
+ append(GDScriptFunction::OPCODE_ASSIGN_TRUE, 1);
append(p_target);
}
@@ -265,18 +265,18 @@ void GDScriptByteCodeGenerator::write_start_ternary(const Address &p_target) {
}
void GDScriptByteCodeGenerator::write_ternary_condition(const Address &p_condition) {
- append(GDScriptFunction::OPCODE_JUMP_IF_NOT);
+ append(GDScriptFunction::OPCODE_JUMP_IF_NOT, 1);
append(p_condition);
ternary_jump_fail_pos.push_back(opcodes.size());
append(0); // Jump target, will be patched.
}
void GDScriptByteCodeGenerator::write_ternary_true_expr(const Address &p_expr) {
- append(GDScriptFunction::OPCODE_ASSIGN);
+ append(GDScriptFunction::OPCODE_ASSIGN, 2);
append(ternary_result.back()->get());
append(p_expr);
// Jump away from the false path.
- append(GDScriptFunction::OPCODE_JUMP);
+ append(GDScriptFunction::OPCODE_JUMP, 0);
ternary_jump_skip_pos.push_back(opcodes.size());
append(0);
// Fail must jump here.
@@ -285,7 +285,7 @@ void GDScriptByteCodeGenerator::write_ternary_true_expr(const Address &p_expr) {
}
void GDScriptByteCodeGenerator::write_ternary_false_expr(const Address &p_expr) {
- append(GDScriptFunction::OPCODE_ASSIGN);
+ append(GDScriptFunction::OPCODE_ASSIGN, 2);
append(ternary_result.back()->get());
append(p_expr);
}
@@ -296,43 +296,43 @@ void GDScriptByteCodeGenerator::write_end_ternary() {
}
void GDScriptByteCodeGenerator::write_set(const Address &p_target, const Address &p_index, const Address &p_source) {
- append(GDScriptFunction::OPCODE_SET);
+ append(GDScriptFunction::OPCODE_SET, 3);
append(p_target);
append(p_index);
append(p_source);
}
void GDScriptByteCodeGenerator::write_get(const Address &p_target, const Address &p_index, const Address &p_source) {
- append(GDScriptFunction::OPCODE_GET);
+ append(GDScriptFunction::OPCODE_GET, 3);
append(p_source);
append(p_index);
append(p_target);
}
void GDScriptByteCodeGenerator::write_set_named(const Address &p_target, const StringName &p_name, const Address &p_source) {
- append(GDScriptFunction::OPCODE_SET_NAMED);
+ append(GDScriptFunction::OPCODE_SET_NAMED, 2);
append(p_target);
- append(p_name);
append(p_source);
+ append(p_name);
}
void GDScriptByteCodeGenerator::write_get_named(const Address &p_target, const StringName &p_name, const Address &p_source) {
- append(GDScriptFunction::OPCODE_GET_NAMED);
+ append(GDScriptFunction::OPCODE_GET_NAMED, 2);
append(p_source);
- append(p_name);
append(p_target);
+ append(p_name);
}
void GDScriptByteCodeGenerator::write_set_member(const Address &p_value, const StringName &p_name) {
- append(GDScriptFunction::OPCODE_SET_MEMBER);
- append(p_name);
+ append(GDScriptFunction::OPCODE_SET_MEMBER, 1);
append(p_value);
+ append(p_name);
}
void GDScriptByteCodeGenerator::write_get_member(const Address &p_target, const StringName &p_name) {
- append(GDScriptFunction::OPCODE_GET_MEMBER);
- append(p_name);
+ append(GDScriptFunction::OPCODE_GET_MEMBER, 1);
append(p_target);
+ append(p_name);
}
void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Address &p_source) {
@@ -340,34 +340,35 @@ void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Addr
// Typed assignment.
switch (p_target.type.kind) {
case GDScriptDataType::BUILTIN: {
- append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN);
- append(p_target.type.builtin_type);
+ append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN, 2);
append(p_target);
append(p_source);
+ append(p_target.type.builtin_type);
} break;
case GDScriptDataType::NATIVE: {
int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_target.type.native_type];
class_idx |= (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS);
- append(GDScriptFunction::OPCODE_ASSIGN_TYPED_NATIVE);
- append(class_idx);
+ append(GDScriptFunction::OPCODE_ASSIGN_TYPED_NATIVE, 3);
append(p_target);
append(p_source);
+ append(class_idx);
} break;
case GDScriptDataType::SCRIPT:
case GDScriptDataType::GDSCRIPT: {
Variant script = p_target.type.script_type;
int idx = get_constant_pos(script);
+ idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS);
- append(GDScriptFunction::OPCODE_ASSIGN_TYPED_SCRIPT);
- append(idx);
+ append(GDScriptFunction::OPCODE_ASSIGN_TYPED_SCRIPT, 3);
append(p_target);
append(p_source);
+ append(idx);
} break;
default: {
ERR_PRINT("Compiler bug: unresolved assign.");
// Shouldn't get here, but fail-safe to a regular assignment
- append(GDScriptFunction::OPCODE_ASSIGN);
+ append(GDScriptFunction::OPCODE_ASSIGN, 2);
append(p_target);
append(p_source);
}
@@ -375,13 +376,13 @@ void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Addr
} else {
if (p_target.type.kind == GDScriptDataType::BUILTIN && p_source.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type != p_source.type.builtin_type) {
// Need conversion..
- append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN);
- append(p_target.type.builtin_type);
+ append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN, 2);
append(p_target);
append(p_source);
+ append(p_target.type.builtin_type);
} else {
// Either untyped assignment or already type-checked by the parser
- append(GDScriptFunction::OPCODE_ASSIGN);
+ append(GDScriptFunction::OPCODE_ASSIGN, 2);
append(p_target);
append(p_source);
}
@@ -389,34 +390,37 @@ void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Addr
}
void GDScriptByteCodeGenerator::write_assign_true(const Address &p_target) {
- append(GDScriptFunction::OPCODE_ASSIGN_TRUE);
+ append(GDScriptFunction::OPCODE_ASSIGN_TRUE, 1);
append(p_target);
}
void GDScriptByteCodeGenerator::write_assign_false(const Address &p_target) {
- append(GDScriptFunction::OPCODE_ASSIGN_FALSE);
+ append(GDScriptFunction::OPCODE_ASSIGN_FALSE, 1);
append(p_target);
}
void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) {
+ int index = 0;
+
switch (p_type.kind) {
case GDScriptDataType::BUILTIN: {
- append(GDScriptFunction::OPCODE_CAST_TO_BUILTIN);
- append(p_type.builtin_type);
+ append(GDScriptFunction::OPCODE_CAST_TO_BUILTIN, 2);
+ index = p_type.builtin_type;
} break;
case GDScriptDataType::NATIVE: {
int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_type.native_type];
class_idx |= (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS);
- append(GDScriptFunction::OPCODE_CAST_TO_NATIVE);
- append(class_idx);
+ append(GDScriptFunction::OPCODE_CAST_TO_NATIVE, 3);
+ index = class_idx;
} break;
case GDScriptDataType::SCRIPT:
case GDScriptDataType::GDSCRIPT: {
Variant script = p_type.script_type;
int idx = get_constant_pos(script);
+ idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS);
- append(GDScriptFunction::OPCODE_CAST_TO_SCRIPT);
- append(idx);
+ append(GDScriptFunction::OPCODE_CAST_TO_SCRIPT, 3);
+ index = idx;
} break;
default: {
return;
@@ -425,147 +429,139 @@ void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Addres
append(p_source);
append(p_target);
+ append(index);
}
void GDScriptByteCodeGenerator::write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) {
- append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN);
- append(p_arguments.size());
- append(p_base);
- append(p_function_name);
+ append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size());
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
+ append(p_base);
append(p_target);
- alloc_call(p_arguments.size());
+ append(p_arguments.size());
+ append(p_function_name);
}
void GDScriptByteCodeGenerator::write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) {
- append(GDScriptFunction::OPCODE_CALL_SELF_BASE);
- append(p_function_name);
- append(p_arguments.size());
+ append(GDScriptFunction::OPCODE_CALL_SELF_BASE, 1 + p_arguments.size());
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
append(p_target);
- alloc_call(p_arguments.size());
+ append(p_arguments.size());
+ append(p_function_name);
}
void GDScriptByteCodeGenerator::write_call_async(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) {
- append(GDScriptFunction::OPCODE_CALL_ASYNC);
- append(p_arguments.size());
- append(p_base);
- append(p_function_name);
+ append(GDScriptFunction::OPCODE_CALL_ASYNC, 2 + p_arguments.size());
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
+ append(p_base);
append(p_target);
- alloc_call(p_arguments.size());
+ append(p_arguments.size());
+ append(p_function_name);
}
void GDScriptByteCodeGenerator::write_call_builtin(const Address &p_target, GDScriptFunctions::Function p_function, const Vector<Address> &p_arguments) {
- append(GDScriptFunction::OPCODE_CALL_BUILT_IN);
- append(p_function);
- append(p_arguments.size());
+ append(GDScriptFunction::OPCODE_CALL_BUILT_IN, 1 + p_arguments.size());
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
append(p_target);
- alloc_call(p_arguments.size());
+ append(p_arguments.size());
+ append(p_function);
}
void GDScriptByteCodeGenerator::write_call_method_bind(const Address &p_target, const Address &p_base, const MethodBind *p_method, const Vector<Address> &p_arguments) {
- append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN);
- append(p_arguments.size());
- append(p_base);
- append(p_method->get_name());
+ append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size());
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
+ append(p_base);
append(p_target);
- alloc_call(p_arguments.size());
+ append(p_arguments.size());
+ append(p_method->get_name());
}
void GDScriptByteCodeGenerator::write_call_ptrcall(const Address &p_target, const Address &p_base, const MethodBind *p_method, const Vector<Address> &p_arguments) {
- append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN);
- append(p_arguments.size());
- append(p_base);
- append(p_method->get_name());
+ append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size());
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
+ append(p_base);
append(p_target);
- alloc_call(p_arguments.size());
+ append(p_arguments.size());
+ append(p_method->get_name());
}
void GDScriptByteCodeGenerator::write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) {
- append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN);
- append(p_arguments.size());
- append(GDScriptFunction::ADDR_TYPE_SELF << GDScriptFunction::ADDR_BITS);
- append(p_function_name);
+ append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size());
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
+ append(GDScriptFunction::ADDR_TYPE_SELF << GDScriptFunction::ADDR_BITS);
append(p_target);
- alloc_call(p_arguments.size());
+ append(p_arguments.size());
+ append(p_function_name);
}
void GDScriptByteCodeGenerator::write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) {
- append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN);
- append(p_arguments.size());
- append(p_base);
- append(p_function_name);
+ append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size());
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
+ append(p_base);
append(p_target);
- alloc_call(p_arguments.size());
+ append(p_arguments.size());
+ append(p_function_name);
}
void GDScriptByteCodeGenerator::write_construct(const Address &p_target, Variant::Type p_type, const Vector<Address> &p_arguments) {
- append(GDScriptFunction::OPCODE_CONSTRUCT);
- append(p_type);
- append(p_arguments.size());
+ append(GDScriptFunction::OPCODE_CONSTRUCT, 1 + p_arguments.size());
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
append(p_target);
- alloc_call(p_arguments.size());
+ append(p_arguments.size());
+ append(p_type);
}
void GDScriptByteCodeGenerator::write_construct_array(const Address &p_target, const Vector<Address> &p_arguments) {
- append(GDScriptFunction::OPCODE_CONSTRUCT_ARRAY);
- append(p_arguments.size());
+ append(GDScriptFunction::OPCODE_CONSTRUCT_ARRAY, 1 + p_arguments.size());
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
append(p_target);
+ append(p_arguments.size());
}
void GDScriptByteCodeGenerator::write_construct_dictionary(const Address &p_target, const Vector<Address> &p_arguments) {
- append(GDScriptFunction::OPCODE_CONSTRUCT_DICTIONARY);
- append(p_arguments.size() / 2); // This is number of key-value pairs, so only half of actual arguments.
+ append(GDScriptFunction::OPCODE_CONSTRUCT_DICTIONARY, 1 + p_arguments.size());
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
append(p_target);
+ append(p_arguments.size() / 2); // This is number of key-value pairs, so only half of actual arguments.
}
void GDScriptByteCodeGenerator::write_await(const Address &p_target, const Address &p_operand) {
- append(GDScriptFunction::OPCODE_AWAIT);
+ append(GDScriptFunction::OPCODE_AWAIT, 1);
append(p_operand);
- append(GDScriptFunction::OPCODE_AWAIT_RESUME);
+ append(GDScriptFunction::OPCODE_AWAIT_RESUME, 1);
append(p_target);
}
void GDScriptByteCodeGenerator::write_if(const Address &p_condition) {
- append(GDScriptFunction::OPCODE_JUMP_IF_NOT);
+ append(GDScriptFunction::OPCODE_JUMP_IF_NOT, 1);
append(p_condition);
if_jmp_addrs.push_back(opcodes.size());
append(0); // Jump destination, will be patched.
}
void GDScriptByteCodeGenerator::write_else() {
- append(GDScriptFunction::OPCODE_JUMP); // Jump from true if block;
+ append(GDScriptFunction::OPCODE_JUMP, 0); // Jump from true if block;
int else_jmp_addr = opcodes.size();
append(0); // Jump destination, will be patched.
@@ -586,34 +582,34 @@ void GDScriptByteCodeGenerator::write_for(const Address &p_variable, const Addre
current_breaks_to_patch.push_back(List<int>());
// Assign container.
- append(GDScriptFunction::OPCODE_ASSIGN);
+ append(GDScriptFunction::OPCODE_ASSIGN, 2);
append(container_pos);
append(p_list);
// Begin loop.
- append(GDScriptFunction::OPCODE_ITERATE_BEGIN);
+ append(GDScriptFunction::OPCODE_ITERATE_BEGIN, 3);
append(counter_pos);
append(container_pos);
+ append(p_variable);
for_jmp_addrs.push_back(opcodes.size());
append(0); // End of loop address, will be patched.
- append(p_variable);
- append(GDScriptFunction::OPCODE_JUMP);
+ append(GDScriptFunction::OPCODE_JUMP, 0);
append(opcodes.size() + 6); // Skip over 'continue' code.
// Next iteration.
int continue_addr = opcodes.size();
continue_addrs.push_back(continue_addr);
- append(GDScriptFunction::OPCODE_ITERATE);
+ append(GDScriptFunction::OPCODE_ITERATE, 3);
append(counter_pos);
append(container_pos);
+ append(p_variable);
for_jmp_addrs.push_back(opcodes.size());
append(0); // Jump destination, will be patched.
- append(p_variable);
}
void GDScriptByteCodeGenerator::write_endfor() {
// Jump back to loop check.
- append(GDScriptFunction::OPCODE_JUMP);
+ append(GDScriptFunction::OPCODE_JUMP, 0);
append(continue_addrs.back()->get());
continue_addrs.pop_back();
@@ -641,7 +637,7 @@ void GDScriptByteCodeGenerator::start_while_condition() {
void GDScriptByteCodeGenerator::write_while(const Address &p_condition) {
// Condition check.
- append(GDScriptFunction::OPCODE_JUMP_IF_NOT);
+ append(GDScriptFunction::OPCODE_JUMP_IF_NOT, 1);
append(p_condition);
while_jmp_addrs.push_back(opcodes.size());
append(0); // End of loop address, will be patched.
@@ -649,7 +645,7 @@ void GDScriptByteCodeGenerator::write_while(const Address &p_condition) {
void GDScriptByteCodeGenerator::write_endwhile() {
// Jump back to loop check.
- append(GDScriptFunction::OPCODE_JUMP);
+ append(GDScriptFunction::OPCODE_JUMP, 0);
append(continue_addrs.back()->get());
continue_addrs.pop_back();
@@ -687,39 +683,39 @@ void GDScriptByteCodeGenerator::end_match() {
}
void GDScriptByteCodeGenerator::write_break() {
- append(GDScriptFunction::OPCODE_JUMP);
+ append(GDScriptFunction::OPCODE_JUMP, 0);
current_breaks_to_patch.back()->get().push_back(opcodes.size());
append(0);
}
void GDScriptByteCodeGenerator::write_continue() {
- append(GDScriptFunction::OPCODE_JUMP);
+ append(GDScriptFunction::OPCODE_JUMP, 0);
append(continue_addrs.back()->get());
}
void GDScriptByteCodeGenerator::write_continue_match() {
- append(GDScriptFunction::OPCODE_JUMP);
+ append(GDScriptFunction::OPCODE_JUMP, 0);
match_continues_to_patch.back()->get().push_back(opcodes.size());
append(0);
}
void GDScriptByteCodeGenerator::write_breakpoint() {
- append(GDScriptFunction::OPCODE_BREAKPOINT);
+ append(GDScriptFunction::OPCODE_BREAKPOINT, 0);
}
void GDScriptByteCodeGenerator::write_newline(int p_line) {
- append(GDScriptFunction::OPCODE_LINE);
+ append(GDScriptFunction::OPCODE_LINE, 0);
append(p_line);
current_line = p_line;
}
void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
- append(GDScriptFunction::OPCODE_RETURN);
+ append(GDScriptFunction::OPCODE_RETURN, 1);
append(p_return_value);
}
void GDScriptByteCodeGenerator::write_assert(const Address &p_test, const Address &p_message) {
- append(GDScriptFunction::OPCODE_ASSERT);
+ append(GDScriptFunction::OPCODE_ASSERT, 2);
append(p_test);
append(p_message);
}
diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h
index 62438b6dd2..e8d7de21c2 100644
--- a/modules/gdscript/gdscript_byte_codegen.h
+++ b/modules/gdscript/gdscript_byte_codegen.h
@@ -33,6 +33,8 @@
#include "gdscript_codegen.h"
+#include "gdscript_function.h"
+
class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
bool ended = false;
GDScriptFunction *function = nullptr;
@@ -57,7 +59,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
#endif
int current_line = 0;
int stack_max = 0;
- int call_max = 0;
+ int instr_args_max = 0;
List<int> if_jmp_addrs; // List since this can be nested.
List<int> for_jmp_addrs;
@@ -139,11 +141,6 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
stack_max = p_level + 1;
}
- void alloc_call(int p_params) {
- if (p_params >= call_max)
- call_max = p_params;
- }
-
int increase_stack() {
int top = current_stack_size++;
alloc_stack(current_stack_size);
@@ -177,8 +174,13 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
return -1; // Unreachable.
}
- void append(int code) {
- opcodes.push_back(code);
+ void append(GDScriptFunction::Opcode p_code, int p_argument_count) {
+ opcodes.push_back((p_code & GDScriptFunction::INSTR_MASK) | (p_argument_count << GDScriptFunction::INSTR_BITS));
+ instr_args_max = MAX(instr_args_max, p_argument_count);
+ }
+
+ void append(int p_code) {
+ opcodes.push_back(p_code);
}
void append(const Address &p_address) {
diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp
index 4c3f5d3e75..d5de126d2e 100644
--- a/modules/gdscript/gdscript_disassembler.cpp
+++ b/modules/gdscript/gdscript_disassembler.cpp
@@ -117,21 +117,22 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
text += ": ";
// This makes the compiler complain if some opcode is unchecked in the switch.
- Opcode code = Opcode(_code_ptr[ip]);
+ Opcode code = Opcode(_code_ptr[ip] & INSTR_MASK);
+ int instr_var_args = (_code_ptr[ip] & INSTR_ARGS_MASK) >> INSTR_BITS;
switch (code) {
case OPCODE_OPERATOR: {
- int operation = _code_ptr[ip + 1];
+ int operation = _code_ptr[ip + 4];
text += "operator ";
- text += DADDR(4);
+ text += DADDR(3);
text += " = ";
- text += DADDR(2);
+ text += DADDR(1);
text += " ";
text += Variant::get_operator_name(Variant::Operator(operation));
text += " ";
- text += DADDR(3);
+ text += DADDR(2);
incr += 5;
} break;
@@ -147,11 +148,11 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
} break;
case OPCODE_IS_BUILTIN: {
text += "is builtin ";
- text += DADDR(3);
+ text += DADDR(2);
text += " = ";
text += DADDR(1);
text += " is ";
- text += Variant::get_type_name(Variant::Type(_code_ptr[ip + 2]));
+ text += Variant::get_type_name(Variant::Type(_code_ptr[ip + 3]));
incr += 4;
} break;
@@ -180,19 +181,19 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
text += "set_named ";
text += DADDR(1);
text += "[\"";
- text += _global_names_ptr[_code_ptr[ip + 2]];
+ text += _global_names_ptr[_code_ptr[ip + 3]];
text += "\"] = ";
- text += DADDR(3);
+ text += DADDR(2);
incr += 4;
} break;
case OPCODE_GET_NAMED: {
text += "get_named ";
- text += DADDR(3);
+ text += DADDR(2);
text += " = ";
text += DADDR(1);
text += "[\"";
- text += _global_names_ptr[_code_ptr[ip + 2]];
+ text += _global_names_ptr[_code_ptr[ip + 3]];
text += "\"]";
incr += 4;
@@ -200,18 +201,18 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
case OPCODE_SET_MEMBER: {
text += "set_member ";
text += "[\"";
- text += _global_names_ptr[_code_ptr[ip + 1]];
+ text += _global_names_ptr[_code_ptr[ip + 2]];
text += "\"] = ";
- text += DADDR(2);
+ text += DADDR(1);
incr += 3;
} break;
case OPCODE_GET_MEMBER: {
text += "get_member ";
- text += DADDR(2);
+ text += DADDR(1);
text += " = ";
text += "[\"";
- text += _global_names_ptr[_code_ptr[ip + 1]];
+ text += _global_names_ptr[_code_ptr[ip + 2]];
text += "\"]";
incr += 3;
@@ -240,45 +241,45 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
} break;
case OPCODE_ASSIGN_TYPED_BUILTIN: {
text += "assign typed builtin (";
- text += Variant::get_type_name((Variant::Type)_code_ptr[ip + 1]);
+ text += Variant::get_type_name((Variant::Type)_code_ptr[ip + 3]);
text += ") ";
- text += DADDR(2);
+ text += DADDR(1);
text += " = ";
- text += DADDR(3);
+ text += DADDR(2);
incr += 4;
} break;
case OPCODE_ASSIGN_TYPED_NATIVE: {
- Variant class_name = _constants_ptr[_code_ptr[ip + 1]];
+ Variant class_name = _constants_ptr[_code_ptr[ip + 3]];
GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(class_name.operator Object *());
text += "assign typed native (";
text += nc->get_name().operator String();
text += ") ";
- text += DADDR(2);
+ text += DADDR(1);
text += " = ";
- text += DADDR(3);
+ text += DADDR(2);
incr += 4;
} break;
case OPCODE_ASSIGN_TYPED_SCRIPT: {
- Variant script = _constants_ptr[_code_ptr[ip + 1]];
+ Variant script = _constants_ptr[_code_ptr[ip + 3]];
Script *sc = Object::cast_to<Script>(script.operator Object *());
text += "assign typed script (";
text += sc->get_path();
text += ") ";
- text += DADDR(2);
+ text += DADDR(1);
text += " = ";
- text += DADDR(3);
+ text += DADDR(2);
incr += 4;
} break;
case OPCODE_CAST_TO_BUILTIN: {
text += "cast builtin ";
- text += DADDR(3);
- text += " = ";
text += DADDR(2);
+ text += " = ";
+ text += DADDR(1);
text += " as ";
text += Variant::get_type_name(Variant::Type(_code_ptr[ip + 1]));
@@ -289,9 +290,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(class_name.operator Object *());
text += "cast native ";
- text += DADDR(3);
- text += " = ";
text += DADDR(2);
+ text += " = ";
+ text += DADDR(1);
text += " as ";
text += nc->get_name();
@@ -299,42 +300,42 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
} break;
case OPCODE_CAST_TO_SCRIPT: {
text += "cast ";
- text += DADDR(3);
- text += " = ";
text += DADDR(2);
- text += " as ";
+ text += " = ";
text += DADDR(1);
+ text += " as ";
+ text += DADDR(3);
incr += 4;
} break;
case OPCODE_CONSTRUCT: {
- Variant::Type t = Variant::Type(_code_ptr[ip + 1]);
- int argc = _code_ptr[ip + 2];
+ Variant::Type t = Variant::Type(_code_ptr[ip + 3 + instr_var_args]);
+ int argc = _code_ptr[ip + 2 + instr_var_args];
text += "construct ";
- text += DADDR(3 + argc);
+ text += DADDR(1 + argc);
text += " = ";
text += Variant::get_type_name(t) + "(";
for (int i = 0; i < argc; i++) {
if (i > 0)
text += ", ";
- text += DADDR(i + 3);
+ text += DADDR(i + 1);
}
text += ")";
- incr = 4 + argc;
+ incr = 3 + instr_var_args;
} break;
case OPCODE_CONSTRUCT_ARRAY: {
- int argc = _code_ptr[ip + 1];
+ int argc = _code_ptr[ip + 1 + instr_var_args];
text += " make_array ";
- text += DADDR(2 + argc);
+ text += DADDR(1 + argc);
text += " = [";
for (int i = 0; i < argc; i++) {
if (i > 0)
text += ", ";
- text += DADDR(2 + i);
+ text += DADDR(1 + i);
}
text += "]";
@@ -342,17 +343,17 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
incr += 3 + argc;
} break;
case OPCODE_CONSTRUCT_DICTIONARY: {
- int argc = _code_ptr[ip + 1];
+ int argc = _code_ptr[ip + 1 + instr_var_args];
text += "make_dict ";
- text += DADDR(2 + argc * 2);
+ text += DADDR(1 + argc * 2);
text += " = {";
for (int i = 0; i < argc; i++) {
if (i > 0)
text += ", ";
- text += DADDR(2 + i * 2 + 0);
+ text += DADDR(1 + i * 2 + 0);
text += ": ";
- text += DADDR(2 + i * 2 + 1);
+ text += DADDR(1 + i * 2 + 1);
}
text += "}";
@@ -362,8 +363,8 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
case OPCODE_CALL:
case OPCODE_CALL_RETURN:
case OPCODE_CALL_ASYNC: {
- bool ret = _code_ptr[ip] == OPCODE_CALL_RETURN;
- bool async = _code_ptr[ip] == OPCODE_CALL_ASYNC;
+ bool ret = (_code_ptr[ip] & INSTR_MASK) == OPCODE_CALL_RETURN;
+ bool async = (_code_ptr[ip] & INSTR_MASK) == OPCODE_CALL_ASYNC;
if (ret) {
text += "call-ret ";
@@ -373,19 +374,19 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
text += "call ";
}
- int argc = _code_ptr[ip + 1];
+ int argc = _code_ptr[ip + 1 + instr_var_args];
if (ret || async) {
- text += DADDR(4 + argc) + " = ";
+ text += DADDR(2 + argc) + " = ";
}
- text += DADDR(2) + ".";
- text += String(_global_names_ptr[_code_ptr[ip + 3]]);
+ text += DADDR(1 + argc) + ".";
+ text += String(_global_names_ptr[_code_ptr[ip + 2 + instr_var_args]]);
text += "(";
for (int i = 0; i < argc; i++) {
if (i > 0)
text += ", ";
- text += DADDR(4 + i);
+ text += DADDR(1 + i);
}
text += ")";
@@ -394,16 +395,16 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
case OPCODE_CALL_BUILT_IN: {
text += "call-built-in ";
- int argc = _code_ptr[ip + 2];
- text += DADDR(3 + argc) + " = ";
+ int argc = _code_ptr[ip + 1 + instr_var_args];
+ text += DADDR(1 + argc) + " = ";
- text += GDScriptFunctions::get_func_name(GDScriptFunctions::Function(_code_ptr[ip + 1]));
+ text += GDScriptFunctions::get_func_name(GDScriptFunctions::Function(_code_ptr[ip + 2 + instr_var_args]));
text += "(";
for (int i = 0; i < argc; i++) {
if (i > 0)
text += ", ";
- text += DADDR(3 + i);
+ text += DADDR(1 + i);
}
text += ")";
@@ -412,16 +413,16 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
case OPCODE_CALL_SELF_BASE: {
text += "call-self-base ";
- int argc = _code_ptr[ip + 2];
- text += DADDR(3 + argc) + " = ";
+ int argc = _code_ptr[ip + 1 + instr_var_args];
+ text += DADDR(2 + argc) + " = ";
- text += _global_names_ptr[_code_ptr[ip + 1]];
+ text += _global_names_ptr[_code_ptr[ip + 2 + instr_var_args]];
text += "(";
for (int i = 0; i < argc; i++) {
if (i > 0)
text += ", ";
- text += DADDR(3 + i);
+ text += DADDR(1 + i);
}
text += ")";
@@ -474,25 +475,25 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
} break;
case OPCODE_ITERATE_BEGIN: {
text += "for-init ";
- text += DADDR(4);
+ text += DADDR(3);
text += " in ";
text += DADDR(2);
text += " counter ";
text += DADDR(1);
text += " end ";
- text += itos(_code_ptr[ip + 3]);
+ text += itos(_code_ptr[ip + 4]);
incr += 5;
} break;
case OPCODE_ITERATE: {
text += "for-loop ";
- text += DADDR(4);
+ text += DADDR(2);
text += " in ";
text += DADDR(2);
text += " counter ";
text += DADDR(1);
text += " end ";
- text += itos(_code_ptr[ip + 3]);
+ text += itos(_code_ptr[ip + 4]);
incr += 5;
} break;
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 397c1f0bf8..32372439c5 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -139,31 +139,13 @@ void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<String
}
}
-GDScriptFunction::GDScriptFunction() :
- function_list(this) {
- _stack_size = 0;
- _call_size = 0;
- rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
+GDScriptFunction::GDScriptFunction() {
name = "<anonymous>";
#ifdef DEBUG_ENABLED
- _func_cname = nullptr;
-
{
MutexLock lock(GDScriptLanguage::get_singleton()->lock);
-
GDScriptLanguage::get_singleton()->function_list.add(&function_list);
}
-
- profile.call_count = 0;
- profile.self_time = 0;
- profile.total_time = 0;
- profile.frame_call_count = 0;
- profile.frame_self_time = 0;
- profile.frame_total_time = 0;
- profile.last_frame_call_count = 0;
- profile.last_frame_self_time = 0;
- profile.last_frame_total_time = 0;
-
#endif
}
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index 50eadcaf86..ca9dda9b80 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -215,6 +215,12 @@ public:
ADDR_TYPE_NIL = 9
};
+ enum Instruction {
+ INSTR_BITS = 20,
+ INSTR_MASK = ((1 << INSTR_BITS) - 1),
+ INSTR_ARGS_MASK = ~INSTR_MASK,
+ };
+
struct StackDebug {
int line;
int pos;
@@ -229,22 +235,22 @@ private:
StringName source;
mutable Variant nil;
- mutable Variant *_constants_ptr;
- int _constant_count;
- const StringName *_global_names_ptr;
- int _global_names_count;
- const int *_default_arg_ptr;
- int _default_arg_count;
- const int *_code_ptr;
- int _code_size;
- int _argument_count;
- int _stack_size;
- int _call_size;
- int _initial_line;
- bool _static;
- MultiplayerAPI::RPCMode rpc_mode;
-
- GDScript *_script;
+ mutable Variant *_constants_ptr = nullptr;
+ int _constant_count = 0;
+ const StringName *_global_names_ptr = nullptr;
+ int _global_names_count = 0;
+ const int *_default_arg_ptr = nullptr;
+ int _default_arg_count = 0;
+ const int *_code_ptr = nullptr;
+ int _code_size = 0;
+ int _argument_count = 0;
+ int _stack_size = 0;
+ int _instruction_args_size = 0;
+ int _initial_line = 0;
+ bool _static = false;
+ MultiplayerAPI::RPCMode rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
+
+ GDScript *_script = nullptr;
StringName name;
Vector<Variant> constants;
@@ -265,22 +271,22 @@ private:
friend class GDScriptLanguage;
- SelfList<GDScriptFunction> function_list;
+ SelfList<GDScriptFunction> function_list{ this };
#ifdef DEBUG_ENABLED
CharString func_cname;
- const char *_func_cname;
+ const char *_func_cname = nullptr;
struct Profile {
StringName signature;
- uint64_t call_count;
- uint64_t self_time;
- uint64_t total_time;
- uint64_t frame_call_count;
- uint64_t frame_self_time;
- uint64_t frame_total_time;
- uint64_t last_frame_call_count;
- uint64_t last_frame_self_time;
- uint64_t last_frame_total_time;
+ uint64_t call_count = 0;
+ uint64_t self_time = 0;
+ uint64_t total_time = 0;
+ uint64_t frame_call_count = 0;
+ uint64_t frame_self_time = 0;
+ uint64_t frame_total_time = 0;
+ uint64_t last_frame_call_count = 0;
+ uint64_t last_frame_self_time = 0;
+ uint64_t last_frame_total_time = 0;
} profile;
#endif
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index 65bea37b94..a10f2a9274 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -231,13 +231,14 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
#define OPCODE(m_op) \
m_op:
-#define OPCODE_WHILE(m_test)
+#define OPCODE_WHILE(m_test) \
+ OPSWHILE:
#define OPCODES_END \
OPSEXIT:
#define OPCODES_OUT \
OPSOUT:
-#define DISPATCH_OPCODE goto *switch_table_ops[_code_ptr[ip]]
-#define OPCODE_SWITCH(m_test) DISPATCH_OPCODE;
+#define DISPATCH_OPCODE goto OPSWHILE
+#define OPCODE_SWITCH(m_test) goto *switch_table_ops[m_test];
#define OPCODE_BREAK goto OPSEXIT
#define OPCODE_OUT goto OPSOUT
#else
@@ -265,7 +266,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
Variant static_ref;
Variant retvalue;
Variant *stack = nullptr;
- Variant **call_args;
+ Variant **instruction_args;
int defarg = 0;
#ifdef DEBUG_ENABLED
@@ -282,7 +283,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
if (p_state) {
//use existing (supplied) state (awaited)
stack = (Variant *)p_state->stack.ptr();
- call_args = (Variant **)&p_state->stack.ptr()[sizeof(Variant) * p_state->stack_size]; //ptr() to avoid bounds check
+ instruction_args = (Variant **)&p_state->stack.ptr()[sizeof(Variant) * p_state->stack_size]; //ptr() to avoid bounds check
line = p_state->line;
ip = p_state->ip;
alloca_size = p_state->stack.size();
@@ -307,7 +308,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
}
- alloca_size = sizeof(Variant *) * _call_size + sizeof(Variant) * _stack_size;
+ alloca_size = sizeof(Variant *) * _instruction_args_size + sizeof(Variant) * _stack_size;
if (alloca_size) {
uint8_t *aptr = (uint8_t *)alloca(alloca_size);
@@ -341,15 +342,15 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
stack = nullptr;
}
- if (_call_size) {
- call_args = (Variant **)&aptr[sizeof(Variant) * _stack_size];
+ if (_instruction_args_size) {
+ instruction_args = (Variant **)&aptr[sizeof(Variant) * _stack_size];
} else {
- call_args = nullptr;
+ instruction_args = nullptr;
}
} else {
stack = nullptr;
- call_args = nullptr;
+ instruction_args = nullptr;
}
if (p_instance) {
@@ -400,6 +401,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif
+#define GET_INSTRUCTION_ARG(m_v, m_idx) \
+ Variant *m_v = instruction_args[m_idx]
+
#ifdef DEBUG_ENABLED
uint64_t function_start_time = 0;
@@ -421,18 +425,24 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#else
OPCODE_WHILE(true) {
#endif
+ // Load arguments for the instruction before each instruction.
+ int instr_arg_count = ((_code_ptr[ip]) & INSTR_ARGS_MASK) >> INSTR_BITS;
+ for (int i = 0; i < instr_arg_count; i++) {
+ GET_VARIANT_PTR(v, i + 1);
+ instruction_args[i] = v;
+ }
- OPCODE_SWITCH(_code_ptr[ip]) {
+ OPCODE_SWITCH(_code_ptr[ip] & INSTR_MASK) {
OPCODE(OPCODE_OPERATOR) {
CHECK_SPACE(5);
bool valid;
- Variant::Operator op = (Variant::Operator)_code_ptr[ip + 1];
+ Variant::Operator op = (Variant::Operator)_code_ptr[ip + 4];
GD_ERR_BREAK(op >= Variant::OP_MAX);
- GET_VARIANT_PTR(a, 2);
- GET_VARIANT_PTR(b, 3);
- GET_VARIANT_PTR(dst, 4);
+ GET_INSTRUCTION_ARG(a, 0);
+ GET_INSTRUCTION_ARG(b, 1);
+ GET_INSTRUCTION_ARG(dst, 2);
#ifdef DEBUG_ENABLED
@@ -461,9 +471,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_EXTENDS_TEST) {
CHECK_SPACE(4);
- GET_VARIANT_PTR(a, 1);
- GET_VARIANT_PTR(b, 2);
- GET_VARIANT_PTR(dst, 3);
+ GET_INSTRUCTION_ARG(a, 0);
+ GET_INSTRUCTION_ARG(b, 1);
+ GET_INSTRUCTION_ARG(dst, 2);
#ifdef DEBUG_ENABLED
if (b->get_type() != Variant::OBJECT || b->operator Object *() == nullptr) {
@@ -536,9 +546,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_IS_BUILTIN) {
CHECK_SPACE(4);
- GET_VARIANT_PTR(value, 1);
- Variant::Type var_type = (Variant::Type)_code_ptr[ip + 2];
- GET_VARIANT_PTR(dst, 3);
+ GET_INSTRUCTION_ARG(value, 0);
+ GET_INSTRUCTION_ARG(dst, 1);
+ Variant::Type var_type = (Variant::Type)_code_ptr[ip + 3];
GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX);
@@ -550,9 +560,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_SET) {
CHECK_SPACE(3);
- GET_VARIANT_PTR(dst, 1);
- GET_VARIANT_PTR(index, 2);
- GET_VARIANT_PTR(value, 3);
+ GET_INSTRUCTION_ARG(dst, 0);
+ GET_INSTRUCTION_ARG(index, 1);
+ GET_INSTRUCTION_ARG(value, 2);
bool valid;
dst->set(*index, *value, &valid);
@@ -576,9 +586,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_GET) {
CHECK_SPACE(3);
- GET_VARIANT_PTR(src, 1);
- GET_VARIANT_PTR(index, 2);
- GET_VARIANT_PTR(dst, 3);
+ GET_INSTRUCTION_ARG(src, 0);
+ GET_INSTRUCTION_ARG(index, 1);
+ GET_INSTRUCTION_ARG(dst, 2);
bool valid;
#ifdef DEBUG_ENABLED
@@ -608,10 +618,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_SET_NAMED) {
CHECK_SPACE(3);
- GET_VARIANT_PTR(dst, 1);
- GET_VARIANT_PTR(value, 3);
+ GET_INSTRUCTION_ARG(dst, 0);
+ GET_INSTRUCTION_ARG(value, 1);
- int indexname = _code_ptr[ip + 2];
+ int indexname = _code_ptr[ip + 3];
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
const StringName *index = &_global_names_ptr[indexname];
@@ -633,10 +643,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_GET_NAMED) {
CHECK_SPACE(4);
- GET_VARIANT_PTR(src, 1);
- GET_VARIANT_PTR(dst, 3);
+ GET_INSTRUCTION_ARG(src, 0);
+ GET_INSTRUCTION_ARG(dst, 1);
- int indexname = _code_ptr[ip + 2];
+ int indexname = _code_ptr[ip + 3];
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
const StringName *index = &_global_names_ptr[indexname];
@@ -666,10 +676,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_SET_MEMBER) {
CHECK_SPACE(3);
- int indexname = _code_ptr[ip + 1];
+ GET_INSTRUCTION_ARG(src, 0);
+ int indexname = _code_ptr[ip + 2];
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
const StringName *index = &_global_names_ptr[indexname];
- GET_VARIANT_PTR(src, 2);
bool valid;
#ifndef DEBUG_ENABLED
@@ -690,11 +700,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_GET_MEMBER) {
CHECK_SPACE(3);
- int indexname = _code_ptr[ip + 1];
+ GET_INSTRUCTION_ARG(dst, 0);
+ int indexname = _code_ptr[ip + 2];
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
const StringName *index = &_global_names_ptr[indexname];
- GET_VARIANT_PTR(dst, 2);
-
#ifndef DEBUG_ENABLED
ClassDB::get_property(p_instance->owner, *index, *dst);
#else
@@ -710,8 +719,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_ASSIGN) {
CHECK_SPACE(3);
- GET_VARIANT_PTR(dst, 1);
- GET_VARIANT_PTR(src, 2);
+ GET_INSTRUCTION_ARG(dst, 0);
+ GET_INSTRUCTION_ARG(src, 1);
*dst = *src;
@@ -721,7 +730,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_ASSIGN_TRUE) {
CHECK_SPACE(2);
- GET_VARIANT_PTR(dst, 1);
+ GET_INSTRUCTION_ARG(dst, 0);
*dst = true;
@@ -731,7 +740,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_ASSIGN_FALSE) {
CHECK_SPACE(2);
- GET_VARIANT_PTR(dst, 1);
+ GET_INSTRUCTION_ARG(dst, 0);
*dst = false;
@@ -741,10 +750,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_ASSIGN_TYPED_BUILTIN) {
CHECK_SPACE(4);
- GET_VARIANT_PTR(dst, 2);
- GET_VARIANT_PTR(src, 3);
+ GET_INSTRUCTION_ARG(dst, 0);
+ GET_INSTRUCTION_ARG(src, 1);
- Variant::Type var_type = (Variant::Type)_code_ptr[ip + 1];
+ Variant::Type var_type = (Variant::Type)_code_ptr[ip + 3];
GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX);
if (src->get_type() != var_type) {
@@ -770,11 +779,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_ASSIGN_TYPED_NATIVE) {
CHECK_SPACE(4);
- GET_VARIANT_PTR(dst, 2);
- GET_VARIANT_PTR(src, 3);
+ GET_INSTRUCTION_ARG(dst, 0);
+ GET_INSTRUCTION_ARG(src, 1);
#ifdef DEBUG_ENABLED
- GET_VARIANT_PTR(type, 1);
+ GET_INSTRUCTION_ARG(type, 2);
GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(type->operator Object *());
GD_ERR_BREAK(!nc);
if (src->get_type() != Variant::OBJECT && src->get_type() != Variant::NIL) {
@@ -798,11 +807,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_ASSIGN_TYPED_SCRIPT) {
CHECK_SPACE(4);
- GET_VARIANT_PTR(dst, 2);
- GET_VARIANT_PTR(src, 3);
+ GET_INSTRUCTION_ARG(dst, 0);
+ GET_INSTRUCTION_ARG(src, 1);
#ifdef DEBUG_ENABLED
- GET_VARIANT_PTR(type, 1);
+ GET_INSTRUCTION_ARG(type, 2);
Script *base_type = Object::cast_to<Script>(type->operator Object *());
GD_ERR_BREAK(!base_type);
@@ -847,9 +856,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_CAST_TO_BUILTIN) {
CHECK_SPACE(4);
- Variant::Type to_type = (Variant::Type)_code_ptr[ip + 1];
- GET_VARIANT_PTR(src, 2);
- GET_VARIANT_PTR(dst, 3);
+ GET_INSTRUCTION_ARG(src, 0);
+ GET_INSTRUCTION_ARG(dst, 1);
+ Variant::Type to_type = (Variant::Type)_code_ptr[ip + 3];
GD_ERR_BREAK(to_type < 0 || to_type >= Variant::VARIANT_MAX);
@@ -869,9 +878,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_CAST_TO_NATIVE) {
CHECK_SPACE(4);
- GET_VARIANT_PTR(to_type, 1);
- GET_VARIANT_PTR(src, 2);
- GET_VARIANT_PTR(dst, 3);
+ GET_INSTRUCTION_ARG(src, 0);
+ GET_INSTRUCTION_ARG(dst, 1);
+ GET_INSTRUCTION_ARG(to_type, 2);
GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(to_type->operator Object *());
GD_ERR_BREAK(!nc);
@@ -896,9 +905,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_CAST_TO_SCRIPT) {
CHECK_SPACE(4);
- GET_VARIANT_PTR(to_type, 1);
- GET_VARIANT_PTR(src, 2);
- GET_VARIANT_PTR(dst, 3);
+ GET_INSTRUCTION_ARG(src, 0);
+ GET_INSTRUCTION_ARG(dst, 1);
+ GET_INSTRUCTION_ARG(to_type, 2);
Script *base_type = Object::cast_to<Script>(to_type->operator Object *());
@@ -940,17 +949,17 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_CONSTRUCT) {
- CHECK_SPACE(2);
- Variant::Type t = Variant::Type(_code_ptr[ip + 1]);
- int argc = _code_ptr[ip + 2];
- CHECK_SPACE(argc + 2);
- Variant **argptrs = call_args;
- for (int i = 0; i < argc; i++) {
- GET_VARIANT_PTR(v, 3 + i);
- argptrs[i] = v;
- }
+ CHECK_SPACE(2 + instr_arg_count);
+
+ ip += instr_arg_count;
+
+ int argc = _code_ptr[ip + 1];
+
+ Variant::Type t = Variant::Type(_code_ptr[ip + 2]);
+ Variant **argptrs = instruction_args;
+
+ GET_INSTRUCTION_ARG(dst, argc);
- GET_VARIANT_PTR(dst, 3 + argc);
Callable::CallError err;
Variant::construct(t, *dst, (const Variant **)argptrs, argc, err);
@@ -961,77 +970,72 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
#endif
- ip += 4 + argc;
- //construct a basic type
+ ip += 3;
}
DISPATCH_OPCODE;
OPCODE(OPCODE_CONSTRUCT_ARRAY) {
- CHECK_SPACE(1);
+ CHECK_SPACE(1 + instr_arg_count);
+ ip += instr_arg_count;
+
int argc = _code_ptr[ip + 1];
- Array array; //arrays are always shared
+ Array array;
array.resize(argc);
- CHECK_SPACE(argc + 2);
for (int i = 0; i < argc; i++) {
- GET_VARIANT_PTR(v, 2 + i);
- array[i] = *v;
+ array[i] = *(instruction_args[i]);
}
- GET_VARIANT_PTR(dst, 2 + argc);
+ GET_INSTRUCTION_ARG(dst, argc);
*dst = array;
- ip += 3 + argc;
+ ip += 2;
}
DISPATCH_OPCODE;
OPCODE(OPCODE_CONSTRUCT_DICTIONARY) {
- CHECK_SPACE(1);
- int argc = _code_ptr[ip + 1];
- Dictionary dict; //arrays are always shared
+ CHECK_SPACE(2 + instr_arg_count);
- CHECK_SPACE(argc * 2 + 2);
+ ip += instr_arg_count;
+
+ int argc = _code_ptr[ip + 1];
+ Dictionary dict;
for (int i = 0; i < argc; i++) {
- GET_VARIANT_PTR(k, 2 + i * 2 + 0);
- GET_VARIANT_PTR(v, 2 + i * 2 + 1);
+ GET_INSTRUCTION_ARG(k, i * 2 + 0);
+ GET_INSTRUCTION_ARG(v, i * 2 + 1);
dict[*k] = *v;
}
- GET_VARIANT_PTR(dst, 2 + argc * 2);
+ GET_INSTRUCTION_ARG(dst, argc * 2);
*dst = dict;
- ip += 3 + argc * 2;
+ ip += 2;
}
DISPATCH_OPCODE;
OPCODE(OPCODE_CALL_ASYNC)
OPCODE(OPCODE_CALL_RETURN)
OPCODE(OPCODE_CALL) {
- CHECK_SPACE(4);
- bool call_ret = _code_ptr[ip] != OPCODE_CALL;
+ CHECK_SPACE(3 + instr_arg_count);
+ bool call_ret = (_code_ptr[ip] & INSTR_MASK) != OPCODE_CALL;
#ifdef DEBUG_ENABLED
- bool call_async = _code_ptr[ip] == OPCODE_CALL_ASYNC;
+ bool call_async = (_code_ptr[ip] & INSTR_MASK) == OPCODE_CALL_ASYNC;
#endif
- int argc = _code_ptr[ip + 1];
- GET_VARIANT_PTR(base, 2);
- int nameg = _code_ptr[ip + 3];
-
- GD_ERR_BREAK(nameg < 0 || nameg >= _global_names_count);
- const StringName *methodname = &_global_names_ptr[nameg];
+ ip += instr_arg_count;
+ int argc = _code_ptr[ip + 1];
GD_ERR_BREAK(argc < 0);
- ip += 4;
- CHECK_SPACE(argc + 1);
- Variant **argptrs = call_args;
- for (int i = 0; i < argc; i++) {
- GET_VARIANT_PTR(v, i);
- argptrs[i] = v;
- }
+ int methodname_idx = _code_ptr[ip + 2];
+ GD_ERR_BREAK(methodname_idx < 0 || methodname_idx >= _global_names_count);
+ const StringName *methodname = &_global_names_ptr[methodname_idx];
+
+ GET_INSTRUCTION_ARG(base, argc);
+ Variant **argptrs = instruction_args;
#ifdef DEBUG_ENABLED
uint64_t call_time = 0;
@@ -1043,7 +1047,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif
Callable::CallError err;
if (call_ret) {
- GET_VARIANT_PTR(ret, argc);
+ GET_INSTRUCTION_ARG(ret, argc + 1);
base->call(*methodname, (const Variant **)argptrs, argc, *ret, err);
#ifdef DEBUG_ENABLED
if (!call_async && ret->get_type() == Variant::OBJECT) {
@@ -1104,31 +1108,24 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
#endif
- //_call_func(nullptr,base,*methodname,ip,argc,p_instance,stack);
- ip += argc + 1;
+ ip += 3;
}
DISPATCH_OPCODE;
OPCODE(OPCODE_CALL_BUILT_IN) {
- CHECK_SPACE(4);
+ CHECK_SPACE(3 + instr_arg_count);
- GDScriptFunctions::Function func = GDScriptFunctions::Function(_code_ptr[ip + 1]);
- int argc = _code_ptr[ip + 2];
- GD_ERR_BREAK(argc < 0);
+ ip += instr_arg_count;
- ip += 3;
- CHECK_SPACE(argc + 1);
- Variant **argptrs = call_args;
+ int argc = _code_ptr[ip + 1];
+ GD_ERR_BREAK(argc < 0);
- for (int i = 0; i < argc; i++) {
- GET_VARIANT_PTR(v, i);
- argptrs[i] = v;
- }
+ GDScriptFunctions::Function func = GDScriptFunctions::Function(_code_ptr[ip + 2]);
+ Variant **argptrs = instruction_args;
- GET_VARIANT_PTR(dst, argc);
+ GET_INSTRUCTION_ARG(dst, argc);
Callable::CallError err;
-
GDScriptFunctions::call(func, (const Variant **)argptrs, argc, *dst, err);
#ifdef DEBUG_ENABLED
@@ -1143,14 +1140,16 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_BREAK;
}
#endif
- ip += argc + 1;
+ ip += 3;
}
DISPATCH_OPCODE;
OPCODE(OPCODE_CALL_SELF_BASE) {
- CHECK_SPACE(2);
- int self_fun = _code_ptr[ip + 1];
+ CHECK_SPACE(3 + instr_arg_count);
+
+ ip += instr_arg_count;
+ int self_fun = _code_ptr[ip + 1];
#ifdef DEBUG_ENABLED
if (self_fun < 0 || self_fun >= _global_names_count) {
err_text = "compiler bug, function name not found";
@@ -1160,17 +1159,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
const StringName *methodname = &_global_names_ptr[self_fun];
int argc = _code_ptr[ip + 2];
+ GD_ERR_BREAK(argc < 0);
- CHECK_SPACE(2 + argc + 1);
-
- Variant **argptrs = call_args;
-
- for (int i = 0; i < argc; i++) {
- GET_VARIANT_PTR(v, i + 3);
- argptrs[i] = v;
- }
+ Variant **argptrs = instruction_args;
- GET_VARIANT_PTR(dst, argc + 3);
+ GET_INSTRUCTION_ARG(dst, argc);
const GDScript *gds = _script;
@@ -1213,15 +1206,15 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_BREAK;
}
- ip += 4 + argc;
+ ip += 3;
}
DISPATCH_OPCODE;
OPCODE(OPCODE_AWAIT) {
CHECK_SPACE(2);
- //do the oneshot connect
- GET_VARIANT_PTR(argobj, 1);
+ // Do the oneshot connect.
+ GET_INSTRUCTION_ARG(argobj, 0);
Signal sig;
bool is_signal = true;
@@ -1313,7 +1306,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_BREAK;
}
#endif
- GET_VARIANT_PTR(result, 1);
+ GET_INSTRUCTION_ARG(result, 0);
*result = p_state->result;
ip += 2;
}
@@ -1331,7 +1324,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_JUMP_IF) {
CHECK_SPACE(3);
- GET_VARIANT_PTR(test, 1);
+ GET_INSTRUCTION_ARG(test, 0);
bool result = test->booleanize();
@@ -1348,7 +1341,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_JUMP_IF_NOT) {
CHECK_SPACE(3);
- GET_VARIANT_PTR(test, 1);
+ GET_INSTRUCTION_ARG(test, 0);
bool result = test->booleanize();
@@ -1370,7 +1363,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_RETURN) {
CHECK_SPACE(2);
- GET_VARIANT_PTR(r, 1);
+ GET_INSTRUCTION_ARG(r, 0);
retvalue = *r;
#ifdef DEBUG_ENABLED
exit_ok = true;
@@ -1379,10 +1372,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
OPCODE(OPCODE_ITERATE_BEGIN) {
- CHECK_SPACE(8); //space for this a regular iterate
+ CHECK_SPACE(8); // Space for this and a regular iterate.
- GET_VARIANT_PTR(counter, 1);
- GET_VARIANT_PTR(container, 2);
+ GET_INSTRUCTION_ARG(counter, 0);
+ GET_INSTRUCTION_ARG(container, 1);
bool valid;
if (!container->iter_init(*counter, valid)) {
@@ -1392,11 +1385,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_BREAK;
}
#endif
- int jumpto = _code_ptr[ip + 3];
+ int jumpto = _code_ptr[ip + 4];
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
ip = jumpto;
} else {
- GET_VARIANT_PTR(iterator, 4);
+ GET_INSTRUCTION_ARG(iterator, 2);
*iterator = container->iter_get(*counter, valid);
#ifdef DEBUG_ENABLED
@@ -1405,7 +1398,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_BREAK;
}
#endif
- ip += 5; //skip regular iterate which is always next
+ ip += 5; // Skip regular iterate which is always next.
}
}
DISPATCH_OPCODE;
@@ -1413,8 +1406,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_ITERATE) {
CHECK_SPACE(4);
- GET_VARIANT_PTR(counter, 1);
- GET_VARIANT_PTR(container, 2);
+ GET_INSTRUCTION_ARG(counter, 0);
+ GET_INSTRUCTION_ARG(container, 1);
bool valid;
if (!container->iter_next(*counter, valid)) {
@@ -1424,11 +1417,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_BREAK;
}
#endif
- int jumpto = _code_ptr[ip + 3];
+ int jumpto = _code_ptr[ip + 4];
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
ip = jumpto;
} else {
- GET_VARIANT_PTR(iterator, 4);
+ GET_INSTRUCTION_ARG(iterator, 2);
*iterator = container->iter_get(*counter, valid);
#ifdef DEBUG_ENABLED
@@ -1446,13 +1439,13 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
CHECK_SPACE(3);
#ifdef DEBUG_ENABLED
- GET_VARIANT_PTR(test, 1);
+ GET_INSTRUCTION_ARG(test, 0);
bool result = test->booleanize();
if (!result) {
String message_str;
if (_code_ptr[ip + 2] != 0) {
- GET_VARIANT_PTR(message, 2);
+ GET_INSTRUCTION_ARG(message, 1);
message_str = *message;
}
if (message_str.empty()) {