mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 04:57:03 +00:00
Fixed: Optionally inline objj_msgSend function. Generate faster code for Array and Dictionary Literals.
This commit is contained in:
@@ -365,7 +365,8 @@ var MethodDef = function(name, types)
|
||||
this.types = types;
|
||||
}
|
||||
|
||||
var currentCompilerFlags = "";
|
||||
var currentCompilerFlags = 0;
|
||||
var currentGccCompilerFlags = "";
|
||||
|
||||
var reservedIdentifiers = exports.acorn.makePredicate("self _cmd undefined localStorage arguments");
|
||||
|
||||
@@ -414,14 +415,12 @@ var ObjJAcornCompiler = function(/*String*/ aString, /*CFURL*/ aURL, /*unsigned*
|
||||
}
|
||||
|
||||
this.dependencies = [];
|
||||
this.flags = flags | ObjJAcornCompiler.Flags.IncludeDebugSymbols;
|
||||
this.flags = flags & (ObjJAcornCompiler.Flags.IncludeDebugSymbols | ObjJAcornCompiler.Flags.InlineMsgSend | ObjJAcornCompiler.Flags.IncludeTypeSignatures);
|
||||
this.classDefs = classDefs ? classDefs : Object.create(null);
|
||||
this.protocolDefs = protocolDefs ? protocolDefs : Object.create(null);
|
||||
this.typeDefs = typeDefs ? typeDefs : Object.create(null);
|
||||
this.lastPos = 0;
|
||||
if (currentCompilerFlags & ObjJAcornCompiler.Flags.Generate)
|
||||
this.generate = true;
|
||||
this.generate = true;
|
||||
this.generate = true; // Before there was an option to generate the code or copy & paste it from the source. Today we always generate the code.
|
||||
|
||||
compile(this.tokens, new Scope(null ,{ compiler: this }), pass === 2 ? pass2 : pass1);
|
||||
}
|
||||
@@ -487,7 +486,42 @@ ObjJAcornCompiler.prototype.compilePass2 = function()
|
||||
return this.jsBuffer.toString();
|
||||
}
|
||||
|
||||
var currentCompilerFlags = "";
|
||||
exports.setCurrentGccCompilerFlags = function(/*String*/ compilerFlags)
|
||||
{
|
||||
if (currentGccCompilerFlags === compilerFlags) return;
|
||||
|
||||
currentGccCompilerFlags = compilerFlags;
|
||||
|
||||
var args = compilerFlags.split(" "),
|
||||
count = args.length,
|
||||
objjcFlags = 0;
|
||||
|
||||
for (var index = 0; index < count; ++index)
|
||||
{
|
||||
var argument = args[index];
|
||||
|
||||
if (argument.indexOf("-g") === 0)
|
||||
objjcFlags |= ObjectiveJ.ObjJAcornCompiler.Flags.IncludeDebugSymbols;
|
||||
|
||||
else if (argument.indexOf("-O") === 0) {
|
||||
objjcFlags |= ObjectiveJ.ObjJAcornCompiler.Flags.Compress;
|
||||
// FIXME: currently we are sending in '-O2' when we want InlineMsgSend. Here we only check if we it is '-O...'.
|
||||
// Maybe we should have some other option for this
|
||||
if (argument.length > 2)
|
||||
objjcFlags |= ObjectiveJ.ObjJAcornCompiler.Flags.InlineMsgSend;
|
||||
}
|
||||
|
||||
else if (argument.indexOf("-G") === 0)
|
||||
objjcFlags |= ObjectiveJ.ObjJAcornCompiler.Flags.Generate;
|
||||
}
|
||||
|
||||
currentCompilerFlags = objjcFlags;
|
||||
}
|
||||
|
||||
exports.currentGccCompilerFlags = function(/*String*/ compilerFlags)
|
||||
{
|
||||
return currentGccCompilerFlags;
|
||||
}
|
||||
|
||||
exports.setCurrentCompilerFlags = function(/*String*/ compilerFlags)
|
||||
{
|
||||
@@ -504,6 +538,7 @@ ObjJAcornCompiler.Flags = { };
|
||||
ObjJAcornCompiler.Flags.IncludeDebugSymbols = 1 << 0;
|
||||
ObjJAcornCompiler.Flags.IncludeTypeSignatures = 1 << 1;
|
||||
ObjJAcornCompiler.Flags.Generate = 1 << 2;
|
||||
ObjJAcornCompiler.Flags.InlineMsgSend = 1 << 3;
|
||||
|
||||
ObjJAcornCompiler.prototype.addWarning = function(/* Warning */ aWarning)
|
||||
{
|
||||
@@ -1626,64 +1661,170 @@ Literal: function(node, st, c) {
|
||||
},
|
||||
ArrayLiteral: function(node, st, c) {
|
||||
var compiler = st.compiler,
|
||||
generate = compiler.generate;
|
||||
generate = compiler.generate,
|
||||
buffer = compiler.jsBuffer;
|
||||
|
||||
if (!generate) {
|
||||
compiler.jsBuffer.concat(compiler.source.substring(compiler.lastPos, node.start));
|
||||
buffer.concat(compiler.source.substring(compiler.lastPos, node.start));
|
||||
compiler.lastPos = node.start;
|
||||
}
|
||||
|
||||
if (!generate) buffer.concat(" "); // Add an extra space if it looks something like this: "return(<expression>)". No space between return and expression.
|
||||
if (!st.receiverLevel) st.receiverLevel = 0;
|
||||
if (!node.elements.length) {
|
||||
compiler.jsBuffer.concat("objj_msgSend(objj_msgSend(CPArray, \"alloc\"), \"init\")");
|
||||
if (compiler.flags & ObjJAcornCompiler.Flags.InlineMsgSend) {
|
||||
buffer.concat("(___r");
|
||||
buffer.concat(++st.receiverLevel + "");
|
||||
buffer.concat(" = (CPArray.isa.method_msgSend[\"alloc\"] || _objj_forward)(CPArray, \"alloc\"), ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(" == null ? null : (___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(".isa.method_msgSend[\"init\"] || _objj_forward)(___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(", \"init\"))");
|
||||
} else {
|
||||
buffer.concat("(___r");
|
||||
buffer.concat(++st.receiverLevel + "");
|
||||
buffer.concat(" = CPArray.isa.objj_msgSend0(CPArray, \"alloc\"), ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(" == null ? null : ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(".isa.objj_msgSend0(___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(", \"init\"))");
|
||||
}
|
||||
|
||||
if (!(st.maxReceiverLevel >= st.receiverLevel))
|
||||
st.maxReceiverLevel = st.receiverLevel;
|
||||
} else {
|
||||
compiler.jsBuffer.concat("objj_msgSend(objj_msgSend(CPArray, \"alloc\"), \"initWithObjects:count:\", [");
|
||||
if (compiler.flags & ObjJAcornCompiler.Flags.InlineMsgSend) {
|
||||
buffer.concat("(___r");
|
||||
buffer.concat(++st.receiverLevel + "");
|
||||
buffer.concat(" = (CPArray.isa.method_msgSend[\"alloc\"] || _objj_forward)(CPArray, \"alloc\"), ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(" == null ? null : (___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(".isa.method_msgSend[\"initWithObjects:count:\"] || _objj_forward)(___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(", \"initWithObjects:count:\", [");
|
||||
} else {
|
||||
buffer.concat("(___r");
|
||||
buffer.concat(++st.receiverLevel + "");
|
||||
buffer.concat(" = CPArray.isa.objj_msgSend0(CPArray, \"alloc\"), ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(" == null ? null : ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(".isa.objj_msgSend2(___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(", \"initWithObjects:count:\", [");
|
||||
}
|
||||
|
||||
if (!(st.maxReceiverLevel >= st.receiverLevel))
|
||||
st.maxReceiverLevel = st.receiverLevel;
|
||||
|
||||
for (var i = 0; i < node.elements.length; i++) {
|
||||
var elt = node.elements[i];
|
||||
|
||||
if (i)
|
||||
compiler.jsBuffer.concat(", ");
|
||||
buffer.concat(", ");
|
||||
|
||||
if (!generate) compiler.lastPos = elt.start;
|
||||
c(elt, st, "Expression");
|
||||
if (!generate) compiler.jsBuffer.concat(compiler.source.substring(compiler.lastPos, elt.end));
|
||||
if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, elt.end));
|
||||
}
|
||||
compiler.jsBuffer.concat("], " + node.elements.length + ")");
|
||||
buffer.concat("], " + node.elements.length + "))");
|
||||
}
|
||||
|
||||
st.receiverLevel--;
|
||||
if (!generate) compiler.lastPos = node.end;
|
||||
},
|
||||
DictionaryLiteral: function(node, st, c) {
|
||||
var compiler = st.compiler,
|
||||
generate = compiler.generate;
|
||||
generate = compiler.generate,
|
||||
buffer = compiler.jsBuffer,
|
||||
noOfKeys = node.keys.length;
|
||||
|
||||
if (!generate) {
|
||||
compiler.jsBuffer.concat(compiler.source.substring(compiler.lastPos, node.start));
|
||||
buffer.concat(compiler.source.substring(compiler.lastPos, node.start));
|
||||
compiler.lastPos = node.start;
|
||||
}
|
||||
|
||||
if (!generate) buffer.concat(" "); // Add an extra space if it looks something like this: "return(<expression>)". No space between return and expression.
|
||||
if (!node.keys.length) {
|
||||
compiler.jsBuffer.concat("objj_msgSend(objj_msgSend(CPDictionary, \"alloc\"), \"init\")");
|
||||
if (!st.receiverLevel) st.receiverLevel = 0;
|
||||
if (!noOfKeys) {
|
||||
if (compiler.flags & ObjJAcornCompiler.Flags.InlineMsgSend) {
|
||||
buffer.concat("(___r");
|
||||
buffer.concat(++st.receiverLevel + "");
|
||||
buffer.concat(" = (CPDictionary.isa.method_msgSend[\"alloc\"] || _objj_forward)(CPDictionary, \"alloc\"), ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(" == null ? null : (___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(".isa.method_msgSend[\"init\"] || _objj_forward)(___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(", \"init\"))");
|
||||
} else {
|
||||
buffer.concat("(___r");
|
||||
buffer.concat(++st.receiverLevel + "");
|
||||
buffer.concat(" = CPDictionary.isa.objj_msgSend0(CPDictionary, \"alloc\"), ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(" == null ? null : ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(".isa.objj_msgSend0(___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(", \"init\"))");
|
||||
}
|
||||
|
||||
if (!(st.maxReceiverLevel >= st.receiverLevel))
|
||||
st.maxReceiverLevel = st.receiverLevel;
|
||||
} else {
|
||||
compiler.jsBuffer.concat("objj_msgSend(objj_msgSend(CPDictionary, \"alloc\"), \"initWithObjectsAndKeys:\"");
|
||||
for (var i = 0; i < node.keys.length; i++) {
|
||||
var key = node.keys[i],
|
||||
value = node.values[i];
|
||||
if (compiler.flags & ObjJAcornCompiler.Flags.InlineMsgSend) {
|
||||
buffer.concat("(___r");
|
||||
buffer.concat(++st.receiverLevel + "");
|
||||
buffer.concat(" = (CPDictionary.isa.method_msgSend[\"alloc\"] || _objj_forward)(CPDictionary, \"alloc\"), ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(" == null ? null : (___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(".isa.method_msgSend[\"initWithObjects:forKeys:\"] || _objj_forward)(___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(", \"initWithObjects:forKeys:\", [");
|
||||
} else {
|
||||
buffer.concat("(___r");
|
||||
buffer.concat(++st.receiverLevel + "");
|
||||
buffer.concat(" = CPDictionary.isa.objj_msgSend0(CPDictionary, \"alloc\"), ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(" == null ? null : ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(".isa.objj_msgSend2(___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(", \"initWithObjects:forKeys:\", [");
|
||||
}
|
||||
|
||||
compiler.jsBuffer.concat(", ");
|
||||
if (!(st.maxReceiverLevel >= st.receiverLevel))
|
||||
st.maxReceiverLevel = st.receiverLevel;
|
||||
|
||||
for (var i = 0; i < noOfKeys; i++) {
|
||||
var value = node.values[i];
|
||||
|
||||
if (i) buffer.concat(", ");
|
||||
if (!generate) compiler.lastPos = value.start;
|
||||
c(value, st, "Expression");
|
||||
if (!generate) compiler.jsBuffer.concat(compiler.source.substring(compiler.lastPos, value.end));
|
||||
if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, value.end));
|
||||
}
|
||||
|
||||
compiler.jsBuffer.concat(", ");
|
||||
buffer.concat("], [");
|
||||
|
||||
for (var i = 0; i < noOfKeys; i++) {
|
||||
var key = node.keys[i];
|
||||
|
||||
if (i) buffer.concat(", ");
|
||||
if (!generate) compiler.lastPos = key.start;
|
||||
c(key, st, "Expression");
|
||||
if (!generate) compiler.jsBuffer.concat(compiler.source.substring(compiler.lastPos, key.end));
|
||||
if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, key.end));
|
||||
}
|
||||
compiler.jsBuffer.concat(")");
|
||||
buffer.concat("]))");
|
||||
}
|
||||
|
||||
st.receiverLevel--;
|
||||
if (!generate) compiler.lastPos = node.end;
|
||||
},
|
||||
ImportStatement: function(node, st, c) {
|
||||
@@ -2257,17 +2398,48 @@ MethodDeclarationStatement: function(node, st, c) {
|
||||
MessageSendExpression: function(node, st, c) {
|
||||
var compiler = st.compiler,
|
||||
generate = compiler.generate,
|
||||
inlineMsgSend = compiler.flags & ObjJAcornCompiler.Flags.InlineMsgSend,
|
||||
buffer = compiler.jsBuffer,
|
||||
nodeObject = node.object;
|
||||
nodeObject = node.object,
|
||||
selectors = node.selectors,
|
||||
arguments = node.arguments,
|
||||
argumentsLength = arguments.length,
|
||||
firstSelector = selectors[0],
|
||||
selector = firstSelector ? firstSelector.name : ""; // There is always at least one selector
|
||||
|
||||
// Put together the selector. Maybe this should be done in the parser...
|
||||
for (var i = 0; i < argumentsLength; i++)
|
||||
if (i === 0)
|
||||
selector += ":";
|
||||
else
|
||||
selector += (selectors[i] ? selectors[i].name : "") + ":";
|
||||
|
||||
if (!generate) {
|
||||
buffer.concat(compiler.source.substring(compiler.lastPos, node.start));
|
||||
compiler.lastPos = nodeObject ? nodeObject.start : node.arguments.length ? node.arguments[0].start : node.end;
|
||||
} else if (!inlineMsgSend) {
|
||||
// Find out the total number of arguments so we can choose appropriate msgSend function. Only needed if call the function and not inline it
|
||||
var totalNoOfParameters = argumentsLength;
|
||||
|
||||
if (node.parameters)
|
||||
totalNoOfParameters += node.parameters.length;
|
||||
}
|
||||
if (node.superObject)
|
||||
{
|
||||
if (!generate) buffer.concat(" "); // Add an extra space if it looks something like this: "return(<expression>)". No space between return and expression.
|
||||
buffer.concat("objj_msgSendSuper(");
|
||||
buffer.concat("{ receiver:self, super_class:" + (st.currentMethodType() === "+" ? compiler.currentSuperMetaClass : compiler.currentSuperClass ) + " }");
|
||||
if (inlineMsgSend) {
|
||||
buffer.concat("(");
|
||||
buffer.concat(st.currentMethodType() === "+" ? compiler.currentSuperMetaClass : compiler.currentSuperClass);
|
||||
buffer.concat(".method_dtable[\"");
|
||||
buffer.concat(selector);
|
||||
buffer.concat("\"] || _objj_forward)(self");
|
||||
} else {
|
||||
buffer.concat("objj_msgSendSuper");
|
||||
if (totalNoOfParameters < 4) {
|
||||
buffer.concat("" + totalNoOfParameters);
|
||||
}
|
||||
buffer.concat("({ receiver:self, super_class:" + (st.currentMethodType() === "+" ? compiler.currentSuperMetaClass : compiler.currentSuperClass ) + " }");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2293,6 +2465,8 @@ MessageSendExpression: function(node, st, c) {
|
||||
c(nodeObject, st, "Expression");
|
||||
buffer.concat(" == null ? null : ");
|
||||
}
|
||||
if (inlineMsgSend)
|
||||
buffer.concat("(");
|
||||
c(nodeObject, st, "Expression");
|
||||
} else {
|
||||
receiverIsNotSelf = true;
|
||||
@@ -2303,12 +2477,20 @@ MessageSendExpression: function(node, st, c) {
|
||||
c(nodeObject, st, "Expression");
|
||||
buffer.concat("), ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(" == null ? null : ___r");
|
||||
buffer.concat(" == null ? null : ");
|
||||
if (inlineMsgSend)
|
||||
buffer.concat("(");
|
||||
buffer.concat("___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
if (!(st.maxReceiverLevel >= st.receiverLevel))
|
||||
st.maxReceiverLevel = st.receiverLevel;
|
||||
}
|
||||
buffer.concat(".isa.objj_msgSend");
|
||||
if (inlineMsgSend) {
|
||||
buffer.concat(".isa.method_msgSend[\"");
|
||||
buffer.concat(selector);
|
||||
buffer.concat("\"] || _objj_forward)");
|
||||
} else
|
||||
buffer.concat(".isa.objj_msgSend");
|
||||
} else {
|
||||
buffer.concat(" "); // Add an extra space if it looks something like this: "return(<expression>)". No space between return and expression.
|
||||
buffer.concat("objj_msgSend(");
|
||||
@@ -2316,19 +2498,11 @@ MessageSendExpression: function(node, st, c) {
|
||||
}
|
||||
}
|
||||
|
||||
var selectors = node.selectors,
|
||||
arguments = node.arguments,
|
||||
argumentsLength = arguments.length,
|
||||
firstSelector = selectors[0],
|
||||
selector = firstSelector ? firstSelector.name : ""; // There is always at least one selector
|
||||
|
||||
if (generate && !node.superObject) {
|
||||
var totalNoOfParameters = argumentsLength;
|
||||
|
||||
if (node.parameters)
|
||||
totalNoOfParameters += node.parameters.length;
|
||||
if (totalNoOfParameters < 4) {
|
||||
buffer.concat("" + totalNoOfParameters);
|
||||
if (!inlineMsgSend) {
|
||||
if (totalNoOfParameters < 4) {
|
||||
buffer.concat("" + totalNoOfParameters);
|
||||
}
|
||||
}
|
||||
|
||||
if (receiverIsIdentifier) {
|
||||
@@ -2340,13 +2514,6 @@ MessageSendExpression: function(node, st, c) {
|
||||
}
|
||||
}
|
||||
|
||||
// Put together the selector. Maybe this should be done in the parser...
|
||||
for (var i = 0; i < argumentsLength; i++)
|
||||
if (i === 0)
|
||||
selector += ":";
|
||||
else
|
||||
selector += (selectors[i] ? selectors[i].name : "") + ":";
|
||||
|
||||
buffer.concat(", \"");
|
||||
buffer.concat(selector); // FIXME: sel_getUid(selector + "") ? This FIXME is from the old preprocessor compiler
|
||||
buffer.concat("\"");
|
||||
|
||||
Reference in New Issue
Block a user