OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 while (!IsGapAt(index)) index--; | 465 while (!IsGapAt(index)) index--; |
466 return index; | 466 return index; |
467 } | 467 } |
468 | 468 |
469 | 469 |
470 void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) { | 470 void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) { |
471 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to); | 471 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to); |
472 } | 472 } |
473 | 473 |
474 | 474 |
475 class LGapNode: public ZoneObject { | |
476 public: | |
477 explicit LGapNode(LOperand* operand) | |
478 : operand_(operand), resolved_(false), visited_id_(-1) { } | |
479 | |
480 LOperand* operand() const { return operand_; } | |
481 bool IsResolved() const { return !IsAssigned() || resolved_; } | |
482 void MarkResolved() { | |
483 ASSERT(!IsResolved()); | |
484 resolved_ = true; | |
485 } | |
486 int visited_id() const { return visited_id_; } | |
487 void set_visited_id(int id) { | |
488 ASSERT(id > visited_id_); | |
489 visited_id_ = id; | |
490 } | |
491 | |
492 bool IsAssigned() const { return assigned_from_.is_set(); } | |
493 LGapNode* assigned_from() const { return assigned_from_.get(); } | |
494 void set_assigned_from(LGapNode* n) { assigned_from_.set(n); } | |
495 | |
496 private: | |
497 LOperand* operand_; | |
498 SetOncePointer<LGapNode> assigned_from_; | |
499 bool resolved_; | |
500 int visited_id_; | |
501 }; | |
502 | |
503 | |
504 LGapResolver::LGapResolver(const ZoneList<LMoveOperands>* moves, | |
505 LOperand* marker_operand) | |
506 : nodes_(4), | |
507 identified_cycles_(4), | |
508 result_(4), | |
509 marker_operand_(marker_operand), | |
510 next_visited_id_(0) { | |
511 for (int i = 0; i < moves->length(); ++i) { | |
512 LMoveOperands move = moves->at(i); | |
513 if (!move.IsRedundant()) RegisterMove(move); | |
514 } | |
515 } | |
516 | |
517 | |
518 const ZoneList<LMoveOperands>* LGapResolver::ResolveInReverseOrder() { | |
519 for (int i = 0; i < identified_cycles_.length(); ++i) { | |
520 ResolveCycle(identified_cycles_[i]); | |
521 } | |
522 | |
523 int unresolved_nodes; | |
524 do { | |
525 unresolved_nodes = 0; | |
526 for (int j = 0; j < nodes_.length(); j++) { | |
527 LGapNode* node = nodes_[j]; | |
528 if (!node->IsResolved() && node->assigned_from()->IsResolved()) { | |
529 AddResultMove(node->assigned_from(), node); | |
530 node->MarkResolved(); | |
531 } | |
532 if (!node->IsResolved()) ++unresolved_nodes; | |
533 } | |
534 } while (unresolved_nodes > 0); | |
535 return &result_; | |
536 } | |
537 | |
538 | |
539 void LGapResolver::AddResultMove(LGapNode* from, LGapNode* to) { | |
540 AddResultMove(from->operand(), to->operand()); | |
541 } | |
542 | |
543 | |
544 void LGapResolver::AddResultMove(LOperand* from, LOperand* to) { | |
545 result_.Add(LMoveOperands(from, to)); | |
546 } | |
547 | |
548 | |
549 void LGapResolver::ResolveCycle(LGapNode* start) { | |
550 ZoneList<LOperand*> circle_operands(8); | |
551 circle_operands.Add(marker_operand_); | |
552 LGapNode* cur = start; | |
553 do { | |
554 cur->MarkResolved(); | |
555 circle_operands.Add(cur->operand()); | |
556 cur = cur->assigned_from(); | |
557 } while (cur != start); | |
558 circle_operands.Add(marker_operand_); | |
559 | |
560 for (int i = circle_operands.length() - 1; i > 0; --i) { | |
561 LOperand* from = circle_operands[i]; | |
562 LOperand* to = circle_operands[i - 1]; | |
563 AddResultMove(from, to); | |
564 } | |
565 } | |
566 | |
567 | |
568 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b, int visited_id) { | |
569 ASSERT(a != b); | |
570 LGapNode* cur = a; | |
571 while (cur != b && cur->visited_id() != visited_id && cur->IsAssigned()) { | |
572 cur->set_visited_id(visited_id); | |
573 cur = cur->assigned_from(); | |
574 } | |
575 | |
576 return cur == b; | |
577 } | |
578 | |
579 | |
580 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b) { | |
581 ASSERT(a != b); | |
582 return CanReach(a, b, next_visited_id_++); | |
583 } | |
584 | |
585 | |
586 void LGapResolver::RegisterMove(LMoveOperands move) { | |
587 if (move.from()->IsConstantOperand()) { | |
588 // Constant moves should be last in the machine code. Therefore add them | |
589 // first to the result set. | |
590 AddResultMove(move.from(), move.to()); | |
591 } else { | |
592 LGapNode* from = LookupNode(move.from()); | |
593 LGapNode* to = LookupNode(move.to()); | |
594 if (to->IsAssigned() && to->assigned_from() == from) { | |
595 move.Eliminate(); | |
596 return; | |
597 } | |
598 ASSERT(!to->IsAssigned()); | |
599 if (CanReach(from, to)) { | |
600 // This introduces a circle. Save. | |
601 identified_cycles_.Add(from); | |
602 } | |
603 to->set_assigned_from(from); | |
604 } | |
605 } | |
606 | |
607 | |
608 LGapNode* LGapResolver::LookupNode(LOperand* operand) { | |
609 for (int i = 0; i < nodes_.length(); ++i) { | |
610 if (nodes_[i]->operand()->Equals(operand)) return nodes_[i]; | |
611 } | |
612 | |
613 // No node found => create a new one. | |
614 LGapNode* result = new LGapNode(operand); | |
615 nodes_.Add(result); | |
616 return result; | |
617 } | |
618 | |
619 | |
620 Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const { | 475 Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const { |
621 return HConstant::cast(graph_->LookupValue(operand->index()))->handle(); | 476 return HConstant::cast(graph_->LookupValue(operand->index()))->handle(); |
622 } | 477 } |
623 | 478 |
624 | 479 |
625 Representation LChunk::LookupLiteralRepresentation( | 480 Representation LChunk::LookupLiteralRepresentation( |
626 LConstantOperand* operand) const { | 481 LConstantOperand* operand) const { |
627 return graph_->LookupValue(operand->index())->representation(); | 482 return graph_->LookupValue(operand->index())->representation(); |
628 } | 483 } |
629 | 484 |
(...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1282 LInstruction* LChunkBuilder::DoCompareMapAndBranch( | 1137 LInstruction* LChunkBuilder::DoCompareMapAndBranch( |
1283 HCompareMapAndBranch* instr) { | 1138 HCompareMapAndBranch* instr) { |
1284 ASSERT(instr->value()->representation().IsTagged()); | 1139 ASSERT(instr->value()->representation().IsTagged()); |
1285 LOperand* value = UseRegisterAtStart(instr->value()); | 1140 LOperand* value = UseRegisterAtStart(instr->value()); |
1286 LOperand* temp = TempRegister(); | 1141 LOperand* temp = TempRegister(); |
1287 return new LCmpMapAndBranch(value, temp); | 1142 return new LCmpMapAndBranch(value, temp); |
1288 } | 1143 } |
1289 | 1144 |
1290 | 1145 |
1291 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { | 1146 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { |
1292 return DefineAsRegister(new LArgumentsLength(Use(length->value()))); | 1147 return DefineAsRegister(new LArgumentsLength(UseRegister(length->value()))); |
1293 } | 1148 } |
1294 | 1149 |
1295 | 1150 |
1296 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { | 1151 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { |
1297 return DefineAsRegister(new LArgumentsElements); | 1152 return DefineAsRegister(new LArgumentsElements); |
1298 } | 1153 } |
1299 | 1154 |
1300 | 1155 |
1301 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { | 1156 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { |
1302 LInstruction* result = | 1157 LInstruction* result = |
1303 new LInstanceOf(UseFixed(instr->left(), r0), | 1158 new LInstanceOf(UseFixed(instr->left(), r0), |
1304 UseFixed(instr->right(), r1)); | 1159 UseFixed(instr->right(), r1)); |
1305 return MarkAsCall(DefineFixed(result, r0), instr); | 1160 return MarkAsCall(DefineFixed(result, r0), instr); |
1306 } | 1161 } |
1307 | 1162 |
1308 | 1163 |
| 1164 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( |
| 1165 HInstanceOfKnownGlobal* instr) { |
| 1166 LInstruction* result = |
| 1167 new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0)); |
| 1168 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1169 } |
| 1170 |
| 1171 |
1309 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { | 1172 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { |
1310 LOperand* function = UseFixed(instr->function(), r1); | 1173 LOperand* function = UseFixed(instr->function(), r1); |
1311 LOperand* receiver = UseFixed(instr->receiver(), r0); | 1174 LOperand* receiver = UseFixed(instr->receiver(), r0); |
1312 LOperand* length = UseRegisterAtStart(instr->length()); | 1175 LOperand* length = UseRegisterAtStart(instr->length()); |
1313 LOperand* elements = UseRegisterAtStart(instr->elements()); | 1176 LOperand* elements = UseRegisterAtStart(instr->elements()); |
1314 LInstruction* result = new LApplyArguments(function, | 1177 LInstruction* result = new LApplyArguments(function, |
1315 receiver, | 1178 receiver, |
1316 length, | 1179 length, |
1317 elements); | 1180 elements); |
1318 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY); | 1181 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY); |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1667 | 1530 |
1668 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { | 1531 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { |
1669 LOperand* object = UseRegister(instr->value()); | 1532 LOperand* object = UseRegister(instr->value()); |
1670 LInstruction* result = new LValueOf(object, TempRegister()); | 1533 LInstruction* result = new LValueOf(object, TempRegister()); |
1671 return AssignEnvironment(DefineSameAsFirst(result)); | 1534 return AssignEnvironment(DefineSameAsFirst(result)); |
1672 } | 1535 } |
1673 | 1536 |
1674 | 1537 |
1675 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { | 1538 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { |
1676 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), | 1539 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), |
1677 Use(instr->length()))); | 1540 UseRegister(instr->length()))); |
1678 } | 1541 } |
1679 | 1542 |
1680 | 1543 |
1681 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { | 1544 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { |
1682 LOperand* value = UseFixed(instr->value(), r0); | 1545 LOperand* value = UseFixed(instr->value(), r0); |
1683 return MarkAsCall(new LThrow(value), instr); | 1546 return MarkAsCall(new LThrow(value), instr); |
1684 } | 1547 } |
1685 | 1548 |
1686 | 1549 |
1687 LInstruction* LChunkBuilder::DoChange(HChange* instr) { | 1550 LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1747 | 1610 |
1748 | 1611 |
1749 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) { | 1612 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) { |
1750 LOperand* value = UseRegisterAtStart(instr->value()); | 1613 LOperand* value = UseRegisterAtStart(instr->value()); |
1751 return AssignEnvironment(new LCheckSmi(value, eq)); | 1614 return AssignEnvironment(new LCheckSmi(value, eq)); |
1752 } | 1615 } |
1753 | 1616 |
1754 | 1617 |
1755 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { | 1618 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
1756 LOperand* value = UseRegisterAtStart(instr->value()); | 1619 LOperand* value = UseRegisterAtStart(instr->value()); |
1757 LOperand* temp = TempRegister(); | 1620 LInstruction* result = new LCheckInstanceType(value); |
1758 LInstruction* result = new LCheckInstanceType(value, temp); | |
1759 return AssignEnvironment(result); | 1621 return AssignEnvironment(result); |
1760 } | 1622 } |
1761 | 1623 |
1762 | 1624 |
1763 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { | 1625 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { |
1764 LOperand* temp1 = TempRegister(); | 1626 LOperand* temp1 = TempRegister(); |
1765 LOperand* temp2 = TempRegister(); | 1627 LOperand* temp2 = TempRegister(); |
1766 LInstruction* result = | 1628 LInstruction* result = |
1767 new LCheckPrototypeMaps(temp1, | 1629 new LCheckPrototypeMaps(temp1, |
1768 temp2, | 1630 temp2, |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1910 | 1772 |
1911 ASSERT(instr->object()->representation().IsTagged()); | 1773 ASSERT(instr->object()->representation().IsTagged()); |
1912 ASSERT(instr->key()->representation().IsTagged()); | 1774 ASSERT(instr->key()->representation().IsTagged()); |
1913 ASSERT(instr->value()->representation().IsTagged()); | 1775 ASSERT(instr->value()->representation().IsTagged()); |
1914 | 1776 |
1915 return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr); | 1777 return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr); |
1916 } | 1778 } |
1917 | 1779 |
1918 | 1780 |
1919 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { | 1781 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { |
1920 bool needs_write_barrier = !instr->value()->type().IsSmi(); | 1782 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
1921 | 1783 |
1922 LOperand* obj = needs_write_barrier | 1784 LOperand* obj = needs_write_barrier |
1923 ? UseTempRegister(instr->object()) | 1785 ? UseTempRegister(instr->object()) |
1924 : UseRegisterAtStart(instr->object()); | 1786 : UseRegisterAtStart(instr->object()); |
1925 | 1787 |
1926 LOperand* val = needs_write_barrier | 1788 LOperand* val = needs_write_barrier |
1927 ? UseTempRegister(instr->value()) | 1789 ? UseTempRegister(instr->value()) |
1928 : UseRegister(instr->value()); | 1790 : UseRegister(instr->value()); |
1929 | 1791 |
1930 // We only need a scratch register if we have a write barrier or we | |
1931 // have a store into the properties array (not in-object-property). | |
1932 LOperand* temp = (!instr->is_in_object() || needs_write_barrier) | |
1933 ? TempRegister() : NULL; | |
1934 | |
1935 return new LStoreNamedField(obj, | 1792 return new LStoreNamedField(obj, |
1936 instr->name(), | 1793 instr->name(), |
1937 val, | 1794 val, |
1938 instr->is_in_object(), | 1795 instr->is_in_object(), |
1939 instr->offset(), | 1796 instr->offset(), |
1940 temp, | |
1941 needs_write_barrier, | 1797 needs_write_barrier, |
1942 instr->transition()); | 1798 instr->transition()); |
1943 } | 1799 } |
1944 | 1800 |
1945 | 1801 |
1946 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { | 1802 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { |
1947 LOperand* obj = UseFixed(instr->object(), r1); | 1803 LOperand* obj = UseFixed(instr->object(), r1); |
1948 LOperand* val = UseFixed(instr->value(), r0); | 1804 LOperand* val = UseFixed(instr->value(), r0); |
1949 | 1805 |
1950 LInstruction* result = new LStoreNamedGeneric(obj, instr->name(), val); | 1806 LInstruction* result = new LStoreNamedGeneric(obj, instr->name(), val); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2007 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { | 1863 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { |
2008 // There are no real uses of the arguments object (we bail out in all other | 1864 // There are no real uses of the arguments object (we bail out in all other |
2009 // cases). | 1865 // cases). |
2010 return NULL; | 1866 return NULL; |
2011 } | 1867 } |
2012 | 1868 |
2013 | 1869 |
2014 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { | 1870 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { |
2015 LOperand* arguments = UseRegister(instr->arguments()); | 1871 LOperand* arguments = UseRegister(instr->arguments()); |
2016 LOperand* length = UseTempRegister(instr->length()); | 1872 LOperand* length = UseTempRegister(instr->length()); |
2017 LOperand* index = Use(instr->index()); | 1873 LOperand* index = UseRegister(instr->index()); |
2018 LInstruction* result = new LAccessArgumentsAt(arguments, length, index); | 1874 LInstruction* result = new LAccessArgumentsAt(arguments, length, index); |
2019 return DefineAsRegister(AssignEnvironment(result)); | 1875 return DefineAsRegister(AssignEnvironment(result)); |
2020 } | 1876 } |
2021 | 1877 |
2022 | 1878 |
2023 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { | 1879 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { |
2024 LInstruction* result = new LTypeof(Use(instr->value())); | 1880 LInstruction* result = new LTypeof(UseRegisterAtStart(instr->value())); |
2025 return MarkAsCall(DefineFixed(result, r0), instr); | 1881 return MarkAsCall(DefineFixed(result, r0), instr); |
2026 } | 1882 } |
2027 | 1883 |
2028 | 1884 |
2029 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { | 1885 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { |
2030 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value()))); | 1886 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value()))); |
2031 } | 1887 } |
2032 | 1888 |
2033 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { | 1889 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { |
2034 HEnvironment* env = current_block_->last_environment(); | 1890 HEnvironment* env = current_block_->last_environment(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2099 void LPointerMap::PrintTo(StringStream* stream) const { | 1955 void LPointerMap::PrintTo(StringStream* stream) const { |
2100 stream->Add("{"); | 1956 stream->Add("{"); |
2101 for (int i = 0; i < pointer_operands_.length(); ++i) { | 1957 for (int i = 0; i < pointer_operands_.length(); ++i) { |
2102 if (i != 0) stream->Add(";"); | 1958 if (i != 0) stream->Add(";"); |
2103 pointer_operands_[i]->PrintTo(stream); | 1959 pointer_operands_[i]->PrintTo(stream); |
2104 } | 1960 } |
2105 stream->Add("} @%d", position()); | 1961 stream->Add("} @%d", position()); |
2106 } | 1962 } |
2107 | 1963 |
2108 } } // namespace v8::internal | 1964 } } // namespace v8::internal |
OLD | NEW |