| 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 // Dart core library. | 4 // Dart core library. |
| 5 | 5 |
| 6 // VM implementation of int. | 6 // VM implementation of int. |
| 7 | 7 |
| 8 @patch | 8 @patch |
| 9 class int { | 9 class int { |
| 10 @patch | 10 @patch |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 while (smallBlockSize >= blockSize) smallBlockSize -= blockSize; | 125 while (smallBlockSize >= blockSize) smallBlockSize -= blockSize; |
| 126 int result = 0; | 126 int result = 0; |
| 127 if (smallBlockSize > 0) { | 127 if (smallBlockSize > 0) { |
| 128 int blockEnd = start + smallBlockSize; | 128 int blockEnd = start + smallBlockSize; |
| 129 _Smi smi = _parseBlock(source, radix, start, blockEnd); | 129 _Smi smi = _parseBlock(source, radix, start, blockEnd); |
| 130 if (smi == null) return null; | 130 if (smi == null) return null; |
| 131 result = sign * smi; | 131 result = sign * smi; |
| 132 start = blockEnd; | 132 start = blockEnd; |
| 133 } | 133 } |
| 134 int multiplier = _PARSE_LIMITS[tableIndex + 1]; | 134 int multiplier = _PARSE_LIMITS[tableIndex + 1]; |
| 135 int positiveOverflowLimit = 0; |
| 136 int negativeOverflowLimit = 0; |
| 137 if (_limitIntsTo64Bits) { |
| 138 tableIndex = tableIndex << 1; // pre-multiply by 2 for simpler indexing |
| 139 positiveOverflowLimit = _int64OverflowLimits[tableIndex]; |
| 140 if (positiveOverflowLimit == 0) { |
| 141 positiveOverflowLimit = |
| 142 _initInt64OverflowLimits(tableIndex, multiplier); |
| 143 } |
| 144 negativeOverflowLimit = _int64OverflowLimits[tableIndex + 1]; |
| 145 } |
| 135 int blockEnd = start + blockSize; | 146 int blockEnd = start + blockSize; |
| 136 do { | 147 do { |
| 137 _Smi smi = _parseBlock(source, radix, start, blockEnd); | 148 _Smi smi = _parseBlock(source, radix, start, blockEnd); |
| 138 if (smi == null) return null; | 149 if (smi == null) return null; |
| 150 if (_limitIntsTo64Bits) { |
| 151 if (result >= positiveOverflowLimit) { |
| 152 if ((result > positiveOverflowLimit) || |
| 153 (smi > _int64OverflowLimits[tableIndex + 2])) { |
| 154 return null; |
| 155 } |
| 156 } else if (result <= negativeOverflowLimit) { |
| 157 if ((result < negativeOverflowLimit) || |
| 158 (smi > _int64OverflowLimits[tableIndex + 3])) { |
| 159 return null; |
| 160 } |
| 161 } |
| 162 } |
| 139 result = (result * multiplier) + (sign * smi); | 163 result = (result * multiplier) + (sign * smi); |
| 140 start = blockEnd; | 164 start = blockEnd; |
| 141 blockEnd = start + blockSize; | 165 blockEnd = start + blockSize; |
| 142 } while (blockEnd <= end); | 166 } while (blockEnd <= end); |
| 143 return result; | 167 return result; |
| 144 } | 168 } |
| 145 | 169 |
| 146 // Parse block of digits into a Smi. | 170 // Parse block of digits into a Smi. |
| 147 static _Smi _parseBlock(String source, int radix, int start, int end) { | 171 static _Smi _parseBlock(String source, int radix, int start, int end) { |
| 148 _Smi result = 0; | 172 _Smi result = 0; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 6, 481890304, 12, 232218265089212416, | 223 6, 481890304, 12, 232218265089212416, |
| 200 6, 594823321, 12, 353814783205469041, | 224 6, 594823321, 12, 353814783205469041, |
| 201 6, 729000000, 12, 531441000000000000, // radix: 30 | 225 6, 729000000, 12, 531441000000000000, // radix: 30 |
| 202 6, 887503681, 12, 787662783788549761, | 226 6, 887503681, 12, 787662783788549761, |
| 203 6, 1073741824, 12, 1152921504606846976, | 227 6, 1073741824, 12, 1152921504606846976, |
| 204 5, 39135393, 12, 1667889514952984961, | 228 5, 39135393, 12, 1667889514952984961, |
| 205 5, 45435424, 12, 2386420683693101056, | 229 5, 45435424, 12, 2386420683693101056, |
| 206 5, 52521875, 12, 3379220508056640625, // radix: 35 | 230 5, 52521875, 12, 3379220508056640625, // radix: 35 |
| 207 5, 60466176, 11, 131621703842267136, | 231 5, 60466176, 11, 131621703842267136, |
| 208 ]; | 232 ]; |
| 233 |
| 234 /// Flag indicating if integers are limited by 64 bits |
| 235 /// (`--limit-ints-to-64-bits` mode is enabled). |
| 236 static const _limitIntsTo64Bits = ((1 << 64) == 0); |
| 237 |
| 238 static const _maxInt64 = 0x7fffffffffffffff; |
| 239 static const _minInt64 = -_maxInt64 - 1; |
| 240 |
| 241 /// In the `--limit-ints-to-64-bits` mode calculation of the expression |
| 242 /// |
| 243 /// result = (result * multiplier) + (sign * smi) |
| 244 /// |
| 245 /// in `_parseRadix()` may overflow 64-bit integers. In such case, |
| 246 /// `int.parse()` should stop with an error. |
| 247 /// |
| 248 /// This table is lazily filled with int64 overflow limits for result and smi. |
| 249 /// For each multiplier from `_PARSE_LIMITS[tableIndex + 1]` this table |
| 250 /// contains |
| 251 /// |
| 252 /// * `[tableIndex*2]` = positive limit for result |
| 253 /// * `[tableIndex*2 + 1]` = negative limit for result |
| 254 /// * `[tableIndex*2 + 2]` = limit for smi if result is exactly at positive li
mit |
| 255 /// * `[tableIndex*2 + 3]` = limit for smi if result is exactly at negative li
mit |
| 256 static final Int64List _int64OverflowLimits = |
| 257 new Int64List(_PARSE_LIMITS.length * 2); |
| 258 |
| 259 static int _initInt64OverflowLimits(int tableIndex, int multiplier) { |
| 260 _int64OverflowLimits[tableIndex] = _maxInt64 ~/ multiplier; |
| 261 _int64OverflowLimits[tableIndex + 1] = _minInt64 ~/ multiplier; |
| 262 _int64OverflowLimits[tableIndex + 2] = _maxInt64.remainder(multiplier); |
| 263 _int64OverflowLimits[tableIndex + 3] = -(_minInt64.remainder(multiplier)); |
| 264 return _int64OverflowLimits[tableIndex]; |
| 265 } |
| 209 } | 266 } |
| OLD | NEW |