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[](uint32_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 if (control_.back().unreachable) { | |
titzer
2017/02/14 13:30:27
At first glance this logic seems best to put into
rossberg
2017/02/14 15:11:17
Unfortunately, no, because it compares across targ
| |
979 // Check that label types still match up. | |
980 Control* c = &control_[control_.size() - target - 1]; | |
981 if (i == 0) { | |
982 merge = &c->merge; | |
983 } else if (merge->arity != c->merge.arity) { | |
984 error(pos, pos, "inconsistent arity in br_table taret %d" | |
titzer
2017/02/14 13:30:27
s/taret/target/
rossberg
2017/02/14 15:11:17
Done.
| |
985 " (previous was %u, this one %u)", | |
986 i, merge->arity, c->merge.arity); | |
987 } else { | |
988 for (uint32_t j = 0; ok() && j < merge->arity; ++j) { | |
989 if ((*merge)[j].type != c->merge[j].type) { | |
990 error(pos, pos, | |
991 "type error in br_table target %d operand %d" | |
992 " (previous expected %s, this one %s)", i, j, | |
993 WasmOpcodes::TypeName((*merge)[j].type), | |
994 WasmOpcodes::TypeName(c->merge[j].type)); | |
995 } | |
996 } | |
997 } | |
998 } | |
976 } | 999 } |
977 if (failed()) break; | 1000 if (failed()) break; |
978 } else { | 1001 } else { |
979 // Only a default target. Do the equivalent of br. | 1002 // Only a default target. Do the equivalent of br. |
980 const byte* pos = iterator.pc(); | 1003 const byte* pos = iterator.pc(); |
981 uint32_t target = iterator.next(); | 1004 uint32_t target = iterator.next(); |
982 if (target >= control_.size()) { | 1005 if (target >= control_.size()) { |
983 error(pos, "improper branch in br_table"); | 1006 error(pos, "improper branch in br_table"); |
984 break; | 1007 break; |
985 } | 1008 } |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1500 EndControl(); | 1523 EndControl(); |
1501 } | 1524 } |
1502 | 1525 |
1503 void Push(ValueType type, TFNode* node) { | 1526 void Push(ValueType type, TFNode* node) { |
1504 if (type != kWasmStmt) { | 1527 if (type != kWasmStmt) { |
1505 stack_.push_back({pc_, node, type}); | 1528 stack_.push_back({pc_, node, type}); |
1506 } | 1529 } |
1507 } | 1530 } |
1508 | 1531 |
1509 void PushEndValues(Control* c) { | 1532 void PushEndValues(Control* c) { |
1533 DCHECK_EQ(c, &control_.back()); | |
1510 stack_.resize(c->stack_depth); | 1534 stack_.resize(c->stack_depth); |
1511 if (c->merge.arity == 1) { | 1535 if (c->merge.arity == 1) { |
1512 stack_.push_back(c->merge.vals.first); | 1536 stack_.push_back(c->merge.vals.first); |
1513 } else { | 1537 } else { |
1514 for (unsigned i = 0; i < c->merge.arity; i++) { | 1538 for (unsigned i = 0; i < c->merge.arity; i++) { |
1515 stack_.push_back(c->merge.vals.array[i]); | 1539 stack_.push_back(c->merge.vals.array[i]); |
1516 } | 1540 } |
1517 } | 1541 } |
1518 DCHECK_EQ(c->stack_depth + c->merge.arity, stack_.size()); | 1542 DCHECK_EQ(c->stack_depth + c->merge.arity, stack_.size()); |
1519 } | 1543 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1561 | 1585 |
1562 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } | 1586 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } |
1563 | 1587 |
1564 void BreakTo(unsigned depth) { | 1588 void BreakTo(unsigned depth) { |
1565 Control* c = &control_[control_.size() - depth - 1]; | 1589 Control* c = &control_[control_.size() - depth - 1]; |
1566 if (c->is_loop()) { | 1590 if (c->is_loop()) { |
1567 // This is the inner loop block, which does not have a value. | 1591 // This is the inner loop block, which does not have a value. |
1568 Goto(ssa_env_, c->end_env); | 1592 Goto(ssa_env_, c->end_env); |
1569 } else { | 1593 } else { |
1570 // Merge the value(s) into the end of the block. | 1594 // Merge the value(s) into the end of the block. |
1571 size_t expected = c->stack_depth + c->merge.arity; | 1595 size_t expected = control_.back().stack_depth + c->merge.arity; |
1572 if (!c->unreachable && stack_.size() < expected) { | 1596 if (stack_.size() < expected && !control_.back().unreachable) { |
1573 error( | 1597 error( |
1574 pc_, pc_, | 1598 pc_, pc_, |
1575 "expected at least %u values on the stack for br to @%d, found %d", | 1599 "expected at least %u values on the stack for br to @%d, found %d", |
1576 c->merge.arity, startrel(c->pc), | 1600 c->merge.arity, startrel(c->pc), |
1577 static_cast<int>(stack_.size() - c->stack_depth)); | 1601 static_cast<int>(stack_.size() - c->stack_depth)); |
1578 return; | 1602 return; |
1579 } | 1603 } |
1580 MergeValuesInto(c); | 1604 MergeValuesInto(c); |
1581 } | 1605 } |
1582 } | 1606 } |
1583 | 1607 |
1584 void FallThruTo(Control* c) { | 1608 void FallThruTo(Control* c) { |
1609 DCHECK_EQ(c, &control_.back()); | |
1585 // Merge the value(s) into the end of the block. | 1610 // Merge the value(s) into the end of the block. |
1586 size_t expected = c->stack_depth + c->merge.arity; | 1611 size_t expected = c->stack_depth + c->merge.arity; |
1587 if (stack_.size() == expected || | 1612 if (stack_.size() == expected || |
1588 (c->unreachable && stack_.size() < expected)) { | 1613 (stack_.size() < expected && c->unreachable)) { |
1589 MergeValuesInto(c); | 1614 MergeValuesInto(c); |
1590 c->unreachable = false; | 1615 c->unreachable = false; |
1591 return; | 1616 return; |
1592 } | 1617 } |
1593 error(pc_, pc_, "expected %u elements on the stack for fallthru to @%d", | 1618 error(pc_, pc_, "expected %u elements on the stack for fallthru to @%d", |
1594 c->merge.arity, startrel(c->pc)); | 1619 c->merge.arity, startrel(c->pc)); |
1595 } | 1620 } |
1596 | 1621 |
1597 inline Value& GetMergeValueFromStack(Control* c, size_t i) { | 1622 inline Value& GetMergeValueFromStack(Control* c, size_t i) { |
1598 return stack_[stack_.size() - c->merge.arity + i]; | 1623 return stack_[stack_.size() - c->merge.arity + i]; |
1599 } | 1624 } |
1600 | 1625 |
1601 void TypeCheckFallThru(Control* c) { | 1626 void TypeCheckFallThru(Control* c) { |
1627 DCHECK_EQ(c, &control_.back()); | |
1602 // Fallthru must match arity exactly. | 1628 // Fallthru must match arity exactly. |
1603 int arity = static_cast<int>(c->merge.arity); | 1629 int arity = static_cast<int>(c->merge.arity); |
1604 if (c->stack_depth + arity < stack_.size() || | 1630 if (c->stack_depth + arity < stack_.size() || |
1605 (!c->unreachable && c->stack_depth + arity != stack_.size())) { | 1631 (c->stack_depth + arity != stack_.size() && !c->unreachable)) { |
1606 error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", | 1632 error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", |
1607 arity, startrel(c->pc)); | 1633 arity, startrel(c->pc)); |
1608 return; | 1634 return; |
1609 } | 1635 } |
1610 // Typecheck the values left on the stack. | 1636 // Typecheck the values left on the stack. |
1611 size_t avail = stack_.size() - c->stack_depth; | 1637 size_t avail = stack_.size() - c->stack_depth; |
1612 for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail; | 1638 for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail; |
1613 i < c->merge.arity; i++) { | 1639 i < c->merge.arity; i++) { |
1614 Value& val = GetMergeValueFromStack(c, i); | 1640 Value& val = GetMergeValueFromStack(c, i); |
1615 Value& old = | 1641 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) { | 1642 if (val.type != old.type) { |
1618 error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i, | 1643 error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i, |
1619 WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type)); | 1644 WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type)); |
1620 return; | 1645 return; |
1621 } | 1646 } |
1622 } | 1647 } |
1623 } | 1648 } |
1624 | 1649 |
1625 void MergeValuesInto(Control* c) { | 1650 void MergeValuesInto(Control* c) { |
1626 SsaEnv* target = c->end_env; | 1651 SsaEnv* target = c->end_env; |
1627 bool first = target->state == SsaEnv::kUnreachable; | 1652 bool first = target->state == SsaEnv::kUnreachable; |
1628 bool reachable = ssa_env_->go(); | 1653 bool reachable = ssa_env_->go(); |
1629 Goto(ssa_env_, target); | 1654 Goto(ssa_env_, target); |
1630 | 1655 |
1631 size_t avail = stack_.size() - c->stack_depth; | 1656 size_t avail = stack_.size() - control_.back().stack_depth; |
1632 for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail; | 1657 for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail; |
1633 i < c->merge.arity; i++) { | 1658 i < c->merge.arity; i++) { |
1634 Value& val = GetMergeValueFromStack(c, i); | 1659 Value& val = GetMergeValueFromStack(c, i); |
1635 Value& old = | 1660 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) { | 1661 if (val.type != old.type && val.type != kWasmVar) { |
1638 error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i, | 1662 error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i, |
1639 WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type)); | 1663 WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type)); |
1640 return; | 1664 return; |
1641 } | 1665 } |
1642 if (builder_ && reachable) { | 1666 if (builder_ && reachable) { |
1643 DCHECK_NOT_NULL(val.node); | 1667 DCHECK_NOT_NULL(val.node); |
1644 old.node = | 1668 old.node = |
1645 first ? val.node : CreateOrMergeIntoPhi(old.type, target->control, | 1669 first ? val.node : CreateOrMergeIntoPhi(old.type, target->control, |
1646 old.node, val.node); | 1670 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, | 2153 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
2130 const byte* start, const byte* end) { | 2154 const byte* start, const byte* end) { |
2131 Decoder decoder(start, end); | 2155 Decoder decoder(start, end); |
2132 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, | 2156 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, |
2133 static_cast<int>(num_locals), zone); | 2157 static_cast<int>(num_locals), zone); |
2134 } | 2158 } |
2135 | 2159 |
2136 } // namespace wasm | 2160 } // namespace wasm |
2137 } // namespace internal | 2161 } // namespace internal |
2138 } // namespace v8 | 2162 } // namespace v8 |
OLD | NEW |