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