Mercurial > repos > tabletprog
comparison cbackend.js @ 96:84b65ee8b78b
Optimize self method calls into static function calls
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 26 Jul 2012 18:54:42 -0700 |
parents | 926b65fe92b4 |
children | 59a94f3ad56f |
comparison
equal
deleted
inserted
replaced
95:926b65fe92b4 | 96:84b65ee8b78b |
---|---|
235 for (var i = start; i < args.length; i++) { | 235 for (var i = start; i < args.length; i++) { |
236 args[i] = ', ' + (!i && method ? '(object *)(' : '') + args[i].toC() + (!i && method ? ')' : ''); | 236 args[i] = ', ' + (!i && method ? '(object *)(' : '') + args[i].toC() + (!i && method ? ')' : ''); |
237 } | 237 } |
238 var callpart; | 238 var callpart; |
239 if (method) { | 239 if (method) { |
240 callpart = 'mcall(' + getMethodId(name) + '/* ' + name + ' */'; | 240 if (funinfo && funinfo.type == 'self' && funinfo.def.name) { |
241 callpart = funinfo.def.name + '(' + (funinfo.def.symbols.parent.needsenv ? (new symbol('self', this.symbols)).toC() + '->env' : 'NULL' ); | |
242 } else { | |
243 callpart = 'mcall(' + getMethodId(name) + '/* ' + name + ' */'; | |
244 } | |
241 } else { | 245 } else { |
242 callpart = 'ccall(' + (new symbol(name, this.symbols)).toC(); | 246 callpart = 'ccall(' + (new symbol(name, this.symbols)).toC(); |
243 } | 247 } |
244 return callpart + ', ' + args.length + args.join('') + ')'; | 248 return callpart + ', ' + args.length + args.join('') + ')'; |
245 }; | 249 }; |
832 | 836 |
833 object.prototype.toCModuleInstance = function() { | 837 object.prototype.toCModuleInstance = function() { |
834 return this.toC(); | 838 return this.toC(); |
835 } | 839 } |
836 | 840 |
837 var lambdanum = 0; | |
838 | |
839 lambda.prototype.toC = function() { | 841 lambda.prototype.toC = function() { |
840 var args = this.args ? this.args.slice(0, this.args.length) : []; | 842 var args = this.args ? this.args.slice(0, this.args.length) : []; |
841 var exprs = this.expressions; | 843 var exprs = this.expressions; |
842 var mynum = lambdanum++; | 844 debugprint('//', this.name); |
843 debugprint('//lambda', mynum); | |
844 if (Object.keys(this.symbols.closedover).length) { | 845 if (Object.keys(this.symbols.closedover).length) { |
845 this.symbols.envtype = 'lambda_' + mynum + '_env'; | 846 this.symbols.envtype = this.name + '_env'; |
847 forwarddec += 'typedef struct ' + this.symbols.envtype + ' ' + this.symbols.envtype + ';\n' | |
846 } | 848 } |
847 if (this.selftype) { | 849 if (this.selftype) { |
848 this.symbols.defineVar('self', this.selftype); | 850 this.symbols.defineVar('self', this.selftype); |
849 if (args[0] && args[0].cleanName() == 'self') { | 851 if (args[0] && args[0].cleanName() == 'self') { |
850 args.splice(0, 1); | 852 args.splice(0, 1); |
869 if (exprs.length) { | 871 if (exprs.length) { |
870 exprs[exprs.length-1] = 'return (object *)(' + exprs[exprs.length-1] + ');'; | 872 exprs[exprs.length-1] = 'return (object *)(' + exprs[exprs.length-1] + ');'; |
871 } | 873 } |
872 | 874 |
873 if (Object.keys(this.symbols.closedover).length) { | 875 if (Object.keys(this.symbols.closedover).length) { |
874 forwarddec += 'typedef struct lambda_' + mynum + '_env {\n'; | 876 forwarddec += 'struct ' + this.name + '_env {\n'; |
875 if (this.symbols.needsParentEnv) { | 877 if (this.symbols.needsParentEnv) { |
876 forwarddec += '\tstruct ' + this.symbols.parentEnvType() + ' * parent;\n'; | 878 forwarddec += '\tstruct ' + this.symbols.parentEnvType() + ' * parent;\n'; |
877 } | 879 } |
878 for (var varname in this.symbols.closedover) { | 880 for (var varname in this.symbols.closedover) { |
879 if (varname == 'self' && this.selftype) { | 881 if (varname == 'self' && this.selftype) { |
880 forwarddec += '\tstruct ' + this.selftype + ' * self;\n'; | 882 forwarddec += '\tstruct ' + this.selftype + ' * self;\n'; |
881 } else { | 883 } else { |
882 forwarddec += '\tobject * ' + escapeCName(varname) + ';\n'; | 884 forwarddec += '\tobject * ' + escapeCName(varname) + ';\n'; |
883 } | 885 } |
884 } | 886 } |
885 forwarddec += '} lambda_' + mynum + '_env;\n' | 887 forwarddec += '};\n' |
886 | 888 |
887 var myenvinit = '\tlambda_' + mynum + '_env * myenv = GC_MALLOC(sizeof(lambda_' + mynum + '_env));\n'; | 889 var myenvinit = '\t' + this.name + '_env * myenv = GC_MALLOC(sizeof(' + this.name + '_env));\n'; |
888 if (this.symbols.needsParentEnv) { | 890 if (this.symbols.needsParentEnv) { |
889 myenvinit += '\tmyenv->parent = env;\n'; | 891 myenvinit += '\tmyenv->parent = env;\n'; |
890 } | 892 } |
891 this.symbols.envtype = 'lambda_' + mynum + '_env'; | 893 this.symbols.envtype = this.name + '_env'; |
892 } else { | 894 } else { |
893 var myenvinit = ''; | 895 var myenvinit = ''; |
894 } | 896 } |
897 forwarddec += 'object *' + this.name + ' (' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...);\n'; | |
895 | 898 |
896 toplevelcode += 'object * lambda_' + mynum + ' (' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...) {\n\tva_list args;\n' + myenvinit + '\tva_start(args, num_args);\n'; | 899 toplevelcode += 'object * ' + this.name + ' ( ' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...) {\n\tva_list args;\n' + myenvinit + '\tva_start(args, num_args);\n'; |
897 if (this.selftype) { | 900 if (this.selftype) { |
898 var selfvar = (new symbol('self', this.symbols)).toC(); | 901 var selfvar = (new symbol('self', this.symbols)).toC(); |
899 if (selfvar == 'self') { | 902 if (selfvar == 'self') { |
900 toplevelcode += '\t' + this.selftype + ' * self = va_arg(args, ' + this.selftype + ' *);\n'; | 903 toplevelcode += '\t' + this.selftype + ' * self = va_arg(args, ' + this.selftype + ' *);\n'; |
901 } else { | 904 } else { |
902 toplevelcode += '\t' + selfvar + ' = va_arg(args, ' + this.selftype + ' *);\n'; | 905 toplevelcode += '\t' + selfvar + ' = va_arg(args, ' + this.selftype + ' *);\n'; |
903 } | 906 } |
904 | 907 |
905 } | 908 } |
906 toplevelcode += args.join('') + '\tva_end(args);\n' + exprs.join(';\n\t') + '\n}\n'; | 909 toplevelcode += args.join('') + '\tva_end(args);\n' + exprs.join(';\n\t') + '\n}\n'; |
907 this.name = 'lambda_' + mynum; | |
908 | 910 |
909 if (this.selftype) { | 911 if (this.selftype) { |
910 return this.name; | 912 return this.name; |
911 } else { | 913 } else { |
912 if (this.symbols.parentEnvType() != 'void') { | 914 if (this.symbols.parentEnvType() != 'void') { |
913 if (this.symbols.parent.passthruenv) { | 915 if (this.symbols.parent.passthruenv) { |
914 var envvar = 'env'; | 916 var envvar = 'env'; |
915 } else { | 917 } else { |
916 var envvar = 'myenv'; | 918 var envvar = 'myenv'; |
917 } | 919 } |
918 debugprint('//lambda_' + mynum, 'has envvar:', envvar, 'num vars closed over:', Object.keys(this.symbols.closedover).length); | 920 debugprint('//' + this.name, 'has envvar:', envvar, 'num vars closed over:', Object.keys(this.symbols.closedover).length); |
919 return 'make_lambda(' + envvar + ', (closure_func)' + this.name + ')'; | 921 return 'make_lambda(' + envvar + ', (closure_func)' + this.name + ')'; |
920 } else { | 922 } else { |
921 toplevelcode += 'lambda lambda_obj_' + mynum + ' = {{&lambda_meta, NULL}, NULL, lambda_' + mynum + '};\n'; | 923 toplevelcode += 'lambda ' + this.name + '_obj = {{&lambda_meta, NULL}, NULL, lambda_' + mynum + '};\n'; |
922 return '((object *)&lambda_obj_' + mynum + ')'; | 924 return '((object *)&' + this.name + '_obj)'; |
923 } | 925 } |
924 } | 926 } |
925 }; | 927 }; |
926 lambda.prototype.toCModuleInstance = function() { | 928 lambda.prototype.toCModuleInstance = function() { |
927 this.toC(); | 929 this.toC(); |