Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 HType mapConstantTypeToSsaType(Constant constant) { |
|
kasperl
2012/03/05 13:53:16
static?
floitsch
2012/03/05 15:43:24
Done.
| |
| 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 addNewConstant(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() { | |
| 169 if (nanLiteral === null) { | |
| 170 nanLiteral = new HLiteral.internal(double.NAN, HType.DOUBLE); | |
| 171 entry.addAtExit(nanLiteral); | |
| 172 } | |
| 173 return nanLiteral; | |
| 174 } | |
| 175 | |
| 176 HLiteral addNewNegativeZeroLiteral() { | |
| 177 if (negativeZeroLiteral === null) { | |
| 178 negativeZeroLiteral = new HLiteral.internal(-0.0, HType.DOUBLE); | |
| 179 entry.addAtExit(negativeZeroLiteral); | |
| 180 } | |
| 181 return negativeZeroLiteral; | |
| 182 } | |
| 183 | |
| 184 HLiteral addNewLiteralDouble(double value) { | |
| 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; | |
| 198 } | |
| 199 | |
| 200 HLiteral addNewLiteralNum(num value, HType type) { | |
| 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; | |
| 217 } | |
| 218 | |
| 219 HLiteral addNewLiteralTrue() { | |
| 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; | |
| 257 } | |
| 258 | |
| 259 void finalize() { | 172 void finalize() { |
| 260 addBlock(exit); | 173 addBlock(exit); |
| 261 exit.open(); | 174 exit.open(); |
| 262 exit.close(new HExit()); | 175 exit.close(new HExit()); |
| 263 assignDominators(); | 176 assignDominators(); |
| 264 } | 177 } |
| 265 | 178 |
| 266 void assignDominators() { | 179 void assignDominators() { |
| 267 // Run through the blocks in order of increasing ids so we are | 180 // Run through the blocks in order of increasing ids so we are |
| 268 // guaranteed that we have computed dominators for all blocks | 181 // guaranteed that we have computed dominators for all blocks |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 317 visitAdd(HAdd node) => visitBinaryArithmetic(node); | 230 visitAdd(HAdd node) => visitBinaryArithmetic(node); |
| 318 visitBitAnd(HBitAnd node) => visitBinaryBitOp(node); | 231 visitBitAnd(HBitAnd node) => visitBinaryBitOp(node); |
| 319 visitBitNot(HBitNot node) => visitInvokeUnary(node); | 232 visitBitNot(HBitNot node) => visitInvokeUnary(node); |
| 320 visitBitOr(HBitOr node) => visitBinaryBitOp(node); | 233 visitBitOr(HBitOr node) => visitBinaryBitOp(node); |
| 321 visitBitXor(HBitXor node) => visitBinaryBitOp(node); | 234 visitBitXor(HBitXor node) => visitBinaryBitOp(node); |
| 322 visitBailoutTarget(HBailoutTarget node) => visitInstruction(node); | 235 visitBailoutTarget(HBailoutTarget node) => visitInstruction(node); |
| 323 visitBoolify(HBoolify node) => visitInstruction(node); | 236 visitBoolify(HBoolify node) => visitInstruction(node); |
| 324 visitBoundsCheck(HBoundsCheck node) => visitCheck(node); | 237 visitBoundsCheck(HBoundsCheck node) => visitCheck(node); |
| 325 visitBreak(HBreak node) => visitGoto(node); | 238 visitBreak(HBreak node) => visitGoto(node); |
| 326 visitCheck(HCheck node) => visitInstruction(node); | 239 visitCheck(HCheck node) => visitInstruction(node); |
| 240 visitConstant(HConstant node) => visitInstruction(node); | |
| 327 visitDivide(HDivide node) => visitBinaryArithmetic(node); | 241 visitDivide(HDivide node) => visitBinaryArithmetic(node); |
| 328 visitEquals(HEquals node) => visitRelational(node); | 242 visitEquals(HEquals node) => visitRelational(node); |
| 329 visitExit(HExit node) => visitControlFlow(node); | 243 visitExit(HExit node) => visitControlFlow(node); |
| 330 visitFieldGet(HFieldGet node) => visitInstruction(node); | 244 visitFieldGet(HFieldGet node) => visitInstruction(node); |
| 331 visitFieldSet(HFieldSet node) => visitInstruction(node); | 245 visitFieldSet(HFieldSet node) => visitInstruction(node); |
| 332 visitForeign(HForeign node) => visitInstruction(node); | 246 visitForeign(HForeign node) => visitInstruction(node); |
| 333 visitForeignNew(HForeignNew node) => visitForeign(node); | 247 visitForeignNew(HForeignNew node) => visitForeign(node); |
| 334 visitGoto(HGoto node) => visitControlFlow(node); | 248 visitGoto(HGoto node) => visitControlFlow(node); |
| 335 visitGreater(HGreater node) => visitRelational(node); | 249 visitGreater(HGreater node) => visitRelational(node); |
| 336 visitGreaterEqual(HGreaterEqual node) => visitRelational(node); | 250 visitGreaterEqual(HGreaterEqual node) => visitRelational(node); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 349 => visitInvokeDynamicField(node); | 263 => visitInvokeDynamicField(node); |
| 350 visitInvokeInterceptor(HInvokeInterceptor node) | 264 visitInvokeInterceptor(HInvokeInterceptor node) |
| 351 => visitInvokeStatic(node); | 265 => visitInvokeStatic(node); |
| 352 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node); | 266 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node); |
| 353 visitInvokeSuper(HInvokeSuper node) => visitInvoke(node); | 267 visitInvokeSuper(HInvokeSuper node) => visitInvoke(node); |
| 354 visitLess(HLess node) => visitRelational(node); | 268 visitLess(HLess node) => visitRelational(node); |
| 355 visitLessEqual(HLessEqual node) => visitRelational(node); | 269 visitLessEqual(HLessEqual node) => visitRelational(node); |
| 356 visitLoad(HLoad node) => visitInstruction(node); | 270 visitLoad(HLoad node) => visitInstruction(node); |
| 357 visitLocal(HLocal node) => visitInstruction(node); | 271 visitLocal(HLocal node) => visitInstruction(node); |
| 358 visitLogicalOperator(HLogicalOperator node) => visitInstruction(node); | 272 visitLogicalOperator(HLogicalOperator node) => visitInstruction(node); |
| 359 visitLiteral(HLiteral node) => visitInstruction(node); | |
| 360 visitLiteralList(HLiteralList node) => visitInstruction(node); | 273 visitLiteralList(HLiteralList node) => visitInstruction(node); |
| 361 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node); | 274 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node); |
| 362 visitModulo(HModulo node) => visitBinaryArithmetic(node); | 275 visitModulo(HModulo node) => visitBinaryArithmetic(node); |
| 363 visitNegate(HNegate node) => visitInvokeUnary(node); | 276 visitNegate(HNegate node) => visitInvokeUnary(node); |
| 364 visitNot(HNot node) => visitInstruction(node); | 277 visitNot(HNot node) => visitInstruction(node); |
| 365 visitPhi(HPhi node) => visitInstruction(node); | 278 visitPhi(HPhi node) => visitInstruction(node); |
| 366 visitMultiply(HMultiply node) => visitBinaryArithmetic(node); | 279 visitMultiply(HMultiply node) => visitBinaryArithmetic(node); |
| 367 visitParameterValue(HParameterValue node) => visitInstruction(node); | 280 visitParameterValue(HParameterValue node) => visitInstruction(node); |
| 368 visitReturn(HReturn node) => visitControlFlow(node); | 281 visitReturn(HReturn node) => visitControlFlow(node); |
| 369 visitShiftRight(HShiftRight node) => visitBinaryBitOp(node); | 282 visitShiftRight(HShiftRight node) => visitBinaryBitOp(node); |
| (...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 998 inputUsedBy[j] = inputUsedBy[inputUsedBy.length - 1]; | 911 inputUsedBy[j] = inputUsedBy[inputUsedBy.length - 1]; |
| 999 inputUsedBy.removeLast(); | 912 inputUsedBy.removeLast(); |
| 1000 break; | 913 break; |
| 1001 } | 914 } |
| 1002 } | 915 } |
| 1003 } | 916 } |
| 1004 this.block = null; | 917 this.block = null; |
| 1005 assert(isValid()); | 918 assert(isValid()); |
| 1006 } | 919 } |
| 1007 | 920 |
| 1008 bool isLiteralNull() => false; | 921 bool isNullConstant() => false; |
|
kasperl
2012/03/05 13:53:16
I know it doesn't read as well, but I think I'd pr
floitsch
2012/03/05 15:43:24
Done.
| |
| 1009 bool isLiteralNumber() => false; | 922 bool isNumberConstant() => false; |
| 1010 bool isLiteralString() => false; | 923 bool isStringConstant() => false; |
| 1011 | 924 |
| 1012 bool isValid() { | 925 bool isValid() { |
| 1013 HValidator validator = new HValidator(); | 926 HValidator validator = new HValidator(); |
| 1014 validator.currentBlock = block; | 927 validator.currentBlock = block; |
| 1015 validator.visitInstruction(this); | 928 validator.visitInstruction(this); |
| 1016 return validator.isValid; | 929 return validator.isValid; |
| 1017 } | 930 } |
| 1018 } | 931 } |
| 1019 | 932 |
| 1020 class HBoolify extends HInstruction { | 933 class HBoolify extends HInstruction { |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1262 || name == const SourceString('removeLast')) { | 1175 || name == const SourceString('removeLast')) { |
| 1263 return HType.ARRAY; | 1176 return HType.ARRAY; |
| 1264 } | 1177 } |
| 1265 } | 1178 } |
| 1266 return HType.UNKNOWN; | 1179 return HType.UNKNOWN; |
| 1267 } | 1180 } |
| 1268 | 1181 |
| 1269 bool hasExpectedType() => builtinJsName != null; | 1182 bool hasExpectedType() => builtinJsName != null; |
| 1270 | 1183 |
| 1271 HInstruction fold(HGraph graph) { | 1184 HInstruction fold(HGraph graph) { |
| 1272 if (name == const SourceString('length') && inputs[1].isLiteralString()) { | 1185 if (name == const SourceString('length') && inputs[1].isStringConstant()) { |
| 1273 HLiteral input = inputs[1]; | 1186 HConstant input = inputs[1]; |
| 1274 DartString string = input.value; | 1187 DartString string = input.constant.value; |
| 1275 return graph.addNewLiteralInt(string.length); | 1188 return graph.addNewConstant(new IntConstant(string.length)); |
|
kasperl
2012/03/05 13:53:16
Maybe keeping a few helpers around (graph.addNewCo
floitsch
2012/03/05 15:43:24
Done.
| |
| 1276 } | 1189 } |
| 1277 return this; | 1190 return this; |
| 1278 } | 1191 } |
| 1279 | 1192 |
| 1280 void prepareGvn() { | 1193 void prepareGvn() { |
| 1281 if (builtinJsName == 'length') { | 1194 if (builtinJsName == 'length') { |
| 1282 assert(!hasSideEffects()); | 1195 assert(!hasSideEffects()); |
| 1283 } else { | 1196 } else { |
| 1284 setAllSideEffects(); | 1197 setAllSideEffects(); |
| 1285 } | 1198 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1360 | 1273 |
| 1361 HType computeInputsType() { | 1274 HType computeInputsType() { |
| 1362 HType leftType = left.type; | 1275 HType leftType = left.type; |
| 1363 HType rightType = right.type; | 1276 HType rightType = right.type; |
| 1364 if (leftType.isUnknown() || rightType.isUnknown()) { | 1277 if (leftType.isUnknown() || rightType.isUnknown()) { |
| 1365 return HType.UNKNOWN; | 1278 return HType.UNKNOWN; |
| 1366 } | 1279 } |
| 1367 return leftType.combine(rightType); | 1280 return leftType.combine(rightType); |
| 1368 } | 1281 } |
| 1369 | 1282 |
| 1370 abstract HInstruction fold(HGraph graph); | 1283 HInstruction fold(HGraph graph) { |
| 1371 abstract evaluate(num a, num b); | 1284 if (left is HConstant && right is HConstant) { |
| 1285 HConstant op1 = left; | |
| 1286 HConstant op2 = right; | |
| 1287 Constant folded = | |
| 1288 op1.constant.binaryFold(operationAsString(), op2.constant); | |
| 1289 if (folded !== null) return graph.addNewConstant(folded); | |
| 1290 } | |
| 1291 return this; | |
| 1292 } | |
| 1293 abstract String operationAsString(); | |
| 1372 } | 1294 } |
| 1373 | 1295 |
| 1374 class HBinaryArithmetic extends HInvokeBinary { | 1296 class HBinaryArithmetic extends HInvokeBinary { |
| 1375 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right) | 1297 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right) |
| 1376 : super(target, left, right); | 1298 : super(target, left, right); |
| 1377 | 1299 |
| 1378 void prepareGvn() { | 1300 void prepareGvn() { |
| 1379 // An arithmetic expression can take part in global value | 1301 // An arithmetic expression can take part in global value |
| 1380 // numbering and do not have any side-effects if we know that all | 1302 // numbering and do not have any side-effects if we know that all |
| 1381 // inputs are numbers. | 1303 // inputs are numbers. |
| 1382 if (builtin) { | 1304 if (builtin) { |
| 1383 assert(!hasSideEffects()); | 1305 assert(!hasSideEffects()); |
| 1384 setUseGvn(); | 1306 setUseGvn(); |
| 1385 } else { | 1307 } else { |
| 1386 setAllSideEffects(); | 1308 setAllSideEffects(); |
| 1387 } | 1309 } |
| 1388 } | 1310 } |
| 1389 | 1311 |
| 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() { | 1312 HType computeType() { |
| 1400 HType type = computeInputsType(); | 1313 HType type = computeInputsType(); |
| 1401 builtin = type.isNumber(); | 1314 builtin = type.isNumber(); |
| 1402 if (!type.isUnknown()) return type; | 1315 if (!type.isUnknown()) return type; |
| 1403 if (left.isNumber()) return HType.NUMBER; | 1316 if (left.isNumber()) return HType.NUMBER; |
| 1404 return HType.UNKNOWN; | 1317 return HType.UNKNOWN; |
| 1405 } | 1318 } |
| 1406 | 1319 |
| 1407 HType computeDesiredInputType(HInstruction input) { | 1320 HType computeDesiredInputType(HInstruction input) { |
| 1408 // TODO(floitsch): we want the target to be a function. | 1321 // TODO(floitsch): we want the target to be a function. |
| 1409 if (input == target) return HType.UNKNOWN; | 1322 if (input == target) return HType.UNKNOWN; |
| 1410 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER; | 1323 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER; |
| 1411 if (type.isUnknown()) return HType.NUMBER; | 1324 if (type.isUnknown()) return HType.NUMBER; |
| 1412 return HType.UNKNOWN; | 1325 return HType.UNKNOWN; |
| 1413 } | 1326 } |
| 1414 | 1327 |
| 1415 bool hasExpectedType() => builtin || type.isUnknown(); | 1328 bool hasExpectedType() => builtin || type.isUnknown(); |
| 1416 | |
| 1417 abstract num evaluate(num a, num b); | |
| 1418 } | 1329 } |
| 1419 | 1330 |
| 1420 class HAdd extends HBinaryArithmetic { | 1331 class HAdd extends HBinaryArithmetic { |
| 1421 HAdd(HStatic target, HInstruction left, HInstruction right) | 1332 HAdd(HStatic target, HInstruction left, HInstruction right) |
| 1422 : super(target, left, right); | 1333 : super(target, left, right); |
| 1423 accept(HVisitor visitor) => visitor.visitAdd(this); | 1334 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 | 1335 |
| 1429 HType computeType() { | 1336 HType computeType() { |
| 1430 HType type = computeInputsType(); | 1337 HType type = computeInputsType(); |
| 1431 builtin = (type.isNumber() || type.isString()); | 1338 builtin = (type.isNumber() || type.isString()); |
| 1432 if (type.isConflicting() && left.isString()) { | 1339 if (type.isConflicting() && left.isString()) { |
| 1433 builtin = right is HLiteral; | 1340 builtin = right is HConstant; |
| 1434 return HType.STRING; | 1341 return HType.STRING; |
| 1435 } | 1342 } |
| 1436 if (!type.isUnknown()) return type; | 1343 if (!type.isUnknown()) return type; |
| 1437 if (left.isNumber()) return HType.NUMBER; | 1344 if (left.isNumber()) return HType.NUMBER; |
| 1438 return HType.UNKNOWN; | 1345 return HType.UNKNOWN; |
| 1439 } | 1346 } |
| 1440 | 1347 |
| 1441 bool hasExpectedType() => builtin || type.isUnknown() || left.isString(); | 1348 bool hasExpectedType() => builtin || type.isUnknown() || left.isString(); |
| 1442 | 1349 |
| 1443 HType computeDesiredInputType(HInstruction input) { | 1350 HType computeDesiredInputType(HInstruction input) { |
| 1444 // TODO(floitsch): we want the target to be a function. | 1351 // TODO(floitsch): we want the target to be a function. |
| 1445 if (input == target) return HType.UNKNOWN; | 1352 if (input == target) return HType.UNKNOWN; |
| 1446 if (isString() || left.isString()) { | 1353 if (isString() || left.isString()) { |
| 1447 return (input == left) ? HType.STRING : HType.UNKNOWN; | 1354 return (input == left) ? HType.STRING : HType.UNKNOWN; |
| 1448 } | 1355 } |
| 1449 if (right.isString()) return HType.STRING; | 1356 if (right.isString()) return HType.STRING; |
| 1450 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER; | 1357 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER; |
| 1451 return HType.UNKNOWN; | 1358 return HType.UNKNOWN; |
| 1452 } | 1359 } |
| 1453 | 1360 |
| 1454 HInstruction fold(HGraph graph) { | 1361 HInstruction fold(HGraph graph) { |
| 1455 if (left.isLiteralString() && right is HLiteral) { | 1362 // TODO(floitsch): move this code to the compile-time-constant handler. |
| 1456 HLiteral op1 = left; | 1363 if (left.isStringConstant() && right is HConstant) { |
| 1457 HLiteral op2 = right; | 1364 HConstant op1 = left; |
| 1458 DartString leftString = op1.value; | 1365 HConstant op2 = right; |
| 1366 DartString leftString = op1.constant.value; | |
| 1459 DartString otherString = null; | 1367 DartString otherString = null; |
| 1460 if (right.isLiteralString()) { | 1368 if (right.isStringConstant()) { |
| 1461 otherString = op2.value; | 1369 otherString = op2.constant.value; |
| 1462 } else { | 1370 } else { |
| 1463 assert(op2.isLiteralNumber() || | 1371 assert(op2.isNumberConstant() || |
| 1464 op2.isLiteralBoolean() || | 1372 op2.isBooleanConstant() || |
| 1465 op2.isLiteralNull()); | 1373 op2.isNullConstant()); |
| 1466 otherString = new DartString.literal(op2.value.toString()); | 1374 otherString = new DartString.literal(op2.constant.value.toString()); |
| 1467 } | 1375 } |
| 1468 DartString cons = new ConsDartString(leftString, otherString); | 1376 DartString cons = new ConsDartString(leftString, otherString); |
| 1469 return graph.addNewLiteralString(cons); | 1377 return graph.addNewConstant(new StringConstant(cons)); |
| 1470 } | 1378 } |
| 1471 return super.fold(graph); | 1379 return super.fold(graph); |
| 1472 } | 1380 } |
| 1381 | |
| 1382 String operationAsString() => "+"; | |
|
kasperl
2012/03/05 13:53:16
These operationAsString seem a bit broken. I wonde
floitsch
2012/03/05 15:43:24
will think about it in another CL.
| |
| 1383 int typeCode() => 5; | |
| 1384 bool typeEquals(other) => other is HAdd; | |
| 1385 bool dataEquals(HInstruction other) => true; | |
| 1473 } | 1386 } |
| 1474 | 1387 |
| 1475 class HDivide extends HBinaryArithmetic { | 1388 class HDivide extends HBinaryArithmetic { |
| 1476 HDivide(HStatic target, HInstruction left, HInstruction right) | 1389 HDivide(HStatic target, HInstruction left, HInstruction right) |
| 1477 : super(target, left, right); | 1390 : super(target, left, right); |
| 1478 accept(HVisitor visitor) => visitor.visitDivide(this); | 1391 accept(HVisitor visitor) => visitor.visitDivide(this); |
| 1479 | 1392 |
| 1480 HType computeType() { | 1393 HType computeType() { |
| 1481 HType type = computeInputsType(); | 1394 HType type = computeInputsType(); |
| 1482 builtin = type.isNumber(); | 1395 builtin = type.isNumber(); |
| 1483 if (left.isNumber()) return HType.DOUBLE; | 1396 if (left.isNumber()) return HType.DOUBLE; |
| 1484 return HType.UNKNOWN; | 1397 return HType.UNKNOWN; |
| 1485 } | 1398 } |
| 1486 | 1399 |
| 1487 num evaluate(num a, num b) => a / b; | 1400 String operationAsString() => "/"; |
| 1488 int typeCode() => 6; | 1401 int typeCode() => 6; |
| 1489 bool typeEquals(other) => other is HDivide; | 1402 bool typeEquals(other) => other is HDivide; |
| 1490 bool dataEquals(HInstruction other) => true; | 1403 bool dataEquals(HInstruction other) => true; |
| 1491 } | 1404 } |
| 1492 | 1405 |
| 1493 class HModulo extends HBinaryArithmetic { | 1406 class HModulo extends HBinaryArithmetic { |
| 1494 HModulo(HStatic target, HInstruction left, HInstruction right) | 1407 HModulo(HStatic target, HInstruction left, HInstruction right) |
| 1495 : super(target, left, right); | 1408 : super(target, left, right); |
| 1496 accept(HVisitor visitor) => visitor.visitModulo(this); | 1409 accept(HVisitor visitor) => visitor.visitModulo(this); |
| 1497 num evaluate(num a, num b) => a % b; | 1410 |
| 1411 String operationAsString() => "%"; | |
| 1498 int typeCode() => 7; | 1412 int typeCode() => 7; |
| 1499 bool typeEquals(other) => other is HModulo; | 1413 bool typeEquals(other) => other is HModulo; |
| 1500 bool dataEquals(HInstruction other) => true; | 1414 bool dataEquals(HInstruction other) => true; |
| 1501 } | 1415 } |
| 1502 | 1416 |
| 1503 class HMultiply extends HBinaryArithmetic { | 1417 class HMultiply extends HBinaryArithmetic { |
| 1504 HMultiply(HStatic target, HInstruction left, HInstruction right) | 1418 HMultiply(HStatic target, HInstruction left, HInstruction right) |
| 1505 : super(target, left, right); | 1419 : super(target, left, right); |
| 1506 accept(HVisitor visitor) => visitor.visitMultiply(this); | 1420 accept(HVisitor visitor) => visitor.visitMultiply(this); |
| 1507 num evaluate(num a, num b) => a * b; | 1421 |
| 1422 String operationAsString() => "*"; | |
| 1508 int typeCode() => 8; | 1423 int typeCode() => 8; |
| 1509 bool typeEquals(other) => other is HMultiply; | 1424 bool typeEquals(other) => other is HMultiply; |
| 1510 bool dataEquals(HInstruction other) => true; | 1425 bool dataEquals(HInstruction other) => true; |
| 1511 } | 1426 } |
| 1512 | 1427 |
| 1513 class HSubtract extends HBinaryArithmetic { | 1428 class HSubtract extends HBinaryArithmetic { |
| 1514 HSubtract(HStatic target, HInstruction left, HInstruction right) | 1429 HSubtract(HStatic target, HInstruction left, HInstruction right) |
| 1515 : super(target, left, right); | 1430 : super(target, left, right); |
| 1516 accept(HVisitor visitor) => visitor.visitSubtract(this); | 1431 accept(HVisitor visitor) => visitor.visitSubtract(this); |
| 1517 num evaluate(num a, num b) => a - b; | 1432 |
| 1433 String operationAsString() => "-"; | |
| 1518 int typeCode() => 9; | 1434 int typeCode() => 9; |
| 1519 bool typeEquals(other) => other is HSubtract; | 1435 bool typeEquals(other) => other is HSubtract; |
| 1520 bool dataEquals(HInstruction other) => true; | 1436 bool dataEquals(HInstruction other) => true; |
| 1521 } | 1437 } |
| 1522 | 1438 |
| 1523 class HTruncatingDivide extends HBinaryArithmetic { | 1439 class HTruncatingDivide extends HBinaryArithmetic { |
| 1524 HTruncatingDivide(HStatic target, HInstruction left, HInstruction right) | 1440 HTruncatingDivide(HStatic target, HInstruction left, HInstruction right) |
| 1525 : super(target, left, right); | 1441 : super(target, left, right); |
| 1526 accept(HVisitor visitor) => visitor.visitTruncatingDivide(this); | 1442 accept(HVisitor visitor) => visitor.visitTruncatingDivide(this); |
| 1527 | 1443 |
| 1528 HInstruction fold(HGraph graph) { | 1444 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; | 1445 int typeCode() => 10; |
| 1538 bool typeEquals(other) => other is HTruncatingDivide; | 1446 bool typeEquals(other) => other is HTruncatingDivide; |
| 1539 bool dataEquals(HInstruction other) => true; | 1447 bool dataEquals(HInstruction other) => true; |
| 1540 } | 1448 } |
| 1541 | 1449 |
| 1542 | 1450 |
| 1543 // TODO(floitsch): Should HBinaryArithmetic really be the super class of | 1451 // TODO(floitsch): Should HBinaryArithmetic really be the super class of |
| 1544 // HBinaryBitOp? | 1452 // HBinaryBitOp? |
| 1545 class HBinaryBitOp extends HBinaryArithmetic { | 1453 class HBinaryBitOp extends HBinaryArithmetic { |
| 1546 HBinaryBitOp(HStatic target, HInstruction left, HInstruction right) | 1454 HBinaryBitOp(HStatic target, HInstruction left, HInstruction right) |
| 1547 : super(target, left, right); | 1455 : super(target, left, right); |
| 1548 | 1456 |
| 1549 HType computeType() { | 1457 HType computeType() { |
| 1550 HType type = computeInputsType(); | 1458 HType type = computeInputsType(); |
| 1551 builtin = type.isInteger(); | 1459 builtin = type.isInteger(); |
| 1552 if (!type.isUnknown()) return type; | 1460 if (!type.isUnknown()) return type; |
| 1553 if (left.isInteger()) return HType.INTEGER; | 1461 if (left.isInteger()) return HType.INTEGER; |
| 1554 return HType.UNKNOWN; | 1462 return HType.UNKNOWN; |
| 1555 } | 1463 } |
| 1556 | 1464 |
| 1557 HType computeDesiredInputType(HInstruction input) { | 1465 HType computeDesiredInputType(HInstruction input) { |
| 1558 // TODO(floitsch): we want the target to be a function. | 1466 // TODO(floitsch): we want the target to be a function. |
| 1559 if (input == target) return HType.UNKNOWN; | 1467 if (input == target) return HType.UNKNOWN; |
| 1560 return HType.INTEGER; | 1468 return HType.INTEGER; |
| 1561 } | 1469 } |
| 1562 | 1470 |
| 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. | 1471 // TODO(floitsch): make class abstract instead of adding an abstract method. |
| 1577 abstract accept(HVisitor visitor); | 1472 abstract accept(HVisitor visitor); |
| 1578 } | 1473 } |
| 1579 | 1474 |
| 1580 class HShiftLeft extends HBinaryBitOp { | 1475 class HShiftLeft extends HBinaryBitOp { |
| 1581 HShiftLeft(HStatic target, HInstruction left, HInstruction right) | 1476 HShiftLeft(HStatic target, HInstruction left, HInstruction right) |
| 1582 : super(target, left, right); | 1477 : super(target, left, right); |
| 1583 accept(HVisitor visitor) => visitor.visitShiftLeft(this); | 1478 accept(HVisitor visitor) => visitor.visitShiftLeft(this); |
| 1584 | 1479 |
| 1585 HInstruction fold(HGraph graph) { | 1480 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; | 1481 int typeCode() => 11; |
| 1599 bool typeEquals(other) => other is HShiftLeft; | 1482 bool typeEquals(other) => other is HShiftLeft; |
| 1600 bool dataEquals(HInstruction other) => true; | 1483 bool dataEquals(HInstruction other) => true; |
| 1601 } | 1484 } |
| 1602 | 1485 |
| 1603 class HShiftRight extends HBinaryBitOp { | 1486 class HShiftRight extends HBinaryBitOp { |
| 1604 HShiftRight(HStatic target, HInstruction left, HInstruction right) | 1487 HShiftRight(HStatic target, HInstruction left, HInstruction right) |
| 1605 : super(target, left, right); | 1488 : super(target, left, right); |
| 1606 accept(HVisitor visitor) => visitor.visitShiftRight(this); | 1489 accept(HVisitor visitor) => visitor.visitShiftRight(this); |
| 1607 | 1490 |
| 1608 HInstruction fold(HGraph graph) { | 1491 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; | 1492 int typeCode() => 12; |
| 1619 bool typeEquals(other) => other is HShiftRight; | 1493 bool typeEquals(other) => other is HShiftRight; |
| 1620 bool dataEquals(HInstruction other) => true; | 1494 bool dataEquals(HInstruction other) => true; |
| 1621 } | 1495 } |
| 1622 | 1496 |
| 1623 class HBitOr extends HBinaryBitOp { | 1497 class HBitOr extends HBinaryBitOp { |
| 1624 HBitOr(HStatic target, HInstruction left, HInstruction right) | 1498 HBitOr(HStatic target, HInstruction left, HInstruction right) |
| 1625 : super(target, left, right); | 1499 : super(target, left, right); |
| 1626 accept(HVisitor visitor) => visitor.visitBitOr(this); | 1500 accept(HVisitor visitor) => visitor.visitBitOr(this); |
| 1627 | 1501 |
| 1628 int evaluate(int a, int b) => a | b; | 1502 String operationAsString() => "|"; |
| 1629 int typeCode() => 13; | 1503 int typeCode() => 13; |
| 1630 bool typeEquals(other) => other is HBitOr; | 1504 bool typeEquals(other) => other is HBitOr; |
| 1631 bool dataEquals(HInstruction other) => true; | 1505 bool dataEquals(HInstruction other) => true; |
| 1632 } | 1506 } |
| 1633 | 1507 |
| 1634 class HBitAnd extends HBinaryBitOp { | 1508 class HBitAnd extends HBinaryBitOp { |
| 1635 HBitAnd(HStatic target, HInstruction left, HInstruction right) | 1509 HBitAnd(HStatic target, HInstruction left, HInstruction right) |
| 1636 : super(target, left, right); | 1510 : super(target, left, right); |
| 1637 accept(HVisitor visitor) => visitor.visitBitAnd(this); | 1511 accept(HVisitor visitor) => visitor.visitBitAnd(this); |
| 1638 | 1512 |
| 1639 int evaluate(int a, int b) => a & b; | 1513 String operationAsString() => "&"; |
| 1640 int typeCode() => 14; | 1514 int typeCode() => 14; |
| 1641 bool typeEquals(other) => other is HBitAnd; | 1515 bool typeEquals(other) => other is HBitAnd; |
| 1642 bool dataEquals(HInstruction other) => true; | 1516 bool dataEquals(HInstruction other) => true; |
| 1643 } | 1517 } |
| 1644 | 1518 |
| 1645 class HBitXor extends HBinaryBitOp { | 1519 class HBitXor extends HBinaryBitOp { |
| 1646 HBitXor(HStatic target, HInstruction left, HInstruction right) | 1520 HBitXor(HStatic target, HInstruction left, HInstruction right) |
| 1647 : super(target, left, right); | 1521 : super(target, left, right); |
| 1648 accept(HVisitor visitor) => visitor.visitBitXor(this); | 1522 accept(HVisitor visitor) => visitor.visitBitXor(this); |
| 1649 | 1523 |
| 1650 int evaluate(int a, int b) => a ^ b; | 1524 String operationAsString() => "^"; |
| 1651 int typeCode() => 15; | 1525 int typeCode() => 15; |
| 1652 bool typeEquals(other) => other is HBitXor; | 1526 bool typeEquals(other) => other is HBitXor; |
| 1653 bool dataEquals(HInstruction other) => true; | 1527 bool dataEquals(HInstruction other) => true; |
| 1654 } | 1528 } |
| 1655 | 1529 |
| 1656 class HInvokeUnary extends HInvokeStatic { | 1530 class HInvokeUnary extends HInvokeStatic { |
| 1657 HInvokeUnary(HStatic target, HInstruction input) | 1531 HInvokeUnary(HStatic target, HInstruction input) |
| 1658 : super(Selector.UNARY_OPERATOR, <HInstruction>[target, input]); | 1532 : super(Selector.UNARY_OPERATOR, <HInstruction>[target, input]); |
| 1659 | 1533 |
| 1660 HInstruction get operand() => inputs[1]; | 1534 HInstruction get operand() => inputs[1]; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1680 | 1554 |
| 1681 HType computeDesiredInputType(HInstruction input) { | 1555 HType computeDesiredInputType(HInstruction input) { |
| 1682 // TODO(floitsch): we want the target to be a function. | 1556 // TODO(floitsch): we want the target to be a function. |
| 1683 if (input == target) return HType.UNKNOWN; | 1557 if (input == target) return HType.UNKNOWN; |
| 1684 if (type.isUnknown() || type.isNumber()) return HType.NUMBER; | 1558 if (type.isUnknown() || type.isNumber()) return HType.NUMBER; |
| 1685 return HType.UNKNOWN; | 1559 return HType.UNKNOWN; |
| 1686 } | 1560 } |
| 1687 | 1561 |
| 1688 bool hasExpectedType() => builtin || (type.isUnknown()); | 1562 bool hasExpectedType() => builtin || (type.isUnknown()); |
| 1689 | 1563 |
| 1690 abstract HInstruction fold(HGraph graph); | 1564 HInstruction fold(HGraph graph) { |
| 1565 if (operand is HConstant) { | |
| 1566 HConstant op = operand; | |
| 1567 Constant folded = op.constant.unaryFold(operationAsString()); | |
| 1568 if (folded !== null) return graph.addNewConstant(folded); | |
| 1569 } | |
| 1570 return this; | |
| 1571 } | |
| 1691 | 1572 |
| 1692 abstract num evaluate(num a); | 1573 abstract String operationAsString(); |
| 1693 } | 1574 } |
| 1694 | 1575 |
| 1695 class HNegate extends HInvokeUnary { | 1576 class HNegate extends HInvokeUnary { |
| 1696 HNegate(HStatic target, HInstruction input) : super(target, input); | 1577 HNegate(HStatic target, HInstruction input) : super(target, input); |
| 1697 accept(HVisitor visitor) => visitor.visitNegate(this); | 1578 accept(HVisitor visitor) => visitor.visitNegate(this); |
| 1698 | 1579 |
| 1699 HInstruction fold(HGraph graph) { | 1580 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; | 1581 int typeCode() => 16; |
| 1709 bool typeEquals(other) => other is HNegate; | 1582 bool typeEquals(other) => other is HNegate; |
| 1710 bool dataEquals(HInstruction other) => true; | 1583 bool dataEquals(HInstruction other) => true; |
| 1711 } | 1584 } |
| 1712 | 1585 |
| 1713 class HBitNot extends HInvokeUnary { | 1586 class HBitNot extends HInvokeUnary { |
| 1714 HBitNot(HStatic target, HInstruction input) : super(target, input); | 1587 HBitNot(HStatic target, HInstruction input) : super(target, input); |
| 1715 accept(HVisitor visitor) => visitor.visitBitNot(this); | 1588 accept(HVisitor visitor) => visitor.visitBitNot(this); |
| 1716 | 1589 |
| 1717 HType computeType() { | 1590 HType computeType() { |
| 1718 HType type = operand.type; | 1591 HType type = operand.type; |
| 1719 builtin = type.isInteger(); | 1592 builtin = type.isInteger(); |
| 1720 if (!type.isUnknown()) return type; | 1593 if (!type.isUnknown()) return type; |
| 1721 return HType.UNKNOWN; | 1594 return HType.UNKNOWN; |
| 1722 } | 1595 } |
| 1723 | 1596 |
| 1724 HType computeDesiredInputType(HInstruction input) { | 1597 HType computeDesiredInputType(HInstruction input) { |
| 1725 // TODO(floitsch): we want the target to be a function. | 1598 // TODO(floitsch): we want the target to be a function. |
| 1726 if (input == target) return HType.UNKNOWN; | 1599 if (input == target) return HType.UNKNOWN; |
| 1727 return HType.INTEGER; | 1600 return HType.INTEGER; |
| 1728 } | 1601 } |
| 1729 | 1602 |
| 1730 HInstruction fold(HGraph graph) { | 1603 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; | 1604 int typeCode() => 17; |
| 1742 bool typeEquals(other) => other is HBitNot; | 1605 bool typeEquals(other) => other is HBitNot; |
| 1743 bool dataEquals(HInstruction other) => true; | 1606 bool dataEquals(HInstruction other) => true; |
| 1744 } | 1607 } |
| 1745 | 1608 |
| 1746 class HExit extends HControlFlow { | 1609 class HExit extends HControlFlow { |
| 1747 HExit() : super(const <HInstruction>[]); | 1610 HExit() : super(const <HInstruction>[]); |
| 1748 toString() => 'exit'; | 1611 toString() => 'exit'; |
| 1749 accept(HVisitor visitor) => visitor.visitExit(this); | 1612 accept(HVisitor visitor) => visitor.visitExit(this); |
| 1750 } | 1613 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1810 HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP]) | 1673 HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP]) |
| 1811 : super(<HInstruction>[condition]); | 1674 : super(<HInstruction>[condition]); |
| 1812 toString() => 'loop-branch'; | 1675 toString() => 'loop-branch'; |
| 1813 accept(HVisitor visitor) => visitor.visitLoopBranch(this); | 1676 accept(HVisitor visitor) => visitor.visitLoopBranch(this); |
| 1814 | 1677 |
| 1815 bool isDoWhile() { | 1678 bool isDoWhile() { |
| 1816 return kind === DO_WHILE_LOOP; | 1679 return kind === DO_WHILE_LOOP; |
| 1817 } | 1680 } |
| 1818 } | 1681 } |
| 1819 | 1682 |
| 1820 class HLiteral extends HInstruction { | 1683 class HConstant extends HInstruction { |
| 1821 final value; | 1684 final Constant constant; |
| 1822 HLiteral.internal(this.value, HType type) : super(<HInstruction>[]) { | 1685 HConstant.internal(this.constant, HType type) : super(<HInstruction>[]) { |
| 1823 this.type = type; | 1686 this.type = type; |
| 1824 tryGenerateAtUseSite(); // Maybe avoid this if the literal is big? | 1687 tryGenerateAtUseSite(); // Maybe avoid this if the literal is big? |
| 1825 } | 1688 } |
| 1826 | 1689 |
| 1827 void prepareGvn() { | 1690 void prepareGvn() { |
| 1828 assert(!hasSideEffects()); | 1691 assert(!hasSideEffects()); |
| 1829 } | 1692 } |
| 1830 | 1693 |
| 1831 toString() => 'literal: $value'; | 1694 toString() => 'literal: $constant'; |
| 1832 accept(HVisitor visitor) => visitor.visitLiteral(this); | 1695 accept(HVisitor visitor) => visitor.visitConstant(this); |
| 1833 HType computeType() => type; | 1696 HType computeType() => type; |
| 1834 | 1697 |
| 1835 // Literals have the type they have. It can't be changed. | 1698 // Literals have the type they have. It can't be changed. |
| 1836 bool updateType() => false; | 1699 bool updateType() => false; |
| 1837 | 1700 |
| 1838 bool hasExpectedType() => true; | 1701 bool hasExpectedType() => true; |
| 1839 | 1702 |
| 1840 bool isLiteralBoolean() => value is bool; | 1703 bool isBooleanConstant() => constant.isBool(); |
| 1841 bool isLiteralNull() => value === null; | 1704 bool isNullConstant() => constant.isNull(); |
| 1842 bool isLiteralNumber() => value is num; | 1705 bool isNumberConstant() => constant.isNum(); |
| 1843 bool isLiteralString() => value is DartString; | 1706 bool isStringConstant() => constant.isString(); |
| 1844 } | 1707 } |
| 1845 | 1708 |
| 1846 class HNot extends HInstruction { | 1709 class HNot extends HInstruction { |
| 1847 HNot(HInstruction value) : super(<HInstruction>[value]); | 1710 HNot(HInstruction value) : super(<HInstruction>[value]); |
| 1848 void prepareGvn() { | 1711 void prepareGvn() { |
| 1849 assert(!hasSideEffects()); | 1712 assert(!hasSideEffects()); |
| 1850 setUseGvn(); | 1713 setUseGvn(); |
| 1851 } | 1714 } |
| 1852 | 1715 |
| 1853 HType computeType() => HType.BOOLEAN; | 1716 HType computeType() => HType.BOOLEAN; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1972 // and do not have any side-effects if we know all the inputs are | 1835 // and do not have any side-effects if we know all the inputs are |
| 1973 // numbers. This can be improved for at least equality. | 1836 // numbers. This can be improved for at least equality. |
| 1974 if (builtin) { | 1837 if (builtin) { |
| 1975 assert(!hasSideEffects()); | 1838 assert(!hasSideEffects()); |
| 1976 setUseGvn(); | 1839 setUseGvn(); |
| 1977 } else { | 1840 } else { |
| 1978 setAllSideEffects(); | 1841 setAllSideEffects(); |
| 1979 } | 1842 } |
| 1980 } | 1843 } |
| 1981 | 1844 |
| 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() { | 1845 HType computeType() { |
| 1992 builtin = computeInputsType().isNumber(); | 1846 builtin = computeInputsType().isNumber(); |
| 1993 return HType.BOOLEAN; | 1847 return HType.BOOLEAN; |
| 1994 } | 1848 } |
| 1995 | 1849 |
| 1996 HType computeDesiredInputType(HInstruction input) { | 1850 HType computeDesiredInputType(HInstruction input) { |
| 1997 // TODO(floitsch): we want the target to be a function. | 1851 // TODO(floitsch): we want the target to be a function. |
| 1998 if (input == target) return HType.UNKNOWN; | 1852 if (input == target) return HType.UNKNOWN; |
| 1999 // For all relational operations exept HEquals, we expect to only | 1853 // For all relational operations exept HEquals, we expect to only |
| 2000 // get numbers. | 1854 // get numbers. |
| 2001 return HType.NUMBER; | 1855 return HType.NUMBER; |
| 2002 } | 1856 } |
| 2003 | 1857 |
| 2004 // A HRelational goes through the builtin operator or the top level | 1858 // A HRelational goes through the builtin operator or the top level |
| 2005 // element. Therefore, it always has the expected type. | 1859 // element. Therefore, it always has the expected type. |
| 2006 bool hasExpectedType() => true; | 1860 bool hasExpectedType() => true; |
| 2007 | |
| 2008 abstract bool evaluate(num a, num b); | |
| 2009 } | 1861 } |
| 2010 | 1862 |
| 2011 class HEquals extends HRelational { | 1863 class HEquals extends HRelational { |
| 2012 HEquals(HStatic target, HInstruction left, HInstruction right) | 1864 HEquals(HStatic target, HInstruction left, HInstruction right) |
| 2013 : super(target, left, right); | 1865 : super(target, left, right); |
| 2014 bool evaluate(num a, num b) => a == b; | |
| 2015 accept(HVisitor visitor) => visitor.visitEquals(this); | 1866 accept(HVisitor visitor) => visitor.visitEquals(this); |
| 2016 int typeCode() => 19; | |
| 2017 bool typeEquals(other) => other is HEquals; | |
| 2018 bool dataEquals(HInstruction other) => true; | |
| 2019 | 1867 |
| 2020 HType computeType() { | 1868 HType computeType() { |
| 2021 builtin = computeInputsType().isNumber() || (left is HLiteral); | 1869 builtin = computeInputsType().isNumber() || (left is HConstant); |
| 2022 return HType.BOOLEAN; | 1870 return HType.BOOLEAN; |
| 2023 } | 1871 } |
| 2024 | 1872 |
| 2025 HType computeDesiredInputType(HInstruction input) { | 1873 HType computeDesiredInputType(HInstruction input) { |
| 2026 // TODO(floitsch): we want the target to be a function. | 1874 // TODO(floitsch): we want the target to be a function. |
| 2027 if (input == target) return HType.UNKNOWN; | 1875 if (input == target) return HType.UNKNOWN; |
| 2028 if (left.isNumber() || right.isNumber()) return HType.NUMBER; | 1876 if (left.isNumber() || right.isNumber()) return HType.NUMBER; |
| 2029 return HType.UNKNOWN; | 1877 return HType.UNKNOWN; |
| 2030 } | 1878 } |
| 1879 | |
| 1880 String operationAsString() => "=="; | |
| 1881 int typeCode() => 19; | |
| 1882 bool typeEquals(other) => other is HEquals; | |
| 1883 bool dataEquals(HInstruction other) => true; | |
| 2031 } | 1884 } |
| 2032 | 1885 |
| 2033 class HIdentity extends HRelational { | 1886 class HIdentity extends HRelational { |
| 2034 HIdentity(HStatic target, HInstruction left, HInstruction right) | 1887 HIdentity(HStatic target, HInstruction left, HInstruction right) |
| 2035 : super(target, left, right); | 1888 : super(target, left, right); |
| 2036 bool evaluate(num a, num b) => a === b; | |
| 2037 accept(HVisitor visitor) => visitor.visitIdentity(this); | 1889 accept(HVisitor visitor) => visitor.visitIdentity(this); |
| 2038 int typeCode() => 20; | |
| 2039 bool typeEquals(other) => other is HIdentity; | |
| 2040 bool dataEquals(HInstruction other) => true; | |
| 2041 | 1890 |
| 2042 HType computeType() { | 1891 HType computeType() { |
| 2043 builtin = true; | 1892 builtin = true; |
| 2044 return HType.BOOLEAN; | 1893 return HType.BOOLEAN; |
| 2045 } | 1894 } |
| 2046 | 1895 |
| 2047 bool hasExpectedType() => true; | 1896 bool hasExpectedType() => true; |
| 2048 | 1897 |
| 2049 HType computeDesiredInputType(HInstruction input) => HType.UNKNOWN; | 1898 HType computeDesiredInputType(HInstruction input) => HType.UNKNOWN; |
| 1899 | |
| 1900 String operationAsString() => "==="; | |
| 1901 int typeCode() => 20; | |
| 1902 bool typeEquals(other) => other is HIdentity; | |
| 1903 bool dataEquals(HInstruction other) => true; | |
| 2050 } | 1904 } |
| 2051 | 1905 |
| 2052 class HGreater extends HRelational { | 1906 class HGreater extends HRelational { |
| 2053 HGreater(HStatic target, HInstruction left, HInstruction right) | 1907 HGreater(HStatic target, HInstruction left, HInstruction right) |
| 2054 : super(target, left, right); | 1908 : super(target, left, right); |
| 2055 bool evaluate(num a, num b) => a > b; | |
| 2056 accept(HVisitor visitor) => visitor.visitGreater(this); | 1909 accept(HVisitor visitor) => visitor.visitGreater(this); |
| 1910 | |
| 1911 String operationAsString() => ">"; | |
| 2057 int typeCode() => 21; | 1912 int typeCode() => 21; |
| 2058 bool typeEquals(other) => other is HGreater; | 1913 bool typeEquals(other) => other is HGreater; |
| 2059 bool dataEquals(HInstruction other) => true; | 1914 bool dataEquals(HInstruction other) => true; |
| 2060 } | 1915 } |
| 2061 | 1916 |
| 2062 class HGreaterEqual extends HRelational { | 1917 class HGreaterEqual extends HRelational { |
| 2063 HGreaterEqual(HStatic target, HInstruction left, HInstruction right) | 1918 HGreaterEqual(HStatic target, HInstruction left, HInstruction right) |
| 2064 : super(target, left, right); | 1919 : super(target, left, right); |
| 2065 bool evaluate(num a, num b) => a >= b; | |
| 2066 accept(HVisitor visitor) => visitor.visitGreaterEqual(this); | 1920 accept(HVisitor visitor) => visitor.visitGreaterEqual(this); |
| 1921 | |
| 1922 String operationAsString() => ">="; | |
| 2067 int typeCode() => 22; | 1923 int typeCode() => 22; |
| 2068 bool typeEquals(other) => other is HGreaterEqual; | 1924 bool typeEquals(other) => other is HGreaterEqual; |
| 2069 bool dataEquals(HInstruction other) => true; | 1925 bool dataEquals(HInstruction other) => true; |
| 2070 } | 1926 } |
| 2071 | 1927 |
| 2072 class HLess extends HRelational { | 1928 class HLess extends HRelational { |
| 2073 HLess(HStatic target, HInstruction left, HInstruction right) | 1929 HLess(HStatic target, HInstruction left, HInstruction right) |
| 2074 : super(target, left, right); | 1930 : super(target, left, right); |
| 2075 bool evaluate(num a, num b) => a < b; | |
| 2076 accept(HVisitor visitor) => visitor.visitLess(this); | 1931 accept(HVisitor visitor) => visitor.visitLess(this); |
| 1932 | |
| 1933 String operationAsString() => "<"; | |
| 1934 int typeCode() => 23; | |
| 2077 bool typeEquals(other) => other is HLess; | 1935 bool typeEquals(other) => other is HLess; |
| 2078 bool dataEquals(HInstruction other) => true; | 1936 bool dataEquals(HInstruction other) => true; |
| 2079 } | 1937 } |
| 2080 | 1938 |
| 2081 class HLessEqual extends HRelational { | 1939 class HLessEqual extends HRelational { |
| 2082 HLessEqual(HStatic target, HInstruction left, HInstruction right) | 1940 HLessEqual(HStatic target, HInstruction left, HInstruction right) |
| 2083 : super(target, left, right); | 1941 : super(target, left, right); |
| 2084 bool evaluate(num a, num b) => a <= b; | |
| 2085 accept(HVisitor visitor) => visitor.visitLessEqual(this); | 1942 accept(HVisitor visitor) => visitor.visitLessEqual(this); |
| 2086 int typeCode() => 23; | 1943 |
| 1944 String operationAsString() => "<="; | |
| 1945 int typeCode() => 24; | |
| 2087 bool typeEquals(other) => other is HLessEqual; | 1946 bool typeEquals(other) => other is HLessEqual; |
| 2088 bool dataEquals(HInstruction other) => true; | 1947 bool dataEquals(HInstruction other) => true; |
| 2089 } | 1948 } |
| 2090 | 1949 |
| 2091 class HReturn extends HControlFlow { | 1950 class HReturn extends HControlFlow { |
| 2092 HReturn(value) : super(<HInstruction>[value]); | 1951 HReturn(value) : super(<HInstruction>[value]); |
| 2093 toString() => 'return'; | 1952 toString() => 'return'; |
| 2094 accept(HVisitor visitor) => visitor.visitReturn(this); | 1953 accept(HVisitor visitor) => visitor.visitReturn(this); |
| 2095 } | 1954 } |
| 2096 | 1955 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2109 void prepareGvn() { | 1968 void prepareGvn() { |
| 2110 assert(!hasSideEffects()); | 1969 assert(!hasSideEffects()); |
| 2111 if (!element.isAssignable()) { | 1970 if (!element.isAssignable()) { |
| 2112 setUseGvn(); | 1971 setUseGvn(); |
| 2113 } | 1972 } |
| 2114 } | 1973 } |
| 2115 toString() => 'static ${element.name}'; | 1974 toString() => 'static ${element.name}'; |
| 2116 accept(HVisitor visitor) => visitor.visitStatic(this); | 1975 accept(HVisitor visitor) => visitor.visitStatic(this); |
| 2117 | 1976 |
| 2118 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode(); | 1977 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode(); |
| 2119 int typeCode() => 24; | 1978 int typeCode() => 25; |
| 2120 bool typeEquals(other) => other is HStatic; | 1979 bool typeEquals(other) => other is HStatic; |
| 2121 bool dataEquals(HStatic other) => element == other.element; | 1980 bool dataEquals(HStatic other) => element == other.element; |
| 2122 } | 1981 } |
| 2123 | 1982 |
| 2124 class HStaticStore extends HInstruction { | 1983 class HStaticStore extends HInstruction { |
| 2125 Element element; | 1984 Element element; |
| 2126 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]); | 1985 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]); |
| 2127 toString() => 'static store ${element.name}'; | 1986 toString() => 'static store ${element.name}'; |
| 2128 accept(HVisitor visitor) => visitor.visitStaticStore(this); | 1987 accept(HVisitor visitor) => visitor.visitStaticStore(this); |
| 2129 | 1988 |
| 2130 int typeCode() => 25; | 1989 int typeCode() => 26; |
| 2131 bool typeEquals(other) => other is HStaticStore; | 1990 bool typeEquals(other) => other is HStaticStore; |
| 2132 bool dataEquals(HStaticStore other) => element == other.element; | 1991 bool dataEquals(HStaticStore other) => element == other.element; |
| 2133 } | 1992 } |
| 2134 | 1993 |
| 2135 class HLiteralList extends HInstruction { | 1994 class HLiteralList extends HInstruction { |
| 2136 HLiteralList(inputs, this.isConst) : super(inputs); | 1995 HLiteralList(inputs, this.isConst) : super(inputs); |
| 2137 toString() => 'literal list'; | 1996 toString() => 'literal list'; |
| 2138 accept(HVisitor visitor) => visitor.visitLiteralList(this); | 1997 accept(HVisitor visitor) => visitor.visitLiteralList(this); |
| 2139 HType computeType() => HType.ARRAY; | 1998 HType computeType() => HType.ARRAY; |
| 2140 bool hasExpectedType() => true; | 1999 bool hasExpectedType() => true; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2266 | 2125 |
| 2267 HInstruction get expression() => inputs[0]; | 2126 HInstruction get expression() => inputs[0]; |
| 2268 | 2127 |
| 2269 HType computeType() => HType.BOOLEAN; | 2128 HType computeType() => HType.BOOLEAN; |
| 2270 bool hasExpectedType() => true; | 2129 bool hasExpectedType() => true; |
| 2271 | 2130 |
| 2272 accept(HVisitor visitor) => visitor.visitIs(this); | 2131 accept(HVisitor visitor) => visitor.visitIs(this); |
| 2273 | 2132 |
| 2274 toString() => "$expression is $typeExpression"; | 2133 toString() => "$expression is $typeExpression"; |
| 2275 } | 2134 } |
| OLD | NEW |