# HG changeset patch # User Mike Pavone # Date 1343354082 25200 # Node ID 84b65ee8b78b0c6e8110638ff547f96b3dd95e3d # Parent 926b65fe92b48682f459a09833f76cc86e58cd54 Optimize self method calls into static function calls diff -r 926b65fe92b4 -r 84b65ee8b78b cbackend.js --- a/cbackend.js Tue Jul 24 19:13:38 2012 -0700 +++ b/cbackend.js Thu Jul 26 18:54:42 2012 -0700 @@ -237,7 +237,11 @@ } var callpart; if (method) { - callpart = 'mcall(' + getMethodId(name) + '/* ' + name + ' */'; + if (funinfo && funinfo.type == 'self' && funinfo.def.name) { + callpart = funinfo.def.name + '(' + (funinfo.def.symbols.parent.needsenv ? (new symbol('self', this.symbols)).toC() + '->env' : 'NULL' ); + } else { + callpart = 'mcall(' + getMethodId(name) + '/* ' + name + ' */'; + } } else { callpart = 'ccall(' + (new symbol(name, this.symbols)).toC(); } @@ -834,15 +838,13 @@ return this.toC(); } -var lambdanum = 0; - lambda.prototype.toC = function() { var args = this.args ? this.args.slice(0, this.args.length) : []; var exprs = this.expressions; - var mynum = lambdanum++; - debugprint('//lambda', mynum); + debugprint('//', this.name); if (Object.keys(this.symbols.closedover).length) { - this.symbols.envtype = 'lambda_' + mynum + '_env'; + this.symbols.envtype = this.name + '_env'; + forwarddec += 'typedef struct ' + this.symbols.envtype + ' ' + this.symbols.envtype + ';\n' } if (this.selftype) { this.symbols.defineVar('self', this.selftype); @@ -871,7 +873,7 @@ } if (Object.keys(this.symbols.closedover).length) { - forwarddec += 'typedef struct lambda_' + mynum + '_env {\n'; + forwarddec += 'struct ' + this.name + '_env {\n'; if (this.symbols.needsParentEnv) { forwarddec += '\tstruct ' + this.symbols.parentEnvType() + ' * parent;\n'; } @@ -882,18 +884,19 @@ forwarddec += '\tobject * ' + escapeCName(varname) + ';\n'; } } - forwarddec += '} lambda_' + mynum + '_env;\n' + forwarddec += '};\n' - var myenvinit = '\tlambda_' + mynum + '_env * myenv = GC_MALLOC(sizeof(lambda_' + mynum + '_env));\n'; + var myenvinit = '\t' + this.name + '_env * myenv = GC_MALLOC(sizeof(' + this.name + '_env));\n'; if (this.symbols.needsParentEnv) { myenvinit += '\tmyenv->parent = env;\n'; } - this.symbols.envtype = 'lambda_' + mynum + '_env'; + this.symbols.envtype = this.name + '_env'; } else { var myenvinit = ''; } + forwarddec += 'object *' + this.name + ' (' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...);\n'; - toplevelcode += 'object * lambda_' + mynum + ' (' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...) {\n\tva_list args;\n' + myenvinit + '\tva_start(args, num_args);\n'; + toplevelcode += 'object * ' + this.name + ' ( ' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...) {\n\tva_list args;\n' + myenvinit + '\tva_start(args, num_args);\n'; if (this.selftype) { var selfvar = (new symbol('self', this.symbols)).toC(); if (selfvar == 'self') { @@ -904,7 +907,6 @@ } toplevelcode += args.join('') + '\tva_end(args);\n' + exprs.join(';\n\t') + '\n}\n'; - this.name = 'lambda_' + mynum; if (this.selftype) { return this.name; @@ -915,11 +917,11 @@ } else { var envvar = 'myenv'; } - debugprint('//lambda_' + mynum, 'has envvar:', envvar, 'num vars closed over:', Object.keys(this.symbols.closedover).length); + debugprint('//' + this.name, 'has envvar:', envvar, 'num vars closed over:', Object.keys(this.symbols.closedover).length); return 'make_lambda(' + envvar + ', (closure_func)' + this.name + ')'; } else { - toplevelcode += 'lambda lambda_obj_' + mynum + ' = {{&lambda_meta, NULL}, NULL, lambda_' + mynum + '};\n'; - return '((object *)&lambda_obj_' + mynum + ')'; + toplevelcode += 'lambda ' + this.name + '_obj = {{&lambda_meta, NULL}, NULL, lambda_' + mynum + '};\n'; + return '((object *)&' + this.name + '_obj)'; } } }; diff -r 926b65fe92b4 -r 84b65ee8b78b compiler.js --- a/compiler.js Tue Jul 24 19:13:38 2012 -0700 +++ b/compiler.js Thu Jul 26 18:54:42 2012 -0700 @@ -329,6 +329,7 @@ } funcall.prototype.populateSymbols = function(symbols) { + var isll = false; if (this.name == 'foreign:') { if ((this.args[0] instanceof lambda) || (this.args[0] instanceof object) || (this.args[0] instanceof symbol)) { return; @@ -351,6 +352,7 @@ if (this.args[1] instanceof lambda) { if (this.args[2] instanceof lambda) { symbols.defineMsg(this.args[0].name, this.args[2]); + isll = true; } else { throw new Error("Third argument to llMessage:withVars:andCode: must be a lambda"); } @@ -368,10 +370,10 @@ symbols.find('self'); } for (var i in this.args) { - this.args[i].populateSymbols(symbols); + this.args[i].populateSymbols(symbols, undefined, isll); } if (this.receiver) { - this.receiver.populateSymbols(symbols); + this.receiver.populateSymbols(symbols, undefined, isll); } } @@ -386,8 +388,11 @@ } this.symbols = symbols; } - -lambda.prototype.populateSymbols = function(symbols, isobject) { +var lambdanum = 0; +lambda.prototype.populateSymbols = function(symbols, isobject, isll) { + if (!isll) { + this.name = 'lambda_' + lambdanum++; + } var args = this.args ? this.args.slice(0, this.args.length) : []; var exprs = this.expressions; var symbols = new lsymbols(symbols);