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

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

Issue 9578021: Revert "Refactor constant part." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: 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 | « dart/frog/leg/ssa/codegen.dart ('k') | dart/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);
16 R visitDivide(HDivide node); 15 R visitDivide(HDivide node);
17 R visitEquals(HEquals node); 16 R visitEquals(HEquals node);
18 R visitExit(HExit node); 17 R visitExit(HExit node);
19 R visitFieldGet(HFieldGet node); 18 R visitFieldGet(HFieldGet node);
20 R visitFieldSet(HFieldSet node); 19 R visitFieldSet(HFieldSet node);
21 R visitForeign(HForeign node); 20 R visitForeign(HForeign node);
22 R visitForeignNew(HForeignNew); 21 R visitForeignNew(HForeignNew);
23 R visitGoto(HGoto node); 22 R visitGoto(HGoto node);
24 R visitGreater(HGreater node); 23 R visitGreater(HGreater node);
25 R visitGreaterEqual(HGreaterEqual node); 24 R visitGreaterEqual(HGreaterEqual node);
26 R visitIdentity(HIdentity node); 25 R visitIdentity(HIdentity node);
27 R visitIf(HIf node); 26 R visitIf(HIf node);
28 R visitIndex(HIndex node); 27 R visitIndex(HIndex node);
29 R visitIndexAssign(HIndexAssign node); 28 R visitIndexAssign(HIndexAssign node);
30 R visitIntegerCheck(HIntegerCheck node); 29 R visitIntegerCheck(HIntegerCheck node);
31 R visitInvokeClosure(HInvokeClosure node); 30 R visitInvokeClosure(HInvokeClosure node);
32 R visitInvokeDynamicGetter(HInvokeDynamicGetter node); 31 R visitInvokeDynamicGetter(HInvokeDynamicGetter node);
33 R visitInvokeDynamicMethod(HInvokeDynamicMethod node); 32 R visitInvokeDynamicMethod(HInvokeDynamicMethod node);
34 R visitInvokeDynamicSetter(HInvokeDynamicSetter node); 33 R visitInvokeDynamicSetter(HInvokeDynamicSetter node);
35 R visitInvokeInterceptor(HInvokeInterceptor node); 34 R visitInvokeInterceptor(HInvokeInterceptor node);
36 R visitInvokeStatic(HInvokeStatic node); 35 R visitInvokeStatic(HInvokeStatic node);
37 R visitInvokeSuper(HInvokeSuper node); 36 R visitInvokeSuper(HInvokeSuper node);
38 R visitIs(HIs node); 37 R visitIs(HIs node);
39 R visitLess(HLess node); 38 R visitLess(HLess node);
40 R visitLessEqual(HLessEqual node); 39 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 constants used within a graph so we do not 119 // We canonicalize all literals 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 Map<Constant, HConstant> constants; 121 HLiteral nullLiteral;
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;
122 130
123 HGraph() 131 HGraph() : blocks = new List<HBasicBlock>() {
124 : blocks = new List<HBasicBlock>(),
125 constants = new Map<Constant, HConstant>() {
126 entry = addNewBlock(); 132 entry = addNewBlock();
127 // The exit block will be added later, so it has an id that is 133 // The exit block will be added later, so it has an id that is
128 // after all others in the system. 134 // after all others in the system.
129 exit = new HBasicBlock(); 135 exit = new HBasicBlock();
130 } 136 }
131 137
132 void addBlock(HBasicBlock block) { 138 void addBlock(HBasicBlock block) {
133 int id = blocks.length; 139 int id = blocks.length;
134 block.id = id; 140 block.id = id;
135 blocks.add(block); 141 blocks.add(block);
136 assert(blocks[id] === block); 142 assert(blocks[id] === block);
137 } 143 }
138 144
139 HBasicBlock addNewBlock() { 145 HBasicBlock addNewBlock() {
140 HBasicBlock result = new HBasicBlock(); 146 HBasicBlock result = new HBasicBlock();
141 addBlock(result); 147 addBlock(result);
142 return result; 148 return result;
143 } 149 }
144 150
145 HBasicBlock addNewLoopHeaderBlock(List<SourceString> labels) { 151 HBasicBlock addNewLoopHeaderBlock(List<SourceString> labels) {
146 HBasicBlock result = addNewBlock(); 152 HBasicBlock result = addNewBlock();
147 result.loopInformation = new HLoopInformation(result, labels); 153 result.loopInformation = new HLoopInformation(result, labels);
148 return result; 154 return result;
149 } 155 }
150 156
151 static HType mapConstantTypeToSsaType(Constant constant) { 157 HLiteral addNewLiteralInt(int value) {
152 if (constant.isNull()) return HType.UNKNOWN; 158 if (intLiterals === null) intLiterals = new Map<int, HLiteral>();
153 if (constant.isBool()) return HType.BOOLEAN; 159 HLiteral result = intLiterals[value];
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];
163 if (result === null) { 160 if (result === null) {
164 HType type = mapConstantTypeToSsaType(constant); 161 result = new HLiteral.internal(value, HType.INTEGER);
165 result = new HConstant.internal(constant, type);
166 entry.addAtExit(result); 162 entry.addAtExit(result);
167 constants[constant] = result; 163 intLiterals[value] = result;
168 } 164 }
169 return result; 165 return result;
170 } 166 }
171 167
172 HConstant addConstantInt(int i) { 168 HLiteral addNewLiteralNaN() {
173 return addConstant(new IntConstant(i)); 169 if (nanLiteral === null) {
170 nanLiteral = new HLiteral.internal(double.NAN, HType.DOUBLE);
171 entry.addAtExit(nanLiteral);
172 }
173 return nanLiteral;
174 } 174 }
175 175
176 HConstant addConstantDouble(int d) { 176 HLiteral addNewNegativeZeroLiteral() {
177 return addConstant(new DoubleConstant(d)); 177 if (negativeZeroLiteral === null) {
178 negativeZeroLiteral = new HLiteral.internal(-0.0, HType.DOUBLE);
179 entry.addAtExit(negativeZeroLiteral);
180 }
181 return negativeZeroLiteral;
178 } 182 }
179 183
180 HConstant addConstantString(DartString str) { 184 HLiteral addNewLiteralDouble(double value) {
181 return addConstant(new StringConstant(str)); 185 if (value.isNaN()) return addNewLiteralNaN(); // Avoid hashing NaN.
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;
182 } 198 }
183 199
184 HConstant addConstantBool(bool value) { 200 HLiteral addNewLiteralNum(num value, HType type) {
185 return addConstant(new BoolConstant(value)); 201 // If we've propagated type information then the type must be a
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;
186 } 217 }
187 218
188 HConstant addConstantNull() { 219 HLiteral addNewLiteralTrue() {
189 return addConstant(const NullConstant()); 220 if (trueLiteral === null) {
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;
190 } 257 }
191 258
192 void finalize() { 259 void finalize() {
193 addBlock(exit); 260 addBlock(exit);
194 exit.open(); 261 exit.open();
195 exit.close(new HExit()); 262 exit.close(new HExit());
196 assignDominators(); 263 assignDominators();
197 } 264 }
198 265
199 void assignDominators() { 266 void assignDominators() {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 visitAdd(HAdd node) => visitBinaryArithmetic(node); 317 visitAdd(HAdd node) => visitBinaryArithmetic(node);
251 visitBitAnd(HBitAnd node) => visitBinaryBitOp(node); 318 visitBitAnd(HBitAnd node) => visitBinaryBitOp(node);
252 visitBitNot(HBitNot node) => visitInvokeUnary(node); 319 visitBitNot(HBitNot node) => visitInvokeUnary(node);
253 visitBitOr(HBitOr node) => visitBinaryBitOp(node); 320 visitBitOr(HBitOr node) => visitBinaryBitOp(node);
254 visitBitXor(HBitXor node) => visitBinaryBitOp(node); 321 visitBitXor(HBitXor node) => visitBinaryBitOp(node);
255 visitBailoutTarget(HBailoutTarget node) => visitInstruction(node); 322 visitBailoutTarget(HBailoutTarget node) => visitInstruction(node);
256 visitBoolify(HBoolify node) => visitInstruction(node); 323 visitBoolify(HBoolify node) => visitInstruction(node);
257 visitBoundsCheck(HBoundsCheck node) => visitCheck(node); 324 visitBoundsCheck(HBoundsCheck node) => visitCheck(node);
258 visitBreak(HBreak node) => visitGoto(node); 325 visitBreak(HBreak node) => visitGoto(node);
259 visitCheck(HCheck node) => visitInstruction(node); 326 visitCheck(HCheck node) => visitInstruction(node);
260 visitConstant(HConstant node) => visitInstruction(node);
261 visitDivide(HDivide node) => visitBinaryArithmetic(node); 327 visitDivide(HDivide node) => visitBinaryArithmetic(node);
262 visitEquals(HEquals node) => visitRelational(node); 328 visitEquals(HEquals node) => visitRelational(node);
263 visitExit(HExit node) => visitControlFlow(node); 329 visitExit(HExit node) => visitControlFlow(node);
264 visitFieldGet(HFieldGet node) => visitInstruction(node); 330 visitFieldGet(HFieldGet node) => visitInstruction(node);
265 visitFieldSet(HFieldSet node) => visitInstruction(node); 331 visitFieldSet(HFieldSet node) => visitInstruction(node);
266 visitForeign(HForeign node) => visitInstruction(node); 332 visitForeign(HForeign node) => visitInstruction(node);
267 visitForeignNew(HForeignNew node) => visitForeign(node); 333 visitForeignNew(HForeignNew node) => visitForeign(node);
268 visitGoto(HGoto node) => visitControlFlow(node); 334 visitGoto(HGoto node) => visitControlFlow(node);
269 visitGreater(HGreater node) => visitRelational(node); 335 visitGreater(HGreater node) => visitRelational(node);
270 visitGreaterEqual(HGreaterEqual node) => visitRelational(node); 336 visitGreaterEqual(HGreaterEqual node) => visitRelational(node);
(...skipping 12 matching lines...) Expand all
283 => visitInvokeDynamicField(node); 349 => visitInvokeDynamicField(node);
284 visitInvokeInterceptor(HInvokeInterceptor node) 350 visitInvokeInterceptor(HInvokeInterceptor node)
285 => visitInvokeStatic(node); 351 => visitInvokeStatic(node);
286 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node); 352 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node);
287 visitInvokeSuper(HInvokeSuper node) => visitInvoke(node); 353 visitInvokeSuper(HInvokeSuper node) => visitInvoke(node);
288 visitLess(HLess node) => visitRelational(node); 354 visitLess(HLess node) => visitRelational(node);
289 visitLessEqual(HLessEqual node) => visitRelational(node); 355 visitLessEqual(HLessEqual node) => visitRelational(node);
290 visitLoad(HLoad node) => visitInstruction(node); 356 visitLoad(HLoad node) => visitInstruction(node);
291 visitLocal(HLocal node) => visitInstruction(node); 357 visitLocal(HLocal node) => visitInstruction(node);
292 visitLogicalOperator(HLogicalOperator node) => visitInstruction(node); 358 visitLogicalOperator(HLogicalOperator node) => visitInstruction(node);
359 visitLiteral(HLiteral node) => visitInstruction(node);
293 visitLiteralList(HLiteralList node) => visitInstruction(node); 360 visitLiteralList(HLiteralList node) => visitInstruction(node);
294 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node); 361 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node);
295 visitModulo(HModulo node) => visitBinaryArithmetic(node); 362 visitModulo(HModulo node) => visitBinaryArithmetic(node);
296 visitNegate(HNegate node) => visitInvokeUnary(node); 363 visitNegate(HNegate node) => visitInvokeUnary(node);
297 visitNot(HNot node) => visitInstruction(node); 364 visitNot(HNot node) => visitInstruction(node);
298 visitPhi(HPhi node) => visitInstruction(node); 365 visitPhi(HPhi node) => visitInstruction(node);
299 visitMultiply(HMultiply node) => visitBinaryArithmetic(node); 366 visitMultiply(HMultiply node) => visitBinaryArithmetic(node);
300 visitParameterValue(HParameterValue node) => visitInstruction(node); 367 visitParameterValue(HParameterValue node) => visitInstruction(node);
301 visitReturn(HReturn node) => visitControlFlow(node); 368 visitReturn(HReturn node) => visitControlFlow(node);
302 visitShiftRight(HShiftRight node) => visitBinaryBitOp(node); 369 visitShiftRight(HShiftRight node) => visitBinaryBitOp(node);
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 inputUsedBy[j] = inputUsedBy[inputUsedBy.length - 1]; 1010 inputUsedBy[j] = inputUsedBy[inputUsedBy.length - 1];
944 inputUsedBy.removeLast(); 1011 inputUsedBy.removeLast();
945 break; 1012 break;
946 } 1013 }
947 } 1014 }
948 } 1015 }
949 this.block = null; 1016 this.block = null;
950 assert(isValid()); 1017 assert(isValid());
951 } 1018 }
952 1019
953 bool isConstantNull() => false; 1020 bool isLiteralNull() => false;
954 bool isConstantNumber() => false; 1021 bool isLiteralNumber() => false;
955 bool isConstantString() => false; 1022 bool isLiteralString() => false;
956 1023
957 bool isValid() { 1024 bool isValid() {
958 HValidator validator = new HValidator(); 1025 HValidator validator = new HValidator();
959 validator.currentBlock = block; 1026 validator.currentBlock = block;
960 validator.visitInstruction(this); 1027 validator.visitInstruction(this);
961 return validator.isValid; 1028 return validator.isValid;
962 } 1029 }
963 } 1030 }
964 1031
965 class HBoolify extends HInstruction { 1032 class HBoolify extends HInstruction {
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
1207 || name == const SourceString('removeLast')) { 1274 || name == const SourceString('removeLast')) {
1208 return HType.ARRAY; 1275 return HType.ARRAY;
1209 } 1276 }
1210 } 1277 }
1211 return HType.UNKNOWN; 1278 return HType.UNKNOWN;
1212 } 1279 }
1213 1280
1214 bool hasExpectedType() => builtinJsName != null; 1281 bool hasExpectedType() => builtinJsName != null;
1215 1282
1216 HInstruction fold(HGraph graph) { 1283 HInstruction fold(HGraph graph) {
1217 if (name == const SourceString('length') && inputs[1].isConstantString()) { 1284 if (name == const SourceString('length') && inputs[1].isLiteralString()) {
1218 HConstant input = inputs[1]; 1285 HLiteral input = inputs[1];
1219 DartString string = input.constant.value; 1286 DartString string = input.value;
1220 return graph.addConstantInt(string.length); 1287 return graph.addNewLiteralInt(string.length);
1221 } 1288 }
1222 return this; 1289 return this;
1223 } 1290 }
1224 1291
1225 void prepareGvn() { 1292 void prepareGvn() {
1226 if (builtinJsName == 'length') { 1293 if (builtinJsName == 'length') {
1227 assert(!hasSideEffects()); 1294 assert(!hasSideEffects());
1228 } else { 1295 } else {
1229 setAllSideEffects(); 1296 setAllSideEffects();
1230 } 1297 }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1305 1372
1306 HType computeInputsType() { 1373 HType computeInputsType() {
1307 HType leftType = left.type; 1374 HType leftType = left.type;
1308 HType rightType = right.type; 1375 HType rightType = right.type;
1309 if (leftType.isUnknown() || rightType.isUnknown()) { 1376 if (leftType.isUnknown() || rightType.isUnknown()) {
1310 return HType.UNKNOWN; 1377 return HType.UNKNOWN;
1311 } 1378 }
1312 return leftType.combine(rightType); 1379 return leftType.combine(rightType);
1313 } 1380 }
1314 1381
1315 HInstruction fold(HGraph graph) { 1382 abstract HInstruction fold(HGraph graph);
1316 if (left is HConstant && right is HConstant) { 1383 abstract evaluate(num a, num b);
1317 HConstant op1 = left;
1318 HConstant op2 = right;
1319 Constant folded =
1320 op1.constant.binaryFold(operationAsString(), op2.constant);
1321 if (folded !== null) return graph.addConstant(folded);
1322 }
1323 return this;
1324 }
1325 abstract String operationAsString();
1326 } 1384 }
1327 1385
1328 class HBinaryArithmetic extends HInvokeBinary { 1386 class HBinaryArithmetic extends HInvokeBinary {
1329 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right) 1387 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right)
1330 : super(target, left, right); 1388 : super(target, left, right);
1331 1389
1332 void prepareGvn() { 1390 void prepareGvn() {
1333 // An arithmetic expression can take part in global value 1391 // An arithmetic expression can take part in global value
1334 // numbering and do not have any side-effects if we know that all 1392 // numbering and do not have any side-effects if we know that all
1335 // inputs are numbers. 1393 // inputs are numbers.
1336 if (builtin) { 1394 if (builtin) {
1337 assert(!hasSideEffects()); 1395 assert(!hasSideEffects());
1338 setUseGvn(); 1396 setUseGvn();
1339 } else { 1397 } else {
1340 setAllSideEffects(); 1398 setAllSideEffects();
1341 } 1399 }
1342 } 1400 }
1343 1401
1402 HInstruction fold(HGraph graph) {
1403 if (left.isLiteralNumber() && right.isLiteralNumber()) {
1404 HLiteral op1 = left;
1405 HLiteral op2 = right;
1406 return graph.addNewLiteralNum(evaluate(op1.value, op2.value), type);
1407 }
1408 return this;
1409 }
1410
1344 HType computeType() { 1411 HType computeType() {
1345 HType type = computeInputsType(); 1412 HType type = computeInputsType();
1346 builtin = type.isNumber(); 1413 builtin = type.isNumber();
1347 if (!type.isUnknown()) return type; 1414 if (!type.isUnknown()) return type;
1348 if (left.isNumber()) return HType.NUMBER; 1415 if (left.isNumber()) return HType.NUMBER;
1349 return HType.UNKNOWN; 1416 return HType.UNKNOWN;
1350 } 1417 }
1351 1418
1352 HType computeDesiredInputType(HInstruction input) { 1419 HType computeDesiredInputType(HInstruction input) {
1353 // TODO(floitsch): we want the target to be a function. 1420 // TODO(floitsch): we want the target to be a function.
1354 if (input == target) return HType.UNKNOWN; 1421 if (input == target) return HType.UNKNOWN;
1355 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER; 1422 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER;
1356 if (type.isUnknown()) return HType.NUMBER; 1423 if (type.isUnknown()) return HType.NUMBER;
1357 return HType.UNKNOWN; 1424 return HType.UNKNOWN;
1358 } 1425 }
1359 1426
1360 bool hasExpectedType() => builtin || type.isUnknown(); 1427 bool hasExpectedType() => builtin || type.isUnknown();
1428
1429 abstract num evaluate(num a, num b);
1361 } 1430 }
1362 1431
1363 class HAdd extends HBinaryArithmetic { 1432 class HAdd extends HBinaryArithmetic {
1364 HAdd(HStatic target, HInstruction left, HInstruction right) 1433 HAdd(HStatic target, HInstruction left, HInstruction right)
1365 : super(target, left, right); 1434 : super(target, left, right);
1366 accept(HVisitor visitor) => visitor.visitAdd(this); 1435 accept(HVisitor visitor) => visitor.visitAdd(this);
1436 num evaluate(num a, num b) => a + b;
1437 int typeCode() => 5;
1438 bool typeEquals(other) => other is HAdd;
1439 bool dataEquals(HInstruction other) => true;
1367 1440
1368 HType computeType() { 1441 HType computeType() {
1369 HType type = computeInputsType(); 1442 HType type = computeInputsType();
1370 builtin = (type.isNumber() || type.isString()); 1443 builtin = (type.isNumber() || type.isString());
1371 if (type.isConflicting() && left.isString()) { 1444 if (type.isConflicting() && left.isString()) {
1372 builtin = right is HConstant; 1445 builtin = right is HLiteral;
1373 return HType.STRING; 1446 return HType.STRING;
1374 } 1447 }
1375 if (!type.isUnknown()) return type; 1448 if (!type.isUnknown()) return type;
1376 if (left.isNumber()) return HType.NUMBER; 1449 if (left.isNumber()) return HType.NUMBER;
1377 return HType.UNKNOWN; 1450 return HType.UNKNOWN;
1378 } 1451 }
1379 1452
1380 bool hasExpectedType() => builtin || type.isUnknown() || left.isString(); 1453 bool hasExpectedType() => builtin || type.isUnknown() || left.isString();
1381 1454
1382 HType computeDesiredInputType(HInstruction input) { 1455 HType computeDesiredInputType(HInstruction input) {
1383 // TODO(floitsch): we want the target to be a function. 1456 // TODO(floitsch): we want the target to be a function.
1384 if (input == target) return HType.UNKNOWN; 1457 if (input == target) return HType.UNKNOWN;
1385 if (isString() || left.isString()) { 1458 if (isString() || left.isString()) {
1386 return (input == left) ? HType.STRING : HType.UNKNOWN; 1459 return (input == left) ? HType.STRING : HType.UNKNOWN;
1387 } 1460 }
1388 if (right.isString()) return HType.STRING; 1461 if (right.isString()) return HType.STRING;
1389 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER; 1462 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER;
1390 return HType.UNKNOWN; 1463 return HType.UNKNOWN;
1391 } 1464 }
1392 1465
1393 HInstruction fold(HGraph graph) { 1466 HInstruction fold(HGraph graph) {
1394 // TODO(floitsch): move this code to the compile-time-constant handler. 1467 if (left.isLiteralString() && right is HLiteral) {
1395 if (left.isConstantString() && right is HConstant) { 1468 HLiteral op1 = left;
1396 HConstant op1 = left; 1469 HLiteral op2 = right;
1397 HConstant op2 = right; 1470 DartString leftString = op1.value;
1398 DartString leftString = op1.constant.value;
1399 DartString otherString = null; 1471 DartString otherString = null;
1400 if (right.isConstantString()) { 1472 if (right.isLiteralString()) {
1401 otherString = op2.constant.value; 1473 otherString = op2.value;
1402 } else { 1474 } else {
1403 assert(op2.isConstantNumber() || 1475 assert(op2.isLiteralNumber() ||
1404 op2.isConstantBoolean() || 1476 op2.isLiteralBoolean() ||
1405 op2.isConstantNull()); 1477 op2.isLiteralNull());
1406 otherString = new DartString.literal(op2.constant.value.toString()); 1478 otherString = new DartString.literal(op2.value.toString());
1407 } 1479 }
1408 DartString cons = new ConsDartString(leftString, otherString); 1480 DartString cons = new ConsDartString(leftString, otherString);
1409 return graph.addConstantString(cons); 1481 return graph.addNewLiteralString(cons);
1410 } 1482 }
1411 return super.fold(graph); 1483 return super.fold(graph);
1412 } 1484 }
1413
1414 String operationAsString() => "+";
1415 int typeCode() => 5;
1416 bool typeEquals(other) => other is HAdd;
1417 bool dataEquals(HInstruction other) => true;
1418 } 1485 }
1419 1486
1420 class HDivide extends HBinaryArithmetic { 1487 class HDivide extends HBinaryArithmetic {
1421 HDivide(HStatic target, HInstruction left, HInstruction right) 1488 HDivide(HStatic target, HInstruction left, HInstruction right)
1422 : super(target, left, right); 1489 : super(target, left, right);
1423 accept(HVisitor visitor) => visitor.visitDivide(this); 1490 accept(HVisitor visitor) => visitor.visitDivide(this);
1424 1491
1425 HType computeType() { 1492 HType computeType() {
1426 HType type = computeInputsType(); 1493 HType type = computeInputsType();
1427 builtin = type.isNumber(); 1494 builtin = type.isNumber();
1428 if (left.isNumber()) return HType.DOUBLE; 1495 if (left.isNumber()) return HType.DOUBLE;
1429 return HType.UNKNOWN; 1496 return HType.UNKNOWN;
1430 } 1497 }
1431 1498
1432 String operationAsString() => "/"; 1499 num evaluate(num a, num b) => a / b;
1433 int typeCode() => 6; 1500 int typeCode() => 6;
1434 bool typeEquals(other) => other is HDivide; 1501 bool typeEquals(other) => other is HDivide;
1435 bool dataEquals(HInstruction other) => true; 1502 bool dataEquals(HInstruction other) => true;
1436 } 1503 }
1437 1504
1438 class HModulo extends HBinaryArithmetic { 1505 class HModulo extends HBinaryArithmetic {
1439 HModulo(HStatic target, HInstruction left, HInstruction right) 1506 HModulo(HStatic target, HInstruction left, HInstruction right)
1440 : super(target, left, right); 1507 : super(target, left, right);
1441 accept(HVisitor visitor) => visitor.visitModulo(this); 1508 accept(HVisitor visitor) => visitor.visitModulo(this);
1442 1509 num evaluate(num a, num b) => a % b;
1443 String operationAsString() => "%";
1444 int typeCode() => 7; 1510 int typeCode() => 7;
1445 bool typeEquals(other) => other is HModulo; 1511 bool typeEquals(other) => other is HModulo;
1446 bool dataEquals(HInstruction other) => true; 1512 bool dataEquals(HInstruction other) => true;
1447 } 1513 }
1448 1514
1449 class HMultiply extends HBinaryArithmetic { 1515 class HMultiply extends HBinaryArithmetic {
1450 HMultiply(HStatic target, HInstruction left, HInstruction right) 1516 HMultiply(HStatic target, HInstruction left, HInstruction right)
1451 : super(target, left, right); 1517 : super(target, left, right);
1452 accept(HVisitor visitor) => visitor.visitMultiply(this); 1518 accept(HVisitor visitor) => visitor.visitMultiply(this);
1453 1519 num evaluate(num a, num b) => a * b;
1454 String operationAsString() => "*";
1455 int typeCode() => 8; 1520 int typeCode() => 8;
1456 bool typeEquals(other) => other is HMultiply; 1521 bool typeEquals(other) => other is HMultiply;
1457 bool dataEquals(HInstruction other) => true; 1522 bool dataEquals(HInstruction other) => true;
1458 } 1523 }
1459 1524
1460 class HSubtract extends HBinaryArithmetic { 1525 class HSubtract extends HBinaryArithmetic {
1461 HSubtract(HStatic target, HInstruction left, HInstruction right) 1526 HSubtract(HStatic target, HInstruction left, HInstruction right)
1462 : super(target, left, right); 1527 : super(target, left, right);
1463 accept(HVisitor visitor) => visitor.visitSubtract(this); 1528 accept(HVisitor visitor) => visitor.visitSubtract(this);
1464 1529 num evaluate(num a, num b) => a - b;
1465 String operationAsString() => "-";
1466 int typeCode() => 9; 1530 int typeCode() => 9;
1467 bool typeEquals(other) => other is HSubtract; 1531 bool typeEquals(other) => other is HSubtract;
1468 bool dataEquals(HInstruction other) => true; 1532 bool dataEquals(HInstruction other) => true;
1469 } 1533 }
1470 1534
1471 class HTruncatingDivide extends HBinaryArithmetic { 1535 class HTruncatingDivide extends HBinaryArithmetic {
1472 HTruncatingDivide(HStatic target, HInstruction left, HInstruction right) 1536 HTruncatingDivide(HStatic target, HInstruction left, HInstruction right)
1473 : super(target, left, right); 1537 : super(target, left, right);
1474 accept(HVisitor visitor) => visitor.visitTruncatingDivide(this); 1538 accept(HVisitor visitor) => visitor.visitTruncatingDivide(this);
1475 1539
1476 String operationAsString() => "~/"; 1540 HInstruction fold(HGraph graph) {
1541 // Avoid a DivisionByZeroException.
1542 if (right.isLiteralNumber() && right.dynamic.value == 0) {
1543 return this;
1544 }
1545 return super.fold(graph);
1546 }
1547
1548 num evaluate(num a, num b) => a ~/ b;
1477 int typeCode() => 10; 1549 int typeCode() => 10;
1478 bool typeEquals(other) => other is HTruncatingDivide; 1550 bool typeEquals(other) => other is HTruncatingDivide;
1479 bool dataEquals(HInstruction other) => true; 1551 bool dataEquals(HInstruction other) => true;
1480 } 1552 }
1481 1553
1482 1554
1483 // TODO(floitsch): Should HBinaryArithmetic really be the super class of 1555 // TODO(floitsch): Should HBinaryArithmetic really be the super class of
1484 // HBinaryBitOp? 1556 // HBinaryBitOp?
1485 class HBinaryBitOp extends HBinaryArithmetic { 1557 class HBinaryBitOp extends HBinaryArithmetic {
1486 HBinaryBitOp(HStatic target, HInstruction left, HInstruction right) 1558 HBinaryBitOp(HStatic target, HInstruction left, HInstruction right)
1487 : super(target, left, right); 1559 : super(target, left, right);
1488 1560
1489 HType computeType() { 1561 HType computeType() {
1490 HType type = computeInputsType(); 1562 HType type = computeInputsType();
1491 builtin = type.isInteger(); 1563 builtin = type.isInteger();
1492 if (!type.isUnknown()) return type; 1564 if (!type.isUnknown()) return type;
1493 if (left.isInteger()) return HType.INTEGER; 1565 if (left.isInteger()) return HType.INTEGER;
1494 return HType.UNKNOWN; 1566 return HType.UNKNOWN;
1495 } 1567 }
1496 1568
1497 HType computeDesiredInputType(HInstruction input) { 1569 HType computeDesiredInputType(HInstruction input) {
1498 // TODO(floitsch): we want the target to be a function. 1570 // TODO(floitsch): we want the target to be a function.
1499 if (input == target) return HType.UNKNOWN; 1571 if (input == target) return HType.UNKNOWN;
1500 return HType.INTEGER; 1572 return HType.INTEGER;
1501 } 1573 }
1502 1574
1575 HInstruction fold(HGraph graph) {
1576 // Bit-operations are only defined on integers.
1577 if (left.isLiteralNumber() && right.isLiteralNumber()) {
1578 HLiteral op1 = left;
1579 HLiteral op2 = right;
1580 // Avoid exceptions.
1581 if (op1.isInteger() && op2.isInteger()) {
1582 return graph.addNewLiteralInt(evaluate(op1.value, op2.value));
1583 }
1584 }
1585 return this;
1586 }
1587
1503 // TODO(floitsch): make class abstract instead of adding an abstract method. 1588 // TODO(floitsch): make class abstract instead of adding an abstract method.
1504 abstract accept(HVisitor visitor); 1589 abstract accept(HVisitor visitor);
1505 } 1590 }
1506 1591
1507 class HShiftLeft extends HBinaryBitOp { 1592 class HShiftLeft extends HBinaryBitOp {
1508 HShiftLeft(HStatic target, HInstruction left, HInstruction right) 1593 HShiftLeft(HStatic target, HInstruction left, HInstruction right)
1509 : super(target, left, right); 1594 : super(target, left, right);
1510 accept(HVisitor visitor) => visitor.visitShiftLeft(this); 1595 accept(HVisitor visitor) => visitor.visitShiftLeft(this);
1511 1596
1512 String operationAsString() => "<<"; 1597 HInstruction fold(HGraph graph) {
1598 if (right.isLiteralNumber()) {
1599 // TODO(floitsch): find good max left-shift amount.
1600 final int MAX_SHIFT_LEFT_AMOUNT = 50;
1601 HLiteral op2 = right;
1602 // Only positive shifting is allowed. Also guard against out-of-memory
1603 // shifts.
1604 if (op2.value < 0 || op2.value > MAX_SHIFT_LEFT_AMOUNT) return this;
1605 }
1606 return super.fold(graph);
1607 }
1608
1609 int evaluate(int a, int b) => a << b;
1513 int typeCode() => 11; 1610 int typeCode() => 11;
1514 bool typeEquals(other) => other is HShiftLeft; 1611 bool typeEquals(other) => other is HShiftLeft;
1515 bool dataEquals(HInstruction other) => true; 1612 bool dataEquals(HInstruction other) => true;
1516 } 1613 }
1517 1614
1518 class HShiftRight extends HBinaryBitOp { 1615 class HShiftRight extends HBinaryBitOp {
1519 HShiftRight(HStatic target, HInstruction left, HInstruction right) 1616 HShiftRight(HStatic target, HInstruction left, HInstruction right)
1520 : super(target, left, right); 1617 : super(target, left, right);
1521 accept(HVisitor visitor) => visitor.visitShiftRight(this); 1618 accept(HVisitor visitor) => visitor.visitShiftRight(this);
1522 1619
1523 String operationAsString() => ">>"; 1620 HInstruction fold(HGraph graph) {
1621 if (right.isLiteralNumber()) {
1622 HLiteral op2 = right;
1623 // Only positive shifting is allowed.
1624 if (op2.value < 0) return this;
1625 }
1626 return super.fold(graph);
1627 }
1628
1629 int evaluate(int a, int b) => a >> b;
1524 int typeCode() => 12; 1630 int typeCode() => 12;
1525 bool typeEquals(other) => other is HShiftRight; 1631 bool typeEquals(other) => other is HShiftRight;
1526 bool dataEquals(HInstruction other) => true; 1632 bool dataEquals(HInstruction other) => true;
1527 } 1633 }
1528 1634
1529 class HBitOr extends HBinaryBitOp { 1635 class HBitOr extends HBinaryBitOp {
1530 HBitOr(HStatic target, HInstruction left, HInstruction right) 1636 HBitOr(HStatic target, HInstruction left, HInstruction right)
1531 : super(target, left, right); 1637 : super(target, left, right);
1532 accept(HVisitor visitor) => visitor.visitBitOr(this); 1638 accept(HVisitor visitor) => visitor.visitBitOr(this);
1533 1639
1534 String operationAsString() => "|"; 1640 int evaluate(int a, int b) => a | b;
1535 int typeCode() => 13; 1641 int typeCode() => 13;
1536 bool typeEquals(other) => other is HBitOr; 1642 bool typeEquals(other) => other is HBitOr;
1537 bool dataEquals(HInstruction other) => true; 1643 bool dataEquals(HInstruction other) => true;
1538 } 1644 }
1539 1645
1540 class HBitAnd extends HBinaryBitOp { 1646 class HBitAnd extends HBinaryBitOp {
1541 HBitAnd(HStatic target, HInstruction left, HInstruction right) 1647 HBitAnd(HStatic target, HInstruction left, HInstruction right)
1542 : super(target, left, right); 1648 : super(target, left, right);
1543 accept(HVisitor visitor) => visitor.visitBitAnd(this); 1649 accept(HVisitor visitor) => visitor.visitBitAnd(this);
1544 1650
1545 String operationAsString() => "&"; 1651 int evaluate(int a, int b) => a & b;
1546 int typeCode() => 14; 1652 int typeCode() => 14;
1547 bool typeEquals(other) => other is HBitAnd; 1653 bool typeEquals(other) => other is HBitAnd;
1548 bool dataEquals(HInstruction other) => true; 1654 bool dataEquals(HInstruction other) => true;
1549 } 1655 }
1550 1656
1551 class HBitXor extends HBinaryBitOp { 1657 class HBitXor extends HBinaryBitOp {
1552 HBitXor(HStatic target, HInstruction left, HInstruction right) 1658 HBitXor(HStatic target, HInstruction left, HInstruction right)
1553 : super(target, left, right); 1659 : super(target, left, right);
1554 accept(HVisitor visitor) => visitor.visitBitXor(this); 1660 accept(HVisitor visitor) => visitor.visitBitXor(this);
1555 1661
1556 String operationAsString() => "^"; 1662 int evaluate(int a, int b) => a ^ b;
1557 int typeCode() => 15; 1663 int typeCode() => 15;
1558 bool typeEquals(other) => other is HBitXor; 1664 bool typeEquals(other) => other is HBitXor;
1559 bool dataEquals(HInstruction other) => true; 1665 bool dataEquals(HInstruction other) => true;
1560 } 1666 }
1561 1667
1562 class HInvokeUnary extends HInvokeStatic { 1668 class HInvokeUnary extends HInvokeStatic {
1563 HInvokeUnary(HStatic target, HInstruction input) 1669 HInvokeUnary(HStatic target, HInstruction input)
1564 : super(Selector.UNARY_OPERATOR, <HInstruction>[target, input]); 1670 : super(Selector.UNARY_OPERATOR, <HInstruction>[target, input]);
1565 1671
1566 HInstruction get operand() => inputs[1]; 1672 HInstruction get operand() => inputs[1];
(...skipping 19 matching lines...) Expand all
1586 1692
1587 HType computeDesiredInputType(HInstruction input) { 1693 HType computeDesiredInputType(HInstruction input) {
1588 // TODO(floitsch): we want the target to be a function. 1694 // TODO(floitsch): we want the target to be a function.
1589 if (input == target) return HType.UNKNOWN; 1695 if (input == target) return HType.UNKNOWN;
1590 if (type.isUnknown() || type.isNumber()) return HType.NUMBER; 1696 if (type.isUnknown() || type.isNumber()) return HType.NUMBER;
1591 return HType.UNKNOWN; 1697 return HType.UNKNOWN;
1592 } 1698 }
1593 1699
1594 bool hasExpectedType() => builtin || (type.isUnknown()); 1700 bool hasExpectedType() => builtin || (type.isUnknown());
1595 1701
1596 HInstruction fold(HGraph graph) { 1702 abstract HInstruction fold(HGraph graph);
1597 if (operand is HConstant) {
1598 HConstant op = operand;
1599 Constant folded = op.constant.unaryFold(operationAsString());
1600 if (folded !== null) return graph.addConstant(folded);
1601 }
1602 return this;
1603 }
1604 1703
1605 abstract String operationAsString(); 1704 abstract num evaluate(num a);
1606 } 1705 }
1607 1706
1608 class HNegate extends HInvokeUnary { 1707 class HNegate extends HInvokeUnary {
1609 HNegate(HStatic target, HInstruction input) : super(target, input); 1708 HNegate(HStatic target, HInstruction input) : super(target, input);
1610 accept(HVisitor visitor) => visitor.visitNegate(this); 1709 accept(HVisitor visitor) => visitor.visitNegate(this);
1611 1710
1612 String operationAsString() => "-"; 1711 HInstruction fold(HGraph graph) {
1712 if (operand.isLiteralNumber()) {
1713 HLiteral input = operand;
1714 return graph.addNewLiteralNum(evaluate(input.value), type);
1715 }
1716 return this;
1717 }
1718
1719 num evaluate(num a) => -a;
1613 int typeCode() => 16; 1720 int typeCode() => 16;
1614 bool typeEquals(other) => other is HNegate; 1721 bool typeEquals(other) => other is HNegate;
1615 bool dataEquals(HInstruction other) => true; 1722 bool dataEquals(HInstruction other) => true;
1616 } 1723 }
1617 1724
1618 class HBitNot extends HInvokeUnary { 1725 class HBitNot extends HInvokeUnary {
1619 HBitNot(HStatic target, HInstruction input) : super(target, input); 1726 HBitNot(HStatic target, HInstruction input) : super(target, input);
1620 accept(HVisitor visitor) => visitor.visitBitNot(this); 1727 accept(HVisitor visitor) => visitor.visitBitNot(this);
1621 1728
1622 HType computeType() { 1729 HType computeType() {
1623 HType type = operand.type; 1730 HType type = operand.type;
1624 builtin = type.isInteger(); 1731 builtin = type.isInteger();
1625 if (!type.isUnknown()) return type; 1732 if (!type.isUnknown()) return type;
1626 return HType.UNKNOWN; 1733 return HType.UNKNOWN;
1627 } 1734 }
1628 1735
1629 HType computeDesiredInputType(HInstruction input) { 1736 HType computeDesiredInputType(HInstruction input) {
1630 // TODO(floitsch): we want the target to be a function. 1737 // TODO(floitsch): we want the target to be a function.
1631 if (input == target) return HType.UNKNOWN; 1738 if (input == target) return HType.UNKNOWN;
1632 return HType.INTEGER; 1739 return HType.INTEGER;
1633 } 1740 }
1634 1741
1635 String operationAsString() => "~"; 1742 HInstruction fold(HGraph graph) {
1743 if (operand.isLiteralNumber()) {
1744 HLiteral input = operand;
1745 if (input.isInteger()) {
1746 return graph.addNewLiteralInt(evaluate(input.value));
1747 }
1748 }
1749 return this;
1750 }
1751
1752 int evaluate(int a) => ~a;
1636 int typeCode() => 17; 1753 int typeCode() => 17;
1637 bool typeEquals(other) => other is HBitNot; 1754 bool typeEquals(other) => other is HBitNot;
1638 bool dataEquals(HInstruction other) => true; 1755 bool dataEquals(HInstruction other) => true;
1639 } 1756 }
1640 1757
1641 class HExit extends HControlFlow { 1758 class HExit extends HControlFlow {
1642 HExit() : super(const <HInstruction>[]); 1759 HExit() : super(const <HInstruction>[]);
1643 toString() => 'exit'; 1760 toString() => 'exit';
1644 accept(HVisitor visitor) => visitor.visitExit(this); 1761 accept(HVisitor visitor) => visitor.visitExit(this);
1645 } 1762 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1698 HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP]) 1815 HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP])
1699 : super(<HInstruction>[condition]); 1816 : super(<HInstruction>[condition]);
1700 toString() => 'loop-branch'; 1817 toString() => 'loop-branch';
1701 accept(HVisitor visitor) => visitor.visitLoopBranch(this); 1818 accept(HVisitor visitor) => visitor.visitLoopBranch(this);
1702 1819
1703 bool isDoWhile() { 1820 bool isDoWhile() {
1704 return kind === DO_WHILE_LOOP; 1821 return kind === DO_WHILE_LOOP;
1705 } 1822 }
1706 } 1823 }
1707 1824
1708 class HConstant extends HInstruction { 1825 class HLiteral extends HInstruction {
1709 final Constant constant; 1826 final value;
1710 HConstant.internal(this.constant, HType type) : super(<HInstruction>[]) { 1827 HLiteral.internal(this.value, HType type) : super(<HInstruction>[]) {
1711 this.type = type; 1828 this.type = type;
1712 tryGenerateAtUseSite(); // Maybe avoid this if the literal is big? 1829 tryGenerateAtUseSite(); // Maybe avoid this if the literal is big?
1713 } 1830 }
1714 1831
1715 void prepareGvn() { 1832 void prepareGvn() {
1716 assert(!hasSideEffects()); 1833 assert(!hasSideEffects());
1717 } 1834 }
1718 1835
1719 toString() => 'literal: $constant'; 1836 toString() => 'literal: $value';
1720 accept(HVisitor visitor) => visitor.visitConstant(this); 1837 accept(HVisitor visitor) => visitor.visitLiteral(this);
1721 HType computeType() => type; 1838 HType computeType() => type;
1722 1839
1723 // Literals have the type they have. It can't be changed. 1840 // Literals have the type they have. It can't be changed.
1724 bool updateType() => false; 1841 bool updateType() => false;
1725 1842
1726 bool hasExpectedType() => true; 1843 bool hasExpectedType() => true;
1727 1844
1728 bool isConstantBoolean() => constant.isBool(); 1845 bool isLiteralBoolean() => value is bool;
1729 bool isConstantNull() => constant.isNull(); 1846 bool isLiteralNull() => value === null;
1730 bool isConstantNumber() => constant.isNum(); 1847 bool isLiteralNumber() => value is num;
1731 bool isConstantString() => constant.isString(); 1848 bool isLiteralString() => value is DartString;
1732 } 1849 }
1733 1850
1734 class HNot extends HInstruction { 1851 class HNot extends HInstruction {
1735 HNot(HInstruction value) : super(<HInstruction>[value]); 1852 HNot(HInstruction value) : super(<HInstruction>[value]);
1736 void prepareGvn() { 1853 void prepareGvn() {
1737 assert(!hasSideEffects()); 1854 assert(!hasSideEffects());
1738 setUseGvn(); 1855 setUseGvn();
1739 } 1856 }
1740 1857
1741 HType computeType() => HType.BOOLEAN; 1858 HType computeType() => HType.BOOLEAN;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1860 // and do not have any side-effects if we know all the inputs are 1977 // and do not have any side-effects if we know all the inputs are
1861 // numbers. This can be improved for at least equality. 1978 // numbers. This can be improved for at least equality.
1862 if (builtin) { 1979 if (builtin) {
1863 assert(!hasSideEffects()); 1980 assert(!hasSideEffects());
1864 setUseGvn(); 1981 setUseGvn();
1865 } else { 1982 } else {
1866 setAllSideEffects(); 1983 setAllSideEffects();
1867 } 1984 }
1868 } 1985 }
1869 1986
1987 HInstruction fold(HGraph graph) {
1988 if (left.isLiteralNumber() && right.isLiteralNumber()) {
1989 HLiteral op1 = left;
1990 HLiteral op2 = right;
1991 return graph.addNewLiteralBool(evaluate(op1.value, op2.value));
1992 }
1993 return this;
1994 }
1995
1870 HType computeType() { 1996 HType computeType() {
1871 builtin = computeInputsType().isNumber(); 1997 builtin = computeInputsType().isNumber();
1872 return HType.BOOLEAN; 1998 return HType.BOOLEAN;
1873 } 1999 }
1874 2000
1875 HType computeDesiredInputType(HInstruction input) { 2001 HType computeDesiredInputType(HInstruction input) {
1876 // TODO(floitsch): we want the target to be a function. 2002 // TODO(floitsch): we want the target to be a function.
1877 if (input == target) return HType.UNKNOWN; 2003 if (input == target) return HType.UNKNOWN;
1878 // For all relational operations exept HEquals, we expect to only 2004 // For all relational operations exept HEquals, we expect to only
1879 // get numbers. 2005 // get numbers.
1880 return HType.NUMBER; 2006 return HType.NUMBER;
1881 } 2007 }
1882 2008
1883 // A HRelational goes through the builtin operator or the top level 2009 // A HRelational goes through the builtin operator or the top level
1884 // element. Therefore, it always has the expected type. 2010 // element. Therefore, it always has the expected type.
1885 bool hasExpectedType() => true; 2011 bool hasExpectedType() => true;
2012
2013 abstract bool evaluate(num a, num b);
1886 } 2014 }
1887 2015
1888 class HEquals extends HRelational { 2016 class HEquals extends HRelational {
1889 HEquals(HStatic target, HInstruction left, HInstruction right) 2017 HEquals(HStatic target, HInstruction left, HInstruction right)
1890 : super(target, left, right); 2018 : super(target, left, right);
2019 bool evaluate(num a, num b) => a == b;
1891 accept(HVisitor visitor) => visitor.visitEquals(this); 2020 accept(HVisitor visitor) => visitor.visitEquals(this);
2021 int typeCode() => 19;
2022 bool typeEquals(other) => other is HEquals;
2023 bool dataEquals(HInstruction other) => true;
1892 2024
1893 HType computeType() { 2025 HType computeType() {
1894 builtin = computeInputsType().isNumber() || (left is HConstant); 2026 builtin = computeInputsType().isNumber() || (left is HLiteral);
1895 return HType.BOOLEAN; 2027 return HType.BOOLEAN;
1896 } 2028 }
1897 2029
1898 HType computeDesiredInputType(HInstruction input) { 2030 HType computeDesiredInputType(HInstruction input) {
1899 // TODO(floitsch): we want the target to be a function. 2031 // TODO(floitsch): we want the target to be a function.
1900 if (input == target) return HType.UNKNOWN; 2032 if (input == target) return HType.UNKNOWN;
1901 if (left.isNumber() || right.isNumber()) return HType.NUMBER; 2033 if (left.isNumber() || right.isNumber()) return HType.NUMBER;
1902 return HType.UNKNOWN; 2034 return HType.UNKNOWN;
1903 } 2035 }
1904
1905 String operationAsString() => "==";
1906 int typeCode() => 19;
1907 bool typeEquals(other) => other is HEquals;
1908 bool dataEquals(HInstruction other) => true;
1909 } 2036 }
1910 2037
1911 class HIdentity extends HRelational { 2038 class HIdentity extends HRelational {
1912 HIdentity(HStatic target, HInstruction left, HInstruction right) 2039 HIdentity(HStatic target, HInstruction left, HInstruction right)
1913 : super(target, left, right); 2040 : super(target, left, right);
2041 bool evaluate(num a, num b) => a === b;
1914 accept(HVisitor visitor) => visitor.visitIdentity(this); 2042 accept(HVisitor visitor) => visitor.visitIdentity(this);
2043 int typeCode() => 20;
2044 bool typeEquals(other) => other is HIdentity;
2045 bool dataEquals(HInstruction other) => true;
1915 2046
1916 HType computeType() { 2047 HType computeType() {
1917 builtin = true; 2048 builtin = true;
1918 return HType.BOOLEAN; 2049 return HType.BOOLEAN;
1919 } 2050 }
1920 2051
1921 bool hasExpectedType() => true; 2052 bool hasExpectedType() => true;
1922 2053
1923 HType computeDesiredInputType(HInstruction input) => HType.UNKNOWN; 2054 HType computeDesiredInputType(HInstruction input) => HType.UNKNOWN;
1924
1925 String operationAsString() => "===";
1926 int typeCode() => 20;
1927 bool typeEquals(other) => other is HIdentity;
1928 bool dataEquals(HInstruction other) => true;
1929 } 2055 }
1930 2056
1931 class HGreater extends HRelational { 2057 class HGreater extends HRelational {
1932 HGreater(HStatic target, HInstruction left, HInstruction right) 2058 HGreater(HStatic target, HInstruction left, HInstruction right)
1933 : super(target, left, right); 2059 : super(target, left, right);
2060 bool evaluate(num a, num b) => a > b;
1934 accept(HVisitor visitor) => visitor.visitGreater(this); 2061 accept(HVisitor visitor) => visitor.visitGreater(this);
1935
1936 String operationAsString() => ">";
1937 int typeCode() => 21; 2062 int typeCode() => 21;
1938 bool typeEquals(other) => other is HGreater; 2063 bool typeEquals(other) => other is HGreater;
1939 bool dataEquals(HInstruction other) => true; 2064 bool dataEquals(HInstruction other) => true;
1940 } 2065 }
1941 2066
1942 class HGreaterEqual extends HRelational { 2067 class HGreaterEqual extends HRelational {
1943 HGreaterEqual(HStatic target, HInstruction left, HInstruction right) 2068 HGreaterEqual(HStatic target, HInstruction left, HInstruction right)
1944 : super(target, left, right); 2069 : super(target, left, right);
2070 bool evaluate(num a, num b) => a >= b;
1945 accept(HVisitor visitor) => visitor.visitGreaterEqual(this); 2071 accept(HVisitor visitor) => visitor.visitGreaterEqual(this);
1946
1947 String operationAsString() => ">=";
1948 int typeCode() => 22; 2072 int typeCode() => 22;
1949 bool typeEquals(other) => other is HGreaterEqual; 2073 bool typeEquals(other) => other is HGreaterEqual;
1950 bool dataEquals(HInstruction other) => true; 2074 bool dataEquals(HInstruction other) => true;
1951 } 2075 }
1952 2076
1953 class HLess extends HRelational { 2077 class HLess extends HRelational {
1954 HLess(HStatic target, HInstruction left, HInstruction right) 2078 HLess(HStatic target, HInstruction left, HInstruction right)
1955 : super(target, left, right); 2079 : super(target, left, right);
2080 bool evaluate(num a, num b) => a < b;
1956 accept(HVisitor visitor) => visitor.visitLess(this); 2081 accept(HVisitor visitor) => visitor.visitLess(this);
1957
1958 String operationAsString() => "<";
1959 int typeCode() => 23;
1960 bool typeEquals(other) => other is HLess; 2082 bool typeEquals(other) => other is HLess;
1961 bool dataEquals(HInstruction other) => true; 2083 bool dataEquals(HInstruction other) => true;
1962 } 2084 }
1963 2085
1964 class HLessEqual extends HRelational { 2086 class HLessEqual extends HRelational {
1965 HLessEqual(HStatic target, HInstruction left, HInstruction right) 2087 HLessEqual(HStatic target, HInstruction left, HInstruction right)
1966 : super(target, left, right); 2088 : super(target, left, right);
2089 bool evaluate(num a, num b) => a <= b;
1967 accept(HVisitor visitor) => visitor.visitLessEqual(this); 2090 accept(HVisitor visitor) => visitor.visitLessEqual(this);
1968 2091 int typeCode() => 23;
1969 String operationAsString() => "<=";
1970 int typeCode() => 24;
1971 bool typeEquals(other) => other is HLessEqual; 2092 bool typeEquals(other) => other is HLessEqual;
1972 bool dataEquals(HInstruction other) => true; 2093 bool dataEquals(HInstruction other) => true;
1973 } 2094 }
1974 2095
1975 class HReturn extends HControlFlow { 2096 class HReturn extends HControlFlow {
1976 HReturn(value) : super(<HInstruction>[value]); 2097 HReturn(value) : super(<HInstruction>[value]);
1977 toString() => 'return'; 2098 toString() => 'return';
1978 accept(HVisitor visitor) => visitor.visitReturn(this); 2099 accept(HVisitor visitor) => visitor.visitReturn(this);
1979 } 2100 }
1980 2101
(...skipping 12 matching lines...) Expand all
1993 void prepareGvn() { 2114 void prepareGvn() {
1994 assert(!hasSideEffects()); 2115 assert(!hasSideEffects());
1995 if (!element.isAssignable()) { 2116 if (!element.isAssignable()) {
1996 setUseGvn(); 2117 setUseGvn();
1997 } 2118 }
1998 } 2119 }
1999 toString() => 'static ${element.name}'; 2120 toString() => 'static ${element.name}';
2000 accept(HVisitor visitor) => visitor.visitStatic(this); 2121 accept(HVisitor visitor) => visitor.visitStatic(this);
2001 2122
2002 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode(); 2123 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode();
2003 int typeCode() => 25; 2124 int typeCode() => 24;
2004 bool typeEquals(other) => other is HStatic; 2125 bool typeEquals(other) => other is HStatic;
2005 bool dataEquals(HStatic other) => element == other.element; 2126 bool dataEquals(HStatic other) => element == other.element;
2006 } 2127 }
2007 2128
2008 class HStaticStore extends HInstruction { 2129 class HStaticStore extends HInstruction {
2009 Element element; 2130 Element element;
2010 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]); 2131 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]);
2011 toString() => 'static store ${element.name}'; 2132 toString() => 'static store ${element.name}';
2012 accept(HVisitor visitor) => visitor.visitStaticStore(this); 2133 accept(HVisitor visitor) => visitor.visitStaticStore(this);
2013 2134
2014 int typeCode() => 26; 2135 int typeCode() => 25;
2015 bool typeEquals(other) => other is HStaticStore; 2136 bool typeEquals(other) => other is HStaticStore;
2016 bool dataEquals(HStaticStore other) => element == other.element; 2137 bool dataEquals(HStaticStore other) => element == other.element;
2017 } 2138 }
2018 2139
2019 class HLiteralList extends HInstruction { 2140 class HLiteralList extends HInstruction {
2020 HLiteralList(inputs, this.isConst) : super(inputs); 2141 HLiteralList(inputs, this.isConst) : super(inputs);
2021 toString() => 'literal list'; 2142 toString() => 'literal list';
2022 accept(HVisitor visitor) => visitor.visitLiteralList(this); 2143 accept(HVisitor visitor) => visitor.visitLiteralList(this);
2023 HType computeType() => HType.ARRAY; 2144 HType computeType() => HType.ARRAY;
2024 bool hasExpectedType() => true; 2145 bool hasExpectedType() => true;
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
2161 class HIfBlockInformation { 2282 class HIfBlockInformation {
2162 final HIf branch; 2283 final HIf branch;
2163 final SubGraph thenGraph; 2284 final SubGraph thenGraph;
2164 final SubGraph elseGraph; 2285 final SubGraph elseGraph;
2165 final HBasicBlock joinBlock; 2286 final HBasicBlock joinBlock;
2166 HIfBlockInformation(this.branch, 2287 HIfBlockInformation(this.branch,
2167 this.thenGraph, 2288 this.thenGraph,
2168 this.elseGraph, 2289 this.elseGraph,
2169 this.joinBlock); 2290 this.joinBlock);
2170 } 2291 }
OLDNEW
« no previous file with comments | « dart/frog/leg/ssa/codegen.dart ('k') | dart/frog/leg/ssa/optimize.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698