/*************************************************************************/ /* gdscript_vm.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "gdscript_function.h" #include "core/core_string_names.h" #include "core/os/os.h" #include "gdscript.h" Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_instance, GDScript *p_script, Variant &self, Variant &static_ref, Variant *p_stack, String &r_error) const { int address = p_address & ADDR_MASK; //sequential table (jump table generated by compiler) switch ((p_address & ADDR_TYPE_MASK) >> ADDR_BITS) { case ADDR_TYPE_SELF: { #ifdef DEBUG_ENABLED if (unlikely(!p_instance)) { r_error = "Cannot access self without instance."; return nullptr; } #endif return &self; } break; case ADDR_TYPE_CLASS: { return &static_ref; } break; case ADDR_TYPE_MEMBER: { #ifdef DEBUG_ENABLED if (unlikely(!p_instance)) { r_error = "Cannot access member without instance."; return nullptr; } #endif //member indexing is O(1) return &p_instance->members.write[address]; } break; case ADDR_TYPE_CLASS_CONSTANT: { //todo change to index! GDScript *s = p_script; #ifdef DEBUG_ENABLED ERR_FAIL_INDEX_V(address, _global_names_count, nullptr); #endif const StringName *sn = &_global_names_ptr[address]; while (s) { GDScript *o = s; while (o) { Map::Element *E = o->constants.find(*sn); if (E) { return &E->get(); } o = o->_owner; } s = s->_base; } ERR_FAIL_V_MSG(nullptr, "GDScriptCompiler bug."); } break; case ADDR_TYPE_LOCAL_CONSTANT: { #ifdef DEBUG_ENABLED ERR_FAIL_INDEX_V(address, _constant_count, nullptr); #endif return &_constants_ptr[address]; } break; case ADDR_TYPE_STACK: case ADDR_TYPE_STACK_VARIABLE: { #ifdef DEBUG_ENABLED ERR_FAIL_INDEX_V(address, _stack_size, nullptr); #endif return &p_stack[address]; } break; case ADDR_TYPE_GLOBAL: { #ifdef DEBUG_ENABLED ERR_FAIL_INDEX_V(address, GDScriptLanguage::get_singleton()->get_global_array_size(), nullptr); #endif return &GDScriptLanguage::get_singleton()->get_global_array()[address]; } break; #ifdef TOOLS_ENABLED case ADDR_TYPE_NAMED_GLOBAL: { #ifdef DEBUG_ENABLED ERR_FAIL_INDEX_V(address, _global_names_count, nullptr); #endif StringName id = _global_names_ptr[address]; if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(id)) { return (Variant *)&GDScriptLanguage::get_singleton()->get_named_globals_map()[id]; } else { r_error = "Autoload singleton '" + String(id) + "' has been removed."; return nullptr; } } break; #endif case ADDR_TYPE_NIL: { return &nil; } break; } ERR_FAIL_V_MSG(nullptr, "Bad code! (unknown addressing mode)."); return nullptr; } #ifdef DEBUG_ENABLED static String _get_script_name(const Ref