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

Side by Side Diff: src/wasm/function-body-decoder.cc

Issue 2696813002: [wasm] Inspect right control frames for unreachable flag (Closed)
Patch Set: Avoid conversion warning Created 3 years, 10 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
« no previous file with comments | « no previous file | test/mjsunit/wasm/function-names.js » ('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 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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/wasm/function-names.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698