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

Side by Side Diff: src/hydrogen-instructions.cc

Issue 185653004: Experimental parser: merge to r19637 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 months 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 | Annotate | Revision Log
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/hydrogen-load-elimination.cc » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 17 matching lines...) Expand all
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "double.h" 30 #include "double.h"
31 #include "factory.h" 31 #include "factory.h"
32 #include "hydrogen-infer-representation.h" 32 #include "hydrogen-infer-representation.h"
33 33
34 #if V8_TARGET_ARCH_IA32 34 #if V8_TARGET_ARCH_IA32
35 #include "ia32/lithium-ia32.h" 35 #include "ia32/lithium-ia32.h"
36 #elif V8_TARGET_ARCH_X64 36 #elif V8_TARGET_ARCH_X64
37 #include "x64/lithium-x64.h" 37 #include "x64/lithium-x64.h"
38 #elif V8_TARGET_ARCH_A64
39 #include "a64/lithium-a64.h"
38 #elif V8_TARGET_ARCH_ARM 40 #elif V8_TARGET_ARCH_ARM
39 #include "arm/lithium-arm.h" 41 #include "arm/lithium-arm.h"
40 #elif V8_TARGET_ARCH_MIPS 42 #elif V8_TARGET_ARCH_MIPS
41 #include "mips/lithium-mips.h" 43 #include "mips/lithium-mips.h"
42 #else 44 #else
43 #error Unsupported target architecture. 45 #error Unsupported target architecture.
44 #endif 46 #endif
45 47
46 namespace v8 { 48 namespace v8 {
47 namespace internal { 49 namespace internal {
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 599
598 600
599 void HValue::PrintChangesTo(StringStream* stream) { 601 void HValue::PrintChangesTo(StringStream* stream) {
600 GVNFlagSet changes_flags = ChangesFlags(); 602 GVNFlagSet changes_flags = ChangesFlags();
601 if (changes_flags.IsEmpty()) return; 603 if (changes_flags.IsEmpty()) return;
602 stream->Add(" changes["); 604 stream->Add(" changes[");
603 if (changes_flags == AllSideEffectsFlagSet()) { 605 if (changes_flags == AllSideEffectsFlagSet()) {
604 stream->Add("*"); 606 stream->Add("*");
605 } else { 607 } else {
606 bool add_comma = false; 608 bool add_comma = false;
607 #define PRINT_DO(type) \ 609 #define PRINT_DO(Type) \
608 if (changes_flags.Contains(kChanges##type)) { \ 610 if (changes_flags.Contains(k##Type)) { \
609 if (add_comma) stream->Add(","); \ 611 if (add_comma) stream->Add(","); \
610 add_comma = true; \ 612 add_comma = true; \
611 stream->Add(#type); \ 613 stream->Add(#Type); \
612 } 614 }
613 GVN_TRACKED_FLAG_LIST(PRINT_DO); 615 GVN_TRACKED_FLAG_LIST(PRINT_DO);
614 GVN_UNTRACKED_FLAG_LIST(PRINT_DO); 616 GVN_UNTRACKED_FLAG_LIST(PRINT_DO);
615 #undef PRINT_DO 617 #undef PRINT_DO
616 } 618 }
617 stream->Add("]"); 619 stream->Add("]");
618 } 620 }
619 621
620 622
621 void HValue::PrintNameTo(StringStream* stream) { 623 void HValue::PrintNameTo(StringStream* stream) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 } 675 }
674 676
675 677
676 void HValue::ComputeInitialRange(Zone* zone) { 678 void HValue::ComputeInitialRange(Zone* zone) {
677 ASSERT(!HasRange()); 679 ASSERT(!HasRange());
678 range_ = InferRange(zone); 680 range_ = InferRange(zone);
679 ASSERT(HasRange()); 681 ASSERT(HasRange());
680 } 682 }
681 683
682 684
685 void HSourcePosition::PrintTo(FILE* out) {
686 if (IsUnknown()) {
687 PrintF(out, "<?>");
688 } else {
689 if (FLAG_hydrogen_track_positions) {
690 PrintF(out, "<%d:%d>", inlining_id(), position());
691 } else {
692 PrintF(out, "<0:%d>", raw());
693 }
694 }
695 }
696
697
683 void HInstruction::PrintTo(StringStream* stream) { 698 void HInstruction::PrintTo(StringStream* stream) {
684 PrintMnemonicTo(stream); 699 PrintMnemonicTo(stream);
685 PrintDataTo(stream); 700 PrintDataTo(stream);
686 PrintRangeTo(stream); 701 PrintRangeTo(stream);
687 PrintChangesTo(stream); 702 PrintChangesTo(stream);
688 PrintTypeTo(stream); 703 PrintTypeTo(stream);
689 if (CheckFlag(HValue::kHasNoObservableSideEffects)) { 704 if (CheckFlag(HValue::kHasNoObservableSideEffects)) {
690 stream->Add(" [noOSE]"); 705 stream->Add(" [noOSE]");
691 } 706 }
707 if (CheckFlag(HValue::kIsDead)) {
708 stream->Add(" [dead]");
709 }
692 } 710 }
693 711
694 712
695 void HInstruction::PrintDataTo(StringStream *stream) { 713 void HInstruction::PrintDataTo(StringStream *stream) {
696 for (int i = 0; i < OperandCount(); ++i) { 714 for (int i = 0; i < OperandCount(); ++i) {
697 if (i > 0) stream->Add(" "); 715 if (i > 0) stream->Add(" ");
698 OperandAt(i)->PrintNameTo(stream); 716 OperandAt(i)->PrintNameTo(stream);
699 } 717 }
700 } 718 }
701 719
(...skipping 24 matching lines...) Expand all
726 ASSERT(!next->IsBlockEntry()); 744 ASSERT(!next->IsBlockEntry());
727 ASSERT(!IsControlInstruction()); 745 ASSERT(!IsControlInstruction());
728 ASSERT(!next->block()->IsStartBlock()); 746 ASSERT(!next->block()->IsStartBlock());
729 ASSERT(next->previous_ != NULL); 747 ASSERT(next->previous_ != NULL);
730 HInstruction* prev = next->previous(); 748 HInstruction* prev = next->previous();
731 prev->next_ = this; 749 prev->next_ = this;
732 next->previous_ = this; 750 next->previous_ = this;
733 next_ = next; 751 next_ = next;
734 previous_ = prev; 752 previous_ = prev;
735 SetBlock(next->block()); 753 SetBlock(next->block());
736 if (position() == RelocInfo::kNoPosition && 754 if (!has_position() && next->has_position()) {
737 next->position() != RelocInfo::kNoPosition) {
738 set_position(next->position()); 755 set_position(next->position());
739 } 756 }
740 } 757 }
741 758
742 759
743 void HInstruction::InsertAfter(HInstruction* previous) { 760 void HInstruction::InsertAfter(HInstruction* previous) {
744 ASSERT(!IsLinked()); 761 ASSERT(!IsLinked());
745 ASSERT(!previous->IsControlInstruction()); 762 ASSERT(!previous->IsControlInstruction());
746 ASSERT(!IsControlInstruction() || previous->next_ == NULL); 763 ASSERT(!IsControlInstruction() || previous->next_ == NULL);
747 HBasicBlock* block = previous->block(); 764 HBasicBlock* block = previous->block();
(...skipping 16 matching lines...) Expand all
764 } 781 }
765 782
766 previous_ = previous; 783 previous_ = previous;
767 next_ = next; 784 next_ = next;
768 SetBlock(block); 785 SetBlock(block);
769 previous->next_ = this; 786 previous->next_ = this;
770 if (next != NULL) next->previous_ = this; 787 if (next != NULL) next->previous_ = this;
771 if (block->last() == previous) { 788 if (block->last() == previous) {
772 block->set_last(this); 789 block->set_last(this);
773 } 790 }
774 if (position() == RelocInfo::kNoPosition && 791 if (!has_position() && previous->has_position()) {
775 previous->position() != RelocInfo::kNoPosition) {
776 set_position(previous->position()); 792 set_position(previous->position());
777 } 793 }
778 } 794 }
779 795
780 796
781 #ifdef DEBUG 797 #ifdef DEBUG
782 void HInstruction::Verify() { 798 void HInstruction::Verify() {
783 // Verify that input operands are defined before use. 799 // Verify that input operands are defined before use.
784 HBasicBlock* cur_block = block(); 800 HBasicBlock* cur_block = block();
785 for (int i = 0; i < OperandCount(); ++i) { 801 for (int i = 0; i < OperandCount(); ++i) {
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 } 1123 }
1108 *block = NULL; 1124 *block = NULL;
1109 return false; 1125 return false;
1110 } 1126 }
1111 1127
1112 1128
1113 void HCompareMap::PrintDataTo(StringStream* stream) { 1129 void HCompareMap::PrintDataTo(StringStream* stream) {
1114 value()->PrintNameTo(stream); 1130 value()->PrintNameTo(stream);
1115 stream->Add(" (%p)", *map().handle()); 1131 stream->Add(" (%p)", *map().handle());
1116 HControlInstruction::PrintDataTo(stream); 1132 HControlInstruction::PrintDataTo(stream);
1133 if (known_successor_index() == 0) {
1134 stream->Add(" [true]");
1135 } else if (known_successor_index() == 1) {
1136 stream->Add(" [false]");
1137 }
1117 } 1138 }
1118 1139
1119 1140
1120 const char* HUnaryMathOperation::OpName() const { 1141 const char* HUnaryMathOperation::OpName() const {
1121 switch (op()) { 1142 switch (op()) {
1122 case kMathFloor: return "floor"; 1143 case kMathFloor: return "floor";
1123 case kMathRound: return "round"; 1144 case kMathRound: return "round";
1124 case kMathAbs: return "abs"; 1145 case kMathAbs: return "abs";
1125 case kMathLog: return "log"; 1146 case kMathLog: return "log";
1126 case kMathExp: return "exp"; 1147 case kMathExp: return "exp";
1127 case kMathSqrt: return "sqrt"; 1148 case kMathSqrt: return "sqrt";
1128 case kMathPowHalf: return "pow-half"; 1149 case kMathPowHalf: return "pow-half";
1150 case kMathClz32: return "clz32";
1129 default: 1151 default:
1130 UNREACHABLE(); 1152 UNREACHABLE();
1131 return NULL; 1153 return NULL;
1132 } 1154 }
1133 } 1155 }
1134 1156
1135 1157
1136 Range* HUnaryMathOperation::InferRange(Zone* zone) { 1158 Range* HUnaryMathOperation::InferRange(Zone* zone) {
1137 Representation r = representation(); 1159 Representation r = representation();
1160 if (op() == kMathClz32) return new(zone) Range(0, 32);
1138 if (r.IsSmiOrInteger32() && value()->HasRange()) { 1161 if (r.IsSmiOrInteger32() && value()->HasRange()) {
1139 if (op() == kMathAbs) { 1162 if (op() == kMathAbs) {
1140 int upper = value()->range()->upper(); 1163 int upper = value()->range()->upper();
1141 int lower = value()->range()->lower(); 1164 int lower = value()->range()->lower();
1142 bool spans_zero = value()->range()->CanBeZero(); 1165 bool spans_zero = value()->range()->CanBeZero();
1143 // Math.abs(kMinInt) overflows its representation, on which the 1166 // Math.abs(kMinInt) overflows its representation, on which the
1144 // instruction deopts. Hence clamp it to kMaxInt. 1167 // instruction deopts. Hence clamp it to kMaxInt.
1145 int abs_upper = upper == kMinInt ? kMaxInt : abs(upper); 1168 int abs_upper = upper == kMinInt ? kMaxInt : abs(upper);
1146 int abs_lower = lower == kMinInt ? kMaxInt : abs(lower); 1169 int abs_lower = lower == kMinInt ? kMaxInt : abs(lower);
1147 Range* result = 1170 Range* result =
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
1401 void HChange::PrintDataTo(StringStream* stream) { 1424 void HChange::PrintDataTo(StringStream* stream) {
1402 HUnaryOperation::PrintDataTo(stream); 1425 HUnaryOperation::PrintDataTo(stream);
1403 stream->Add(" %s to %s", from().Mnemonic(), to().Mnemonic()); 1426 stream->Add(" %s to %s", from().Mnemonic(), to().Mnemonic());
1404 1427
1405 if (CanTruncateToInt32()) stream->Add(" truncating-int32"); 1428 if (CanTruncateToInt32()) stream->Add(" truncating-int32");
1406 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); 1429 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
1407 if (CheckFlag(kAllowUndefinedAsNaN)) stream->Add(" allow-undefined-as-nan"); 1430 if (CheckFlag(kAllowUndefinedAsNaN)) stream->Add(" allow-undefined-as-nan");
1408 } 1431 }
1409 1432
1410 1433
1411 static HValue* SimplifiedDividendForMathFloorOfDiv(HValue* dividend) {
1412 // A value with an integer representation does not need to be transformed.
1413 if (dividend->representation().IsInteger32()) {
1414 return dividend;
1415 }
1416 // A change from an integer32 can be replaced by the integer32 value.
1417 if (dividend->IsChange() &&
1418 HChange::cast(dividend)->from().IsInteger32()) {
1419 return HChange::cast(dividend)->value();
1420 }
1421 return NULL;
1422 }
1423
1424
1425 HValue* HUnaryMathOperation::Canonicalize() { 1434 HValue* HUnaryMathOperation::Canonicalize() {
1426 if (op() == kMathRound || op() == kMathFloor) { 1435 if (op() == kMathRound || op() == kMathFloor) {
1427 HValue* val = value(); 1436 HValue* val = value();
1428 if (val->IsChange()) val = HChange::cast(val)->value(); 1437 if (val->IsChange()) val = HChange::cast(val)->value();
1429
1430 // If the input is smi or integer32 then we replace the instruction with its
1431 // input.
1432 if (val->representation().IsSmiOrInteger32()) { 1438 if (val->representation().IsSmiOrInteger32()) {
1433 if (!val->representation().Equals(representation())) { 1439 if (val->representation().Equals(representation())) return val;
1434 HChange* result = new(block()->zone()) HChange( 1440 return Prepend(new(block()->zone()) HChange(
1435 val, representation(), false, false); 1441 val, representation(), false, false));
1436 result->InsertBefore(this);
1437 return result;
1438 }
1439 return val;
1440 } 1442 }
1441 } 1443 }
1444 if (op() == kMathFloor && value()->IsDiv() && value()->UseCount() == 1) {
1445 HDiv* hdiv = HDiv::cast(value());
1442 1446
1443 if (op() == kMathFloor) { 1447 HValue* left = hdiv->left();
1444 HValue* val = value(); 1448 if (left->representation().IsInteger32()) {
1445 if (val->IsChange()) val = HChange::cast(val)->value(); 1449 // A value with an integer representation does not need to be transformed.
1446 if (val->IsDiv() && (val->UseCount() == 1)) { 1450 } else if (left->IsChange() && HChange::cast(left)->from().IsInteger32()) {
1447 HDiv* hdiv = HDiv::cast(val); 1451 // A change from an integer32 can be replaced by the integer32 value.
1448 HValue* left = hdiv->left(); 1452 left = HChange::cast(left)->value();
1449 HValue* right = hdiv->right(); 1453 } else if (hdiv->observed_input_representation(1).IsSmiOrInteger32()) {
1450 // Try to simplify left and right values of the division. 1454 left = Prepend(new(block()->zone()) HChange(
1451 HValue* new_left = SimplifiedDividendForMathFloorOfDiv(left); 1455 left, Representation::Integer32(), false, false));
1452 if (new_left == NULL && 1456 } else {
1453 hdiv->observed_input_representation(1).IsSmiOrInteger32()) { 1457 return this;
1454 new_left = new(block()->zone()) HChange( 1458 }
1455 left, Representation::Integer32(), false, false);
1456 HChange::cast(new_left)->InsertBefore(this);
1457 }
1458 HValue* new_right =
1459 LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(right);
1460 if (new_right == NULL &&
1461 #if V8_TARGET_ARCH_ARM
1462 CpuFeatures::IsSupported(SUDIV) &&
1463 #endif
1464 hdiv->observed_input_representation(2).IsSmiOrInteger32()) {
1465 new_right = new(block()->zone()) HChange(
1466 right, Representation::Integer32(), false, false);
1467 HChange::cast(new_right)->InsertBefore(this);
1468 }
1469 1459
1470 // Return if left or right are not optimizable. 1460 HValue* right = hdiv->right();
1471 if ((new_left == NULL) || (new_right == NULL)) return this; 1461 if (right->IsInteger32Constant()) {
1462 right = Prepend(HConstant::cast(right)->CopyToRepresentation(
1463 Representation::Integer32(), right->block()->zone()));
1464 } else if (right->representation().IsInteger32()) {
1465 // A value with an integer representation does not need to be transformed.
1466 } else if (right->IsChange() &&
1467 HChange::cast(right)->from().IsInteger32()) {
1468 // A change from an integer32 can be replaced by the integer32 value.
1469 right = HChange::cast(right)->value();
1470 } else if (hdiv->observed_input_representation(2).IsSmiOrInteger32()) {
1471 right = Prepend(new(block()->zone()) HChange(
1472 right, Representation::Integer32(), false, false));
1473 } else {
1474 return this;
1475 }
1472 1476
1473 // Insert the new values in the graph. 1477 return Prepend(HMathFloorOfDiv::New(
1474 if (new_left->IsInstruction() && 1478 block()->zone(), context(), left, right));
1475 !HInstruction::cast(new_left)->IsLinked()) {
1476 HInstruction::cast(new_left)->InsertBefore(this);
1477 }
1478 if (new_right->IsInstruction() &&
1479 !HInstruction::cast(new_right)->IsLinked()) {
1480 HInstruction::cast(new_right)->InsertBefore(this);
1481 }
1482 HMathFloorOfDiv* instr =
1483 HMathFloorOfDiv::New(block()->zone(), context(), new_left, new_right);
1484 // Replace this HMathFloor instruction by the new HMathFloorOfDiv.
1485 instr->InsertBefore(this);
1486 ReplaceAllUsesWith(instr);
1487 Kill();
1488 // We know the division had no other uses than this HMathFloor. Delete it.
1489 // Dead code elimination will deal with |left| and |right| if
1490 // appropriate.
1491 hdiv->DeleteAndReplaceWith(NULL);
1492
1493 // Return NULL to remove this instruction from the graph.
1494 return NULL;
1495 }
1496 } 1479 }
1497 return this; 1480 return this;
1498 } 1481 }
1499 1482
1500 1483
1501 HValue* HCheckInstanceType::Canonicalize() { 1484 HValue* HCheckInstanceType::Canonicalize() {
1502 if (check_ == IS_STRING && value()->type().IsString()) { 1485 if (check_ == IS_STRING && value()->type().IsString()) {
1503 return value(); 1486 return value();
1504 } 1487 }
1505 1488
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1539 case IS_INTERNALIZED_STRING: 1522 case IS_INTERNALIZED_STRING:
1540 *mask = kIsNotStringMask | kIsNotInternalizedMask; 1523 *mask = kIsNotStringMask | kIsNotInternalizedMask;
1541 *tag = kInternalizedTag; 1524 *tag = kInternalizedTag;
1542 return; 1525 return;
1543 default: 1526 default:
1544 UNREACHABLE(); 1527 UNREACHABLE();
1545 } 1528 }
1546 } 1529 }
1547 1530
1548 1531
1549 void HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect, 1532 bool HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect,
1550 HValue* dominator) { 1533 HValue* dominator) {
1551 ASSERT(side_effect == kChangesMaps); 1534 ASSERT(side_effect == kMaps);
1552 // TODO(mstarzinger): For now we specialize on HStoreNamedField, but once 1535 // TODO(mstarzinger): For now we specialize on HStoreNamedField, but once
1553 // type information is rich enough we should generalize this to any HType 1536 // type information is rich enough we should generalize this to any HType
1554 // for which the map is known. 1537 // for which the map is known.
1555 if (HasNoUses() && dominator->IsStoreNamedField()) { 1538 if (HasNoUses() && dominator->IsStoreNamedField()) {
1556 HStoreNamedField* store = HStoreNamedField::cast(dominator); 1539 HStoreNamedField* store = HStoreNamedField::cast(dominator);
1557 if (!store->has_transition() || store->object() != value()) return; 1540 if (!store->has_transition() || store->object() != value()) return false;
1558 HConstant* transition = HConstant::cast(store->transition()); 1541 HConstant* transition = HConstant::cast(store->transition());
1559 if (map_set_.Contains(transition->GetUnique())) { 1542 if (map_set_.Contains(transition->GetUnique())) {
1560 DeleteAndReplaceWith(NULL); 1543 DeleteAndReplaceWith(NULL);
1561 return; 1544 return true;
1562 } 1545 }
1563 } 1546 }
1547 return false;
1564 } 1548 }
1565 1549
1566 1550
1567 void HCheckMaps::PrintDataTo(StringStream* stream) { 1551 void HCheckMaps::PrintDataTo(StringStream* stream) {
1568 value()->PrintNameTo(stream); 1552 value()->PrintNameTo(stream);
1569 stream->Add(" [%p", *map_set_.at(0).handle()); 1553 stream->Add(" [%p", *map_set_.at(0).handle());
1570 for (int i = 1; i < map_set_.size(); ++i) { 1554 for (int i = 1; i < map_set_.size(); ++i) {
1571 stream->Add(",%p", *map_set_.at(i).handle()); 1555 stream->Add(",%p", *map_set_.at(i).handle());
1572 } 1556 }
1573 stream->Add("]%s", CanOmitMapChecks() ? "(omitted)" : ""); 1557 stream->Add("]%s", CanOmitMapChecks() ? "(omitted)" : "");
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1648 1632
1649 1633
1650 Range* HChange::InferRange(Zone* zone) { 1634 Range* HChange::InferRange(Zone* zone) {
1651 Range* input_range = value()->range(); 1635 Range* input_range = value()->range();
1652 if (from().IsInteger32() && !value()->CheckFlag(HInstruction::kUint32) && 1636 if (from().IsInteger32() && !value()->CheckFlag(HInstruction::kUint32) &&
1653 (to().IsSmi() || 1637 (to().IsSmi() ||
1654 (to().IsTagged() && 1638 (to().IsTagged() &&
1655 input_range != NULL && 1639 input_range != NULL &&
1656 input_range->IsInSmiRange()))) { 1640 input_range->IsInSmiRange()))) {
1657 set_type(HType::Smi()); 1641 set_type(HType::Smi());
1658 ClearGVNFlag(kChangesNewSpacePromotion); 1642 ClearChangesFlag(kNewSpacePromotion);
1659 } 1643 }
1660 Range* result = (input_range != NULL) 1644 Range* result = (input_range != NULL)
1661 ? input_range->Copy(zone) 1645 ? input_range->Copy(zone)
1662 : HValue::InferRange(zone); 1646 : HValue::InferRange(zone);
1663 result->set_can_be_minus_zero(!to().IsSmiOrInteger32() || 1647 result->set_can_be_minus_zero(!to().IsSmiOrInteger32() ||
1664 !(CheckFlag(kAllUsesTruncatingToInt32) || 1648 !(CheckFlag(kAllUsesTruncatingToInt32) ||
1665 CheckFlag(kAllUsesTruncatingToSmi))); 1649 CheckFlag(kAllUsesTruncatingToSmi)));
1666 if (to().IsSmi()) result->ClampToSmi(); 1650 if (to().IsSmi()) result->ClampToSmi();
1667 return result; 1651 return result;
1668 } 1652 }
1669 1653
1670 1654
1671 Range* HConstant::InferRange(Zone* zone) { 1655 Range* HConstant::InferRange(Zone* zone) {
1672 if (has_int32_value_) { 1656 if (has_int32_value_) {
1673 Range* result = new(zone) Range(int32_value_, int32_value_); 1657 Range* result = new(zone) Range(int32_value_, int32_value_);
1674 result->set_can_be_minus_zero(false); 1658 result->set_can_be_minus_zero(false);
1675 return result; 1659 return result;
1676 } 1660 }
1677 return HValue::InferRange(zone); 1661 return HValue::InferRange(zone);
1678 } 1662 }
1679 1663
1680 1664
1681 int HPhi::position() const { 1665 HSourcePosition HPhi::position() const {
1682 return block()->first()->position(); 1666 return block()->first()->position();
1683 } 1667 }
1684 1668
1685 1669
1686 Range* HPhi::InferRange(Zone* zone) { 1670 Range* HPhi::InferRange(Zone* zone) {
1687 Representation r = representation(); 1671 Representation r = representation();
1688 if (r.IsSmiOrInteger32()) { 1672 if (r.IsSmiOrInteger32()) {
1689 if (block()->IsLoopHeader()) { 1673 if (block()->IsLoopHeader()) {
1690 Range* range = r.IsSmi() 1674 Range* range = r.IsSmi()
1691 ? new(zone) Range(Smi::kMinValue, Smi::kMaxValue) 1675 ? new(zone) Range(Smi::kMinValue, Smi::kMaxValue)
(...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after
2524 Heap* heap = Handle<HeapObject>::cast(handle)->GetHeap(); 2508 Heap* heap = Handle<HeapObject>::cast(handle)->GetHeap();
2525 is_not_in_new_space_ = !heap->InNewSpace(*handle); 2509 is_not_in_new_space_ = !heap->InNewSpace(*handle);
2526 } 2510 }
2527 if (handle->IsNumber()) { 2511 if (handle->IsNumber()) {
2528 double n = handle->Number(); 2512 double n = handle->Number();
2529 has_int32_value_ = IsInteger32(n); 2513 has_int32_value_ = IsInteger32(n);
2530 int32_value_ = DoubleToInt32(n); 2514 int32_value_ = DoubleToInt32(n);
2531 has_smi_value_ = has_int32_value_ && Smi::IsValid(int32_value_); 2515 has_smi_value_ = has_int32_value_ && Smi::IsValid(int32_value_);
2532 double_value_ = n; 2516 double_value_ = n;
2533 has_double_value_ = true; 2517 has_double_value_ = true;
2518 // TODO(titzer): if this heap number is new space, tenure a new one.
2534 } else { 2519 } else {
2535 is_internalized_string_ = handle->IsInternalizedString(); 2520 is_internalized_string_ = handle->IsInternalizedString();
2536 } 2521 }
2537 2522
2538 is_cell_ = !handle.is_null() && 2523 is_cell_ = !handle.is_null() &&
2539 (handle->IsCell() || handle->IsPropertyCell()); 2524 (handle->IsCell() || handle->IsPropertyCell());
2540 Initialize(r); 2525 Initialize(r);
2541 } 2526 }
2542 2527
2543 2528
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2640 } 2625 }
2641 } 2626 }
2642 r = Representation::Tagged(); 2627 r = Representation::Tagged();
2643 } 2628 }
2644 } 2629 }
2645 set_representation(r); 2630 set_representation(r);
2646 SetFlag(kUseGVN); 2631 SetFlag(kUseGVN);
2647 } 2632 }
2648 2633
2649 2634
2635 bool HConstant::ImmortalImmovable() const {
2636 if (has_int32_value_) {
2637 return false;
2638 }
2639 if (has_double_value_) {
2640 if (IsSpecialDouble()) {
2641 return true;
2642 }
2643 return false;
2644 }
2645 if (has_external_reference_value_) {
2646 return false;
2647 }
2648
2649 ASSERT(!object_.handle().is_null());
2650 Heap* heap = isolate()->heap();
2651 ASSERT(!object_.IsKnownGlobal(heap->minus_zero_value()));
2652 ASSERT(!object_.IsKnownGlobal(heap->nan_value()));
2653 return
2654 #define IMMORTAL_IMMOVABLE_ROOT(name) \
2655 object_.IsKnownGlobal(heap->name()) ||
2656 IMMORTAL_IMMOVABLE_ROOT_LIST(IMMORTAL_IMMOVABLE_ROOT)
2657 #undef IMMORTAL_IMMOVABLE_ROOT
2658 #define INTERNALIZED_STRING(name, value) \
2659 object_.IsKnownGlobal(heap->name()) ||
2660 INTERNALIZED_STRING_LIST(INTERNALIZED_STRING)
2661 #undef INTERNALIZED_STRING
2662 #define STRING_TYPE(NAME, size, name, Name) \
2663 object_.IsKnownGlobal(heap->name##_map()) ||
2664 STRING_TYPE_LIST(STRING_TYPE)
2665 #undef STRING_TYPE
2666 false;
2667 }
2668
2669
2650 bool HConstant::EmitAtUses() { 2670 bool HConstant::EmitAtUses() {
2651 ASSERT(IsLinked()); 2671 ASSERT(IsLinked());
2652 if (block()->graph()->has_osr() && 2672 if (block()->graph()->has_osr() &&
2653 block()->graph()->IsStandardConstant(this)) { 2673 block()->graph()->IsStandardConstant(this)) {
2654 // TODO(titzer): this seems like a hack that should be fixed by custom OSR. 2674 // TODO(titzer): this seems like a hack that should be fixed by custom OSR.
2655 return true; 2675 return true;
2656 } 2676 }
2657 if (UseCount() == 0) return true; 2677 if (UseCount() == 0) return true;
2658 if (IsCell()) return false; 2678 if (IsCell()) return false;
2659 if (representation().IsDouble()) return false; 2679 if (representation().IsDouble()) return false;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2722 if (has_int32_value_) { 2742 if (has_int32_value_) {
2723 stream->Add("%d ", int32_value_); 2743 stream->Add("%d ", int32_value_);
2724 } else if (has_double_value_) { 2744 } else if (has_double_value_) {
2725 stream->Add("%f ", FmtElm(double_value_)); 2745 stream->Add("%f ", FmtElm(double_value_));
2726 } else if (has_external_reference_value_) { 2746 } else if (has_external_reference_value_) {
2727 stream->Add("%p ", reinterpret_cast<void*>( 2747 stream->Add("%p ", reinterpret_cast<void*>(
2728 external_reference_value_.address())); 2748 external_reference_value_.address()));
2729 } else { 2749 } else {
2730 handle(Isolate::Current())->ShortPrint(stream); 2750 handle(Isolate::Current())->ShortPrint(stream);
2731 } 2751 }
2752 if (!is_not_in_new_space_) {
2753 stream->Add("[new space] ");
2754 }
2732 } 2755 }
2733 2756
2734 2757
2735 void HBinaryOperation::PrintDataTo(StringStream* stream) { 2758 void HBinaryOperation::PrintDataTo(StringStream* stream) {
2736 left()->PrintNameTo(stream); 2759 left()->PrintNameTo(stream);
2737 stream->Add(" "); 2760 stream->Add(" ");
2738 right()->PrintNameTo(stream); 2761 right()->PrintNameTo(stream);
2739 if (CheckFlag(kCanOverflow)) stream->Add(" !"); 2762 if (CheckFlag(kCanOverflow)) stream->Add(" !");
2740 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); 2763 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
2741 } 2764 }
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
2938 } 2961 }
2939 if (access().IsStringLength()) { 2962 if (access().IsStringLength()) {
2940 return new(zone) Range(0, String::kMaxLength); 2963 return new(zone) Range(0, String::kMaxLength);
2941 } 2964 }
2942 return HValue::InferRange(zone); 2965 return HValue::InferRange(zone);
2943 } 2966 }
2944 2967
2945 2968
2946 Range* HLoadKeyed::InferRange(Zone* zone) { 2969 Range* HLoadKeyed::InferRange(Zone* zone) {
2947 switch (elements_kind()) { 2970 switch (elements_kind()) {
2948 case EXTERNAL_BYTE_ELEMENTS: 2971 case EXTERNAL_INT8_ELEMENTS:
2949 return new(zone) Range(kMinInt8, kMaxInt8); 2972 return new(zone) Range(kMinInt8, kMaxInt8);
2950 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 2973 case EXTERNAL_UINT8_ELEMENTS:
2951 case EXTERNAL_PIXEL_ELEMENTS: 2974 case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
2952 return new(zone) Range(kMinUInt8, kMaxUInt8); 2975 return new(zone) Range(kMinUInt8, kMaxUInt8);
2953 case EXTERNAL_SHORT_ELEMENTS: 2976 case EXTERNAL_INT16_ELEMENTS:
2954 return new(zone) Range(kMinInt16, kMaxInt16); 2977 return new(zone) Range(kMinInt16, kMaxInt16);
2955 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 2978 case EXTERNAL_UINT16_ELEMENTS:
2956 return new(zone) Range(kMinUInt16, kMaxUInt16); 2979 return new(zone) Range(kMinUInt16, kMaxUInt16);
2957 default: 2980 default:
2958 return HValue::InferRange(zone); 2981 return HValue::InferRange(zone);
2959 } 2982 }
2960 } 2983 }
2961 2984
2962 2985
2963 void HCompareGeneric::PrintDataTo(StringStream* stream) { 2986 void HCompareGeneric::PrintDataTo(StringStream* stream) {
2964 stream->Add(Token::Name(token())); 2987 stream->Add(Token::Name(token()));
2965 stream->Add(" "); 2988 stream->Add(" ");
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
3075 3098
3076 3099
3077 void HParameter::PrintDataTo(StringStream* stream) { 3100 void HParameter::PrintDataTo(StringStream* stream) {
3078 stream->Add("%u", index()); 3101 stream->Add("%u", index());
3079 } 3102 }
3080 3103
3081 3104
3082 void HLoadNamedField::PrintDataTo(StringStream* stream) { 3105 void HLoadNamedField::PrintDataTo(StringStream* stream) {
3083 object()->PrintNameTo(stream); 3106 object()->PrintNameTo(stream);
3084 access_.PrintTo(stream); 3107 access_.PrintTo(stream);
3108
3109 if (HasDependency()) {
3110 stream->Add(" ");
3111 dependency()->PrintNameTo(stream);
3112 }
3085 } 3113 }
3086 3114
3087 3115
3088 HCheckMaps* HCheckMaps::New(Zone* zone, 3116 HCheckMaps* HCheckMaps::New(Zone* zone,
3089 HValue* context, 3117 HValue* context,
3090 HValue* value, 3118 HValue* value,
3091 Handle<Map> map, 3119 Handle<Map> map,
3092 CompilationInfo* info, 3120 CompilationInfo* info,
3093 HValue* typecheck) { 3121 HValue* typecheck) {
3094 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); 3122 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
3225 names_cache->map()); 3253 names_cache->map());
3226 HInstruction* index = HLoadKeyed::New( 3254 HInstruction* index = HLoadKeyed::New(
3227 block()->graph()->zone(), 3255 block()->graph()->zone(),
3228 block()->graph()->GetInvalidContext(), 3256 block()->graph()->GetInvalidContext(),
3229 index_cache, 3257 index_cache,
3230 key_load->key(), 3258 key_load->key(),
3231 key_load->key(), 3259 key_load->key(),
3232 key_load->elements_kind()); 3260 key_load->elements_kind());
3233 map_check->InsertBefore(this); 3261 map_check->InsertBefore(this);
3234 index->InsertBefore(this); 3262 index->InsertBefore(this);
3235 HLoadFieldByIndex* load = new(block()->zone()) HLoadFieldByIndex( 3263 return Prepend(new(block()->zone()) HLoadFieldByIndex(
3236 object(), index); 3264 object(), index));
3237 load->InsertBefore(this);
3238 return load;
3239 } 3265 }
3240 } 3266 }
3241 } 3267 }
3242 3268
3243 return this; 3269 return this;
3244 } 3270 }
3245 3271
3246 3272
3247 void HStoreNamedGeneric::PrintDataTo(StringStream* stream) { 3273 void HStoreNamedGeneric::PrintDataTo(StringStream* stream) {
3248 object()->PrintNameTo(stream); 3274 object()->PrintNameTo(stream);
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
3392 // If any of the actual input representation is more general than what we 3418 // If any of the actual input representation is more general than what we
3393 // have so far but not Tagged, use that representation instead. 3419 // have so far but not Tagged, use that representation instead.
3394 Representation input_rep = value()->representation(); 3420 Representation input_rep = value()->representation();
3395 if (!input_rep.IsTagged()) { 3421 if (!input_rep.IsTagged()) {
3396 rep = rep.generalize(input_rep); 3422 rep = rep.generalize(input_rep);
3397 } 3423 }
3398 return rep; 3424 return rep;
3399 } 3425 }
3400 3426
3401 3427
3402 void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, 3428 bool HAllocate::HandleSideEffectDominator(GVNFlag side_effect,
3403 HValue* dominator) { 3429 HValue* dominator) {
3404 ASSERT(side_effect == kChangesNewSpacePromotion); 3430 ASSERT(side_effect == kNewSpacePromotion);
3405 Zone* zone = block()->zone(); 3431 Zone* zone = block()->zone();
3406 if (!FLAG_use_allocation_folding) return; 3432 if (!FLAG_use_allocation_folding) return false;
3407 3433
3408 // Try to fold allocations together with their dominating allocations. 3434 // Try to fold allocations together with their dominating allocations.
3409 if (!dominator->IsAllocate()) { 3435 if (!dominator->IsAllocate()) {
3410 if (FLAG_trace_allocation_folding) { 3436 if (FLAG_trace_allocation_folding) {
3411 PrintF("#%d (%s) cannot fold into #%d (%s)\n", 3437 PrintF("#%d (%s) cannot fold into #%d (%s)\n",
3412 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); 3438 id(), Mnemonic(), dominator->id(), dominator->Mnemonic());
3413 } 3439 }
3414 return; 3440 return false;
3441 }
3442
3443 // Check whether we are folding within the same block for local folding.
3444 if (FLAG_use_local_allocation_folding && dominator->block() != block()) {
3445 if (FLAG_trace_allocation_folding) {
3446 PrintF("#%d (%s) cannot fold into #%d (%s), crosses basic blocks\n",
3447 id(), Mnemonic(), dominator->id(), dominator->Mnemonic());
3448 }
3449 return false;
3415 } 3450 }
3416 3451
3417 HAllocate* dominator_allocate = HAllocate::cast(dominator); 3452 HAllocate* dominator_allocate = HAllocate::cast(dominator);
3418 HValue* dominator_size = dominator_allocate->size(); 3453 HValue* dominator_size = dominator_allocate->size();
3419 HValue* current_size = size(); 3454 HValue* current_size = size();
3420 3455
3421 // TODO(hpayer): Add support for non-constant allocation in dominator. 3456 // TODO(hpayer): Add support for non-constant allocation in dominator.
3422 if (!current_size->IsInteger32Constant() || 3457 if (!current_size->IsInteger32Constant() ||
3423 !dominator_size->IsInteger32Constant()) { 3458 !dominator_size->IsInteger32Constant()) {
3424 if (FLAG_trace_allocation_folding) { 3459 if (FLAG_trace_allocation_folding) {
3425 PrintF("#%d (%s) cannot fold into #%d (%s), dynamic allocation size\n", 3460 PrintF("#%d (%s) cannot fold into #%d (%s), dynamic allocation size\n",
3426 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); 3461 id(), Mnemonic(), dominator->id(), dominator->Mnemonic());
3427 } 3462 }
3428 return; 3463 return false;
3429 } 3464 }
3430 3465
3431 dominator_allocate = GetFoldableDominator(dominator_allocate); 3466 dominator_allocate = GetFoldableDominator(dominator_allocate);
3432 if (dominator_allocate == NULL) { 3467 if (dominator_allocate == NULL) {
3433 return; 3468 return false;
3434 } 3469 }
3435 3470
3436 ASSERT((IsNewSpaceAllocation() && 3471 ASSERT((IsNewSpaceAllocation() &&
3437 dominator_allocate->IsNewSpaceAllocation()) || 3472 dominator_allocate->IsNewSpaceAllocation()) ||
3438 (IsOldDataSpaceAllocation() && 3473 (IsOldDataSpaceAllocation() &&
3439 dominator_allocate->IsOldDataSpaceAllocation()) || 3474 dominator_allocate->IsOldDataSpaceAllocation()) ||
3440 (IsOldPointerSpaceAllocation() && 3475 (IsOldPointerSpaceAllocation() &&
3441 dominator_allocate->IsOldPointerSpaceAllocation())); 3476 dominator_allocate->IsOldPointerSpaceAllocation()));
3442 3477
3443 // First update the size of the dominator allocate instruction. 3478 // First update the size of the dominator allocate instruction.
3444 dominator_size = dominator_allocate->size(); 3479 dominator_size = dominator_allocate->size();
3445 int32_t original_object_size = 3480 int32_t original_object_size =
3446 HConstant::cast(dominator_size)->GetInteger32Constant(); 3481 HConstant::cast(dominator_size)->GetInteger32Constant();
3447 int32_t dominator_size_constant = original_object_size; 3482 int32_t dominator_size_constant = original_object_size;
3448 int32_t current_size_constant = 3483 int32_t current_size_constant =
3449 HConstant::cast(current_size)->GetInteger32Constant(); 3484 HConstant::cast(current_size)->GetInteger32Constant();
3450 int32_t new_dominator_size = dominator_size_constant + current_size_constant; 3485 int32_t new_dominator_size = dominator_size_constant + current_size_constant;
3451 3486
3452 if (MustAllocateDoubleAligned()) { 3487 if (MustAllocateDoubleAligned()) {
3453 if (!dominator_allocate->MustAllocateDoubleAligned()) { 3488 if (!dominator_allocate->MustAllocateDoubleAligned()) {
3454 dominator_allocate->MakeDoubleAligned(); 3489 dominator_allocate->MakeDoubleAligned();
3455 } 3490 }
3456 if ((dominator_size_constant & kDoubleAlignmentMask) != 0) { 3491 if ((dominator_size_constant & kDoubleAlignmentMask) != 0) {
3457 dominator_size_constant += kDoubleSize / 2; 3492 dominator_size_constant += kDoubleSize / 2;
3458 new_dominator_size += kDoubleSize / 2; 3493 new_dominator_size += kDoubleSize / 2;
3459 } 3494 }
3460 } 3495 }
3461 3496
3462 if (new_dominator_size > isolate()->heap()->MaxRegularSpaceAllocationSize()) { 3497 // Since we clear the first word after folded memory, we cannot use the
3498 // whole Page::kMaxRegularHeapObjectSize memory.
3499 if (new_dominator_size > Page::kMaxRegularHeapObjectSize - kPointerSize) {
3463 if (FLAG_trace_allocation_folding) { 3500 if (FLAG_trace_allocation_folding) {
3464 PrintF("#%d (%s) cannot fold into #%d (%s) due to size: %d\n", 3501 PrintF("#%d (%s) cannot fold into #%d (%s) due to size: %d\n",
3465 id(), Mnemonic(), dominator_allocate->id(), 3502 id(), Mnemonic(), dominator_allocate->id(),
3466 dominator_allocate->Mnemonic(), new_dominator_size); 3503 dominator_allocate->Mnemonic(), new_dominator_size);
3467 } 3504 }
3468 return; 3505 return false;
3469 } 3506 }
3470 3507
3471 HInstruction* new_dominator_size_constant = HConstant::CreateAndInsertBefore( 3508 HInstruction* new_dominator_size_constant = HConstant::CreateAndInsertBefore(
3472 zone, 3509 zone,
3473 context(), 3510 context(),
3474 new_dominator_size, 3511 new_dominator_size,
3475 Representation::None(), 3512 Representation::None(),
3476 dominator_allocate); 3513 dominator_allocate);
3477 dominator_allocate->UpdateSize(new_dominator_size_constant); 3514 dominator_allocate->UpdateSize(new_dominator_size_constant);
3478 3515
(...skipping 27 matching lines...) Expand all
3506 dominator_allocate, 3543 dominator_allocate,
3507 inner_offset, 3544 inner_offset,
3508 type()); 3545 type());
3509 dominated_allocate_instr->InsertBefore(this); 3546 dominated_allocate_instr->InsertBefore(this);
3510 DeleteAndReplaceWith(dominated_allocate_instr); 3547 DeleteAndReplaceWith(dominated_allocate_instr);
3511 if (FLAG_trace_allocation_folding) { 3548 if (FLAG_trace_allocation_folding) {
3512 PrintF("#%d (%s) folded into #%d (%s)\n", 3549 PrintF("#%d (%s) folded into #%d (%s)\n",
3513 id(), Mnemonic(), dominator_allocate->id(), 3550 id(), Mnemonic(), dominator_allocate->id(),
3514 dominator_allocate->Mnemonic()); 3551 dominator_allocate->Mnemonic());
3515 } 3552 }
3553 return true;
3516 } 3554 }
3517 3555
3518 3556
3519 HAllocate* HAllocate::GetFoldableDominator(HAllocate* dominator) { 3557 HAllocate* HAllocate::GetFoldableDominator(HAllocate* dominator) {
3520 if (!IsFoldable(dominator)) { 3558 if (!IsFoldable(dominator)) {
3521 // We cannot hoist old space allocations over new space allocations. 3559 // We cannot hoist old space allocations over new space allocations.
3522 if (IsNewSpaceAllocation() || dominator->IsNewSpaceAllocation()) { 3560 if (IsNewSpaceAllocation() || dominator->IsNewSpaceAllocation()) {
3523 if (FLAG_trace_allocation_folding) { 3561 if (FLAG_trace_allocation_folding) {
3524 PrintF("#%d (%s) cannot fold into #%d (%s), new space hoisting\n", 3562 PrintF("#%d (%s) cannot fold into #%d (%s), new space hoisting\n",
3525 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); 3563 id(), Mnemonic(), dominator->id(), dominator->Mnemonic());
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
3615 store_map->SetFlag(HValue::kHasNoObservableSideEffects); 3653 store_map->SetFlag(HValue::kHasNoObservableSideEffects);
3616 store_map->InsertAfter(filler_map); 3654 store_map->InsertAfter(filler_map);
3617 3655
3618 // We must explicitly force Smi representation here because on x64 we 3656 // We must explicitly force Smi representation here because on x64 we
3619 // would otherwise automatically choose int32, but the actual store 3657 // would otherwise automatically choose int32, but the actual store
3620 // requires a Smi-tagged value. 3658 // requires a Smi-tagged value.
3621 HConstant* filler_size = HConstant::CreateAndInsertAfter( 3659 HConstant* filler_size = HConstant::CreateAndInsertAfter(
3622 zone, context(), free_space_size, Representation::Smi(), store_map); 3660 zone, context(), free_space_size, Representation::Smi(), store_map);
3623 // Must force Smi representation for x64 (see comment above). 3661 // Must force Smi representation for x64 (see comment above).
3624 HObjectAccess access = 3662 HObjectAccess access =
3625 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset, 3663 HObjectAccess::ForMapAndOffset(isolate()->factory()->free_space_map(),
3626 Representation::Smi()); 3664 FreeSpace::kSizeOffset,
3665 Representation::Smi());
3627 HStoreNamedField* store_size = HStoreNamedField::New(zone, context(), 3666 HStoreNamedField* store_size = HStoreNamedField::New(zone, context(),
3628 free_space_instr, access, filler_size); 3667 free_space_instr, access, filler_size);
3629 store_size->SetFlag(HValue::kHasNoObservableSideEffects); 3668 store_size->SetFlag(HValue::kHasNoObservableSideEffects);
3630 store_size->InsertAfter(filler_size); 3669 store_size->InsertAfter(filler_size);
3631 filler_free_space_size_ = store_size; 3670 filler_free_space_size_ = store_size;
3632 } 3671 }
3633 3672
3634 3673
3635 void HAllocate::ClearNextMapWord(int offset) { 3674 void HAllocate::ClearNextMapWord(int offset) {
3636 if (MustClearNextMapWord()) { 3675 if (MustClearNextMapWord()) {
3637 Zone* zone = block()->zone(); 3676 Zone* zone = block()->zone();
3638 HObjectAccess access = HObjectAccess::ForJSObjectOffset(offset); 3677 HObjectAccess access =
3678 HObjectAccess::ForObservableJSObjectOffset(offset);
3639 HStoreNamedField* clear_next_map = 3679 HStoreNamedField* clear_next_map =
3640 HStoreNamedField::New(zone, context(), this, access, 3680 HStoreNamedField::New(zone, context(), this, access,
3641 block()->graph()->GetConstant0()); 3681 block()->graph()->GetConstant0());
3642 clear_next_map->ClearAllSideEffects(); 3682 clear_next_map->ClearAllSideEffects();
3643 clear_next_map->InsertAfter(this); 3683 clear_next_map->InsertAfter(this);
3644 } 3684 }
3645 } 3685 }
3646 3686
3647 3687
3648 void HAllocate::PrintDataTo(StringStream* stream) { 3688 void HAllocate::PrintDataTo(StringStream* stream) {
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
3880 return H_CONSTANT_DOUBLE((d > 0.0) ? d : 0.0); 3920 return H_CONSTANT_DOUBLE((d > 0.0) ? d : 0.0);
3881 case kMathLog: 3921 case kMathLog:
3882 case kMathSqrt: 3922 case kMathSqrt:
3883 return H_CONSTANT_DOUBLE((d > 0.0) ? d : OS::nan_value()); 3923 return H_CONSTANT_DOUBLE((d > 0.0) ? d : OS::nan_value());
3884 case kMathPowHalf: 3924 case kMathPowHalf:
3885 case kMathAbs: 3925 case kMathAbs:
3886 return H_CONSTANT_DOUBLE((d > 0.0) ? d : -d); 3926 return H_CONSTANT_DOUBLE((d > 0.0) ? d : -d);
3887 case kMathRound: 3927 case kMathRound:
3888 case kMathFloor: 3928 case kMathFloor:
3889 return H_CONSTANT_DOUBLE(d); 3929 return H_CONSTANT_DOUBLE(d);
3930 case kMathClz32:
3931 return H_CONSTANT_INT(32);
3890 default: 3932 default:
3891 UNREACHABLE(); 3933 UNREACHABLE();
3892 break; 3934 break;
3893 } 3935 }
3894 } 3936 }
3895 switch (op) { 3937 switch (op) {
3896 case kMathExp: 3938 case kMathExp:
3897 return H_CONSTANT_DOUBLE(fast_exp(d)); 3939 return H_CONSTANT_DOUBLE(fast_exp(d));
3898 case kMathLog: 3940 case kMathLog:
3899 return H_CONSTANT_DOUBLE(std::log(d)); 3941 return H_CONSTANT_DOUBLE(std::log(d));
3900 case kMathSqrt: 3942 case kMathSqrt:
3901 return H_CONSTANT_DOUBLE(fast_sqrt(d)); 3943 return H_CONSTANT_DOUBLE(fast_sqrt(d));
3902 case kMathPowHalf: 3944 case kMathPowHalf:
3903 return H_CONSTANT_DOUBLE(power_double_double(d, 0.5)); 3945 return H_CONSTANT_DOUBLE(power_double_double(d, 0.5));
3904 case kMathAbs: 3946 case kMathAbs:
3905 return H_CONSTANT_DOUBLE((d >= 0.0) ? d + 0.0 : -d); 3947 return H_CONSTANT_DOUBLE((d >= 0.0) ? d + 0.0 : -d);
3906 case kMathRound: 3948 case kMathRound:
3907 // -0.5 .. -0.0 round to -0.0. 3949 // -0.5 .. -0.0 round to -0.0.
3908 if ((d >= -0.5 && Double(d).Sign() < 0)) return H_CONSTANT_DOUBLE(-0.0); 3950 if ((d >= -0.5 && Double(d).Sign() < 0)) return H_CONSTANT_DOUBLE(-0.0);
3909 // Doubles are represented as Significant * 2 ^ Exponent. If the 3951 // Doubles are represented as Significant * 2 ^ Exponent. If the
3910 // Exponent is not negative, the double value is already an integer. 3952 // Exponent is not negative, the double value is already an integer.
3911 if (Double(d).Exponent() >= 0) return H_CONSTANT_DOUBLE(d); 3953 if (Double(d).Exponent() >= 0) return H_CONSTANT_DOUBLE(d);
3912 return H_CONSTANT_DOUBLE(std::floor(d + 0.5)); 3954 return H_CONSTANT_DOUBLE(std::floor(d + 0.5));
3913 case kMathFloor: 3955 case kMathFloor:
3914 return H_CONSTANT_DOUBLE(std::floor(d)); 3956 return H_CONSTANT_DOUBLE(std::floor(d));
3957 case kMathClz32: {
3958 uint32_t i = DoubleToUint32(d);
3959 return H_CONSTANT_INT(
3960 (i == 0) ? 32 : CompilerIntrinsics::CountLeadingZeros(i));
3961 }
3915 default: 3962 default:
3916 UNREACHABLE(); 3963 UNREACHABLE();
3917 break; 3964 break;
3918 } 3965 }
3919 } while (false); 3966 } while (false);
3920 return new(zone) HUnaryMathOperation(context, value, op); 3967 return new(zone) HUnaryMathOperation(context, value, op);
3921 } 3968 }
3922 3969
3923 3970
3924 HInstruction* HPower::New(Zone* zone, 3971 HInstruction* HPower::New(Zone* zone,
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
4255 4302
4256 4303
4257 HObjectAccess HObjectAccess::ForFixedArrayHeader(int offset) { 4304 HObjectAccess HObjectAccess::ForFixedArrayHeader(int offset) {
4258 ASSERT(offset >= 0); 4305 ASSERT(offset >= 0);
4259 ASSERT(offset < FixedArray::kHeaderSize); 4306 ASSERT(offset < FixedArray::kHeaderSize);
4260 if (offset == FixedArray::kLengthOffset) return ForFixedArrayLength(); 4307 if (offset == FixedArray::kLengthOffset) return ForFixedArrayLength();
4261 return HObjectAccess(kInobject, offset); 4308 return HObjectAccess(kInobject, offset);
4262 } 4309 }
4263 4310
4264 4311
4265 HObjectAccess HObjectAccess::ForJSObjectOffset(int offset, 4312 HObjectAccess HObjectAccess::ForMapAndOffset(Handle<Map> map, int offset,
4266 Representation representation) { 4313 Representation representation) {
4267 ASSERT(offset >= 0); 4314 ASSERT(offset >= 0);
4268 Portion portion = kInobject; 4315 Portion portion = kInobject;
4269 4316
4270 if (offset == JSObject::kElementsOffset) { 4317 if (offset == JSObject::kElementsOffset) {
4271 portion = kElementsPointer; 4318 portion = kElementsPointer;
4272 } else if (offset == JSObject::kMapOffset) { 4319 } else if (offset == JSObject::kMapOffset) {
4273 portion = kMaps; 4320 portion = kMaps;
4274 } 4321 }
4275 return HObjectAccess(portion, offset, representation); 4322 bool existing_inobject_property = true;
4323 if (!map.is_null()) {
4324 existing_inobject_property = (offset <
4325 map->instance_size() - map->unused_property_fields() * kPointerSize);
4326 }
4327 return HObjectAccess(portion, offset, representation, Handle<String>::null(),
4328 false, existing_inobject_property);
4276 } 4329 }
4277 4330
4278 4331
4279 HObjectAccess HObjectAccess::ForAllocationSiteOffset(int offset) { 4332 HObjectAccess HObjectAccess::ForAllocationSiteOffset(int offset) {
4280 switch (offset) { 4333 switch (offset) {
4281 case AllocationSite::kTransitionInfoOffset: 4334 case AllocationSite::kTransitionInfoOffset:
4282 return HObjectAccess(kInobject, offset, Representation::Tagged()); 4335 return HObjectAccess(kInobject, offset, Representation::Tagged());
4283 case AllocationSite::kNestedSiteOffset: 4336 case AllocationSite::kNestedSiteOffset:
4284 return HObjectAccess(kInobject, offset, Representation::Tagged()); 4337 return HObjectAccess(kInobject, offset, Representation::Tagged());
4285 case AllocationSite::kPretenureDataOffset: 4338 case AllocationSite::kPretenureDataOffset:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4317 } else if (offset == JSObject::kMapOffset) { 4370 } else if (offset == JSObject::kMapOffset) {
4318 portion = kMaps; 4371 portion = kMaps;
4319 } 4372 }
4320 return HObjectAccess(portion, offset); 4373 return HObjectAccess(portion, offset);
4321 } 4374 }
4322 4375
4323 4376
4324 HObjectAccess HObjectAccess::ForBackingStoreOffset(int offset, 4377 HObjectAccess HObjectAccess::ForBackingStoreOffset(int offset,
4325 Representation representation) { 4378 Representation representation) {
4326 ASSERT(offset >= 0); 4379 ASSERT(offset >= 0);
4327 return HObjectAccess(kBackingStore, offset, representation); 4380 return HObjectAccess(kBackingStore, offset, representation,
4381 Handle<String>::null(), false, false);
4328 } 4382 }
4329 4383
4330 4384
4331 HObjectAccess HObjectAccess::ForField(Handle<Map> map, 4385 HObjectAccess HObjectAccess::ForField(Handle<Map> map,
4332 LookupResult *lookup, Handle<String> name) { 4386 LookupResult* lookup,
4333 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*map)); 4387 Handle<String> name) {
4388 ASSERT(lookup->IsField() || lookup->IsTransitionToField());
4334 int index; 4389 int index;
4335 Representation representation; 4390 Representation representation;
4336 if (lookup->IsField()) { 4391 if (lookup->IsField()) {
4337 index = lookup->GetLocalFieldIndexFromMap(*map); 4392 index = lookup->GetLocalFieldIndexFromMap(*map);
4338 representation = lookup->representation(); 4393 representation = lookup->representation();
4339 } else { 4394 } else {
4340 Map* transition = lookup->GetTransitionMapFromMap(*map); 4395 Map* transition = lookup->GetTransitionTarget();
4341 int descriptor = transition->LastAdded(); 4396 int descriptor = transition->LastAdded();
4342 index = transition->instance_descriptors()->GetFieldIndex(descriptor) - 4397 index = transition->instance_descriptors()->GetFieldIndex(descriptor) -
4343 map->inobject_properties(); 4398 map->inobject_properties();
4344 PropertyDetails details = 4399 PropertyDetails details =
4345 transition->instance_descriptors()->GetDetails(descriptor); 4400 transition->instance_descriptors()->GetDetails(descriptor);
4346 representation = details.representation(); 4401 representation = details.representation();
4347 } 4402 }
4348 if (index < 0) { 4403 if (index < 0) {
4349 // Negative property indices are in-object properties, indexed 4404 // Negative property indices are in-object properties, indexed
4350 // from the end of the fixed part of the object. 4405 // from the end of the fixed part of the object.
4351 int offset = (index * kPointerSize) + map->instance_size(); 4406 int offset = (index * kPointerSize) + map->instance_size();
4352 return HObjectAccess(kInobject, offset, representation); 4407 return HObjectAccess(kInobject, offset, representation, name, false, true);
4353 } else { 4408 } else {
4354 // Non-negative property indices are in the properties array. 4409 // Non-negative property indices are in the properties array.
4355 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; 4410 int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
4356 return HObjectAccess(kBackingStore, offset, representation, name); 4411 return HObjectAccess(kBackingStore, offset, representation, name,
4412 false, false);
4357 } 4413 }
4358 } 4414 }
4359 4415
4360 4416
4361 HObjectAccess HObjectAccess::ForCellPayload(Isolate* isolate) { 4417 HObjectAccess HObjectAccess::ForCellPayload(Isolate* isolate) {
4362 return HObjectAccess( 4418 return HObjectAccess(
4363 kInobject, Cell::kValueOffset, Representation::Tagged(), 4419 kInobject, Cell::kValueOffset, Representation::Tagged(),
4364 Handle<String>(isolate->heap()->cell_value_string())); 4420 Handle<String>(isolate->heap()->cell_value_string()));
4365 } 4421 }
4366 4422
4367 4423
4368 void HObjectAccess::SetGVNFlags(HValue *instr, bool is_store) { 4424 void HObjectAccess::SetGVNFlags(HValue *instr, PropertyAccessType access_type) {
4369 // set the appropriate GVN flags for a given load or store instruction 4425 // set the appropriate GVN flags for a given load or store instruction
4370 if (is_store) { 4426 if (access_type == STORE) {
4371 // track dominating allocations in order to eliminate write barriers 4427 // track dominating allocations in order to eliminate write barriers
4372 instr->SetGVNFlag(kDependsOnNewSpacePromotion); 4428 instr->SetDependsOnFlag(::v8::internal::kNewSpacePromotion);
4373 instr->SetFlag(HValue::kTrackSideEffectDominators); 4429 instr->SetFlag(HValue::kTrackSideEffectDominators);
4374 } else { 4430 } else {
4375 // try to GVN loads, but don't hoist above map changes 4431 // try to GVN loads, but don't hoist above map changes
4376 instr->SetFlag(HValue::kUseGVN); 4432 instr->SetFlag(HValue::kUseGVN);
4377 instr->SetGVNFlag(kDependsOnMaps); 4433 instr->SetDependsOnFlag(::v8::internal::kMaps);
4378 } 4434 }
4379 4435
4380 switch (portion()) { 4436 switch (portion()) {
4381 case kArrayLengths: 4437 case kArrayLengths:
4382 instr->SetGVNFlag(is_store 4438 if (access_type == STORE) {
4383 ? kChangesArrayLengths : kDependsOnArrayLengths); 4439 instr->SetChangesFlag(::v8::internal::kArrayLengths);
4440 } else {
4441 instr->SetDependsOnFlag(::v8::internal::kArrayLengths);
4442 }
4384 break; 4443 break;
4385 case kStringLengths: 4444 case kStringLengths:
4386 instr->SetGVNFlag(is_store 4445 if (access_type == STORE) {
4387 ? kChangesStringLengths : kDependsOnStringLengths); 4446 instr->SetChangesFlag(::v8::internal::kStringLengths);
4447 } else {
4448 instr->SetDependsOnFlag(::v8::internal::kStringLengths);
4449 }
4388 break; 4450 break;
4389 case kInobject: 4451 case kInobject:
4390 instr->SetGVNFlag(is_store 4452 if (access_type == STORE) {
4391 ? kChangesInobjectFields : kDependsOnInobjectFields); 4453 instr->SetChangesFlag(::v8::internal::kInobjectFields);
4454 } else {
4455 instr->SetDependsOnFlag(::v8::internal::kInobjectFields);
4456 }
4392 break; 4457 break;
4393 case kDouble: 4458 case kDouble:
4394 instr->SetGVNFlag(is_store 4459 if (access_type == STORE) {
4395 ? kChangesDoubleFields : kDependsOnDoubleFields); 4460 instr->SetChangesFlag(::v8::internal::kDoubleFields);
4461 } else {
4462 instr->SetDependsOnFlag(::v8::internal::kDoubleFields);
4463 }
4396 break; 4464 break;
4397 case kBackingStore: 4465 case kBackingStore:
4398 instr->SetGVNFlag(is_store 4466 if (access_type == STORE) {
4399 ? kChangesBackingStoreFields : kDependsOnBackingStoreFields); 4467 instr->SetChangesFlag(::v8::internal::kBackingStoreFields);
4468 } else {
4469 instr->SetDependsOnFlag(::v8::internal::kBackingStoreFields);
4470 }
4400 break; 4471 break;
4401 case kElementsPointer: 4472 case kElementsPointer:
4402 instr->SetGVNFlag(is_store 4473 if (access_type == STORE) {
4403 ? kChangesElementsPointer : kDependsOnElementsPointer); 4474 instr->SetChangesFlag(::v8::internal::kElementsPointer);
4475 } else {
4476 instr->SetDependsOnFlag(::v8::internal::kElementsPointer);
4477 }
4404 break; 4478 break;
4405 case kMaps: 4479 case kMaps:
4406 instr->SetGVNFlag(is_store 4480 if (access_type == STORE) {
4407 ? kChangesMaps : kDependsOnMaps); 4481 instr->SetChangesFlag(::v8::internal::kMaps);
4482 } else {
4483 instr->SetDependsOnFlag(::v8::internal::kMaps);
4484 }
4408 break; 4485 break;
4409 case kExternalMemory: 4486 case kExternalMemory:
4410 instr->SetGVNFlag(is_store 4487 if (access_type == STORE) {
4411 ? kChangesExternalMemory : kDependsOnExternalMemory); 4488 instr->SetChangesFlag(::v8::internal::kExternalMemory);
4489 } else {
4490 instr->SetDependsOnFlag(::v8::internal::kExternalMemory);
4491 }
4412 break; 4492 break;
4413 } 4493 }
4414 } 4494 }
4415 4495
4416 4496
4417 void HObjectAccess::PrintTo(StringStream* stream) { 4497 void HObjectAccess::PrintTo(StringStream* stream) const {
4418 stream->Add("."); 4498 stream->Add(".");
4419 4499
4420 switch (portion()) { 4500 switch (portion()) {
4421 case kArrayLengths: 4501 case kArrayLengths:
4422 case kStringLengths: 4502 case kStringLengths:
4423 stream->Add("%length"); 4503 stream->Add("%length");
4424 break; 4504 break;
4425 case kElementsPointer: 4505 case kElementsPointer:
4426 stream->Add("%elements"); 4506 stream->Add("%elements");
4427 break; 4507 break;
(...skipping 15 matching lines...) Expand all
4443 break; 4523 break;
4444 case kExternalMemory: 4524 case kExternalMemory:
4445 stream->Add("[external-memory]"); 4525 stream->Add("[external-memory]");
4446 break; 4526 break;
4447 } 4527 }
4448 4528
4449 stream->Add("@%d", offset()); 4529 stream->Add("@%d", offset());
4450 } 4530 }
4451 4531
4452 } } // namespace v8::internal 4532 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/hydrogen-load-elimination.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698