Line data Source code
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
3 : // found in the LICENSE file.
4 :
5 : #include "src/signature.h"
6 :
7 : #include "src/handles.h"
8 : #include "src/objects-inl.h"
9 : #include "src/v8.h"
10 : #include "src/zone/zone-containers.h"
11 :
12 : #include "src/wasm/function-body-decoder.h"
13 : #include "src/wasm/leb-helper.h"
14 : #include "src/wasm/wasm-constants.h"
15 : #include "src/wasm/wasm-module-builder.h"
16 : #include "src/wasm/wasm-module.h"
17 : #include "src/wasm/wasm-opcodes.h"
18 :
19 : #include "src/v8memory.h"
20 :
21 : namespace v8 {
22 : namespace internal {
23 : namespace wasm {
24 :
25 : namespace {
26 :
27 : // Emit a section code and the size as a padded varint that can be patched
28 : // later.
29 17633 : size_t EmitSection(SectionCode code, ZoneBuffer& buffer) {
30 : // Emit the section code.
31 17633 : buffer.write_u8(code);
32 :
33 : // Emit a placeholder for the length.
34 17634 : return buffer.reserve_u32v();
35 : }
36 :
37 : // Patch the size of a section after it's finished.
38 : void FixupSection(ZoneBuffer& buffer, size_t start) {
39 22642 : buffer.patch_u32v(start, static_cast<uint32_t>(buffer.offset() - start -
40 : kPaddedVarInt32Size));
41 : }
42 :
43 : } // namespace
44 :
45 15590 : WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder)
46 : : builder_(builder),
47 : locals_(builder->zone()),
48 : signature_index_(0),
49 : func_index_(static_cast<uint32_t>(builder->functions_.size())),
50 : body_(builder->zone(), 256),
51 : i32_temps_(builder->zone()),
52 : i64_temps_(builder->zone()),
53 : f32_temps_(builder->zone()),
54 : f64_temps_(builder->zone()),
55 : direct_calls_(builder->zone()),
56 62359 : asm_offsets_(builder->zone(), 8) {}
57 :
58 49868 : void WasmFunctionBuilder::EmitI32V(int32_t val) { body_.write_i32v(val); }
59 :
60 8196 : void WasmFunctionBuilder::EmitU32V(uint32_t val) { body_.write_u32v(val); }
61 :
62 14557 : void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
63 : DCHECK(!locals_.has_sig());
64 : locals_.set_sig(sig);
65 14980 : signature_index_ = builder_->AddSignature(sig);
66 14559 : }
67 :
68 545535 : uint32_t WasmFunctionBuilder::AddLocal(ValueType type) {
69 : DCHECK(locals_.has_sig());
70 545535 : return locals_.AddLocals(1, type);
71 : }
72 :
73 501684 : void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
74 501684 : EmitWithU32V(kExprGetLocal, local_index);
75 501684 : }
76 :
77 548954 : void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) {
78 548954 : EmitWithU32V(kExprSetLocal, local_index);
79 548954 : }
80 :
81 179465 : void WasmFunctionBuilder::EmitTeeLocal(uint32_t local_index) {
82 179465 : EmitWithU32V(kExprTeeLocal, local_index);
83 179465 : }
84 :
85 423 : void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
86 33695 : body_.write(code, code_size);
87 423 : }
88 :
89 12778174 : void WasmFunctionBuilder::Emit(WasmOpcode opcode) { body_.write_u8(opcode); }
90 :
91 151417 : void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
92 151417 : body_.write_u8(opcode);
93 : body_.write_u8(immediate);
94 151417 : }
95 :
96 0 : void WasmFunctionBuilder::EmitWithU8U8(WasmOpcode opcode, const byte imm1,
97 : const byte imm2) {
98 0 : body_.write_u8(opcode);
99 : body_.write_u8(imm1);
100 : body_.write_u8(imm2);
101 0 : }
102 :
103 1510123 : void WasmFunctionBuilder::EmitWithI32V(WasmOpcode opcode, int32_t immediate) {
104 1510123 : body_.write_u8(opcode);
105 : body_.write_i32v(immediate);
106 1510123 : }
107 :
108 1281259 : void WasmFunctionBuilder::EmitWithU32V(WasmOpcode opcode, uint32_t immediate) {
109 1281259 : body_.write_u8(opcode);
110 1281258 : body_.write_u32v(immediate);
111 1281258 : }
112 :
113 1468758 : void WasmFunctionBuilder::EmitI32Const(int32_t value) {
114 1468758 : EmitWithI32V(kExprI32Const, value);
115 1468758 : }
116 :
117 0 : void WasmFunctionBuilder::EmitI64Const(int64_t value) {
118 0 : body_.write_u8(kExprI64Const);
119 : body_.write_i64v(value);
120 0 : }
121 :
122 32 : void WasmFunctionBuilder::EmitF32Const(float value) {
123 32 : body_.write_u8(kExprF32Const);
124 : body_.write_f32(value);
125 32 : }
126 :
127 5009357 : void WasmFunctionBuilder::EmitF64Const(double value) {
128 5009357 : body_.write_u8(kExprF64Const);
129 : body_.write_f64(value);
130 5009357 : }
131 :
132 33272 : void WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) {
133 : DirectCallIndex call;
134 33272 : call.offset = body_.size();
135 33272 : call.direct_index = index;
136 33272 : direct_calls_.push_back(call);
137 33272 : byte placeholder_bytes[kMaxVarInt32Size] = {0};
138 : EmitCode(placeholder_bytes, arraysize(placeholder_bytes));
139 33272 : }
140 :
141 12639 : void WasmFunctionBuilder::SetName(Vector<const char> name) { name_ = name; }
142 :
143 59286 : void WasmFunctionBuilder::AddAsmWasmOffset(size_t call_position,
144 : size_t to_number_position) {
145 : // We only want to emit one mapping per byte offset.
146 : DCHECK(asm_offsets_.size() == 0 || body_.size() > last_asm_byte_offset_);
147 :
148 : DCHECK_LE(body_.size(), kMaxUInt32);
149 59286 : uint32_t byte_offset = static_cast<uint32_t>(body_.size());
150 59286 : asm_offsets_.write_u32v(byte_offset - last_asm_byte_offset_);
151 59286 : last_asm_byte_offset_ = byte_offset;
152 :
153 : DCHECK_GE(std::numeric_limits<uint32_t>::max(), call_position);
154 59286 : uint32_t call_position_u32 = static_cast<uint32_t>(call_position);
155 59286 : asm_offsets_.write_i32v(call_position_u32 - last_asm_source_position_);
156 :
157 : DCHECK_GE(std::numeric_limits<uint32_t>::max(), to_number_position);
158 59286 : uint32_t to_number_position_u32 = static_cast<uint32_t>(to_number_position);
159 59286 : asm_offsets_.write_i32v(to_number_position_u32 - call_position_u32);
160 59286 : last_asm_source_position_ = to_number_position_u32;
161 59286 : }
162 :
163 12639 : void WasmFunctionBuilder::SetAsmFunctionStartPosition(
164 : size_t function_position) {
165 : DCHECK_EQ(0, asm_func_start_source_position_);
166 : DCHECK_GE(std::numeric_limits<uint32_t>::max(), function_position);
167 12639 : uint32_t function_position_u32 = static_cast<uint32_t>(function_position);
168 : // Must be called before emitting any asm.js source position.
169 : DCHECK_EQ(0, asm_offsets_.size());
170 12639 : asm_func_start_source_position_ = function_position_u32;
171 12639 : last_asm_source_position_ = function_position_u32;
172 12639 : }
173 :
174 9 : void WasmFunctionBuilder::SetCompilationHint(
175 : WasmCompilationHintStrategy strategy, WasmCompilationHintTier baseline,
176 : WasmCompilationHintTier top_tier) {
177 : uint8_t hint_byte = static_cast<uint8_t>(strategy) |
178 9 : static_cast<uint8_t>(baseline) << 2 |
179 9 : static_cast<uint8_t>(top_tier) << 4;
180 : DCHECK_NE(hint_byte, kNoCompilationHint);
181 9 : hint_ = hint_byte;
182 9 : }
183 :
184 392907 : void WasmFunctionBuilder::DeleteCodeAfter(size_t position) {
185 : DCHECK_LE(position, body_.size());
186 : body_.Truncate(position);
187 392907 : }
188 :
189 0 : void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const {
190 14802 : buffer.write_u32v(signature_index_);
191 0 : }
192 :
193 14800 : void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const {
194 14800 : size_t locals_size = locals_.Size();
195 14800 : buffer.write_size(locals_size + body_.size());
196 14800 : buffer.EnsureSpace(locals_size);
197 : byte** ptr = buffer.pos_ptr();
198 14800 : locals_.Emit(*ptr);
199 14800 : (*ptr) += locals_size; // UGLY: manual bump of position pointer
200 14800 : if (body_.size() > 0) {
201 : size_t base = buffer.offset();
202 14800 : buffer.write(body_.begin(), body_.size());
203 48028 : for (DirectCallIndex call : direct_calls_) {
204 33228 : buffer.patch_u32v(
205 : base + call.offset,
206 : call.direct_index +
207 33228 : static_cast<uint32_t>(builder_->function_imports_.size()));
208 : }
209 : }
210 14800 : }
211 :
212 14377 : void WasmFunctionBuilder::WriteAsmWasmOffsetTable(ZoneBuffer& buffer) const {
213 16872 : if (asm_func_start_source_position_ == 0 && asm_offsets_.size() == 0) {
214 2495 : buffer.write_size(0);
215 2495 : return;
216 : }
217 11882 : size_t locals_enc_size = LEBHelper::sizeof_u32v(locals_.Size());
218 : size_t func_start_size =
219 11882 : LEBHelper::sizeof_u32v(asm_func_start_source_position_);
220 11882 : buffer.write_size(asm_offsets_.size() + locals_enc_size + func_start_size);
221 : // Offset of the recorded byte offsets.
222 : DCHECK_GE(kMaxUInt32, locals_.Size());
223 11882 : buffer.write_u32v(static_cast<uint32_t>(locals_.Size()));
224 : // Start position of the function.
225 11881 : buffer.write_u32v(asm_func_start_source_position_);
226 11880 : buffer.write(asm_offsets_.begin(), asm_offsets_.size());
227 : }
228 :
229 4078 : WasmModuleBuilder::WasmModuleBuilder(Zone* zone)
230 : : zone_(zone),
231 : signatures_(zone),
232 : function_imports_(zone),
233 : function_exports_(zone),
234 : global_imports_(zone),
235 : functions_(zone),
236 : data_segments_(zone),
237 : indirect_functions_(zone),
238 : globals_(zone),
239 : signature_map_(zone),
240 : start_function_index_(-1),
241 : min_memory_size_(16),
242 : max_memory_size_(0),
243 : has_max_memory_size_(false),
244 8157 : has_shared_memory_(false) {}
245 :
246 15590 : WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) {
247 46771 : functions_.push_back(new (zone_) WasmFunctionBuilder(this));
248 : // Add the signature if one was provided here.
249 16013 : if (sig) functions_.back()->SetSignature(sig);
250 15590 : return functions_.back();
251 : }
252 :
253 4 : void WasmModuleBuilder::AddDataSegment(const byte* data, uint32_t size,
254 : uint32_t dest) {
255 8 : data_segments_.push_back({ZoneVector<byte>(zone()), dest});
256 : ZoneVector<byte>& vec = data_segments_.back().data;
257 36 : for (uint32_t i = 0; i < size; i++) {
258 16 : vec.push_back(data[i]);
259 : }
260 4 : }
261 :
262 64418 : uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
263 64418 : auto sig_entry = signature_map_.find(*sig);
264 64420 : if (sig_entry != signature_map_.end()) return sig_entry->second;
265 6669 : uint32_t index = static_cast<uint32_t>(signatures_.size());
266 6669 : signature_map_.emplace(*sig, index);
267 6670 : signatures_.push_back(sig);
268 6669 : return index;
269 : }
270 :
271 219 : uint32_t WasmModuleBuilder::AllocateIndirectFunctions(uint32_t count) {
272 219 : uint32_t index = static_cast<uint32_t>(indirect_functions_.size());
273 : DCHECK_GE(FLAG_wasm_max_table_size, index);
274 219 : if (count > FLAG_wasm_max_table_size - index) {
275 : return std::numeric_limits<uint32_t>::max();
276 : }
277 209 : indirect_functions_.resize(indirect_functions_.size() + count);
278 209 : return index;
279 : }
280 :
281 4189 : void WasmModuleBuilder::SetIndirectFunction(uint32_t indirect,
282 : uint32_t direct) {
283 8378 : indirect_functions_[indirect] = direct;
284 4189 : }
285 :
286 2076 : uint32_t WasmModuleBuilder::AddImport(Vector<const char> name,
287 : FunctionSig* sig) {
288 4152 : function_imports_.push_back({name, AddSignature(sig)});
289 2076 : return static_cast<uint32_t>(function_imports_.size() - 1);
290 : }
291 :
292 469 : uint32_t WasmModuleBuilder::AddGlobalImport(Vector<const char> name,
293 : ValueType type) {
294 938 : global_imports_.push_back({name, ValueTypes::ValueTypeCodeFor(type)});
295 469 : return static_cast<uint32_t>(global_imports_.size() - 1);
296 : }
297 :
298 2494 : void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) {
299 2494 : start_function_index_ = function->func_index();
300 2494 : }
301 :
302 4655 : void WasmModuleBuilder::AddExport(Vector<const char> name,
303 : WasmFunctionBuilder* function) {
304 9309 : function_exports_.push_back({name, function->func_index()});
305 4654 : }
306 :
307 2956 : uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported,
308 : bool mutability,
309 : const WasmInitExpr& init) {
310 5912 : globals_.push_back({type, exported, mutability, init});
311 2956 : return static_cast<uint32_t>(globals_.size() - 1);
312 : }
313 :
314 3755 : void WasmModuleBuilder::SetMinMemorySize(uint32_t value) {
315 3755 : min_memory_size_ = value;
316 3755 : }
317 :
318 6 : void WasmModuleBuilder::SetMaxMemorySize(uint32_t value) {
319 6 : has_max_memory_size_ = true;
320 6 : max_memory_size_ = value;
321 6 : }
322 :
323 4 : void WasmModuleBuilder::SetHasSharedMemory() { has_shared_memory_ = true; }
324 :
325 2817 : void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
326 : // == Emit magic =============================================================
327 2817 : buffer.write_u32(kWasmMagic);
328 2818 : buffer.write_u32(kWasmVersion);
329 :
330 : // == Emit signatures ========================================================
331 2818 : if (signatures_.size() > 0) {
332 2813 : size_t start = EmitSection(kTypeSectionCode, buffer);
333 2814 : buffer.write_size(signatures_.size());
334 :
335 9228 : for (FunctionSig* sig : signatures_) {
336 : buffer.write_u8(kWasmFunctionTypeCode);
337 6415 : buffer.write_size(sig->parameter_count());
338 18249 : for (auto param : sig->parameters()) {
339 5918 : buffer.write_u8(ValueTypes::ValueTypeCodeFor(param));
340 : }
341 6414 : buffer.write_size(sig->return_count());
342 13391 : for (auto ret : sig->returns()) {
343 3489 : buffer.write_u8(ValueTypes::ValueTypeCodeFor(ret));
344 : }
345 : }
346 : FixupSection(buffer, start);
347 : }
348 :
349 : // == Emit imports ===========================================================
350 2819 : if (global_imports_.size() + function_imports_.size() > 0) {
351 234 : size_t start = EmitSection(kImportSectionCode, buffer);
352 234 : buffer.write_size(global_imports_.size() + function_imports_.size());
353 703 : for (auto import : global_imports_) {
354 469 : buffer.write_u32v(0); // module name (length)
355 : buffer.write_string(import.name); // field name
356 : buffer.write_u8(kExternalGlobal);
357 : buffer.write_u8(import.type_code);
358 : buffer.write_u8(0); // immutable
359 : }
360 2274 : for (auto import : function_imports_) {
361 2040 : buffer.write_u32v(0); // module name (length)
362 : buffer.write_string(import.name); // field name
363 : buffer.write_u8(kExternalFunction);
364 2040 : buffer.write_u32v(import.sig_index);
365 : }
366 : FixupSection(buffer, start);
367 : }
368 :
369 : // == Emit function signatures ===============================================
370 : uint32_t num_function_names = 0;
371 2819 : if (functions_.size() > 0) {
372 2813 : size_t start = EmitSection(kFunctionSectionCode, buffer);
373 2814 : buffer.write_size(functions_.size());
374 17616 : for (auto* function : functions_) {
375 : function->WriteSignature(buffer);
376 14802 : if (!function->name_.empty()) ++num_function_names;
377 : }
378 : FixupSection(buffer, start);
379 : }
380 :
381 : // == emit function table ====================================================
382 2820 : if (indirect_functions_.size() > 0) {
383 45 : size_t start = EmitSection(kTableSectionCode, buffer);
384 : buffer.write_u8(1); // table count
385 : buffer.write_u8(kLocalAnyFunc);
386 : buffer.write_u8(kHasMaximumFlag);
387 45 : buffer.write_size(indirect_functions_.size());
388 45 : buffer.write_size(indirect_functions_.size());
389 : FixupSection(buffer, start);
390 : }
391 :
392 : // == emit memory declaration ================================================
393 : {
394 2820 : size_t start = EmitSection(kMemorySectionCode, buffer);
395 : buffer.write_u8(1); // memory count
396 2817 : if (has_shared_memory_) {
397 4 : buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kSharedAndMaximum
398 : : MemoryFlags::kSharedNoMaximum);
399 : } else {
400 2813 : buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kMaximum
401 : : MemoryFlags::kNoMaximum);
402 : }
403 2817 : buffer.write_u32v(min_memory_size_);
404 2818 : if (has_max_memory_size_) {
405 6 : buffer.write_u32v(max_memory_size_);
406 : }
407 : FixupSection(buffer, start);
408 : }
409 :
410 : // == Emit globals ===========================================================
411 2818 : if (globals_.size() > 0) {
412 791 : size_t start = EmitSection(kGlobalSectionCode, buffer);
413 791 : buffer.write_size(globals_.size());
414 :
415 3561 : for (auto global : globals_) {
416 2770 : buffer.write_u8(ValueTypes::ValueTypeCodeFor(global.type));
417 2770 : buffer.write_u8(global.mutability ? 1 : 0);
418 2770 : switch (global.init.kind) {
419 : case WasmInitExpr::kI32Const:
420 : DCHECK_EQ(kWasmI32, global.type);
421 : buffer.write_u8(kExprI32Const);
422 1947 : buffer.write_i32v(global.init.val.i32_const);
423 : break;
424 : case WasmInitExpr::kI64Const:
425 : DCHECK_EQ(kWasmI64, global.type);
426 : buffer.write_u8(kExprI64Const);
427 0 : buffer.write_i64v(global.init.val.i64_const);
428 : break;
429 : case WasmInitExpr::kF32Const:
430 : DCHECK_EQ(kWasmF32, global.type);
431 : buffer.write_u8(kExprF32Const);
432 60 : buffer.write_f32(global.init.val.f32_const);
433 : break;
434 : case WasmInitExpr::kF64Const:
435 : DCHECK_EQ(kWasmF64, global.type);
436 : buffer.write_u8(kExprF64Const);
437 274 : buffer.write_f64(global.init.val.f64_const);
438 : break;
439 : case WasmInitExpr::kGlobalIndex:
440 : buffer.write_u8(kExprGetGlobal);
441 12 : buffer.write_u32v(global.init.val.global_index);
442 12 : break;
443 : default: {
444 : // No initializer, emit a default value.
445 477 : switch (global.type) {
446 : case kWasmI32:
447 : buffer.write_u8(kExprI32Const);
448 : // LEB encoding of 0.
449 : buffer.write_u8(0);
450 : break;
451 : case kWasmI64:
452 : buffer.write_u8(kExprI64Const);
453 : // LEB encoding of 0.
454 : buffer.write_u8(0);
455 : break;
456 : case kWasmF32:
457 : buffer.write_u8(kExprF32Const);
458 : buffer.write_f32(0.f);
459 : break;
460 : case kWasmF64:
461 : buffer.write_u8(kExprF64Const);
462 : buffer.write_f64(0.);
463 : break;
464 : default:
465 0 : UNREACHABLE();
466 : }
467 : }
468 : }
469 : buffer.write_u8(kExprEnd);
470 : }
471 : FixupSection(buffer, start);
472 : }
473 :
474 : // == emit exports ===========================================================
475 2818 : if (!function_exports_.empty()) {
476 2762 : size_t start = EmitSection(kExportSectionCode, buffer);
477 2762 : buffer.write_size(function_exports_.size());
478 7353 : for (auto function_export : function_exports_) {
479 : buffer.write_string(function_export.name);
480 : buffer.write_u8(kExternalFunction);
481 9182 : buffer.write_size(function_export.function_index +
482 4591 : function_imports_.size());
483 : }
484 : FixupSection(buffer, start);
485 : }
486 :
487 : // == emit start function index ==============================================
488 2818 : if (start_function_index_ >= 0) {
489 2495 : size_t start = EmitSection(kStartSectionCode, buffer);
490 4988 : buffer.write_size(start_function_index_ + function_imports_.size());
491 : FixupSection(buffer, start);
492 : }
493 :
494 : // == emit function table elements ===========================================
495 2817 : if (indirect_functions_.size() > 0) {
496 45 : size_t start = EmitSection(kElementSectionCode, buffer);
497 : buffer.write_u8(1); // count of entries
498 : buffer.write_u8(0); // table index
499 : buffer.write_u8(kExprI32Const); // offset
500 45 : buffer.write_u32v(0);
501 : buffer.write_u8(kExprEnd);
502 45 : buffer.write_size(indirect_functions_.size()); // element count
503 :
504 4230 : for (auto index : indirect_functions_) {
505 8370 : buffer.write_size(index + function_imports_.size());
506 : }
507 :
508 : FixupSection(buffer, start);
509 : }
510 :
511 : // == emit compilation hints section =========================================
512 : bool emit_compilation_hints = false;
513 17608 : for (auto* fn : functions_) {
514 14801 : if (fn->hint_ != kNoCompilationHint) {
515 : emit_compilation_hints = true;
516 : break;
517 : }
518 : }
519 2817 : if (emit_compilation_hints) {
520 : // Emit the section code.
521 : buffer.write_u8(kUnknownSectionCode);
522 : // Emit a placeholder for section length.
523 : size_t start = buffer.reserve_u32v();
524 : // Emit custom section name.
525 : buffer.write_string(CStrVector("compilationHints"));
526 : // Emit hint count.
527 9 : buffer.write_size(functions_.size());
528 : // Emit hint bytes.
529 18 : for (auto* fn : functions_) {
530 : uint8_t hint_byte =
531 9 : fn->hint_ != kNoCompilationHint ? fn->hint_ : kDefaultCompilationHint;
532 : buffer.write_u8(hint_byte);
533 : }
534 : FixupSection(buffer, start);
535 : }
536 :
537 : // == emit code ==============================================================
538 2817 : if (functions_.size() > 0) {
539 2813 : size_t start = EmitSection(kCodeSectionCode, buffer);
540 2814 : buffer.write_size(functions_.size());
541 17614 : for (auto* function : functions_) {
542 14800 : function->WriteBody(buffer);
543 : }
544 : FixupSection(buffer, start);
545 : }
546 :
547 : // == emit data segments =====================================================
548 2818 : if (data_segments_.size() > 0) {
549 4 : size_t start = EmitSection(kDataSectionCode, buffer);
550 4 : buffer.write_size(data_segments_.size());
551 :
552 8 : for (auto segment : data_segments_) {
553 : buffer.write_u8(0); // linear memory segment
554 : buffer.write_u8(kExprI32Const); // initializer expression for dest
555 4 : buffer.write_u32v(segment.dest);
556 : buffer.write_u8(kExprEnd);
557 4 : buffer.write_u32v(static_cast<uint32_t>(segment.data.size()));
558 4 : buffer.write(&segment.data[0], segment.data.size());
559 : }
560 : FixupSection(buffer, start);
561 : }
562 :
563 : // == Emit names =============================================================
564 2818 : if (num_function_names > 0 || !function_imports_.empty()) {
565 : // Emit the section code.
566 : buffer.write_u8(kUnknownSectionCode);
567 : // Emit a placeholder for the length.
568 : size_t start = buffer.reserve_u32v();
569 : // Emit the section string.
570 : buffer.write_string(CStrVector("name"));
571 : // Emit a subsection for the function names.
572 : buffer.write_u8(NameSectionKindCode::kFunction);
573 : // Emit a placeholder for the subsection length.
574 : size_t functions_start = buffer.reserve_u32v();
575 : // Emit the function names.
576 : // Imports are always named.
577 2499 : uint32_t num_imports = static_cast<uint32_t>(function_imports_.size());
578 2499 : buffer.write_size(num_imports + num_function_names);
579 : uint32_t function_index = 0;
580 6579 : for (; function_index < num_imports; ++function_index) {
581 2040 : const WasmFunctionImport* import = &function_imports_[function_index];
582 : DCHECK(!import->name.empty());
583 2040 : buffer.write_u32v(function_index);
584 : buffer.write_string(import->name);
585 : }
586 2499 : if (num_function_names > 0) {
587 16869 : for (auto* function : functions_) {
588 : DCHECK_EQ(function_index,
589 : function->func_index() + function_imports_.size());
590 14375 : if (!function->name_.empty()) {
591 11881 : buffer.write_u32v(function_index);
592 : buffer.write_string(function->name_);
593 : }
594 14375 : ++function_index;
595 : }
596 : }
597 : FixupSection(buffer, functions_start);
598 : FixupSection(buffer, start);
599 : }
600 2818 : }
601 :
602 2494 : void WasmModuleBuilder::WriteAsmJsOffsetTable(ZoneBuffer& buffer) const {
603 : // == Emit asm.js offset table ===============================================
604 2494 : buffer.write_size(functions_.size());
605 : // Emit the offset table per function.
606 16870 : for (auto* function : functions_) {
607 14375 : function->WriteAsmWasmOffsetTable(buffer);
608 : }
609 : // Append a 0 to indicate that this is an encoded table.
610 : buffer.write_u8(0);
611 2495 : }
612 : } // namespace wasm
613 : } // namespace internal
614 122036 : } // namespace v8
|