changeset 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
files cbackend.js compiler.js
diffstat 2 files changed, 26 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- 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)';
 		}
 	}
 };
--- 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);