Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ | 5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ |
| 6 #define VM_INTERMEDIATE_LANGUAGE_H_ | 6 #define VM_INTERMEDIATE_LANGUAGE_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/ast.h" | 9 #include "vm/ast.h" |
| 10 #include "vm/growable_array.h" | 10 #include "vm/growable_array.h" |
| 11 #include "vm/handles_impl.h" | 11 #include "vm/handles_impl.h" |
| 12 #include "vm/object.h" | 12 #include "vm/object.h" |
| 13 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 class BitVector; | 16 class BitVector; |
| 17 class FlowGraphVisitor; | 17 class FlowGraphVisitor; |
| 18 class LocalVariable; | 18 class LocalVariable; |
| 19 class LocationSummary; | |
| 19 | 20 |
| 20 // M is a two argument macro. It is applied to each concrete value's | 21 // M is a two argument macro. It is applied to each concrete value's |
| 21 // typename and classname. | 22 // typename and classname. |
| 22 #define FOR_EACH_VALUE(M) \ | 23 #define FOR_EACH_VALUE(M) \ |
| 23 M(Use, UseVal) \ | 24 M(Use, UseVal) \ |
| 24 M(Constant, ConstantVal) \ | 25 M(Constant, ConstantVal) \ |
| 25 | 26 |
| 26 | 27 |
| 27 // M is a two argument macro. It is applied to each concrete instruction's | 28 // M is a two argument macro. It is applied to each concrete instruction's |
| 28 // (including the values) typename and classname. | 29 // (including the values) typename and classname. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 101 // frame-allocated locals assigned to by the computation. | 102 // frame-allocated locals assigned to by the computation. |
| 102 virtual void RecordAssignedVars(BitVector* assigned_vars); | 103 virtual void RecordAssignedVars(BitVector* assigned_vars); |
| 103 | 104 |
| 104 virtual const char* DebugName() const = 0; | 105 virtual const char* DebugName() const = 0; |
| 105 | 106 |
| 106 // Printing support. These functions are sometimes overridden for custom | 107 // Printing support. These functions are sometimes overridden for custom |
| 107 // formatting. Otherwise, it prints in the format "opcode(op1, op2, op3)". | 108 // formatting. Otherwise, it prints in the format "opcode(op1, op2, op3)". |
| 108 virtual void PrintTo(BufferFormatter* f) const; | 109 virtual void PrintTo(BufferFormatter* f) const; |
| 109 virtual void PrintOperandsTo(BufferFormatter* f) const; | 110 virtual void PrintOperandsTo(BufferFormatter* f) const; |
| 110 | 111 |
| 112 // Returns structure describing location constraints required | |
| 113 // to emit native code for this computation. | |
| 114 virtual LocationSummary* GetLocationSummary() const { | |
| 115 // TODO(vegorov): This should be pure virtual method. | |
| 116 // However we are temporary using NULL for instructions that | |
| 117 // were not converted to the location based code generation yet. | |
| 118 return NULL; | |
| 119 } | |
| 120 | |
| 111 private: | 121 private: |
| 112 friend class Instruction; | 122 friend class Instruction; |
| 113 static intptr_t GetNextCid(Isolate* isolate) { | 123 static intptr_t GetNextCid(Isolate* isolate) { |
| 114 intptr_t tmp = isolate->computation_id(); | 124 intptr_t tmp = isolate->computation_id(); |
| 115 isolate->set_computation_id(tmp + 1); | 125 isolate->set_computation_id(tmp + 1); |
| 116 return tmp; | 126 return tmp; |
| 117 } | 127 } |
| 118 static ICData* GetICDataForCid(intptr_t cid, Isolate* isolate) { | 128 static ICData* GetICDataForCid(intptr_t cid, Isolate* isolate) { |
| 119 if (isolate->ic_data_array() == Array::null()) { | 129 if (isolate->ic_data_array() == Array::null()) { |
| 120 return NULL; | 130 return NULL; |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 442 }; | 452 }; |
| 443 | 453 |
| 444 | 454 |
| 445 class StrictCompareComp : public TemplateComputation<2> { | 455 class StrictCompareComp : public TemplateComputation<2> { |
| 446 public: | 456 public: |
| 447 StrictCompareComp(Token::Kind kind, Value* left, Value* right) | 457 StrictCompareComp(Token::Kind kind, Value* left, Value* right) |
| 448 : kind_(kind) { | 458 : kind_(kind) { |
| 449 ASSERT((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kNE_STRICT)); | 459 ASSERT((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kNE_STRICT)); |
| 450 inputs_[0] = left; | 460 inputs_[0] = left; |
| 451 inputs_[1] = right; | 461 inputs_[1] = right; |
| 462 location_summary_ = MakeLocationSummary(); | |
| 452 } | 463 } |
| 453 | 464 |
| 454 DECLARE_COMPUTATION(StrictCompare) | 465 DECLARE_COMPUTATION(StrictCompare) |
| 455 | 466 |
| 456 Token::Kind kind() const { return kind_; } | 467 Token::Kind kind() const { return kind_; } |
| 457 Value* left() const { return inputs_[0]; } | 468 Value* left() const { return inputs_[0]; } |
| 458 Value* right() const { return inputs_[1]; } | 469 Value* right() const { return inputs_[1]; } |
| 459 | 470 |
| 460 virtual void PrintOperandsTo(BufferFormatter* f) const; | 471 virtual void PrintOperandsTo(BufferFormatter* f) const; |
| 461 | 472 |
| 473 virtual LocationSummary* GetLocationSummary() const { | |
| 474 return location_summary_; | |
| 475 } | |
| 476 | |
| 477 // Platform specific summary factory for this instruction. | |
| 478 LocationSummary* MakeLocationSummary(); | |
| 479 | |
| 462 private: | 480 private: |
| 463 const Token::Kind kind_; | 481 const Token::Kind kind_; |
| 464 | 482 |
| 483 LocationSummary* location_summary_; | |
| 484 | |
| 465 DISALLOW_COPY_AND_ASSIGN(StrictCompareComp); | 485 DISALLOW_COPY_AND_ASSIGN(StrictCompareComp); |
| 466 }; | 486 }; |
| 467 | 487 |
| 468 | 488 |
| 469 class EqualityCompareComp : public TemplateComputation<2> { | 489 class EqualityCompareComp : public TemplateComputation<2> { |
| 470 public: | 490 public: |
| 471 EqualityCompareComp(intptr_t token_index, | 491 EqualityCompareComp(intptr_t token_index, |
| 472 intptr_t try_index, | 492 intptr_t try_index, |
| 473 Value* left, | 493 Value* left, |
| 474 Value* right) | 494 Value* right) |
| (...skipping 881 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1356 virtual type##Instr* As##type() { return NULL; } | 1376 virtual type##Instr* As##type() { return NULL; } |
| 1357 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK) | 1377 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK) |
| 1358 #undef INSTRUCTION_TYPE_CHECK | 1378 #undef INSTRUCTION_TYPE_CHECK |
| 1359 | 1379 |
| 1360 // Static type of the instruction. | 1380 // Static type of the instruction. |
| 1361 virtual RawAbstractType* StaticType() const { | 1381 virtual RawAbstractType* StaticType() const { |
| 1362 UNREACHABLE(); | 1382 UNREACHABLE(); |
| 1363 return AbstractType::null(); | 1383 return AbstractType::null(); |
| 1364 } | 1384 } |
| 1365 | 1385 |
| 1386 // Returns structure describing location constraints required | |
| 1387 // to emit native code for this instruction. | |
| 1388 virtual LocationSummary* GetLocationSummary() const { | |
| 1389 // TODO(vegorov): This should be pure virtual method. | |
| 1390 // However we are temporary using NULL for instructions that | |
| 1391 // were not converted to the location based code generation yet. | |
| 1392 return NULL; | |
|
srdjan
2012/05/18 18:00:14
Will we need this? I would guess that we are only
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
Some instructions also pop and push things (see fo
srdjan
2012/05/21 16:05:22
Please add comment why this is needed (essentially
| |
| 1393 } | |
| 1394 | |
| 1366 private: | 1395 private: |
| 1367 intptr_t cid_; | 1396 intptr_t cid_; |
| 1368 ICData* ic_data_; | 1397 ICData* ic_data_; |
| 1369 DISALLOW_COPY_AND_ASSIGN(Instruction); | 1398 DISALLOW_COPY_AND_ASSIGN(Instruction); |
| 1370 }; | 1399 }; |
| 1371 | 1400 |
| 1372 | 1401 |
| 1373 // Basic block entries are administrative nodes. There is a distinguished | 1402 // Basic block entries are administrative nodes. There is a distinguished |
| 1374 // graph entry with no predecessor. Joins are the only nodes with multiple | 1403 // graph entry with no predecessor. Joins are the only nodes with multiple |
| 1375 // predecessors. Targets are all other basic block entries. The types | 1404 // predecessors. Targets are all other basic block entries. The types |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1560 virtual Instruction* StraightLineSuccessor() const { | 1589 virtual Instruction* StraightLineSuccessor() const { |
| 1561 return successor_; | 1590 return successor_; |
| 1562 } | 1591 } |
| 1563 virtual void SetSuccessor(Instruction* instr) { | 1592 virtual void SetSuccessor(Instruction* instr) { |
| 1564 ASSERT(successor_ == NULL); | 1593 ASSERT(successor_ == NULL); |
| 1565 successor_ = instr; | 1594 successor_ = instr; |
| 1566 } | 1595 } |
| 1567 | 1596 |
| 1568 virtual void RecordAssignedVars(BitVector* assigned_vars); | 1597 virtual void RecordAssignedVars(BitVector* assigned_vars); |
| 1569 | 1598 |
| 1599 virtual LocationSummary* GetLocationSummary() const { | |
| 1600 return computation()->GetLocationSummary(); | |
| 1601 } | |
| 1602 | |
| 1570 private: | 1603 private: |
| 1571 Computation* computation_; | 1604 Computation* computation_; |
| 1572 Instruction* successor_; | 1605 Instruction* successor_; |
| 1573 | 1606 |
| 1574 DISALLOW_COPY_AND_ASSIGN(DoInstr); | 1607 DISALLOW_COPY_AND_ASSIGN(DoInstr); |
| 1575 }; | 1608 }; |
| 1576 | 1609 |
| 1577 | 1610 |
| 1578 class Definition : public Instruction { | 1611 class Definition : public Instruction { |
| 1579 public: | 1612 public: |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 1608 successor_ = instr; | 1641 successor_ = instr; |
| 1609 } | 1642 } |
| 1610 | 1643 |
| 1611 // Static type of the underlying computation. | 1644 // Static type of the underlying computation. |
| 1612 virtual RawAbstractType* StaticType() const { | 1645 virtual RawAbstractType* StaticType() const { |
| 1613 return computation()->StaticType(); | 1646 return computation()->StaticType(); |
| 1614 } | 1647 } |
| 1615 | 1648 |
| 1616 virtual void RecordAssignedVars(BitVector* assigned_vars); | 1649 virtual void RecordAssignedVars(BitVector* assigned_vars); |
| 1617 | 1650 |
| 1651 virtual LocationSummary* GetLocationSummary() const { | |
| 1652 return computation()->GetLocationSummary(); | |
| 1653 } | |
| 1654 | |
| 1618 private: | 1655 private: |
| 1619 Computation* computation_; | 1656 Computation* computation_; |
| 1620 Instruction* successor_; | 1657 Instruction* successor_; |
| 1621 | 1658 |
| 1622 DISALLOW_COPY_AND_ASSIGN(BindInstr); | 1659 DISALLOW_COPY_AND_ASSIGN(BindInstr); |
| 1623 }; | 1660 }; |
| 1624 | 1661 |
| 1625 | 1662 |
| 1626 class ReturnInstr : public Instruction { | 1663 class ReturnInstr : public Instruction { |
| 1627 public: | 1664 public: |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1793 // block_order for reverse iterations. | 1830 // block_order for reverse iterations. |
| 1794 intptr_t reverse_index(intptr_t index) { | 1831 intptr_t reverse_index(intptr_t index) { |
| 1795 return block_order_.length() - index - 1; | 1832 return block_order_.length() - index - 1; |
| 1796 } | 1833 } |
| 1797 | 1834 |
| 1798 const GrowableArray<BlockEntryInstr*>& block_order_; | 1835 const GrowableArray<BlockEntryInstr*>& block_order_; |
| 1799 | 1836 |
| 1800 private: | 1837 private: |
| 1801 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); | 1838 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); |
| 1802 }; | 1839 }; |
| 1803 | 1840 |
|
srdjan
2012/05/18 18:00:14
All these classes need a small amount of comment,
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
Commented, moved to location.{cc,h}
| |
| 1804 | 1841 |
| 1842 class Location : public ValueObject { | |
|
srdjan
2012/05/18 18:00:14
Add comment about formatting.
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
Done.
| |
| 1843 public: | |
| 1844 enum Kind { | |
| 1845 INVALID, | |
| 1846 UNALLOCATED, | |
| 1847 REGISTER | |
|
srdjan
2012/05/18 18:00:14
enums are typically named kInvalid, kUnallocated e
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
Renamed to match style.
Did not add kStack/kAddr
| |
| 1848 }; | |
| 1849 | |
| 1850 Location() : value_(KindField::encode(INVALID)) { } | |
| 1851 | |
| 1852 Kind kind() const { return KindField::decode(value_); } | |
| 1853 | |
| 1854 uword value() const { return value_; } | |
|
srdjan
2012/05/18 18:00:14
This belongs in protected?
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
Can't be in the protected because it is used from
srdjan
2012/05/21 16:05:22
Ha!
| |
| 1855 | |
| 1856 protected: | |
| 1857 explicit Location(uword value) : value_(value) { } | |
|
srdjan
2012/05/18 18:00:14
Do you need this constructor?
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
It is called by similar constructors of children w
| |
| 1858 | |
| 1859 Location(Kind kind, uword payload) | |
| 1860 : value_(KindField::encode(kind) | PayloadField::encode(payload)) { } | |
|
srdjan
2012/05/18 18:00:14
BitField::encode needs range checks.
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
It does use is_valid(), I think that should be eno
| |
| 1861 | |
| 1862 uword payload() const { return PayloadField::decode(value_); } | |
| 1863 | |
| 1864 private: | |
| 1865 typedef BitField<Kind, 0, 2> KindField; | |
| 1866 typedef BitField<uword, 2, kWordSize * kBitsPerByte - 2> PayloadField; | |
| 1867 | |
| 1868 uword value_; | |
|
srdjan
2012/05/18 18:00:14
const
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
If I put const here I would need to implement my o
| |
| 1869 }; | |
| 1870 | |
| 1871 | |
| 1872 class UnallocatedLocation : public Location { | |
| 1873 public: | |
| 1874 enum Policy { | |
| 1875 REGISTER, | |
| 1876 SAME_AS_FIRST_INPUT | |
| 1877 }; | |
| 1878 | |
| 1879 explicit UnallocatedLocation(Policy policy) | |
| 1880 : Location(UNALLOCATED, PolicyField::encode(policy)) { | |
| 1881 } | |
| 1882 | |
| 1883 Policy policy() { return PolicyField::decode(payload()); } | |
| 1884 | |
| 1885 static UnallocatedLocation Cast(Location loc) { | |
|
srdjan
2012/05/18 18:00:14
Maybe AsUnaloocatedLocation instead of Cast? And d
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
I can put helper methods into Location but then I
| |
| 1886 ASSERT(loc.kind() == UNALLOCATED); | |
| 1887 return UnallocatedLocation(loc.value()); | |
| 1888 } | |
| 1889 | |
| 1890 private: | |
| 1891 explicit UnallocatedLocation(uword value) : Location(value) { } | |
| 1892 | |
| 1893 typedef BitField<Policy, 0, 1> PolicyField; | |
| 1894 }; | |
| 1895 | |
| 1896 | |
| 1897 class RegisterLocation : public Location { | |
| 1898 public: | |
| 1899 explicit RegisterLocation(Register reg) | |
|
srdjan
2012/05/18 18:00:14
This cannot handle XMMRegisters, maybe add the reg
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
see above about organically growing Location as we
| |
| 1900 : Location(REGISTER, reg) { } | |
| 1901 | |
| 1902 Register reg() const { | |
| 1903 return static_cast<Register>(payload()); | |
| 1904 } | |
| 1905 | |
| 1906 static RegisterLocation Cast(Location loc) { | |
| 1907 ASSERT(loc.kind() == REGISTER); | |
| 1908 return RegisterLocation(loc.value()); | |
| 1909 } | |
| 1910 | |
| 1911 private: | |
| 1912 explicit RegisterLocation(uword value) : Location(value) { } | |
| 1913 }; | |
| 1914 | |
| 1915 | |
| 1916 class LocationSummary : public ZoneAllocated { | |
|
srdjan
2012/05/18 18:00:14
I am not too happy with the name LocationSummary a
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
ComputationLocations does not work because instruc
| |
| 1917 public: | |
| 1918 explicit LocationSummary(intptr_t count) | |
| 1919 : count_(count) { | |
| 1920 Zone* zone = Isolate::Current()->current_zone(); | |
|
srdjan
2012/05/18 18:00:14
Use ZoneGrowableArray fro now, and we can replace
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
Using ZoneGrowableArray. Added TODO to use ZoneArr
| |
| 1921 input_locations_ = reinterpret_cast<Location*>( | |
| 1922 zone->Allocate(sizeof(Location) * count)); | |
| 1923 } | |
| 1924 | |
| 1925 intptr_t InputLocationsCount() const { | |
| 1926 return count_; | |
| 1927 } | |
| 1928 | |
| 1929 Location InputLocationAt(intptr_t index) const { | |
| 1930 ASSERT(0 <= index && index < count_); | |
| 1931 return input_locations_[index]; | |
| 1932 } | |
| 1933 | |
| 1934 void SetInputLocationAt(intptr_t index, Location loc) { | |
| 1935 ASSERT(0 <= index && index < count_); | |
| 1936 input_locations_[index] = loc; | |
| 1937 } | |
| 1938 | |
| 1939 Location result_location() const { | |
| 1940 return result_location_; | |
| 1941 } | |
| 1942 | |
| 1943 void set_result_location(Location loc) { | |
| 1944 result_location_ = loc; | |
| 1945 } | |
| 1946 | |
| 1947 private: | |
| 1948 intptr_t count_; | |
| 1949 Location* input_locations_; | |
| 1950 Location result_location_; | |
| 1951 }; | |
| 1952 | |
| 1953 | |
| 1805 } // namespace dart | 1954 } // namespace dart |
| 1806 | 1955 |
| 1807 #endif // VM_INTERMEDIATE_LANGUAGE_H_ | 1956 #endif // VM_INTERMEDIATE_LANGUAGE_H_ |
| OLD | NEW |