| 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); | |
| 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 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 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |