Browse Source

Optimizations. Cleaning.

Herby Vojčík 4 years ago
parent
commit
0f51004ae5

+ 1 - 49
lang/src/Compiler-AST.js

@@ -1701,7 +1701,7 @@ $globals.ReturnNode);
 
 
 
-$core.addClass("SendNode", $globals.ASTNode, ["selector", "arguments", "receiver", "index", "shouldBeInlined"], "Compiler-AST");
+$core.addClass("SendNode", $globals.ASTNode, ["selector", "arguments", "receiver", "index"], "Compiler-AST");
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.SendNode.comment="I represent an message send node.";
 //>>excludeEnd("ide");
@@ -2002,54 +2002,6 @@ return self;
 }; }),
 $globals.SendNode);
 
-$core.addMethod(
-$core.method({
-selector: "shouldBeInlined",
-protocol: "accessing",
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "shouldBeInlined\x0a\x09^ shouldBeInlined ifNil: [ false ]",
-referencedClasses: [],
-//>>excludeEnd("ide");
-pragmas: [],
-messageSends: ["ifNil:"]
-}, function ($methodClass){ return function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-var $1,$receiver;
-$1=$self.shouldBeInlined;
-if(($receiver = $1) == null || $receiver.a$nil){
-return false;
-} else {
-return $1;
-}
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"shouldBeInlined",{})});
-//>>excludeEnd("ctx");
-}; }),
-$globals.SendNode);
-
-$core.addMethod(
-$core.method({
-selector: "shouldBeInlined:",
-protocol: "accessing",
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aBoolean"],
-source: "shouldBeInlined: aBoolean\x0a\x09shouldBeInlined := aBoolean",
-referencedClasses: [],
-//>>excludeEnd("ide");
-pragmas: [],
-messageSends: []
-}, function ($methodClass){ return function (aBoolean){
-var self=this,$self=this;
-$self.shouldBeInlined=aBoolean;
-return self;
-
-}; }),
-$globals.SendNode);
-
 $core.addMethod(
 $core.method({
 selector: "superSend",

+ 1 - 9
lang/src/Compiler-AST.st

@@ -432,7 +432,7 @@ acceptDagVisitor: aVisitor
 ! !
 
 ASTNode subclass: #SendNode
-	slots: {#selector. #arguments. #receiver. #index. #shouldBeInlined}
+	slots: {#selector. #arguments. #receiver. #index}
 	package: 'Compiler-AST'!
 !SendNode commentStamp!
 I represent an message send node.!
@@ -481,14 +481,6 @@ selector: aString
 	selector := aString
 !
 
-shouldBeInlined
-	^ shouldBeInlined ifNil: [ false ]
-!
-
-shouldBeInlined: aBoolean
-	shouldBeInlined := aBoolean
-!
-
 superSend
 	^ self receiver notNil and: [ self receiver isSuper ]
 ! !

+ 49 - 98
lang/src/Compiler-IR.js

@@ -105,55 +105,61 @@ selector: "aliasTemporally:",
 protocol: "visiting",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aCollection"],
-source: "aliasTemporally: aCollection\x0a\x09\x22https://lolg.it/amber/amber/issues/296\x0a\x09\x0a\x09If a node is aliased, all preceding ones are aliased as well.\x0a\x09The tree is iterated twice. First we get the aliasing dependency,\x0a\x09then the aliasing itself is done\x22\x0a\x0a\x09| threshold result |\x0a\x09threshold := 0.\x0a\x09\x0a\x09aCollection withIndexDo: [ :each :i |\x0a\x09\x09each subtreeNeedsAliasing\x0a\x09\x09\x09ifTrue: [ threshold := i ] ].\x0a\x0a\x09result := OrderedCollection new.\x0a\x09aCollection withIndexDo: [ :each :i |\x0a\x09\x09result add: (i <= threshold\x0a\x09\x09\x09ifTrue: [ self alias: each ]\x0a\x09\x09\x09ifFalse: [ self visit: each ]) ].\x0a\x0a\x09^ result",
-referencedClasses: ["OrderedCollection"],
+source: "aliasTemporally: aCollection\x0a\x09\x22https://lolg.it/amber/amber/issues/296\x0a\x09\x0a\x09If a node is aliased, all preceding ones are aliased as well.\x0a\x09The tree is iterated twice. First we get the aliasing dependency,\x0a\x09then the aliasing itself is done\x22\x0a\x0a\x09| threshold shouldAlias |\x0a\x09threshold := aCollection reversed\x0a\x09\x09detect: [ :each | each subtreeNeedsAliasing ]\x0a\x09\x09ifNone: [ ^ self visitAll: aCollection ].\x0a\x0a\x09shouldAlias := true.\x0a\x09^ aCollection collect: [ :each |\x0a\x09\x09shouldAlias\x0a\x09\x09\x09ifTrue: [ each == threshold ifTrue: [ shouldAlias := false ]. self alias: each ]\x0a\x09\x09\x09ifFalse: [ self visit: each ] ]",
+referencedClasses: [],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["withIndexDo:", "ifTrue:", "subtreeNeedsAliasing", "new", "add:", "ifTrue:ifFalse:", "<=", "alias:", "visit:"]
+messageSends: ["detect:ifNone:", "reversed", "subtreeNeedsAliasing", "visitAll:", "collect:", "ifTrue:ifFalse:", "ifTrue:", "==", "alias:", "visit:"]
 }, function ($methodClass){ return function (aCollection){
 var self=this,$self=this;
-var threshold,result;
+var threshold,shouldAlias;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $1,$2,$4,$3;
-threshold=(0);
-$recv(aCollection)._withIndexDo_((function(each,i){
+var $1,$2;
+var $early={};
+try {
+threshold=$recv($recv(aCollection)._reversed())._detect_ifNone_((function(each){
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx2) {
 //>>excludeEnd("ctx");
-$1=$recv(each)._subtreeNeedsAliasing();
-if($core.assert($1)){
-threshold=i;
-return threshold;
-}
+return $recv(each)._subtreeNeedsAliasing();
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({each:each,i:i},$ctx1,1)});
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
 //>>excludeEnd("ctx");
-}));
+}),(function(){
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.sendIdx["withIndexDo:"]=1;
+return $core.withContext(function($ctx2) {
 //>>excludeEnd("ctx");
-result=$recv($globals.OrderedCollection)._new();
-$recv(aCollection)._withIndexDo_((function(each,i){
+throw $early=[$self._visitAll_(aCollection)];
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)});
+//>>excludeEnd("ctx");
+}));
+shouldAlias=true;
+return $recv(aCollection)._collect_((function(each){
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx2) {
 //>>excludeEnd("ctx");
-$2=result;
-$4=$recv(i).__lt_eq(threshold);
-if($core.assert($4)){
-$3=$self._alias_(each);
+$1=shouldAlias;
+if($core.assert($1)){
+$2=$recv(each).__eq_eq(threshold);
+if($core.assert($2)){
+shouldAlias=false;
+shouldAlias;
+}
+return $self._alias_(each);
 } else {
-$3=$self._visit_(each);
+return $self._visit_(each);
 }
-return $recv($2)._add_($3);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({each:each,i:i},$ctx1,3)});
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,3)});
 //>>excludeEnd("ctx");
 }));
-return result;
+}
+catch(e) {if(e===$early)return e[0]; throw e}
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"aliasTemporally:",{aCollection:aCollection,threshold:threshold,result:result})});
+}, function($ctx1) {$ctx1.fill(self,"aliasTemporally:",{aCollection:aCollection,threshold:threshold,shouldAlias:shouldAlias})});
 //>>excludeEnd("ctx");
 }; }),
 $globals.IRASTTranslator);
