| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/typer.h" | 5 #include "src/compiler/typer.h" |
| 6 | 6 |
| 7 #include "src/base/flags.h" | 7 #include "src/base/flags.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
| 10 #include "src/compiler/common-operator.h" | 10 #include "src/compiler/common-operator.h" |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 }; | 224 }; |
| 225 typedef base::Flags<ComparisonOutcomeFlags> ComparisonOutcome; | 225 typedef base::Flags<ComparisonOutcomeFlags> ComparisonOutcome; |
| 226 | 226 |
| 227 static ComparisonOutcome Invert(ComparisonOutcome, Typer*); | 227 static ComparisonOutcome Invert(ComparisonOutcome, Typer*); |
| 228 static Type* Invert(Type*, Typer*); | 228 static Type* Invert(Type*, Typer*); |
| 229 static Type* FalsifyUndefined(ComparisonOutcome, Typer*); | 229 static Type* FalsifyUndefined(ComparisonOutcome, Typer*); |
| 230 static Type* Rangify(Type*, Typer*); | 230 static Type* Rangify(Type*, Typer*); |
| 231 | 231 |
| 232 static Type* ToPrimitive(Type*, Typer*); | 232 static Type* ToPrimitive(Type*, Typer*); |
| 233 static Type* ToBoolean(Type*, Typer*); | 233 static Type* ToBoolean(Type*, Typer*); |
| 234 static Type* ToInteger(Type*, Typer*); |
| 235 static Type* ToLength(Type*, Typer*); |
| 236 static Type* ToName(Type*, Typer*); |
| 234 static Type* ToNumber(Type*, Typer*); | 237 static Type* ToNumber(Type*, Typer*); |
| 238 static Type* ToObject(Type*, Typer*); |
| 235 static Type* ToString(Type*, Typer*); | 239 static Type* ToString(Type*, Typer*); |
| 236 static Type* NumberToInt32(Type*, Typer*); | 240 static Type* NumberToInt32(Type*, Typer*); |
| 237 static Type* NumberToUint32(Type*, Typer*); | 241 static Type* NumberToUint32(Type*, Typer*); |
| 238 | 242 |
| 239 static Type* JSAddRanger(Type::RangeType*, Type::RangeType*, Typer*); | 243 static Type* JSAddRanger(Type::RangeType*, Type::RangeType*, Typer*); |
| 240 static Type* JSSubtractRanger(Type::RangeType*, Type::RangeType*, Typer*); | 244 static Type* JSSubtractRanger(Type::RangeType*, Type::RangeType*, Typer*); |
| 241 static Type* JSMultiplyRanger(Type::RangeType*, Type::RangeType*, Typer*); | 245 static Type* JSMultiplyRanger(Type::RangeType*, Type::RangeType*, Typer*); |
| 242 static Type* JSDivideRanger(Type::RangeType*, Type::RangeType*, Typer*); | 246 static Type* JSDivideRanger(Type::RangeType*, Type::RangeType*, Typer*); |
| 243 static Type* JSModulusRanger(Type::RangeType*, Type::RangeType*, Typer*); | 247 static Type* JSModulusRanger(Type::RangeType*, Type::RangeType*, Typer*); |
| 244 | 248 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 if (type->Is(Type::Boolean())) return type; | 399 if (type->Is(Type::Boolean())) return type; |
| 396 if (type->Is(t->falsish_)) return t->singleton_false_; | 400 if (type->Is(t->falsish_)) return t->singleton_false_; |
| 397 if (type->Is(t->truish_)) return t->singleton_true_; | 401 if (type->Is(t->truish_)) return t->singleton_true_; |
| 398 if (type->Is(Type::PlainNumber()) && (type->Max() < 0 || 0 < type->Min())) { | 402 if (type->Is(Type::PlainNumber()) && (type->Max() < 0 || 0 < type->Min())) { |
| 399 return t->singleton_true_; // Ruled out nan, -0 and +0. | 403 return t->singleton_true_; // Ruled out nan, -0 and +0. |
| 400 } | 404 } |
| 401 return Type::Boolean(); | 405 return Type::Boolean(); |
| 402 } | 406 } |
| 403 | 407 |
| 404 | 408 |
| 409 // static |
| 410 Type* Typer::Visitor::ToInteger(Type* type, Typer* t) { |
| 411 // ES6 section 7.1.4 ToInteger ( argument ) |
| 412 type = ToNumber(type, t); |
| 413 if (type->Is(t->cache_.kIntegerOrMinusZero)) return type; |
| 414 return t->cache_.kIntegerOrMinusZero; |
| 415 } |
| 416 |
| 417 |
| 418 // static |
| 419 Type* Typer::Visitor::ToLength(Type* type, Typer* t) { |
| 420 // ES6 section 7.1.15 ToLength ( argument ) |
| 421 type = ToInteger(type, t); |
| 422 double min = type->Min(); |
| 423 double max = type->Max(); |
| 424 if (min <= 0.0) min = 0.0; |
| 425 if (max > kMaxSafeInteger) max = kMaxSafeInteger; |
| 426 if (max <= min) max = min; |
| 427 return Type::Range(min, max, t->zone()); |
| 428 } |
| 429 |
| 430 |
| 431 // static |
| 432 Type* Typer::Visitor::ToName(Type* type, Typer* t) { |
| 433 // ES6 section 7.1.14 ToPropertyKey ( argument ) |
| 434 type = ToPrimitive(type, t); |
| 435 if (type->Is(Type::Name())) return type; |
| 436 if (type->Maybe(Type::Symbol())) return Type::Name(); |
| 437 return ToString(type, t); |
| 438 } |
| 439 |
| 440 |
| 441 // static |
| 405 Type* Typer::Visitor::ToNumber(Type* type, Typer* t) { | 442 Type* Typer::Visitor::ToNumber(Type* type, Typer* t) { |
| 406 if (type->Is(Type::Number())) return type; | 443 if (type->Is(Type::Number())) return type; |
| 407 if (type->Is(Type::NullOrUndefined())) { | 444 if (type->Is(Type::NullOrUndefined())) { |
| 408 if (type->Is(Type::Null())) return t->cache_.kSingletonZero; | 445 if (type->Is(Type::Null())) return t->cache_.kSingletonZero; |
| 409 if (type->Is(Type::Undefined())) return Type::NaN(); | 446 if (type->Is(Type::Undefined())) return Type::NaN(); |
| 410 return Type::Union(Type::NaN(), t->cache_.kSingletonZero, t->zone()); | 447 return Type::Union(Type::NaN(), t->cache_.kSingletonZero, t->zone()); |
| 411 } | 448 } |
| 412 if (type->Is(Type::NumberOrUndefined())) { | 449 if (type->Is(Type::NumberOrUndefined())) { |
| 413 return Type::Union(Type::Intersect(type, Type::Number(), t->zone()), | 450 return Type::Union(Type::Intersect(type, Type::Number(), t->zone()), |
| 414 Type::NaN(), t->zone()); | 451 Type::NaN(), t->zone()); |
| 415 } | 452 } |
| 416 if (type->Is(t->singleton_false_)) return t->cache_.kSingletonZero; | 453 if (type->Is(t->singleton_false_)) return t->cache_.kSingletonZero; |
| 417 if (type->Is(t->singleton_true_)) return t->cache_.kSingletonOne; | 454 if (type->Is(t->singleton_true_)) return t->cache_.kSingletonOne; |
| 418 if (type->Is(Type::Boolean())) return t->cache_.kZeroOrOne; | 455 if (type->Is(Type::Boolean())) return t->cache_.kZeroOrOne; |
| 419 if (type->Is(Type::BooleanOrNumber())) { | 456 if (type->Is(Type::BooleanOrNumber())) { |
| 420 return Type::Union(Type::Intersect(type, Type::Number(), t->zone()), | 457 return Type::Union(Type::Intersect(type, Type::Number(), t->zone()), |
| 421 t->cache_.kZeroOrOne, t->zone()); | 458 t->cache_.kZeroOrOne, t->zone()); |
| 422 } | 459 } |
| 423 return Type::Number(); | 460 return Type::Number(); |
| 424 } | 461 } |
| 425 | 462 |
| 426 | 463 |
| 464 // static |
| 465 Type* Typer::Visitor::ToObject(Type* type, Typer* t) { |
| 466 // ES6 section 7.1.13 ToObject ( argument ) |
| 467 if (type->Is(Type::Receiver())) return type; |
| 468 if (type->Is(Type::Primitive())) return Type::OtherObject(); |
| 469 if (!type->Maybe(Type::Undetectable())) return Type::DetectableReceiver(); |
| 470 return Type::Receiver(); |
| 471 } |
| 472 |
| 473 |
| 474 // static |
| 427 Type* Typer::Visitor::ToString(Type* type, Typer* t) { | 475 Type* Typer::Visitor::ToString(Type* type, Typer* t) { |
| 476 // ES6 section 7.1.12 ToString ( argument ) |
| 477 type = ToPrimitive(type, t); |
| 428 if (type->Is(Type::String())) return type; | 478 if (type->Is(Type::String())) return type; |
| 429 return Type::String(); | 479 return Type::String(); |
| 430 } | 480 } |
| 431 | 481 |
| 432 | 482 |
| 433 Type* Typer::Visitor::NumberToInt32(Type* type, Typer* t) { | 483 Type* Typer::Visitor::NumberToInt32(Type* type, Typer* t) { |
| 434 // TODO(neis): DCHECK(type->Is(Type::Number())); | 484 // TODO(neis): DCHECK(type->Is(Type::Number())); |
| 435 if (type->Is(Type::Signed32())) return type; | 485 if (type->Is(Type::Signed32())) return type; |
| 436 if (type->Is(t->cache_.kZeroish)) return t->cache_.kSingletonZero; | 486 if (type->Is(t->cache_.kZeroish)) return t->cache_.kSingletonZero; |
| 437 if (type->Is(t->signed32ish_)) { | 487 if (type->Is(t->signed32ish_)) { |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 results[2] = lmax * rmin; | 1038 results[2] = lmax * rmin; |
| 989 results[3] = lmax * rmax; | 1039 results[3] = lmax * rmax; |
| 990 // If the result may be nan, we give up on calculating a precise type, because | 1040 // If the result may be nan, we give up on calculating a precise type, because |
| 991 // the discontinuity makes it too complicated. Note that even if none of the | 1041 // the discontinuity makes it too complicated. Note that even if none of the |
| 992 // "results" above is nan, the actual result may still be, so we have to do a | 1042 // "results" above is nan, the actual result may still be, so we have to do a |
| 993 // different check: | 1043 // different check: |
| 994 bool maybe_nan = (lhs->Maybe(t->cache_.kSingletonZero) && | 1044 bool maybe_nan = (lhs->Maybe(t->cache_.kSingletonZero) && |
| 995 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) || | 1045 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) || |
| 996 (rhs->Maybe(t->cache_.kSingletonZero) && | 1046 (rhs->Maybe(t->cache_.kSingletonZero) && |
| 997 (lmin == -V8_INFINITY || lmax == +V8_INFINITY)); | 1047 (lmin == -V8_INFINITY || lmax == +V8_INFINITY)); |
| 998 if (maybe_nan) return t->cache_.kWeakint; // Giving up. | 1048 if (maybe_nan) return t->cache_.kIntegerOrMinusZeroOrNaN; // Giving up. |
| 999 bool maybe_minuszero = (lhs->Maybe(t->cache_.kSingletonZero) && rmin < 0) || | 1049 bool maybe_minuszero = (lhs->Maybe(t->cache_.kSingletonZero) && rmin < 0) || |
| 1000 (rhs->Maybe(t->cache_.kSingletonZero) && lmin < 0); | 1050 (rhs->Maybe(t->cache_.kSingletonZero) && lmin < 0); |
| 1001 Type* range = | 1051 Type* range = |
| 1002 Type::Range(array_min(results, 4), array_max(results, 4), t->zone()); | 1052 Type::Range(array_min(results, 4), array_max(results, 4), t->zone()); |
| 1003 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), t->zone()) | 1053 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), t->zone()) |
| 1004 : range; | 1054 : range; |
| 1005 } | 1055 } |
| 1006 | 1056 |
| 1007 | 1057 |
| 1008 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) { | 1058 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) { |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1135 Type* Typer::Visitor::TypeJSToNumber(Node* node) { | 1185 Type* Typer::Visitor::TypeJSToNumber(Node* node) { |
| 1136 return TypeUnaryOp(node, ToNumber); | 1186 return TypeUnaryOp(node, ToNumber); |
| 1137 } | 1187 } |
| 1138 | 1188 |
| 1139 | 1189 |
| 1140 Type* Typer::Visitor::TypeJSToString(Node* node) { | 1190 Type* Typer::Visitor::TypeJSToString(Node* node) { |
| 1141 return TypeUnaryOp(node, ToString); | 1191 return TypeUnaryOp(node, ToString); |
| 1142 } | 1192 } |
| 1143 | 1193 |
| 1144 | 1194 |
| 1145 Type* Typer::Visitor::TypeJSToName(Node* node) { return Type::Name(); } | 1195 Type* Typer::Visitor::TypeJSToName(Node* node) { |
| 1196 return TypeUnaryOp(node, ToName); |
| 1197 } |
| 1146 | 1198 |
| 1147 | 1199 |
| 1148 Type* Typer::Visitor::TypeJSToObject(Node* node) { return Type::Receiver(); } | 1200 Type* Typer::Visitor::TypeJSToObject(Node* node) { |
| 1201 return TypeUnaryOp(node, ToObject); |
| 1202 } |
| 1149 | 1203 |
| 1150 | 1204 |
| 1151 // JS object operators. | 1205 // JS object operators. |
| 1152 | 1206 |
| 1153 | 1207 |
| 1154 Type* Typer::Visitor::TypeJSCreate(Node* node) { return Type::Object(); } | 1208 Type* Typer::Visitor::TypeJSCreate(Node* node) { return Type::Object(); } |
| 1155 | 1209 |
| 1156 | 1210 |
| 1157 Type* Typer::Visitor::TypeJSCreateArguments(Node* node) { | 1211 Type* Typer::Visitor::TypeJSCreateArguments(Node* node) { |
| 1158 return Type::OtherObject(); | 1212 return Type::OtherObject(); |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1387 if (fun->IsConstant() && fun->AsConstant()->Value()->IsJSFunction()) { | 1441 if (fun->IsConstant() && fun->AsConstant()->Value()->IsJSFunction()) { |
| 1388 Handle<JSFunction> function = | 1442 Handle<JSFunction> function = |
| 1389 Handle<JSFunction>::cast(fun->AsConstant()->Value()); | 1443 Handle<JSFunction>::cast(fun->AsConstant()->Value()); |
| 1390 if (function->shared()->HasBuiltinFunctionId()) { | 1444 if (function->shared()->HasBuiltinFunctionId()) { |
| 1391 switch (function->shared()->builtin_function_id()) { | 1445 switch (function->shared()->builtin_function_id()) { |
| 1392 case kMathRandom: | 1446 case kMathRandom: |
| 1393 return Type::OrderedNumber(); | 1447 return Type::OrderedNumber(); |
| 1394 case kMathFloor: | 1448 case kMathFloor: |
| 1395 case kMathRound: | 1449 case kMathRound: |
| 1396 case kMathCeil: | 1450 case kMathCeil: |
| 1397 return t->cache_.kWeakint; | 1451 return t->cache_.kIntegerOrMinusZeroOrNaN; |
| 1398 // Unary math functions. | 1452 // Unary math functions. |
| 1399 case kMathAbs: | 1453 case kMathAbs: |
| 1400 case kMathLog: | 1454 case kMathLog: |
| 1401 case kMathExp: | 1455 case kMathExp: |
| 1402 case kMathSqrt: | 1456 case kMathSqrt: |
| 1403 case kMathCos: | 1457 case kMathCos: |
| 1404 case kMathSin: | 1458 case kMathSin: |
| 1405 case kMathTan: | 1459 case kMathTan: |
| 1406 case kMathAcos: | 1460 case kMathAcos: |
| 1407 case kMathAsin: | 1461 case kMathAsin: |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1461 case Runtime::kInlineMathSqrt: | 1515 case Runtime::kInlineMathSqrt: |
| 1462 case Runtime::kInlineMathAcos: | 1516 case Runtime::kInlineMathAcos: |
| 1463 case Runtime::kInlineMathAsin: | 1517 case Runtime::kInlineMathAsin: |
| 1464 case Runtime::kInlineMathAtan: | 1518 case Runtime::kInlineMathAtan: |
| 1465 case Runtime::kInlineMathAtan2: | 1519 case Runtime::kInlineMathAtan2: |
| 1466 return Type::Number(); | 1520 return Type::Number(); |
| 1467 case Runtime::kInlineMathClz32: | 1521 case Runtime::kInlineMathClz32: |
| 1468 return Type::Range(0, 32, zone()); | 1522 return Type::Range(0, 32, zone()); |
| 1469 case Runtime::kInlineStringGetLength: | 1523 case Runtime::kInlineStringGetLength: |
| 1470 return Type::Range(0, String::kMaxLength, zone()); | 1524 return Type::Range(0, String::kMaxLength, zone()); |
| 1525 case Runtime::kInlineToInteger: |
| 1526 return TypeUnaryOp(node, ToInteger); |
| 1527 case Runtime::kInlineToLength: |
| 1528 return TypeUnaryOp(node, ToLength); |
| 1529 case Runtime::kInlineToName: |
| 1530 return TypeUnaryOp(node, ToName); |
| 1531 case Runtime::kInlineToNumber: |
| 1532 return TypeUnaryOp(node, ToNumber); |
| 1471 case Runtime::kInlineToObject: | 1533 case Runtime::kInlineToObject: |
| 1472 return Type::Receiver(); | 1534 return TypeUnaryOp(node, ToObject); |
| 1535 case Runtime::kInlineToPrimitive: |
| 1536 case Runtime::kInlineToPrimitive_Number: |
| 1537 case Runtime::kInlineToPrimitive_String: |
| 1538 return TypeUnaryOp(node, ToPrimitive); |
| 1539 case Runtime::kInlineToString: |
| 1540 return TypeUnaryOp(node, ToString); |
| 1473 default: | 1541 default: |
| 1474 break; | 1542 break; |
| 1475 } | 1543 } |
| 1476 return Type::Any(); | 1544 return Type::Any(); |
| 1477 } | 1545 } |
| 1478 | 1546 |
| 1479 | 1547 |
| 1480 Type* Typer::Visitor::TypeJSConvertReceiver(Node* node) { | 1548 Type* Typer::Visitor::TypeJSConvertReceiver(Node* node) { |
| 1481 return Type::Receiver(); | 1549 return Type::Receiver(); |
| 1482 } | 1550 } |
| (...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2202 } | 2270 } |
| 2203 if (Type::IsInteger(*value)) { | 2271 if (Type::IsInteger(*value)) { |
| 2204 return Type::Range(value->Number(), value->Number(), zone()); | 2272 return Type::Range(value->Number(), value->Number(), zone()); |
| 2205 } | 2273 } |
| 2206 return Type::Constant(value, zone()); | 2274 return Type::Constant(value, zone()); |
| 2207 } | 2275 } |
| 2208 | 2276 |
| 2209 } // namespace compiler | 2277 } // namespace compiler |
| 2210 } // namespace internal | 2278 } // namespace internal |
| 2211 } // namespace v8 | 2279 } // namespace v8 |
| OLD | NEW |