| 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 |