OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "src/compiler/operation-typer.h" |
| 6 |
| 7 #include "src/factory.h" |
| 8 #include "src/isolate.h" |
| 9 #include "src/type-cache.h" |
| 10 #include "src/types.h" |
| 11 |
| 12 #include "src/objects-inl.h" |
| 13 |
| 14 namespace v8 { |
| 15 namespace internal { |
| 16 namespace compiler { |
| 17 |
| 18 OperationTyper::OperationTyper(Isolate* isolate, Zone* zone) |
| 19 : zone_(zone), cache_(TypeCache::Get()) { |
| 20 Factory* factory = isolate->factory(); |
| 21 singleton_false_ = Type::Constant(factory->false_value(), zone); |
| 22 singleton_true_ = Type::Constant(factory->true_value(), zone); |
| 23 singleton_the_hole_ = Type::Constant(factory->the_hole_value(), zone); |
| 24 } |
| 25 |
| 26 Type* OperationTyper::Merge(Type* left, Type* right) { |
| 27 return Type::Union(left, right, zone()); |
| 28 } |
| 29 |
| 30 Type* OperationTyper::WeakenRange(Type* previous_range, Type* current_range) { |
| 31 static const double kWeakenMinLimits[] = {0.0, |
| 32 -1073741824.0, |
| 33 -2147483648.0, |
| 34 -4294967296.0, |
| 35 -8589934592.0, |
| 36 -17179869184.0, |
| 37 -34359738368.0, |
| 38 -68719476736.0, |
| 39 -137438953472.0, |
| 40 -274877906944.0, |
| 41 -549755813888.0, |
| 42 -1099511627776.0, |
| 43 -2199023255552.0, |
| 44 -4398046511104.0, |
| 45 -8796093022208.0, |
| 46 -17592186044416.0, |
| 47 -35184372088832.0, |
| 48 -70368744177664.0, |
| 49 -140737488355328.0, |
| 50 -281474976710656.0, |
| 51 -562949953421312.0}; |
| 52 static const double kWeakenMaxLimits[] = {0.0, |
| 53 1073741823.0, |
| 54 2147483647.0, |
| 55 4294967295.0, |
| 56 8589934591.0, |
| 57 17179869183.0, |
| 58 34359738367.0, |
| 59 68719476735.0, |
| 60 137438953471.0, |
| 61 274877906943.0, |
| 62 549755813887.0, |
| 63 1099511627775.0, |
| 64 2199023255551.0, |
| 65 4398046511103.0, |
| 66 8796093022207.0, |
| 67 17592186044415.0, |
| 68 35184372088831.0, |
| 69 70368744177663.0, |
| 70 140737488355327.0, |
| 71 281474976710655.0, |
| 72 562949953421311.0}; |
| 73 STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits)); |
| 74 |
| 75 double current_min = current_range->Min(); |
| 76 double new_min = current_min; |
| 77 // Find the closest lower entry in the list of allowed |
| 78 // minima (or negative infinity if there is no such entry). |
| 79 if (current_min != previous_range->Min()) { |
| 80 new_min = -V8_INFINITY; |
| 81 for (double const min : kWeakenMinLimits) { |
| 82 if (min <= current_min) { |
| 83 new_min = min; |
| 84 break; |
| 85 } |
| 86 } |
| 87 } |
| 88 |
| 89 double current_max = current_range->Max(); |
| 90 double new_max = current_max; |
| 91 // Find the closest greater entry in the list of allowed |
| 92 // maxima (or infinity if there is no such entry). |
| 93 if (current_max != previous_range->Max()) { |
| 94 new_max = V8_INFINITY; |
| 95 for (double const max : kWeakenMaxLimits) { |
| 96 if (max >= current_max) { |
| 97 new_max = max; |
| 98 break; |
| 99 } |
| 100 } |
| 101 } |
| 102 |
| 103 return Type::Range(new_min, new_max, zone()); |
| 104 } |
| 105 |
| 106 Type* OperationTyper::Rangify(Type* type) { |
| 107 if (type->IsRange()) return type; // Shortcut. |
| 108 if (!type->Is(cache_.kInteger)) { |
| 109 return type; // Give up on non-integer types. |
| 110 } |
| 111 double min = type->Min(); |
| 112 double max = type->Max(); |
| 113 // Handle the degenerate case of empty bitset types (such as |
| 114 // OtherUnsigned31 and OtherSigned32 on 64-bit architectures). |
| 115 if (std::isnan(min)) { |
| 116 DCHECK(std::isnan(max)); |
| 117 return type; |
| 118 } |
| 119 return Type::Range(min, max, zone()); |
| 120 } |
| 121 |
| 122 namespace { |
| 123 |
| 124 // Returns the array's least element, ignoring NaN. |
| 125 // There must be at least one non-NaN element. |
| 126 // Any -0 is converted to 0. |
| 127 double array_min(double a[], size_t n) { |
| 128 DCHECK(n != 0); |
| 129 double x = +V8_INFINITY; |
| 130 for (size_t i = 0; i < n; ++i) { |
| 131 if (!std::isnan(a[i])) { |
| 132 x = std::min(a[i], x); |
| 133 } |
| 134 } |
| 135 DCHECK(!std::isnan(x)); |
| 136 return x == 0 ? 0 : x; // -0 -> 0 |
| 137 } |
| 138 |
| 139 // Returns the array's greatest element, ignoring NaN. |
| 140 // There must be at least one non-NaN element. |
| 141 // Any -0 is converted to 0. |
| 142 double array_max(double a[], size_t n) { |
| 143 DCHECK(n != 0); |
| 144 double x = -V8_INFINITY; |
| 145 for (size_t i = 0; i < n; ++i) { |
| 146 if (!std::isnan(a[i])) { |
| 147 x = std::max(a[i], x); |
| 148 } |
| 149 } |
| 150 DCHECK(!std::isnan(x)); |
| 151 return x == 0 ? 0 : x; // -0 -> 0 |
| 152 } |
| 153 |
| 154 } // namespace |
| 155 |
| 156 Type* OperationTyper::AddRanger(RangeType* lhs, RangeType* rhs) { |
| 157 double results[4]; |
| 158 results[0] = lhs->Min() + rhs->Min(); |
| 159 results[1] = lhs->Min() + rhs->Max(); |
| 160 results[2] = lhs->Max() + rhs->Min(); |
| 161 results[3] = lhs->Max() + rhs->Max(); |
| 162 // Since none of the inputs can be -0, the result cannot be -0 either. |
| 163 // However, it can be nan (the sum of two infinities of opposite sign). |
| 164 // On the other hand, if none of the "results" above is nan, then the actual |
| 165 // result cannot be nan either. |
| 166 int nans = 0; |
| 167 for (int i = 0; i < 4; ++i) { |
| 168 if (std::isnan(results[i])) ++nans; |
| 169 } |
| 170 if (nans == 4) return Type::NaN(); // [-inf..-inf] + [inf..inf] or vice versa |
| 171 Type* range = |
| 172 Type::Range(array_min(results, 4), array_max(results, 4), zone()); |
| 173 return nans == 0 ? range : Type::Union(range, Type::NaN(), zone()); |
| 174 // Examples: |
| 175 // [-inf, -inf] + [+inf, +inf] = NaN |
| 176 // [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN |
| 177 // [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN |
| 178 // [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN |
| 179 } |
| 180 |
| 181 Type* OperationTyper::SubtractRanger(RangeType* lhs, RangeType* rhs) { |
| 182 double results[4]; |
| 183 results[0] = lhs->Min() - rhs->Min(); |
| 184 results[1] = lhs->Min() - rhs->Max(); |
| 185 results[2] = lhs->Max() - rhs->Min(); |
| 186 results[3] = lhs->Max() - rhs->Max(); |
| 187 // Since none of the inputs can be -0, the result cannot be -0. |
| 188 // However, it can be nan (the subtraction of two infinities of same sign). |
| 189 // On the other hand, if none of the "results" above is nan, then the actual |
| 190 // result cannot be nan either. |
| 191 int nans = 0; |
| 192 for (int i = 0; i < 4; ++i) { |
| 193 if (std::isnan(results[i])) ++nans; |
| 194 } |
| 195 if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign) |
| 196 Type* range = |
| 197 Type::Range(array_min(results, 4), array_max(results, 4), zone()); |
| 198 return nans == 0 ? range : Type::Union(range, Type::NaN(), zone()); |
| 199 // Examples: |
| 200 // [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN |
| 201 // [-inf, -inf] - [-inf, -inf] = NaN |
| 202 // [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN |
| 203 // [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN |
| 204 } |
| 205 |
| 206 Type* OperationTyper::ModulusRanger(RangeType* lhs, RangeType* rhs) { |
| 207 double lmin = lhs->Min(); |
| 208 double lmax = lhs->Max(); |
| 209 double rmin = rhs->Min(); |
| 210 double rmax = rhs->Max(); |
| 211 |
| 212 double labs = std::max(std::abs(lmin), std::abs(lmax)); |
| 213 double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1; |
| 214 double abs = std::min(labs, rabs); |
| 215 bool maybe_minus_zero = false; |
| 216 double omin = 0; |
| 217 double omax = 0; |
| 218 if (lmin >= 0) { // {lhs} positive. |
| 219 omin = 0; |
| 220 omax = abs; |
| 221 } else if (lmax <= 0) { // {lhs} negative. |
| 222 omin = 0 - abs; |
| 223 omax = 0; |
| 224 maybe_minus_zero = true; |
| 225 } else { |
| 226 omin = 0 - abs; |
| 227 omax = abs; |
| 228 maybe_minus_zero = true; |
| 229 } |
| 230 |
| 231 Type* result = Type::Range(omin, omax, zone()); |
| 232 if (maybe_minus_zero) result = Type::Union(result, Type::MinusZero(), zone()); |
| 233 return result; |
| 234 } |
| 235 |
| 236 Type* OperationTyper::ToNumber(Type* type) { |
| 237 if (type->Is(Type::Number())) return type; |
| 238 if (type->Is(Type::NullOrUndefined())) { |
| 239 if (type->Is(Type::Null())) return cache_.kSingletonZero; |
| 240 if (type->Is(Type::Undefined())) return Type::NaN(); |
| 241 return Type::Union(Type::NaN(), cache_.kSingletonZero, zone()); |
| 242 } |
| 243 if (type->Is(Type::NumberOrUndefined())) { |
| 244 return Type::Union(Type::Intersect(type, Type::Number(), zone()), |
| 245 Type::NaN(), zone()); |
| 246 } |
| 247 if (type->Is(singleton_false_)) return cache_.kSingletonZero; |
| 248 if (type->Is(singleton_true_)) return cache_.kSingletonOne; |
| 249 if (type->Is(Type::Boolean())) return cache_.kZeroOrOne; |
| 250 if (type->Is(Type::BooleanOrNumber())) { |
| 251 return Type::Union(Type::Intersect(type, Type::Number(), zone()), |
| 252 cache_.kZeroOrOne, zone()); |
| 253 } |
| 254 return Type::Number(); |
| 255 } |
| 256 |
| 257 Type* OperationTyper::NumericAdd(Type* lhs, Type* rhs) { |
| 258 DCHECK(lhs->Is(Type::Number())); |
| 259 DCHECK(rhs->Is(Type::Number())); |
| 260 |
| 261 lhs = Rangify(lhs); |
| 262 rhs = Rangify(rhs); |
| 263 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 264 if (lhs->IsRange() && rhs->IsRange()) { |
| 265 return AddRanger(lhs->AsRange(), rhs->AsRange()); |
| 266 } |
| 267 // TODO(neis): Deal with numeric bitsets here and elsewhere. |
| 268 return Type::Number(); |
| 269 } |
| 270 |
| 271 Type* OperationTyper::NumericSubtract(Type* lhs, Type* rhs) { |
| 272 DCHECK(lhs->Is(Type::Number())); |
| 273 DCHECK(rhs->Is(Type::Number())); |
| 274 |
| 275 lhs = Rangify(lhs); |
| 276 rhs = Rangify(rhs); |
| 277 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 278 if (lhs->IsRange() && rhs->IsRange()) { |
| 279 return SubtractRanger(lhs->AsRange(), rhs->AsRange()); |
| 280 } |
| 281 // TODO(neis): Deal with numeric bitsets here and elsewhere. |
| 282 return Type::Number(); |
| 283 } |
| 284 |
| 285 Type* OperationTyper::ToPrimitive(Type* type) { |
| 286 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { |
| 287 return type; |
| 288 } |
| 289 return Type::Primitive(); |
| 290 } |
| 291 |
| 292 Type* OperationTyper::Invert(Type* type) { |
| 293 DCHECK(type->Is(Type::Boolean())); |
| 294 DCHECK(type->IsInhabited()); |
| 295 if (type->Is(singleton_false())) return singleton_true(); |
| 296 if (type->Is(singleton_true())) return singleton_false(); |
| 297 return type; |
| 298 } |
| 299 |
| 300 OperationTyper::ComparisonOutcome OperationTyper::Invert( |
| 301 ComparisonOutcome outcome) { |
| 302 ComparisonOutcome result(0); |
| 303 if ((outcome & kComparisonUndefined) != 0) result |= kComparisonUndefined; |
| 304 if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse; |
| 305 if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue; |
| 306 return result; |
| 307 } |
| 308 |
| 309 Type* OperationTyper::FalsifyUndefined(ComparisonOutcome outcome) { |
| 310 if ((outcome & kComparisonFalse) != 0 || |
| 311 (outcome & kComparisonUndefined) != 0) { |
| 312 return (outcome & kComparisonTrue) != 0 ? Type::Boolean() |
| 313 : singleton_false(); |
| 314 } |
| 315 // Type should be non empty, so we know it should be true. |
| 316 DCHECK((outcome & kComparisonTrue) != 0); |
| 317 return singleton_true(); |
| 318 } |
| 319 |
| 320 Type* OperationTyper::TypeJSAdd(Type* lhs, Type* rhs) { |
| 321 lhs = ToPrimitive(lhs); |
| 322 rhs = ToPrimitive(rhs); |
| 323 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) { |
| 324 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) { |
| 325 return Type::String(); |
| 326 } else { |
| 327 return Type::NumberOrString(); |
| 328 } |
| 329 } |
| 330 lhs = ToNumber(lhs); |
| 331 rhs = ToNumber(rhs); |
| 332 return NumericAdd(lhs, rhs); |
| 333 } |
| 334 |
| 335 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) { |
| 336 return NumericSubtract(ToNumber(lhs), ToNumber(rhs)); |
| 337 } |
| 338 |
| 339 } // namespace compiler |
| 340 } // namespace internal |
| 341 } // namespace v8 |
OLD | NEW |