Browse Source

Fixes issue #774

Nicolas Petton 11 years ago
parent
commit
f0b70f6054
4 changed files with 45 additions and 13 deletions
  1. 19 12
      js/Compiler-Semantic.js
  2. 18 0
      js/Compiler-Tests.js
  3. 2 1
      st/Compiler-Semantic.st
  4. 6 0
      st/Compiler-Tests.st

+ 19 - 12
js/Compiler-Semantic.js

@@ -1814,7 +1814,7 @@ var self=this;
 function $Set(){return smalltalk.Set||(typeof Set=="undefined"?nil:Set)}
 function $IRSendInliner(){return smalltalk.IRSendInliner||(typeof IRSendInliner=="undefined"?nil:IRSendInliner)}
 return smalltalk.withContext(function($ctx1) { 
-var $3,$2,$1,$4,$5,$6,$8,$9,$7,$11,$12,$10,$13,$14,$16,$17,$15;
+var $3,$2,$1,$4,$5,$6,$8,$9,$7,$11,$12,$10,$13,$14,$15,$17,$18,$16;
 $3=_st(aNode)._receiver();
 $ctx1.sendIdx["receiver"]=1;
 $2=_st($3)._value();
@@ -1848,30 +1848,37 @@ $ctx1.sendIdx["selector"]=3;
 $10=_st($11)._includes_($12);
 if(smalltalk.assert($10)){
 _st(aNode)._shouldBeInlined_(true);
-_st(_st(aNode)._receiver())._shouldBeAliased_(true);
+$13=_st(aNode)._receiver();
+if(($receiver = $13) == nil || $receiver == null){
+$13;
+} else {
+var receiver;
+receiver=$receiver;
+_st(receiver)._shouldBeAliased_(true);
+};
 };
 };
-$13=self._messageSends();
+$14=self._messageSends();
 $ctx1.sendIdx["messageSends"]=1;
-$14=_st(aNode)._selector();
+$15=_st(aNode)._selector();
 $ctx1.sendIdx["selector"]=4;
-_st($13)._at_ifAbsentPut_($14,(function(){
+_st($14)._at_ifAbsentPut_($15,(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st($Set())._new();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,5)})}));
-$16=self._messageSends();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,6)})}));
+$17=self._messageSends();
 $ctx1.sendIdx["messageSends"]=2;
-$17=_st(aNode)._selector();
+$18=_st(aNode)._selector();
 $ctx1.sendIdx["selector"]=5;
-$15=_st($16)._at_($17);
+$16=_st($17)._at_($18);
 $ctx1.sendIdx["at:"]=2;
-_st($15)._add_(aNode);
+_st($16)._add_(aNode);
 _st(aNode)._index_(_st(_st(self._messageSends())._at_(_st(aNode)._selector()))._size());
 smalltalk.SemanticAnalyzer.superclass.fn.prototype._visitSendNode_.apply(_st(self), [aNode]);
 return self}, function($ctx1) {$ctx1.fill(self,"visitSendNode:",{aNode:aNode},smalltalk.SemanticAnalyzer)})},
 args: ["aNode"],
-source: "visitSendNode: aNode\x0a\x0a\x09aNode receiver value = 'super'\x0a\x09\x09ifTrue: [\x0a\x09\x09\x09aNode superSend: true.\x0a\x09\x09\x09aNode receiver value: 'self'.\x0a\x09\x09\x09self superSends at: aNode selector ifAbsentPut: [ Set new ].\x0a\x09\x09\x09(self superSends at: aNode selector) add: aNode ]\x0a\x09\x09\x0a\x09\x09ifFalse: [ (IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [\x0a\x09\x09\x09aNode shouldBeInlined: true.\x0a\x09\x09\x09aNode receiver shouldBeAliased: true ] ].\x0a\x0a\x09self messageSends at: aNode selector ifAbsentPut: [ Set new ].\x0a\x09(self messageSends at: aNode selector) add: aNode.\x0a\x0a\x09aNode index: (self messageSends at: aNode selector) size.\x0a\x0a\x09super visitSendNode: aNode",
-messageSends: ["ifTrue:ifFalse:", "=", "value", "receiver", "superSend:", "value:", "at:ifAbsentPut:", "superSends", "selector", "new", "add:", "at:", "ifTrue:", "includes:", "inlinedSelectors", "shouldBeInlined:", "shouldBeAliased:", "messageSends", "index:", "size", "visitSendNode:"],
+source: "visitSendNode: aNode\x0a\x0a\x09aNode receiver value = 'super'\x0a\x09\x09ifTrue: [\x0a\x09\x09\x09aNode superSend: true.\x0a\x09\x09\x09aNode receiver value: 'self'.\x0a\x09\x09\x09self superSends at: aNode selector ifAbsentPut: [ Set new ].\x0a\x09\x09\x09(self superSends at: aNode selector) add: aNode ]\x0a\x09\x09\x0a\x09\x09ifFalse: [ (IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [\x0a\x09\x09\x09aNode shouldBeInlined: true.\x0a\x09\x09\x09aNode receiver ifNotNil: [ :receiver |\x0a\x09\x09\x09\x09receiver shouldBeAliased: true ] ] ].\x0a\x0a\x09self messageSends at: aNode selector ifAbsentPut: [ Set new ].\x0a\x09(self messageSends at: aNode selector) add: aNode.\x0a\x0a\x09aNode index: (self messageSends at: aNode selector) size.\x0a\x0a\x09super visitSendNode: aNode",
+messageSends: ["ifTrue:ifFalse:", "=", "value", "receiver", "superSend:", "value:", "at:ifAbsentPut:", "superSends", "selector", "new", "add:", "at:", "ifTrue:", "includes:", "inlinedSelectors", "shouldBeInlined:", "ifNotNil:", "shouldBeAliased:", "messageSends", "index:", "size", "visitSendNode:"],
 referencedClasses: ["Set", "IRSendInliner"]
 }),
 smalltalk.SemanticAnalyzer);

+ 18 - 0
js/Compiler-Tests.js

@@ -458,6 +458,24 @@ referencedClasses: []
 }),
 smalltalk.CodeGeneratorTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testCascadesWithInlining",
+protocol: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._should_return_("foo ^ true ifTrue: [ 1 ] ifFalse: [ 2 ]",(1));
+$ctx1.sendIdx["should:return:"]=1;
+self._should_return_("foo ^ false ifTrue: [ 1 ] ifFalse: [ 2 ]",(2));
+return self}, function($ctx1) {$ctx1.fill(self,"testCascadesWithInlining",{},smalltalk.CodeGeneratorTest)})},
+args: [],
+source: "testCascadesWithInlining\x0a\x09\x0a\x09self should: 'foo ^ true ifTrue: [ 1 ] ifFalse: [ 2 ]' return: 1.\x0a\x09self should: 'foo ^ false ifTrue: [ 1 ] ifFalse: [ 2 ]' return: 2",
+messageSends: ["should:return:"],
+referencedClasses: []
+}),
+smalltalk.CodeGeneratorTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testDynamicArrayElementsOrdered",

+ 2 - 1
st/Compiler-Semantic.st

@@ -577,7 +577,8 @@ visitSendNode: aNode
 		
 		ifFalse: [ (IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [
 			aNode shouldBeInlined: true.
-			aNode receiver shouldBeAliased: true ] ].
+			aNode receiver ifNotNil: [ :receiver |
+				receiver shouldBeAliased: true ] ] ].
 
 	self messageSends at: aNode selector ifAbsentPut: [ Set new ].
 	(self messageSends at: aNode selector) add: aNode.

+ 6 - 0
st/Compiler-Tests.st

@@ -175,6 +175,12 @@ testCascades
 	self should: 'foo ^ Array new add: 3; add: 4; yourself' return: #(3 4)
 !
 
+testCascadesWithInlining
+	
+	self should: 'foo ^ true ifTrue: [ 1 ] ifFalse: [ 2 ]' return: 1.
+	self should: 'foo ^ false ifTrue: [ 1 ] ifFalse: [ 2 ]' return: 2
+!
+
 testDynamicArrayElementsOrdered
 	self should: 'foo
 	| x |