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 library dart2js.constant_system.js; | 5 library dart2js.constant_system.js; |
6 | 6 |
7 import '../compiler.dart' show Compiler; | 7 import '../compiler.dart' show Compiler; |
8 import '../constant_system_dart.dart'; | 8 import '../constant_system_dart.dart'; |
9 import '../constants/constant_system.dart'; | 9 import '../constants/constant_system.dart'; |
10 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 double leftDouble = leftNum.primitiveValue.toDouble(); | 158 double leftDouble = leftNum.primitiveValue.toDouble(); |
159 double rightDouble = rightNum.primitiveValue.toDouble(); | 159 double rightDouble = rightNum.primitiveValue.toDouble(); |
160 return new BoolConstantValue(leftDouble == rightDouble); | 160 return new BoolConstantValue(leftDouble == rightDouble); |
161 } | 161 } |
162 return result; | 162 return result; |
163 } | 163 } |
164 | 164 |
165 apply(left, right) => identical(left, right); | 165 apply(left, right) => identical(left, right); |
166 } | 166 } |
167 | 167 |
| 168 class JavaScriptRoundOperation implements UnaryOperation { |
| 169 const JavaScriptRoundOperation(); |
| 170 String get name => DART_CONSTANT_SYSTEM.round.name; |
| 171 ConstantValue fold(ConstantValue constant) { |
| 172 // Be careful to round() only values that do not throw on either the host or |
| 173 // target platform. |
| 174 ConstantValue tryToRound(num value) { |
| 175 // Due to differences between browsers, only 'round' easy cases. Avoid |
| 176 // cases where nudging the value up or down changes the answer. |
| 177 // 13 digits is safely within the ~15 digit precision of doubles. |
| 178 const severalULP = 0.0000000000001; |
| 179 // Use 'roundToDouble()' to avoid exceptions on rounding the nudged value. |
| 180 double rounded = value.roundToDouble(); |
| 181 double rounded1 = (value * (1.0 + severalULP)).roundToDouble(); |
| 182 double rounded2 = (value * (1.0 - severalULP)).roundToDouble(); |
| 183 if (rounded != rounded1 || rounded != rounded2) return null; |
| 184 return JAVA_SCRIPT_CONSTANT_SYSTEM |
| 185 .convertToJavaScriptConstant(new IntConstantValue(value.round())); |
| 186 } |
| 187 |
| 188 if (constant.isInt) { |
| 189 IntConstantValue intConstant = constant; |
| 190 int value = intConstant.primitiveValue; |
| 191 if (value >= -double.MAX_FINITE && value <= double.MAX_FINITE) { |
| 192 return tryToRound(value); |
| 193 } |
| 194 } |
| 195 if (constant.isDouble) { |
| 196 DoubleConstantValue doubleConstant = constant; |
| 197 double value = doubleConstant.primitiveValue; |
| 198 // NaN and infinities will throw. |
| 199 if (value.isNaN) return null; |
| 200 if (value.isInfinite) return null; |
| 201 return tryToRound(value); |
| 202 } |
| 203 return null; |
| 204 } |
| 205 } |
| 206 |
168 /** | 207 /** |
169 * Constant system following the semantics for Dart code that has been | 208 * Constant system following the semantics for Dart code that has been |
170 * compiled to JavaScript. | 209 * compiled to JavaScript. |
171 */ | 210 */ |
172 class JavaScriptConstantSystem extends ConstantSystem { | 211 class JavaScriptConstantSystem extends ConstantSystem { |
173 final int BITS31 = 0x8FFFFFFF; | |
174 final int BITS32 = 0xFFFFFFFF; | 212 final int BITS32 = 0xFFFFFFFF; |
175 | 213 |
176 final add = const JavaScriptAddOperation(); | 214 final add = const JavaScriptAddOperation(); |
177 final bitAnd = const JavaScriptBinaryBitOperation(const BitAndOperation()); | 215 final bitAnd = const JavaScriptBinaryBitOperation(const BitAndOperation()); |
178 final bitNot = const JavaScriptBitNotOperation(); | 216 final bitNot = const JavaScriptBitNotOperation(); |
179 final bitOr = const JavaScriptBinaryBitOperation(const BitOrOperation()); | 217 final bitOr = const JavaScriptBinaryBitOperation(const BitOrOperation()); |
180 final bitXor = const JavaScriptBinaryBitOperation(const BitXorOperation()); | 218 final bitXor = const JavaScriptBinaryBitOperation(const BitXorOperation()); |
181 final booleanAnd = const BooleanAndOperation(); | 219 final booleanAnd = const BooleanAndOperation(); |
182 final booleanOr = const BooleanOrOperation(); | 220 final booleanOr = const BooleanOrOperation(); |
183 final divide = | 221 final divide = |
(...skipping 12 matching lines...) Expand all Loading... |
196 final negate = const JavaScriptNegateOperation(); | 234 final negate = const JavaScriptNegateOperation(); |
197 final not = const NotOperation(); | 235 final not = const NotOperation(); |
198 final shiftLeft = | 236 final shiftLeft = |
199 const JavaScriptBinaryBitOperation(const ShiftLeftOperation()); | 237 const JavaScriptBinaryBitOperation(const ShiftLeftOperation()); |
200 final shiftRight = const JavaScriptShiftRightOperation(); | 238 final shiftRight = const JavaScriptShiftRightOperation(); |
201 final subtract = | 239 final subtract = |
202 const JavaScriptBinaryArithmeticOperation(const SubtractOperation()); | 240 const JavaScriptBinaryArithmeticOperation(const SubtractOperation()); |
203 final truncatingDivide = const JavaScriptBinaryArithmeticOperation( | 241 final truncatingDivide = const JavaScriptBinaryArithmeticOperation( |
204 const TruncatingDivideOperation()); | 242 const TruncatingDivideOperation()); |
205 final codeUnitAt = const CodeUnitAtRuntimeOperation(); | 243 final codeUnitAt = const CodeUnitAtRuntimeOperation(); |
| 244 final round = const JavaScriptRoundOperation(); |
206 | 245 |
207 const JavaScriptConstantSystem(); | 246 const JavaScriptConstantSystem(); |
208 | 247 |
209 /** | 248 /** |
210 * Returns true if [value] will turn into NaN or infinity | 249 * Returns true if [value] will turn into NaN or infinity |
211 * at runtime. | 250 * at runtime. |
212 */ | 251 */ |
213 bool integerBecomesNanOrInfinity(int value) { | 252 bool integerBecomesNanOrInfinity(int value) { |
214 double doubleValue = value.toDouble(); | 253 double doubleValue = value.toDouble(); |
215 return doubleValue.isNaN || doubleValue.isInfinite; | 254 return doubleValue.isNaN || doubleValue.isInfinite; |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 result.add(keyList); | 439 result.add(keyList); |
401 } else { | 440 } else { |
402 // Add the keys individually to avoid generating an unused list constant | 441 // Add the keys individually to avoid generating an unused list constant |
403 // for the keys. | 442 // for the keys. |
404 result.addAll(keys); | 443 result.addAll(keys); |
405 } | 444 } |
406 result.addAll(values); | 445 result.addAll(values); |
407 return result; | 446 return result; |
408 } | 447 } |
409 } | 448 } |
OLD | NEW |