Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(266)

Side by Side Diff: src/compiler/typer.cc

Issue 1428243003: [turbofan] Add support for relevant ES6 type conversion intrinsics. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Address comments. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/operator-properties.cc ('k') | src/heap/heap.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/operator-properties.cc ('k') | src/heap/heap.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698