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/bit-vector.h" | 7 #include "src/bit-vector.h" |
8 #include "src/flags.h" | 8 #include "src/flags.h" |
9 #include "src/handles.h" | 9 #include "src/handles.h" |
10 #include "src/zone-containers.h" | 10 #include "src/zone-containers.h" |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 ModuleEnv* m = module_; | 150 ModuleEnv* m = module_; |
151 if (m && m->module && operand.index < m->module->globals.size()) { | 151 if (m && m->module && operand.index < m->module->globals.size()) { |
152 operand.machine_type = m->module->globals[operand.index].type; | 152 operand.machine_type = m->module->globals[operand.index].type; |
153 operand.type = WasmOpcodes::LocalTypeFor(operand.machine_type); | 153 operand.type = WasmOpcodes::LocalTypeFor(operand.machine_type); |
154 return true; | 154 return true; |
155 } | 155 } |
156 error(pc, pc + 1, "invalid global index"); | 156 error(pc, pc + 1, "invalid global index"); |
157 return false; | 157 return false; |
158 } | 158 } |
159 | 159 |
| 160 inline bool Complete(const byte* pc, CallFunctionOperand& operand) { |
| 161 ModuleEnv* m = module_; |
| 162 if (m && m->module && operand.index < m->module->functions.size()) { |
| 163 operand.sig = m->module->functions[operand.index].sig; |
| 164 return true; |
| 165 } |
| 166 return false; |
| 167 } |
| 168 |
160 inline bool Validate(const byte* pc, CallFunctionOperand& operand) { | 169 inline bool Validate(const byte* pc, CallFunctionOperand& operand) { |
161 ModuleEnv* m = module_; | 170 if (Complete(pc, operand)) { |
162 if (m && m->module && operand.index < m->module->functions.size()) { | |
163 operand.sig = m->module->functions[operand.index].sig; | |
164 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count()); | 171 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count()); |
165 if (operand.arity != expected) { | 172 if (operand.arity != expected) { |
166 error(pc, pc + 1, | 173 error(pc, pc + 1, |
167 "arity mismatch in direct function call (expected %u, got %u)", | 174 "arity mismatch in direct function call (expected %u, got %u)", |
168 expected, operand.arity); | 175 expected, operand.arity); |
169 return false; | 176 return false; |
170 } | 177 } |
171 return true; | 178 return true; |
172 } | 179 } |
173 error(pc, pc + 1, "invalid function index"); | 180 error(pc, pc + 1, "invalid function index"); |
174 return false; | 181 return false; |
175 } | 182 } |
176 | 183 |
| 184 inline bool Complete(const byte* pc, CallIndirectOperand& operand) { |
| 185 ModuleEnv* m = module_; |
| 186 if (m && m->module && operand.index < m->module->signatures.size()) { |
| 187 operand.sig = m->module->signatures[operand.index]; |
| 188 return true; |
| 189 } |
| 190 return false; |
| 191 } |
| 192 |
177 inline bool Validate(const byte* pc, CallIndirectOperand& operand) { | 193 inline bool Validate(const byte* pc, CallIndirectOperand& operand) { |
178 ModuleEnv* m = module_; | 194 if (Complete(pc, operand)) { |
179 if (m && m->module && operand.index < m->module->signatures.size()) { | |
180 operand.sig = m->module->signatures[operand.index]; | |
181 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count()); | 195 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count()); |
182 if (operand.arity != expected) { | 196 if (operand.arity != expected) { |
183 error(pc, pc + 1, | 197 error(pc, pc + 1, |
184 "arity mismatch in indirect function call (expected %u, got %u)", | 198 "arity mismatch in indirect function call (expected %u, got %u)", |
185 expected, operand.arity); | 199 expected, operand.arity); |
186 return false; | 200 return false; |
187 } | 201 } |
188 return true; | 202 return true; |
189 } | 203 } |
190 error(pc, pc + 1, "invalid signature index"); | 204 error(pc, pc + 1, "invalid signature index"); |
191 return false; | 205 return false; |
192 } | 206 } |
193 | 207 |
| 208 inline bool Complete(const byte* pc, CallImportOperand& operand) { |
| 209 ModuleEnv* m = module_; |
| 210 if (m && m->module && operand.index < m->module->import_table.size()) { |
| 211 operand.sig = m->module->import_table[operand.index].sig; |
| 212 return true; |
| 213 } |
| 214 return false; |
| 215 } |
| 216 |
194 inline bool Validate(const byte* pc, CallImportOperand& operand) { | 217 inline bool Validate(const byte* pc, CallImportOperand& operand) { |
195 ModuleEnv* m = module_; | 218 if (Complete(pc, operand)) { |
196 if (m && m->module && operand.index < m->module->import_table.size()) { | |
197 operand.sig = m->module->import_table[operand.index].sig; | |
198 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count()); | 219 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count()); |
199 if (operand.arity != expected) { | 220 if (operand.arity != expected) { |
200 error(pc, pc + 1, "arity mismatch in import call (expected %u, got %u)", | 221 error(pc, pc + 1, "arity mismatch in import call (expected %u, got %u)", |
201 expected, operand.arity); | 222 expected, operand.arity); |
202 return false; | 223 return false; |
203 } | 224 } |
204 return true; | 225 return true; |
205 } | 226 } |
206 error(pc, pc + 1, "invalid signature index"); | 227 error(pc, pc + 1, "invalid signature index"); |
207 return false; | 228 return false; |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 default: | 405 default: |
385 return 1; | 406 return 1; |
386 } | 407 } |
387 } | 408 } |
388 }; | 409 }; |
389 | 410 |
390 // A shift-reduce-parser strategy for decoding Wasm code that uses an explicit | 411 // A shift-reduce-parser strategy for decoding Wasm code that uses an explicit |
391 // shift-reduce strategy with multiple internal stacks. | 412 // shift-reduce strategy with multiple internal stacks. |
392 class SR_WasmDecoder : public WasmDecoder { | 413 class SR_WasmDecoder : public WasmDecoder { |
393 public: | 414 public: |
394 SR_WasmDecoder(Zone* zone, TFBuilder* builder, FunctionBody& body) | 415 SR_WasmDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) |
395 : WasmDecoder(body.module, body.sig, body.start, body.end), | 416 : WasmDecoder(body.module, body.sig, body.start, body.end), |
396 zone_(zone), | 417 zone_(zone), |
397 builder_(builder), | 418 builder_(builder), |
398 base_(body.base), | 419 base_(body.base), |
399 local_type_vec_(zone), | 420 local_type_vec_(zone), |
400 stack_(zone), | 421 stack_(zone), |
401 control_(zone) { | 422 control_(zone) { |
402 local_types_ = &local_type_vec_; | 423 local_types_ = &local_type_vec_; |
403 } | 424 } |
404 | 425 |
(...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1519 WasmDecoder decoder(nullptr, nullptr, pc, end); | 1540 WasmDecoder decoder(nullptr, nullptr, pc, end); |
1520 return decoder.OpcodeLength(pc); | 1541 return decoder.OpcodeLength(pc); |
1521 } | 1542 } |
1522 | 1543 |
1523 int OpcodeArity(const byte* pc, const byte* end) { | 1544 int OpcodeArity(const byte* pc, const byte* end) { |
1524 WasmDecoder decoder(nullptr, nullptr, pc, end); | 1545 WasmDecoder decoder(nullptr, nullptr, pc, end); |
1525 return decoder.OpcodeArity(pc); | 1546 return decoder.OpcodeArity(pc); |
1526 } | 1547 } |
1527 | 1548 |
1528 void PrintAstForDebugging(const byte* start, const byte* end) { | 1549 void PrintAstForDebugging(const byte* start, const byte* end) { |
1529 FunctionBody body = {nullptr, nullptr, start, start, end}; | |
1530 base::AccountingAllocator allocator; | 1550 base::AccountingAllocator allocator; |
1531 PrintAst(&allocator, body); | 1551 OFStream os(stdout); |
| 1552 PrintAst(&allocator, FunctionBodyForTesting(start, end), os, nullptr); |
1532 } | 1553 } |
1533 | 1554 |
1534 void PrintAst(base::AccountingAllocator* allocator, FunctionBody& body) { | 1555 bool PrintAst(base::AccountingAllocator* allocator, const FunctionBody& body, |
| 1556 std::ostream& os, |
| 1557 std::vector<std::tuple<uint32_t, int, int>>* offset_table) { |
1535 Zone zone(allocator); | 1558 Zone zone(allocator); |
1536 SR_WasmDecoder decoder(&zone, nullptr, body); | 1559 SR_WasmDecoder decoder(&zone, nullptr, body); |
1537 | 1560 int line_nr = 0; |
1538 OFStream os(stdout); | |
1539 | 1561 |
1540 // Print the function signature. | 1562 // Print the function signature. |
1541 if (body.sig) { | 1563 if (body.sig) { |
1542 os << "// signature: " << *body.sig << std::endl; | 1564 os << "// signature: " << *body.sig << std::endl; |
| 1565 ++line_nr; |
1543 } | 1566 } |
1544 | 1567 |
1545 // Print the local declarations. | 1568 // Print the local declarations. |
1546 AstLocalDecls decls(&zone); | 1569 AstLocalDecls decls(&zone); |
1547 decoder.DecodeLocalDecls(decls); | 1570 decoder.DecodeLocalDecls(decls); |
1548 const byte* pc = decoder.pc(); | 1571 const byte* pc = decoder.pc(); |
1549 if (body.start != decoder.pc()) { | 1572 if (body.start != decoder.pc()) { |
1550 os << "// locals: "; | 1573 os << "// locals: "; |
1551 for (auto p : decls.local_types) { | 1574 for (auto p : decls.local_types) { |
1552 LocalType type = p.first; | 1575 LocalType type = p.first; |
1553 uint32_t count = p.second; | 1576 uint32_t count = p.second; |
1554 os << " " << count << " " << WasmOpcodes::TypeName(type); | 1577 os << " " << count << " " << WasmOpcodes::TypeName(type); |
1555 } | 1578 } |
1556 os << std::endl; | 1579 os << std::endl; |
1557 | 1580 |
1558 for (const byte* locals = body.start; locals < pc; locals++) { | 1581 for (const byte* locals = body.start; locals < pc; locals++) { |
1559 printf(" 0x%02x,", *locals); | 1582 os << (locals == body.start ? "0x" : " 0x") << AsHex(*locals, 2) << ","; |
1560 } | 1583 } |
1561 os << std::endl; | 1584 os << std::endl; |
| 1585 ++line_nr; |
1562 } | 1586 } |
1563 | 1587 |
1564 os << "// body: \n"; | 1588 os << "// body: " << std::endl; |
1565 int control_depth = 0; | 1589 ++line_nr; |
| 1590 unsigned control_depth = 0; |
1566 while (pc < body.end) { | 1591 while (pc < body.end) { |
1567 size_t length = decoder.OpcodeLength(pc); | 1592 size_t length = decoder.OpcodeLength(pc); |
1568 | 1593 |
1569 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); | 1594 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); |
1570 if (opcode == kExprElse) control_depth--; | 1595 if (opcode == kExprElse) control_depth--; |
1571 | 1596 |
1572 for (int i = 0; i < control_depth && i < 32; i++) printf(" "); | 1597 int num_whitespaces = control_depth < 32 ? 2 * control_depth : 64; |
1573 printf("k%s,", WasmOpcodes::OpcodeName(opcode)); | 1598 if (offset_table) { |
| 1599 offset_table->push_back( |
| 1600 std::make_tuple(pc - body.start, line_nr, num_whitespaces)); |
| 1601 } |
| 1602 |
| 1603 // 64 whitespaces |
| 1604 const char* padding = |
| 1605 " "; |
| 1606 os.write(padding, num_whitespaces); |
| 1607 os << "k" << WasmOpcodes::OpcodeName(opcode) << ","; |
1574 | 1608 |
1575 for (size_t i = 1; i < length; i++) { | 1609 for (size_t i = 1; i < length; i++) { |
1576 printf(" 0x%02x,", pc[i]); | 1610 os << " " << AsHex(pc[i], 2) << ","; |
1577 } | 1611 } |
1578 | 1612 |
1579 switch (opcode) { | 1613 switch (opcode) { |
1580 case kExprIf: | 1614 case kExprIf: |
1581 case kExprElse: | 1615 case kExprElse: |
1582 case kExprLoop: | 1616 case kExprLoop: |
1583 case kExprBlock: | 1617 case kExprBlock: |
1584 os << " // @" << static_cast<int>(pc - body.start); | 1618 os << " // @" << static_cast<int>(pc - body.start); |
1585 control_depth++; | 1619 control_depth++; |
1586 break; | 1620 break; |
(...skipping 12 matching lines...) Expand all Loading... |
1599 break; | 1633 break; |
1600 } | 1634 } |
1601 case kExprBrTable: { | 1635 case kExprBrTable: { |
1602 BranchTableOperand operand(&decoder, pc); | 1636 BranchTableOperand operand(&decoder, pc); |
1603 os << " // arity=" << operand.arity | 1637 os << " // arity=" << operand.arity |
1604 << " entries=" << operand.table_count; | 1638 << " entries=" << operand.table_count; |
1605 break; | 1639 break; |
1606 } | 1640 } |
1607 case kExprCallIndirect: { | 1641 case kExprCallIndirect: { |
1608 CallIndirectOperand operand(&decoder, pc); | 1642 CallIndirectOperand operand(&decoder, pc); |
1609 if (decoder.Validate(pc, operand)) { | 1643 if (decoder.Complete(pc, operand)) { |
1610 os << " // sig #" << operand.index << ": " << *operand.sig; | 1644 os << " // sig #" << operand.index << ": " << *operand.sig; |
1611 } else { | 1645 } else { |
1612 os << " // arity=" << operand.arity << " sig #" << operand.index; | 1646 os << " // arity=" << operand.arity << " sig #" << operand.index; |
1613 } | 1647 } |
1614 break; | 1648 break; |
1615 } | 1649 } |
1616 case kExprCallImport: { | 1650 case kExprCallImport: { |
1617 CallImportOperand operand(&decoder, pc); | 1651 CallImportOperand operand(&decoder, pc); |
1618 if (decoder.Validate(pc, operand)) { | 1652 if (decoder.Complete(pc, operand)) { |
1619 os << " // import #" << operand.index << ": " << *operand.sig; | 1653 os << " // import #" << operand.index << ": " << *operand.sig; |
1620 } else { | 1654 } else { |
1621 os << " // arity=" << operand.arity << " import #" << operand.index; | 1655 os << " // arity=" << operand.arity << " import #" << operand.index; |
1622 } | 1656 } |
1623 break; | 1657 break; |
1624 } | 1658 } |
1625 case kExprCallFunction: { | 1659 case kExprCallFunction: { |
1626 CallFunctionOperand operand(&decoder, pc); | 1660 CallFunctionOperand operand(&decoder, pc); |
1627 if (decoder.Validate(pc, operand)) { | 1661 if (decoder.Complete(pc, operand)) { |
1628 os << " // function #" << operand.index << ": " << *operand.sig; | 1662 os << " // function #" << operand.index << ": " << *operand.sig; |
1629 } else { | 1663 } else { |
1630 os << " // arity=" << operand.arity << " function #" << operand.index; | 1664 os << " // arity=" << operand.arity << " function #" << operand.index; |
1631 } | 1665 } |
1632 break; | 1666 break; |
1633 } | 1667 } |
1634 case kExprReturn: { | 1668 case kExprReturn: { |
1635 ReturnArityOperand operand(&decoder, pc); | 1669 ReturnArityOperand operand(&decoder, pc); |
1636 os << " // arity=" << operand.arity; | 1670 os << " // arity=" << operand.arity; |
1637 break; | 1671 break; |
1638 } | 1672 } |
1639 default: | 1673 default: |
1640 break; | 1674 break; |
1641 } | 1675 } |
1642 | 1676 |
1643 pc += length; | 1677 pc += length; |
1644 os << std::endl; | 1678 os << std::endl; |
| 1679 ++line_nr; |
1645 } | 1680 } |
| 1681 |
| 1682 return decoder.ok(); |
1646 } | 1683 } |
1647 | 1684 |
1648 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 1685 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
1649 const byte* start, const byte* end) { | 1686 const byte* start, const byte* end) { |
1650 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; | 1687 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; |
1651 SR_WasmDecoder decoder(zone, nullptr, body); | 1688 SR_WasmDecoder decoder(zone, nullptr, body); |
1652 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); | 1689 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); |
1653 } | 1690 } |
1654 | 1691 |
1655 } // namespace wasm | 1692 } // namespace wasm |
1656 } // namespace internal | 1693 } // namespace internal |
1657 } // namespace v8 | 1694 } // namespace v8 |
OLD | NEW |