@@ -5905,20 +5911,19 @@ selector: "shouldBeAliased",
 protocol: "*Compiler-IR",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: [],
-source: "shouldBeAliased\x0a\x09\x22Because we keep track of send indexes, some send nodes need additional care for aliasing. \x0a\x09See IRJSVisitor >> visitIRSend:\x22\x0a\x09\x0a\x09| sends |\x0a\x09\x0a\x09sends := (self method sendIndexes at: self selector) size.\x0a\x09\x0a\x09^ (super shouldBeAliased or: [\x0a\x09\x09self isReferenced and: [\x0a\x09\x09\x09self index < sends or: [\x0a\x09\x09\x09\x09self superSend ] ] ])",
+source: "shouldBeAliased\x0a\x09\x22Because we keep track of send indexes, some send nodes need additional care for aliasing. \x0a\x09See IRJSVisitor >> visitIRSend:\x22\x0a\x09\x0a\x09| sends |\x0a\x09\x0a\x09super shouldBeAliased ifTrue: [ ^ true ].\x0a\x09self isReferenced ifFalse: [ ^ false ].\x0a\x09self superSend ifTrue: [ ^ true ].\x0a\x09sends := (self method sendIndexes at: self selector) size.\x0a\x09^ self index < sends",
 referencedClasses: [],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["size", "at:", "sendIndexes", "method", "selector", "or:", "shouldBeAliased", "and:", "isReferenced", "<", "index", "superSend"]
