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/module-decoder.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 24819 : size_t EmitSection(SectionCode code, ZoneBuffer& buffer) {
30 : // Emit the section code.
31 24819 : buffer.write_u8(code);
32 :
33 : // Emit a placeholder for the length.
34 24819 : return buffer.reserve_u32v();
35 : }
36 :
37 : // Patch the size of a section after it's finished.
38 31913 : void FixupSection(ZoneBuffer& buffer, size_t start) {
39 : buffer.patch_u32v(start, static_cast<uint32_t>(buffer.offset() - start -
40 31913 : kPaddedVarInt32Size));
41 31913 : }
42 :
43 : } // namespace
44 :
45 187731 : WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder)
46 : : builder_(builder),
47 : locals_(builder->zone()),
48 : signature_index_(0),
49 20859 : 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 104295 : asm_offsets_(builder->zone(), 8) {}
57 :
58 60308 : void WasmFunctionBuilder::EmitI32V(int32_t val) { body_.write_i32v(val); }
59 :
60 9004 : void WasmFunctionBuilder::EmitU32V(uint32_t val) { body_.write_u32v(val); }
61 :
62 19505 : void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
63 : DCHECK(!locals_.has_sig());
64 : locals_.set_sig(sig);
65 20036 : signature_index_ = builder_->AddSignature(sig);
66 19505 : }
67 :
68 56116 : uint32_t WasmFunctionBuilder::AddLocal(ValueType type) {
69 : DCHECK(locals_.has_sig());
70 56116 : return locals_.AddLocals(1, type);
71 : }
72 :
73 630558 : void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
74 630558 : EmitWithU32V(kExprGetLocal, local_index);
75 630558 : }
76 :
77 59877 : void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) {
78 59877 : EmitWithU32V(kExprSetLocal, local_index);
79 59877 : }
80 :
81 223075 : void WasmFunctionBuilder::EmitTeeLocal(uint32_t local_index) {
82 223075 : EmitWithU32V(kExprTeeLocal, local_index);
83 223075 : }
84 :
85 533 : void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
86 41445 : body_.write(code, code_size);
87 533 : }
88 :
89 3480860 : void WasmFunctionBuilder::Emit(WasmOpcode opcode) { body_.write_u8(opcode); }
90 :
91 188831 : void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
92 188831 : body_.write_u8(opcode);
93 : body_.write_u8(immediate);
94 188831 : }
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 1260464 : void WasmFunctionBuilder::EmitWithI32V(WasmOpcode opcode, int32_t immediate) {
104 1260464 : body_.write_u8(opcode);
105 : body_.write_i32v(immediate);
106 1260464 : }
107 :
108 976025 : void WasmFunctionBuilder::EmitWithU32V(WasmOpcode opcode, uint32_t immediate) {
109 976025 : body_.write_u8(opcode);
110 976025 : body_.write_u32v(immediate);
111 976025 : }
112 :
113 1208026 : void WasmFunctionBuilder::EmitI32Const(int32_t value) {
114 1208026 : EmitWithI32V(kExprI32Const, value);
115 1208026 : }
116 :
117 0 : void WasmFunctionBuilder::EmitI64Const(int64_t value) {
118 0 : body_.write_u8(kExprI64Const);
119 : body_.write_i64v(value);
120 0 : }
121 :
122 48 : void WasmFunctionBuilder::EmitF32Const(float value) {
123 48 : body_.write_u8(kExprF32Const);
124 : body_.write_f32(value);
125 48 : }
126 :
127 12212 : void WasmFunctionBuilder::EmitF64Const(double value) {
128 12212 : body_.write_u8(kExprF64Const);
129 : body_.write_f64(value);
130 12212 : }
131 :
132 40912 : void WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) {
133 : DirectCallIndex call;
134 81824 : call.offset = body_.size();
135 40912 : call.direct_index = index;
136 40912 : direct_calls_.push_back(call);
137 40912 : byte placeholder_bytes[kMaxVarInt32Size] = {0};
138 : EmitCode(placeholder_bytes, arraysize(placeholder_bytes));
139 40912 : }
140 :
141 16733 : void WasmFunctionBuilder::SetName(Vector<const char> name) { name_ = name; }
142 :
143 55615 : void WasmFunctionBuilder::AddAsmWasmOffset(int call_position,
144 : int 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 111230 : uint32_t byte_offset = static_cast<uint32_t>(body_.size());
150 55615 : asm_offsets_.write_u32v(byte_offset - last_asm_byte_offset_);
151 55615 : last_asm_byte_offset_ = byte_offset;
152 :
153 : DCHECK_GE(call_position, 0);
154 55615 : asm_offsets_.write_i32v(call_position - last_asm_source_position_);
155 :
156 : DCHECK_GE(to_number_position, 0);
157 55615 : asm_offsets_.write_i32v(to_number_position - call_position);
158 55615 : last_asm_source_position_ = to_number_position;
159 55615 : }
160 :
161 16733 : void WasmFunctionBuilder::SetAsmFunctionStartPosition(int position) {
162 : DCHECK_EQ(0, asm_func_start_source_position_);
163 : DCHECK_LE(0, position);
164 : // Must be called before emitting any asm.js source position.
165 : DCHECK_EQ(0, asm_offsets_.size());
166 16733 : asm_func_start_source_position_ = position;
167 16733 : last_asm_source_position_ = position;
168 16733 : }
169 :
170 487869 : void WasmFunctionBuilder::DeleteCodeAfter(size_t position) {
171 : DCHECK_LE(position, body_.size());
172 487869 : body_.Truncate(position);
173 487869 : }
174 :
175 0 : void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const {
176 19790 : buffer.write_u32v(signature_index_);
177 0 : }
178 :
179 80426 : void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const {
180 19790 : size_t locals_size = locals_.Size();
181 59370 : buffer.write_size(locals_size + body_.size());
182 19790 : buffer.EnsureSpace(locals_size);
183 : byte** ptr = buffer.pos_ptr();
184 19790 : locals_.Emit(*ptr);
185 19790 : (*ptr) += locals_size; // UGLY: manual bump of position pointer
186 19790 : if (body_.size() > 0) {
187 : size_t base = buffer.offset();
188 19790 : buffer.write(body_.begin(), body_.size());
189 80426 : for (DirectCallIndex call : direct_calls_) {
190 : buffer.patch_u32v(
191 : base + call.offset,
192 : call.direct_index +
193 81692 : static_cast<uint32_t>(builder_->function_imports_.size()));
194 : }
195 : }
196 19790 : }
197 :
198 19259 : void WasmFunctionBuilder::WriteAsmWasmOffsetTable(ZoneBuffer& buffer) const {
199 54230 : if (asm_func_start_source_position_ == 0 && asm_offsets_.size() == 0) {
200 3547 : buffer.write_size(0);
201 22806 : return;
202 : }
203 15712 : size_t locals_enc_size = LEBHelper::sizeof_u32v(locals_.Size());
204 : size_t func_start_size =
205 15712 : LEBHelper::sizeof_u32v(asm_func_start_source_position_);
206 15712 : buffer.write_size(asm_offsets_.size() + locals_enc_size + func_start_size);
207 : // Offset of the recorded byte offsets.
208 : DCHECK_GE(kMaxUInt32, locals_.Size());
209 15712 : buffer.write_u32v(static_cast<uint32_t>(locals_.Size()));
210 : // Start position of the function.
211 15712 : buffer.write_u32v(asm_func_start_source_position_);
212 15712 : buffer.write(asm_offsets_.begin(), asm_offsets_.size());
213 : }
214 :
215 346446 : WasmModuleBuilder::WasmModuleBuilder(Zone* zone)
216 : : zone_(zone),
217 : signatures_(zone),
218 : function_imports_(zone),
219 : function_exports_(zone),
220 : global_imports_(zone),
221 : functions_(zone),
222 : data_segments_(zone),
223 : indirect_functions_(zone),
224 : globals_(zone),
225 : signature_map_(zone),
226 : start_function_index_(-1),
227 : min_memory_size_(16),
228 : max_memory_size_(0),
229 : has_max_memory_size_(false),
230 692892 : has_shared_memory_(false) {}
231 :
232 20859 : WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) {
233 62577 : functions_.push_back(new (zone_) WasmFunctionBuilder(this));
234 : // Add the signature if one was provided here.
235 21390 : if (sig) functions_.back()->SetSignature(sig);
236 20859 : return functions_.back();
237 : }
238 :
239 6 : void WasmModuleBuilder::AddDataSegment(const byte* data, uint32_t size,
240 6 : uint32_t dest) {
241 12 : data_segments_.push_back({ZoneVector<byte>(zone()), dest});
242 : ZoneVector<byte>& vec = data_segments_.back().data;
243 30 : for (uint32_t i = 0; i < size; i++) {
244 24 : vec.push_back(data[i]);
245 : }
246 6 : }
247 :
248 1263550 : bool WasmModuleBuilder::CompareFunctionSigs::operator()(FunctionSig* a,
249 1263550 : FunctionSig* b) const {
250 445157 : if (a->return_count() < b->return_count()) return true;
251 420353 : if (a->return_count() > b->return_count()) return false;
252 389121 : if (a->parameter_count() < b->parameter_count()) return true;
253 265015 : if (a->parameter_count() > b->parameter_count()) return false;
254 79266 : for (size_t r = 0; r < a->return_count(); r++) {
255 93575 : if (a->GetReturn(r) < b->GetReturn(r)) return true;
256 90974 : if (a->GetReturn(r) > b->GetReturn(r)) return false;
257 : }
258 320191 : for (size_t p = 0; p < a->parameter_count(); p++) {
259 335697 : if (a->GetParam(p) < b->GetParam(p)) return true;
260 333319 : if (a->GetParam(p) > b->GetParam(p)) return false;
261 : }
262 : return false;
263 : }
264 :
265 80987 : uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
266 : SignatureMap::iterator pos = signature_map_.find(sig);
267 80987 : if (pos != signature_map_.end()) {
268 71520 : return pos->second;
269 : } else {
270 18934 : uint32_t index = static_cast<uint32_t>(signatures_.size());
271 9467 : signature_map_[sig] = index;
272 9467 : signatures_.push_back(sig);
273 9467 : return index;
274 : }
275 : }
276 :
277 299 : uint32_t WasmModuleBuilder::AllocateIndirectFunctions(uint32_t count) {
278 598 : uint32_t index = static_cast<uint32_t>(indirect_functions_.size());
279 : DCHECK_GE(FLAG_wasm_max_table_size, index);
280 299 : if (count > FLAG_wasm_max_table_size - index) {
281 : return std::numeric_limits<uint32_t>::max();
282 : }
283 285 : indirect_functions_.resize(indirect_functions_.size() + count);
284 285 : return index;
285 : }
286 :
287 5045 : void WasmModuleBuilder::SetIndirectFunction(uint32_t indirect,
288 : uint32_t direct) {
289 10090 : indirect_functions_[indirect] = direct;
290 5045 : }
291 :
292 2836 : uint32_t WasmModuleBuilder::AddImport(Vector<const char> name,
293 : FunctionSig* sig) {
294 5672 : function_imports_.push_back({name, AddSignature(sig)});
295 2836 : return static_cast<uint32_t>(function_imports_.size() - 1);
296 : }
297 :
298 661 : uint32_t WasmModuleBuilder::AddGlobalImport(Vector<const char> name,
299 : ValueType type) {
300 1322 : global_imports_.push_back({name, WasmOpcodes::ValueTypeCodeFor(type)});
301 661 : return static_cast<uint32_t>(global_imports_.size() - 1);
302 : }
303 :
304 3547 : void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) {
305 3547 : start_function_index_ = function->func_index();
306 3547 : }
307 :
308 6514 : void WasmModuleBuilder::AddExport(Vector<const char> name,
309 6514 : WasmFunctionBuilder* function) {
310 19542 : function_exports_.push_back({name, function->func_index()});
311 6514 : }
312 :
313 4217 : uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported,
314 : bool mutability,
315 : const WasmInitExpr& init) {
316 8434 : globals_.push_back({type, exported, mutability, init});
317 4217 : return static_cast<uint32_t>(globals_.size() - 1);
318 : }
319 :
320 346047 : void WasmModuleBuilder::SetMinMemorySize(uint32_t value) {
321 346047 : min_memory_size_ = value;
322 346047 : }
323 :
324 9 : void WasmModuleBuilder::SetMaxMemorySize(uint32_t value) {
325 9 : has_max_memory_size_ = true;
326 9 : max_memory_size_ = value;
327 9 : }
328 :
329 6 : void WasmModuleBuilder::SetHasSharedMemory() { has_shared_memory_ = true; }
330 :
331 3946 : void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
332 : // == Emit magic =============================================================
333 : buffer.write_u32(kWasmMagic);
334 : buffer.write_u32(kWasmVersion);
335 :
336 : // == Emit signatures ========================================================
337 11838 : if (signatures_.size() > 0) {
338 3946 : size_t start = EmitSection(kTypeSectionCode, buffer);
339 3946 : buffer.write_size(signatures_.size());
340 :
341 44348 : for (FunctionSig* sig : signatures_) {
342 : buffer.write_u8(kWasmFunctionTypeForm);
343 9114 : buffer.write_size(sig->parameter_count());
344 17451 : for (auto param : sig->parameters()) {
345 8337 : buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(param));
346 : }
347 9114 : buffer.write_size(sig->return_count());
348 14071 : for (auto ret : sig->returns()) {
349 4957 : buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(ret));
350 : }
351 : }
352 3946 : FixupSection(buffer, start);
353 : }
354 :
355 : // == Emit imports ===========================================================
356 33821 : if (global_imports_.size() + function_imports_.size() > 0) {
357 322 : size_t start = EmitSection(kImportSectionCode, buffer);
358 322 : buffer.write_size(global_imports_.size() + function_imports_.size());
359 1305 : for (auto import : global_imports_) {
360 661 : buffer.write_u32v(0); // module name (length)
361 : buffer.write_string(import.name); // field name
362 : buffer.write_u8(kExternalGlobal);
363 : buffer.write_u8(import.type_code);
364 : buffer.write_u8(0); // immutable
365 : }
366 3426 : for (auto import : function_imports_) {
367 2782 : buffer.write_u32v(0); // module name (length)
368 : buffer.write_string(import.name); // field name
369 : buffer.write_u8(kExternalFunction);
370 2782 : buffer.write_u32v(import.sig_index);
371 : }
372 322 : FixupSection(buffer, start);
373 : }
374 :
375 : // == Emit function signatures ===============================================
376 : uint32_t num_function_names = 0;
377 19730 : if (functions_.size() > 0) {
378 3946 : size_t start = EmitSection(kFunctionSectionCode, buffer);
379 3946 : buffer.write_size(functions_.size());
380 27682 : for (auto function : functions_) {
381 : function->WriteSignature(buffer);
382 19790 : if (!function->name_.is_empty()) ++num_function_names;
383 : }
384 3946 : FixupSection(buffer, start);
385 : }
386 :
387 : // == emit function table ====================================================
388 12033 : if (indirect_functions_.size() > 0) {
389 65 : size_t start = EmitSection(kTableSectionCode, buffer);
390 : buffer.write_u8(1); // table count
391 : buffer.write_u8(kWasmAnyFunctionTypeForm);
392 : buffer.write_u8(kHasMaximumFlag);
393 65 : buffer.write_size(indirect_functions_.size());
394 65 : buffer.write_size(indirect_functions_.size());
395 65 : FixupSection(buffer, start);
396 : }
397 :
398 : // == emit memory declaration ================================================
399 : {
400 3946 : size_t start = EmitSection(kMemorySectionCode, buffer);
401 : buffer.write_u8(1); // memory count
402 3946 : if (has_shared_memory_) {
403 : buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kSharedAndMaximum
404 6 : : MemoryFlags::kSharedNoMaximum);
405 : } else {
406 : buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kMaximum
407 3940 : : MemoryFlags::kNoMaximum);
408 : }
409 3946 : buffer.write_u32v(min_memory_size_);
410 3946 : if (has_max_memory_size_) {
411 9 : buffer.write_u32v(max_memory_size_);
412 : }
413 3946 : FixupSection(buffer, start);
414 : }
415 :
416 : // == Emit globals ===========================================================
417 9036 : if (globals_.size() > 0) {
418 1144 : size_t start = EmitSection(kGlobalSectionCode, buffer);
419 1144 : buffer.write_size(globals_.size());
420 :
421 6247 : for (auto global : globals_) {
422 3959 : buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(global.type));
423 3959 : buffer.write_u8(global.mutability ? 1 : 0);
424 3959 : switch (global.init.kind) {
425 : case WasmInitExpr::kI32Const:
426 : DCHECK_EQ(kWasmI32, global.type);
427 : buffer.write_u8(kExprI32Const);
428 2784 : buffer.write_i32v(global.init.val.i32_const);
429 : break;
430 : case WasmInitExpr::kI64Const:
431 : DCHECK_EQ(kWasmI64, global.type);
432 : buffer.write_u8(kExprI64Const);
433 0 : buffer.write_i64v(global.init.val.i64_const);
434 : break;
435 : case WasmInitExpr::kF32Const:
436 : DCHECK_EQ(kWasmF32, global.type);
437 : buffer.write_u8(kExprF32Const);
438 84 : buffer.write_f32(global.init.val.f32_const);
439 : break;
440 : case WasmInitExpr::kF64Const:
441 : DCHECK_EQ(kWasmF64, global.type);
442 : buffer.write_u8(kExprF64Const);
443 400 : buffer.write_f64(global.init.val.f64_const);
444 : break;
445 : case WasmInitExpr::kGlobalIndex:
446 : buffer.write_u8(kExprGetGlobal);
447 18 : buffer.write_u32v(global.init.val.global_index);
448 18 : break;
449 : default: {
450 : // No initializer, emit a default value.
451 673 : switch (global.type) {
452 : case kWasmI32:
453 : buffer.write_u8(kExprI32Const);
454 : // LEB encoding of 0.
455 : buffer.write_u8(0);
456 : break;
457 : case kWasmI64:
458 : buffer.write_u8(kExprI64Const);
459 : // LEB encoding of 0.
460 : buffer.write_u8(0);
461 : break;
462 : case kWasmF32:
463 : buffer.write_u8(kExprF32Const);
464 : buffer.write_f32(0.f);
465 : break;
466 : case kWasmF64:
467 : buffer.write_u8(kExprF64Const);
468 : buffer.write_f64(0.);
469 : break;
470 : default:
471 0 : UNREACHABLE();
472 : }
473 : }
474 : }
475 : buffer.write_u8(kExprEnd);
476 : }
477 1144 : FixupSection(buffer, start);
478 : }
479 :
480 : // == emit exports ===========================================================
481 7832 : if (!function_exports_.empty()) {
482 3886 : size_t start = EmitSection(kExportSectionCode, buffer);
483 3886 : buffer.write_size(function_exports_.size());
484 14196 : for (auto function_export : function_exports_) {
485 : buffer.write_string(function_export.name);
486 : buffer.write_u8(kExternalFunction);
487 : buffer.write_size(function_export.function_index +
488 12848 : function_imports_.size());
489 : }
490 3886 : FixupSection(buffer, start);
491 : }
492 :
493 : // == emit start function index ==============================================
494 3946 : if (start_function_index_ >= 0) {
495 3547 : size_t start = EmitSection(kStartSectionCode, buffer);
496 7094 : buffer.write_size(start_function_index_ + function_imports_.size());
497 3547 : FixupSection(buffer, start);
498 : }
499 :
500 : // == emit function table elements ===========================================
501 3946 : if (indirect_functions_.size() > 0) {
502 65 : size_t start = EmitSection(kElementSectionCode, buffer);
503 : buffer.write_u8(1); // count of entries
504 : buffer.write_u8(0); // table index
505 : buffer.write_u8(kExprI32Const); // offset
506 65 : buffer.write_u32v(0);
507 : buffer.write_u8(kExprEnd);
508 65 : buffer.write_size(indirect_functions_.size()); // element count
509 :
510 5169 : for (auto index : indirect_functions_) {
511 10078 : buffer.write_size(index + function_imports_.size());
512 : }
513 :
514 65 : FixupSection(buffer, start);
515 : }
516 :
517 : // == emit code ==============================================================
518 3946 : if (functions_.size() > 0) {
519 3946 : size_t start = EmitSection(kCodeSectionCode, buffer);
520 3946 : buffer.write_size(functions_.size());
521 27682 : for (auto function : functions_) {
522 19790 : function->WriteBody(buffer);
523 : }
524 3946 : FixupSection(buffer, start);
525 : }
526 :
527 : // == emit data segments =====================================================
528 7898 : if (data_segments_.size() > 0) {
529 6 : size_t start = EmitSection(kDataSectionCode, buffer);
530 6 : buffer.write_size(data_segments_.size());
531 :
532 18 : for (auto segment : data_segments_) {
533 : buffer.write_u8(0); // linear memory segment
534 : buffer.write_u8(kExprI32Const); // initializer expression for dest
535 6 : buffer.write_u32v(segment.dest);
536 : buffer.write_u8(kExprEnd);
537 12 : buffer.write_u32v(static_cast<uint32_t>(segment.data.size()));
538 12 : buffer.write(&segment.data[0], segment.data.size());
539 : }
540 6 : FixupSection(buffer, start);
541 : }
542 :
543 : // == Emit names =============================================================
544 4345 : if (num_function_names > 0 || !function_imports_.empty()) {
545 : // Emit the section code.
546 : buffer.write_u8(kUnknownSectionCode);
547 : // Emit a placeholder for the length.
548 : size_t start = buffer.reserve_u32v();
549 : // Emit the section string.
550 3547 : buffer.write_size(4);
551 3547 : buffer.write(reinterpret_cast<const byte*>("name"), 4);
552 : // Emit a subsection for the function names.
553 : buffer.write_u8(NameSectionType::kFunction);
554 : // Emit a placeholder for the subsection length.
555 : size_t functions_start = buffer.reserve_u32v();
556 : // Emit the function names.
557 : // Imports are always named.
558 3547 : uint32_t num_imports = static_cast<uint32_t>(function_imports_.size());
559 3547 : buffer.write_size(num_imports + num_function_names);
560 : uint32_t function_index = 0;
561 6329 : for (; function_index < num_imports; ++function_index) {
562 2782 : const WasmFunctionImport* import = &function_imports_[function_index];
563 : DCHECK(!import->name.is_empty());
564 2782 : buffer.write_u32v(function_index);
565 : buffer.write_string(import->name);
566 : }
567 3547 : if (num_function_names > 0) {
568 26353 : for (auto function : functions_) {
569 : DCHECK_EQ(function_index,
570 : function->func_index() + function_imports_.size());
571 19259 : if (!function->name_.is_empty()) {
572 15712 : buffer.write_u32v(function_index);
573 : buffer.write_string(function->name_);
574 : }
575 19259 : ++function_index;
576 : }
577 : }
578 3547 : FixupSection(buffer, functions_start);
579 3547 : FixupSection(buffer, start);
580 : }
581 3946 : }
582 :
583 3547 : void WasmModuleBuilder::WriteAsmJsOffsetTable(ZoneBuffer& buffer) const {
584 : // == Emit asm.js offset table ===============================================
585 7094 : buffer.write_size(functions_.size());
586 : // Emit the offset table per function.
587 26353 : for (auto function : functions_) {
588 19259 : function->WriteAsmWasmOffsetTable(buffer);
589 : }
590 : // Append a 0 to indicate that this is an encoded table.
591 : buffer.write_u8(0);
592 3547 : }
593 : } // namespace wasm
594 : } // namespace internal
595 : } // namespace v8
|