MessageNode.st
changeset 992 7e8ef3583a43
parent 910 eb4849c04fff
child 993 902eec8d132b
equal deleted inserted replaced
991:16411f243a75 992:7e8ef3583a43
   112      The constant folding code can usually not optimize much
   112      The constant folding code can usually not optimize much
   113      - this may change when some kind of constant/macro declaration is added to smalltalk,
   113      - this may change when some kind of constant/macro declaration is added to smalltalk,
   114      so that constant classVars can be inlined.
   114      so that constant classVars can be inlined.
   115     "
   115     "
   116     folding notNil ifTrue:[
   116     folding notNil ifTrue:[
   117 	selector := selectorString asSymbolIfInterned.
   117         selector := selectorString asSymbolIfInterned.
   118 	selector notNil ifTrue:[
   118         selector notNil ifTrue:[
   119 
   119 
   120 	    "/
   120             "/
   121 	    "/ do constant folding ...
   121             "/ do constant folding ...
   122 	    "/
   122             "/
   123 	    canFold := false.
   123             canFold := false.
   124 
   124 
   125 	    (recNode isGlobal and:[argNode isConstant]) ifTrue:[
   125             (recNode isGlobal and:[argNode isConstant]) ifTrue:[
   126 		globalName := recNode name.
   126                 globalName := recNode name.
   127 		recVal := recNode evaluate.
   127                 recVal := recNode evaluate.
   128 
   128 
   129 		(globalName = 'SmallInteger') ifTrue:[
   129                 (globalName = 'SmallInteger') ifTrue:[
   130 		    ( #( bitMaskFor: ) includes:selector)
   130                     ( #( bitMaskFor: ) includes:selector)
   131 		    ifTrue:[
   131                     ifTrue:[
   132 			canFold := true
   132                         canFold := true
   133 		    ]
   133                     ]
   134 		].
   134                 ].
   135 		(globalName = 'Float') ifTrue:[
   135             ].
   136 		    ( #( pi unity zero ) includes:selector)
   136 
   137 		    ifTrue:[
   137             (recNode isConstant and:[argNode isConstant]) ifTrue:[
   138 			(recVal respondsTo:selector) ifTrue:[
   138                 "check if we can do it ..."
   139 			    canFold := true
   139                 recVal := recNode evaluate.
   140 			]
   140                 "
   141 		    ]
   141                  we could do much more here - but then, we need a dependency from
   142 		]
   142                  the folded selectors method to the method we generate code for ...
   143 	    ].
   143                  limit optimizations to those that will never change
   144 
   144                  (or - if you change them - you will crash so bad ...)
   145 	    (recNode isConstant and:[argNode isConstant]) ifTrue:[
   145                 "
   146 		"check if we can do it ..."
   146                 argVal := argNode evaluate.
   147 		recVal := recNode evaluate.
   147                 (recVal respondsToArithmetic and:[argVal respondsToArithmetic]) ifTrue:[
   148 		"
   148                     ( #( + - * / // \\ min: max: quo:) includes:selector) ifTrue:[
   149 		 we could do much more here - but then, we need a dependency from
   149                         (#( / // \\ ) includes:selector) ifTrue:[
   150 		 the folded selectors method to the method we generate code for ...
   150                             argVal = 0 ifTrue:[
   151 		 limit optimizations to those that will never change
   151                                 ^ 'division by zero in constant expression'
   152 		 (or - if you change them - you will crash so bad ...)
   152                             ].
   153 		"
   153                         ].
   154 		argVal := argNode evaluate.
   154                         canFold := true
   155 		(recVal respondsToArithmetic and:[argVal respondsToArithmetic]) ifTrue:[
   155                     ].
   156 		    ( #( + - * / // \\ min: max: quo:) includes:selector) ifTrue:[
   156                     ( #( @ ) includes:selector) ifTrue:[
   157 			(#( / // \\ ) includes:selector) ifTrue:[
   157                         canFold := (folding == #full)
   158 			    argVal = 0 ifTrue:[
   158                     ]
   159 				^ 'division by zero in constant expression'
   159                 ].
   160 			    ].
   160                 (recVal isInteger and:[argVal isInteger]) ifTrue:[
   161 			].
   161                     ( #( bitShift: bitOr: ) includes:selector) ifTrue:[
   162 			canFold := true
   162                         canFold := true
   163 		    ].
   163                     ]
   164 		    ( #( @ ) includes:selector) ifTrue:[
   164                 ].
   165 			canFold := (folding == #full)
   165                 (recVal isMemberOf:String) ifTrue:[
   166 		    ]
   166                     (argVal isInteger and:[selector == #at:]) ifTrue:[
   167 		].
   167                         canFold := (folding >= #level2) or:[folding == #full].
   168 		(recVal isInteger and:[argVal isInteger]) ifTrue:[
   168                     ].
   169 		    ( #( bitShift: bitOr: ) includes:selector) ifTrue:[
   169                     ((argVal isMemberOf:String) and:[selector == #',']) ifTrue:[
   170 			canFold := true
   170                         canFold := (folding >= #level2) or:[folding == #full].
   171 		    ]
   171                     ]
   172 		].
   172                 ].
   173 		(recVal isMemberOf:String) ifTrue:[
   173             ].
   174 		    (argVal isInteger and:[selector == #at:]) ifTrue:[
   174 
   175 			canFold := (folding >= #level2) or:[folding == #full].
   175             canFold ifTrue:[
   176 		    ].
   176                 (recVal respondsTo:selector) ifTrue:[
   177 		    ((argVal isMemberOf:String) and:[selector == #',']) ifTrue:[
   177                     SignalSet anySignal handle:[:ex |
   178 			canFold := (folding >= #level2) or:[folding == #full].
   178                         ^ 'error in constant expression (' , ex errorString , ')'
   179 		    ]
   179                     ] do:[
   180 		].
   180                         result := recVal perform:selector with:argVal.
   181 	    ].
   181                     ].
   182 
   182                     ^ ConstantNode type:(ConstantNode typeOfConstant:result) value:result
   183 	    canFold ifTrue:[
   183                 ]
   184 		(recVal respondsTo:selector) ifTrue:[
   184             ]
   185 		    SignalSet anySignal handle:[:ex |
   185         ].
   186 			^ 'error in constant expression (' , ex errorString , ')'
   186 
   187 		    ] do:[
   187         "/
   188 			result := recVal perform:selector with:argVal.
   188         "/ #perform with a constant selector
   189 		    ].
   189         "/
   190 		    ^ ConstantNode type:(ConstantNode typeOfConstant:result) value:result
   190         (selector == #perform: 
   191 		]
   191         and:[argNode isConstant]) ifTrue:[
   192 	    ]
   192             argVal := argNode evaluate.
   193 	].
   193             argVal isSymbol ifTrue:[
   194 
   194                 ^ UnaryNode receiver:recNode selector:argVal fold:folding
   195 	"/
   195             ]
   196 	"/ #perform with a constant selector
   196         ].
   197 	"/
       
   198 	(selector == #perform: 
       
   199 	and:[argNode isConstant]) ifTrue:[
       
   200 	    argVal := argNode evaluate.
       
   201 	    argVal isSymbol ifTrue:[
       
   202 		^ UnaryNode receiver:recNode selector:argVal fold:folding
       
   203 	    ]
       
   204 	].
       
   205     ].
   197     ].
   206 
   198 
   207     ^ (self basicNew) receiver:recNode selector:selectorString args:(Array with:argNode) lineno:0
   199     ^ (self basicNew) receiver:recNode selector:selectorString args:(Array with:argNode) lineno:0
   208 
   200 
   209     "Modified: / 15.1.1998 / 15:04:27 / cg"
   201     "Modified: / 15.1.1998 / 15:04:27 / cg"
   880     |pos pos2 theReceiver theArg theByteCode optByteCode subsel code needLineNr
   872     |pos pos2 theReceiver theArg theByteCode optByteCode subsel code needLineNr
   881      needJump block1|
   873      needJump block1|
   882 
   874 
   883     theReceiver := receiver.
   875     theReceiver := receiver.
   884 
   876 
       
   877     theReceiver isConstant ifTrue:[
       
   878         (self tryFoldedIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler) ifTrue:[
       
   879             ^ self
       
   880         ].
       
   881     ].
       
   882 
   885     (theReceiver isMessage) ifTrue:[
   883     (theReceiver isMessage) ifTrue:[
   886 	subsel := theReceiver selector.
   884         subsel := theReceiver selector.
   887 	(subsel == #and:) ifTrue:[
   885         (subsel == #and:) ifTrue:[
   888 	    self codeAndIfElseOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
   886             self codeAndIfElseOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
   889 	    ^ self
   887             ^ self
   890 	].
   888         ].
   891 	(subsel == #or:) ifTrue:[
   889         (subsel == #or:) ifTrue:[
   892 	    self codeOrIfElseOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
   890             self codeOrIfElseOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
   893 	    ^ self
   891             ^ self
   894 	]
   892         ]
   895     ].
   893     ].
   896     (selector == #ifTrue:ifFalse:) ifTrue:[
   894     (selector == #ifTrue:ifFalse:) ifTrue:[
   897 	theByteCode := #falseJump
   895         theByteCode := #falseJump
   898     ] ifFalse:[
   896     ] ifFalse:[
   899 	(selector == #ifFalse:ifTrue:) ifTrue:[
   897         (selector == #ifFalse:ifTrue:) ifTrue:[
   900 	    theByteCode := #trueJump
   898             theByteCode := #trueJump
   901 	]
   899         ]
   902     ].
   900     ].
   903     optByteCode := self optimizedConditionFor:theReceiver
   901     optByteCode := self optimizedConditionFor:theReceiver
   904 					 with:theByteCode.
   902                                          with:theByteCode.
   905     optByteCode notNil ifTrue:[
   903     optByteCode notNil ifTrue:[
   906 	((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[
   904         ((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[
   907 	    theArg := theReceiver arg1
   905             theArg := theReceiver arg1
   908 	].
   906         ].
   909 	theReceiver := theReceiver receiver.
   907         theReceiver := theReceiver receiver.
   910 	theByteCode := optByteCode
   908         theByteCode := optByteCode
   911     ].
   909     ].
   912     theByteCode notNil ifTrue:[
   910     theByteCode notNil ifTrue:[
   913 	theReceiver codeOn:aStream inBlock:b for:aCompiler.
   911         theReceiver codeOn:aStream inBlock:b for:aCompiler.
   914 
   912 
   915 	needLineNr := true.
   913         needLineNr := true.
   916 	theArg isNil ifTrue:[
   914         theArg isNil ifTrue:[
   917 	    theReceiver isMessage ifTrue:[
   915             theReceiver isMessage ifTrue:[
   918 		(aCompiler hasLineNumber:(theReceiver selector)) ifTrue:[
   916                 (aCompiler hasLineNumber:(theReceiver selector)) ifTrue:[
   919 		    theReceiver lineNumber == lineNr ifTrue:[
   917                     theReceiver lineNumber == lineNr ifTrue:[
   920 			needLineNr := false
   918                         needLineNr := false
   921 		    ]
   919                     ]
   922 		]
   920                 ]
   923 	    ]
   921             ]
   924 	] ifFalse:[
   922         ] ifFalse:[
   925 	    theArg codeOn:aStream inBlock:b for:aCompiler
   923             theArg codeOn:aStream inBlock:b for:aCompiler
   926 	].
   924         ].
   927 
   925 
   928 	needLineNr ifTrue:[
   926         needLineNr ifTrue:[
   929 	    (lineNr between:1 and:255) ifTrue:[
   927             (lineNr between:1 and:255) ifTrue:[
   930 		aStream nextPut:#lineno; nextPut:lineNr.
   928                 aStream nextPut:#lineno; nextPut:lineNr.
   931 	    ]
   929             ]
   932 	].
   930         ].
   933 
   931 
   934 	aStream nextPut:theByteCode.
   932         aStream nextPut:theByteCode.
   935 	pos := aStream position.
   933         pos := aStream position.
   936 	aStream nextPut:0.
   934         aStream nextPut:0.
   937 	block1 := argArray at:1.
   935         block1 := argArray at:1.
   938 	block1 codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
   936         block1 codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
   939 	needJump := true.
   937         needJump := true.
   940 	(block1 isBlock and:[block1 endsWithReturn]) ifTrue:[
   938         (block1 isBlock and:[block1 endsWithReturn]) ifTrue:[
   941 	    needJump := false
   939             needJump := false
   942 	].
   940         ].
   943 	needJump ifTrue:[
   941         needJump ifTrue:[
   944 	    aStream nextPut:#jump.
   942             aStream nextPut:#jump.
   945 	    pos2 := aStream position.
   943             pos2 := aStream position.
   946 	    aStream nextPut:0.
   944             aStream nextPut:0.
   947 	].
   945         ].
   948 	code := aStream contents.
   946         code := aStream contents.
   949 	code at:pos put:(aStream position).
   947         code at:pos put:(aStream position).
   950 	(argArray at:2) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
   948         (argArray at:2) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
   951 	needJump ifTrue:[
   949         needJump ifTrue:[
   952 	    code at:pos2 put:(aStream position)
   950             code at:pos2 put:(aStream position)
   953 	]
   951         ]
   954     ]
   952     ]
   955 
   953 
   956     "Modified: 9.11.1996 / 19:53:52 / cg"
   954     "Modified: 9.11.1996 / 19:53:52 / cg"
   957 !
   955 !
   958 
   956 
  1072     |pos pos2 theReceiver theArg theByteCode optByteCode subsel code
  1070     |pos pos2 theReceiver theArg theByteCode optByteCode subsel code
  1073      needLineNr|
  1071      needLineNr|
  1074 
  1072 
  1075     theReceiver := receiver.
  1073     theReceiver := receiver.
  1076 
  1074 
       
  1075     theReceiver isConstant ifTrue:[
       
  1076         (self tryFoldedIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler) ifTrue:[
       
  1077             ^ self
       
  1078         ].
       
  1079     ].
       
  1080 
  1077     (theReceiver isMessage) ifTrue:[
  1081     (theReceiver isMessage) ifTrue:[
  1078 	subsel := theReceiver selector.
  1082         subsel := theReceiver selector.
  1079 
  1083 
  1080 	(subsel == #and:) ifTrue:[
  1084         (subsel == #and:) ifTrue:[
  1081 	    theReceiver arg1 isBlock ifTrue:[
  1085             theReceiver arg1 isBlock ifTrue:[
  1082 		self codeAndIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
  1086                 self codeAndIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
  1083 		^ self
  1087                 ^ self
  1084 	    ]
  1088             ]
  1085 	].
  1089         ].
  1086 	(subsel == #or:) ifTrue:[
  1090         (subsel == #or:) ifTrue:[
  1087 	    theReceiver arg1 isBlock ifTrue:[
  1091             theReceiver arg1 isBlock ifTrue:[
  1088 		self codeOrIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
  1092                 self codeOrIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
  1089 		^ self
  1093                 ^ self
  1090 	    ]
  1094             ]
  1091 	].
  1095         ].
  1092     ].
  1096     ].
  1093     (selector == #ifTrue:) ifTrue:[
  1097     (selector == #ifTrue:) ifTrue:[
  1094 	theByteCode := #falseJump
  1098         theByteCode := #falseJump
  1095     ] ifFalse:[
  1099     ] ifFalse:[
  1096 	theByteCode := #trueJump
  1100         theByteCode := #trueJump
  1097     ].
  1101     ].
  1098     optByteCode := self optimizedConditionFor:theReceiver
  1102     optByteCode := self optimizedConditionFor:theReceiver
  1099 					 with:theByteCode.
  1103                                          with:theByteCode.
  1100     optByteCode notNil ifTrue:[
  1104     optByteCode notNil ifTrue:[
  1101 	((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[
  1105         ((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[
  1102 	    theArg := theReceiver arg1
  1106             theArg := theReceiver arg1
  1103 	].
  1107         ].
  1104 	theReceiver := theReceiver receiver.
  1108         theReceiver := theReceiver receiver.
  1105 	theByteCode := optByteCode
  1109         theByteCode := optByteCode
  1106     ].
  1110     ].
  1107 
  1111 
  1108     theReceiver codeOn:aStream inBlock:b for:aCompiler.
  1112     theReceiver codeOn:aStream inBlock:b for:aCompiler.
  1109     theArg notNil ifTrue:[
  1113     theArg notNil ifTrue:[
  1110 	theArg codeOn:aStream inBlock:b for:aCompiler
  1114         theArg codeOn:aStream inBlock:b for:aCompiler
  1111     ].
  1115     ].
  1112 
  1116 
  1113     needLineNr := true.
  1117     needLineNr := true.
  1114     theArg isNil ifTrue:[
  1118     theArg isNil ifTrue:[
  1115 	theReceiver isMessage ifTrue:[
  1119         theReceiver isMessage ifTrue:[
  1116 	    (aCompiler hasLineNumber:(theReceiver selector)) ifTrue:[
  1120             (aCompiler hasLineNumber:(theReceiver selector)) ifTrue:[
  1117 		theReceiver lineNumber == lineNr ifTrue:[
  1121                 theReceiver lineNumber == lineNr ifTrue:[
  1118 		    needLineNr := false
  1122                     needLineNr := false
  1119 		]
  1123                 ]
  1120 	    ]
  1124             ]
  1121 	]
  1125         ]
  1122     ].
  1126     ].
  1123 
  1127 
  1124     needLineNr ifTrue:[
  1128     needLineNr ifTrue:[
  1125 	(lineNr between:1 and:255) ifTrue:[
  1129         (lineNr between:1 and:255) ifTrue:[
  1126 	    aStream nextPut:#lineno; nextPut:lineNr.
  1130             aStream nextPut:#lineno; nextPut:lineNr.
  1127 	]
  1131         ]
  1128     ].
  1132     ].
  1129 
  1133 
  1130     aStream nextPut:theByteCode.
  1134     aStream nextPut:theByteCode.
  1131     pos := aStream position.
  1135     pos := aStream position.
  1132     aStream nextPut:0.
  1136     aStream nextPut:0.
  1133     (argArray at: 1) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
  1137     (argArray at: 1) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
  1134 
  1138 
  1135     code := aStream contents.
  1139     code := aStream contents.
  1136     valueNeeded ifTrue:[
  1140     valueNeeded ifTrue:[
  1137 	aStream nextPut:#jump.
  1141         aStream nextPut:#jump.
  1138 	pos2 := aStream position.
  1142         pos2 := aStream position.
  1139 	aStream nextPut:0.
  1143         aStream nextPut:0.
  1140 	code at:pos put:(aStream position).
  1144         code at:pos put:(aStream position).
  1141 	aStream nextPut:#pushNil.
  1145         aStream nextPut:#pushNil.
  1142 	code at:pos2 put:(aStream position)
  1146         code at:pos2 put:(aStream position)
  1143     ] ifFalse:[
  1147     ] ifFalse:[
  1144 	code at:pos put:(aStream position)
  1148         code at:pos put:(aStream position)
  1145     ]
  1149     ]
  1146 
  1150 
  1147     "Modified: / 28.10.1997 / 18:33:42 / cg"
  1151     "Modified: / 28.10.1997 / 18:33:42 / cg"
  1148 !
  1152 !
  1149 
  1153 
  2510 	    (aByteCode == #falseJump) ifTrue:[^ #eqJump].
  2514 	    (aByteCode == #falseJump) ifTrue:[^ #eqJump].
  2511 	    (aByteCode == #trueJump) ifTrue:[^ #notEqJump]
  2515 	    (aByteCode == #trueJump) ifTrue:[^ #notEqJump]
  2512 	]
  2516 	]
  2513     ].
  2517     ].
  2514     ^ nil
  2518     ^ nil
       
  2519 !
       
  2520 
       
  2521 tryFoldedIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
       
  2522     |rVal branch|
       
  2523 
       
  2524     receiver isConstant ifTrue:[
       
  2525         rVal := receiver evaluate.
       
  2526         rVal == true ifTrue:[
       
  2527             ((selector == #ifTrue:) or:[selector == #ifTrue:ifFalse:]) ifTrue:[
       
  2528                 branch := (argArray at: 1).
       
  2529             ].
       
  2530             (selector == #ifFalse:ifTrue:) ifTrue:[
       
  2531                 branch := (argArray at: 2).
       
  2532             ].
       
  2533             (selector == #ifFalse:) ifTrue:[
       
  2534                 ^ true.
       
  2535             ].
       
  2536         ].
       
  2537         rVal == false ifTrue:[
       
  2538             ((selector == #ifFalse:) or:[selector == #ifFalse:ifTrue:]) ifTrue:[
       
  2539                 branch := (argArray at: 1).
       
  2540             ].
       
  2541             (selector == #ifTrue:ifFalse:) ifTrue:[
       
  2542                 branch := (argArray at: 2).
       
  2543             ].
       
  2544             (selector == #ifTrue:) ifTrue:[
       
  2545                 ^ true.
       
  2546             ].
       
  2547         ].
       
  2548         branch notNil ifTrue:[
       
  2549             branch codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
       
  2550             ^ true.
       
  2551         ]
       
  2552     ].
       
  2553     ^ false
       
  2554 
  2515 ! !
  2555 ! !
  2516 
  2556 
  2517 !MessageNode methodsFor:'enumeration'!
  2557 !MessageNode methodsFor:'enumeration'!
  2518 
  2558 
  2519 nodeDo:anEnumerator
  2559 nodeDo:anEnumerator
  2747 ! !
  2787 ! !
  2748 
  2788 
  2749 !MessageNode class methodsFor:'documentation'!
  2789 !MessageNode class methodsFor:'documentation'!
  2750 
  2790 
  2751 version
  2791 version
  2752     ^ '$Header: /cvs/stx/stx/libcomp/MessageNode.st,v 1.104 1999-07-15 11:16:37 cg Exp $'
  2792     ^ '$Header: /cvs/stx/stx/libcomp/MessageNode.st,v 1.105 1999-11-09 09:35:56 cg Exp $'
  2753 ! !
  2793 ! !