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 : #if DEBUG
22 : #define TRACE(...) \
23 : do { \
24 : if (FLAG_trace_wasm_encoder) PrintF(__VA_ARGS__); \
25 : } while (false)
26 : #else
27 : #define TRACE(...)
28 : #endif
29 :
30 : namespace v8 {
31 : namespace internal {
32 : namespace wasm {
33 :
34 : namespace {
35 :
36 : // Emit a section code and the size as a padded varint that can be patched
37 : // later.
38 24875 : size_t EmitSection(SectionCode code, ZoneBuffer& buffer) {
39 : // Emit the section code.
40 : buffer.write_u8(code);
41 :
42 : // Emit a placeholder for the length.
43 24875 : return buffer.reserve_u32v();
44 : }
45 :
46 : // Patch the size of a section after it's finished.
47 31143 : void FixupSection(ZoneBuffer& buffer, size_t start) {
48 : buffer.patch_u32v(start, static_cast<uint32_t>(buffer.offset() - start -
49 31143 : kPaddedVarInt32Size));
50 31143 : }
51 :
52 : } // namespace
53 :
54 145565 : WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder)
55 : : builder_(builder),
56 : locals_(builder->zone()),
57 : signature_index_(0),
58 20795 : func_index_(static_cast<uint32_t>(builder->functions_.size())),
59 : body_(builder->zone()),
60 : name_(builder->zone()),
61 : exported_names_(builder->zone()),
62 : i32_temps_(builder->zone()),
63 : i64_temps_(builder->zone()),
64 : f32_temps_(builder->zone()),
65 : f64_temps_(builder->zone()),
66 : direct_calls_(builder->zone()),
67 83180 : asm_offsets_(builder->zone(), 8) {}
68 :
69 5236 : void WasmFunctionBuilder::EmitI32V(int32_t val) { body_.write_i32v(val); }
70 :
71 41327 : void WasmFunctionBuilder::EmitU32V(uint32_t val) { body_.write_u32v(val); }
72 :
73 5681 : void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
74 : DCHECK(!locals_.has_sig());
75 : locals_.set_sig(sig);
76 20596 : signature_index_ = builder_->AddSignature(sig);
77 5681 : }
78 :
79 37808 : uint32_t WasmFunctionBuilder::AddLocal(ValueType type) {
80 : DCHECK(locals_.has_sig());
81 37808 : return locals_.AddLocals(1, type);
82 : }
83 :
84 445830 : void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
85 445830 : EmitWithU32V(kExprGetLocal, local_index);
86 445830 : }
87 :
88 169519 : void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) {
89 169519 : EmitWithU32V(kExprSetLocal, local_index);
90 169519 : }
91 :
92 22026 : void WasmFunctionBuilder::EmitTeeLocal(uint32_t local_index) {
93 22026 : EmitWithU32V(kExprTeeLocal, local_index);
94 22026 : }
95 :
96 411 : void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
97 27160 : body_.write(code, code_size);
98 411 : }
99 :
100 2062800 : void WasmFunctionBuilder::Emit(WasmOpcode opcode) { body_.write_u8(opcode); }
101 :
102 209224 : void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
103 209224 : body_.write_u8(opcode);
104 : body_.write_u8(immediate);
105 209224 : }
106 :
107 0 : void WasmFunctionBuilder::EmitWithU8U8(WasmOpcode opcode, const byte imm1,
108 : const byte imm2) {
109 0 : body_.write_u8(opcode);
110 : body_.write_u8(imm1);
111 : body_.write_u8(imm2);
112 0 : }
113 :
114 518707 : void WasmFunctionBuilder::EmitWithI32V(WasmOpcode opcode, int32_t immediate) {
115 518707 : body_.write_u8(opcode);
116 : body_.write_i32v(immediate);
117 518707 : }
118 :
119 684064 : void WasmFunctionBuilder::EmitWithU32V(WasmOpcode opcode, uint32_t immediate) {
120 684064 : body_.write_u8(opcode);
121 684064 : body_.write_u32v(immediate);
122 684064 : }
123 :
124 513023 : void WasmFunctionBuilder::EmitI32Const(int32_t value) {
125 513023 : EmitWithI32V(kExprI32Const, value);
126 513023 : }
127 :
128 0 : void WasmFunctionBuilder::EmitI64Const(int64_t value) {
129 0 : body_.write_u8(kExprI64Const);
130 : body_.write_i64v(value);
131 0 : }
132 :
133 164 : void WasmFunctionBuilder::EmitF32Const(float value) {
134 164 : body_.write_u8(kExprF32Const);
135 : body_.write_f32(value);
136 164 : }
137 :
138 10104 : void WasmFunctionBuilder::EmitF64Const(double value) {
139 10104 : body_.write_u8(kExprF64Const);
140 : body_.write_f64(value);
141 10104 : }
142 :
143 26749 : void WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) {
144 : DirectCallIndex call;
145 53498 : call.offset = body_.size();
146 26749 : call.direct_index = index;
147 26749 : direct_calls_.push_back(call);
148 26749 : byte placeholder_bytes[kMaxVarInt32Size] = {0};
149 : EmitCode(placeholder_bytes, arraysize(placeholder_bytes));
150 26749 : }
151 :
152 8884 : void WasmFunctionBuilder::ExportAs(Vector<const char> name) {
153 : exported_names_.push_back(ZoneVector<char>(
154 26652 : name.start(), name.start() + name.length(), builder_->zone()));
155 8884 : }
156 :
157 13224 : void WasmFunctionBuilder::SetName(Vector<const char> name) {
158 13224 : name_.resize(name.length());
159 13224 : memcpy(name_.data(), name.start(), name.length());
160 13224 : }
161 :
162 36183 : void WasmFunctionBuilder::AddAsmWasmOffset(int call_position,
163 : int to_number_position) {
164 : // We only want to emit one mapping per byte offset.
165 : DCHECK(asm_offsets_.size() == 0 || body_.size() > last_asm_byte_offset_);
166 :
167 : DCHECK_LE(body_.size(), kMaxUInt32);
168 72366 : uint32_t byte_offset = static_cast<uint32_t>(body_.size());
169 36183 : asm_offsets_.write_u32v(byte_offset - last_asm_byte_offset_);
170 36183 : last_asm_byte_offset_ = byte_offset;
171 :
172 : DCHECK_GE(call_position, 0);
173 36183 : asm_offsets_.write_i32v(call_position - last_asm_source_position_);
174 :
175 : DCHECK_GE(to_number_position, 0);
176 36183 : asm_offsets_.write_i32v(to_number_position - call_position);
177 36183 : last_asm_source_position_ = to_number_position;
178 36183 : }
179 :
180 16738 : void WasmFunctionBuilder::SetAsmFunctionStartPosition(int position) {
181 : DCHECK_EQ(0, asm_func_start_source_position_);
182 : DCHECK_LE(0, position);
183 : // Must be called before emitting any asm.js source position.
184 : DCHECK_EQ(0, asm_offsets_.size());
185 16738 : asm_func_start_source_position_ = position;
186 16738 : last_asm_source_position_ = position;
187 16738 : }
188 :
189 29068 : void WasmFunctionBuilder::DeleteCodeAfter(size_t position) {
190 : DCHECK_LE(position, body_.size());
191 29068 : body_.Truncate(position);
192 29068 : }
193 :
194 0 : void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const {
195 19942 : buffer.write_u32v(signature_index_);
196 0 : }
197 :
198 19942 : void WasmFunctionBuilder::WriteExports(ZoneBuffer& buffer) const {
199 48741 : for (auto name : exported_names_) {
200 17714 : buffer.write_size(name.size());
201 17714 : buffer.write(reinterpret_cast<const byte*>(name.data()), name.size());
202 : buffer.write_u8(kExternalFunction);
203 17714 : buffer.write_size(func_index_ + builder_->function_imports_.size());
204 : }
205 19942 : }
206 :
207 66593 : void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const {
208 19942 : size_t locals_size = locals_.Size();
209 59826 : buffer.write_size(locals_size + body_.size());
210 19942 : buffer.EnsureSpace(locals_size);
211 : byte** ptr = buffer.pos_ptr();
212 19942 : locals_.Emit(*ptr);
213 19942 : (*ptr) += locals_size; // UGLY: manual bump of position pointer
214 19942 : if (body_.size() > 0) {
215 : size_t base = buffer.offset();
216 19942 : buffer.write(body_.begin(), body_.size());
217 66593 : for (DirectCallIndex call : direct_calls_) {
218 : buffer.patch_u32v(
219 : base + call.offset,
220 : call.direct_index +
221 53418 : static_cast<uint32_t>(builder_->function_imports_.size()));
222 : }
223 : }
224 19942 : }
225 :
226 19533 : void WasmFunctionBuilder::WriteAsmWasmOffsetTable(ZoneBuffer& buffer) const {
227 54983 : if (asm_func_start_source_position_ == 0 && asm_offsets_.size() == 0) {
228 3616 : buffer.write_size(0);
229 23149 : return;
230 : }
231 15917 : size_t locals_enc_size = LEBHelper::sizeof_u32v(locals_.Size());
232 : size_t func_start_size =
233 15917 : LEBHelper::sizeof_u32v(asm_func_start_source_position_);
234 15917 : buffer.write_size(asm_offsets_.size() + locals_enc_size + func_start_size);
235 : // Offset of the recorded byte offsets.
236 : DCHECK_GE(kMaxUInt32, locals_.Size());
237 15917 : buffer.write_u32v(static_cast<uint32_t>(locals_.Size()));
238 : // Start position of the function.
239 15917 : buffer.write_u32v(asm_func_start_source_position_);
240 15917 : buffer.write(asm_offsets_.begin(), asm_offsets_.size());
241 : }
242 :
243 355090 : WasmModuleBuilder::WasmModuleBuilder(Zone* zone)
244 : : zone_(zone),
245 : signatures_(zone),
246 : function_imports_(zone),
247 : global_imports_(zone),
248 : functions_(zone),
249 : data_segments_(zone),
250 : indirect_functions_(zone),
251 : globals_(zone),
252 : signature_map_(zone),
253 710180 : start_function_index_(-1) {}
254 :
255 20795 : WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) {
256 62385 : functions_.push_back(new (zone_) WasmFunctionBuilder(this));
257 : // Add the signature if one was provided here.
258 35710 : if (sig) functions_.back()->SetSignature(sig);
259 20795 : return functions_.back();
260 : }
261 :
262 7 : void WasmModuleBuilder::AddDataSegment(const byte* data, uint32_t size,
263 7 : uint32_t dest) {
264 14 : data_segments_.push_back({ZoneVector<byte>(zone()), dest});
265 : ZoneVector<byte>& vec = data_segments_.back().data;
266 35 : for (uint32_t i = 0; i < size; i++) {
267 28 : vec.push_back(data[i]);
268 : }
269 7 : }
270 :
271 307431 : bool WasmModuleBuilder::CompareFunctionSigs::operator()(FunctionSig* a,
272 307431 : FunctionSig* b) const {
273 118289 : if (a->return_count() < b->return_count()) return true;
274 105122 : if (a->return_count() > b->return_count()) return false;
275 93885 : if (a->parameter_count() < b->parameter_count()) return true;
276 67252 : if (a->parameter_count() > b->parameter_count()) return false;
277 19044 : for (size_t r = 0; r < a->return_count(); r++) {
278 22487 : if (a->GetReturn(r) < b->GetReturn(r)) return true;
279 21379 : if (a->GetReturn(r) > b->GetReturn(r)) return false;
280 : }
281 70026 : for (size_t p = 0; p < a->parameter_count(); p++) {
282 72770 : if (a->GetParam(p) < b->GetParam(p)) return true;
283 72147 : if (a->GetParam(p) > b->GetParam(p)) return false;
284 : }
285 : return false;
286 : }
287 :
288 27270 : uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
289 : SignatureMap::iterator pos = signature_map_.find(sig);
290 27270 : if (pos != signature_map_.end()) {
291 17943 : return pos->second;
292 : } else {
293 18654 : uint32_t index = static_cast<uint32_t>(signatures_.size());
294 9327 : signature_map_[sig] = index;
295 9327 : signatures_.push_back(sig);
296 9327 : return index;
297 : }
298 : }
299 :
300 240 : uint32_t WasmModuleBuilder::AllocateIndirectFunctions(uint32_t count) {
301 480 : uint32_t ret = static_cast<uint32_t>(indirect_functions_.size());
302 240 : indirect_functions_.resize(indirect_functions_.size() + count);
303 240 : return ret;
304 : }
305 :
306 2989 : void WasmModuleBuilder::SetIndirectFunction(uint32_t indirect,
307 : uint32_t direct) {
308 5978 : indirect_functions_[indirect] = direct;
309 2989 : }
310 :
311 1053 : uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length,
312 : FunctionSig* sig) {
313 2106 : function_imports_.push_back({AddSignature(sig), name, name_length});
314 1053 : return static_cast<uint32_t>(function_imports_.size() - 1);
315 : }
316 :
317 136 : uint32_t WasmModuleBuilder::AddGlobalImport(const char* name, int name_length,
318 : ValueType type) {
319 : global_imports_.push_back(
320 272 : {WasmOpcodes::ValueTypeCodeFor(type), name, name_length});
321 136 : return static_cast<uint32_t>(global_imports_.size() - 1);
322 : }
323 :
324 4081 : void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) {
325 4081 : start_function_index_ = function->func_index();
326 4081 : }
327 :
328 3141 : uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported,
329 : bool mutability,
330 : const WasmInitExpr& init) {
331 6282 : globals_.push_back({type, exported, mutability, init});
332 3141 : return static_cast<uint32_t>(globals_.size() - 1);
333 : }
334 :
335 4011 : void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
336 : uint32_t exports = 0;
337 :
338 : // == Emit magic =============================================================
339 : TRACE("emit magic\n");
340 : buffer.write_u32(kWasmMagic);
341 : buffer.write_u32(kWasmVersion);
342 :
343 : // == Emit signatures ========================================================
344 12033 : if (signatures_.size() > 0) {
345 4011 : size_t start = EmitSection(kTypeSectionCode, buffer);
346 4011 : buffer.write_size(signatures_.size());
347 :
348 42798 : for (FunctionSig* sig : signatures_) {
349 : buffer.write_u8(kWasmFunctionTypeForm);
350 8694 : buffer.write_size(sig->parameter_count());
351 16231 : for (auto param : sig->parameters()) {
352 7537 : buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(param));
353 : }
354 8694 : buffer.write_size(sig->return_count());
355 13380 : for (auto ret : sig->returns()) {
356 4686 : buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(ret));
357 : }
358 : }
359 4011 : FixupSection(buffer, start);
360 : }
361 :
362 : // == Emit imports ===========================================================
363 23295 : if (global_imports_.size() + function_imports_.size() > 0) {
364 243 : size_t start = EmitSection(kImportSectionCode, buffer);
365 243 : buffer.write_size(global_imports_.size() + function_imports_.size());
366 622 : for (auto import : global_imports_) {
367 136 : buffer.write_u32v(0); // module name length
368 136 : buffer.write_u32v(import.name_length); // field name length
369 : buffer.write(reinterpret_cast<const byte*>(import.name), // field name
370 136 : import.name_length);
371 : buffer.write_u8(kExternalGlobal);
372 : buffer.write_u8(import.type_code);
373 : buffer.write_u8(0); // immutable
374 : }
375 1530 : for (auto import : function_imports_) {
376 1044 : buffer.write_u32v(0); // module name length
377 1044 : buffer.write_u32v(import.name_length); // field name length
378 : buffer.write(reinterpret_cast<const byte*>(import.name), // field name
379 1044 : import.name_length);
380 : buffer.write_u8(kExternalFunction);
381 1044 : buffer.write_u32v(import.sig_index);
382 : }
383 243 : FixupSection(buffer, start);
384 : }
385 :
386 : // == Emit function signatures ===============================================
387 : uint32_t num_function_names = 0;
388 20055 : if (functions_.size() > 0) {
389 4011 : size_t start = EmitSection(kFunctionSectionCode, buffer);
390 4011 : buffer.write_size(functions_.size());
391 27964 : for (auto function : functions_) {
392 : function->WriteSignature(buffer);
393 39884 : exports += static_cast<uint32_t>(function->exported_names_.size());
394 19942 : if (!function->name_.empty()) ++num_function_names;
395 : }
396 4011 : FixupSection(buffer, start);
397 : }
398 :
399 : // == emit function table ====================================================
400 12222 : if (indirect_functions_.size() > 0) {
401 63 : size_t start = EmitSection(kTableSectionCode, buffer);
402 : buffer.write_u8(1); // table count
403 : buffer.write_u8(kWasmAnyFunctionTypeForm);
404 : buffer.write_u8(kResizableMaximumFlag);
405 63 : buffer.write_size(indirect_functions_.size());
406 63 : buffer.write_size(indirect_functions_.size());
407 63 : FixupSection(buffer, start);
408 : }
409 :
410 : // == emit memory declaration ================================================
411 : {
412 4011 : size_t start = EmitSection(kMemorySectionCode, buffer);
413 : buffer.write_u8(1); // memory count
414 4011 : buffer.write_u32v(kResizableMaximumFlag);
415 4011 : buffer.write_u32v(16); // min memory size
416 4011 : buffer.write_u32v(32); // max memory size
417 4011 : FixupSection(buffer, start);
418 : }
419 :
420 : // == Emit globals ===========================================================
421 8850 : if (globals_.size() > 0) {
422 828 : size_t start = EmitSection(kGlobalSectionCode, buffer);
423 828 : buffer.write_size(globals_.size());
424 :
425 4686 : for (auto global : globals_) {
426 3030 : buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(global.type));
427 3030 : buffer.write_u8(global.mutability ? 1 : 0);
428 3030 : switch (global.init.kind) {
429 : case WasmInitExpr::kI32Const:
430 : DCHECK_EQ(kWasmI32, global.type);
431 : buffer.write_u8(kExprI32Const);
432 1212 : buffer.write_i32v(global.init.val.i32_const);
433 : break;
434 : case WasmInitExpr::kI64Const:
435 : DCHECK_EQ(kWasmI64, global.type);
436 : buffer.write_u8(kExprI64Const);
437 0 : buffer.write_i64v(global.init.val.i64_const);
438 : break;
439 : case WasmInitExpr::kF32Const:
440 : DCHECK_EQ(kWasmF32, global.type);
441 : buffer.write_u8(kExprF32Const);
442 74 : buffer.write_f32(global.init.val.f32_const);
443 : break;
444 : case WasmInitExpr::kF64Const:
445 : DCHECK_EQ(kWasmF64, global.type);
446 : buffer.write_u8(kExprF64Const);
447 116 : buffer.write_f64(global.init.val.f64_const);
448 : break;
449 : case WasmInitExpr::kGlobalIndex:
450 : buffer.write_u8(kExprGetGlobal);
451 0 : buffer.write_u32v(global.init.val.global_index);
452 0 : break;
453 : default: {
454 : // No initializer, emit a default value.
455 1628 : switch (global.type) {
456 : case kWasmI32:
457 : buffer.write_u8(kExprI32Const);
458 : // LEB encoding of 0.
459 : buffer.write_u8(0);
460 : break;
461 : case kWasmI64:
462 : buffer.write_u8(kExprI64Const);
463 : // LEB encoding of 0.
464 : buffer.write_u8(0);
465 : break;
466 : case kWasmF32:
467 : buffer.write_u8(kExprF32Const);
468 : buffer.write_f32(0.f);
469 : break;
470 : case kWasmF64:
471 : buffer.write_u8(kExprF64Const);
472 : buffer.write_f64(0.);
473 : break;
474 : default:
475 0 : UNREACHABLE();
476 : }
477 : }
478 : }
479 : buffer.write_u8(kExprEnd);
480 : }
481 828 : FixupSection(buffer, start);
482 : }
483 :
484 : // == emit exports ===========================================================
485 4011 : if (exports > 0) {
486 4011 : size_t start = EmitSection(kExportSectionCode, buffer);
487 4011 : buffer.write_u32v(exports);
488 27964 : for (auto function : functions_) function->WriteExports(buffer);
489 4011 : FixupSection(buffer, start);
490 : }
491 :
492 : // == emit start function index ==============================================
493 4011 : if (start_function_index_ >= 0) {
494 3616 : size_t start = EmitSection(kStartSectionCode, buffer);
495 7232 : buffer.write_size(start_function_index_ + function_imports_.size());
496 3616 : FixupSection(buffer, start);
497 : }
498 :
499 : // == emit function table elements ===========================================
500 4011 : if (indirect_functions_.size() > 0) {
501 63 : size_t start = EmitSection(kElementSectionCode, buffer);
502 : buffer.write_u8(1); // count of entries
503 : buffer.write_u8(0); // table index
504 : buffer.write_u8(kExprI32Const); // offset
505 63 : buffer.write_u32v(0);
506 : buffer.write_u8(kExprEnd);
507 63 : buffer.write_size(indirect_functions_.size()); // element count
508 :
509 3108 : for (auto index : indirect_functions_) {
510 5964 : buffer.write_size(index + function_imports_.size());
511 : }
512 :
513 63 : FixupSection(buffer, start);
514 : }
515 :
516 : // == emit code ==============================================================
517 4011 : if (functions_.size() > 0) {
518 4011 : size_t start = EmitSection(kCodeSectionCode, buffer);
519 4011 : buffer.write_size(functions_.size());
520 27964 : for (auto function : functions_) {
521 19942 : function->WriteBody(buffer);
522 : }
523 4011 : FixupSection(buffer, start);
524 : }
525 :
526 : // == emit data segments =====================================================
527 8029 : if (data_segments_.size() > 0) {
528 7 : size_t start = EmitSection(kDataSectionCode, buffer);
529 7 : buffer.write_size(data_segments_.size());
530 :
531 21 : for (auto segment : data_segments_) {
532 : buffer.write_u8(0); // linear memory segment
533 : buffer.write_u8(kExprI32Const); // initializer expression for dest
534 7 : buffer.write_u32v(segment.dest);
535 : buffer.write_u8(kExprEnd);
536 14 : buffer.write_u32v(static_cast<uint32_t>(segment.data.size()));
537 14 : buffer.write(&segment.data[0], segment.data.size());
538 : }
539 7 : FixupSection(buffer, start);
540 : }
541 :
542 : // == Emit names =============================================================
543 4888 : if (num_function_names > 0 || !function_imports_.empty()) {
544 : // Emit the section code.
545 : buffer.write_u8(kUnknownSectionCode);
546 : // Emit a placeholder for the length.
547 : size_t start = buffer.reserve_u32v();
548 : // Emit the section string.
549 3134 : buffer.write_size(4);
550 3134 : buffer.write(reinterpret_cast<const byte*>("name"), 4);
551 : // Emit a subsection for the function names.
552 : buffer.write_u8(NameSectionType::kFunction);
553 : // Emit a placeholder for the subsection length.
554 : size_t functions_start = buffer.reserve_u32v();
555 : // Emit the function names.
556 : // Imports are always named.
557 3134 : uint32_t num_imports = static_cast<uint32_t>(function_imports_.size());
558 3134 : buffer.write_size(num_imports + num_function_names);
559 : uint32_t function_index = 0;
560 4178 : for (; function_index < num_imports; ++function_index) {
561 1044 : const WasmFunctionImport* import = &function_imports_[function_index];
562 : DCHECK_NOT_NULL(import->name);
563 1044 : buffer.write_u32v(function_index);
564 1044 : uint32_t name_len = static_cast<uint32_t>(import->name_length);
565 1044 : buffer.write_u32v(name_len);
566 1044 : buffer.write(reinterpret_cast<const byte*>(import->name), name_len);
567 : }
568 3134 : if (num_function_names > 0) {
569 24837 : for (auto function : functions_) {
570 : DCHECK_EQ(function_index,
571 : function->func_index() + function_imports_.size());
572 44269 : if (!function->name_.empty()) {
573 12850 : buffer.write_u32v(function_index);
574 12850 : buffer.write_size(function->name_.size());
575 : buffer.write(reinterpret_cast<const byte*>(function->name_.data()),
576 12850 : function->name_.size());
577 : }
578 18569 : ++function_index;
579 : }
580 : }
581 3134 : FixupSection(buffer, functions_start);
582 3134 : FixupSection(buffer, start);
583 : }
584 4011 : }
585 :
586 3616 : void WasmModuleBuilder::WriteAsmJsOffsetTable(ZoneBuffer& buffer) const {
587 : // == Emit asm.js offset table ===============================================
588 7232 : buffer.write_size(functions_.size());
589 : // Emit the offset table per function.
590 26765 : for (auto function : functions_) {
591 19533 : function->WriteAsmWasmOffsetTable(buffer);
592 : }
593 : // Append a 0 to indicate that this is an encoded table.
594 : buffer.write_u8(0);
595 3616 : }
596 : } // namespace wasm
597 : } // namespace internal
598 : } // namespace v8
|