diff options
Diffstat (limited to 'modules/gdscript')
| -rw-r--r-- | modules/gdscript/gd_compiler.cpp | 41 | ||||
| -rw-r--r-- | modules/gdscript/gd_editor.cpp | 58 | ||||
| -rw-r--r-- | modules/gdscript/gd_script.cpp | 436 | ||||
| -rw-r--r-- | modules/gdscript/gd_script.h | 51 |
4 files changed, 442 insertions, 144 deletions
diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp index d38f5f3e3..5a6299bcf 100644 --- a/modules/gdscript/gd_compiler.cpp +++ b/modules/gdscript/gd_compiler.cpp @@ -1290,8 +1290,8 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode * // gdfunc = &p_script->initializer; //} else { //regular func - p_script->member_functions[func_name]=GDFunction(); - gdfunc = &p_script->member_functions[func_name]; + p_script->member_functions[func_name]=memnew(GDFunction); + gdfunc = p_script->member_functions[func_name]; //} if (p_func) @@ -1358,6 +1358,32 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode * gdfunc->_stack_size=codegen.stack_max; gdfunc->_call_size=codegen.call_max; gdfunc->name=func_name; +#ifdef DEBUG_ENABLED + if (ScriptDebugger::get_singleton()){ + String signature; + //path + if (p_script->get_path()!=String()) + signature+=p_script->get_path(); + //loc + if (p_func) { + signature+="::"+itos(p_func->body->line); + } else { + signature+="::0"; + } + + //funciton and class + + if (p_class->name) { + signature+="::"+String(p_class->name)+"."+String(func_name);; + } else { + signature+="::"+String(func_name); + } + + + + gdfunc->profile.signature=signature; + } +#endif gdfunc->_script=p_script; gdfunc->source=source; @@ -1396,6 +1422,9 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars p_script->_base=NULL; p_script->members.clear(); p_script->constants.clear(); + for (Map<StringName,GDFunction*>::Element *E=p_script->member_functions.front();E;E=E->next()) { + memdelete(E->get()); + } p_script->member_functions.clear(); p_script->member_indices.clear(); p_script->member_info.clear(); @@ -1690,7 +1719,7 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars for(int i=0;i<p_class->variables.size();i++) { if (p_class->variables[i].setter) { - const Map<StringName,GDFunction>::Element *E=p_script->get_member_functions().find(p_class->variables[i].setter); + const Map<StringName,GDFunction*>::Element *E=p_script->get_member_functions().find(p_class->variables[i].setter); if (!E) { _set_error("Setter function '"+String(p_class->variables[i].setter)+"' not found in class.",NULL); err_line=p_class->variables[i].line; @@ -1698,7 +1727,7 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars return ERR_PARSE_ERROR; } - if (E->get().is_static()) { + if (E->get()->is_static()) { _set_error("Setter function '"+String(p_class->variables[i].setter)+"' is static.",NULL); err_line=p_class->variables[i].line; @@ -1708,7 +1737,7 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars } if (p_class->variables[i].getter) { - const Map<StringName,GDFunction>::Element *E=p_script->get_member_functions().find(p_class->variables[i].getter); + const Map<StringName,GDFunction*>::Element *E=p_script->get_member_functions().find(p_class->variables[i].getter); if (!E) { _set_error("Getter function '"+String(p_class->variables[i].getter)+"' not found in class.",NULL); err_line=p_class->variables[i].line; @@ -1716,7 +1745,7 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars return ERR_PARSE_ERROR; } - if (E->get().is_static()) { + if (E->get()->is_static()) { _set_error("Getter function '"+String(p_class->variables[i].getter)+"' is static.",NULL); err_line=p_class->variables[i].line; diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index ff19518ad..7e5ff620c 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -1310,9 +1310,9 @@ static void _find_identifiers_in_class(GDCompletionContext& context,bool p_stati } } - for (const Map<StringName,GDFunction>::Element *E=script->get_member_functions().front();E;E=E->next()) { - if (!p_static || E->get().is_static()) { - if (E->get().get_argument_count()) + for (const Map<StringName,GDFunction*>::Element *E=script->get_member_functions().front();E;E=E->next()) { + if (!p_static || E->get()->is_static()) { + if (E->get()->get_argument_count()) result.insert(E->key().operator String()+"("); else result.insert(E->key().operator String()+"()"); @@ -1536,10 +1536,10 @@ static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const St if (scr) { while (scr) { - for (const Map<StringName,GDFunction>::Element *E=scr->get_member_functions().front();E;E=E->next()) { - if (E->get().is_static() && p_method==E->get().get_name()) { + for (const Map<StringName,GDFunction*>::Element *E=scr->get_member_functions().front();E;E=E->next()) { + if (E->get()->is_static() && p_method==E->get()->get_name()) { arghint="static func "+String(p_method)+"("; - for(int i=0;i<E->get().get_argument_count();i++) { + for(int i=0;i<E->get()->get_argument_count();i++) { if (i>0) arghint+=", "; else @@ -1547,12 +1547,12 @@ static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const St if (i==p_argidx) { arghint+=String::chr(0xFFFF); } - arghint+="var "+E->get().get_argument_name(i); - int deffrom = E->get().get_argument_count()-E->get().get_default_argument_count(); + arghint+="var "+E->get()->get_argument_name(i); + int deffrom = E->get()->get_argument_count()-E->get()->get_default_argument_count(); if (i>=deffrom) { int defidx = deffrom-i; - if (defidx>=0 && defidx<E->get().get_default_argument_count()) { - arghint+="="+E->get().get_default_argument(defidx).get_construct_string(); + if (defidx>=0 && defidx<E->get()->get_default_argument_count()) { + arghint+="="+E->get()->get_default_argument(defidx).get_construct_string(); } } if (i==p_argidx) { @@ -1670,10 +1670,10 @@ static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const St if (code=="") { - for (const Map<StringName,GDFunction>::Element *E=scr->get_member_functions().front();E;E=E->next()) { - if (p_method==E->get().get_name()) { + for (const Map<StringName,GDFunction*>::Element *E=scr->get_member_functions().front();E;E=E->next()) { + if (p_method==E->get()->get_name()) { arghint="func "+String(p_method)+"("; - for(int i=0;i<E->get().get_argument_count();i++) { + for(int i=0;i<E->get()->get_argument_count();i++) { if (i>0) arghint+=", "; else @@ -1681,12 +1681,12 @@ static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const St if (i==p_argidx) { arghint+=String::chr(0xFFFF); } - arghint+="var "+E->get().get_argument_name(i); - int deffrom = E->get().get_argument_count()-E->get().get_default_argument_count(); + arghint+="var "+E->get()->get_argument_name(i); + int deffrom = E->get()->get_argument_count()-E->get()->get_default_argument_count(); if (i>=deffrom) { int defidx = deffrom-i; - if (defidx>=0 && defidx<E->get().get_default_argument_count()) { - arghint+="="+E->get().get_default_argument(defidx).get_construct_string(); + if (defidx>=0 && defidx<E->get()->get_default_argument_count()) { + arghint+="="+E->get()->get_default_argument(defidx).get_construct_string(); } } if (i==p_argidx) { @@ -1926,16 +1926,16 @@ static void _find_call_arguments(GDCompletionContext& context,const GDParser::No if (script.is_valid()) { - for (const Map<StringName,GDFunction>::Element *E=script->get_member_functions().front();E;E=E->next()) { + for (const Map<StringName,GDFunction*>::Element *E=script->get_member_functions().front();E;E=E->next()) { if (E->key()==id->name) { - if (context.function && context.function->_static && !E->get().is_static()) + if (context.function && context.function->_static && !E->get()->is_static()) continue; arghint = "func "+id->name.operator String()+String("("); - for(int i=0;i<E->get().get_argument_count();i++) { + for(int i=0;i<E->get()->get_argument_count();i++) { if (i>0) arghint+=", "; else @@ -1943,12 +1943,12 @@ static void _find_call_arguments(GDCompletionContext& context,const GDParser::No if (i==p_argidx) { arghint+=String::chr(0xFFFF); } - arghint+=E->get().get_argument_name(i); - int deffrom = E->get().get_argument_count()-E->get().get_default_argument_count(); + arghint+=E->get()->get_argument_name(i); + int deffrom = E->get()->get_argument_count()-E->get()->get_default_argument_count(); if (i>=deffrom) { int defidx = deffrom-i; - if (defidx>=0 && defidx<E->get().get_default_argument_count()) { - arghint+="="+E->get().get_default_argument(defidx).get_construct_string(); + if (defidx>=0 && defidx<E->get()->get_default_argument_count()) { + arghint+="="+E->get()->get_default_argument(defidx).get_construct_string(); } } if (i==p_argidx) { @@ -1956,7 +1956,7 @@ static void _find_call_arguments(GDCompletionContext& context,const GDParser::No } } - if (E->get().get_argument_count()>0) + if (E->get()->get_argument_count()>0) arghint+=" "; arghint+=")"; return; @@ -2178,8 +2178,8 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base options.insert(E->key()); } } - for (const Map<StringName,GDFunction>::Element *E=scr->get_member_functions().front();E;E=E->next()) { - if (E->get().is_static()) + for (const Map<StringName,GDFunction*>::Element *E=scr->get_member_functions().front();E;E=E->next()) { + if (E->get()->is_static()) options.insert(E->key()); } @@ -2266,8 +2266,8 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base options.insert(E->key()); } } - for (const Map<StringName,GDFunction>::Element *E=scr->get_member_functions().front();E;E=E->next()) { - if (E->get().get_argument_count()) + for (const Map<StringName,GDFunction*>::Element *E=scr->get_member_functions().front();E;E=E->next()) { + if (E->get()->get_argument_count()) options.insert(String(E->key())+"()"); else options.insert(String(E->key())+"("); diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp index beec314e4..cd5e35db3 100644 --- a/modules/gdscript/gd_script.cpp +++ b/modules/gdscript/gd_script.cpp @@ -32,7 +32,7 @@ #include "gd_compiler.h" #include "os/file_access.h" #include "io/file_access_encrypted.h" - +#include "os/os.h" @@ -199,6 +199,8 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a int ip=0; int line=_initial_line; + + if (p_state) { //use existing (supplied) state (yielded) stack=(Variant*)p_state->stack.ptr(); @@ -282,8 +284,8 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a #ifdef DEBUG_ENABLED - if (ScriptDebugger::get_singleton()) - GDScriptLanguage::get_singleton()->enter_function(p_instance,this,stack,&ip,&line); + if (ScriptDebugger::get_singleton()) + GDScriptLanguage::get_singleton()->enter_function(p_instance,this,stack,&ip,&line); #define CHECK_SPACE(m_space)\ ERR_BREAK((ip+m_space)>_code_size) @@ -292,7 +294,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a Variant *m_v; \ m_v = _get_variant(_code_ptr[ip+m_code_ofs],p_instance,_class,self,stack,err_text);\ if (!m_v)\ - break; + break; #else @@ -304,7 +306,18 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a #endif +#ifdef DEBUG_ENABLED + + uint64_t function_start_time; + uint64_t function_call_time; + if (GDScriptLanguage::get_singleton()->profiling) { + function_start_time=OS::get_singleton()->get_ticks_usec(); + function_call_time=0; + profile.call_count++; + profile.frame_call_count++; + } +#endif bool exit_ok=false; while(ip<_code_size) { @@ -461,7 +474,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a bool valid; #ifdef DEBUG_ENABLED -//allow better error message in cases where src and dst are the same stack position + //allow better error message in cases where src and dst are the same stack position Variant ret = src->get(*index,&valid); #else *dst = src->get(*index,&valid); @@ -520,7 +533,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a bool valid; #ifdef DEBUG_ENABLED -//allow better error message in cases where src and dst are the same stack position + //allow better error message in cases where src and dst are the same stack position Variant ret = src->get_named(*index,&valid); #else @@ -662,6 +675,14 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a argptrs[i]=v; } +#ifdef DEBUG_ENABLED + uint64_t call_time; + + if (GDScriptLanguage::get_singleton()->profiling) { + call_time=OS::get_singleton()->get_ticks_usec(); + } + +#endif Variant::CallError err; if (call_ret) { @@ -671,6 +692,11 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a base->call(*methodname,(const Variant**)argptrs,argc,err); } +#ifdef DEBUG_ENABLED + if (GDScriptLanguage::get_singleton()->profiling) { + function_call_time+=OS::get_singleton()->get_ticks_usec() - call_time; + } +#endif if (err.error!=Variant::CallError::CALL_OK) { @@ -774,7 +800,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a const GDScript *gds = _script; - const Map<StringName,GDFunction>::Element *E=NULL; + const Map<StringName,GDFunction*>::Element *E=NULL; while (gds->base.ptr()) { gds=gds->base.ptr(); E=gds->member_functions.find(*methodname); @@ -1082,7 +1108,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a ip+=2; if (ScriptDebugger::get_singleton()) { - // line + // line bool do_break=false; if (ScriptDebugger::get_singleton()->get_lines_left()>0) { @@ -1136,18 +1162,30 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a err_text="Internal Script Error! - opcode #"+itos(last_opcode)+" (report please)."; } - if (!GDScriptLanguage::get_singleton()->debug_break(err_text,false)) { - // debugger break did not happen + if (!GDScriptLanguage::get_singleton()->debug_break(err_text,false)) { + // debugger break did not happen - _err_print_error(err_func.utf8().get_data(),err_file.utf8().get_data(),err_line,err_text.utf8().get_data(),ERR_HANDLER_SCRIPT); - } + _err_print_error(err_func.utf8().get_data(),err_file.utf8().get_data(),err_line,err_text.utf8().get_data(),ERR_HANDLER_SCRIPT); + } break; } - if (ScriptDebugger::get_singleton()) - GDScriptLanguage::get_singleton()->exit_function(); +#ifdef DEBUG_ENABLED + if (GDScriptLanguage::get_singleton()->profiling) { + uint64_t time_taken = OS::get_singleton()->get_ticks_usec() - function_start_time; + profile.total_time+=time_taken; + profile.self_time+=time_taken-function_call_time; + profile.frame_total_time+=time_taken; + profile.frame_self_time+=time_taken-function_call_time; + GDScriptLanguage::get_singleton()->script_frame_time+=time_taken-function_call_time; + + } + +#endif + if (ScriptDebugger::get_singleton()) + GDScriptLanguage::get_singleton()->exit_function(); if (_stack_size) { @@ -1204,76 +1242,76 @@ int GDFunction::get_max_stack_size() const { struct _GDFKC { - int order; - List<int> pos; + int order; + List<int> pos; }; struct _GDFKCS { - int order; - StringName id; - int pos; + int order; + StringName id; + int pos; - bool operator<(const _GDFKCS &p_r) const { + bool operator<(const _GDFKCS &p_r) const { - return order<p_r.order; - } + return order<p_r.order; + } }; void GDFunction::debug_get_stack_member_state(int p_line,List<Pair<StringName,int> > *r_stackvars) const { - int oc=0; - Map<StringName,_GDFKC> sdmap; - for( const List<StackDebug>::Element *E=stack_debug.front();E;E=E->next()) { + int oc=0; + Map<StringName,_GDFKC> sdmap; + for( const List<StackDebug>::Element *E=stack_debug.front();E;E=E->next()) { - const StackDebug &sd=E->get(); - if (sd.line>p_line) - break; + const StackDebug &sd=E->get(); + if (sd.line>p_line) + break; - if (sd.added) { + if (sd.added) { - if (!sdmap.has(sd.identifier)) { - _GDFKC d; - d.order=oc++; - d.pos.push_back(sd.pos); - sdmap[sd.identifier]=d; + if (!sdmap.has(sd.identifier)) { + _GDFKC d; + d.order=oc++; + d.pos.push_back(sd.pos); + sdmap[sd.identifier]=d; - } else { - sdmap[sd.identifier].pos.push_back(sd.pos); - } - } else { + } else { + sdmap[sd.identifier].pos.push_back(sd.pos); + } + } else { - ERR_CONTINUE(!sdmap.has(sd.identifier)); + ERR_CONTINUE(!sdmap.has(sd.identifier)); - sdmap[sd.identifier].pos.pop_back(); - if (sdmap[sd.identifier].pos.empty()) - sdmap.erase(sd.identifier); - } + sdmap[sd.identifier].pos.pop_back(); + if (sdmap[sd.identifier].pos.empty()) + sdmap.erase(sd.identifier); + } - } + } - List<_GDFKCS> stackpositions; - for(Map<StringName,_GDFKC>::Element *E=sdmap.front();E;E=E->next() ) { + List<_GDFKCS> stackpositions; + for(Map<StringName,_GDFKC>::Element *E=sdmap.front();E;E=E->next() ) { - _GDFKCS spp; - spp.id=E->key(); - spp.order=E->get().order; - spp.pos=E->get().pos.back()->get(); - stackpositions.push_back(spp); - } + _GDFKCS spp; + spp.id=E->key(); + spp.order=E->get().order; + spp.pos=E->get().pos.back()->get(); + stackpositions.push_back(spp); + } - stackpositions.sort(); + stackpositions.sort(); - for(List<_GDFKCS>::Element *E=stackpositions.front();E;E=E->next()) { + for(List<_GDFKCS>::Element *E=stackpositions.front();E;E=E->next()) { - Pair<StringName,int> p; - p.first=E->get().id; - p.second=E->get().pos; - r_stackvars->push_back(p); - } + Pair<StringName,int> p; + p.first=E->get().id; + p.second=E->get().pos; + r_stackvars->push_back(p); + } } @@ -1294,15 +1332,47 @@ void GDFunction::clear() { } #endif -GDFunction::GDFunction() { +GDFunction::GDFunction() : function_list(this) { _stack_size=0; _call_size=0; name="<anonymous>"; #ifdef DEBUG_ENABLED _func_cname=NULL; + + if (GDScriptLanguage::get_singleton()->lock) { + GDScriptLanguage::get_singleton()->lock->lock(); + } + GDScriptLanguage::get_singleton()->function_list.add(&function_list); + + if (GDScriptLanguage::get_singleton()->lock) { + GDScriptLanguage::get_singleton()->lock->unlock(); + } + + 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 +} + +GDFunction::~GDFunction() { +#ifdef DEBUG_ENABLED + if (GDScriptLanguage::get_singleton()->lock) { + GDScriptLanguage::get_singleton()->lock->lock(); + } + GDScriptLanguage::get_singleton()->function_list.remove(&function_list); + if (GDScriptLanguage::get_singleton()->lock) { + GDScriptLanguage::get_singleton()->lock->unlock(); + } +#endif } ///////////////////// @@ -1935,14 +2005,14 @@ Variant GDScript::call(const StringName& p_method,const Variant** p_args,int p_a GDScript *top=this; while(top) { - Map<StringName,GDFunction>::Element *E=top->member_functions.find(p_method); + Map<StringName,GDFunction*>::Element *E=top->member_functions.find(p_method); if (E) { - if (!E->get().is_static()) { + if (!E->get()->is_static()) { WARN_PRINT(String("Can't call non-static function: '"+String(p_method)+"' in script.").utf8().get_data()); } - return E->get().call(NULL,p_args,p_argcount,r_error); + return E->get()->call(NULL,p_args,p_argcount,r_error); } top=top->_base; } @@ -2127,7 +2197,7 @@ Error GDScript::load_source_code(const String& p_path) { } -const Map<StringName,GDFunction>& GDScript::debug_get_member_functions() const { +const Map<StringName,GDFunction*>& GDScript::debug_get_member_functions() const { return member_functions; } @@ -2209,6 +2279,12 @@ GDScript::GDScript() { } +GDScript::~GDScript() { + for (Map<StringName,GDFunction*>::Element *E=member_functions.front();E;E=E->next()) { + memdelete( E->get() ); + } +} + @@ -2242,14 +2318,14 @@ bool GDInstance::set(const StringName& p_name, const Variant& p_value) { while(sptr) { - Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set); + Map<StringName,GDFunction*>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set); if (E) { Variant name=p_name; const Variant *args[2]={&name,&p_value}; Variant::CallError err; - Variant ret = E->get().call(this,(const Variant**)args,2,err); + Variant ret = E->get()->call(this,(const Variant**)args,2,err); if (err.error==Variant::CallError::CALL_OK && ret.get_type()==Variant::BOOL && ret.operator bool()) return true; } @@ -2292,14 +2368,14 @@ bool GDInstance::get(const StringName& p_name, Variant &r_ret) const { } { - const Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get); + const Map<StringName,GDFunction*>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get); if (E) { Variant name=p_name; const Variant *args[1]={&name}; Variant::CallError err; - Variant ret = const_cast<GDFunction*>(&E->get())->call(const_cast<GDInstance*>(this),(const Variant**)args,1,err); + Variant ret = const_cast<GDFunction*>(E->get())->call(const_cast<GDInstance*>(this),(const Variant**)args,1,err); if (err.error==Variant::CallError::CALL_OK && ret.get_type()!=Variant::NIL) { r_ret=ret; return true; @@ -2341,12 +2417,12 @@ void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const { while(sptr) { - const Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list); + const Map<StringName,GDFunction*>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list); if (E) { Variant::CallError err; - Variant ret = const_cast<GDFunction*>(&E->get())->call(const_cast<GDInstance*>(this),NULL,0,err); + Variant ret = const_cast<GDFunction*>(E->get())->call(const_cast<GDInstance*>(this),NULL,0,err); if (err.error==Variant::CallError::CALL_OK) { if (ret.get_type()!=Variant::ARRAY) { @@ -2403,7 +2479,7 @@ void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const { if (sptr->member_functions.has("_get_property_list")) { Variant::CallError err; - GDFunction *f = const_cast<GDFunction*>(&sptr->member_functions["_get_property_list"]); + GDFunction *f = const_cast<GDFunction*>(sptr->member_functions["_get_property_list"]); Variant plv = f->call(const_cast<GDInstance*>(this),NULL,0,err); if (plv.get_type()!=Variant::ARRAY) { @@ -2419,11 +2495,11 @@ void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const { PropertyInfo pinfo; if (!p.has("name")) { ERR_PRINT("_get_property_list: expected 'name' key of type string.") - continue; + continue; } if (!p.has("type")) { ERR_PRINT("_get_property_list: expected 'type' key of type integer.") - continue; + continue; } pinfo.name=p["name"]; pinfo.type=Variant::Type(int(p["type"])); @@ -2457,12 +2533,12 @@ void GDInstance::get_method_list(List<MethodInfo> *p_list) const { const GDScript *sptr=script.ptr(); while(sptr) { - for (Map<StringName,GDFunction>::Element *E = sptr->member_functions.front();E;E=E->next()) { + for (Map<StringName,GDFunction*>::Element *E = sptr->member_functions.front();E;E=E->next()) { MethodInfo mi; mi.name=E->key(); mi.flags|=METHOD_FLAG_FROM_SCRIPT; - for(int i=0;i<E->get().get_argument_count();i++) + for(int i=0;i<E->get()->get_argument_count();i++) mi.arguments.push_back(PropertyInfo(Variant::NIL,"arg"+itos(i))); p_list->push_back(mi); } @@ -2475,7 +2551,7 @@ bool GDInstance::has_method(const StringName& p_method) const { const GDScript *sptr=script.ptr(); while(sptr) { - const Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(p_method); + const Map<StringName,GDFunction*>::Element *E = sptr->member_functions.find(p_method); if (E) return true; sptr = sptr->_base; @@ -2489,9 +2565,9 @@ Variant GDInstance::call(const StringName& p_method,const Variant** p_args,int p GDScript *sptr=script.ptr(); while(sptr) { - Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(p_method); + Map<StringName,GDFunction*>::Element *E = sptr->member_functions.find(p_method); if (E) { - return E->get().call(this,p_args,p_argcount,r_error); + return E->get()->call(this,p_args,p_argcount,r_error); } sptr = sptr->_base; } @@ -2505,9 +2581,9 @@ void GDInstance::call_multilevel(const StringName& p_method,const Variant** p_ar Variant::CallError ce; while(sptr) { - Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(p_method); + Map<StringName,GDFunction*>::Element *E = sptr->member_functions.find(p_method); if (E) { - E->get().call(this,p_args,p_argcount,ce); + E->get()->call(this,p_args,p_argcount,ce); } sptr = sptr->_base; } @@ -2522,9 +2598,9 @@ void GDInstance::_ml_call_reversed(GDScript *sptr,const StringName& p_method,con Variant::CallError ce; - Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(p_method); + Map<StringName,GDFunction*>::Element *E = sptr->member_functions.find(p_method); if (E) { - E->get().call(this,p_args,p_argcount,ce); + E->get()->call(this,p_args,p_argcount,ce); } } @@ -2544,10 +2620,10 @@ void GDInstance::notification(int p_notification) { GDScript *sptr=script.ptr(); while(sptr) { - Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification); + Map<StringName,GDFunction*>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification); if (E) { Variant::CallError err; - E->get().call(this,args,1,err); + E->get()->call(this,args,1,err); if (err.error!=Variant::CallError::CALL_OK) { //print error about notification call @@ -2672,11 +2748,154 @@ void GDScriptLanguage::finish() { } +void GDScriptLanguage::profiling_start() { + +#ifdef DEBUG_ENABLED + if (lock) { + lock->lock(); + } + + SelfList<GDFunction> *elem=function_list.first(); + while(elem) { + elem->self()->profile.call_count=0; + elem->self()->profile.self_time=0; + elem->self()->profile.total_time=0; + elem->self()->profile.frame_call_count=0; + elem->self()->profile.frame_self_time=0; + elem->self()->profile.frame_total_time=0; + elem->self()->profile.last_frame_call_count=0; + elem->self()->profile.last_frame_self_time=0; + elem->self()->profile.last_frame_total_time=0; + elem=elem->next(); + } + + profiling=true; + if (lock) { + lock->unlock(); + } + +#endif + +} + +void GDScriptLanguage::profiling_stop() { + +#ifdef DEBUG_ENABLED + if (lock) { + lock->lock(); + } + + profiling=false; + if (lock) { + lock->unlock(); + } + +#endif +} + +int GDScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr,int p_info_max) { + + int current=0; +#ifdef DEBUG_ENABLED + if (lock) { + lock->lock(); + } + + + SelfList<GDFunction> *elem=function_list.first(); + while(elem) { + if (current>=p_info_max) + break; + p_info_arr[current].call_count=elem->self()->profile.call_count; + p_info_arr[current].self_time=elem->self()->profile.self_time; + p_info_arr[current].total_time=elem->self()->profile.total_time; + p_info_arr[current].signature=elem->self()->profile.signature; + elem=elem->next(); + current++; + } + + + + if (lock) { + lock->unlock(); + } + + +#endif + + return current; + + +} + +int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr,int p_info_max) { + + int current=0; + +#ifdef DEBUG_ENABLED + if (lock) { + lock->lock(); + } + + + SelfList<GDFunction> *elem=function_list.first(); + while(elem) { + if (current>=p_info_max) + break; + if (elem->self()->profile.last_frame_call_count>0) { + p_info_arr[current].call_count=elem->self()->profile.last_frame_call_count; + p_info_arr[current].self_time=elem->self()->profile.last_frame_self_time; + p_info_arr[current].total_time=elem->self()->profile.last_frame_total_time; + p_info_arr[current].signature=elem->self()->profile.signature; + //print_line(String(elem->self()->profile.signature)+": "+itos(elem->self()->profile.last_frame_call_count)); + current++; + } + elem=elem->next(); + + } + + + if (lock) { + lock->unlock(); + } + + +#endif + + return current; + +} + void GDScriptLanguage::frame() { -// print_line("calls: "+itos(calls)); + // print_line("calls: "+itos(calls)); calls=0; + +#ifdef DEBUG_ENABLED + if (profiling) { + if (lock) { + lock->lock(); + } + + SelfList<GDFunction> *elem=function_list.first(); + while(elem) { + elem->self()->profile.last_frame_call_count=elem->self()->profile.frame_call_count; + elem->self()->profile.last_frame_self_time=elem->self()->profile.frame_self_time; + elem->self()->profile.last_frame_total_time=elem->self()->profile.frame_total_time; + elem->self()->profile.frame_call_count=0; + elem->self()->profile.frame_self_time=0; + elem->self()->profile.frame_total_time=0; + elem=elem->next(); + } + + + if (lock) { + lock->unlock(); + } + } + +#endif } /* EDITOR FUNCTIONS */ @@ -2724,7 +2943,7 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const { "pass", "return", "while", - 0}; + 0}; const char **w=_reserved_words; @@ -2756,30 +2975,43 @@ GDScriptLanguage::GDScriptLanguage() { _debug_parse_err_line=-1; _debug_parse_err_file=""; - _debug_call_stack_pos=0; - int dmcs=GLOBAL_DEF("debug/script_max_call_stack",1024); - if (ScriptDebugger::get_singleton()) { - //debugging enabled! +#ifdef NO_THREADS + lock=NULL; +#else + lock = Mutex::create(); +#endif + profiling=false; + script_frame_time=0; + + _debug_call_stack_pos=0; + int dmcs=GLOBAL_DEF("debug/script_max_call_stack",1024); + if (ScriptDebugger::get_singleton()) { + //debugging enabled! - _debug_max_call_stack = dmcs; - if (_debug_max_call_stack<1024) - _debug_max_call_stack=1024; - _call_stack = memnew_arr( CallLevel, _debug_max_call_stack+1 ); + _debug_max_call_stack = dmcs; + if (_debug_max_call_stack<1024) + _debug_max_call_stack=1024; + _call_stack = memnew_arr( CallLevel, _debug_max_call_stack+1 ); - } else { - _debug_max_call_stack=0; - _call_stack=NULL; - } + } else { + _debug_max_call_stack=0; + _call_stack=NULL; + } } GDScriptLanguage::~GDScriptLanguage() { - if (_call_stack) { - memdelete_arr(_call_stack); - } - singleton=NULL; + + if (lock) { + memdelete(lock); + lock=NULL; + } + if (_call_stack) { + memdelete_arr(_call_stack); + } + singleton=NULL; } /*************** RESOURCE ***************/ diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h index 663fc985a..5f6cd012d 100644 --- a/modules/gdscript/gd_script.h +++ b/modules/gdscript/gd_script.h @@ -34,6 +34,8 @@ #include "io/resource_saver.h" #include "os/thread.h" #include "pair.h" +#include "self_list.h" + class GDInstance; class GDScript; @@ -125,10 +127,6 @@ friend class GDCompiler; Vector<StringName> global_names; Vector<int> default_arguments; Vector<int> code; -#ifdef DEBUG_ENABLED - CharString func_cname; - const char*_func_cname; -#endif #ifdef TOOLS_ENABLED Vector<StringName> arg_names; @@ -139,9 +137,32 @@ friend class GDCompiler; _FORCE_INLINE_ Variant *_get_variant(int p_address,GDInstance *p_instance,GDScript *p_script,Variant &self,Variant *p_stack,String& r_error) const; _FORCE_INLINE_ String _get_call_error(const Variant::CallError& p_err, const String& p_where,const Variant**argptrs) const; +friend class GDScriptLanguage; + + SelfList<GDFunction> function_list; +#ifdef DEBUG_ENABLED + CharString func_cname; + const char*_func_cname; + + 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; + } profile; + +#endif public: + + struct CallState { GDInstance *instance; @@ -190,6 +211,7 @@ public: Variant call(GDInstance *p_instance,const Variant **p_args, int p_argcount,Variant::CallError& r_err,CallState *p_state=NULL); GDFunction(); + ~GDFunction(); }; @@ -258,7 +280,7 @@ friend class GDScriptLanguage; Set<StringName> members; //members are just indices to the instanced script. Map<StringName,Variant> constants; - Map<StringName,GDFunction> member_functions; + Map<StringName,GDFunction*> member_functions; Map<StringName,MemberInfo> member_indices; //members are just indices to the instanced script. Map<StringName,Ref<GDScript> > subclasses; Map<StringName,Vector<StringName> > _signals; @@ -317,7 +339,7 @@ public: const Map<StringName,Ref<GDScript> >& get_subclasses() const { return subclasses; } const Map<StringName,Variant >& get_constants() const { return constants; } const Set<StringName>& get_members() const { return members; } - const Map<StringName,GDFunction>& get_member_functions() const { return member_functions; } + const Map<StringName,GDFunction*>& get_member_functions() const { return member_functions; } const Ref<GDNativeClass>& get_native() const { return native; } virtual bool has_script_signal(const StringName& p_signal) const; @@ -328,7 +350,7 @@ public: Ref<GDScript> get_base() const; const Map<StringName,MemberInfo>& debug_get_member_indices() const { return member_indices; } - const Map<StringName,GDFunction>& debug_get_member_functions() const; //this is debug only + const Map<StringName,GDFunction*>& debug_get_member_functions() const; //this is debug only StringName debug_get_member_by_index(int p_idx) const; Variant _new(const Variant** p_args,int p_argcount,Variant::CallError& r_error); @@ -357,6 +379,7 @@ public: virtual ScriptLanguage *get_language() const; GDScript(); + ~GDScript(); }; class GDInstance : public ScriptInstance { @@ -369,6 +392,7 @@ friend class GDFunctions; Vector<Variant> members; bool base_ref; + void _ml_call_reversed(GDScript *sptr,const StringName& p_method,const Variant** p_args,int p_argcount); public: @@ -431,8 +455,15 @@ class GDScriptLanguage : public ScriptLanguage { void _add_global(const StringName& p_name,const Variant& p_value); + Mutex *lock; +friend class GDFunction; + + SelfList<GDFunction>::List function_list; + bool profiling; + uint64_t script_frame_time; public: + int calls; bool debug_break(const String& p_error,bool p_allow_continue=true); @@ -552,6 +583,12 @@ public: virtual void get_public_functions(List<MethodInfo> *p_functions) const; virtual void get_public_constants(List<Pair<String,Variant> > *p_constants) const; + virtual void profiling_start(); + virtual void profiling_stop(); + + virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr,int p_info_max); + virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr,int p_info_max); + /* LOADER FUNCTIONS */ virtual void get_recognized_extensions(List<String> *p_extensions) const; |
