Chromium Code Reviews| 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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 141 operand.type = kAstStmt; | 141 operand.type = kAstStmt; |
| 142 } | 142 } |
| 143 return true; | 143 return true; |
| 144 } | 144 } |
| 145 error(pc, pc + 1, "invalid local index"); | 145 error(pc, pc + 1, "invalid local index"); |
| 146 return false; | 146 return false; |
| 147 } | 147 } |
| 148 | 148 |
| 149 inline bool Validate(const byte* pc, GlobalIndexOperand& operand) { | 149 inline bool Validate(const byte* pc, GlobalIndexOperand& operand) { |
| 150 ModuleEnv* m = module_; | 150 ModuleEnv* m = module_; |
| 151 if (m && m->module && operand.index < m->module->globals.size()) { | 151 if (!m || !m->module) return false; |
|
titzer
2016/06/10 10:57:40
This change means that there will not be an error
Clemens Hammacher
2016/06/13 09:45:17
I changed it to have a Complete() and a Validate()
| |
| 152 if (operand.index < m->module->globals.size()) { | |
| 152 operand.machine_type = m->module->globals[operand.index].type; | 153 operand.machine_type = m->module->globals[operand.index].type; |
| 153 operand.type = WasmOpcodes::LocalTypeFor(operand.machine_type); | 154 operand.type = WasmOpcodes::LocalTypeFor(operand.machine_type); |
| 154 return true; | 155 return true; |
| 155 } | 156 } |
| 156 error(pc, pc + 1, "invalid global index"); | 157 error(pc, pc + 1, "invalid global index"); |
| 157 return false; | 158 return false; |
| 158 } | 159 } |
| 159 | 160 |
| 160 inline bool Validate(const byte* pc, CallFunctionOperand& operand) { | 161 inline bool Validate(const byte* pc, CallFunctionOperand& operand) { |
| 161 ModuleEnv* m = module_; | 162 ModuleEnv* m = module_; |
| 162 if (m && m->module && operand.index < m->module->functions.size()) { | 163 if (!m || !m->module) return false; |
| 164 if (operand.index < m->module->functions.size()) { | |
| 163 operand.sig = m->module->functions[operand.index].sig; | 165 operand.sig = m->module->functions[operand.index].sig; |
| 164 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count()); | 166 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count()); |
| 165 if (operand.arity != expected) { | 167 if (operand.arity != expected) { |
| 166 error(pc, pc + 1, | 168 error(pc, pc + 1, |
| 167 "arity mismatch in direct function call (expected %u, got %u)", | 169 "arity mismatch in direct function call (expected %u, got %u)", |
| 168 expected, operand.arity); | 170 expected, operand.arity); |
| 169 return false; | 171 return false; |
| 170 } | 172 } |
| 171 return true; | 173 return true; |
| 172 } | 174 } |
| 173 error(pc, pc + 1, "invalid function index"); | 175 error(pc, pc + 1, "invalid function index"); |
| 174 return false; | 176 return false; |
| 175 } | 177 } |
| 176 | 178 |
| 177 inline bool Validate(const byte* pc, CallIndirectOperand& operand) { | 179 inline bool Validate(const byte* pc, CallIndirectOperand& operand) { |
| 178 ModuleEnv* m = module_; | 180 ModuleEnv* m = module_; |
| 179 if (m && m->module && operand.index < m->module->signatures.size()) { | 181 if (!m || !m->module) return false; |
| 182 if (operand.index < m->module->signatures.size()) { | |
| 180 operand.sig = m->module->signatures[operand.index]; | 183 operand.sig = m->module->signatures[operand.index]; |
| 181 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count()); | 184 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count()); |
| 182 if (operand.arity != expected) { | 185 if (operand.arity != expected) { |
| 183 error(pc, pc + 1, | 186 error(pc, pc + 1, |
| 184 "arity mismatch in indirect function call (expected %u, got %u)", | 187 "arity mismatch in indirect function call (expected %u, got %u)", |
| 185 expected, operand.arity); | 188 expected, operand.arity); |
| 186 return false; | 189 return false; |
| 187 } | 190 } |
| 188 return true; | 191 return true; |
| 189 } | 192 } |
| 190 error(pc, pc + 1, "invalid signature index"); | 193 error(pc, pc + 1, "invalid signature index"); |
| 191 return false; | 194 return false; |
| 192 } | 195 } |
| 193 | 196 |
| 194 inline bool Validate(const byte* pc, CallImportOperand& operand) { | 197 inline bool Validate(const byte* pc, CallImportOperand& operand) { |
| 195 ModuleEnv* m = module_; | 198 ModuleEnv* m = module_; |
| 196 if (m && m->module && operand.index < m->module->import_table.size()) { | 199 if (!m || !m->module) return false; |
| 200 if (operand.index < m->module->import_table.size()) { | |
| 197 operand.sig = m->module->import_table[operand.index].sig; | 201 operand.sig = m->module->import_table[operand.index].sig; |
| 198 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count()); | 202 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count()); |
| 199 if (operand.arity != expected) { | 203 if (operand.arity != expected) { |
| 200 error(pc, pc + 1, "arity mismatch in import call (expected %u, got %u)", | 204 error(pc, pc + 1, "arity mismatch in import call (expected %u, got %u)", |
| 201 expected, operand.arity); | 205 expected, operand.arity); |
| 202 return false; | 206 return false; |
| 203 } | 207 } |
| 204 return true; | 208 return true; |
| 205 } | 209 } |
| 206 error(pc, pc + 1, "invalid signature index"); | 210 error(pc, pc + 1, "invalid signature index"); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 384 default: | 388 default: |
| 385 return 1; | 389 return 1; |
| 386 } | 390 } |
| 387 } | 391 } |
| 388 }; | 392 }; |
| 389 | 393 |
| 390 // A shift-reduce-parser strategy for decoding Wasm code that uses an explicit | 394 // A shift-reduce-parser strategy for decoding Wasm code that uses an explicit |
| 391 // shift-reduce strategy with multiple internal stacks. | 395 // shift-reduce strategy with multiple internal stacks. |
| 392 class SR_WasmDecoder : public WasmDecoder { | 396 class SR_WasmDecoder : public WasmDecoder { |
| 393 public: | 397 public: |
| 394 SR_WasmDecoder(Zone* zone, TFBuilder* builder, FunctionBody& body) | 398 SR_WasmDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) |
| 395 : WasmDecoder(body.module, body.sig, body.start, body.end), | 399 : WasmDecoder(body.module, body.sig, body.start, body.end), |
| 396 zone_(zone), | 400 zone_(zone), |
| 397 builder_(builder), | 401 builder_(builder), |
| 398 base_(body.base), | 402 base_(body.base), |
| 399 local_type_vec_(zone), | 403 local_type_vec_(zone), |
| 400 stack_(zone), | 404 stack_(zone), |
| 401 control_(zone) { | 405 control_(zone) { |
| 402 local_types_ = &local_type_vec_; | 406 local_types_ = &local_type_vec_; |
| 403 } | 407 } |
| 404 | 408 |
| (...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1519 WasmDecoder decoder(nullptr, nullptr, pc, end); | 1523 WasmDecoder decoder(nullptr, nullptr, pc, end); |
| 1520 return decoder.OpcodeLength(pc); | 1524 return decoder.OpcodeLength(pc); |
| 1521 } | 1525 } |
| 1522 | 1526 |
| 1523 int OpcodeArity(const byte* pc, const byte* end) { | 1527 int OpcodeArity(const byte* pc, const byte* end) { |
| 1524 WasmDecoder decoder(nullptr, nullptr, pc, end); | 1528 WasmDecoder decoder(nullptr, nullptr, pc, end); |
| 1525 return decoder.OpcodeArity(pc); | 1529 return decoder.OpcodeArity(pc); |
| 1526 } | 1530 } |
| 1527 | 1531 |
| 1528 void PrintAstForDebugging(const byte* start, const byte* end) { | 1532 void PrintAstForDebugging(const byte* start, const byte* end) { |
| 1529 FunctionBody body = {nullptr, nullptr, start, start, end}; | |
| 1530 base::AccountingAllocator allocator; | 1533 base::AccountingAllocator allocator; |
| 1531 PrintAst(&allocator, body); | 1534 OFStream os(stdout); |
| 1535 PrintAst(&allocator, FunctionBody::ForTesting(start, end), os); | |
| 1532 } | 1536 } |
| 1533 | 1537 |
| 1534 void PrintAst(base::AccountingAllocator* allocator, FunctionBody& body) { | 1538 bool PrintAst(base::AccountingAllocator* allocator, const FunctionBody& body, |
| 1539 std::ostream& os, | |
| 1540 std::function<void(uint32_t)> instruction_callback) { | |
| 1535 Zone zone(allocator); | 1541 Zone zone(allocator); |
| 1536 SR_WasmDecoder decoder(&zone, nullptr, body); | 1542 SR_WasmDecoder decoder(&zone, nullptr, body); |
| 1537 | 1543 |
| 1538 OFStream os(stdout); | |
| 1539 | |
| 1540 // Print the function signature. | 1544 // Print the function signature. |
| 1541 if (body.sig) { | 1545 if (body.sig) { |
| 1542 os << "// signature: " << *body.sig << std::endl; | 1546 os << "// signature: " << *body.sig << std::endl; |
| 1543 } | 1547 } |
| 1544 | 1548 |
| 1545 // Print the local declarations. | 1549 // Print the local declarations. |
| 1546 AstLocalDecls decls(&zone); | 1550 AstLocalDecls decls(&zone); |
| 1547 decoder.DecodeLocalDecls(decls); | 1551 decoder.DecodeLocalDecls(decls); |
| 1548 const byte* pc = decoder.pc(); | 1552 const byte* pc = decoder.pc(); |
| 1549 if (body.start != decoder.pc()) { | 1553 if (body.start != decoder.pc()) { |
| 1550 os << "// locals: "; | 1554 os << "// locals: "; |
| 1551 for (auto p : decls.local_types) { | 1555 for (auto p : decls.local_types) { |
| 1552 LocalType type = p.first; | 1556 LocalType type = p.first; |
| 1553 uint32_t count = p.second; | 1557 uint32_t count = p.second; |
| 1554 os << " " << count << " " << WasmOpcodes::TypeName(type); | 1558 os << " " << count << " " << WasmOpcodes::TypeName(type); |
| 1555 } | 1559 } |
| 1556 os << std::endl; | 1560 os << std::endl; |
| 1557 | 1561 |
| 1558 for (const byte* locals = body.start; locals < pc; locals++) { | 1562 for (const byte* locals = body.start; locals < pc; locals++) { |
| 1559 printf(" 0x%02x,", *locals); | 1563 os << (locals == body.start ? "0x" : " 0x") << AsHex(*locals, 2) << ","; |
| 1560 } | 1564 } |
| 1561 os << std::endl; | 1565 os << std::endl; |
| 1562 } | 1566 } |
| 1563 | 1567 |
| 1564 os << "// body: \n"; | 1568 os << "// body: \n"; |
| 1565 int control_depth = 0; | 1569 unsigned control_depth = 0; |
| 1566 while (pc < body.end) { | 1570 while (pc < body.end) { |
| 1567 size_t length = decoder.OpcodeLength(pc); | 1571 size_t length = decoder.OpcodeLength(pc); |
| 1568 | 1572 |
| 1569 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); | 1573 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); |
| 1570 if (opcode == kExprElse) control_depth--; | 1574 if (opcode == kExprElse) control_depth--; |
| 1571 | 1575 |
| 1572 for (int i = 0; i < control_depth && i < 32; i++) printf(" "); | 1576 // 32 whitespaces |
| 1573 printf("k%s,", WasmOpcodes::OpcodeName(opcode)); | 1577 const char* padding = " "; |
| 1578 os.write(padding, control_depth < 32 ? control_depth : 32); | |
| 1579 if (instruction_callback) { | |
| 1580 instruction_callback(static_cast<int>(pc - body.start)); | |
| 1581 } | |
| 1582 os << "k" << WasmOpcodes::OpcodeName(opcode) << ","; | |
| 1574 | 1583 |
| 1575 for (size_t i = 1; i < length; i++) { | 1584 for (size_t i = 1; i < length; i++) { |
| 1576 printf(" 0x%02x,", pc[i]); | 1585 os << " " << AsHex(pc[i], 2) << ","; |
| 1577 } | 1586 } |
| 1578 | 1587 |
| 1579 switch (opcode) { | 1588 switch (opcode) { |
| 1580 case kExprIf: | 1589 case kExprIf: |
| 1581 case kExprElse: | 1590 case kExprElse: |
| 1582 case kExprLoop: | 1591 case kExprLoop: |
| 1583 case kExprBlock: | 1592 case kExprBlock: |
| 1584 os << " // @" << static_cast<int>(pc - body.start); | 1593 os << " // @" << static_cast<int>(pc - body.start); |
| 1585 control_depth++; | 1594 control_depth++; |
| 1586 break; | 1595 break; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1636 os << " // arity=" << operand.arity; | 1645 os << " // arity=" << operand.arity; |
| 1637 break; | 1646 break; |
| 1638 } | 1647 } |
| 1639 default: | 1648 default: |
| 1640 break; | 1649 break; |
| 1641 } | 1650 } |
| 1642 | 1651 |
| 1643 pc += length; | 1652 pc += length; |
| 1644 os << std::endl; | 1653 os << std::endl; |
| 1645 } | 1654 } |
| 1655 | |
| 1656 return decoder.ok(); | |
| 1646 } | 1657 } |
| 1647 | 1658 |
| 1648 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 1659 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
| 1649 const byte* start, const byte* end) { | 1660 const byte* start, const byte* end) { |
| 1650 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; | 1661 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; |
| 1651 SR_WasmDecoder decoder(zone, nullptr, body); | 1662 SR_WasmDecoder decoder(zone, nullptr, body); |
| 1652 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); | 1663 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); |
| 1653 } | 1664 } |
| 1654 | 1665 |
| 1655 } // namespace wasm | 1666 } // namespace wasm |
| 1656 } // namespace internal | 1667 } // namespace internal |
| 1657 } // namespace v8 | 1668 } // namespace v8 |
| OLD | NEW |