Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/wasm/encoder.cc

Issue 1909513002: [wasm] Extra LEB utilities to leb-helper.h (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add unittests for signed encodings. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/wasm/encoder.h ('k') | src/wasm/leb-helper.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 #include "src/wasm/ast-decoder.h" 11 #include "src/wasm/ast-decoder.h"
12 #include "src/wasm/encoder.h" 12 #include "src/wasm/encoder.h"
13 #include "src/wasm/leb-helper.h"
13 #include "src/wasm/wasm-macro-gen.h" 14 #include "src/wasm/wasm-macro-gen.h"
14 #include "src/wasm/wasm-module.h" 15 #include "src/wasm/wasm-module.h"
15 #include "src/wasm/wasm-opcodes.h" 16 #include "src/wasm/wasm-opcodes.h"
16 17
17 #include "src/v8memory.h" 18 #include "src/v8memory.h"
18 19
19 #if DEBUG 20 #if DEBUG
20 #define TRACE(...) \ 21 #define TRACE(...) \
21 do { \ 22 do { \
22 if (FLAG_trace_wasm_encoder) PrintF(__VA_ARGS__); \ 23 if (FLAG_trace_wasm_encoder) PrintF(__VA_ARGS__); \
(...skipping 20 matching lines...) Expand all
43 WriteUnalignedUInt16(*b, x); 44 WriteUnalignedUInt16(*b, x);
44 *b += 2; 45 *b += 2;
45 } 46 }
46 47
47 48
48 void EmitUint32(byte** b, uint32_t x) { 49 void EmitUint32(byte** b, uint32_t x) {
49 WriteUnalignedUInt32(*b, x); 50 WriteUnalignedUInt32(*b, x);
50 *b += 4; 51 *b += 4;
51 } 52 }
52 53
54 void EmitVarInt(byte** b, size_t val) {
55 LEBHelper::write_u32v(b, static_cast<uint32_t>(val));
56 }
57
53 // 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.
54 // 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.
55 // 60 //
56 // 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.
57 const size_t padded_varint = 5; 62 const size_t padded_varint = 5;
58 63
59 void EmitVarInt(byte** b, size_t val) {
60 while (true) {
61 size_t next = val >> 7;
62 byte out = static_cast<byte>(val & 0x7f);
63 if (next) {
64 *((*b)++) = 0x80 | out;
65 val = next;
66 } else {
67 *((*b)++) = out;
68 break;
69 }
70 }
71 }
72
73 size_t SizeOfVarInt(size_t value) {
74 size_t size = 0;
75 do {
76 size++;
77 value = value >> 7;
78 } while (value > 0);
79 return size;
80 }
81
82 void FixupSection(byte* start, byte* end) { 64 void FixupSection(byte* start, byte* end) {
83 // Same as EmitVarInt, but fixed-width with zeroes in the MSBs. 65 // Same as LEBHelper::write_u32v, but fixed-width with zeroes in the MSBs.
84 size_t val = end - start - padded_varint; 66 size_t val = end - start - padded_varint;
85 TRACE(" fixup %u\n", (unsigned)val); 67 TRACE(" fixup %u\n", (unsigned)val);
86 for (size_t pos = 0; pos != padded_varint; ++pos) { 68 for (size_t pos = 0; pos != padded_varint; ++pos) {
87 size_t next = val >> 7; 69 size_t next = val >> 7;
88 byte out = static_cast<byte>(val & 0x7f); 70 byte out = static_cast<byte>(val & 0x7f);
89 if (pos != padded_varint - 1) { 71 if (pos != padded_varint - 1) {
90 *(start++) = 0x80 | out; 72 *(start++) = 0x80 | out;
91 val = next; 73 val = next;
92 } else { 74 } else {
93 *(start++) = out; 75 *(start++) = out;
(...skipping 25 matching lines...) Expand all
119 101
120 WasmFunctionBuilder::WasmFunctionBuilder(Zone* zone) 102 WasmFunctionBuilder::WasmFunctionBuilder(Zone* zone)
121 : return_type_(kAstI32), 103 : return_type_(kAstI32),
122 locals_(zone), 104 locals_(zone),
123 exported_(0), 105 exported_(0),
124 external_(0), 106 external_(0),
125 body_(zone), 107 body_(zone),
126 local_indices_(zone), 108 local_indices_(zone),
127 name_(zone) {} 109 name_(zone) {}
128 110
111 void WasmFunctionBuilder::EmitVarInt(uint32_t val) {
112 byte buffer[8];
113 byte* ptr = buffer;
114 LEBHelper::write_u32v(&ptr, val);
115 for (byte* p = buffer; p < ptr; p++) {
116 body_.push_back(*p);
117 }
118 }
129 119
130 uint16_t WasmFunctionBuilder::AddParam(LocalType type) { 120 uint16_t WasmFunctionBuilder::AddParam(LocalType type) {
131 return AddVar(type, true); 121 return AddVar(type, true);
132 } 122 }
133 123
134 124
135 uint16_t WasmFunctionBuilder::AddLocal(LocalType type) { 125 uint16_t WasmFunctionBuilder::AddLocal(LocalType type) {
136 return AddVar(type, false); 126 return AddVar(type, false);
137 } 127 }
138 128
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 void WasmFunctionBuilder::EmitWithU8U8(WasmOpcode opcode, const byte imm1, 176 void WasmFunctionBuilder::EmitWithU8U8(WasmOpcode opcode, const byte imm1,
187 const byte imm2) { 177 const byte imm2) {
188 body_.push_back(static_cast<byte>(opcode)); 178 body_.push_back(static_cast<byte>(opcode));
189 body_.push_back(imm1); 179 body_.push_back(imm1);
190 body_.push_back(imm2); 180 body_.push_back(imm2);
191 } 181 }
192 182
193 void WasmFunctionBuilder::EmitWithVarInt(WasmOpcode opcode, 183 void WasmFunctionBuilder::EmitWithVarInt(WasmOpcode opcode,
194 uint32_t immediate) { 184 uint32_t immediate) {
195 body_.push_back(static_cast<byte>(opcode)); 185 body_.push_back(static_cast<byte>(opcode));
196 size_t immediate_size = SizeOfVarInt(immediate); 186 EmitVarInt(immediate);
197 body_.insert(body_.end(), immediate_size, 0);
198 byte* p = &body_[body_.size() - immediate_size];
199 EmitVarInt(&p, immediate);
200 } 187 }
201 188
202 uint32_t WasmFunctionBuilder::EmitEditableVarIntImmediate() { 189 uint32_t WasmFunctionBuilder::EmitEditableVarIntImmediate() {
203 // Guess that the immediate will be 1 byte. If it is more, we'll have to 190 // Guess that the immediate will be 1 byte. If it is more, we'll have to
204 // shift everything down. 191 // shift everything down.
205 body_.push_back(0); 192 body_.push_back(0);
206 return static_cast<uint32_t>(body_.size()) - 1; 193 return static_cast<uint32_t>(body_.size()) - 1;
207 } 194 }
208 195
209 void WasmFunctionBuilder::EditVarIntImmediate(uint32_t offset, 196 void WasmFunctionBuilder::EditVarIntImmediate(uint32_t offset,
210 const uint32_t immediate) { 197 const uint32_t immediate) {
211 uint32_t immediate_size = static_cast<uint32_t>(SizeOfVarInt(immediate)); 198 uint32_t immediate_size =
199 static_cast<uint32_t>(LEBHelper::sizeof_u32v(immediate));
212 // In EmitEditableVarIntImmediate, we guessed that we'd only need one byte. 200 // In EmitEditableVarIntImmediate, we guessed that we'd only need one byte.
213 // If we need more, shift everything down to make room for the larger 201 // If we need more, shift everything down to make room for the larger
214 // immediate. 202 // immediate.
215 if (immediate_size > 1) { 203 if (immediate_size > 1) {
216 uint32_t diff = immediate_size - 1; 204 uint32_t diff = immediate_size - 1;
217 body_.insert(body_.begin() + offset, diff, 0); 205 body_.insert(body_.begin() + offset, diff, 0);
218 206
219 for (size_t i = 0; i < local_indices_.size(); ++i) { 207 for (size_t i = 0; i < local_indices_.size(); ++i) {
220 if (local_indices_[i] >= offset) { 208 if (local_indices_[i] >= offset) {
221 local_indices_[i] += diff; 209 local_indices_[i] += diff;
222 } 210 }
223 } 211 }
224 } 212 }
225 DCHECK(offset + immediate_size <= body_.size()); 213 DCHECK(offset + immediate_size <= body_.size());
226 byte* p = &body_[offset]; 214 byte* p = &body_[offset];
227 EmitVarInt(&p, immediate); 215 v8::internal::wasm::EmitVarInt(&p, immediate);
228 } 216 }
229 217
230 218
231 void WasmFunctionBuilder::Exported(uint8_t flag) { exported_ = flag; } 219 void WasmFunctionBuilder::Exported(uint8_t flag) { exported_ = flag; }
232 220
233 221
234 void WasmFunctionBuilder::External(uint8_t flag) { external_ = flag; } 222 void WasmFunctionBuilder::External(uint8_t flag) { external_ = flag; }
235 223
236 void WasmFunctionBuilder::SetName(const unsigned char* name, int name_length) { 224 void WasmFunctionBuilder::SetName(const unsigned char* name, int name_length) {
237 name_.clear(); 225 name_.clear();
238 if (name_length > 0) { 226 if (name_length > 0) {
239 for (int i = 0; i < name_length; i++) { 227 for (int i = 0; i < name_length; i++) {
240 name_.push_back(*(name + i)); 228 name_.push_back(*(name + i));
241 } 229 }
242 } 230 }
243 } 231 }
244 232
245 233
246 WasmFunctionEncoder* WasmFunctionBuilder::Build(Zone* zone, 234 WasmFunctionEncoder* WasmFunctionBuilder::Build(Zone* zone,
247 WasmModuleBuilder* mb) const { 235 WasmModuleBuilder* mb) const {
248 WasmFunctionEncoder* e = 236 WasmFunctionEncoder* e =
249 new (zone) WasmFunctionEncoder(zone, return_type_, exported_, external_); 237 new (zone) WasmFunctionEncoder(zone, return_type_, exported_, external_);
250 uint16_t* var_index = zone->NewArray<uint16_t>(locals_.size()); 238 uint16_t* var_index = zone->NewArray<uint16_t>(locals_.size());
251 IndexVars(e, var_index); 239 IndexVars(e, var_index);
252 if (body_.size() > 0) { 240 if (body_.size() > 0) {
253 // TODO(titzer): iterate over local indexes, not the bytes. 241 // TODO(titzer): iterate over local indexes, not the bytes.
254 const byte* start = &body_[0]; 242 const byte* start = &body_[0];
255 const byte* end = start + body_.size();
256 size_t local_index = 0; 243 size_t local_index = 0;
257 for (size_t i = 0; i < body_.size();) { 244 for (size_t i = 0; i < body_.size();) {
258 if (local_index < local_indices_.size() && 245 if (local_index < local_indices_.size() &&
259 i == local_indices_[local_index]) { 246 i == local_indices_[local_index]) {
260 int length = 0; 247 // Read the old index.
261 uint32_t index; 248 uint32_t index = 0;
262 ReadUnsignedLEB128Operand(start + i, end, &length, &index); 249 uint8_t b = 0;
250 uint32_t shift = 0;
251 while ((b = start[i++]) >= 0x80) {
252 index |= (b & 0x7F) << shift;
253 shift += 7;
254 }
255 index |= b << shift;
256
257 // Write the new index.
263 uint16_t new_index = var_index[index]; 258 uint16_t new_index = var_index[index];
264 const std::vector<uint8_t>& index_vec = UnsignedLEB128From(new_index); 259 while (new_index >= 0x80) {
265 for (size_t j = 0; j < index_vec.size(); j++) { 260 e->body_.push_back(new_index | 0x80);
266 e->body_.push_back(index_vec.at(j)); 261 new_index >>= 7;
267 } 262 }
268 i += length; 263 e->body_.push_back(new_index);
264
269 local_index++; 265 local_index++;
270 } else { 266 } else {
271 e->body_.push_back(*(start + i)); 267 e->body_.push_back(*(start + i));
272 i++; 268 i++;
273 } 269 }
274 } 270 }
275 } 271 }
276 FunctionSig::Builder sig(zone, return_type_ == kAstStmt ? 0 : 1, 272 FunctionSig::Builder sig(zone, return_type_ == kAstStmt ? 0 : 1,
277 e->params_.size()); 273 e->params_.size());
278 if (return_type_ != kAstStmt) { 274 if (return_type_ != kAstStmt) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 external_(external), 336 external_(external),
341 body_(zone), 337 body_(zone),
342 name_(zone) {} 338 name_(zone) {}
343 339
344 340
345 uint32_t WasmFunctionEncoder::HeaderSize() const { 341 uint32_t WasmFunctionEncoder::HeaderSize() const {
346 uint32_t size = 3; 342 uint32_t size = 3;
347 if (!external_) size += 2; 343 if (!external_) size += 2;
348 if (HasName()) { 344 if (HasName()) {
349 uint32_t name_size = NameSize(); 345 uint32_t name_size = NameSize();
350 size += static_cast<uint32_t>(SizeOfVarInt(name_size)) + name_size; 346 size +=
347 static_cast<uint32_t>(LEBHelper::sizeof_u32v(name_size)) + name_size;
351 } 348 }
352 return size; 349 return size;
353 } 350 }
354 351
355 352
356 uint32_t WasmFunctionEncoder::BodySize(void) const { 353 uint32_t WasmFunctionEncoder::BodySize(void) const {
357 // TODO(titzer): embed a LocalDeclEncoder in the WasmFunctionEncoder 354 // TODO(titzer): embed a LocalDeclEncoder in the WasmFunctionEncoder
358 LocalDeclEncoder local_decl; 355 LocalDeclEncoder local_decl;
359 local_decl.AddLocals(local_i32_count_, kAstI32); 356 local_decl.AddLocals(local_i32_count_, kAstI32);
360 local_decl.AddLocals(local_i64_count_, kAstI64); 357 local_decl.AddLocals(local_i64_count_, kAstI64);
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 size_t body_size; 541 size_t body_size;
545 542
546 size_t total() { return header_size + body_size; } 543 size_t total() { return header_size + body_size; }
547 544
548 void Add(size_t header, size_t body) { 545 void Add(size_t header, size_t body) {
549 header_size += header; 546 header_size += header;
550 body_size += body; 547 body_size += body;
551 } 548 }
552 549
553 void AddSection(WasmSection::Code code, size_t other_size) { 550 void AddSection(WasmSection::Code code, size_t other_size) {
554 Add(padded_varint + SizeOfVarInt(WasmSection::getNameLength(code)) + 551 Add(padded_varint +
552 LEBHelper::sizeof_u32v(WasmSection::getNameLength(code)) +
555 WasmSection::getNameLength(code), 553 WasmSection::getNameLength(code),
556 0); 554 0);
557 if (other_size) Add(SizeOfVarInt(other_size), 0); 555 if (other_size) Add(LEBHelper::sizeof_u32v(other_size), 0);
558 } 556 }
559 }; 557 };
560 558
561 WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const { 559 WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
562 Sizes sizes = {0, 0}; 560 Sizes sizes = {0, 0};
563 561
564 sizes.Add(2 * sizeof(uint32_t), 0); // header 562 sizes.Add(2 * sizeof(uint32_t), 0); // header
565 563
566 sizes.AddSection(WasmSection::Code::Memory, 0); 564 sizes.AddSection(WasmSection::Code::Memory, 0);
567 sizes.Add(kDeclMemorySize, 0); 565 sizes.Add(kDeclMemorySize, 0);
568 TRACE("Size after memory: %u, %u\n", (unsigned)sizes.header_size, 566 TRACE("Size after memory: %u, %u\n", (unsigned)sizes.header_size,
569 (unsigned)sizes.body_size); 567 (unsigned)sizes.body_size);
570 568
571 if (globals_.size() > 0) { 569 if (globals_.size() > 0) {
572 sizes.AddSection(WasmSection::Code::Globals, globals_.size()); 570 sizes.AddSection(WasmSection::Code::Globals, globals_.size());
573 /* These globals never have names, so are always 3 bytes. */ 571 /* These globals never have names, so are always 3 bytes. */
574 sizes.Add(3 * globals_.size(), 0); 572 sizes.Add(3 * globals_.size(), 0);
575 TRACE("Size after globals: %u, %u\n", (unsigned)sizes.header_size, 573 TRACE("Size after globals: %u, %u\n", (unsigned)sizes.header_size,
576 (unsigned)sizes.body_size); 574 (unsigned)sizes.body_size);
577 } 575 }
578 576
579 if (signatures_.size() > 0) { 577 if (signatures_.size() > 0) {
580 sizes.AddSection(WasmSection::Code::Signatures, signatures_.size()); 578 sizes.AddSection(WasmSection::Code::Signatures, signatures_.size());
581 for (auto sig : signatures_) { 579 for (auto sig : signatures_) {
582 sizes.Add( 580 sizes.Add(1 + LEBHelper::sizeof_u32v(sig->parameter_count()) +
583 1 + SizeOfVarInt(sig->parameter_count()) + sig->parameter_count(), 0); 581 sig->parameter_count(),
582 0);
584 } 583 }
585 TRACE("Size after signatures: %u, %u\n", (unsigned)sizes.header_size, 584 TRACE("Size after signatures: %u, %u\n", (unsigned)sizes.header_size,
586 (unsigned)sizes.body_size); 585 (unsigned)sizes.body_size);
587 } 586 }
588 587
589 if (functions_.size() > 0) { 588 if (functions_.size() > 0) {
590 sizes.AddSection(WasmSection::Code::Functions, functions_.size()); 589 sizes.AddSection(WasmSection::Code::Functions, functions_.size());
591 for (auto function : functions_) { 590 for (auto function : functions_) {
592 sizes.Add(function->HeaderSize() + function->BodySize(), 591 sizes.Add(function->HeaderSize() + function->BodySize(),
593 function->NameSize()); 592 function->NameSize());
594 } 593 }
595 TRACE("Size after functions: %u, %u\n", (unsigned)sizes.header_size, 594 TRACE("Size after functions: %u, %u\n", (unsigned)sizes.header_size,
596 (unsigned)sizes.body_size); 595 (unsigned)sizes.body_size);
597 } 596 }
598 597
599 if (start_function_index_ >= 0) { 598 if (start_function_index_ >= 0) {
600 sizes.AddSection(WasmSection::Code::StartFunction, 0); 599 sizes.AddSection(WasmSection::Code::StartFunction, 0);
601 sizes.Add(SizeOfVarInt(start_function_index_), 0); 600 sizes.Add(LEBHelper::sizeof_u32v(start_function_index_), 0);
602 TRACE("Size after start: %u, %u\n", (unsigned)sizes.header_size, 601 TRACE("Size after start: %u, %u\n", (unsigned)sizes.header_size,
603 (unsigned)sizes.body_size); 602 (unsigned)sizes.body_size);
604 } 603 }
605 604
606 if (data_segments_.size() > 0) { 605 if (data_segments_.size() > 0) {
607 sizes.AddSection(WasmSection::Code::DataSegments, data_segments_.size()); 606 sizes.AddSection(WasmSection::Code::DataSegments, data_segments_.size());
608 for (auto segment : data_segments_) { 607 for (auto segment : data_segments_) {
609 sizes.Add(segment->HeaderSize(), segment->BodySize()); 608 sizes.Add(segment->HeaderSize(), segment->BodySize());
610 } 609 }
611 TRACE("Size after data segments: %u, %u\n", (unsigned)sizes.header_size, 610 TRACE("Size after data segments: %u, %u\n", (unsigned)sizes.header_size,
612 (unsigned)sizes.body_size); 611 (unsigned)sizes.body_size);
613 } 612 }
614 613
615 if (indirect_functions_.size() > 0) { 614 if (indirect_functions_.size() > 0) {
616 sizes.AddSection(WasmSection::Code::FunctionTable, 615 sizes.AddSection(WasmSection::Code::FunctionTable,
617 indirect_functions_.size()); 616 indirect_functions_.size());
618 for (auto function_index : indirect_functions_) { 617 for (auto function_index : indirect_functions_) {
619 sizes.Add(SizeOfVarInt(function_index), 0); 618 sizes.Add(LEBHelper::sizeof_u32v(function_index), 0);
620 } 619 }
621 TRACE("Size after indirect functions: %u, %u\n", 620 TRACE("Size after indirect functions: %u, %u\n",
622 (unsigned)sizes.header_size, (unsigned)sizes.body_size); 621 (unsigned)sizes.header_size, (unsigned)sizes.body_size);
623 } 622 }
624 623
625 if (sizes.body_size > 0) { 624 if (sizes.body_size > 0) {
626 sizes.AddSection(WasmSection::Code::End, 0); 625 sizes.AddSection(WasmSection::Code::End, 0);
627 TRACE("Size after end: %u, %u\n", (unsigned)sizes.header_size, 626 TRACE("Size after end: %u, %u\n", (unsigned)sizes.header_size,
628 (unsigned)sizes.body_size); 627 (unsigned)sizes.body_size);
629 } 628 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
720 FixupSection(section, header); 719 FixupSection(section, header);
721 } 720 }
722 721
723 if (sizes.body_size > 0) { 722 if (sizes.body_size > 0) {
724 byte* section = EmitSection(WasmSection::Code::End, &header); 723 byte* section = EmitSection(WasmSection::Code::End, &header);
725 FixupSection(section, header); 724 FixupSection(section, header);
726 } 725 }
727 726
728 return new (zone) WasmModuleIndex(buffer, buffer + sizes.total()); 727 return new (zone) WasmModuleIndex(buffer, buffer + sizes.total());
729 } 728 }
730
731
732 std::vector<uint8_t> UnsignedLEB128From(uint32_t result) {
733 std::vector<uint8_t> output;
734 uint8_t next = 0;
735 int shift = 0;
736 do {
737 next = static_cast<uint8_t>(result >> shift);
738 if (((result >> shift) & 0xFFFFFF80) != 0) {
739 next = next | 0x80;
740 }
741 output.push_back(next);
742 shift += 7;
743 } while ((next & 0x80) != 0);
744 return output;
745 }
746 } // namespace wasm 729 } // namespace wasm
747 } // namespace internal 730 } // namespace internal
748 } // namespace v8 731 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/encoder.h ('k') | src/wasm/leb-helper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698