OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 import 'dart:math' as math; |
5 import '../common.dart'; | 6 import '../common.dart'; |
6 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 7 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
7 import '../common/tasks.dart' show CompilerTask; | 8 import '../common/tasks.dart' show CompilerTask; |
8 import '../compiler.dart' show Compiler; | 9 import '../compiler.dart' show Compiler; |
9 import '../constants/constant_system.dart'; | 10 import '../constants/constant_system.dart'; |
10 import '../constants/values.dart'; | 11 import '../constants/values.dart'; |
11 import '../core_types.dart' show CoreClasses; | 12 import '../core_types.dart' show CoreClasses; |
12 import '../dart_types.dart'; | 13 import '../dart_types.dart'; |
13 import '../elements/elements.dart'; | 14 import '../elements/elements.dart'; |
14 import '../elements/entities.dart'; | 15 import '../elements/entities.dart'; |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 phiSet.add(user); | 204 phiSet.add(user); |
204 if (hasNonBitOpUser(user, phiSet)) return true; | 205 if (hasNonBitOpUser(user, phiSet)) return true; |
205 } | 206 } |
206 } else if (user is! HBitNot && user is! HBinaryBitOp) { | 207 } else if (user is! HBitNot && user is! HBinaryBitOp) { |
207 return true; | 208 return true; |
208 } | 209 } |
209 } | 210 } |
210 return false; | 211 return false; |
211 } | 212 } |
212 | 213 |
| 214 // Returns the number of bits occupied by the value computed by [instruction]. |
| 215 // Returns `32` if the value is negative or does not fit in a smaller number |
| 216 // of bits. |
| 217 int bitWidth(HInstruction instruction) { |
| 218 const int MAX = 32; |
| 219 int constant(HInstruction insn) { |
| 220 if (insn is HConstant && insn.isConstantInteger()) { |
| 221 IntConstantValue constant = insn.constant; |
| 222 return constant.primitiveValue; |
| 223 } |
| 224 return null; |
| 225 } |
| 226 |
| 227 if (instruction.isConstantInteger()) { |
| 228 int value = constant(instruction); |
| 229 if (value < 0) return MAX; |
| 230 if (value > ((1 << 31) - 1)) return MAX; |
| 231 return value.bitLength; |
| 232 } |
| 233 if (instruction is HBitAnd) { |
| 234 return math.min(bitWidth(instruction.left), bitWidth(instruction.right)); |
| 235 } |
| 236 if (instruction is HBitOr || instruction is HBitXor) { |
| 237 HBinaryBitOp bitOp = instruction; |
| 238 int leftWidth = bitWidth(bitOp.left); |
| 239 if (leftWidth == MAX) return MAX; |
| 240 return math.max(leftWidth, bitWidth(bitOp.right)); |
| 241 } |
| 242 if (instruction is HShiftLeft) { |
| 243 int shiftCount = constant(instruction.right); |
| 244 if (shiftCount == null || shiftCount < 0 || shiftCount > 31) return MAX; |
| 245 int leftWidth = bitWidth(instruction.left); |
| 246 int width = leftWidth + shiftCount; |
| 247 return math.min(width, MAX); |
| 248 } |
| 249 if (instruction is HShiftRight) { |
| 250 int shiftCount = constant(instruction.right); |
| 251 if (shiftCount == null || shiftCount < 0 || shiftCount > 31) return MAX; |
| 252 int leftWidth = bitWidth(instruction.left); |
| 253 if (leftWidth >= MAX) return MAX; |
| 254 return math.max(leftWidth - shiftCount, 0); |
| 255 } |
| 256 if (instruction is HAdd) { |
| 257 return math.min( |
| 258 1 + math.max(bitWidth(instruction.left), bitWidth(instruction.right)), |
| 259 MAX); |
| 260 } |
| 261 return MAX; |
| 262 } |
| 263 |
213 bool requiresUintConversion(instruction) { | 264 bool requiresUintConversion(instruction) { |
214 if (instruction.isUInt31(compiler)) return false; | 265 if (instruction.isUInt31(compiler)) return false; |
| 266 if (bitWidth(instruction) <= 31) return false; |
215 // If the result of a bit-operation is only used by other bit | 267 // If the result of a bit-operation is only used by other bit |
216 // operations, we do not have to convert to an unsigned integer. | 268 // operations, we do not have to convert to an unsigned integer. |
217 return hasNonBitOpUser(instruction, new Set<HPhi>()); | 269 return hasNonBitOpUser(instruction, new Set<HPhi>()); |
218 } | 270 } |
219 | 271 |
220 /** | 272 /** |
221 * If the [instruction] is not `null` it will be used to attach the position | 273 * If the [instruction] is not `null` it will be used to attach the position |
222 * to the [statement]. | 274 * to the [statement]. |
223 */ | 275 */ |
224 void pushStatement(js.Statement statement) { | 276 void pushStatement(js.Statement statement) { |
(...skipping 2819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3044 registry.registerStaticUse(new StaticUse.staticInvoke( | 3096 registry.registerStaticUse(new StaticUse.staticInvoke( |
3045 helper, new CallStructure.unnamed(argumentCount))); | 3097 helper, new CallStructure.unnamed(argumentCount))); |
3046 return backend.emitter.staticFunctionAccess(helper); | 3098 return backend.emitter.staticFunctionAccess(helper); |
3047 } | 3099 } |
3048 | 3100 |
3049 @override | 3101 @override |
3050 void visitRef(HRef node) { | 3102 void visitRef(HRef node) { |
3051 visit(node.value); | 3103 visit(node.value); |
3052 } | 3104 } |
3053 } | 3105 } |
OLD | NEW |