+messageSends: ["ifTrue:", "shouldBeAliased", "ifFalse:", "isReferenced", "superSend", "size", "at:", "sendIndexes", "method", "selector", "<", "index"]
 }, function ($methodClass){ return function (){
 var self=this,$self=this;
 var sends;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $2,$1;
-sends=$recv($recv($recv($self._method())._sendIndexes())._at_($self._selector()))._size();
-$2=(
+var $1,$2,$3;
+$1=(
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.supercall = true,
 //>>excludeEnd("ctx");
@@ -5926,77 +5931,23 @@ $ctx1.supercall = true,
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.supercall = false;
 //>>excludeEnd("ctx");;
-$1=$recv($2)._or_((function(){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $recv($self._isReferenced())._and_((function(){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx3) {
-//>>excludeEnd("ctx");
-return $recv($recv($self._index()).__lt(sends))._or_((function(){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx4) {
-//>>excludeEnd("ctx");
-return $self._superSend();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx4) {$ctx4.fillBlock({},$ctx3,3)});
-//>>excludeEnd("ctx");
-}));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx3) {$ctx3.fillBlock({},$ctx2,2)});
-//>>excludeEnd("ctx");
-}));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
-//>>excludeEnd("ctx");
-}));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.sendIdx["or:"]=1;
-//>>excludeEnd("ctx");
-return $1;
+if($core.assert($1)){
+return true;
+}
+$2=$self._isReferenced();
+if(!$core.assert($2)){
+return false;
+}
+$3=$self._superSend();
+if($core.assert($3)){
+return true;
+}
+sends=$recv($recv($recv($self._method())._sendIndexes())._at_($self._selector()))._size();
+return $recv($self._index()).__lt(sends);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"shouldBeAliased",{sends:sends})});
 //>>excludeEnd("ctx");
 }; }),
 $globals.SendNode);
 
-$core.addMethod(
-$core.method({
-selector: "subtreeNeedsAliasing",
-protocol: "*Compiler-IR",
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "subtreeNeedsAliasing\x0a\x09^ self shouldBeInlined or: [ super subtreeNeedsAliasing ]",
-referencedClasses: [],
-//>>excludeEnd("ide");
-pragmas: [],
-messageSends: ["or:", "shouldBeInlined", "subtreeNeedsAliasing"]
-}, function ($methodClass){ return function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $recv($self._shouldBeInlined())._or_((function(){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return (
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx2.supercall = true,
-//>>excludeEnd("ctx");
-($methodClass.superclass||$boot.nilAsClass).fn.prototype._subtreeNeedsAliasing.call($self));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx2.supercall = false;
-//>>excludeEnd("ctx");;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
-//>>excludeEnd("ctx");
-}));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"subtreeNeedsAliasing",{})});
-//>>excludeEnd("ctx");
-}; }),
-$globals.SendNode);
-
 });

