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 |