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();