OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/signature.h" | 5 #include "src/signature.h" |
6 | 6 |
7 #include "src/base/platform/elapsed-timer.h" | 7 #include "src/base/platform/elapsed-timer.h" |
8 #include "src/bit-vector.h" | 8 #include "src/bit-vector.h" |
9 #include "src/flags.h" | 9 #include "src/flags.h" |
10 #include "src/handles.h" | 10 #include "src/handles.h" |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 explicit TryInfo(SsaEnv* c) : catch_env(c), exception(nullptr) {} | 82 explicit TryInfo(SsaEnv* c) : catch_env(c), exception(nullptr) {} |
83 }; | 83 }; |
84 | 84 |
85 struct MergeValues { | 85 struct MergeValues { |
86 uint32_t arity; | 86 uint32_t arity; |
87 union { | 87 union { |
88 Value* array; | 88 Value* array; |
89 Value first; | 89 Value first; |
90 } vals; // Either multiple values or a single value. | 90 } vals; // Either multiple values or a single value. |
91 | 91 |
92 Value& first() { | 92 Value& operator[](size_t i) { |
93 DCHECK_GT(arity, 0); | 93 DCHECK_GT(arity, i); |
94 return arity == 1 ? vals.first : vals.array[0]; | 94 return arity == 1 ? vals.first : vals.array[i]; |
95 } | 95 } |
96 }; | 96 }; |
97 | 97 |
98 static Value* NO_VALUE = nullptr; | 98 static Value* NO_VALUE = nullptr; |
99 | 99 |
100 enum ControlKind { kControlIf, kControlBlock, kControlLoop, kControlTry }; | 100 enum ControlKind { kControlIf, kControlBlock, kControlLoop, kControlTry }; |
101 | 101 |
102 // An entry on the control stack (i.e. if, block, loop). | 102 // An entry on the control stack (i.e. if, block, loop). |
103 struct Control { | 103 struct Control { |
104 const byte* pc; | 104 const byte* pc; |
(...skipping 848 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
953 Value key = Pop(0, kWasmI32); | 953 Value key = Pop(0, kWasmI32); |
954 if (failed()) break; | 954 if (failed()) break; |
955 | 955 |
956 SsaEnv* break_env = ssa_env_; | 956 SsaEnv* break_env = ssa_env_; |
957 if (operand.table_count > 0) { | 957 if (operand.table_count > 0) { |
958 // Build branches to the various blocks based on the table. | 958 // Build branches to the various blocks based on the table. |
959 TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node); | 959 TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node); |
960 | 960 |
961 SsaEnv* copy = Steal(break_env); | 961 SsaEnv* copy = Steal(break_env); |
962 ssa_env_ = copy; | 962 ssa_env_ = copy; |
| 963 MergeValues* merge = nullptr; |
963 while (ok() && iterator.has_next()) { | 964 while (ok() && iterator.has_next()) { |
964 uint32_t i = iterator.cur_index(); | 965 uint32_t i = iterator.cur_index(); |
965 const byte* pos = iterator.pc(); | 966 const byte* pos = iterator.pc(); |
966 uint32_t target = iterator.next(); | 967 uint32_t target = iterator.next(); |
967 if (target >= control_.size()) { | 968 if (target >= control_.size()) { |
968 error(pos, "improper branch in br_table"); | 969 error(pos, "improper branch in br_table"); |
969 break; | 970 break; |
970 } | 971 } |
971 ssa_env_ = Split(copy); | 972 ssa_env_ = Split(copy); |
972 ssa_env_->control = (i == operand.table_count) | 973 ssa_env_->control = (i == operand.table_count) |
973 ? BUILD(IfDefault, sw) | 974 ? BUILD(IfDefault, sw) |
974 : BUILD(IfValue, i, sw); | 975 : BUILD(IfValue, i, sw); |
975 BreakTo(target); | 976 BreakTo(target); |
| 977 |
| 978 // Check that label types match up. |
| 979 Control* c = &control_[control_.size() - target - 1]; |
| 980 if (i == 0) { |
| 981 merge = &c->merge; |
| 982 } else if (merge->arity != c->merge.arity) { |
| 983 error(pos, pos, "inconsistent arity in br_table target %d" |
| 984 " (previous was %u, this one %u)", |
| 985 i, merge->arity, c->merge.arity); |
| 986 } else if (control_.back().unreachable) { |
| 987 for (uint32_t j = 0; ok() && j < merge->arity; ++j) { |
| 988 if ((*merge)[j].type != c->merge[j].type) { |
| 989 error(pos, pos, |
| 990 "type error in br_table target %d operand %d" |
| 991 " (previous expected %s, this one %s)", i, j, |
| 992 WasmOpcodes::TypeName((*merge)[j].type), |
| 993 WasmOpcodes::TypeName(c->merge[j].type)); |
| 994 } |
| 995 } |
| 996 } |
976 } | 997 } |
977 if (failed()) break; | 998 if (failed()) break; |
978 } else { | 999 } else { |
979 // Only a default target. Do the equivalent of br. | 1000 // Only a default target. Do the equivalent of br. |
980 const byte* pos = iterator.pc(); | 1001 const byte* pos = iterator.pc(); |
981 uint32_t target = iterator.next(); | 1002 uint32_t target = iterator.next(); |
982 if (target >= control_.size()) { | 1003 if (target >= control_.size()) { |
983 error(pos, "improper branch in br_table"); | 1004 error(pos, "improper branch in br_table"); |
984 break; | 1005 break; |
985 } | 1006 } |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1500 EndControl(); | 1521 EndControl(); |
1501 } | 1522 } |
1502 | 1523 |
1503 void Push(ValueType type, TFNode* node) { | 1524 void Push(ValueType type, TFNode* node) { |
1504 if (type != kWasmStmt) { | 1525 if (type != kWasmStmt) { |
1505 stack_.push_back({pc_, node, type}); | 1526 stack_.push_back({pc_, node, type}); |
1506 } | 1527 } |
1507 } | 1528 } |
1508 | 1529 |
1509 void PushEndValues(Control* c) { | 1530 void PushEndValues(Control* c) { |
| 1531 DCHECK_EQ(c, &control_.back()); |
1510 stack_.resize(c->stack_depth); | 1532 stack_.resize(c->stack_depth); |
1511 if (c->merge.arity == 1) { | 1533 if (c->merge.arity == 1) { |
1512 stack_.push_back(c->merge.vals.first); | 1534 stack_.push_back(c->merge.vals.first); |
1513 } else { | 1535 } else { |
1514 for (unsigned i = 0; i < c->merge.arity; i++) { | 1536 for (unsigned i = 0; i < c->merge.arity; i++) { |
1515 stack_.push_back(c->merge.vals.array[i]); | 1537 stack_.push_back(c->merge.vals.array[i]); |
1516 } | 1538 } |
1517 } | 1539 } |
1518 DCHECK_EQ(c->stack_depth + c->merge.arity, stack_.size()); | 1540 DCHECK_EQ(c->stack_depth + c->merge.arity, stack_.size()); |
1519 } | 1541 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1561 | 1583 |
1562 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } | 1584 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } |
1563 | 1585 |
1564 void BreakTo(unsigned depth) { | 1586 void BreakTo(unsigned depth) { |
1565 Control* c = &control_[control_.size() - depth - 1]; | 1587 Control* c = &control_[control_.size() - depth - 1]; |
1566 if (c->is_loop()) { | 1588 if (c->is_loop()) { |
1567 // This is the inner loop block, which does not have a value. | 1589 // This is the inner loop block, which does not have a value. |
1568 Goto(ssa_env_, c->end_env); | 1590 Goto(ssa_env_, c->end_env); |
1569 } else { | 1591 } else { |
1570 // Merge the value(s) into the end of the block. | 1592 // Merge the value(s) into the end of the block. |
1571 size_t expected = c->stack_depth + c->merge.arity; | 1593 size_t expected = control_.back().stack_depth + c->merge.arity; |
1572 if (!c->unreachable && stack_.size() < expected) { | 1594 if (stack_.size() < expected && !control_.back().unreachable) { |
1573 error( | 1595 error( |
1574 pc_, pc_, | 1596 pc_, pc_, |
1575 "expected at least %u values on the stack for br to @%d, found %d", | 1597 "expected at least %u values on the stack for br to @%d, found %d", |
1576 c->merge.arity, startrel(c->pc), | 1598 c->merge.arity, startrel(c->pc), |
1577 static_cast<int>(stack_.size() - c->stack_depth)); | 1599 static_cast<int>(stack_.size() - c->stack_depth)); |
1578 return; | 1600 return; |
1579 } | 1601 } |
1580 MergeValuesInto(c); | 1602 MergeValuesInto(c); |
1581 } | 1603 } |
1582 } | 1604 } |
1583 | 1605 |
1584 void FallThruTo(Control* c) { | 1606 void FallThruTo(Control* c) { |
| 1607 DCHECK_EQ(c, &control_.back()); |
1585 // Merge the value(s) into the end of the block. | 1608 // Merge the value(s) into the end of the block. |
1586 size_t expected = c->stack_depth + c->merge.arity; | 1609 size_t expected = c->stack_depth + c->merge.arity; |
1587 if (stack_.size() == expected || | 1610 if (stack_.size() == expected || |
1588 (c->unreachable && stack_.size() < expected)) { | 1611 (stack_.size() < expected && c->unreachable)) { |
1589 MergeValuesInto(c); | 1612 MergeValuesInto(c); |
1590 c->unreachable = false; | 1613 c->unreachable = false; |
1591 return; | 1614 return; |
1592 } | 1615 } |
1593 error(pc_, pc_, "expected %u elements on the stack for fallthru to @%d", | 1616 error(pc_, pc_, "expected %u elements on the stack for fallthru to @%d", |
1594 c->merge.arity, startrel(c->pc)); | 1617 c->merge.arity, startrel(c->pc)); |
1595 } | 1618 } |
1596 | 1619 |
1597 inline Value& GetMergeValueFromStack(Control* c, size_t i) { | 1620 inline Value& GetMergeValueFromStack(Control* c, size_t i) { |
1598 return stack_[stack_.size() - c->merge.arity + i]; | 1621 return stack_[stack_.size() - c->merge.arity + i]; |
1599 } | 1622 } |
1600 | 1623 |
1601 void TypeCheckFallThru(Control* c) { | 1624 void TypeCheckFallThru(Control* c) { |
| 1625 DCHECK_EQ(c, &control_.back()); |
1602 // Fallthru must match arity exactly. | 1626 // Fallthru must match arity exactly. |
1603 int arity = static_cast<int>(c->merge.arity); | 1627 int arity = static_cast<int>(c->merge.arity); |
1604 if (c->stack_depth + arity < stack_.size() || | 1628 if (c->stack_depth + arity < stack_.size() || |
1605 (!c->unreachable && c->stack_depth + arity != stack_.size())) { | 1629 (c->stack_depth + arity != stack_.size() && !c->unreachable)) { |
1606 error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", | 1630 error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", |
1607 arity, startrel(c->pc)); | 1631 arity, startrel(c->pc)); |
1608 return; | 1632 return; |
1609 } | 1633 } |
1610 // Typecheck the values left on the stack. | 1634 // Typecheck the values left on the stack. |
1611 size_t avail = stack_.size() - c->stack_depth; | 1635 size_t avail = stack_.size() - c->stack_depth; |
1612 for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail; | 1636 for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail; |
1613 i < c->merge.arity; i++) { | 1637 i < c->merge.arity; i++) { |
1614 Value& val = GetMergeValueFromStack(c, i); | 1638 Value& val = GetMergeValueFromStack(c, i); |
1615 Value& old = | 1639 Value& old = c->merge[i]; |
1616 c->merge.arity == 1 ? c->merge.vals.first : c->merge.vals.array[i]; | |
1617 if (val.type != old.type) { | 1640 if (val.type != old.type) { |
1618 error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i, | 1641 error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i, |
1619 WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type)); | 1642 WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type)); |
1620 return; | 1643 return; |
1621 } | 1644 } |
1622 } | 1645 } |
1623 } | 1646 } |
1624 | 1647 |
1625 void MergeValuesInto(Control* c) { | 1648 void MergeValuesInto(Control* c) { |
1626 SsaEnv* target = c->end_env; | 1649 SsaEnv* target = c->end_env; |
1627 bool first = target->state == SsaEnv::kUnreachable; | 1650 bool first = target->state == SsaEnv::kUnreachable; |
1628 bool reachable = ssa_env_->go(); | 1651 bool reachable = ssa_env_->go(); |
1629 Goto(ssa_env_, target); | 1652 Goto(ssa_env_, target); |
1630 | 1653 |
1631 size_t avail = stack_.size() - c->stack_depth; | 1654 size_t avail = stack_.size() - control_.back().stack_depth; |
1632 for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail; | 1655 for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail; |
1633 i < c->merge.arity; i++) { | 1656 i < c->merge.arity; i++) { |
1634 Value& val = GetMergeValueFromStack(c, i); | 1657 Value& val = GetMergeValueFromStack(c, i); |
1635 Value& old = | 1658 Value& old = c->merge[i]; |
1636 c->merge.arity == 1 ? c->merge.vals.first : c->merge.vals.array[i]; | |
1637 if (val.type != old.type && val.type != kWasmVar) { | 1659 if (val.type != old.type && val.type != kWasmVar) { |
1638 error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i, | 1660 error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i, |
1639 WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type)); | 1661 WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type)); |
1640 return; | 1662 return; |
1641 } | 1663 } |
1642 if (builder_ && reachable) { | 1664 if (builder_ && reachable) { |
1643 DCHECK_NOT_NULL(val.node); | 1665 DCHECK_NOT_NULL(val.node); |
1644 old.node = | 1666 old.node = |
1645 first ? val.node : CreateOrMergeIntoPhi(old.type, target->control, | 1667 first ? val.node : CreateOrMergeIntoPhi(old.type, target->control, |
1646 old.node, val.node); | 1668 old.node, val.node); |
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2129 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 2151 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
2130 const byte* start, const byte* end) { | 2152 const byte* start, const byte* end) { |
2131 Decoder decoder(start, end); | 2153 Decoder decoder(start, end); |
2132 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, | 2154 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, |
2133 static_cast<int>(num_locals), zone); | 2155 static_cast<int>(num_locals), zone); |
2134 } | 2156 } |
2135 | 2157 |
2136 } // namespace wasm | 2158 } // namespace wasm |
2137 } // namespace internal | 2159 } // namespace internal |
2138 } // namespace v8 | 2160 } // namespace v8 |
OLD | NEW |