| 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 size_t len = body_.size() - position; |
| 190 if (dst != nullptr) { |
| 191 dst->resize(body_.size() - position); |
| 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 |