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 12 matching lines...) Expand all Loading... | |
23 if (FLAG_trace_wasm_encoder) PrintF(__VA_ARGS__); \ | 23 if (FLAG_trace_wasm_encoder) PrintF(__VA_ARGS__); \ |
24 } while (false) | 24 } while (false) |
25 #else | 25 #else |
26 #define TRACE(...) | 26 #define TRACE(...) |
27 #endif | 27 #endif |
28 | 28 |
29 namespace v8 { | 29 namespace v8 { |
30 namespace internal { | 30 namespace internal { |
31 namespace wasm { | 31 namespace wasm { |
32 | 32 |
33 /*TODO: add error cases for adding too many locals, too many functions and bad | 33 // Emit a section name and the size as a padded varint that can be patched |
34 indices in body */ | 34 // later. |
35 | 35 size_t EmitSection(WasmSection::Code code, ZoneBuffer& buffer) { |
36 namespace { | |
37 void EmitUint8(byte** b, uint8_t x) { | |
38 Memory::uint8_at(*b) = x; | |
39 *b += 1; | |
40 } | |
41 | |
42 void EmitUint16(byte** b, uint16_t x) { | |
43 WriteUnalignedUInt16(*b, x); | |
44 *b += 2; | |
45 } | |
46 | |
47 void EmitUint32(byte** b, uint32_t x) { | |
48 WriteUnalignedUInt32(*b, x); | |
49 *b += 4; | |
50 } | |
51 | |
52 void EmitVarInt(byte** b, size_t val) { | |
53 LEBHelper::write_u32v(b, static_cast<uint32_t>(val)); | |
54 } | |
55 | |
56 // Sections all start with a size, but it's unknown at the start. | |
57 // We generate a large varint which we then fixup later when the size is known. | |
58 // | |
59 // TODO(jfb) Not strictly necessary since sizes are calculated ahead of time. | |
60 const size_t kPaddedVarintSize = 5; | |
61 | |
62 void FixupSection(byte* start, byte* end) { | |
63 // Same as LEBHelper::write_u32v, but fixed-width with zeroes in the MSBs. | |
64 size_t val = end - start - kPaddedVarintSize; | |
65 TRACE(" fixup %u\n", (unsigned)val); | |
66 for (size_t pos = 0; pos != kPaddedVarintSize; ++pos) { | |
67 size_t next = val >> 7; | |
68 byte out = static_cast<byte>(val & 0x7f); | |
69 if (pos != kPaddedVarintSize - 1) { | |
70 *(start++) = 0x80 | out; | |
71 val = next; | |
72 } else { | |
73 *(start++) = out; | |
74 // TODO(jfb) check that the pre-allocated fixup size isn't overflowed. | |
75 } | |
76 } | |
77 } | |
78 | |
79 // Returns the start of the section, where the section VarInt size is. | |
80 byte* EmitSection(WasmSection::Code code, byte** b) { | |
81 // Emit the section name. | 36 // Emit the section name. |
82 const char* name = WasmSection::getName(code); | 37 const char* name = WasmSection::getName(code); |
83 TRACE("emit section: %s\n", name); | 38 TRACE("emit section: %s\n", name); |
84 size_t length = WasmSection::getNameLength(code); | 39 size_t length = WasmSection::getNameLength(code); |
85 EmitVarInt(b, length); // Section name string size. | 40 buffer.write_size(length); // Section name string size. |
86 for (size_t i = 0; i != length; ++i) EmitUint8(b, name[i]); | 41 buffer.write(reinterpret_cast<const byte*>(name), length); |
87 | 42 |
88 // Emit a placeholder for the length. | 43 // Emit a placeholder for the length. |
89 byte* start = *b; | 44 return buffer.reserve_u32v(); |
90 for (size_t padding = 0; padding != kPaddedVarintSize; ++padding) { | 45 } |
91 EmitUint8(b, 0xff); // Will get fixed up later. | |
92 } | |
93 | 46 |
94 return start; | 47 // Patch the size of a section after it's finished. |
48 void FixupSection(ZoneBuffer& buffer, size_t start) { | |
49 buffer.patch_u32v(start, static_cast<uint32_t>(buffer.offset() - start - | |
50 kPaddedVarInt32Size)); | |
95 } | 51 } |
96 } // namespace | |
97 | 52 |
98 WasmFunctionBuilder::WasmFunctionBuilder(Zone* zone) | 53 WasmFunctionBuilder::WasmFunctionBuilder(Zone* zone) |
99 : locals_(zone), exported_(0), body_(zone), name_(zone) {} | 54 : locals_(zone), exported_(0), body_(zone), name_(zone) {} |
100 | 55 |
101 void WasmFunctionBuilder::EmitVarInt(uint32_t val) { | 56 void WasmFunctionBuilder::EmitVarInt(uint32_t val) { |
102 byte buffer[8]; | 57 byte buffer[8]; |
103 byte* ptr = buffer; | 58 byte* ptr = buffer; |
104 LEBHelper::write_u32v(&ptr, val); | 59 LEBHelper::write_u32v(&ptr, val); |
105 for (byte* p = buffer; p < ptr; p++) { | 60 for (byte* p = buffer; p < ptr; p++) { |
106 body_.push_back(*p); | 61 body_.push_back(*p); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
182 e->body_.insert(e->body_.begin(), body_.begin(), body_.end()); | 137 e->body_.insert(e->body_.begin(), body_.begin(), body_.end()); |
183 e->signature_index_ = mb->AddSignature(locals_.get_sig()); | 138 e->signature_index_ = mb->AddSignature(locals_.get_sig()); |
184 e->name_.insert(e->name_.begin(), name_.begin(), name_.end()); | 139 e->name_.insert(e->name_.begin(), name_.begin(), name_.end()); |
185 return e; | 140 return e; |
186 } | 141 } |
187 | 142 |
188 WasmFunctionEncoder::WasmFunctionEncoder(Zone* zone, LocalDeclEncoder locals, | 143 WasmFunctionEncoder::WasmFunctionEncoder(Zone* zone, LocalDeclEncoder locals, |
189 bool exported) | 144 bool exported) |
190 : locals_(locals), exported_(exported), body_(zone), name_(zone) {} | 145 : locals_(locals), exported_(exported), body_(zone), name_(zone) {} |
191 | 146 |
192 uint32_t WasmFunctionEncoder::HeaderSize() const { | 147 void WasmFunctionEncoder::WriteSignature(ZoneBuffer& buffer) const { |
193 uint32_t size = 3; | 148 buffer.write_u32v(signature_index_); |
194 size += 2; | |
195 if (HasName()) { | |
196 uint32_t name_size = NameSize(); | |
197 size += | |
198 static_cast<uint32_t>(LEBHelper::sizeof_u32v(name_size)) + name_size; | |
199 } | |
200 return size; | |
201 } | 149 } |
202 | 150 |
203 uint32_t WasmFunctionEncoder::BodySize(void) const { | 151 void WasmFunctionEncoder::WriteExport(ZoneBuffer& buffer, |
204 return static_cast<uint32_t>(body_.size() + locals_.Size()); | 152 uint32_t func_index) const { |
205 } | 153 if (exported_) { |
206 | 154 buffer.write_u32v(func_index); |
207 uint32_t WasmFunctionEncoder::NameSize() const { | 155 buffer.write_size(name_.size()); |
208 return HasName() ? static_cast<uint32_t>(name_.size()) : 0; | 156 if (name_.size() > 0) { |
209 } | 157 buffer.write(reinterpret_cast<const byte*>(&name_[0]), name_.size()); |
210 | |
211 void WasmFunctionEncoder::Serialize(byte* buffer, byte** header, | |
212 byte** body) const { | |
213 uint8_t decl_bits = (exported_ ? kDeclFunctionExport : 0) | | |
214 (HasName() ? kDeclFunctionName : 0); | |
215 | |
216 EmitUint8(header, decl_bits); | |
217 EmitUint16(header, signature_index_); | |
218 | |
219 if (HasName()) { | |
220 EmitVarInt(header, NameSize()); | |
221 for (size_t i = 0; i < name_.size(); ++i) { | |
222 EmitUint8(header, name_[i]); | |
223 } | 158 } |
224 } | 159 } |
225 | |
226 EmitUint16(header, static_cast<uint16_t>(body_.size() + locals_.Size())); | |
227 (*header) += locals_.Emit(*header); | |
228 if (body_.size() > 0) { | |
229 std::memcpy(*header, &body_[0], body_.size()); | |
230 (*header) += body_.size(); | |
231 } | |
232 } | 160 } |
233 | 161 |
162 void WasmFunctionEncoder::WriteBody(ZoneBuffer& buffer) const { | |
163 size_t locals_size = locals_.Size(); | |
164 buffer.write_size(locals_size + body_.size()); | |
165 buffer.EnsureSpace(locals_size); | |
166 byte** ptr = buffer.pos_ptr(); | |
167 locals_.Emit(*ptr); | |
bradnelson
2016/05/25 14:51:23
Yeah, yuck.
| |
168 (*ptr) += locals_size; // UGLY: manual bump of position pointer | |
169 if (body_.size() > 0) { | |
170 buffer.write(&body_[0], body_.size()); | |
171 } | |
172 } | |
173 | |
234 WasmDataSegmentEncoder::WasmDataSegmentEncoder(Zone* zone, const byte* data, | 174 WasmDataSegmentEncoder::WasmDataSegmentEncoder(Zone* zone, const byte* data, |
235 uint32_t size, uint32_t dest) | 175 uint32_t size, uint32_t dest) |
236 : data_(zone), dest_(dest) { | 176 : data_(zone), dest_(dest) { |
237 for (size_t i = 0; i < size; i++) { | 177 for (size_t i = 0; i < size; i++) { |
238 data_.push_back(data[i]); | 178 data_.push_back(data[i]); |
239 } | 179 } |
240 } | 180 } |
241 | 181 |
242 uint32_t WasmDataSegmentEncoder::HeaderSize() const { | 182 void WasmDataSegmentEncoder::Write(ZoneBuffer& buffer) const { |
243 static const int kDataSegmentSize = 13; | 183 buffer.write_u32v(dest_); |
244 return kDataSegmentSize; | 184 buffer.write_u32v(static_cast<uint32_t>(data_.size())); |
245 } | 185 buffer.write(&data_[0], data_.size()); |
246 | |
247 uint32_t WasmDataSegmentEncoder::BodySize() const { | |
248 return static_cast<uint32_t>(data_.size()); | |
249 } | |
250 | |
251 void WasmDataSegmentEncoder::Serialize(byte* buffer, byte** header, | |
252 byte** body) const { | |
253 EmitVarInt(header, dest_); | |
254 EmitVarInt(header, static_cast<uint32_t>(data_.size())); | |
255 | |
256 std::memcpy(*header, &data_[0], data_.size()); | |
257 (*header) += data_.size(); | |
258 } | 186 } |
259 | 187 |
260 WasmModuleBuilder::WasmModuleBuilder(Zone* zone) | 188 WasmModuleBuilder::WasmModuleBuilder(Zone* zone) |
261 : zone_(zone), | 189 : zone_(zone), |
262 signatures_(zone), | 190 signatures_(zone), |
263 imports_(zone), | 191 imports_(zone), |
264 functions_(zone), | 192 functions_(zone), |
265 data_segments_(zone), | 193 data_segments_(zone), |
266 indirect_functions_(zone), | 194 indirect_functions_(zone), |
267 globals_(zone), | 195 globals_(zone), |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
358 } | 286 } |
359 | 287 |
360 WasmModuleWriter::WasmModuleWriter(Zone* zone) | 288 WasmModuleWriter::WasmModuleWriter(Zone* zone) |
361 : imports_(zone), | 289 : imports_(zone), |
362 functions_(zone), | 290 functions_(zone), |
363 data_segments_(zone), | 291 data_segments_(zone), |
364 signatures_(zone), | 292 signatures_(zone), |
365 indirect_functions_(zone), | 293 indirect_functions_(zone), |
366 globals_(zone) {} | 294 globals_(zone) {} |
367 | 295 |
368 struct Sizes { | 296 void WasmModuleWriter::WriteTo(ZoneBuffer& buffer) const { |
369 size_t header_size; | 297 uint32_t exports = 0; |
370 size_t body_size; | |
371 | 298 |
372 size_t total() { return header_size + body_size; } | 299 // == Emit magic ============================================================= |
300 TRACE("emit magic\n"); | |
301 buffer.write_u32(kWasmMagic); | |
302 buffer.write_u32(kWasmVersion); | |
373 | 303 |
374 void Add(size_t header, size_t body) { | 304 // == Emit signatures ======================================================== |
375 header_size += header; | 305 if (signatures_.size() > 0) { |
376 body_size += body; | 306 size_t start = EmitSection(WasmSection::Code::Signatures, buffer); |
307 buffer.write_size(signatures_.size()); | |
308 | |
309 for (FunctionSig* sig : signatures_) { | |
310 buffer.write_u8(kWasmFunctionTypeForm); | |
311 buffer.write_size(sig->parameter_count()); | |
312 for (size_t j = 0; j < sig->parameter_count(); j++) { | |
313 buffer.write_u8(WasmOpcodes::LocalTypeCodeFor(sig->GetParam(j))); | |
314 } | |
315 buffer.write_size(sig->return_count()); | |
316 for (size_t j = 0; j < sig->return_count(); j++) { | |
317 buffer.write_u8(WasmOpcodes::LocalTypeCodeFor(sig->GetReturn(j))); | |
318 } | |
319 } | |
320 FixupSection(buffer, start); | |
377 } | 321 } |
378 | 322 |
379 void AddSection(WasmSection::Code code, size_t other_size) { | 323 // == Emit globals =========================================================== |
380 Add(kPaddedVarintSize + | 324 if (globals_.size() > 0) { |
381 LEBHelper::sizeof_u32v(WasmSection::getNameLength(code)) + | 325 size_t start = EmitSection(WasmSection::Code::Globals, buffer); |
382 WasmSection::getNameLength(code), | 326 buffer.write_size(globals_.size()); |
383 0); | |
384 if (other_size) Add(LEBHelper::sizeof_u32v(other_size), 0); | |
385 } | |
386 }; | |
387 | 327 |
388 WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const { | 328 for (auto global : globals_) { |
389 Sizes sizes = {0, 0}; | 329 buffer.write_u32v(0); // Length of the global name. |
390 | 330 buffer.write_u8(WasmOpcodes::MemTypeCodeFor(global.first)); |
391 sizes.Add(2 * sizeof(uint32_t), 0); // header | 331 buffer.write_u8(global.second); |
392 | 332 } |
393 if (globals_.size() > 0) { | 333 FixupSection(buffer, start); |
394 sizes.AddSection(WasmSection::Code::Globals, globals_.size()); | |
395 /* These globals never have names, so are always 3 bytes. */ | |
396 sizes.Add(3 * globals_.size(), 0); | |
397 TRACE("Size after globals: %u, %u\n", (unsigned)sizes.header_size, | |
398 (unsigned)sizes.body_size); | |
399 } | 334 } |
400 | 335 |
401 if (signatures_.size() > 0) { | 336 // == Emit imports =========================================================== |
402 sizes.AddSection(WasmSection::Code::Signatures, signatures_.size()); | 337 if (imports_.size() > 0) { |
403 for (auto sig : signatures_) { | 338 size_t start = EmitSection(WasmSection::Code::ImportTable, buffer); |
404 sizes.Add(1 + LEBHelper::sizeof_u32v(sig->parameter_count()) + | 339 buffer.write_size(imports_.size()); |
405 sig->parameter_count() + | 340 for (auto import : imports_) { |
406 LEBHelper::sizeof_u32v(sig->return_count()) + | 341 buffer.write_u32v(import.sig_index); |
407 sig->return_count(), | 342 buffer.write_u32v(import.name_length); |
408 0); | 343 buffer.write(reinterpret_cast<const byte*>(import.name), |
344 import.name_length); | |
345 buffer.write_u32v(0); | |
409 } | 346 } |
410 TRACE("Size after signatures: %u, %u\n", (unsigned)sizes.header_size, | 347 FixupSection(buffer, start); |
411 (unsigned)sizes.body_size); | |
412 } | 348 } |
413 | 349 |
350 // == Emit function signatures =============================================== | |
414 if (functions_.size() > 0) { | 351 if (functions_.size() > 0) { |
415 sizes.AddSection(WasmSection::Code::OldFunctions, functions_.size()); | 352 size_t start = EmitSection(WasmSection::Code::FunctionSignatures, buffer); |
353 buffer.write_size(functions_.size()); | |
416 for (auto function : functions_) { | 354 for (auto function : functions_) { |
417 sizes.Add(function->HeaderSize() + function->BodySize(), | 355 function->WriteSignature(buffer); |
418 function->NameSize()); | 356 if (function->exported()) exports++; |
419 } | 357 } |
420 TRACE("Size after functions: %u, %u\n", (unsigned)sizes.header_size, | 358 FixupSection(buffer, start); |
421 (unsigned)sizes.body_size); | |
422 } | 359 } |
423 | 360 |
424 if (imports_.size() > 0) { | 361 // == emit function table ==================================================== |
425 sizes.AddSection(WasmSection::Code::ImportTable, imports_.size()); | 362 if (indirect_functions_.size() > 0) { |
426 for (auto import : imports_) { | 363 size_t start = EmitSection(WasmSection::Code::FunctionTable, buffer); |
427 sizes.Add(LEBHelper::sizeof_u32v(import.sig_index), 0); | 364 buffer.write_size(indirect_functions_.size()); |
428 sizes.Add(LEBHelper::sizeof_u32v(import.name_length), 0); | 365 |
429 sizes.Add(import.name_length, 0); | 366 for (auto index : indirect_functions_) { |
430 sizes.Add(1, 0); | 367 buffer.write_u32v(index); |
431 } | 368 } |
432 TRACE("Size after imports: %u, %u\n", (unsigned)sizes.header_size, | 369 FixupSection(buffer, start); |
433 (unsigned)sizes.body_size); | |
434 } | 370 } |
435 | 371 |
436 if (indirect_functions_.size() > 0) { | 372 // == emit memory declaration ================================================ |
437 sizes.AddSection(WasmSection::Code::FunctionTable, | 373 { |
438 indirect_functions_.size()); | 374 size_t start = EmitSection(WasmSection::Code::Memory, buffer); |
439 for (auto function_index : indirect_functions_) { | 375 buffer.write_u32v(16); // min memory size |
440 sizes.Add(LEBHelper::sizeof_u32v(function_index), 0); | 376 buffer.write_u32v(16); // max memory size |
441 } | 377 buffer.write_u8(0); // memory export |
442 TRACE("Size after indirect functions: %u, %u\n", | 378 static_assert(kDeclMemorySize == 3, "memory size must match emit above"); |
443 (unsigned)sizes.header_size, (unsigned)sizes.body_size); | 379 FixupSection(buffer, start); |
444 } | 380 } |
445 | 381 |
446 sizes.AddSection(WasmSection::Code::Memory, 0); | 382 // == emit exports =========================================================== |
447 sizes.Add(kDeclMemorySize, 0); | 383 if (exports > 0) { |
448 TRACE("Size after memory: %u, %u\n", (unsigned)sizes.header_size, | 384 size_t start = EmitSection(WasmSection::Code::ExportTable, buffer); |
449 (unsigned)sizes.body_size); | 385 buffer.write_u32v(exports); |
450 | 386 uint32_t index = 0; |
451 if (start_function_index_ >= 0) { | 387 for (auto function : functions_) { |
452 sizes.AddSection(WasmSection::Code::StartFunction, 0); | 388 function->WriteExport(buffer, index++); |
453 sizes.Add(LEBHelper::sizeof_u32v(start_function_index_), 0); | 389 } |
454 TRACE("Size after start: %u, %u\n", (unsigned)sizes.header_size, | 390 FixupSection(buffer, start); |
455 (unsigned)sizes.body_size); | |
456 } | 391 } |
457 | 392 |
458 if (data_segments_.size() > 0) { | 393 // == emit start function index ============================================== |
459 sizes.AddSection(WasmSection::Code::DataSegments, data_segments_.size()); | 394 if (start_function_index_ >= 0) { |
460 for (auto segment : data_segments_) { | 395 size_t start = EmitSection(WasmSection::Code::StartFunction, buffer); |
461 sizes.Add(segment->HeaderSize(), segment->BodySize()); | 396 buffer.write_u32v(start_function_index_); |
462 } | 397 FixupSection(buffer, start); |
463 TRACE("Size after data segments: %u, %u\n", (unsigned)sizes.header_size, | |
464 (unsigned)sizes.body_size); | |
465 } | 398 } |
466 | 399 |
467 if (sizes.body_size > 0) { | 400 // == emit code ============================================================== |
468 sizes.AddSection(WasmSection::Code::End, 0); | 401 if (functions_.size() > 0) { |
469 TRACE("Size after end: %u, %u\n", (unsigned)sizes.header_size, | 402 size_t start = EmitSection(WasmSection::Code::FunctionBodies, buffer); |
470 (unsigned)sizes.body_size); | 403 buffer.write_size(functions_.size()); |
404 for (auto function : functions_) { | |
405 function->WriteBody(buffer); | |
406 } | |
407 FixupSection(buffer, start); | |
471 } | 408 } |
472 | 409 |
473 ZoneVector<uint8_t> buffer_vector(sizes.total(), zone); | 410 // == emit data segments ===================================================== |
474 byte* buffer = &buffer_vector[0]; | |
475 byte* header = buffer; | |
476 byte* body = buffer + sizes.header_size; | |
477 | |
478 // -- emit magic ------------------------------------------------------------- | |
479 TRACE("emit magic\n"); | |
480 EmitUint32(&header, kWasmMagic); | |
481 EmitUint32(&header, kWasmVersion); | |
482 | |
483 // -- emit globals ----------------------------------------------------------- | |
484 if (globals_.size() > 0) { | |
485 byte* section = EmitSection(WasmSection::Code::Globals, &header); | |
486 EmitVarInt(&header, globals_.size()); | |
487 | |
488 for (auto global : globals_) { | |
489 EmitVarInt(&header, 0); // Length of the global name. | |
490 EmitUint8(&header, WasmOpcodes::MemTypeCodeFor(global.first)); | |
491 EmitUint8(&header, global.second); | |
492 } | |
493 FixupSection(section, header); | |
494 } | |
495 | |
496 // -- emit signatures -------------------------------------------------------- | |
497 if (signatures_.size() > 0) { | |
498 byte* section = EmitSection(WasmSection::Code::Signatures, &header); | |
499 EmitVarInt(&header, signatures_.size()); | |
500 | |
501 for (FunctionSig* sig : signatures_) { | |
502 EmitUint8(&header, kWasmFunctionTypeForm); | |
503 EmitVarInt(&header, sig->parameter_count()); | |
504 for (size_t j = 0; j < sig->parameter_count(); j++) { | |
505 EmitUint8(&header, WasmOpcodes::LocalTypeCodeFor(sig->GetParam(j))); | |
506 } | |
507 EmitVarInt(&header, sig->return_count()); | |
508 for (size_t j = 0; j < sig->return_count(); j++) { | |
509 EmitUint8(&header, WasmOpcodes::LocalTypeCodeFor(sig->GetReturn(j))); | |
510 } | |
511 } | |
512 FixupSection(section, header); | |
513 } | |
514 | |
515 // -- emit imports ----------------------------------------------------------- | |
516 if (imports_.size() > 0) { | |
517 byte* section = EmitSection(WasmSection::Code::ImportTable, &header); | |
518 EmitVarInt(&header, imports_.size()); | |
519 for (auto import : imports_) { | |
520 EmitVarInt(&header, import.sig_index); | |
521 EmitVarInt(&header, import.name_length); | |
522 std::memcpy(header, import.name, import.name_length); | |
523 header += import.name_length; | |
524 EmitVarInt(&header, 0); | |
525 } | |
526 FixupSection(section, header); | |
527 } | |
528 | |
529 // -- emit functions --------------------------------------------------------- | |
530 if (functions_.size() > 0) { | |
531 byte* section = EmitSection(WasmSection::Code::OldFunctions, &header); | |
532 EmitVarInt(&header, functions_.size()); | |
533 | |
534 for (auto func : functions_) { | |
535 func->Serialize(buffer, &header, &body); | |
536 } | |
537 FixupSection(section, header); | |
538 } | |
539 | |
540 // -- emit function table ---------------------------------------------------- | |
541 if (indirect_functions_.size() > 0) { | |
542 byte* section = EmitSection(WasmSection::Code::FunctionTable, &header); | |
543 EmitVarInt(&header, indirect_functions_.size()); | |
544 | |
545 for (auto index : indirect_functions_) { | |
546 EmitVarInt(&header, index); | |
547 } | |
548 FixupSection(section, header); | |
549 } | |
550 | |
551 // -- emit memory declaration ------------------------------------------------ | |
552 { | |
553 byte* section = EmitSection(WasmSection::Code::Memory, &header); | |
554 EmitVarInt(&header, 16); // min memory size | |
555 EmitVarInt(&header, 16); // max memory size | |
556 EmitUint8(&header, 0); // memory export | |
557 static_assert(kDeclMemorySize == 3, "memory size must match emit above"); | |
558 FixupSection(section, header); | |
559 } | |
560 | |
561 // -- emit start function index ---------------------------------------------- | |
562 if (start_function_index_ >= 0) { | |
563 byte* section = EmitSection(WasmSection::Code::StartFunction, &header); | |
564 EmitVarInt(&header, start_function_index_); | |
565 FixupSection(section, header); | |
566 } | |
567 | |
568 // -- emit data segments ----------------------------------------------------- | |
569 if (data_segments_.size() > 0) { | 411 if (data_segments_.size() > 0) { |
570 byte* section = EmitSection(WasmSection::Code::DataSegments, &header); | 412 size_t start = EmitSection(WasmSection::Code::DataSegments, buffer); |
571 EmitVarInt(&header, data_segments_.size()); | 413 buffer.write_size(data_segments_.size()); |
572 | 414 |
573 for (auto segment : data_segments_) { | 415 for (auto segment : data_segments_) { |
574 segment->Serialize(buffer, &header, &body); | 416 segment->Write(buffer); |
575 } | 417 } |
576 FixupSection(section, header); | 418 FixupSection(buffer, start); |
577 } | 419 } |
578 | |
579 if (sizes.body_size > 0) { | |
580 byte* section = EmitSection(WasmSection::Code::End, &header); | |
581 FixupSection(section, header); | |
582 } | |
583 | |
584 return new (zone) WasmModuleIndex(buffer, buffer + sizes.total()); | |
585 } | 420 } |
586 } // namespace wasm | 421 } // namespace wasm |
587 } // namespace internal | 422 } // namespace internal |
588 } // namespace v8 | 423 } // namespace v8 |
OLD | NEW |