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 17614 : size_t EmitSection(SectionCode code, ZoneBuffer& buffer) {
30 : // Emit the section code.
31 17614 : buffer.write_u8(code);
32 :
33 : // Emit a placeholder for the length.
34 17615 : 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 22623 : buffer.patch_u32v(start, static_cast<uint32_t>(buffer.offset() - start -
40 : kPaddedVarInt32Size));
41 : }
42 :
43 : } // namespace
44 :
45 15593 : 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 62372 : 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 14571 : void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
63 : DCHECK(!locals_.has_sig());
64 : locals_.set_sig(sig);
65 14985 : signature_index_ = builder_->AddSignature(sig);
66 14571 : }
67 :
68 545535 : uint32_t WasmFunctionBuilder::AddLocal(ValueType type) {
69 : DCHECK(locals_.has_sig());
70 545535 : return locals_.AddLocals(1, type);
71 : }
72 :
73 501689 : void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
74 501689 : EmitWithU32V(kExprGetLocal, local_index);
75 501689 : }
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 414 : void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
86 33686 : body_.write(code, code_size);
87 414 : }
88 :
89 12778224 : void WasmFunctionBuilder::Emit(WasmOpcode opcode) { body_.write_u8(opcode); }
90 :
91 151419 : void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
92 151419 : body_.write_u8(opcode);
93 : body_.write_u8(immediate);
94 151419 : }
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 1510135 : void WasmFunctionBuilder::EmitWithI32V(WasmOpcode opcode, int32_t immediate) {
104 1510135 : body_.write_u8(opcode);
105 : body_.write_i32v(immediate);
106 1510135 : }
107 :
108 1281265 : void WasmFunctionBuilder::EmitWithU32V(WasmOpcode opcode, uint32_t immediate) {
109 1281265 : body_.write_u8(opcode);
110 1281265 : body_.write_u32v(immediate);
111 1281265 : }
112 :
113 1468770 : void WasmFunctionBuilder::EmitI32Const(int32_t value) {
114 1468770 : EmitWithI32V(kExprI32Const, value);
115 1468770 : }
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 12648 : void WasmFunctionBuilder::SetName(Vector<const char> name) { name_ = name; }
142 :
143 59287 : 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 59287 : uint32_t byte_offset = static_cast<uint32_t>(body_.size());
150 59287 : asm_offsets_.write_u32v(byte_offset - last_asm_byte_offset_);
151 59287 : last_asm_byte_offset_ = byte_offset;
152 :
153 : DCHECK_GE(std::numeric_limits<uint32_t>::max(), call_position);
154 59287 : uint32_t call_position_u32 = static_cast<uint32_t>(call_position);
155 59287 : 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 59287 : uint32_t to_number_position_u32 = static_cast<uint32_t>(to_number_position);
159 59287 : asm_offsets_.write_i32v(to_number_position_u32 - call_position_u32);
160 59287 : last_asm_source_position_ = to_number_position_u32;
161 59287 : }
162 :
163 12648 : 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 12648 : 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 12648 : asm_func_start_source_position_ = function_position_u32;
171 12648 : last_asm_source_position_ = function_position_u32;
172 12648 : }
173 :
174 392914 : void WasmFunctionBuilder::DeleteCodeAfter(size_t position) {
175 : DCHECK_LE(position, body_.size());
176 : body_.Truncate(position);
177 392914 : }
178 :
179 0 : void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const {
180 14805 : buffer.write_u32v(signature_index_);
181 0 : }
182 :
183 14805 : void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const {
184 14805 : size_t locals_size = locals_.Size();
185 14805 : buffer.write_size(locals_size + body_.size());
186 14805 : buffer.EnsureSpace(locals_size);
187 : byte** ptr = buffer.pos_ptr();
188 14805 : locals_.Emit(*ptr);
189 14805 : (*ptr) += locals_size; // UGLY: manual bump of position pointer
190 14805 : if (body_.size() > 0) {
191 : size_t base = buffer.offset();
192 14805 : buffer.write(body_.begin(), body_.size());
193 48033 : for (DirectCallIndex call : direct_calls_) {
194 33228 : buffer.patch_u32v(
195 : base + call.offset,
196 : call.direct_index +
197 33228 : static_cast<uint32_t>(builder_->function_imports_.size()));
198 : }
199 : }
200 14805 : }
201 :
202 14391 : void WasmFunctionBuilder::WriteAsmWasmOffsetTable(ZoneBuffer& buffer) const {
203 16890 : if (asm_func_start_source_position_ == 0 && asm_offsets_.size() == 0) {
204 2499 : buffer.write_size(0);
205 2499 : return;
206 : }
207 11892 : size_t locals_enc_size = LEBHelper::sizeof_u32v(locals_.Size());
208 : size_t func_start_size =
209 11892 : LEBHelper::sizeof_u32v(asm_func_start_source_position_);
210 11892 : buffer.write_size(asm_offsets_.size() + locals_enc_size + func_start_size);
211 : // Offset of the recorded byte offsets.
212 : DCHECK_GE(kMaxUInt32, locals_.Size());
213 11892 : buffer.write_u32v(static_cast<uint32_t>(locals_.Size()));
214 : // Start position of the function.
215 11892 : buffer.write_u32v(asm_func_start_source_position_);
216 11892 : buffer.write(asm_offsets_.begin(), asm_offsets_.size());
217 : }
218 :
219 4073 : WasmModuleBuilder::WasmModuleBuilder(Zone* zone)
220 : : zone_(zone),
221 : signatures_(zone),
222 : function_imports_(zone),
223 : function_exports_(zone),
224 : global_imports_(zone),
225 : functions_(zone),
226 : data_segments_(zone),
227 : indirect_functions_(zone),
228 : globals_(zone),
229 : signature_map_(zone),
230 : start_function_index_(-1),
231 : min_memory_size_(16),
232 : max_memory_size_(0),
233 : has_max_memory_size_(false),
234 8146 : has_shared_memory_(false) {}
235 :
236 15593 : WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) {
237 46779 : functions_.push_back(new (zone_) WasmFunctionBuilder(this));
238 : // Add the signature if one was provided here.
239 16007 : if (sig) functions_.back()->SetSignature(sig);
240 15593 : return functions_.back();
241 : }
242 :
243 4 : void WasmModuleBuilder::AddDataSegment(const byte* data, uint32_t size,
244 : uint32_t dest) {
245 8 : data_segments_.push_back({ZoneVector<byte>(zone()), dest});
246 : ZoneVector<byte>& vec = data_segments_.back().data;
247 36 : for (uint32_t i = 0; i < size; i++) {
248 16 : vec.push_back(data[i]);
249 : }
250 4 : }
251 :
252 64431 : uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
253 64431 : auto sig_entry = signature_map_.find(*sig);
254 64431 : if (sig_entry != signature_map_.end()) return sig_entry->second;
255 6673 : uint32_t index = static_cast<uint32_t>(signatures_.size());
256 6673 : signature_map_.emplace(*sig, index);
257 6673 : signatures_.push_back(sig);
258 6673 : return index;
259 : }
260 :
261 219 : uint32_t WasmModuleBuilder::AllocateIndirectFunctions(uint32_t count) {
262 219 : uint32_t index = static_cast<uint32_t>(indirect_functions_.size());
263 : DCHECK_GE(FLAG_wasm_max_table_size, index);
264 219 : if (count > FLAG_wasm_max_table_size - index) {
265 : return std::numeric_limits<uint32_t>::max();
266 : }
267 209 : indirect_functions_.resize(indirect_functions_.size() + count);
268 209 : return index;
269 : }
270 :
271 4189 : void WasmModuleBuilder::SetIndirectFunction(uint32_t indirect,
272 : uint32_t direct) {
273 8378 : indirect_functions_[indirect] = direct;
274 4189 : }
275 :
276 2076 : uint32_t WasmModuleBuilder::AddImport(Vector<const char> name,
277 : FunctionSig* sig) {
278 4152 : function_imports_.push_back({name, AddSignature(sig)});
279 2076 : return static_cast<uint32_t>(function_imports_.size() - 1);
280 : }
281 :
282 469 : uint32_t WasmModuleBuilder::AddGlobalImport(Vector<const char> name,
283 : ValueType type) {
284 938 : global_imports_.push_back({name, ValueTypes::ValueTypeCodeFor(type)});
285 469 : return static_cast<uint32_t>(global_imports_.size() - 1);
286 : }
287 :
288 2499 : void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) {
289 2499 : start_function_index_ = function->func_index();
290 2499 : }
291 :
292 4650 : void WasmModuleBuilder::AddExport(Vector<const char> name,
293 : WasmFunctionBuilder* function) {
294 9300 : function_exports_.push_back({name, function->func_index()});
295 4650 : }
296 :
297 2958 : uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported,
298 : bool mutability,
299 : const WasmInitExpr& init) {
300 5916 : globals_.push_back({type, exported, mutability, init});
301 2958 : return static_cast<uint32_t>(globals_.size() - 1);
302 : }
303 :
304 3759 : void WasmModuleBuilder::SetMinMemorySize(uint32_t value) {
305 3759 : min_memory_size_ = value;
306 3759 : }
307 :
308 6 : void WasmModuleBuilder::SetMaxMemorySize(uint32_t value) {
309 6 : has_max_memory_size_ = true;
310 6 : max_memory_size_ = value;
311 6 : }
312 :
313 4 : void WasmModuleBuilder::SetHasSharedMemory() { has_shared_memory_ = true; }
314 :
315 2813 : void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
316 : // == Emit magic =============================================================
317 2813 : buffer.write_u32(kWasmMagic);
318 2813 : buffer.write_u32(kWasmVersion);
319 :
320 : // == Emit signatures ========================================================
321 2813 : if (signatures_.size() > 0) {
322 2809 : size_t start = EmitSection(kTypeSectionCode, buffer);
323 2809 : buffer.write_size(signatures_.size());
324 :
325 9228 : for (FunctionSig* sig : signatures_) {
326 : buffer.write_u8(kWasmFunctionTypeCode);
327 6419 : buffer.write_size(sig->parameter_count());
328 18279 : for (auto param : sig->parameters()) {
329 5930 : buffer.write_u8(ValueTypes::ValueTypeCodeFor(param));
330 : }
331 6419 : buffer.write_size(sig->return_count());
332 13391 : for (auto ret : sig->returns()) {
333 3486 : buffer.write_u8(ValueTypes::ValueTypeCodeFor(ret));
334 : }
335 : }
336 : FixupSection(buffer, start);
337 : }
338 :
339 : // == Emit imports ===========================================================
340 2813 : if (global_imports_.size() + function_imports_.size() > 0) {
341 234 : size_t start = EmitSection(kImportSectionCode, buffer);
342 234 : buffer.write_size(global_imports_.size() + function_imports_.size());
343 703 : for (auto import : global_imports_) {
344 469 : buffer.write_u32v(0); // module name (length)
345 : buffer.write_string(import.name); // field name
346 : buffer.write_u8(kExternalGlobal);
347 : buffer.write_u8(import.type_code);
348 : buffer.write_u8(0); // immutable
349 : }
350 2274 : for (auto import : function_imports_) {
351 2040 : buffer.write_u32v(0); // module name (length)
352 : buffer.write_string(import.name); // field name
353 : buffer.write_u8(kExternalFunction);
354 2040 : buffer.write_u32v(import.sig_index);
355 : }
356 : FixupSection(buffer, start);
357 : }
358 :
359 : // == Emit function signatures ===============================================
360 : uint32_t num_function_names = 0;
361 2813 : if (functions_.size() > 0) {
362 2809 : size_t start = EmitSection(kFunctionSectionCode, buffer);
363 2809 : buffer.write_size(functions_.size());
364 17614 : for (auto function : functions_) {
365 : function->WriteSignature(buffer);
366 14805 : if (!function->name_.empty()) ++num_function_names;
367 : }
368 : FixupSection(buffer, start);
369 : }
370 :
371 : // == emit function table ====================================================
372 2813 : if (indirect_functions_.size() > 0) {
373 45 : size_t start = EmitSection(kTableSectionCode, buffer);
374 : buffer.write_u8(1); // table count
375 : buffer.write_u8(kLocalAnyFunc);
376 : buffer.write_u8(kHasMaximumFlag);
377 45 : buffer.write_size(indirect_functions_.size());
378 45 : buffer.write_size(indirect_functions_.size());
379 : FixupSection(buffer, start);
380 : }
381 :
382 : // == emit memory declaration ================================================
383 : {
384 2813 : size_t start = EmitSection(kMemorySectionCode, buffer);
385 : buffer.write_u8(1); // memory count
386 2813 : if (has_shared_memory_) {
387 4 : buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kSharedAndMaximum
388 : : MemoryFlags::kSharedNoMaximum);
389 : } else {
390 2809 : buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kMaximum
391 : : MemoryFlags::kNoMaximum);
392 : }
393 2813 : buffer.write_u32v(min_memory_size_);
394 2813 : if (has_max_memory_size_) {
395 6 : buffer.write_u32v(max_memory_size_);
396 : }
397 : FixupSection(buffer, start);
398 : }
399 :
400 : // == Emit globals ===========================================================
401 2813 : if (globals_.size() > 0) {
402 793 : size_t start = EmitSection(kGlobalSectionCode, buffer);
403 793 : buffer.write_size(globals_.size());
404 :
405 3565 : for (auto global : globals_) {
406 2772 : buffer.write_u8(ValueTypes::ValueTypeCodeFor(global.type));
407 2772 : buffer.write_u8(global.mutability ? 1 : 0);
408 2772 : switch (global.init.kind) {
409 : case WasmInitExpr::kI32Const:
410 : DCHECK_EQ(kWasmI32, global.type);
411 : buffer.write_u8(kExprI32Const);
412 1949 : buffer.write_i32v(global.init.val.i32_const);
413 : break;
414 : case WasmInitExpr::kI64Const:
415 : DCHECK_EQ(kWasmI64, global.type);
416 : buffer.write_u8(kExprI64Const);
417 0 : buffer.write_i64v(global.init.val.i64_const);
418 : break;
419 : case WasmInitExpr::kF32Const:
420 : DCHECK_EQ(kWasmF32, global.type);
421 : buffer.write_u8(kExprF32Const);
422 60 : buffer.write_f32(global.init.val.f32_const);
423 : break;
424 : case WasmInitExpr::kF64Const:
425 : DCHECK_EQ(kWasmF64, global.type);
426 : buffer.write_u8(kExprF64Const);
427 274 : buffer.write_f64(global.init.val.f64_const);
428 : break;
429 : case WasmInitExpr::kGlobalIndex:
430 : buffer.write_u8(kExprGetGlobal);
431 12 : buffer.write_u32v(global.init.val.global_index);
432 12 : break;
433 : default: {
434 : // No initializer, emit a default value.
435 477 : switch (global.type) {
436 : case kWasmI32:
437 : buffer.write_u8(kExprI32Const);
438 : // LEB encoding of 0.
439 : buffer.write_u8(0);
440 : break;
441 : case kWasmI64:
442 : buffer.write_u8(kExprI64Const);
443 : // LEB encoding of 0.
444 : buffer.write_u8(0);
445 : break;
446 : case kWasmF32:
447 : buffer.write_u8(kExprF32Const);
448 : buffer.write_f32(0.f);
449 : break;
450 : case kWasmF64:
451 : buffer.write_u8(kExprF64Const);
452 : buffer.write_f64(0.);
453 : break;
454 : default:
455 0 : UNREACHABLE();
456 : }
457 : }
458 : }
459 : buffer.write_u8(kExprEnd);
460 : }
461 : FixupSection(buffer, start);
462 : }
463 :
464 : // == emit exports ===========================================================
465 2813 : if (!function_exports_.empty()) {
466 2757 : size_t start = EmitSection(kExportSectionCode, buffer);
467 2757 : buffer.write_size(function_exports_.size());
468 7343 : for (auto function_export : function_exports_) {
469 : buffer.write_string(function_export.name);
470 : buffer.write_u8(kExternalFunction);
471 9172 : buffer.write_size(function_export.function_index +
472 4586 : function_imports_.size());
473 : }
474 : FixupSection(buffer, start);
475 : }
476 :
477 : // == emit start function index ==============================================
478 2813 : if (start_function_index_ >= 0) {
479 2499 : size_t start = EmitSection(kStartSectionCode, buffer);
480 4998 : buffer.write_size(start_function_index_ + function_imports_.size());
481 : FixupSection(buffer, start);
482 : }
483 :
484 : // == emit function table elements ===========================================
485 2813 : if (indirect_functions_.size() > 0) {
486 45 : size_t start = EmitSection(kElementSectionCode, buffer);
487 : buffer.write_u8(1); // count of entries
488 : buffer.write_u8(0); // table index
489 : buffer.write_u8(kExprI32Const); // offset
490 45 : buffer.write_u32v(0);
491 : buffer.write_u8(kExprEnd);
492 45 : buffer.write_size(indirect_functions_.size()); // element count
493 :
494 4230 : for (auto index : indirect_functions_) {
495 8370 : buffer.write_size(index + function_imports_.size());
496 : }
497 :
498 : FixupSection(buffer, start);
499 : }
500 :
501 : // == emit code ==============================================================
502 2813 : if (functions_.size() > 0) {
503 2809 : size_t start = EmitSection(kCodeSectionCode, buffer);
504 2809 : buffer.write_size(functions_.size());
505 17614 : for (auto function : functions_) {
506 14805 : function->WriteBody(buffer);
507 : }
508 : FixupSection(buffer, start);
509 : }
510 :
511 : // == emit data segments =====================================================
512 2813 : if (data_segments_.size() > 0) {
513 4 : size_t start = EmitSection(kDataSectionCode, buffer);
514 4 : buffer.write_size(data_segments_.size());
515 :
516 8 : for (auto segment : data_segments_) {
517 : buffer.write_u8(0); // linear memory segment
518 : buffer.write_u8(kExprI32Const); // initializer expression for dest
519 4 : buffer.write_u32v(segment.dest);
520 : buffer.write_u8(kExprEnd);
521 4 : buffer.write_u32v(static_cast<uint32_t>(segment.data.size()));
522 4 : buffer.write(&segment.data[0], segment.data.size());
523 : }
524 : FixupSection(buffer, start);
525 : }
526 :
527 : // == Emit names =============================================================
528 2813 : if (num_function_names > 0 || !function_imports_.empty()) {
529 : // Emit the section code.
530 : buffer.write_u8(kUnknownSectionCode);
531 : // Emit a placeholder for the length.
532 : size_t start = buffer.reserve_u32v();
533 : // Emit the section string.
534 2503 : buffer.write_size(4);
535 2503 : buffer.write(reinterpret_cast<const byte*>("name"), 4);
536 : // Emit a subsection for the function names.
537 : buffer.write_u8(NameSectionKindCode::kFunction);
538 : // Emit a placeholder for the subsection length.
539 : size_t functions_start = buffer.reserve_u32v();
540 : // Emit the function names.
541 : // Imports are always named.
542 2503 : uint32_t num_imports = static_cast<uint32_t>(function_imports_.size());
543 2503 : buffer.write_size(num_imports + num_function_names);
544 : uint32_t function_index = 0;
545 6583 : for (; function_index < num_imports; ++function_index) {
546 2040 : const WasmFunctionImport* import = &function_imports_[function_index];
547 : DCHECK(!import->name.empty());
548 2040 : buffer.write_u32v(function_index);
549 : buffer.write_string(import->name);
550 : }
551 2503 : if (num_function_names > 0) {
552 16890 : for (auto function : functions_) {
553 : DCHECK_EQ(function_index,
554 : function->func_index() + function_imports_.size());
555 14391 : if (!function->name_.empty()) {
556 11892 : buffer.write_u32v(function_index);
557 : buffer.write_string(function->name_);
558 : }
559 14391 : ++function_index;
560 : }
561 : }
562 : FixupSection(buffer, functions_start);
563 : FixupSection(buffer, start);
564 : }
565 2813 : }
566 :
567 2499 : void WasmModuleBuilder::WriteAsmJsOffsetTable(ZoneBuffer& buffer) const {
568 : // == Emit asm.js offset table ===============================================
569 2499 : buffer.write_size(functions_.size());
570 : // Emit the offset table per function.
571 16890 : for (auto function : functions_) {
572 14391 : function->WriteAsmWasmOffsetTable(buffer);
573 : }
574 : // Append a 0 to indicate that this is an encoded table.
575 : buffer.write_u8(0);
576 2499 : }
577 : } // namespace wasm
578 : } // namespace internal
579 122004 : } // namespace v8
|