| 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/wasm/wasm-objects.h" | 5 #include "src/wasm/wasm-objects.h" |
| 6 #include "src/utils.h" | 6 #include "src/utils.h" |
| 7 | 7 |
| 8 #include "src/wasm/module-decoder.h" | 8 #include "src/wasm/module-decoder.h" |
| 9 #include "src/wasm/wasm-module.h" | 9 #include "src/wasm/wasm-module.h" |
| 10 #include "src/wasm/wasm-text.h" | 10 #include "src/wasm/wasm-text.h" |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 WasmFunction& function = module()->functions[func_index]; | 454 WasmFunction& function = module()->functions[func_index]; |
| 455 | 455 |
| 456 info->line = func_index; | 456 info->line = func_index; |
| 457 info->column = position - function.code_start_offset; | 457 info->column = position - function.code_start_offset; |
| 458 info->line_start = function.code_start_offset; | 458 info->line_start = function.code_start_offset; |
| 459 info->line_end = function.code_end_offset; | 459 info->line_end = function.code_end_offset; |
| 460 return true; | 460 return true; |
| 461 } | 461 } |
| 462 | 462 |
| 463 namespace { | 463 namespace { |
| 464 | |
| 465 enum AsmJsOffsetTableEntryLayout { | |
| 466 kOTEByteOffset, | |
| 467 kOTECallPosition, | |
| 468 kOTENumberConvPosition, | |
| 469 kOTESize | |
| 470 }; | |
| 471 | |
| 472 Handle<ByteArray> GetDecodedAsmJsOffsetTable( | 464 Handle<ByteArray> GetDecodedAsmJsOffsetTable( |
| 473 Handle<WasmCompiledModule> compiled_module, Isolate* isolate) { | 465 Handle<WasmCompiledModule> compiled_module, Isolate* isolate) { |
| 474 DCHECK(compiled_module->has_asm_js_offset_table()); | 466 DCHECK(compiled_module->has_asm_js_offset_table()); |
| 475 Handle<ByteArray> offset_table = compiled_module->asm_js_offset_table(); | 467 Handle<ByteArray> offset_table = compiled_module->asm_js_offset_table(); |
| 476 | 468 |
| 477 // The last byte in the asm_js_offset_tables ByteArray tells whether it is | 469 // The last byte in the asm_js_offset_tables ByteArray tells whether it is |
| 478 // still encoded (0) or decoded (1). | 470 // still encoded (0) or decoded (1). |
| 479 enum AsmJsTableType : int { Encoded = 0, Decoded = 1 }; | 471 enum AsmJsTableType : int { Encoded = 0, Decoded = 1 }; |
| 480 int table_type = offset_table->get(offset_table->length() - 1); | 472 int table_type = offset_table->get(offset_table->length() - 1); |
| 481 DCHECK(table_type == Encoded || table_type == Decoded); | 473 DCHECK(table_type == Encoded || table_type == Decoded); |
| 482 if (table_type == Decoded) return offset_table; | 474 if (table_type == Decoded) return offset_table; |
| 483 | 475 |
| 484 AsmJsOffsetsResult asm_offsets; | 476 AsmJsOffsetsResult asm_offsets; |
| 485 { | 477 { |
| 486 DisallowHeapAllocation no_gc; | 478 DisallowHeapAllocation no_gc; |
| 487 const byte* bytes_start = offset_table->GetDataStartAddress(); | 479 const byte* bytes_start = offset_table->GetDataStartAddress(); |
| 488 const byte* bytes_end = bytes_start + offset_table->length() - 1; | 480 const byte* bytes_end = bytes_start + offset_table->length() - 1; |
| 489 asm_offsets = wasm::DecodeAsmJsOffsets(bytes_start, bytes_end); | 481 asm_offsets = wasm::DecodeAsmJsOffsets(bytes_start, bytes_end); |
| 490 } | 482 } |
| 491 // Wasm bytes must be valid and must contain asm.js offset table. | 483 // Wasm bytes must be valid and must contain asm.js offset table. |
| 492 DCHECK(asm_offsets.ok()); | 484 DCHECK(asm_offsets.ok()); |
| 493 DCHECK_GE(kMaxInt, asm_offsets.val.size()); | 485 DCHECK_GE(kMaxInt, asm_offsets.val.size()); |
| 494 int num_functions = static_cast<int>(asm_offsets.val.size()); | 486 int num_functions = static_cast<int>(asm_offsets.val.size()); |
| 495 int num_imported_functions = | 487 int num_imported_functions = |
| 496 static_cast<int>(compiled_module->module()->num_imported_functions); | 488 static_cast<int>(compiled_module->module()->num_imported_functions); |
| 497 DCHECK_EQ(compiled_module->module()->functions.size(), | 489 DCHECK_EQ(compiled_module->module()->functions.size(), |
| 498 static_cast<size_t>(num_functions) + num_imported_functions); | 490 static_cast<size_t>(num_functions) + num_imported_functions); |
| 499 int num_entries = 0; | 491 // One byte to encode that this is a decoded table. |
| 492 int total_size = 1; |
| 500 for (int func = 0; func < num_functions; ++func) { | 493 for (int func = 0; func < num_functions; ++func) { |
| 501 size_t new_size = asm_offsets.val[func].size(); | 494 size_t new_size = asm_offsets.val[func].size() * 2 * kIntSize; |
| 502 DCHECK_LE(new_size, static_cast<size_t>(kMaxInt) - num_entries); | 495 DCHECK_LE(new_size, static_cast<size_t>(kMaxInt) - total_size); |
| 503 num_entries += static_cast<int>(new_size); | 496 total_size += static_cast<int>(new_size); |
| 504 } | 497 } |
| 505 // One byte to encode that this is a decoded table. | |
| 506 DCHECK_GE(kMaxInt, | |
| 507 1 + static_cast<uint64_t>(num_entries) * kOTESize * kIntSize); | |
| 508 int total_size = 1 + num_entries * kOTESize * kIntSize; | |
| 509 Handle<ByteArray> decoded_table = | 498 Handle<ByteArray> decoded_table = |
| 510 isolate->factory()->NewByteArray(total_size, TENURED); | 499 isolate->factory()->NewByteArray(total_size, TENURED); |
| 511 decoded_table->set(total_size - 1, AsmJsTableType::Decoded); | 500 decoded_table->set(total_size - 1, AsmJsTableType::Decoded); |
| 512 compiled_module->set_asm_js_offset_table(decoded_table); | 501 compiled_module->set_asm_js_offset_table(decoded_table); |
| 513 | 502 |
| 514 int idx = 0; | 503 int idx = 0; |
| 515 std::vector<WasmFunction>& wasm_funs = compiled_module->module()->functions; | 504 std::vector<WasmFunction>& wasm_funs = compiled_module->module()->functions; |
| 516 for (int func = 0; func < num_functions; ++func) { | 505 for (int func = 0; func < num_functions; ++func) { |
| 517 std::vector<AsmJsOffsetEntry>& func_asm_offsets = asm_offsets.val[func]; | 506 std::vector<std::pair<int, int>>& func_asm_offsets = asm_offsets.val[func]; |
| 518 if (func_asm_offsets.empty()) continue; | 507 if (func_asm_offsets.empty()) continue; |
| 519 int func_offset = | 508 int func_offset = |
| 520 wasm_funs[num_imported_functions + func].code_start_offset; | 509 wasm_funs[num_imported_functions + func].code_start_offset; |
| 521 for (AsmJsOffsetEntry& e : func_asm_offsets) { | 510 for (std::pair<int, int> p : func_asm_offsets) { |
| 522 // Byte offsets must be strictly monotonously increasing: | 511 // Byte offsets must be strictly monotonously increasing: |
| 523 DCHECK_IMPLIES(idx > 0, func_offset + e.byte_offset > | 512 DCHECK(idx == 0 || |
| 524 decoded_table->get_int(idx - kOTESize)); | 513 func_offset + p.first > decoded_table->get_int(idx - 2)); |
| 525 decoded_table->set_int(idx + kOTEByteOffset, func_offset + e.byte_offset); | 514 decoded_table->set_int(idx++, func_offset + p.first); |
| 526 decoded_table->set_int(idx + kOTECallPosition, e.source_position_call); | 515 decoded_table->set_int(idx++, p.second); |
| 527 decoded_table->set_int(idx + kOTENumberConvPosition, | |
| 528 e.source_position_number_conversion); | |
| 529 idx += kOTESize; | |
| 530 } | 516 } |
| 531 } | 517 } |
| 532 DCHECK_EQ(total_size, idx * kIntSize + 1); | 518 DCHECK_EQ(total_size, idx * kIntSize + 1); |
| 533 return decoded_table; | 519 return decoded_table; |
| 534 } | 520 } |
| 535 } // namespace | 521 } // namespace |
| 536 | 522 |
| 537 int WasmCompiledModule::GetAsmJsSourcePosition( | 523 int WasmCompiledModule::GetAsmJsSourcePosition( |
| 538 Handle<WasmCompiledModule> compiled_module, uint32_t func_index, | 524 Handle<WasmCompiledModule> compiled_module, uint32_t func_index, |
| 539 uint32_t byte_offset, bool is_at_number_conversion) { | 525 uint32_t byte_offset) { |
| 540 Isolate* isolate = compiled_module->GetIsolate(); | 526 Isolate* isolate = compiled_module->GetIsolate(); |
| 541 Handle<ByteArray> offset_table = | 527 Handle<ByteArray> offset_table = |
| 542 GetDecodedAsmJsOffsetTable(compiled_module, isolate); | 528 GetDecodedAsmJsOffsetTable(compiled_module, isolate); |
| 543 | 529 |
| 544 DCHECK_LT(func_index, compiled_module->module()->functions.size()); | 530 DCHECK_LT(func_index, compiled_module->module()->functions.size()); |
| 545 uint32_t func_code_offset = | 531 uint32_t func_code_offset = |
| 546 compiled_module->module()->functions[func_index].code_start_offset; | 532 compiled_module->module()->functions[func_index].code_start_offset; |
| 547 uint32_t total_offset = func_code_offset + byte_offset; | 533 uint32_t total_offset = func_code_offset + byte_offset; |
| 548 | 534 |
| 549 // Binary search for the total byte offset. | 535 // Binary search for the total byte offset. |
| 550 int left = 0; // inclusive | 536 int left = 0; // inclusive |
| 551 int right = offset_table->length() / kIntSize / kOTESize; // exclusive | 537 int right = offset_table->length() / kIntSize / 2; // exclusive |
| 552 DCHECK_LT(left, right); | 538 DCHECK_LT(left, right); |
| 553 while (right - left > 1) { | 539 while (right - left > 1) { |
| 554 int mid = left + (right - left) / 2; | 540 int mid = left + (right - left) / 2; |
| 555 int mid_entry = offset_table->get_int(kOTESize * mid); | 541 int mid_entry = offset_table->get_int(2 * mid); |
| 556 DCHECK_GE(kMaxInt, mid_entry); | 542 DCHECK_GE(kMaxInt, mid_entry); |
| 557 if (static_cast<uint32_t>(mid_entry) <= total_offset) { | 543 if (static_cast<uint32_t>(mid_entry) <= total_offset) { |
| 558 left = mid; | 544 left = mid; |
| 559 } else { | 545 } else { |
| 560 right = mid; | 546 right = mid; |
| 561 } | 547 } |
| 562 } | 548 } |
| 563 // There should be an entry for each position that could show up on the stack | 549 // There should be an entry for each position that could show up on the stack |
| 564 // trace: | 550 // trace: |
| 565 DCHECK_EQ(total_offset, offset_table->get_int(kOTESize * left)); | 551 DCHECK_EQ(total_offset, |
| 566 int idx = is_at_number_conversion ? kOTENumberConvPosition : kOTECallPosition; | 552 static_cast<uint32_t>(offset_table->get_int(2 * left))); |
| 567 return offset_table->get_int(kOTESize * left + idx); | 553 return offset_table->get_int(2 * left + 1); |
| 568 } | 554 } |
| 569 | 555 |
| 570 v8::debug::WasmDisassembly WasmCompiledModule::DisassembleFunction( | 556 v8::debug::WasmDisassembly WasmCompiledModule::DisassembleFunction( |
| 571 int func_index) { | 557 int func_index) { |
| 572 DisallowHeapAllocation no_gc; | 558 DisallowHeapAllocation no_gc; |
| 573 | 559 |
| 574 if (func_index < 0 || | 560 if (func_index < 0 || |
| 575 static_cast<uint32_t>(func_index) >= module()->functions.size()) | 561 static_cast<uint32_t>(func_index) >= module()->functions.size()) |
| 576 return {}; | 562 return {}; |
| 577 | 563 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 !array->get(kPreviousInstanceWrapper)->IsFixedArray()) | 597 !array->get(kPreviousInstanceWrapper)->IsFixedArray()) |
| 612 return false; | 598 return false; |
| 613 return true; | 599 return true; |
| 614 } | 600 } |
| 615 | 601 |
| 616 void WasmInstanceWrapper::set_instance_object(Handle<JSObject> instance, | 602 void WasmInstanceWrapper::set_instance_object(Handle<JSObject> instance, |
| 617 Isolate* isolate) { | 603 Isolate* isolate) { |
| 618 Handle<WeakCell> cell = isolate->factory()->NewWeakCell(instance); | 604 Handle<WeakCell> cell = isolate->factory()->NewWeakCell(instance); |
| 619 set(kWrapperInstanceObject, *cell); | 605 set(kWrapperInstanceObject, *cell); |
| 620 } | 606 } |
| OLD | NEW |