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 |