OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/signature.h" | 5 #include "src/signature.h" |
6 | 6 |
7 #include "src/handles.h" | 7 #include "src/handles.h" |
8 #include "src/objects-inl.h" | 8 #include "src/objects-inl.h" |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 #include "src/zone/zone-containers.h" | 10 #include "src/zone/zone-containers.h" |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 | 178 |
179 void WasmFunctionBuilder::SetAsmFunctionStartPosition(int position) { | 179 void WasmFunctionBuilder::SetAsmFunctionStartPosition(int position) { |
180 DCHECK_EQ(0, asm_func_start_source_position_); | 180 DCHECK_EQ(0, asm_func_start_source_position_); |
181 DCHECK_LE(0, position); | 181 DCHECK_LE(0, position); |
182 // Must be called before emitting any asm.js source position. | 182 // Must be called before emitting any asm.js source position. |
183 DCHECK_EQ(0, asm_offsets_.size()); | 183 DCHECK_EQ(0, asm_offsets_.size()); |
184 asm_func_start_source_position_ = position; | 184 asm_func_start_source_position_ = position; |
185 last_asm_source_position_ = position; | 185 last_asm_source_position_ = position; |
186 } | 186 } |
187 | 187 |
| 188 void WasmFunctionBuilder::StashCode(std::vector<byte>* dst, size_t position) { |
| 189 if (dst == nullptr) { |
| 190 body_.resize(position); |
| 191 return; |
| 192 } |
| 193 size_t len = body_.size() - position; |
| 194 dst->resize(len); |
| 195 memcpy(dst->data(), &body_[position], len); |
| 196 body_.resize(position); |
| 197 } |
| 198 |
188 void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const { | 199 void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const { |
189 buffer.write_u32v(signature_index_); | 200 buffer.write_u32v(signature_index_); |
190 } | 201 } |
191 | 202 |
192 void WasmFunctionBuilder::WriteExports(ZoneBuffer& buffer) const { | 203 void WasmFunctionBuilder::WriteExports(ZoneBuffer& buffer) const { |
193 for (auto name : exported_names_) { | 204 for (auto name : exported_names_) { |
194 buffer.write_size(name.size()); | 205 buffer.write_size(name.size()); |
195 buffer.write(reinterpret_cast<const byte*>(name.data()), name.size()); | 206 buffer.write(reinterpret_cast<const byte*>(name.data()), name.size()); |
196 buffer.write_u8(kExternalFunction); | 207 buffer.write_u8(kExternalFunction); |
197 buffer.write_u32v(func_index_ + | 208 buffer.write_u32v(func_index_ + static_cast<uint32_t>( |
198 static_cast<uint32_t>(builder_->imports_.size())); | 209 builder_->function_imports_.size())); |
199 } | 210 } |
200 } | 211 } |
201 | 212 |
202 void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const { | 213 void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const { |
203 size_t locals_size = locals_.Size(); | 214 size_t locals_size = locals_.Size(); |
204 buffer.write_size(locals_size + body_.size()); | 215 buffer.write_size(locals_size + body_.size()); |
205 buffer.EnsureSpace(locals_size); | 216 buffer.EnsureSpace(locals_size); |
206 byte** ptr = buffer.pos_ptr(); | 217 byte** ptr = buffer.pos_ptr(); |
207 locals_.Emit(*ptr); | 218 locals_.Emit(*ptr); |
208 (*ptr) += locals_size; // UGLY: manual bump of position pointer | 219 (*ptr) += locals_size; // UGLY: manual bump of position pointer |
209 if (body_.size() > 0) { | 220 if (body_.size() > 0) { |
210 size_t base = buffer.offset(); | 221 size_t base = buffer.offset(); |
211 buffer.write(&body_[0], body_.size()); | 222 buffer.write(&body_[0], body_.size()); |
212 for (DirectCallIndex call : direct_calls_) { | 223 for (DirectCallIndex call : direct_calls_) { |
213 buffer.patch_u32v( | 224 buffer.patch_u32v( |
214 base + call.offset, | 225 base + call.offset, |
215 call.direct_index + static_cast<uint32_t>(builder_->imports_.size())); | 226 call.direct_index + |
| 227 static_cast<uint32_t>(builder_->function_imports_.size())); |
216 } | 228 } |
217 } | 229 } |
218 } | 230 } |
219 | 231 |
220 void WasmFunctionBuilder::WriteAsmWasmOffsetTable(ZoneBuffer& buffer) const { | 232 void WasmFunctionBuilder::WriteAsmWasmOffsetTable(ZoneBuffer& buffer) const { |
221 if (asm_func_start_source_position_ == 0 && asm_offsets_.size() == 0) { | 233 if (asm_func_start_source_position_ == 0 && asm_offsets_.size() == 0) { |
222 buffer.write_size(0); | 234 buffer.write_size(0); |
223 return; | 235 return; |
224 } | 236 } |
225 size_t locals_enc_size = LEBHelper::sizeof_u32v(locals_.Size()); | 237 size_t locals_enc_size = LEBHelper::sizeof_u32v(locals_.Size()); |
226 size_t func_start_size = | 238 size_t func_start_size = |
227 LEBHelper::sizeof_u32v(asm_func_start_source_position_); | 239 LEBHelper::sizeof_u32v(asm_func_start_source_position_); |
228 buffer.write_size(asm_offsets_.size() + locals_enc_size + func_start_size); | 240 buffer.write_size(asm_offsets_.size() + locals_enc_size + func_start_size); |
229 // Offset of the recorded byte offsets. | 241 // Offset of the recorded byte offsets. |
230 DCHECK_GE(kMaxUInt32, locals_.Size()); | 242 DCHECK_GE(kMaxUInt32, locals_.Size()); |
231 buffer.write_u32v(static_cast<uint32_t>(locals_.Size())); | 243 buffer.write_u32v(static_cast<uint32_t>(locals_.Size())); |
232 // Start position of the function. | 244 // Start position of the function. |
233 buffer.write_u32v(asm_func_start_source_position_); | 245 buffer.write_u32v(asm_func_start_source_position_); |
234 buffer.write(asm_offsets_.begin(), asm_offsets_.size()); | 246 buffer.write(asm_offsets_.begin(), asm_offsets_.size()); |
235 } | 247 } |
236 | 248 |
237 WasmModuleBuilder::WasmModuleBuilder(Zone* zone) | 249 WasmModuleBuilder::WasmModuleBuilder(Zone* zone) |
238 : zone_(zone), | 250 : zone_(zone), |
239 signatures_(zone), | 251 signatures_(zone), |
240 imports_(zone), | 252 function_imports_(zone), |
| 253 global_imports_(zone), |
241 functions_(zone), | 254 functions_(zone), |
242 data_segments_(zone), | 255 data_segments_(zone), |
243 indirect_functions_(zone), | 256 indirect_functions_(zone), |
244 globals_(zone), | 257 globals_(zone), |
245 signature_map_(zone), | 258 signature_map_(zone), |
246 start_function_index_(-1) {} | 259 start_function_index_(-1) {} |
247 | 260 |
248 WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) { | 261 WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) { |
249 functions_.push_back(new (zone_) WasmFunctionBuilder(this)); | 262 functions_.push_back(new (zone_) WasmFunctionBuilder(this)); |
250 // Add the signature if one was provided here. | 263 // Add the signature if one was provided here. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 return ret; | 309 return ret; |
297 } | 310 } |
298 | 311 |
299 void WasmModuleBuilder::SetIndirectFunction(uint32_t indirect, | 312 void WasmModuleBuilder::SetIndirectFunction(uint32_t indirect, |
300 uint32_t direct) { | 313 uint32_t direct) { |
301 indirect_functions_[indirect] = direct; | 314 indirect_functions_[indirect] = direct; |
302 } | 315 } |
303 | 316 |
304 uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length, | 317 uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length, |
305 FunctionSig* sig) { | 318 FunctionSig* sig) { |
306 imports_.push_back({AddSignature(sig), name, name_length}); | 319 function_imports_.push_back({AddSignature(sig), name, name_length}); |
307 return static_cast<uint32_t>(imports_.size() - 1); | 320 return static_cast<uint32_t>(function_imports_.size() - 1); |
| 321 } |
| 322 |
| 323 uint32_t WasmModuleBuilder::AddGlobalImport(const char* name, int name_length, |
| 324 ValueType type) { |
| 325 global_imports_.push_back( |
| 326 {WasmOpcodes::ValueTypeCodeFor(type), name, name_length}); |
| 327 return static_cast<uint32_t>(global_imports_.size() - 1); |
308 } | 328 } |
309 | 329 |
310 void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) { | 330 void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) { |
311 start_function_index_ = function->func_index(); | 331 start_function_index_ = function->func_index(); |
312 } | 332 } |
313 | 333 |
314 uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported, | 334 uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported, |
315 bool mutability, | 335 bool mutability, |
316 const WasmInitExpr& init) { | 336 const WasmInitExpr& init) { |
317 globals_.push_back({type, exported, mutability, init}); | 337 globals_.push_back({type, exported, mutability, init}); |
(...skipping 21 matching lines...) Expand all Loading... |
339 } | 359 } |
340 buffer.write_size(sig->return_count()); | 360 buffer.write_size(sig->return_count()); |
341 for (auto ret : sig->returns()) { | 361 for (auto ret : sig->returns()) { |
342 buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(ret)); | 362 buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(ret)); |
343 } | 363 } |
344 } | 364 } |
345 FixupSection(buffer, start); | 365 FixupSection(buffer, start); |
346 } | 366 } |
347 | 367 |
348 // == Emit imports =========================================================== | 368 // == Emit imports =========================================================== |
349 if (imports_.size() > 0) { | 369 if (global_imports_.size() + function_imports_.size() > 0) { |
350 size_t start = EmitSection(kImportSectionCode, buffer); | 370 size_t start = EmitSection(kImportSectionCode, buffer); |
351 buffer.write_size(imports_.size()); | 371 buffer.write_size(global_imports_.size() + function_imports_.size()); |
352 for (auto import : imports_) { | 372 for (auto import : global_imports_) { |
353 buffer.write_u32v(0); // module name length | 373 buffer.write_u32v(0); // module name length |
354 buffer.write_u32v(import.name_length); // field name length | 374 buffer.write_u32v(import.name_length); // field name length |
355 buffer.write(reinterpret_cast<const byte*>(import.name), // field name | 375 buffer.write(reinterpret_cast<const byte*>(import.name), // field name |
| 376 import.name_length); |
| 377 buffer.write_u8(kExternalGlobal); |
| 378 buffer.write_u8(import.type_code); |
| 379 buffer.write_u8(0); // immutable |
| 380 } |
| 381 for (auto import : function_imports_) { |
| 382 buffer.write_u32v(0); // module name length |
| 383 buffer.write_u32v(import.name_length); // field name length |
| 384 buffer.write(reinterpret_cast<const byte*>(import.name), // field name |
356 import.name_length); | 385 import.name_length); |
357 buffer.write_u8(kExternalFunction); | 386 buffer.write_u8(kExternalFunction); |
358 buffer.write_u32v(import.sig_index); | 387 buffer.write_u32v(import.sig_index); |
359 } | 388 } |
360 FixupSection(buffer, start); | 389 FixupSection(buffer, start); |
361 } | 390 } |
362 | 391 |
363 // == Emit function signatures =============================================== | 392 // == Emit function signatures =============================================== |
364 bool has_names = false; | 393 bool has_names = false; |
365 if (functions_.size() > 0) { | 394 if (functions_.size() > 0) { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 size_t start = EmitSection(kExportSectionCode, buffer); | 500 size_t start = EmitSection(kExportSectionCode, buffer); |
472 buffer.write_u32v(exports); | 501 buffer.write_u32v(exports); |
473 for (auto function : functions_) function->WriteExports(buffer); | 502 for (auto function : functions_) function->WriteExports(buffer); |
474 FixupSection(buffer, start); | 503 FixupSection(buffer, start); |
475 } | 504 } |
476 | 505 |
477 // == emit start function index ============================================== | 506 // == emit start function index ============================================== |
478 if (start_function_index_ >= 0) { | 507 if (start_function_index_ >= 0) { |
479 size_t start = EmitSection(kStartSectionCode, buffer); | 508 size_t start = EmitSection(kStartSectionCode, buffer); |
480 buffer.write_u32v(start_function_index_ + | 509 buffer.write_u32v(start_function_index_ + |
481 static_cast<uint32_t>(imports_.size())); | 510 static_cast<uint32_t>(function_imports_.size())); |
482 FixupSection(buffer, start); | 511 FixupSection(buffer, start); |
483 } | 512 } |
484 | 513 |
485 // == emit function table elements =========================================== | 514 // == emit function table elements =========================================== |
486 if (indirect_functions_.size() > 0) { | 515 if (indirect_functions_.size() > 0) { |
487 size_t start = EmitSection(kElementSectionCode, buffer); | 516 size_t start = EmitSection(kElementSectionCode, buffer); |
488 buffer.write_u8(1); // count of entries | 517 buffer.write_u8(1); // count of entries |
489 buffer.write_u8(0); // table index | 518 buffer.write_u8(0); // table index |
490 buffer.write_u8(kExprI32Const); // offset | 519 buffer.write_u8(kExprI32Const); // offset |
491 buffer.write_u32v(0); | 520 buffer.write_u32v(0); |
492 buffer.write_u8(kExprEnd); | 521 buffer.write_u8(kExprEnd); |
493 buffer.write_size(indirect_functions_.size()); // element count | 522 buffer.write_size(indirect_functions_.size()); // element count |
494 | 523 |
495 for (auto index : indirect_functions_) { | 524 for (auto index : indirect_functions_) { |
496 buffer.write_u32v(index + static_cast<uint32_t>(imports_.size())); | 525 buffer.write_u32v(index + |
| 526 static_cast<uint32_t>(function_imports_.size())); |
497 } | 527 } |
498 | 528 |
499 FixupSection(buffer, start); | 529 FixupSection(buffer, start); |
500 } | 530 } |
501 | 531 |
502 // == emit code ============================================================== | 532 // == emit code ============================================================== |
503 if (functions_.size() > 0) { | 533 if (functions_.size() > 0) { |
504 size_t start = EmitSection(kCodeSectionCode, buffer); | 534 size_t start = EmitSection(kCodeSectionCode, buffer); |
505 buffer.write_size(functions_.size()); | 535 buffer.write_size(functions_.size()); |
506 for (auto function : functions_) { | 536 for (auto function : functions_) { |
(...skipping 21 matching lines...) Expand all Loading... |
528 // == Emit names ============================================================= | 558 // == Emit names ============================================================= |
529 if (has_names) { | 559 if (has_names) { |
530 // Emit the section code. | 560 // Emit the section code. |
531 buffer.write_u8(kUnknownSectionCode); | 561 buffer.write_u8(kUnknownSectionCode); |
532 // Emit a placeholder for the length. | 562 // Emit a placeholder for the length. |
533 size_t start = buffer.reserve_u32v(); | 563 size_t start = buffer.reserve_u32v(); |
534 // Emit the section string. | 564 // Emit the section string. |
535 buffer.write_size(4); | 565 buffer.write_size(4); |
536 buffer.write(reinterpret_cast<const byte*>("name"), 4); | 566 buffer.write(reinterpret_cast<const byte*>("name"), 4); |
537 // Emit the names. | 567 // Emit the names. |
538 size_t count = functions_.size() + imports_.size(); | 568 size_t count = functions_.size() + function_imports_.size(); |
539 buffer.write_size(count); | 569 buffer.write_size(count); |
540 for (size_t i = 0; i < imports_.size(); i++) { | 570 for (size_t i = 0; i < function_imports_.size(); i++) { |
541 buffer.write_u8(0); // empty name for import | 571 buffer.write_u8(0); // empty name for import |
542 buffer.write_u8(0); // no local variables | 572 buffer.write_u8(0); // no local variables |
543 } | 573 } |
544 for (auto function : functions_) { | 574 for (auto function : functions_) { |
545 buffer.write_size(function->name_.size()); | 575 buffer.write_size(function->name_.size()); |
546 buffer.write(reinterpret_cast<const byte*>(function->name_.data()), | 576 buffer.write(reinterpret_cast<const byte*>(function->name_.data()), |
547 function->name_.size()); | 577 function->name_.size()); |
548 buffer.write_u8(0); | 578 buffer.write_u8(0); |
549 } | 579 } |
550 FixupSection(buffer, start); | 580 FixupSection(buffer, start); |
551 } | 581 } |
552 } | 582 } |
553 | 583 |
554 void WasmModuleBuilder::WriteAsmJsOffsetTable(ZoneBuffer& buffer) const { | 584 void WasmModuleBuilder::WriteAsmJsOffsetTable(ZoneBuffer& buffer) const { |
555 // == Emit asm.js offset table =============================================== | 585 // == Emit asm.js offset table =============================================== |
556 buffer.write_size(functions_.size()); | 586 buffer.write_size(functions_.size()); |
557 // Emit the offset table per function. | 587 // Emit the offset table per function. |
558 for (auto function : functions_) { | 588 for (auto function : functions_) { |
559 function->WriteAsmWasmOffsetTable(buffer); | 589 function->WriteAsmWasmOffsetTable(buffer); |
560 } | 590 } |
561 // Append a 0 to indicate that this is an encoded table. | 591 // Append a 0 to indicate that this is an encoded table. |
562 buffer.write_u8(0); | 592 buffer.write_u8(0); |
563 } | 593 } |
564 } // namespace wasm | 594 } // namespace wasm |
565 } // namespace internal | 595 } // namespace internal |
566 } // namespace v8 | 596 } // namespace v8 |
OLD | NEW |