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