| 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 13 matching lines...) Expand all Loading... |
| 24 | 24 |
| 25 #if DEBUG | 25 #if DEBUG |
| 26 #define TRACE(...) \ | 26 #define TRACE(...) \ |
| 27 do { \ | 27 do { \ |
| 28 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \ | 28 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \ |
| 29 } while (false) | 29 } while (false) |
| 30 #else | 30 #else |
| 31 #define TRACE(...) | 31 #define TRACE(...) |
| 32 #endif | 32 #endif |
| 33 | 33 |
| 34 // The root of a decoded tree. | |
| 35 struct Tree { | |
| 36 LocalType type; // tree type. | |
| 37 uint32_t count; // number of children. | |
| 38 const byte* pc; // start of the syntax tree. | |
| 39 TFNode* node; // node in the TurboFan graph. | |
| 40 Tree* children[1]; // pointers to children. | |
| 41 | |
| 42 WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc); } | |
| 43 }; | |
| 44 | |
| 45 // An SsaEnv environment carries the current local variable renaming | 34 // An SsaEnv environment carries the current local variable renaming |
| 46 // as well as the current effect and control dependency in the TF graph. | 35 // as well as the current effect and control dependency in the TF graph. |
| 47 // It maintains a control state that tracks whether the environment | 36 // It maintains a control state that tracks whether the environment |
| 48 // is reachable, has reached a control end, or has been merged. | 37 // is reachable, has reached a control end, or has been merged. |
| 49 struct SsaEnv { | 38 struct SsaEnv { |
| 50 enum State { kControlEnd, kUnreachable, kReached, kMerged }; | 39 enum State { kControlEnd, kUnreachable, kReached, kMerged }; |
| 51 | 40 |
| 52 State state; | 41 State state; |
| 53 TFNode* control; | 42 TFNode* control; |
| 54 TFNode* effect; | 43 TFNode* effect; |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 ReturnArityOperand operand(this, pc); | 391 ReturnArityOperand operand(this, pc); |
| 403 return 1 + operand.length; | 392 return 1 + operand.length; |
| 404 } | 393 } |
| 405 | 394 |
| 406 default: | 395 default: |
| 407 return 1; | 396 return 1; |
| 408 } | 397 } |
| 409 } | 398 } |
| 410 }; | 399 }; |
| 411 | 400 |
| 412 // A shift-reduce-parser strategy for decoding Wasm code that uses an explicit | 401 // The full WASM decoder for bytecode. Both verifies bytecode and generates |
| 413 // shift-reduce strategy with multiple internal stacks. | 402 // a TurboFan IR graph. |
| 414 class SR_WasmDecoder : public WasmDecoder { | 403 class WasmFullDecoder : public WasmDecoder { |
| 415 public: | 404 public: |
| 416 SR_WasmDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) | 405 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) |
| 417 : WasmDecoder(body.module, body.sig, body.start, body.end), | 406 : WasmDecoder(body.module, body.sig, body.start, body.end), |
| 418 zone_(zone), | 407 zone_(zone), |
| 419 builder_(builder), | 408 builder_(builder), |
| 420 base_(body.base), | 409 base_(body.base), |
| 421 local_type_vec_(zone), | 410 local_type_vec_(zone), |
| 422 stack_(zone), | 411 stack_(zone), |
| 423 control_(zone) { | 412 control_(zone) { |
| 424 local_types_ = &local_type_vec_; | 413 local_types_ = &local_type_vec_; |
| 425 } | 414 } |
| 426 | 415 |
| (...skipping 1061 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1488 DCHECK_EQ(pc_ - start_, offset); // overflows cannot happen | 1477 DCHECK_EQ(pc_ - start_, offset); // overflows cannot happen |
| 1489 return offset; | 1478 return offset; |
| 1490 } | 1479 } |
| 1491 }; | 1480 }; |
| 1492 | 1481 |
| 1493 bool DecodeLocalDecls(AstLocalDecls& decls, const byte* start, | 1482 bool DecodeLocalDecls(AstLocalDecls& decls, const byte* start, |
| 1494 const byte* end) { | 1483 const byte* end) { |
| 1495 base::AccountingAllocator allocator; | 1484 base::AccountingAllocator allocator; |
| 1496 Zone tmp(&allocator); | 1485 Zone tmp(&allocator); |
| 1497 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; | 1486 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; |
| 1498 SR_WasmDecoder decoder(&tmp, nullptr, body); | 1487 WasmFullDecoder decoder(&tmp, nullptr, body); |
| 1499 return decoder.DecodeLocalDecls(decls); | 1488 return decoder.DecodeLocalDecls(decls); |
| 1500 } | 1489 } |
| 1501 | 1490 |
| 1502 TreeResult VerifyWasmCode(base::AccountingAllocator* allocator, | 1491 DecodeResult VerifyWasmCode(base::AccountingAllocator* allocator, |
| 1503 FunctionBody& body) { | 1492 FunctionBody& body) { |
| 1504 Zone zone(allocator); | 1493 Zone zone(allocator); |
| 1505 SR_WasmDecoder decoder(&zone, nullptr, body); | 1494 WasmFullDecoder decoder(&zone, nullptr, body); |
| 1506 decoder.Decode(); | 1495 decoder.Decode(); |
| 1507 return decoder.toResult<Tree*>(nullptr); | 1496 return decoder.toResult<DecodeStruct*>(nullptr); |
| 1508 } | 1497 } |
| 1509 | 1498 |
| 1510 TreeResult BuildTFGraph(base::AccountingAllocator* allocator, | 1499 DecodeResult BuildTFGraph(base::AccountingAllocator* allocator, |
| 1511 TFBuilder* builder, FunctionBody& body) { | 1500 TFBuilder* builder, FunctionBody& body) { |
| 1512 Zone zone(allocator); | 1501 Zone zone(allocator); |
| 1513 SR_WasmDecoder decoder(&zone, builder, body); | 1502 WasmFullDecoder decoder(&zone, builder, body); |
| 1514 decoder.Decode(); | 1503 decoder.Decode(); |
| 1515 return decoder.toResult<Tree*>(nullptr); | 1504 return decoder.toResult<DecodeStruct*>(nullptr); |
| 1516 } | |
| 1517 | |
| 1518 std::ostream& operator<<(std::ostream& os, const Tree& tree) { | |
| 1519 if (tree.pc == nullptr) { | |
| 1520 os << "null"; | |
| 1521 return os; | |
| 1522 } | |
| 1523 PrintF("%s", WasmOpcodes::OpcodeName(tree.opcode())); | |
| 1524 if (tree.count > 0) os << "("; | |
| 1525 for (uint32_t i = 0; i < tree.count; ++i) { | |
| 1526 if (i > 0) os << ", "; | |
| 1527 os << *tree.children[i]; | |
| 1528 } | |
| 1529 if (tree.count > 0) os << ")"; | |
| 1530 return os; | |
| 1531 } | 1505 } |
| 1532 | 1506 |
| 1533 unsigned OpcodeLength(const byte* pc, const byte* end) { | 1507 unsigned OpcodeLength(const byte* pc, const byte* end) { |
| 1534 WasmDecoder decoder(nullptr, nullptr, pc, end); | 1508 WasmDecoder decoder(nullptr, nullptr, pc, end); |
| 1535 return decoder.OpcodeLength(pc); | 1509 return decoder.OpcodeLength(pc); |
| 1536 } | 1510 } |
| 1537 | 1511 |
| 1538 unsigned OpcodeArity(const byte* pc, const byte* end) { | 1512 unsigned OpcodeArity(const byte* pc, const byte* end) { |
| 1539 WasmDecoder decoder(nullptr, nullptr, pc, end); | 1513 WasmDecoder decoder(nullptr, nullptr, pc, end); |
| 1540 return decoder.OpcodeArity(pc); | 1514 return decoder.OpcodeArity(pc); |
| 1541 } | 1515 } |
| 1542 | 1516 |
| 1543 void PrintAstForDebugging(const byte* start, const byte* end) { | 1517 void PrintAstForDebugging(const byte* start, const byte* end) { |
| 1544 base::AccountingAllocator allocator; | 1518 base::AccountingAllocator allocator; |
| 1545 OFStream os(stdout); | 1519 OFStream os(stdout); |
| 1546 PrintAst(&allocator, FunctionBodyForTesting(start, end), os, nullptr); | 1520 PrintAst(&allocator, FunctionBodyForTesting(start, end), os, nullptr); |
| 1547 } | 1521 } |
| 1548 | 1522 |
| 1549 bool PrintAst(base::AccountingAllocator* allocator, const FunctionBody& body, | 1523 bool PrintAst(base::AccountingAllocator* allocator, const FunctionBody& body, |
| 1550 std::ostream& os, | 1524 std::ostream& os, |
| 1551 std::vector<std::tuple<uint32_t, int, int>>* offset_table) { | 1525 std::vector<std::tuple<uint32_t, int, int>>* offset_table) { |
| 1552 Zone zone(allocator); | 1526 Zone zone(allocator); |
| 1553 SR_WasmDecoder decoder(&zone, nullptr, body); | 1527 WasmFullDecoder decoder(&zone, nullptr, body); |
| 1554 int line_nr = 0; | 1528 int line_nr = 0; |
| 1555 | 1529 |
| 1556 // Print the function signature. | 1530 // Print the function signature. |
| 1557 if (body.sig) { | 1531 if (body.sig) { |
| 1558 os << "// signature: " << *body.sig << std::endl; | 1532 os << "// signature: " << *body.sig << std::endl; |
| 1559 ++line_nr; | 1533 ++line_nr; |
| 1560 } | 1534 } |
| 1561 | 1535 |
| 1562 // Print the local declarations. | 1536 // Print the local declarations. |
| 1563 AstLocalDecls decls(&zone); | 1537 AstLocalDecls decls(&zone); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1672 os << std::endl; | 1646 os << std::endl; |
| 1673 ++line_nr; | 1647 ++line_nr; |
| 1674 } | 1648 } |
| 1675 | 1649 |
| 1676 return decoder.ok(); | 1650 return decoder.ok(); |
| 1677 } | 1651 } |
| 1678 | 1652 |
| 1679 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 1653 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
| 1680 const byte* start, const byte* end) { | 1654 const byte* start, const byte* end) { |
| 1681 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; | 1655 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; |
| 1682 SR_WasmDecoder decoder(zone, nullptr, body); | 1656 WasmFullDecoder decoder(zone, nullptr, body); |
| 1683 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); | 1657 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); |
| 1684 } | 1658 } |
| 1685 | 1659 |
| 1686 } // namespace wasm | 1660 } // namespace wasm |
| 1687 } // namespace internal | 1661 } // namespace internal |
| 1688 } // namespace v8 | 1662 } // namespace v8 |
| OLD | NEW |