|
7 | 7 | namespace llnode {
|
8 | 8 | namespace v8 {
|
9 | 9 |
|
| 10 | +using lldb::addr_t; |
| 11 | +using lldb::SBError; |
| 12 | + |
| 13 | +template <typename T> |
| 14 | +inline std::string CheckedType<T>::ToString(const char* fmt) { |
| 15 | + if (!Check()) return "???"; |
| 16 | + |
| 17 | + char buf[20]; |
| 18 | + snprintf(buf, sizeof(buf), fmt, val_); |
| 19 | + return std::string(buf); |
| 20 | +} |
| 21 | + |
| 22 | +template <class T> |
| 23 | +inline CheckedType<T> LLV8::LoadUnsigned(int64_t addr, uint32_t byte_size) { |
| 24 | + SBError sberr; |
| 25 | + int64_t value = process_.ReadUnsignedFromMemory(static_cast<addr_t>(addr), |
| 26 | + byte_size, sberr); |
| 27 | + |
| 28 | + if (sberr.Fail()) { |
| 29 | + PRINT_DEBUG("Failed to load unsigned from v8 memory. Reason: %s", |
| 30 | + sberr.GetCString()); |
| 31 | + return CheckedType<T>(); |
| 32 | + } |
| 33 | + |
| 34 | + return CheckedType<T>(value); |
| 35 | +} |
| 36 | + |
10 | 37 | template <>
|
11 | 38 | inline double LLV8::LoadValue<double>(int64_t addr, Error& err) {
|
12 | 39 | return LoadDouble(addr, err);
|
@@ -67,6 +94,14 @@ inline int64_t HeapObject::LoadField(int64_t off, Error& err) {
|
67 | 94 | }
|
68 | 95 |
|
69 | 96 |
|
| 97 | +template <typename T> |
| 98 | +inline CheckedType<T> HeapObject::LoadCheckedField(Constant<int64_t> off) { |
| 99 | + RETURN_IF_THIS_INVALID(CheckedType<T>()); |
| 100 | + RETURN_IF_INVALID(off, CheckedType<T>()); |
| 101 | + return v8()->LoadUnsigned<T>(LeaField(*off), 8); |
| 102 | +} |
| 103 | + |
| 104 | + |
70 | 105 | template <>
|
71 | 106 | inline int32_t HeapObject::LoadFieldValue<int32_t>(int64_t off, Error& err) {
|
72 | 107 | return v8()->LoadValue<int32_t>(LeaField(off), err);
|
@@ -499,22 +534,139 @@ inline int64_t Code::Size(Error& err) {
|
499 | 534 |
|
500 | 535 | ACCESSOR(Oddball, Kind, oddball()->kKindOffset, Smi)
|
501 | 536 |
|
502 |
| -inline int64_t JSArrayBuffer::BackingStore(Error& err) { |
503 |
| - return LoadField(v8()->js_array_buffer()->kBackingStoreOffset, err); |
| 537 | +inline CheckedType<uintptr_t> JSArrayBuffer::BackingStore() { |
| 538 | + RETURN_IF_THIS_INVALID(CheckedType<size_t>()); |
| 539 | + |
| 540 | + return LoadCheckedField<uintptr_t>( |
| 541 | + v8()->js_array_buffer()->kBackingStoreOffset); |
| 542 | +} |
| 543 | + |
| 544 | +inline CheckedType<size_t> JSArrayBuffer::ByteLength() { |
| 545 | + RETURN_IF_THIS_INVALID(CheckedType<size_t>()); |
| 546 | + |
| 547 | + if (!v8()->js_array_buffer()->IsByteLengthScalar()) { |
| 548 | + Error err; |
| 549 | + Smi len = byte_length(err); |
| 550 | + RETURN_IF_INVALID(len, CheckedType<size_t>()); |
| 551 | + |
| 552 | + return CheckedType<size_t>(len.GetValue()); |
| 553 | + } |
| 554 | + |
| 555 | + return LoadCheckedField<size_t>(v8()->js_array_buffer()->kByteLengthOffset); |
504 | 556 | }
|
505 | 557 |
|
506 |
| -inline int64_t JSArrayBuffer::BitField(Error& err) { |
507 |
| - return LoadField(v8()->js_array_buffer()->kBitFieldOffset, err) & 0xffffffff; |
| 558 | +inline CheckedType<int64_t> JSArrayBuffer::BitField() { |
| 559 | + RETURN_IF_THIS_INVALID(CheckedType<int64_t>()); |
| 560 | + CheckedType<int64_t> bit_fields = |
| 561 | + LoadCheckedField<int64_t>(v8()->js_array_buffer()->BitFieldOffset()); |
| 562 | + RETURN_IF_INVALID(bit_fields, CheckedType<int64_t>()); |
| 563 | + return CheckedType<int64_t>(*bit_fields & 0xffffffff); |
508 | 564 | }
|
509 | 565 |
|
510 |
| -ACCESSOR(JSArrayBuffer, ByteLength, js_array_buffer()->kByteLengthOffset, Smi) |
| 566 | +SAFE_ACCESSOR(JSArrayBuffer, byte_length, js_array_buffer()->kByteLengthOffset, |
| 567 | + Smi) |
511 | 568 |
|
512 | 569 | ACCESSOR(JSArrayBufferView, Buffer, js_array_buffer_view()->kBufferOffset,
|
513 | 570 | JSArrayBuffer)
|
514 |
| -ACCESSOR(JSArrayBufferView, ByteOffset, |
515 |
| - js_array_buffer_view()->kByteOffsetOffset, Smi) |
516 |
| -ACCESSOR(JSArrayBufferView, ByteLength, |
517 |
| - js_array_buffer_view()->kByteLengthOffset, Smi) |
| 571 | + |
| 572 | +inline CheckedType<size_t> JSArrayBufferView::ByteLength() { |
| 573 | + RETURN_IF_THIS_INVALID(CheckedType<size_t>()); |
| 574 | + |
| 575 | + if (!v8()->js_array_buffer_view()->IsByteLengthScalar()) { |
| 576 | + Error err; |
| 577 | + Smi len = byte_length(err); |
| 578 | + RETURN_IF_INVALID(len, CheckedType<size_t>()); |
| 579 | + |
| 580 | + return CheckedType<size_t>(len.GetValue()); |
| 581 | + } |
| 582 | + |
| 583 | + return LoadCheckedField<size_t>( |
| 584 | + v8()->js_array_buffer_view()->kByteLengthOffset); |
| 585 | +} |
| 586 | + |
| 587 | +inline CheckedType<size_t> JSArrayBufferView::ByteOffset() { |
| 588 | + RETURN_IF_THIS_INVALID(CheckedType<size_t>()); |
| 589 | + |
| 590 | + if (!v8()->js_array_buffer_view()->IsByteOffsetScalar()) { |
| 591 | + Error err; |
| 592 | + Smi len = byte_offset(err); |
| 593 | + RETURN_IF_INVALID(len, CheckedType<size_t>()); |
| 594 | + |
| 595 | + return CheckedType<size_t>(len.GetValue()); |
| 596 | + } |
| 597 | + |
| 598 | + return LoadCheckedField<size_t>( |
| 599 | + v8()->js_array_buffer_view()->kByteOffsetOffset); |
| 600 | +} |
| 601 | + |
| 602 | +SAFE_ACCESSOR(JSArrayBufferView, byte_offset, |
| 603 | + js_array_buffer_view()->kByteOffsetOffset, Smi) |
| 604 | +SAFE_ACCESSOR(JSArrayBufferView, byte_length, |
| 605 | + js_array_buffer_view()->kByteLengthOffset, Smi) |
| 606 | + |
| 607 | +inline CheckedType<int64_t> JSTypedArray::base() { |
| 608 | + return LoadCheckedField<int64_t>(v8()->js_typed_array()->kBasePointerOffset); |
| 609 | +} |
| 610 | + |
| 611 | +inline CheckedType<int64_t> JSTypedArray::external() { |
| 612 | + return LoadCheckedField<int64_t>( |
| 613 | + v8()->js_typed_array()->kExternalPointerOffset); |
| 614 | +} |
| 615 | + |
| 616 | +inline CheckedType<int64_t> JSTypedArray::GetExternal() { |
| 617 | + if (v8()->js_typed_array()->IsDataPointerInJSTypedArray()) { |
| 618 | + PRINT_DEBUG("OHALO"); |
| 619 | + return external(); |
| 620 | + } else { |
| 621 | + PRINT_DEBUG("NAY"); |
| 622 | + // TODO(mmarchini): don't rely on Error |
| 623 | + Error err; |
| 624 | + v8::HeapObject elements_obj = Elements(err); |
| 625 | + RETURN_IF_INVALID(elements_obj, CheckedType<int64_t>()); |
| 626 | + v8::FixedTypedArrayBase elements(elements_obj); |
| 627 | + return elements.GetExternal(); |
| 628 | + } |
| 629 | +} |
| 630 | + |
| 631 | +inline CheckedType<int64_t> JSTypedArray::GetBase() { |
| 632 | + if (v8()->js_typed_array()->IsDataPointerInJSTypedArray()) { |
| 633 | + PRINT_DEBUG("ALOHA"); |
| 634 | + return base(); |
| 635 | + } else { |
| 636 | + PRINT_DEBUG("NEY"); |
| 637 | + // TODO(mmarchini): don't rely on Error |
| 638 | + Error err; |
| 639 | + v8::HeapObject elements_obj = Elements(err); |
| 640 | + RETURN_IF_INVALID(elements_obj, CheckedType<int64_t>()); |
| 641 | + v8::FixedTypedArrayBase elements(elements_obj); |
| 642 | + return elements.GetBase(); |
| 643 | + } |
| 644 | +} |
| 645 | + |
| 646 | +inline CheckedType<uintptr_t> JSTypedArray::GetData() { |
| 647 | + // TODO(mmarchini): don't rely on Error |
| 648 | + Error err; |
| 649 | + v8::JSArrayBuffer buf = Buffer(err); |
| 650 | + if (err.Fail()) return CheckedType<uintptr_t>(); |
| 651 | + |
| 652 | + v8::CheckedType<uintptr_t> data = buf.BackingStore(); |
| 653 | + // TODO(mmarchini): be more lenient to failed load |
| 654 | + RETURN_IF_INVALID(data, CheckedType<uintptr_t>()); |
| 655 | + |
| 656 | + if (*data == 0) { |
| 657 | + // The backing store has not been materialized yet. |
| 658 | + |
| 659 | + CheckedType<int64_t> base = GetBase(); |
| 660 | + RETURN_IF_INVALID(base, v8::CheckedType<uintptr_t>()); |
| 661 | + |
| 662 | + CheckedType<int64_t> external = GetExternal(); |
| 663 | + RETURN_IF_INVALID(external, v8::CheckedType<uintptr_t>()); |
| 664 | + |
| 665 | + data = v8::CheckedType<uintptr_t>(*base + *external); |
| 666 | + } |
| 667 | + return data; |
| 668 | +} |
| 669 | + |
518 | 670 |
|
519 | 671 | inline ScopeInfo::PositionInfo ScopeInfo::MaybePositionInfo(Error& err) {
|
520 | 672 | ScopeInfo::PositionInfo position_info = {
|
@@ -632,12 +784,14 @@ ACCESSOR(ThinString, Actual, thin_string()->kActualOffset, String);
|
632 | 784 |
|
633 | 785 | ACCESSOR(FixedArrayBase, Length, fixed_array_base()->kLengthOffset, Smi);
|
634 | 786 |
|
635 |
| -inline int64_t FixedTypedArrayBase::GetBase(Error& err) { |
636 |
| - return LoadField(v8()->fixed_typed_array_base()->kBasePointerOffset, err); |
| 787 | +inline CheckedType<int64_t> FixedTypedArrayBase::GetBase() { |
| 788 | + return LoadCheckedField<int64_t>( |
| 789 | + v8()->fixed_typed_array_base()->kBasePointerOffset); |
637 | 790 | }
|
638 | 791 |
|
639 |
| -inline int64_t FixedTypedArrayBase::GetExternal(Error& err) { |
640 |
| - return LoadField(v8()->fixed_typed_array_base()->kExternalPointerOffset, err); |
| 792 | +inline CheckedType<int64_t> FixedTypedArrayBase::GetExternal() { |
| 793 | + return LoadCheckedField<int64_t>( |
| 794 | + v8()->fixed_typed_array_base()->kExternalPointerOffset); |
641 | 795 | }
|
642 | 796 |
|
643 | 797 | inline std::string OneByteString::ToString(Error& err) {
|
@@ -973,10 +1127,12 @@ inline bool Oddball::IsHole(Error& err) {
|
973 | 1127 | return kind.GetValue() == v8()->oddball()->kTheHole;
|
974 | 1128 | }
|
975 | 1129 |
|
| 1130 | +// TODO(mmarchini): return CheckedType |
976 | 1131 | inline bool JSArrayBuffer::WasNeutered(Error& err) {
|
977 |
| - int64_t field = BitField(err); |
978 |
| - if (err.Fail()) return false; |
| 1132 | + CheckedType<int64_t> bit_field = BitField(); |
| 1133 | + RETURN_IF_INVALID(bit_field, false); |
979 | 1134 |
|
| 1135 | + int64_t field = *bit_field; |
980 | 1136 | field &= v8()->js_array_buffer()->kWasNeuteredMask;
|
981 | 1137 | field >>= v8()->js_array_buffer()->kWasNeuteredShift;
|
982 | 1138 | return field != 0;
|
|
0 commit comments