+ 13 - 22
lang/src/Compiler-IR.st

@@ -89,20 +89,16 @@ aliasTemporally: aCollection
 	The tree is iterated twice. First we get the aliasing dependency,
 	then the aliasing itself is done"
 
-	| threshold result |
-	threshold := 0.
-	
-	aCollection withIndexDo: [ :each :i |
-		each subtreeNeedsAliasing
-			ifTrue: [ threshold := i ] ].
-
-	result := OrderedCollection new.
-	aCollection withIndexDo: [ :each :i |
-		result add: (i <= threshold
-			ifTrue: [ self alias: each ]
-			ifFalse: [ self visit: each ]) ].
+	| threshold shouldAlias |
+	threshold := aCollection reversed
+		detect: [ :each | each subtreeNeedsAliasing ]
+		ifNone: [ ^ self visitAll: aCollection ].
 
-	^ result
+	shouldAlias := true.
+	^ aCollection collect: [ :each |
+		shouldAlias
+			ifTrue: [ each == threshold ifTrue: [ shouldAlias := false ]. self alias: each ]
+			ifFalse: [ self visit: each ] ]
 !
 
 visitAssignmentNode: aNode
@@ -1375,15 +1371,10 @@ shouldBeAliased
 	
 	| sends |
 	
+	super shouldBeAliased ifTrue: [ ^ true ].
+	self isReferenced ifFalse: [ ^ false ].
+	self superSend ifTrue: [ ^ true ].
 	sends := (self method sendIndexes at: self selector) size.
-	
-	^ (super shouldBeAliased or: [
-		self isReferenced and: [
-			self index < sends or: [
-				self superSend ] ] ])
-!
-
-subtreeNeedsAliasing
-	^ self shouldBeInlined or: [ super subtreeNeedsAliasing ]
+	^ self index < sends
 ! !
 

+ 2 - 3
lang/src/Compiler-Inlining.js

@@ -11,11 +11,11 @@ selector: "visitSendNode:",
 protocol: "visiting",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
-source: "visitSendNode: aNode\x0a\x0a\x09aNode superSend ifFalse: [ \x0a\x09\x09(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\x09^ super visitSendNode: aNode",
+source: "visitSendNode: aNode\x0a\x0a\x09aNode superSend ifFalse: [ \x0a\x09\x09(IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [\x0a\x09\x09\x09aNode receiver ifNotNil: [ :receiver |\x0a\x09\x09\x09\x09receiver shouldBeAliased: true ] ] ].\x0a\x0a\x09^ super visitSendNode: aNode",
 referencedClasses: ["IRSendInliner"],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["ifFalse:", "superSend", "ifTrue:", "includes:", "inlinedSelectors", "selector", "shouldBeInlined:", "ifNotNil:", "receiver", "shouldBeAliased:", "visitSendNode:"]
+messageSends: ["ifFalse:", "superSend", "ifTrue:", "includes:", "inlinedSelectors", "selector", "ifNotNil:", "receiver", "shouldBeAliased:", "visitSendNode:"]
 }, function ($methodClass){ return function (aNode){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
@@ -26,7 +26,6 @@ $1=$recv(aNode)._superSend();
 if(!$core.assert($1)){
 $2=$recv($recv($globals.IRSendInliner)._inlinedSelectors())._includes_($recv(aNode)._selector());
 if($core.assert($2)){
-$recv(aNode)._shouldBeInlined_(true);
 $3=$recv(aNode)._receiver();
 if(($receiver = $3) == null || $receiver.a$nil){
 $3;

+ 0 - 1
lang/src/Compiler-Inlining.st

@@ -9,7 +9,6 @@ visitSendNode: aNode
 
 	aNode superSend ifFalse: [ 
 		(IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [
-			aNode shouldBeInlined: true.
 			aNode receiver ifNotNil: [ :receiver |
 				receiver shouldBeAliased: true ] ] ].