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 |