Bladeren bron

Optimizations. Cleaning.

Herby Vojčík 5 jaren geleden
bovenliggende
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);
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.SendNode.comment="I represent an message send node.";
 $globals.SendNode.comment="I represent an message send node.";
 //>>excludeEnd("ide");
 //>>excludeEnd("ide");
@@ -2002,54 +2002,6 @@ return self;
 }; }),
 }; }),
 $globals.SendNode);
 $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.addMethod(
 $core.method({
 $core.method({
 selector: "superSend",
 selector: "superSend",

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

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

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

@@ -105,55 +105,61 @@ selector: "aliasTemporally:",
 protocol: "visiting",
 protocol: "visiting",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aCollection"],
 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");
 //>>excludeEnd("ide");
 pragmas: [],
 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){
 }, function ($methodClass){ return function (aCollection){
 var self=this,$self=this;
 var self=this,$self=this;
-var threshold,result;
+var threshold,shouldAlias;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
 //>>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);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx2) {
 return $core.withContext(function($ctx2) {
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
-$1=$recv(each)._subtreeNeedsAliasing();
-if($core.assert($1)){
-threshold=i;
-return threshold;
-}
+return $recv(each)._subtreeNeedsAliasing();
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({each:each,i:i},$ctx1,1)});
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
-}));
+}),(function(){
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.sendIdx["withIndexDo:"]=1;
+return $core.withContext(function($ctx2) {
 //>>excludeEnd("ctx");
 //>>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);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx2) {
 return $core.withContext(function($ctx2) {
 //>>excludeEnd("ctx");
 //>>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 {
 } else {
-$3=$self._visit_(each);
+return $self._visit_(each);
 }
 }
-return $recv($2)._add_($3);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({each:each,i:i},$ctx1,3)});
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,3)});
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
 }));
 }));
-return result;
+}
+catch(e) {if(e===$early)return e[0]; throw e}
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>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");
 //>>excludeEnd("ctx");
 }; }),
 }; }),
 $globals.IRASTTranslator);
 $globals.IRASTTranslator);
@@ -5905,20 +5911,19 @@ selector: "shouldBeAliased",
 protocol: "*Compiler-IR",
 protocol: "*Compiler-IR",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: [],
 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: [],
 referencedClasses: [],
 //>>excludeEnd("ide");
 //>>excludeEnd("ide");
 pragmas: [],
 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 (){
 }, function ($methodClass){ return function (){
 var self=this,$self=this;
 var self=this,$self=this;
 var sends;
 var sends;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
 //>>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);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.supercall = true,
 $ctx1.supercall = true,
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
@@ -5926,77 +5931,23 @@ $ctx1.supercall = true,
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.supercall = false;
 $ctx1.supercall = false;
 //>>excludeEnd("ctx");;
 //>>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);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"shouldBeAliased",{sends:sends})});
 }, function($ctx1) {$ctx1.fill(self,"shouldBeAliased",{sends:sends})});
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
 }; }),
 }; }),
 $globals.SendNode);
 $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,
 	The tree is iterated twice. First we get the aliasing dependency,
 	then the aliasing itself is done"
 	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
 visitAssignmentNode: aNode
@@ -1375,15 +1371,10 @@ shouldBeAliased
 	
 	
 	| sends |
 	| sends |
 	
 	
+	super shouldBeAliased ifTrue: [ ^ true ].
+	self isReferenced ifFalse: [ ^ false ].
+	self superSend ifTrue: [ ^ true ].
 	sends := (self method sendIndexes at: self selector) size.
 	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",
 protocol: "visiting",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
 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"],
 referencedClasses: ["IRSendInliner"],
 //>>excludeEnd("ide");
 //>>excludeEnd("ide");
 pragmas: [],
 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){
 }, function ($methodClass){ return function (aNode){
 var self=this,$self=this;
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
@@ -26,7 +26,6 @@ $1=$recv(aNode)._superSend();
 if(!$core.assert($1)){
 if(!$core.assert($1)){
 $2=$recv($recv($globals.IRSendInliner)._inlinedSelectors())._includes_($recv(aNode)._selector());
 $2=$recv($recv($globals.IRSendInliner)._inlinedSelectors())._includes_($recv(aNode)._selector());
 if($core.assert($2)){
 if($core.assert($2)){
-$recv(aNode)._shouldBeInlined_(true);
 $3=$recv(aNode)._receiver();
 $3=$recv(aNode)._receiver();
 if(($receiver = $3) == null || $receiver.a$nil){
 if(($receiver = $3) == null || $receiver.a$nil){
 $3;
 $3;

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

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