mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-04 09:53:41 +00:00
Merge pull request #2103 from mrcarlberg/fast_msg_send
Fixed: Faster objj_msgSend
This commit is contained in:
@@ -51,7 +51,7 @@
|
||||
|
||||
// Not being able to set the action is a fatal error.
|
||||
if ([_source respondsToSelector:@selector(setAction:)])
|
||||
objj_msgSend(_source, @selector(setAction:), selector);
|
||||
[_source setAction:selector];
|
||||
|
||||
else
|
||||
[CPException
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
// Not being able to set the target is a fatal error.
|
||||
if ([_source respondsToSelector:@selector(setTarget:)])
|
||||
objj_msgSend(_source, @selector(setTarget:), _destination);
|
||||
[_source setTarget:_destination];
|
||||
|
||||
else
|
||||
[CPException
|
||||
|
||||
@@ -1400,9 +1400,18 @@ AssignmentExpression: function(node, st, c) {
|
||||
return;
|
||||
}
|
||||
|
||||
var saveAssignment = st.assignment;
|
||||
var saveAssignment = st.assignment,
|
||||
nodeLeft = node.left;
|
||||
st.assignment = true;
|
||||
(generate && nodePrecedence(node, node.left) ? surroundExpression(c) : c)(node.left, st, "Expression");
|
||||
if (nodeLeft.type === "Identifier" && nodeLeft.name === "self") {
|
||||
var lVar = st.getLvar("self", true);
|
||||
if (lVar) {
|
||||
var lVarScope = lVar.scope;
|
||||
if (lVarScope)
|
||||
lVarScope.assignmentToSelf = true;
|
||||
}
|
||||
}
|
||||
(generate && nodePrecedence(node, nodeLeft) ? surroundExpression(c) : c)(nodeLeft, st, "Expression");
|
||||
if (generate) {
|
||||
buffer.concat(" ");
|
||||
buffer.concat(node.operator);
|
||||
@@ -1410,8 +1419,8 @@ AssignmentExpression: function(node, st, c) {
|
||||
}
|
||||
st.assignment = saveAssignment;
|
||||
(generate && nodePrecedence(node, node.right, true) ? surroundExpression(c) : c)(node.right, st, "Expression");
|
||||
if (st.isRootScope() && node.left.type === "Identifier" && !st.getLvar(node.left.name))
|
||||
st.vars[node.left.name] = {type: "global", node: node.left};
|
||||
if (st.isRootScope() && nodeLeft.type === "Identifier" && !st.getLvar(nodeLeft.name))
|
||||
st.vars[nodeLeft.name] = {type: "global", node: nodeLeft};
|
||||
},
|
||||
ConditionalExpression: function(node, st, c) {
|
||||
var compiler = st.compiler,
|
||||
@@ -1440,8 +1449,22 @@ NewExpression: function(node, st, c) {
|
||||
},
|
||||
CallExpression: function(node, st, c) {
|
||||
var compiler = st.compiler,
|
||||
generate = compiler.generate;
|
||||
(generate && nodePrecedence(node, node.callee) ? surroundExpression(c) : c)(node.callee, st, "Expression");
|
||||
generate = compiler.generate,
|
||||
callee = node.callee;
|
||||
|
||||
// If call to function 'eval' we assume that 'self' can be altered and from this point
|
||||
// we check if 'self' is null before 'objj_msgSend' is called with 'self' as receiver.
|
||||
if (callee.type === "Identifier" && callee.name === "eval") {
|
||||
var selfLvar = st.getLvar("self", true);
|
||||
if (selfLvar) {
|
||||
var selfScope = selfLvar.scope;
|
||||
if (selfScope) {
|
||||
selfScope.assignmentToSelf = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(generate && nodePrecedence(node, callee) ? surroundExpression(c) : c)(callee, st, "Expression");
|
||||
if (generate) compiler.jsBuffer.concat("(");
|
||||
if (node.arguments) {
|
||||
for (var i = 0; i < node.arguments.length; ++i) {
|
||||
@@ -2026,6 +2049,9 @@ MethodDeclarationStatement: function(node, st, c) {
|
||||
compiler.jsBuffer.concat("(self, _cmd");
|
||||
|
||||
methodScope.methodType = node.methodtype;
|
||||
methodScope.vars["self"] = {type: "method base", scope: methodScope};
|
||||
methodScope.vars["_cmd"] = {type: "method base", scope: methodScope};
|
||||
|
||||
if (nodeArguments) for (var i = 0; i < nodeArguments.length; i++)
|
||||
{
|
||||
var argument = nodeArguments[i],
|
||||
@@ -2125,10 +2151,11 @@ MethodDeclarationStatement: function(node, st, c) {
|
||||
MessageSendExpression: function(node, st, c) {
|
||||
var compiler = st.compiler,
|
||||
generate = compiler.generate,
|
||||
buffer = compiler.jsBuffer;
|
||||
buffer = compiler.jsBuffer,
|
||||
nodeObject = node.object;
|
||||
if (!generate) {
|
||||
buffer.concat(compiler.source.substring(compiler.lastPos, node.start));
|
||||
compiler.lastPos = node.object ? node.object.start : node.arguments.length ? node.arguments[0].start : node.end;
|
||||
compiler.lastPos = nodeObject ? nodeObject.start : node.arguments.length ? node.arguments[0].start : node.end;
|
||||
}
|
||||
if (node.superObject)
|
||||
{
|
||||
@@ -2138,20 +2165,49 @@ MessageSendExpression: function(node, st, c) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!st.receiverLevel) st.receiverLevel = 0;
|
||||
if (!generate) buffer.concat(" "); // Add an extra space if it looks something like this: "return(<expression>)". No space between return and expression.
|
||||
buffer.concat("((___r");
|
||||
buffer.concat(++st.receiverLevel + "");
|
||||
buffer.concat(" = ");
|
||||
c(node.object, st, "Expression");
|
||||
buffer.concat("), ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(" == null ? null : ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(".isa.objj_msgSend");
|
||||
if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, node.object.end));
|
||||
if (!(st.maxReceiverLevel >= st.receiverLevel))
|
||||
st.maxReceiverLevel = st.receiverLevel;
|
||||
if (generate) {
|
||||
// If the recevier is not an identifier or an ivar that should have 'self.' infront we need to assign it to a temporary variable
|
||||
// If it is 'self' we assume it will never be nil and remove that test
|
||||
var receiverIsIdentifier = nodeObject.type === "Identifier" && !(st.currentMethodType() === "-" && compiler.getIvarForClass(nodeObject.name, st) && !st.getLvar(nodeObject.name, true)),
|
||||
selfLvar,
|
||||
receiverIsNotSelf;
|
||||
|
||||
if (receiverIsIdentifier) {
|
||||
var name = nodeObject.name,
|
||||
selfLvar = st.getLvar(name);
|
||||
|
||||
if (name === "self") {
|
||||
receiverIsNotSelf = !selfLvar || !selfLvar.scope || selfLvar.scope.assignmentToSelf;
|
||||
} else {
|
||||
receiverIsNotSelf = !!selfLvar || !compiler.getClassDef(name);
|
||||
}
|
||||
|
||||
if (receiverIsNotSelf) {
|
||||
buffer.concat("(");
|
||||
c(nodeObject, st, "Expression");
|
||||
buffer.concat(" == null ? null : ");
|
||||
}
|
||||
c(nodeObject, st, "Expression");
|
||||
} else {
|
||||
receiverIsNotSelf = true;
|
||||
if (!st.receiverLevel) st.receiverLevel = 0;
|
||||
buffer.concat("((___r");
|
||||
buffer.concat(++st.receiverLevel + "");
|
||||
buffer.concat(" = ");
|
||||
c(nodeObject, st, "Expression");
|
||||
buffer.concat("), ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
buffer.concat(" == null ? null : ___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
if (!(st.maxReceiverLevel >= st.receiverLevel))
|
||||
st.maxReceiverLevel = st.receiverLevel;
|
||||
}
|
||||
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(");
|
||||
buffer.concat(compiler.source.substring(compiler.lastPos, nodeObject.end));
|
||||
}
|
||||
}
|
||||
|
||||
var selectors = node.selectors,
|
||||
@@ -2160,7 +2216,7 @@ MessageSendExpression: function(node, st, c) {
|
||||
firstSelector = selectors[0],
|
||||
selector = firstSelector ? firstSelector.name : ""; // There is always at least one selector
|
||||
|
||||
if (!node.superObject) {
|
||||
if (generate && !node.superObject) {
|
||||
var totalNoOfParameters = argumentsLength;
|
||||
|
||||
if (node.parameters)
|
||||
@@ -2169,8 +2225,13 @@ MessageSendExpression: function(node, st, c) {
|
||||
buffer.concat("" + totalNoOfParameters);
|
||||
}
|
||||
|
||||
buffer.concat("(___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
if (receiverIsIdentifier) {
|
||||
buffer.concat("(");
|
||||
c(nodeObject, st, "Expression");
|
||||
} else {
|
||||
buffer.concat("(___r");
|
||||
buffer.concat(st.receiverLevel + "");
|
||||
}
|
||||
}
|
||||
|
||||
// Put together the selector. Maybe this should be done in the parser...
|
||||
@@ -2213,9 +2274,11 @@ MessageSendExpression: function(node, st, c) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!node.superObject) {
|
||||
buffer.concat(")");
|
||||
st.receiverLevel--;
|
||||
if (generate && !node.superObject) {
|
||||
if (receiverIsNotSelf)
|
||||
buffer.concat(")");
|
||||
if (!receiverIsIdentifier)
|
||||
st.receiverLevel--;
|
||||
}
|
||||
|
||||
buffer.concat(")");
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
|
||||
((___r1=object),___r1==null?null:___r1.isa.objj_msgSend1(___r1,":",argument));
|
||||
(object==null?null:object.isa.objj_msgSend1(object,":",argument));
|
||||
@@ -1 +1 @@
|
||||
((___r1=object),___r1==null?null:___r1.isa.objj_msgSend3(___r1,"for:in:nil:",a,b,nil));
|
||||
(object==null?null:object.isa.objj_msgSend3(object,"for:in:nil:",a,b,nil));
|
||||
@@ -1,2 +1,2 @@
|
||||
|
||||
((___r1=object),___r1==null?null:___r1.isa.objj_msgSend(___r1,"label:label2:label3:label4:",argument,argument2,argument3,argument4));
|
||||
(object==null?null:object.isa.objj_msgSend(object,"label:label2:label3:label4:",argument,argument2,argument3,argument4));
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
|
||||
[CPArray new];
|
||||
[object message];
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
|
||||
((___r1=object),___r1==null?null:___r1.isa.objj_msgSend0(___r1,"message"));
|
||||
CPArray.isa.objj_msgSend0(CPArray,"new");
|
||||
(object==null?null:object.isa.objj_msgSend0(object,"message"));
|
||||
@@ -1,2 +1,2 @@
|
||||
|
||||
[CPArray arrayWithArray:[]];
|
||||
[object label:argument];
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
|
||||
((___r1=object),___r1==null?null:___r1.isa.objj_msgSend1(___r1,"label:",argument));
|
||||
CPArray.isa.objj_msgSend1(CPArray,"arrayWithArray:",[]);
|
||||
(object==null?null:object.isa.objj_msgSend1(object,"label:",argument));
|
||||
@@ -0,0 +1,15 @@
|
||||
@implementation MyClass
|
||||
|
||||
- (id)mySelector {
|
||||
[self init];
|
||||
self = nil;
|
||||
[self init];
|
||||
}
|
||||
|
||||
- (id)mySelector2 {
|
||||
[self init];
|
||||
eval("self = null;");
|
||||
[self init];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,11 @@
|
||||
var the_class=objj_allocateClassPair(Nil,"MyClass"),meta_class=the_class.isa;
|
||||
objj_registerClassPair(the_class);
|
||||
class_addMethods(the_class,[new objj_method(sel_getUid("mySelector"),function $MyClass__mySelector(_1,_2){
|
||||
_1.isa.objj_msgSend0(_1,"init");
|
||||
_1=nil;
|
||||
(_1==null?null:_1.isa.objj_msgSend0(_1,"init"));
|
||||
},["id"]),new objj_method(sel_getUid("mySelector2"),function $MyClass__mySelector2(_3,_4){
|
||||
_3.isa.objj_msgSend0(_3,"init");
|
||||
eval("self = null;");
|
||||
(_3==null?null:_3.isa.objj_msgSend0(_3,"init"));
|
||||
},["id"])]);
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
((___r1=object),___r1==null?null:___r1.isa.objj_msgSend1(___r1,"label:",condition?true:false));
|
||||
((___r1=object),___r1==null?null:___r1.isa.objj_msgSend1(___r1,"label:",condition?true:false));
|
||||
((___r1=object),___r1==null?null:___r1.isa.objj_msgSend1(___r1,"label:",condition?true:false));
|
||||
(object==null?null:object.isa.objj_msgSend1(object,"label:",condition?true:false));
|
||||
(object==null?null:object.isa.objj_msgSend1(object,"label:",condition?true:false));
|
||||
(object==null?null:object.isa.objj_msgSend1(object,"label:",condition?true:false));
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
x=function(){
|
||||
return ((_1=someIval),_1==null?null:_1.isa.objj_msgSend0(_1,"someMethod"));
|
||||
var _1;
|
||||
};
|
||||
return (someIval==null?null:someIval.isa.objj_msgSend0(someIval,"someMethod"));
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@ var FILENAMES = [
|
||||
"Messages/ternary-operator-argument",
|
||||
"Messages/keyword-in-selector",
|
||||
"Messages/colon-selector",
|
||||
"Messages/self-as-receiver",
|
||||
|
||||
"Misc/parenthesis-return",
|
||||
"Misc/preprocess-if-directives",
|
||||
|
||||
Reference in New Issue
Block a user