Chromium Code Reviews| 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 |