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/handles.h" | 7 #include "src/handles.h" |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 #include "src/zone-containers.h" | 9 #include "src/zone-containers.h" |
10 | 10 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 } | 52 } |
53 | 53 |
54 void EmitVarInt(byte** b, size_t val) { | 54 void EmitVarInt(byte** b, size_t val) { |
55 LEBHelper::write_u32v(b, static_cast<uint32_t>(val)); | 55 LEBHelper::write_u32v(b, static_cast<uint32_t>(val)); |
56 } | 56 } |
57 | 57 |
58 // Sections all start with a size, but it's unknown at the start. | 58 // Sections all start with a size, but it's unknown at the start. |
59 // We generate a large varint which we then fixup later when the size is known. | 59 // We generate a large varint which we then fixup later when the size is known. |
60 // | 60 // |
61 // TODO(jfb) Not strictly necessary since sizes are calculated ahead of time. | 61 // TODO(jfb) Not strictly necessary since sizes are calculated ahead of time. |
62 const size_t padded_varint = 5; | 62 const size_t kPaddedVarintSize = 5; |
63 | 63 |
64 void FixupSection(byte* start, byte* end) { | 64 void FixupSection(byte* start, byte* end) { |
65 // Same as LEBHelper::write_u32v, but fixed-width with zeroes in the MSBs. | 65 // Same as LEBHelper::write_u32v, but fixed-width with zeroes in the MSBs. |
66 size_t val = end - start - padded_varint; | 66 size_t val = end - start - kPaddedVarintSize; |
67 TRACE(" fixup %u\n", (unsigned)val); | 67 TRACE(" fixup %u\n", (unsigned)val); |
68 for (size_t pos = 0; pos != padded_varint; ++pos) { | 68 for (size_t pos = 0; pos != kPaddedVarintSize; ++pos) { |
69 size_t next = val >> 7; | 69 size_t next = val >> 7; |
70 byte out = static_cast<byte>(val & 0x7f); | 70 byte out = static_cast<byte>(val & 0x7f); |
71 if (pos != padded_varint - 1) { | 71 if (pos != kPaddedVarintSize - 1) { |
72 *(start++) = 0x80 | out; | 72 *(start++) = 0x80 | out; |
73 val = next; | 73 val = next; |
74 } else { | 74 } else { |
75 *(start++) = out; | 75 *(start++) = out; |
76 // TODO(jfb) check that the pre-allocated fixup size isn't overflowed. | 76 // TODO(jfb) check that the pre-allocated fixup size isn't overflowed. |
77 } | 77 } |
78 } | 78 } |
79 } | 79 } |
80 | 80 |
81 // Returns the start of the section, where the section VarInt size is. | 81 // Returns the start of the section, where the section VarInt size is. |
82 byte* EmitSection(WasmSection::Code code, byte** b) { | 82 byte* EmitSection(WasmSection::Code code, byte** b) { |
| 83 // Emit a placeholder for the length. |
83 byte* start = *b; | 84 byte* start = *b; |
84 const char* name = WasmSection::getName(code); | 85 for (size_t padding = 0; padding != kPaddedVarintSize; ++padding) { |
85 size_t length = WasmSection::getNameLength(code); | |
86 TRACE("emit section: %s\n", name); | |
87 for (size_t padding = 0; padding != padded_varint; ++padding) { | |
88 EmitUint8(b, 0xff); // Will get fixed up later. | 86 EmitUint8(b, 0xff); // Will get fixed up later. |
89 } | 87 } |
| 88 // Emit the section name. |
| 89 const char* name = WasmSection::getName(code); |
| 90 TRACE("emit section: %s\n", name); |
| 91 size_t length = WasmSection::getNameLength(code); |
90 EmitVarInt(b, length); // Section name string size. | 92 EmitVarInt(b, length); // Section name string size. |
91 for (size_t i = 0; i != length; ++i) EmitUint8(b, name[i]); | 93 for (size_t i = 0; i != length; ++i) EmitUint8(b, name[i]); |
| 94 |
92 return start; | 95 return start; |
93 } | 96 } |
94 } // namespace | 97 } // namespace |
95 | 98 |
96 struct WasmFunctionBuilder::Type { | 99 struct WasmFunctionBuilder::Type { |
97 bool param_; | 100 bool param_; |
98 LocalType type_; | 101 LocalType type_; |
99 }; | 102 }; |
100 | 103 |
101 | 104 |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 size_t body_size; | 544 size_t body_size; |
542 | 545 |
543 size_t total() { return header_size + body_size; } | 546 size_t total() { return header_size + body_size; } |
544 | 547 |
545 void Add(size_t header, size_t body) { | 548 void Add(size_t header, size_t body) { |
546 header_size += header; | 549 header_size += header; |
547 body_size += body; | 550 body_size += body; |
548 } | 551 } |
549 | 552 |
550 void AddSection(WasmSection::Code code, size_t other_size) { | 553 void AddSection(WasmSection::Code code, size_t other_size) { |
551 Add(padded_varint + | 554 Add(kPaddedVarintSize + |
552 LEBHelper::sizeof_u32v(WasmSection::getNameLength(code)) + | 555 LEBHelper::sizeof_u32v(WasmSection::getNameLength(code)) + |
553 WasmSection::getNameLength(code), | 556 WasmSection::getNameLength(code), |
554 0); | 557 0); |
555 if (other_size) Add(LEBHelper::sizeof_u32v(other_size), 0); | 558 if (other_size) Add(LEBHelper::sizeof_u32v(other_size), 0); |
556 } | 559 } |
557 }; | 560 }; |
558 | 561 |
559 WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const { | 562 WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const { |
560 Sizes sizes = {0, 0}; | 563 Sizes sizes = {0, 0}; |
561 | 564 |
562 sizes.Add(2 * sizeof(uint32_t), 0); // header | 565 sizes.Add(2 * sizeof(uint32_t), 0); // header |
563 | 566 |
564 sizes.AddSection(WasmSection::Code::Memory, 0); | |
565 sizes.Add(kDeclMemorySize, 0); | |
566 TRACE("Size after memory: %u, %u\n", (unsigned)sizes.header_size, | |
567 (unsigned)sizes.body_size); | |
568 | |
569 if (globals_.size() > 0) { | 567 if (globals_.size() > 0) { |
570 sizes.AddSection(WasmSection::Code::Globals, globals_.size()); | 568 sizes.AddSection(WasmSection::Code::Globals, globals_.size()); |
571 /* These globals never have names, so are always 3 bytes. */ | 569 /* These globals never have names, so are always 3 bytes. */ |
572 sizes.Add(3 * globals_.size(), 0); | 570 sizes.Add(3 * globals_.size(), 0); |
573 TRACE("Size after globals: %u, %u\n", (unsigned)sizes.header_size, | 571 TRACE("Size after globals: %u, %u\n", (unsigned)sizes.header_size, |
574 (unsigned)sizes.body_size); | 572 (unsigned)sizes.body_size); |
575 } | 573 } |
576 | 574 |
577 if (signatures_.size() > 0) { | 575 if (signatures_.size() > 0) { |
578 sizes.AddSection(WasmSection::Code::Signatures, signatures_.size()); | 576 sizes.AddSection(WasmSection::Code::Signatures, signatures_.size()); |
579 for (auto sig : signatures_) { | 577 for (auto sig : signatures_) { |
580 sizes.Add(1 + LEBHelper::sizeof_u32v(sig->parameter_count()) + | 578 sizes.Add(1 + LEBHelper::sizeof_u32v(sig->parameter_count()) + |
581 sig->parameter_count(), | 579 sig->parameter_count(), |
582 0); | 580 0); |
583 } | 581 } |
584 TRACE("Size after signatures: %u, %u\n", (unsigned)sizes.header_size, | 582 TRACE("Size after signatures: %u, %u\n", (unsigned)sizes.header_size, |
585 (unsigned)sizes.body_size); | 583 (unsigned)sizes.body_size); |
586 } | 584 } |
587 | 585 |
588 if (functions_.size() > 0) { | 586 if (functions_.size() > 0) { |
589 sizes.AddSection(WasmSection::Code::Functions, functions_.size()); | 587 sizes.AddSection(WasmSection::Code::Functions, functions_.size()); |
590 for (auto function : functions_) { | 588 for (auto function : functions_) { |
591 sizes.Add(function->HeaderSize() + function->BodySize(), | 589 sizes.Add(function->HeaderSize() + function->BodySize(), |
592 function->NameSize()); | 590 function->NameSize()); |
593 } | 591 } |
594 TRACE("Size after functions: %u, %u\n", (unsigned)sizes.header_size, | 592 TRACE("Size after functions: %u, %u\n", (unsigned)sizes.header_size, |
595 (unsigned)sizes.body_size); | 593 (unsigned)sizes.body_size); |
596 } | 594 } |
597 | 595 |
| 596 if (indirect_functions_.size() > 0) { |
| 597 sizes.AddSection(WasmSection::Code::FunctionTable, |
| 598 indirect_functions_.size()); |
| 599 for (auto function_index : indirect_functions_) { |
| 600 sizes.Add(LEBHelper::sizeof_u32v(function_index), 0); |
| 601 } |
| 602 TRACE("Size after indirect functions: %u, %u\n", |
| 603 (unsigned)sizes.header_size, (unsigned)sizes.body_size); |
| 604 } |
| 605 |
| 606 sizes.AddSection(WasmSection::Code::Memory, 0); |
| 607 sizes.Add(kDeclMemorySize, 0); |
| 608 TRACE("Size after memory: %u, %u\n", (unsigned)sizes.header_size, |
| 609 (unsigned)sizes.body_size); |
| 610 |
598 if (start_function_index_ >= 0) { | 611 if (start_function_index_ >= 0) { |
599 sizes.AddSection(WasmSection::Code::StartFunction, 0); | 612 sizes.AddSection(WasmSection::Code::StartFunction, 0); |
600 sizes.Add(LEBHelper::sizeof_u32v(start_function_index_), 0); | 613 sizes.Add(LEBHelper::sizeof_u32v(start_function_index_), 0); |
601 TRACE("Size after start: %u, %u\n", (unsigned)sizes.header_size, | 614 TRACE("Size after start: %u, %u\n", (unsigned)sizes.header_size, |
602 (unsigned)sizes.body_size); | 615 (unsigned)sizes.body_size); |
603 } | 616 } |
604 | 617 |
605 if (data_segments_.size() > 0) { | 618 if (data_segments_.size() > 0) { |
606 sizes.AddSection(WasmSection::Code::DataSegments, data_segments_.size()); | 619 sizes.AddSection(WasmSection::Code::DataSegments, data_segments_.size()); |
607 for (auto segment : data_segments_) { | 620 for (auto segment : data_segments_) { |
608 sizes.Add(segment->HeaderSize(), segment->BodySize()); | 621 sizes.Add(segment->HeaderSize(), segment->BodySize()); |
609 } | 622 } |
610 TRACE("Size after data segments: %u, %u\n", (unsigned)sizes.header_size, | 623 TRACE("Size after data segments: %u, %u\n", (unsigned)sizes.header_size, |
611 (unsigned)sizes.body_size); | 624 (unsigned)sizes.body_size); |
612 } | 625 } |
613 | 626 |
614 if (indirect_functions_.size() > 0) { | |
615 sizes.AddSection(WasmSection::Code::FunctionTable, | |
616 indirect_functions_.size()); | |
617 for (auto function_index : indirect_functions_) { | |
618 sizes.Add(LEBHelper::sizeof_u32v(function_index), 0); | |
619 } | |
620 TRACE("Size after indirect functions: %u, %u\n", | |
621 (unsigned)sizes.header_size, (unsigned)sizes.body_size); | |
622 } | |
623 | |
624 if (sizes.body_size > 0) { | 627 if (sizes.body_size > 0) { |
625 sizes.AddSection(WasmSection::Code::End, 0); | 628 sizes.AddSection(WasmSection::Code::End, 0); |
626 TRACE("Size after end: %u, %u\n", (unsigned)sizes.header_size, | 629 TRACE("Size after end: %u, %u\n", (unsigned)sizes.header_size, |
627 (unsigned)sizes.body_size); | 630 (unsigned)sizes.body_size); |
628 } | 631 } |
629 | 632 |
630 ZoneVector<uint8_t> buffer_vector(sizes.total(), zone); | 633 ZoneVector<uint8_t> buffer_vector(sizes.total(), zone); |
631 byte* buffer = &buffer_vector[0]; | 634 byte* buffer = &buffer_vector[0]; |
632 byte* header = buffer; | 635 byte* header = buffer; |
633 byte* body = buffer + sizes.header_size; | 636 byte* body = buffer + sizes.header_size; |
634 | 637 |
635 // -- emit magic ------------------------------------------------------------- | 638 // -- emit magic ------------------------------------------------------------- |
636 TRACE("emit magic\n"); | 639 TRACE("emit magic\n"); |
637 EmitUint32(&header, kWasmMagic); | 640 EmitUint32(&header, kWasmMagic); |
638 EmitUint32(&header, kWasmVersion); | 641 EmitUint32(&header, kWasmVersion); |
639 | 642 |
640 // -- emit memory declaration ------------------------------------------------ | |
641 { | |
642 byte* section = EmitSection(WasmSection::Code::Memory, &header); | |
643 EmitVarInt(&header, 16); // min memory size | |
644 EmitVarInt(&header, 16); // max memory size | |
645 EmitUint8(&header, 0); // memory export | |
646 static_assert(kDeclMemorySize == 3, "memory size must match emit above"); | |
647 FixupSection(section, header); | |
648 } | |
649 | |
650 // -- emit globals ----------------------------------------------------------- | 643 // -- emit globals ----------------------------------------------------------- |
651 if (globals_.size() > 0) { | 644 if (globals_.size() > 0) { |
652 byte* section = EmitSection(WasmSection::Code::Globals, &header); | 645 byte* section = EmitSection(WasmSection::Code::Globals, &header); |
653 EmitVarInt(&header, globals_.size()); | 646 EmitVarInt(&header, globals_.size()); |
654 | 647 |
655 for (auto global : globals_) { | 648 for (auto global : globals_) { |
656 EmitVarInt(&header, 0); // Length of the global name. | 649 EmitVarInt(&header, 0); // Length of the global name. |
657 EmitUint8(&header, WasmOpcodes::MemTypeCodeFor(global.first)); | 650 EmitUint8(&header, WasmOpcodes::MemTypeCodeFor(global.first)); |
658 EmitUint8(&header, global.second); | 651 EmitUint8(&header, global.second); |
659 } | 652 } |
(...skipping 23 matching lines...) Expand all Loading... |
683 if (functions_.size() > 0) { | 676 if (functions_.size() > 0) { |
684 byte* section = EmitSection(WasmSection::Code::Functions, &header); | 677 byte* section = EmitSection(WasmSection::Code::Functions, &header); |
685 EmitVarInt(&header, functions_.size()); | 678 EmitVarInt(&header, functions_.size()); |
686 | 679 |
687 for (auto func : functions_) { | 680 for (auto func : functions_) { |
688 func->Serialize(buffer, &header, &body); | 681 func->Serialize(buffer, &header, &body); |
689 } | 682 } |
690 FixupSection(section, header); | 683 FixupSection(section, header); |
691 } | 684 } |
692 | 685 |
| 686 // -- emit function table ---------------------------------------------------- |
| 687 if (indirect_functions_.size() > 0) { |
| 688 byte* section = EmitSection(WasmSection::Code::FunctionTable, &header); |
| 689 EmitVarInt(&header, indirect_functions_.size()); |
| 690 |
| 691 for (auto index : indirect_functions_) { |
| 692 EmitVarInt(&header, index); |
| 693 } |
| 694 FixupSection(section, header); |
| 695 } |
| 696 |
| 697 // -- emit memory declaration ------------------------------------------------ |
| 698 { |
| 699 byte* section = EmitSection(WasmSection::Code::Memory, &header); |
| 700 EmitVarInt(&header, 16); // min memory size |
| 701 EmitVarInt(&header, 16); // max memory size |
| 702 EmitUint8(&header, 0); // memory export |
| 703 static_assert(kDeclMemorySize == 3, "memory size must match emit above"); |
| 704 FixupSection(section, header); |
| 705 } |
| 706 |
693 // -- emit start function index ---------------------------------------------- | 707 // -- emit start function index ---------------------------------------------- |
694 if (start_function_index_ >= 0) { | 708 if (start_function_index_ >= 0) { |
695 byte* section = EmitSection(WasmSection::Code::StartFunction, &header); | 709 byte* section = EmitSection(WasmSection::Code::StartFunction, &header); |
696 EmitVarInt(&header, start_function_index_); | 710 EmitVarInt(&header, start_function_index_); |
697 FixupSection(section, header); | 711 FixupSection(section, header); |
698 } | 712 } |
699 | 713 |
700 // -- emit data segments ----------------------------------------------------- | 714 // -- emit data segments ----------------------------------------------------- |
701 if (data_segments_.size() > 0) { | 715 if (data_segments_.size() > 0) { |
702 byte* section = EmitSection(WasmSection::Code::DataSegments, &header); | 716 byte* section = EmitSection(WasmSection::Code::DataSegments, &header); |
703 EmitVarInt(&header, data_segments_.size()); | 717 EmitVarInt(&header, data_segments_.size()); |
704 | 718 |
705 for (auto segment : data_segments_) { | 719 for (auto segment : data_segments_) { |
706 segment->Serialize(buffer, &header, &body); | 720 segment->Serialize(buffer, &header, &body); |
707 } | 721 } |
708 FixupSection(section, header); | 722 FixupSection(section, header); |
709 } | 723 } |
710 | 724 |
711 // -- emit function table ---------------------------------------------------- | |
712 if (indirect_functions_.size() > 0) { | |
713 byte* section = EmitSection(WasmSection::Code::FunctionTable, &header); | |
714 EmitVarInt(&header, indirect_functions_.size()); | |
715 | |
716 for (auto index : indirect_functions_) { | |
717 EmitVarInt(&header, index); | |
718 } | |
719 FixupSection(section, header); | |
720 } | |
721 | |
722 if (sizes.body_size > 0) { | 725 if (sizes.body_size > 0) { |
723 byte* section = EmitSection(WasmSection::Code::End, &header); | 726 byte* section = EmitSection(WasmSection::Code::End, &header); |
724 FixupSection(section, header); | 727 FixupSection(section, header); |
725 } | 728 } |
726 | 729 |
727 return new (zone) WasmModuleIndex(buffer, buffer + sizes.total()); | 730 return new (zone) WasmModuleIndex(buffer, buffer + sizes.total()); |
728 } | 731 } |
729 } // namespace wasm | 732 } // namespace wasm |
730 } // namespace internal | 733 } // namespace internal |
731 } // namespace v8 | 734 } // namespace v8 |
OLD | NEW |