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...) 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...) 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...) 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...) 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 |