Skip to content

Commit f8eebcc

Browse files
committed
src: v12 fixed for JSArrayBuffer & FixedTypedArray
PR-URL: #330 Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
1 parent 2cc07cd commit f8eebcc

File tree

7 files changed

+318
-109
lines changed

7 files changed

+318
-109
lines changed

src/constants.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ class Constant {
4848

4949
inline std::string name() { return name_; }
5050

51-
protected:
52-
friend class Constants;
5351
explicit Constant(T value) : value_(value), status_(kValid), name_("") {}
5452
Constant(T value, std::string name)
5553
: value_(value), status_(kLoaded), name_(name) {}

src/llv8-constants.cc

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -348,12 +348,26 @@ void FixedArray::Load() {
348348

349349

350350
void FixedTypedArrayBase::Load() {
351+
kBasePointerOffset = LoadOptionalConstant(
352+
{"class_FixedTypedArrayBase__base_pointer__Object"}, 0);
353+
kExternalPointerOffset = LoadOptionalConstant(
354+
{"class_FixedTypedArrayBase__external_pointer__Object",
355+
"class_FixedTypedArrayBase__external_pointer__uintptr_t"},
356+
0);
357+
}
358+
359+
void JSTypedArray::Load() {
351360
kBasePointerOffset =
352-
LoadConstant("class_FixedTypedArrayBase__base_pointer__Object");
353-
kExternalPointerOffset =
354-
LoadConstant("class_FixedTypedArrayBase__external_pointer__Object");
361+
LoadOptionalConstant({"class_JSTypedArray__base_pointer__Object"}, 0);
362+
kExternalPointerOffset = LoadOptionalConstant(
363+
{"class_JSTypedArray__external_pointer__uintptr_t"}, 0);
355364
}
356365

366+
// TODO(mmarchini): proper validation so that we log an error if neither classes
367+
// were able to load their constants.
368+
bool JSTypedArray::IsDataPointerInJSTypedArray() {
369+
return kBasePointerOffset.Loaded() && kExternalPointerOffset.Loaded();
370+
}
357371

358372
void Oddball::Load() {
359373
kKindOffset = LoadConstant("class_Oddball__kind_offset__int");
@@ -370,19 +384,15 @@ void Oddball::Load() {
370384

371385
void JSArrayBuffer::Load() {
372386
kBackingStoreOffset =
373-
LoadConstant("class_JSArrayBuffer__backing_store__Object");
374-
kByteLengthOffset = LoadConstant("class_JSArrayBuffer__byte_length__Object");
375-
376-
// v4 compatibility fix
377-
if (kBackingStoreOffset == -1) {
378-
common_->Load();
387+
LoadConstant({"class_JSArrayBuffer__backing_store__Object",
388+
"class_JSArrayBuffer__backing_store__uintptr_t"});
389+
kByteLengthOffset =
390+
LoadConstant({"class_JSArrayBuffer__byte_length__Object",
391+
"class_JSArrayBuffer__byte_length__size_t"});
379392

380-
kBackingStoreOffset = kByteLengthOffset + common_->kPointerSize;
393+
if (kBackingStoreOffset.Check()) {
381394
}
382395

383-
kBitFieldOffset = kBackingStoreOffset + common_->kPointerSize;
384-
if (common_->kPointerSize == 8) kBitFieldOffset += 4;
385-
386396
kWasNeuteredMask = LoadConstant("jsarray_buffer_was_neutered_mask");
387397
kWasNeuteredShift = LoadConstant("jsarray_buffer_was_neutered_shift");
388398

@@ -394,14 +404,40 @@ void JSArrayBuffer::Load() {
394404
}
395405

396406

407+
bool JSArrayBuffer::IsByteLengthScalar() {
408+
return kByteLengthOffset.name() ==
409+
"v8dbg_class_JSArrayBuffer__byte_length__size_t";
410+
}
411+
412+
Constant<int64_t> JSArrayBuffer::BitFieldOffset() {
413+
if (!kBackingStoreOffset.Check()) return Constant<int64_t>();
414+
415+
common_->Load();
416+
int64_t kBitFieldOffset = *kBackingStoreOffset + common_->kPointerSize;
417+
if (common_->kPointerSize == 8) kBitFieldOffset += 4;
418+
return Constant<int64_t>(kBitFieldOffset);
419+
}
420+
421+
397422
void JSArrayBufferView::Load() {
398423
kBufferOffset = LoadConstant("class_JSArrayBufferView__buffer__Object");
399424
kByteOffsetOffset =
400-
LoadConstant("class_JSArrayBufferView__raw_byte_offset__Object");
425+
LoadConstant({"class_JSArrayBufferView__raw_byte_offset__Object",
426+
"class_JSArrayBufferView__byte_offset__size_t"});
401427
kByteLengthOffset =
402-
LoadConstant("class_JSArrayBufferView__raw_byte_length__Object");
428+
LoadConstant({"class_JSArrayBufferView__raw_byte_length__Object",
429+
"class_JSArrayBufferView__byte_length__size_t"});
430+
}
431+
432+
bool JSArrayBufferView::IsByteLengthScalar() {
433+
return kByteLengthOffset.name() ==
434+
"v8dbg_class_JSArrayBufferView__byte_length__size_t";
403435
}
404436

437+
bool JSArrayBufferView::IsByteOffsetScalar() {
438+
return kByteOffsetOffset.name() ==
439+
"v8dbg_class_JSArrayBufferView__byte_offset__size_t";
440+
}
405441

406442
void DescriptorArray::Load() {
407443
kDetailsOffset = LoadConstant({"prop_desc_details"});

src/llv8-constants.h

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,21 @@ class FixedTypedArrayBase : public Module {
348348
public:
349349
CONSTANTS_DEFAULT_METHODS(FixedTypedArrayBase);
350350

351-
int64_t kBasePointerOffset;
352-
int64_t kExternalPointerOffset;
351+
Constant<int64_t> kBasePointerOffset;
352+
Constant<int64_t> kExternalPointerOffset;
353+
354+
protected:
355+
void Load();
356+
};
357+
358+
class JSTypedArray : public Module {
359+
public:
360+
CONSTANTS_DEFAULT_METHODS(JSTypedArray);
361+
362+
Constant<int64_t> kBasePointerOffset;
363+
Constant<int64_t> kExternalPointerOffset;
364+
365+
bool IsDataPointerInJSTypedArray();
353366

354367
protected:
355368
void Load();
@@ -379,13 +392,15 @@ class JSArrayBuffer : public Module {
379392

380393
int64_t kKindOffset;
381394

382-
int64_t kBackingStoreOffset;
383-
int64_t kByteLengthOffset;
384-
int64_t kBitFieldOffset;
395+
Constant<int64_t> kBackingStoreOffset;
396+
Constant<int64_t> kByteLengthOffset;
385397

386398
int64_t kWasNeuteredMask;
387399
int64_t kWasNeuteredShift;
388400

401+
Constant<int64_t> BitFieldOffset();
402+
bool IsByteLengthScalar();
403+
389404
protected:
390405
void Load();
391406
};
@@ -395,8 +410,11 @@ class JSArrayBufferView : public Module {
395410
CONSTANTS_DEFAULT_METHODS(JSArrayBufferView);
396411

397412
int64_t kBufferOffset;
398-
int64_t kByteOffsetOffset;
399-
int64_t kByteLengthOffset;
413+
Constant<int64_t> kByteOffsetOffset;
414+
Constant<int64_t> kByteLengthOffset;
415+
416+
bool IsByteLengthScalar();
417+
bool IsByteOffsetScalar();
400418

401419
protected:
402420
void Load();

src/llv8-inl.h

Lines changed: 171 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,33 @@
77
namespace llnode {
88
namespace v8 {
99

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+
1037
template <>
1138
inline double LLV8::LoadValue<double>(int64_t addr, Error& err) {
1239
return LoadDouble(addr, err);
@@ -67,6 +94,14 @@ inline int64_t HeapObject::LoadField(int64_t off, Error& err) {
6794
}
6895

6996

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+
70105
template <>
71106
inline int32_t HeapObject::LoadFieldValue<int32_t>(int64_t off, Error& err) {
72107
return v8()->LoadValue<int32_t>(LeaField(off), err);
@@ -499,22 +534,139 @@ inline int64_t Code::Size(Error& err) {
499534

500535
ACCESSOR(Oddball, Kind, oddball()->kKindOffset, Smi)
501536

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);
504556
}
505557

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);
508564
}
509565

510-
ACCESSOR(JSArrayBuffer, ByteLength, js_array_buffer()->kByteLengthOffset, Smi)
566+
SAFE_ACCESSOR(JSArrayBuffer, byte_length, js_array_buffer()->kByteLengthOffset,
567+
Smi)
511568

512569
ACCESSOR(JSArrayBufferView, Buffer, js_array_buffer_view()->kBufferOffset,
513570
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+
518670

519671
inline ScopeInfo::PositionInfo ScopeInfo::MaybePositionInfo(Error& err) {
520672
ScopeInfo::PositionInfo position_info = {
@@ -632,12 +784,14 @@ ACCESSOR(ThinString, Actual, thin_string()->kActualOffset, String);
632784

633785
ACCESSOR(FixedArrayBase, Length, fixed_array_base()->kLengthOffset, Smi);
634786

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);
637790
}
638791

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);
641795
}
642796

643797
inline std::string OneByteString::ToString(Error& err) {
@@ -973,10 +1127,12 @@ inline bool Oddball::IsHole(Error& err) {
9731127
return kind.GetValue() == v8()->oddball()->kTheHole;
9741128
}
9751129

1130+
// TODO(mmarchini): return CheckedType
9761131
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);
9791134

1135+
int64_t field = *bit_field;
9801136
field &= v8()->js_array_buffer()->kWasNeuteredMask;
9811137
field >>= v8()->js_array_buffer()->kWasNeuteredShift;
9821138
return field != 0;

0 commit comments

Comments
 (0)