Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(321)

Side by Side Diff: frog/leg/ssa/nodes.dart

Issue 9595017: Refactor constant part. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: More comment addressing. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « frog/leg/ssa/codegen.dart ('k') | frog/leg/ssa/optimize.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 interface HVisitor<R> { 5 interface HVisitor<R> {
6 R visitAdd(HAdd node); 6 R visitAdd(HAdd node);
7 R visitBailoutTarget(HBailoutTarget node); 7 R visitBailoutTarget(HBailoutTarget node);
8 R visitBitAnd(HBitAnd node); 8 R visitBitAnd(HBitAnd node);
9 R visitBitNot(HBitNot node); 9 R visitBitNot(HBitNot node);
10 R visitBitOr(HBitOr node); 10 R visitBitOr(HBitOr node);
11 R visitBitXor(HBitXor node); 11 R visitBitXor(HBitXor node);
12 R visitBoolify(HBoolify node); 12 R visitBoolify(HBoolify node);
13 R visitBoundsCheck(HBoundsCheck node); 13 R visitBoundsCheck(HBoundsCheck node);
14 R visitBreak(HBreak node); 14 R visitBreak(HBreak node);
15 R visitConstant(HConstant node);
15 R visitDivide(HDivide node); 16 R visitDivide(HDivide node);
16 R visitEquals(HEquals node); 17 R visitEquals(HEquals node);
17 R visitExit(HExit node); 18 R visitExit(HExit node);
18 R visitFieldGet(HFieldGet node); 19 R visitFieldGet(HFieldGet node);
19 R visitFieldSet(HFieldSet node); 20 R visitFieldSet(HFieldSet node);
20 R visitForeign(HForeign node); 21 R visitForeign(HForeign node);
21 R visitForeignNew(HForeignNew); 22 R visitForeignNew(HForeignNew);
22 R visitGoto(HGoto node); 23 R visitGoto(HGoto node);
23 R visitGreater(HGreater node); 24 R visitGreater(HGreater node);
24 R visitGreaterEqual(HGreaterEqual node); 25 R visitGreaterEqual(HGreaterEqual node);
25 R visitIdentity(HIdentity node); 26 R visitIdentity(HIdentity node);
26 R visitIf(HIf node); 27 R visitIf(HIf node);
27 R visitIndex(HIndex node); 28 R visitIndex(HIndex node);
28 R visitIndexAssign(HIndexAssign node); 29 R visitIndexAssign(HIndexAssign node);
29 R visitIntegerCheck(HIntegerCheck node); 30 R visitIntegerCheck(HIntegerCheck node);
30 R visitInvokeClosure(HInvokeClosure node); 31 R visitInvokeClosure(HInvokeClosure node);
31 R visitInvokeDynamicGetter(HInvokeDynamicGetter node); 32 R visitInvokeDynamicGetter(HInvokeDynamicGetter node);
32 R visitInvokeDynamicMethod(HInvokeDynamicMethod node); 33 R visitInvokeDynamicMethod(HInvokeDynamicMethod node);
33 R visitInvokeDynamicSetter(HInvokeDynamicSetter node); 34 R visitInvokeDynamicSetter(HInvokeDynamicSetter node);
34 R visitInvokeInterceptor(HInvokeInterceptor node); 35 R visitInvokeInterceptor(HInvokeInterceptor node);
35 R visitInvokeStatic(HInvokeStatic node); 36 R visitInvokeStatic(HInvokeStatic node);
36 R visitInvokeSuper(HInvokeSuper node); 37 R visitInvokeSuper(HInvokeSuper node);
37 R visitIs(HIs node); 38 R visitIs(HIs node);
38 R visitLess(HLess node); 39 R visitLess(HLess node);
39 R visitLessEqual(HLessEqual node); 40 R visitLessEqual(HLessEqual node);
40 R visitLiteral(HLiteral node);
41 R visitLiteralList(HLiteralList node); 41 R visitLiteralList(HLiteralList node);
42 R visitLoad(HLoad node); 42 R visitLoad(HLoad node);
43 R visitLocal(HLocal node); 43 R visitLocal(HLocal node);
44 R visitLogicalOperator(HLogicalOperator node); 44 R visitLogicalOperator(HLogicalOperator node);
45 R visitLoopBranch(HLoopBranch node); 45 R visitLoopBranch(HLoopBranch node);
46 R visitModulo(HModulo node); 46 R visitModulo(HModulo node);
47 R visitMultiply(HMultiply node); 47 R visitMultiply(HMultiply node);
48 R visitNegate(HNegate node); 48 R visitNegate(HNegate node);
49 R visitNot(HNot node); 49 R visitNot(HNot node);
50 R visitParameterValue(HParameterValue node); 50 R visitParameterValue(HParameterValue node);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 currentBlock = node; 109 currentBlock = node;
110 visitInstructionList(node); 110 visitInstructionList(node);
111 } 111 }
112 } 112 }
113 113
114 class HGraph { 114 class HGraph {
115 HBasicBlock entry; 115 HBasicBlock entry;
116 HBasicBlock exit; 116 HBasicBlock exit;
117 final List<HBasicBlock> blocks; 117 final List<HBasicBlock> blocks;
118 118
119 // We canonicalize all literals used within a graph so we do not 119 // We canonicalize all constants used within a graph so we do not
120 // have to worry about them for global value numbering. 120 // have to worry about them for global value numbering.
121 HLiteral nullLiteral; 121 Map<Constant, HConstant> constants;
122 HLiteral trueLiteral;
123 HLiteral falseLiteral;
124 HLiteral nanLiteral;
125 HLiteral negativeZeroLiteral;
126 Map<int, HLiteral> intLiterals;
127 Map<double, HLiteral> doubleLiterals;
128 Map<num, HLiteral> numLiterals;
129 Map<String, HLiteral> stringLiterals;
130 122
131 HGraph() : blocks = new List<HBasicBlock>() { 123 HGraph()
124 : blocks = new List<HBasicBlock>(),
125 constants = new Map<Constant, HConstant>() {
132 entry = addNewBlock(); 126 entry = addNewBlock();
133 // The exit block will be added later, so it has an id that is 127 // The exit block will be added later, so it has an id that is
134 // after all others in the system. 128 // after all others in the system.
135 exit = new HBasicBlock(); 129 exit = new HBasicBlock();
136 } 130 }
137 131
138 void addBlock(HBasicBlock block) { 132 void addBlock(HBasicBlock block) {
139 int id = blocks.length; 133 int id = blocks.length;
140 block.id = id; 134 block.id = id;
141 blocks.add(block); 135 blocks.add(block);
142 assert(blocks[id] === block); 136 assert(blocks[id] === block);
143 } 137 }
144 138
145 HBasicBlock addNewBlock() { 139 HBasicBlock addNewBlock() {
146 HBasicBlock result = new HBasicBlock(); 140 HBasicBlock result = new HBasicBlock();
147 addBlock(result); 141 addBlock(result);
148 return result; 142 return result;
149 } 143 }
150 144
151 HBasicBlock addNewLoopHeaderBlock(List<SourceString> labels) { 145 HBasicBlock addNewLoopHeaderBlock(List<SourceString> labels) {
152 HBasicBlock result = addNewBlock(); 146 HBasicBlock result = addNewBlock();
153 result.loopInformation = new HLoopInformation(result, labels); 147 result.loopInformation = new HLoopInformation(result, labels);
154 return result; 148 return result;
155 } 149 }
156 150
157 HLiteral addNewLiteralInt(int value) { 151 static HType mapConstantTypeToSsaType(Constant constant) {
158 if (intLiterals === null) intLiterals = new Map<int, HLiteral>(); 152 if (constant.isNull()) return HType.UNKNOWN;
159 HLiteral result = intLiterals[value]; 153 if (constant.isBool()) return HType.BOOLEAN;
154 if (constant.isInt()) return HType.INTEGER;
155 if (constant.isDouble()) return HType.DOUBLE;
156 if (constant.isString()) return HType.STRING;
157 if (constant.isList()) return HType.ARRAY;
158 return HType.UNKNOWN;
159 }
160
161 HConstant addConstant(Constant constant) {
162 HConstant result = constants[constant];
160 if (result === null) { 163 if (result === null) {
161 result = new HLiteral.internal(value, HType.INTEGER); 164 HType type = mapConstantTypeToSsaType(constant);
165 result = new HConstant.internal(constant, type);
162 entry.addAtExit(result); 166 entry.addAtExit(result);
163 intLiterals[value] = result; 167 constants[constant] = result;
164 } 168 }
165 return result; 169 return result;
166 } 170 }
167 171
168 HLiteral addNewLiteralNaN() { 172 HConstant addConstantInt(int i) {
169 if (nanLiteral === null) { 173 return addConstant(new IntConstant(i));
170 nanLiteral = new HLiteral.internal(double.NAN, HType.DOUBLE);
171 entry.addAtExit(nanLiteral);
172 }
173 return nanLiteral;
174 } 174 }
175 175
176 HLiteral addNewNegativeZeroLiteral() { 176 HConstant addConstantDouble(int d) {
177 if (negativeZeroLiteral === null) { 177 return addConstant(new DoubleConstant(d));
178 negativeZeroLiteral = new HLiteral.internal(-0.0, HType.DOUBLE);
179 entry.addAtExit(negativeZeroLiteral);
180 }
181 return negativeZeroLiteral;
182 } 178 }
183 179
184 HLiteral addNewLiteralDouble(double value) { 180 HConstant addConstantString(DartString str) {
185 if (value.isNaN()) return addNewLiteralNaN(); // Avoid hashing NaN. 181 return addConstant(new StringConstant(str));
186 if (value == 0 && value.isNegative()) {
187 // Avoid hashing -0.0 as it compares equal to 0.0.
188 return addNewNegativeZeroLiteral();
189 }
190 if (doubleLiterals === null) doubleLiterals = new Map<double, HLiteral>();
191 HLiteral result = doubleLiterals[value];
192 if (result === null) {
193 result = new HLiteral.internal(value, HType.DOUBLE);
194 entry.addAtExit(result);
195 doubleLiterals[value] = result;
196 }
197 return result;
198 } 182 }
199 183
200 HLiteral addNewLiteralNum(num value, HType type) { 184 HConstant addConstantBool(bool value) {
201 // If we've propagated type information then the type must be a 185 return addConstant(new BoolConstant(value));
202 // number or in conflict, but when we turn off speculative
203 // optimization the type may be unknown. In any case, we make it a
204 // number from this point forward.
205 assert(type.isUnknown() || type.isConflicting() || type.isNumber());
206 if (type.isInteger()) return addNewLiteralInt(value);
207 if (type.isDouble() || value.isNaN()) return addNewLiteralDouble(value);
208 // Probe our literals map and add a new number literal if necessary.
209 if (numLiterals === null) numLiterals = new Map<num, HLiteral>();
210 HLiteral result = numLiterals[value];
211 if (result === null) {
212 result = new HLiteral.internal(value, HType.NUMBER);
213 entry.addAtExit(result);
214 numLiterals[value] = result;
215 }
216 return result;
217 } 186 }
218 187
219 HLiteral addNewLiteralTrue() { 188 HConstant addConstantNull() {
220 if (trueLiteral === null) { 189 return addConstant(const NullConstant());
221 trueLiteral = new HLiteral.internal(true, HType.BOOLEAN);
222 entry.addAtExit(trueLiteral);
223 }
224 return trueLiteral;
225 }
226
227 HLiteral addNewLiteralFalse() {
228 if (falseLiteral === null) {
229 falseLiteral = new HLiteral.internal(false, HType.BOOLEAN);
230 entry.addAtExit(falseLiteral);
231 }
232 return falseLiteral;
233 }
234
235 HLiteral addNewLiteralBool(bool value) {
236 return value ? addNewLiteralTrue() : addNewLiteralFalse();
237 }
238
239 HLiteral addNewLiteralString(DartString value) {
240 if (stringLiterals === null) stringLiterals = new Map<String, HLiteral>();
241 String key = value.toString(); // We need something hashable.
242 HLiteral result = stringLiterals[key];
243 if (result === null) {
244 result = new HLiteral.internal(value, HType.STRING);
245 entry.addAtExit(result);
246 stringLiterals[key] = result;
247 }
248 return result;
249 }
250
251 HLiteral addNewLiteralNull() {
252 if (nullLiteral === null) {
253 nullLiteral = new HLiteral.internal(null, HType.UNKNOWN);
254 entry.addAtExit(nullLiteral);
255 }
256 return nullLiteral;
257 } 190 }
258 191
259 void finalize() { 192 void finalize() {
260 addBlock(exit); 193 addBlock(exit);
261 exit.open(); 194 exit.open();
262 exit.close(new HExit()); 195 exit.close(new HExit());
263 assignDominators(); 196 assignDominators();
264 } 197 }
265 198
266 void assignDominators() { 199 void assignDominators() {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 visitAdd(HAdd node) => visitBinaryArithmetic(node); 250 visitAdd(HAdd node) => visitBinaryArithmetic(node);
318 visitBitAnd(HBitAnd node) => visitBinaryBitOp(node); 251 visitBitAnd(HBitAnd node) => visitBinaryBitOp(node);
319 visitBitNot(HBitNot node) => visitInvokeUnary(node); 252 visitBitNot(HBitNot node) => visitInvokeUnary(node);
320 visitBitOr(HBitOr node) => visitBinaryBitOp(node); 253 visitBitOr(HBitOr node) => visitBinaryBitOp(node);
321 visitBitXor(HBitXor node) => visitBinaryBitOp(node); 254 visitBitXor(HBitXor node) => visitBinaryBitOp(node);
322 visitBailoutTarget(HBailoutTarget node) => visitInstruction(node); 255 visitBailoutTarget(HBailoutTarget node) => visitInstruction(node);
323 visitBoolify(HBoolify node) => visitInstruction(node); 256 visitBoolify(HBoolify node) => visitInstruction(node);
324 visitBoundsCheck(HBoundsCheck node) => visitCheck(node); 257 visitBoundsCheck(HBoundsCheck node) => visitCheck(node);
325 visitBreak(HBreak node) => visitGoto(node); 258 visitBreak(HBreak node) => visitGoto(node);
326 visitCheck(HCheck node) => visitInstruction(node); 259 visitCheck(HCheck node) => visitInstruction(node);
260 visitConstant(HConstant node) => visitInstruction(node);
327 visitDivide(HDivide node) => visitBinaryArithmetic(node); 261 visitDivide(HDivide node) => visitBinaryArithmetic(node);
328 visitEquals(HEquals node) => visitRelational(node); 262 visitEquals(HEquals node) => visitRelational(node);
329 visitExit(HExit node) => visitControlFlow(node); 263 visitExit(HExit node) => visitControlFlow(node);
330 visitFieldGet(HFieldGet node) => visitInstruction(node); 264 visitFieldGet(HFieldGet node) => visitInstruction(node);
331 visitFieldSet(HFieldSet node) => visitInstruction(node); 265 visitFieldSet(HFieldSet node) => visitInstruction(node);
332 visitForeign(HForeign node) => visitInstruction(node); 266 visitForeign(HForeign node) => visitInstruction(node);
333 visitForeignNew(HForeignNew node) => visitForeign(node); 267 visitForeignNew(HForeignNew node) => visitForeign(node);
334 visitGoto(HGoto node) => visitControlFlow(node); 268 visitGoto(HGoto node) => visitControlFlow(node);
335 visitGreater(HGreater node) => visitRelational(node); 269 visitGreater(HGreater node) => visitRelational(node);
336 visitGreaterEqual(HGreaterEqual node) => visitRelational(node); 270 visitGreaterEqual(HGreaterEqual node) => visitRelational(node);
(...skipping 12 matching lines...) Expand all
349 => visitInvokeDynamicField(node); 283 => visitInvokeDynamicField(node);
350 visitInvokeInterceptor(HInvokeInterceptor node) 284 visitInvokeInterceptor(HInvokeInterceptor node)
351 => visitInvokeStatic(node); 285 => visitInvokeStatic(node);
352 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node); 286 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node);
353 visitInvokeSuper(HInvokeSuper node) => visitInvoke(node); 287 visitInvokeSuper(HInvokeSuper node) => visitInvoke(node);
354 visitLess(HLess node) => visitRelational(node); 288 visitLess(HLess node) => visitRelational(node);
355 visitLessEqual(HLessEqual node) => visitRelational(node); 289 visitLessEqual(HLessEqual node) => visitRelational(node);
356 visitLoad(HLoad node) => visitInstruction(node); 290 visitLoad(HLoad node) => visitInstruction(node);
357 visitLocal(HLocal node) => visitInstruction(node); 291 visitLocal(HLocal node) => visitInstruction(node);
358 visitLogicalOperator(HLogicalOperator node) => visitInstruction(node); 292 visitLogicalOperator(HLogicalOperator node) => visitInstruction(node);
359 visitLiteral(HLiteral node) => visitInstruction(node);
360 visitLiteralList(HLiteralList node) => visitInstruction(node); 293 visitLiteralList(HLiteralList node) => visitInstruction(node);
361 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node); 294 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node);
362 visitModulo(HModulo node) => visitBinaryArithmetic(node); 295 visitModulo(HModulo node) => visitBinaryArithmetic(node);
363 visitNegate(HNegate node) => visitInvokeUnary(node); 296 visitNegate(HNegate node) => visitInvokeUnary(node);
364 visitNot(HNot node) => visitInstruction(node); 297 visitNot(HNot node) => visitInstruction(node);
365 visitPhi(HPhi node) => visitInstruction(node); 298 visitPhi(HPhi node) => visitInstruction(node);
366 visitMultiply(HMultiply node) => visitBinaryArithmetic(node); 299 visitMultiply(HMultiply node) => visitBinaryArithmetic(node);
367 visitParameterValue(HParameterValue node) => visitInstruction(node); 300 visitParameterValue(HParameterValue node) => visitInstruction(node);
368 visitReturn(HReturn node) => visitControlFlow(node); 301 visitReturn(HReturn node) => visitControlFlow(node);
369 visitShiftRight(HShiftRight node) => visitBinaryBitOp(node); 302 visitShiftRight(HShiftRight node) => visitBinaryBitOp(node);
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 inputUsedBy[j] = inputUsedBy[inputUsedBy.length - 1]; 931 inputUsedBy[j] = inputUsedBy[inputUsedBy.length - 1];
999 inputUsedBy.removeLast(); 932 inputUsedBy.removeLast();
1000 break; 933 break;
1001 } 934 }
1002 } 935 }
1003 } 936 }
1004 this.block = null; 937 this.block = null;
1005 assert(isValid()); 938 assert(isValid());
1006 } 939 }
1007 940
1008 bool isLiteralNull() => false; 941 bool isConstantNull() => false;
1009 bool isLiteralNumber() => false; 942 bool isConstantNumber() => false;
1010 bool isLiteralString() => false; 943 bool isConstantString() => false;
1011 944
1012 bool isValid() { 945 bool isValid() {
1013 HValidator validator = new HValidator(); 946 HValidator validator = new HValidator();
1014 validator.currentBlock = block; 947 validator.currentBlock = block;
1015 validator.visitInstruction(this); 948 validator.visitInstruction(this);
1016 return validator.isValid; 949 return validator.isValid;
1017 } 950 }
1018 } 951 }
1019 952
1020 class HBoolify extends HInstruction { 953 class HBoolify extends HInstruction {
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
1262 || name == const SourceString('removeLast')) { 1195 || name == const SourceString('removeLast')) {
1263 return HType.ARRAY; 1196 return HType.ARRAY;
1264 } 1197 }
1265 } 1198 }
1266 return HType.UNKNOWN; 1199 return HType.UNKNOWN;
1267 } 1200 }
1268 1201
1269 bool hasExpectedType() => builtinJsName != null; 1202 bool hasExpectedType() => builtinJsName != null;
1270 1203
1271 HInstruction fold(HGraph graph) { 1204 HInstruction fold(HGraph graph) {
1272 if (name == const SourceString('length') && inputs[1].isLiteralString()) { 1205 if (name == const SourceString('length') && inputs[1].isConstantString()) {
1273 HLiteral input = inputs[1]; 1206 HConstant input = inputs[1];
1274 DartString string = input.value; 1207 DartString string = input.constant.value;
1275 return graph.addNewLiteralInt(string.length); 1208 return graph.addConstantInt(string.length);
1276 } 1209 }
1277 return this; 1210 return this;
1278 } 1211 }
1279 1212
1280 void prepareGvn() { 1213 void prepareGvn() {
1281 if (builtinJsName == 'length') { 1214 if (builtinJsName == 'length') {
1282 assert(!hasSideEffects()); 1215 assert(!hasSideEffects());
1283 } else { 1216 } else {
1284 setAllSideEffects(); 1217 setAllSideEffects();
1285 } 1218 }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1360 1293
1361 HType computeInputsType() { 1294 HType computeInputsType() {
1362 HType leftType = left.type; 1295 HType leftType = left.type;
1363 HType rightType = right.type; 1296 HType rightType = right.type;
1364 if (leftType.isUnknown() || rightType.isUnknown()) { 1297 if (leftType.isUnknown() || rightType.isUnknown()) {
1365 return HType.UNKNOWN; 1298 return HType.UNKNOWN;
1366 } 1299 }
1367 return leftType.combine(rightType); 1300 return leftType.combine(rightType);
1368 } 1301 }
1369 1302
1370 abstract HInstruction fold(HGraph graph); 1303 HInstruction fold(HGraph graph) {
1371 abstract evaluate(num a, num b); 1304 if (left is HConstant && right is HConstant) {
1305 HConstant op1 = left;
1306 HConstant op2 = right;
1307 Constant folded =
1308 op1.constant.binaryFold(operationAsString(), op2.constant);
1309 if (folded !== null) return graph.addConstant(folded);
1310 }
1311 return this;
1312 }
1313 abstract String operationAsString();
1372 } 1314 }
1373 1315
1374 class HBinaryArithmetic extends HInvokeBinary { 1316 class HBinaryArithmetic extends HInvokeBinary {
1375 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right) 1317 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right)
1376 : super(target, left, right); 1318 : super(target, left, right);
1377 1319
1378 void prepareGvn() { 1320 void prepareGvn() {
1379 // An arithmetic expression can take part in global value 1321 // An arithmetic expression can take part in global value
1380 // numbering and do not have any side-effects if we know that all 1322 // numbering and do not have any side-effects if we know that all
1381 // inputs are numbers. 1323 // inputs are numbers.
1382 if (builtin) { 1324 if (builtin) {
1383 assert(!hasSideEffects()); 1325 assert(!hasSideEffects());
1384 setUseGvn(); 1326 setUseGvn();
1385 } else { 1327 } else {
1386 setAllSideEffects(); 1328 setAllSideEffects();
1387 } 1329 }
1388 } 1330 }
1389 1331
1390 HInstruction fold(HGraph graph) {
1391 if (left.isLiteralNumber() && right.isLiteralNumber()) {
1392 HLiteral op1 = left;
1393 HLiteral op2 = right;
1394 return graph.addNewLiteralNum(evaluate(op1.value, op2.value), type);
1395 }
1396 return this;
1397 }
1398
1399 HType computeType() { 1332 HType computeType() {
1400 HType type = computeInputsType(); 1333 HType type = computeInputsType();
1401 builtin = type.isNumber(); 1334 builtin = type.isNumber();
1402 if (!type.isUnknown()) return type; 1335 if (!type.isUnknown()) return type;
1403 if (left.isNumber()) return HType.NUMBER; 1336 if (left.isNumber()) return HType.NUMBER;
1404 return HType.UNKNOWN; 1337 return HType.UNKNOWN;
1405 } 1338 }
1406 1339
1407 HType computeDesiredInputType(HInstruction input) { 1340 HType computeDesiredInputType(HInstruction input) {
1408 // TODO(floitsch): we want the target to be a function. 1341 // TODO(floitsch): we want the target to be a function.
1409 if (input == target) return HType.UNKNOWN; 1342 if (input == target) return HType.UNKNOWN;
1410 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER; 1343 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER;
1411 if (type.isUnknown()) return HType.NUMBER; 1344 if (type.isUnknown()) return HType.NUMBER;
1412 return HType.UNKNOWN; 1345 return HType.UNKNOWN;
1413 } 1346 }
1414 1347
1415 bool hasExpectedType() => builtin || type.isUnknown(); 1348 bool hasExpectedType() => builtin || type.isUnknown();
1416
1417 abstract num evaluate(num a, num b);
1418 } 1349 }
1419 1350
1420 class HAdd extends HBinaryArithmetic { 1351 class HAdd extends HBinaryArithmetic {
1421 HAdd(HStatic target, HInstruction left, HInstruction right) 1352 HAdd(HStatic target, HInstruction left, HInstruction right)
1422 : super(target, left, right); 1353 : super(target, left, right);
1423 accept(HVisitor visitor) => visitor.visitAdd(this); 1354 accept(HVisitor visitor) => visitor.visitAdd(this);
1424 num evaluate(num a, num b) => a + b;
1425 int typeCode() => 5;
1426 bool typeEquals(other) => other is HAdd;
1427 bool dataEquals(HInstruction other) => true;
1428 1355
1429 HType computeType() { 1356 HType computeType() {
1430 HType type = computeInputsType(); 1357 HType type = computeInputsType();
1431 builtin = (type.isNumber() || type.isString()); 1358 builtin = (type.isNumber() || type.isString());
1432 if (type.isConflicting() && left.isString()) { 1359 if (type.isConflicting() && left.isString()) {
1433 builtin = right is HLiteral; 1360 builtin = right is HConstant;
1434 return HType.STRING; 1361 return HType.STRING;
1435 } 1362 }
1436 if (!type.isUnknown()) return type; 1363 if (!type.isUnknown()) return type;
1437 if (left.isNumber()) return HType.NUMBER; 1364 if (left.isNumber()) return HType.NUMBER;
1438 return HType.UNKNOWN; 1365 return HType.UNKNOWN;
1439 } 1366 }
1440 1367
1441 bool hasExpectedType() => builtin || type.isUnknown() || left.isString(); 1368 bool hasExpectedType() => builtin || type.isUnknown() || left.isString();
1442 1369
1443 HType computeDesiredInputType(HInstruction input) { 1370 HType computeDesiredInputType(HInstruction input) {
1444 // TODO(floitsch): we want the target to be a function. 1371 // TODO(floitsch): we want the target to be a function.
1445 if (input == target) return HType.UNKNOWN; 1372 if (input == target) return HType.UNKNOWN;
1446 if (isString() || left.isString()) { 1373 if (isString() || left.isString()) {
1447 return (input == left) ? HType.STRING : HType.UNKNOWN; 1374 return (input == left) ? HType.STRING : HType.UNKNOWN;
1448 } 1375 }
1449 if (right.isString()) return HType.STRING; 1376 if (right.isString()) return HType.STRING;
1450 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER; 1377 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER;
1451 return HType.UNKNOWN; 1378 return HType.UNKNOWN;
1452 } 1379 }
1453 1380
1454 HInstruction fold(HGraph graph) { 1381 HInstruction fold(HGraph graph) {
1455 if (left.isLiteralString() && right is HLiteral) { 1382 // TODO(floitsch): move this code to the compile-time-constant handler.
1456 HLiteral op1 = left; 1383 if (left.isConstantString() && right is HConstant) {
1457 HLiteral op2 = right; 1384 HConstant op1 = left;
1458 DartString leftString = op1.value; 1385 HConstant op2 = right;
1386 DartString leftString = op1.constant.value;
1459 DartString otherString = null; 1387 DartString otherString = null;
1460 if (right.isLiteralString()) { 1388 if (right.isConstantString()) {
1461 otherString = op2.value; 1389 otherString = op2.constant.value;
1462 } else { 1390 } else {
1463 assert(op2.isLiteralNumber() || 1391 assert(op2.isConstantNumber() ||
1464 op2.isLiteralBoolean() || 1392 op2.isConstantBoolean() ||
1465 op2.isLiteralNull()); 1393 op2.isConstantNull());
1466 otherString = new DartString.literal(op2.value.toString()); 1394 otherString = new DartString.literal(op2.constant.value.toString());
1467 } 1395 }
1468 DartString cons = new ConsDartString(leftString, otherString); 1396 DartString cons = new ConsDartString(leftString, otherString);
1469 return graph.addNewLiteralString(cons); 1397 return graph.addConstantString(cons);
1470 } 1398 }
1471 return super.fold(graph); 1399 return super.fold(graph);
1472 } 1400 }
1401
1402 String operationAsString() => "+";
1403 int typeCode() => 5;
1404 bool typeEquals(other) => other is HAdd;
1405 bool dataEquals(HInstruction other) => true;
1473 } 1406 }
1474 1407
1475 class HDivide extends HBinaryArithmetic { 1408 class HDivide extends HBinaryArithmetic {
1476 HDivide(HStatic target, HInstruction left, HInstruction right) 1409 HDivide(HStatic target, HInstruction left, HInstruction right)
1477 : super(target, left, right); 1410 : super(target, left, right);
1478 accept(HVisitor visitor) => visitor.visitDivide(this); 1411 accept(HVisitor visitor) => visitor.visitDivide(this);
1479 1412
1480 HType computeType() { 1413 HType computeType() {
1481 HType type = computeInputsType(); 1414 HType type = computeInputsType();
1482 builtin = type.isNumber(); 1415 builtin = type.isNumber();
1483 if (left.isNumber()) return HType.DOUBLE; 1416 if (left.isNumber()) return HType.DOUBLE;
1484 return HType.UNKNOWN; 1417 return HType.UNKNOWN;
1485 } 1418 }
1486 1419
1487 num evaluate(num a, num b) => a / b; 1420 String operationAsString() => "/";
1488 int typeCode() => 6; 1421 int typeCode() => 6;
1489 bool typeEquals(other) => other is HDivide; 1422 bool typeEquals(other) => other is HDivide;
1490 bool dataEquals(HInstruction other) => true; 1423 bool dataEquals(HInstruction other) => true;
1491 } 1424 }
1492 1425
1493 class HModulo extends HBinaryArithmetic { 1426 class HModulo extends HBinaryArithmetic {
1494 HModulo(HStatic target, HInstruction left, HInstruction right) 1427 HModulo(HStatic target, HInstruction left, HInstruction right)
1495 : super(target, left, right); 1428 : super(target, left, right);
1496 accept(HVisitor visitor) => visitor.visitModulo(this); 1429 accept(HVisitor visitor) => visitor.visitModulo(this);
1497 num evaluate(num a, num b) => a % b; 1430
1431 String operationAsString() => "%";
1498 int typeCode() => 7; 1432 int typeCode() => 7;
1499 bool typeEquals(other) => other is HModulo; 1433 bool typeEquals(other) => other is HModulo;
1500 bool dataEquals(HInstruction other) => true; 1434 bool dataEquals(HInstruction other) => true;
1501 } 1435 }
1502 1436
1503 class HMultiply extends HBinaryArithmetic { 1437 class HMultiply extends HBinaryArithmetic {
1504 HMultiply(HStatic target, HInstruction left, HInstruction right) 1438 HMultiply(HStatic target, HInstruction left, HInstruction right)
1505 : super(target, left, right); 1439 : super(target, left, right);
1506 accept(HVisitor visitor) => visitor.visitMultiply(this); 1440 accept(HVisitor visitor) => visitor.visitMultiply(this);
1507 num evaluate(num a, num b) => a * b; 1441
1442 String operationAsString() => "*";
1508 int typeCode() => 8; 1443 int typeCode() => 8;
1509 bool typeEquals(other) => other is HMultiply; 1444 bool typeEquals(other) => other is HMultiply;
1510 bool dataEquals(HInstruction other) => true; 1445 bool dataEquals(HInstruction other) => true;
1511 } 1446 }
1512 1447
1513 class HSubtract extends HBinaryArithmetic { 1448 class HSubtract extends HBinaryArithmetic {
1514 HSubtract(HStatic target, HInstruction left, HInstruction right) 1449 HSubtract(HStatic target, HInstruction left, HInstruction right)
1515 : super(target, left, right); 1450 : super(target, left, right);
1516 accept(HVisitor visitor) => visitor.visitSubtract(this); 1451 accept(HVisitor visitor) => visitor.visitSubtract(this);
1517 num evaluate(num a, num b) => a - b; 1452
1453 String operationAsString() => "-";
1518 int typeCode() => 9; 1454 int typeCode() => 9;
1519 bool typeEquals(other) => other is HSubtract; 1455 bool typeEquals(other) => other is HSubtract;
1520 bool dataEquals(HInstruction other) => true; 1456 bool dataEquals(HInstruction other) => true;
1521 } 1457 }
1522 1458
1523 class HTruncatingDivide extends HBinaryArithmetic { 1459 class HTruncatingDivide extends HBinaryArithmetic {
1524 HTruncatingDivide(HStatic target, HInstruction left, HInstruction right) 1460 HTruncatingDivide(HStatic target, HInstruction left, HInstruction right)
1525 : super(target, left, right); 1461 : super(target, left, right);
1526 accept(HVisitor visitor) => visitor.visitTruncatingDivide(this); 1462 accept(HVisitor visitor) => visitor.visitTruncatingDivide(this);
1527 1463
1528 HInstruction fold(HGraph graph) { 1464 String operationAsString() => "~/";
1529 // Avoid a DivisionByZeroException.
1530 if (right.isLiteralNumber() && right.dynamic.value == 0) {
1531 return this;
1532 }
1533 return super.fold(graph);
1534 }
1535
1536 num evaluate(num a, num b) => a ~/ b;
1537 int typeCode() => 10; 1465 int typeCode() => 10;
1538 bool typeEquals(other) => other is HTruncatingDivide; 1466 bool typeEquals(other) => other is HTruncatingDivide;
1539 bool dataEquals(HInstruction other) => true; 1467 bool dataEquals(HInstruction other) => true;
1540 } 1468 }
1541 1469
1542 1470
1543 // TODO(floitsch): Should HBinaryArithmetic really be the super class of 1471 // TODO(floitsch): Should HBinaryArithmetic really be the super class of
1544 // HBinaryBitOp? 1472 // HBinaryBitOp?
1545 class HBinaryBitOp extends HBinaryArithmetic { 1473 class HBinaryBitOp extends HBinaryArithmetic {
1546 HBinaryBitOp(HStatic target, HInstruction left, HInstruction right) 1474 HBinaryBitOp(HStatic target, HInstruction left, HInstruction right)
1547 : super(target, left, right); 1475 : super(target, left, right);
1548 1476
1549 HType computeType() { 1477 HType computeType() {
1550 HType type = computeInputsType(); 1478 HType type = computeInputsType();
1551 builtin = type.isInteger(); 1479 builtin = type.isInteger();
1552 if (!type.isUnknown()) return type; 1480 if (!type.isUnknown()) return type;
1553 if (left.isInteger()) return HType.INTEGER; 1481 if (left.isInteger()) return HType.INTEGER;
1554 return HType.UNKNOWN; 1482 return HType.UNKNOWN;
1555 } 1483 }
1556 1484
1557 HType computeDesiredInputType(HInstruction input) { 1485 HType computeDesiredInputType(HInstruction input) {
1558 // TODO(floitsch): we want the target to be a function. 1486 // TODO(floitsch): we want the target to be a function.
1559 if (input == target) return HType.UNKNOWN; 1487 if (input == target) return HType.UNKNOWN;
1560 return HType.INTEGER; 1488 return HType.INTEGER;
1561 } 1489 }
1562 1490
1563 HInstruction fold(HGraph graph) {
1564 // Bit-operations are only defined on integers.
1565 if (left.isLiteralNumber() && right.isLiteralNumber()) {
1566 HLiteral op1 = left;
1567 HLiteral op2 = right;
1568 // Avoid exceptions.
1569 if (op1.isInteger() && op2.isInteger()) {
1570 return graph.addNewLiteralInt(evaluate(op1.value, op2.value));
1571 }
1572 }
1573 return this;
1574 }
1575
1576 // TODO(floitsch): make class abstract instead of adding an abstract method. 1491 // TODO(floitsch): make class abstract instead of adding an abstract method.
1577 abstract accept(HVisitor visitor); 1492 abstract accept(HVisitor visitor);
1578 } 1493 }
1579 1494
1580 class HShiftLeft extends HBinaryBitOp { 1495 class HShiftLeft extends HBinaryBitOp {
1581 HShiftLeft(HStatic target, HInstruction left, HInstruction right) 1496 HShiftLeft(HStatic target, HInstruction left, HInstruction right)
1582 : super(target, left, right); 1497 : super(target, left, right);
1583 accept(HVisitor visitor) => visitor.visitShiftLeft(this); 1498 accept(HVisitor visitor) => visitor.visitShiftLeft(this);
1584 1499
1585 HInstruction fold(HGraph graph) { 1500 String operationAsString() => "<<";
1586 if (right.isLiteralNumber()) {
1587 // TODO(floitsch): find good max left-shift amount.
1588 final int MAX_SHIFT_LEFT_AMOUNT = 50;
1589 HLiteral op2 = right;
1590 // Only positive shifting is allowed. Also guard against out-of-memory
1591 // shifts.
1592 if (op2.value < 0 || op2.value > MAX_SHIFT_LEFT_AMOUNT) return this;
1593 }
1594 return super.fold(graph);
1595 }
1596
1597 int evaluate(int a, int b) => a << b;
1598 int typeCode() => 11; 1501 int typeCode() => 11;
1599 bool typeEquals(other) => other is HShiftLeft; 1502 bool typeEquals(other) => other is HShiftLeft;
1600 bool dataEquals(HInstruction other) => true; 1503 bool dataEquals(HInstruction other) => true;
1601 } 1504 }
1602 1505
1603 class HShiftRight extends HBinaryBitOp { 1506 class HShiftRight extends HBinaryBitOp {
1604 HShiftRight(HStatic target, HInstruction left, HInstruction right) 1507 HShiftRight(HStatic target, HInstruction left, HInstruction right)
1605 : super(target, left, right); 1508 : super(target, left, right);
1606 accept(HVisitor visitor) => visitor.visitShiftRight(this); 1509 accept(HVisitor visitor) => visitor.visitShiftRight(this);
1607 1510
1608 HInstruction fold(HGraph graph) { 1511 String operationAsString() => ">>";
1609 if (right.isLiteralNumber()) {
1610 HLiteral op2 = right;
1611 // Only positive shifting is allowed.
1612 if (op2.value < 0) return this;
1613 }
1614 return super.fold(graph);
1615 }
1616
1617 int evaluate(int a, int b) => a >> b;
1618 int typeCode() => 12; 1512 int typeCode() => 12;
1619 bool typeEquals(other) => other is HShiftRight; 1513 bool typeEquals(other) => other is HShiftRight;
1620 bool dataEquals(HInstruction other) => true; 1514 bool dataEquals(HInstruction other) => true;
1621 } 1515 }
1622 1516
1623 class HBitOr extends HBinaryBitOp { 1517 class HBitOr extends HBinaryBitOp {
1624 HBitOr(HStatic target, HInstruction left, HInstruction right) 1518 HBitOr(HStatic target, HInstruction left, HInstruction right)
1625 : super(target, left, right); 1519 : super(target, left, right);
1626 accept(HVisitor visitor) => visitor.visitBitOr(this); 1520 accept(HVisitor visitor) => visitor.visitBitOr(this);
1627 1521
1628 int evaluate(int a, int b) => a | b; 1522 String operationAsString() => "|";
1629 int typeCode() => 13; 1523 int typeCode() => 13;
1630 bool typeEquals(other) => other is HBitOr; 1524 bool typeEquals(other) => other is HBitOr;
1631 bool dataEquals(HInstruction other) => true; 1525 bool dataEquals(HInstruction other) => true;
1632 } 1526 }
1633 1527
1634 class HBitAnd extends HBinaryBitOp { 1528 class HBitAnd extends HBinaryBitOp {
1635 HBitAnd(HStatic target, HInstruction left, HInstruction right) 1529 HBitAnd(HStatic target, HInstruction left, HInstruction right)
1636 : super(target, left, right); 1530 : super(target, left, right);
1637 accept(HVisitor visitor) => visitor.visitBitAnd(this); 1531 accept(HVisitor visitor) => visitor.visitBitAnd(this);
1638 1532
1639 int evaluate(int a, int b) => a & b; 1533 String operationAsString() => "&";
1640 int typeCode() => 14; 1534 int typeCode() => 14;
1641 bool typeEquals(other) => other is HBitAnd; 1535 bool typeEquals(other) => other is HBitAnd;
1642 bool dataEquals(HInstruction other) => true; 1536 bool dataEquals(HInstruction other) => true;
1643 } 1537 }
1644 1538
1645 class HBitXor extends HBinaryBitOp { 1539 class HBitXor extends HBinaryBitOp {
1646 HBitXor(HStatic target, HInstruction left, HInstruction right) 1540 HBitXor(HStatic target, HInstruction left, HInstruction right)
1647 : super(target, left, right); 1541 : super(target, left, right);
1648 accept(HVisitor visitor) => visitor.visitBitXor(this); 1542 accept(HVisitor visitor) => visitor.visitBitXor(this);
1649 1543
1650 int evaluate(int a, int b) => a ^ b; 1544 String operationAsString() => "^";
1651 int typeCode() => 15; 1545 int typeCode() => 15;
1652 bool typeEquals(other) => other is HBitXor; 1546 bool typeEquals(other) => other is HBitXor;
1653 bool dataEquals(HInstruction other) => true; 1547 bool dataEquals(HInstruction other) => true;
1654 } 1548 }
1655 1549
1656 class HInvokeUnary extends HInvokeStatic { 1550 class HInvokeUnary extends HInvokeStatic {
1657 HInvokeUnary(HStatic target, HInstruction input) 1551 HInvokeUnary(HStatic target, HInstruction input)
1658 : super(Selector.UNARY_OPERATOR, <HInstruction>[target, input]); 1552 : super(Selector.UNARY_OPERATOR, <HInstruction>[target, input]);
1659 1553
1660 HInstruction get operand() => inputs[1]; 1554 HInstruction get operand() => inputs[1];
(...skipping 19 matching lines...) Expand all
1680 1574
1681 HType computeDesiredInputType(HInstruction input) { 1575 HType computeDesiredInputType(HInstruction input) {
1682 // TODO(floitsch): we want the target to be a function. 1576 // TODO(floitsch): we want the target to be a function.
1683 if (input == target) return HType.UNKNOWN; 1577 if (input == target) return HType.UNKNOWN;
1684 if (type.isUnknown() || type.isNumber()) return HType.NUMBER; 1578 if (type.isUnknown() || type.isNumber()) return HType.NUMBER;
1685 return HType.UNKNOWN; 1579 return HType.UNKNOWN;
1686 } 1580 }
1687 1581
1688 bool hasExpectedType() => builtin || (type.isUnknown()); 1582 bool hasExpectedType() => builtin || (type.isUnknown());
1689 1583
1690 abstract HInstruction fold(HGraph graph); 1584 HInstruction fold(HGraph graph) {
1585 if (operand is HConstant) {
1586 HConstant op = operand;
1587 Constant folded = op.constant.unaryFold(operationAsString());
1588 if (folded !== null) return graph.addConstant(folded);
1589 }
1590 return this;
1591 }
1691 1592
1692 abstract num evaluate(num a); 1593 abstract String operationAsString();
1693 } 1594 }
1694 1595
1695 class HNegate extends HInvokeUnary { 1596 class HNegate extends HInvokeUnary {
1696 HNegate(HStatic target, HInstruction input) : super(target, input); 1597 HNegate(HStatic target, HInstruction input) : super(target, input);
1697 accept(HVisitor visitor) => visitor.visitNegate(this); 1598 accept(HVisitor visitor) => visitor.visitNegate(this);
1698 1599
1699 HInstruction fold(HGraph graph) { 1600 String operationAsString() => "-";
1700 if (operand.isLiteralNumber()) {
1701 HLiteral input = operand;
1702 return graph.addNewLiteralNum(evaluate(input.value), type);
1703 }
1704 return this;
1705 }
1706
1707 num evaluate(num a) => -a;
1708 int typeCode() => 16; 1601 int typeCode() => 16;
1709 bool typeEquals(other) => other is HNegate; 1602 bool typeEquals(other) => other is HNegate;
1710 bool dataEquals(HInstruction other) => true; 1603 bool dataEquals(HInstruction other) => true;
1711 } 1604 }
1712 1605
1713 class HBitNot extends HInvokeUnary { 1606 class HBitNot extends HInvokeUnary {
1714 HBitNot(HStatic target, HInstruction input) : super(target, input); 1607 HBitNot(HStatic target, HInstruction input) : super(target, input);
1715 accept(HVisitor visitor) => visitor.visitBitNot(this); 1608 accept(HVisitor visitor) => visitor.visitBitNot(this);
1716 1609
1717 HType computeType() { 1610 HType computeType() {
1718 HType type = operand.type; 1611 HType type = operand.type;
1719 builtin = type.isInteger(); 1612 builtin = type.isInteger();
1720 if (!type.isUnknown()) return type; 1613 if (!type.isUnknown()) return type;
1721 return HType.UNKNOWN; 1614 return HType.UNKNOWN;
1722 } 1615 }
1723 1616
1724 HType computeDesiredInputType(HInstruction input) { 1617 HType computeDesiredInputType(HInstruction input) {
1725 // TODO(floitsch): we want the target to be a function. 1618 // TODO(floitsch): we want the target to be a function.
1726 if (input == target) return HType.UNKNOWN; 1619 if (input == target) return HType.UNKNOWN;
1727 return HType.INTEGER; 1620 return HType.INTEGER;
1728 } 1621 }
1729 1622
1730 HInstruction fold(HGraph graph) { 1623 String operationAsString() => "~";
1731 if (operand.isLiteralNumber()) {
1732 HLiteral input = operand;
1733 if (input.isInteger()) {
1734 return graph.addNewLiteralInt(evaluate(input.value));
1735 }
1736 }
1737 return this;
1738 }
1739
1740 int evaluate(int a) => ~a;
1741 int typeCode() => 17; 1624 int typeCode() => 17;
1742 bool typeEquals(other) => other is HBitNot; 1625 bool typeEquals(other) => other is HBitNot;
1743 bool dataEquals(HInstruction other) => true; 1626 bool dataEquals(HInstruction other) => true;
1744 } 1627 }
1745 1628
1746 class HExit extends HControlFlow { 1629 class HExit extends HControlFlow {
1747 HExit() : super(const <HInstruction>[]); 1630 HExit() : super(const <HInstruction>[]);
1748 toString() => 'exit'; 1631 toString() => 'exit';
1749 accept(HVisitor visitor) => visitor.visitExit(this); 1632 accept(HVisitor visitor) => visitor.visitExit(this);
1750 } 1633 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1810 HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP]) 1693 HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP])
1811 : super(<HInstruction>[condition]); 1694 : super(<HInstruction>[condition]);
1812 toString() => 'loop-branch'; 1695 toString() => 'loop-branch';
1813 accept(HVisitor visitor) => visitor.visitLoopBranch(this); 1696 accept(HVisitor visitor) => visitor.visitLoopBranch(this);
1814 1697
1815 bool isDoWhile() { 1698 bool isDoWhile() {
1816 return kind === DO_WHILE_LOOP; 1699 return kind === DO_WHILE_LOOP;
1817 } 1700 }
1818 } 1701 }
1819 1702
1820 class HLiteral extends HInstruction { 1703 class HConstant extends HInstruction {
1821 final value; 1704 final Constant constant;
1822 HLiteral.internal(this.value, HType type) : super(<HInstruction>[]) { 1705 HConstant.internal(this.constant, HType type) : super(<HInstruction>[]) {
1823 this.type = type; 1706 this.type = type;
1824 tryGenerateAtUseSite(); // Maybe avoid this if the literal is big? 1707 tryGenerateAtUseSite(); // Maybe avoid this if the literal is big?
1825 } 1708 }
1826 1709
1827 void prepareGvn() { 1710 void prepareGvn() {
1828 assert(!hasSideEffects()); 1711 assert(!hasSideEffects());
1829 } 1712 }
1830 1713
1831 toString() => 'literal: $value'; 1714 toString() => 'literal: $constant';
1832 accept(HVisitor visitor) => visitor.visitLiteral(this); 1715 accept(HVisitor visitor) => visitor.visitConstant(this);
1833 HType computeType() => type; 1716 HType computeType() => type;
1834 1717
1835 // Literals have the type they have. It can't be changed. 1718 // Literals have the type they have. It can't be changed.
1836 bool updateType() => false; 1719 bool updateType() => false;
1837 1720
1838 bool hasExpectedType() => true; 1721 bool hasExpectedType() => true;
1839 1722
1840 bool isLiteralBoolean() => value is bool; 1723 bool isConstantBoolean() => constant.isBool();
1841 bool isLiteralNull() => value === null; 1724 bool isConstantNull() => constant.isNull();
1842 bool isLiteralNumber() => value is num; 1725 bool isConstantNumber() => constant.isNum();
1843 bool isLiteralString() => value is DartString; 1726 bool isConstantString() => constant.isString();
1844 } 1727 }
1845 1728
1846 class HNot extends HInstruction { 1729 class HNot extends HInstruction {
1847 HNot(HInstruction value) : super(<HInstruction>[value]); 1730 HNot(HInstruction value) : super(<HInstruction>[value]);
1848 void prepareGvn() { 1731 void prepareGvn() {
1849 assert(!hasSideEffects()); 1732 assert(!hasSideEffects());
1850 setUseGvn(); 1733 setUseGvn();
1851 } 1734 }
1852 1735
1853 HType computeType() => HType.BOOLEAN; 1736 HType computeType() => HType.BOOLEAN;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1972 // and do not have any side-effects if we know all the inputs are 1855 // and do not have any side-effects if we know all the inputs are
1973 // numbers. This can be improved for at least equality. 1856 // numbers. This can be improved for at least equality.
1974 if (builtin) { 1857 if (builtin) {
1975 assert(!hasSideEffects()); 1858 assert(!hasSideEffects());
1976 setUseGvn(); 1859 setUseGvn();
1977 } else { 1860 } else {
1978 setAllSideEffects(); 1861 setAllSideEffects();
1979 } 1862 }
1980 } 1863 }
1981 1864
1982 HInstruction fold(HGraph graph) {
1983 if (left.isLiteralNumber() && right.isLiteralNumber()) {
1984 HLiteral op1 = left;
1985 HLiteral op2 = right;
1986 return graph.addNewLiteralBool(evaluate(op1.value, op2.value));
1987 }
1988 return this;
1989 }
1990
1991 HType computeType() { 1865 HType computeType() {
1992 builtin = computeInputsType().isNumber(); 1866 builtin = computeInputsType().isNumber();
1993 return HType.BOOLEAN; 1867 return HType.BOOLEAN;
1994 } 1868 }
1995 1869
1996 HType computeDesiredInputType(HInstruction input) { 1870 HType computeDesiredInputType(HInstruction input) {
1997 // TODO(floitsch): we want the target to be a function. 1871 // TODO(floitsch): we want the target to be a function.
1998 if (input == target) return HType.UNKNOWN; 1872 if (input == target) return HType.UNKNOWN;
1999 // For all relational operations exept HEquals, we expect to only 1873 // For all relational operations exept HEquals, we expect to only
2000 // get numbers. 1874 // get numbers.
2001 return HType.NUMBER; 1875 return HType.NUMBER;
2002 } 1876 }
2003 1877
2004 // A HRelational goes through the builtin operator or the top level 1878 // A HRelational goes through the builtin operator or the top level
2005 // element. Therefore, it always has the expected type. 1879 // element. Therefore, it always has the expected type.
2006 bool hasExpectedType() => true; 1880 bool hasExpectedType() => true;
2007
2008 abstract bool evaluate(num a, num b);
2009 } 1881 }
2010 1882
2011 class HEquals extends HRelational { 1883 class HEquals extends HRelational {
2012 HEquals(HStatic target, HInstruction left, HInstruction right) 1884 HEquals(HStatic target, HInstruction left, HInstruction right)
2013 : super(target, left, right); 1885 : super(target, left, right);
2014 bool evaluate(num a, num b) => a == b;
2015 accept(HVisitor visitor) => visitor.visitEquals(this); 1886 accept(HVisitor visitor) => visitor.visitEquals(this);
2016 int typeCode() => 19;
2017 bool typeEquals(other) => other is HEquals;
2018 bool dataEquals(HInstruction other) => true;
2019 1887
2020 HType computeType() { 1888 HType computeType() {
2021 builtin = computeInputsType().isNumber() || (left is HLiteral); 1889 builtin = computeInputsType().isNumber() || (left is HConstant);
2022 return HType.BOOLEAN; 1890 return HType.BOOLEAN;
2023 } 1891 }
2024 1892
2025 HType computeDesiredInputType(HInstruction input) { 1893 HType computeDesiredInputType(HInstruction input) {
2026 // TODO(floitsch): we want the target to be a function. 1894 // TODO(floitsch): we want the target to be a function.
2027 if (input == target) return HType.UNKNOWN; 1895 if (input == target) return HType.UNKNOWN;
2028 if (left.isNumber() || right.isNumber()) return HType.NUMBER; 1896 if (left.isNumber() || right.isNumber()) return HType.NUMBER;
2029 return HType.UNKNOWN; 1897 return HType.UNKNOWN;
2030 } 1898 }
1899
1900 String operationAsString() => "==";
1901 int typeCode() => 19;
1902 bool typeEquals(other) => other is HEquals;
1903 bool dataEquals(HInstruction other) => true;
2031 } 1904 }
2032 1905
2033 class HIdentity extends HRelational { 1906 class HIdentity extends HRelational {
2034 HIdentity(HStatic target, HInstruction left, HInstruction right) 1907 HIdentity(HStatic target, HInstruction left, HInstruction right)
2035 : super(target, left, right); 1908 : super(target, left, right);
2036 bool evaluate(num a, num b) => a === b;
2037 accept(HVisitor visitor) => visitor.visitIdentity(this); 1909 accept(HVisitor visitor) => visitor.visitIdentity(this);
2038 int typeCode() => 20;
2039 bool typeEquals(other) => other is HIdentity;
2040 bool dataEquals(HInstruction other) => true;
2041 1910
2042 HType computeType() { 1911 HType computeType() {
2043 builtin = true; 1912 builtin = true;
2044 return HType.BOOLEAN; 1913 return HType.BOOLEAN;
2045 } 1914 }
2046 1915
2047 bool hasExpectedType() => true; 1916 bool hasExpectedType() => true;
2048 1917
2049 HType computeDesiredInputType(HInstruction input) => HType.UNKNOWN; 1918 HType computeDesiredInputType(HInstruction input) => HType.UNKNOWN;
1919
1920 String operationAsString() => "===";
1921 int typeCode() => 20;
1922 bool typeEquals(other) => other is HIdentity;
1923 bool dataEquals(HInstruction other) => true;
2050 } 1924 }
2051 1925
2052 class HGreater extends HRelational { 1926 class HGreater extends HRelational {
2053 HGreater(HStatic target, HInstruction left, HInstruction right) 1927 HGreater(HStatic target, HInstruction left, HInstruction right)
2054 : super(target, left, right); 1928 : super(target, left, right);
2055 bool evaluate(num a, num b) => a > b;
2056 accept(HVisitor visitor) => visitor.visitGreater(this); 1929 accept(HVisitor visitor) => visitor.visitGreater(this);
1930
1931 String operationAsString() => ">";
2057 int typeCode() => 21; 1932 int typeCode() => 21;
2058 bool typeEquals(other) => other is HGreater; 1933 bool typeEquals(other) => other is HGreater;
2059 bool dataEquals(HInstruction other) => true; 1934 bool dataEquals(HInstruction other) => true;
2060 } 1935 }
2061 1936
2062 class HGreaterEqual extends HRelational { 1937 class HGreaterEqual extends HRelational {
2063 HGreaterEqual(HStatic target, HInstruction left, HInstruction right) 1938 HGreaterEqual(HStatic target, HInstruction left, HInstruction right)
2064 : super(target, left, right); 1939 : super(target, left, right);
2065 bool evaluate(num a, num b) => a >= b;
2066 accept(HVisitor visitor) => visitor.visitGreaterEqual(this); 1940 accept(HVisitor visitor) => visitor.visitGreaterEqual(this);
1941
1942 String operationAsString() => ">=";
2067 int typeCode() => 22; 1943 int typeCode() => 22;
2068 bool typeEquals(other) => other is HGreaterEqual; 1944 bool typeEquals(other) => other is HGreaterEqual;
2069 bool dataEquals(HInstruction other) => true; 1945 bool dataEquals(HInstruction other) => true;
2070 } 1946 }
2071 1947
2072 class HLess extends HRelational { 1948 class HLess extends HRelational {
2073 HLess(HStatic target, HInstruction left, HInstruction right) 1949 HLess(HStatic target, HInstruction left, HInstruction right)
2074 : super(target, left, right); 1950 : super(target, left, right);
2075 bool evaluate(num a, num b) => a < b;
2076 accept(HVisitor visitor) => visitor.visitLess(this); 1951 accept(HVisitor visitor) => visitor.visitLess(this);
1952
1953 String operationAsString() => "<";
1954 int typeCode() => 23;
2077 bool typeEquals(other) => other is HLess; 1955 bool typeEquals(other) => other is HLess;
2078 bool dataEquals(HInstruction other) => true; 1956 bool dataEquals(HInstruction other) => true;
2079 } 1957 }
2080 1958
2081 class HLessEqual extends HRelational { 1959 class HLessEqual extends HRelational {
2082 HLessEqual(HStatic target, HInstruction left, HInstruction right) 1960 HLessEqual(HStatic target, HInstruction left, HInstruction right)
2083 : super(target, left, right); 1961 : super(target, left, right);
2084 bool evaluate(num a, num b) => a <= b;
2085 accept(HVisitor visitor) => visitor.visitLessEqual(this); 1962 accept(HVisitor visitor) => visitor.visitLessEqual(this);
2086 int typeCode() => 23; 1963
1964 String operationAsString() => "<=";
1965 int typeCode() => 24;
2087 bool typeEquals(other) => other is HLessEqual; 1966 bool typeEquals(other) => other is HLessEqual;
2088 bool dataEquals(HInstruction other) => true; 1967 bool dataEquals(HInstruction other) => true;
2089 } 1968 }
2090 1969
2091 class HReturn extends HControlFlow { 1970 class HReturn extends HControlFlow {
2092 HReturn(value) : super(<HInstruction>[value]); 1971 HReturn(value) : super(<HInstruction>[value]);
2093 toString() => 'return'; 1972 toString() => 'return';
2094 accept(HVisitor visitor) => visitor.visitReturn(this); 1973 accept(HVisitor visitor) => visitor.visitReturn(this);
2095 } 1974 }
2096 1975
(...skipping 12 matching lines...) Expand all
2109 void prepareGvn() { 1988 void prepareGvn() {
2110 assert(!hasSideEffects()); 1989 assert(!hasSideEffects());
2111 if (!element.isAssignable()) { 1990 if (!element.isAssignable()) {
2112 setUseGvn(); 1991 setUseGvn();
2113 } 1992 }
2114 } 1993 }
2115 toString() => 'static ${element.name}'; 1994 toString() => 'static ${element.name}';
2116 accept(HVisitor visitor) => visitor.visitStatic(this); 1995 accept(HVisitor visitor) => visitor.visitStatic(this);
2117 1996
2118 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode(); 1997 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode();
2119 int typeCode() => 24; 1998 int typeCode() => 25;
2120 bool typeEquals(other) => other is HStatic; 1999 bool typeEquals(other) => other is HStatic;
2121 bool dataEquals(HStatic other) => element == other.element; 2000 bool dataEquals(HStatic other) => element == other.element;
2122 } 2001 }
2123 2002
2124 class HStaticStore extends HInstruction { 2003 class HStaticStore extends HInstruction {
2125 Element element; 2004 Element element;
2126 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]); 2005 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]);
2127 toString() => 'static store ${element.name}'; 2006 toString() => 'static store ${element.name}';
2128 accept(HVisitor visitor) => visitor.visitStaticStore(this); 2007 accept(HVisitor visitor) => visitor.visitStaticStore(this);
2129 2008
2130 int typeCode() => 25; 2009 int typeCode() => 26;
2131 bool typeEquals(other) => other is HStaticStore; 2010 bool typeEquals(other) => other is HStaticStore;
2132 bool dataEquals(HStaticStore other) => element == other.element; 2011 bool dataEquals(HStaticStore other) => element == other.element;
2133 } 2012 }
2134 2013
2135 class HLiteralList extends HInstruction { 2014 class HLiteralList extends HInstruction {
2136 HLiteralList(inputs, this.isConst) : super(inputs); 2015 HLiteralList(inputs, this.isConst) : super(inputs);
2137 toString() => 'literal list'; 2016 toString() => 'literal list';
2138 accept(HVisitor visitor) => visitor.visitLiteralList(this); 2017 accept(HVisitor visitor) => visitor.visitLiteralList(this);
2139 HType computeType() => HType.ARRAY; 2018 HType computeType() => HType.ARRAY;
2140 bool hasExpectedType() => true; 2019 bool hasExpectedType() => true;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
2266 2145
2267 HInstruction get expression() => inputs[0]; 2146 HInstruction get expression() => inputs[0];
2268 2147
2269 HType computeType() => HType.BOOLEAN; 2148 HType computeType() => HType.BOOLEAN;
2270 bool hasExpectedType() => true; 2149 bool hasExpectedType() => true;
2271 2150
2272 accept(HVisitor visitor) => visitor.visitIs(this); 2151 accept(HVisitor visitor) => visitor.visitIs(this);
2273 2152
2274 toString() => "$expression is $typeExpression"; 2153 toString() => "$expression is $typeExpression";
2275 } 2154 }
OLDNEW
« no previous file with comments | « frog/leg/ssa/codegen.dart ('k') | frog/leg/ssa/optimize.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698