| 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 |