summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorFedor Indutny <fedor@indutny.com>2015-09-16 10:57:30 -0700
committerFedor Indutny <fedor@indutny.com>2015-09-16 17:32:47 -0700
commit2b8a06b32347ac16eaac820227a4672dbe05c134 (patch)
tree996414bad8047049a4b108ca4e38482fe34dc30c /deps
parent5f6579d3661b5a55ccefdcbc4e24d4b1ebea6588 (diff)
downloadnode-new-2b8a06b32347ac16eaac820227a4672dbe05c134.tar.gz
deps: backport 0d01728 from v8's upstream
Original commit message: [objects] do not visit ArrayBuffer's backing store ArrayBuffer's backing store is a pointer to external heap, and can't be treated as a heap object. Doing so will result in crashes, when the backing store is unaligned. See: https://github.com/nodejs/node/issues/2791 BUG=chromium:530531 R=mlippautz@chromium.org LOG=N Review URL: https://codereview.chromium.org/1327403002 Cr-Commit-Position: refs/heads/master@{#30771} Fix: https://github.com/nodejs/node/issues/2791 PR-URL: https://github.com/nodejs/node/pull/2912 Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps')
-rw-r--r--deps/v8/src/heap/mark-compact.cc28
-rw-r--r--deps/v8/src/heap/objects-visiting-inl.h11
-rw-r--r--deps/v8/src/heap/store-buffer.cc11
-rw-r--r--deps/v8/src/objects-inl.h28
-rw-r--r--deps/v8/src/objects.cc4
-rw-r--r--deps/v8/src/objects.h17
-rw-r--r--deps/v8/test/cctest/test-api.cc22
7 files changed, 109 insertions, 12 deletions
diff --git a/deps/v8/src/heap/mark-compact.cc b/deps/v8/src/heap/mark-compact.cc
index 508d49913f..45f5af3f4d 100644
--- a/deps/v8/src/heap/mark-compact.cc
+++ b/deps/v8/src/heap/mark-compact.cc
@@ -2782,6 +2782,28 @@ void MarkCompactCollector::MigrateObjectMixed(HeapObject* dst, HeapObject* src,
Address base_pointer_slot =
dst->address() + FixedTypedArrayBase::kBasePointerOffset;
RecordMigratedSlot(Memory::Object_at(base_pointer_slot), base_pointer_slot);
+ } else if (src->IsJSArrayBuffer()) {
+ heap()->MoveBlock(dst->address(), src->address(), size);
+
+ // Visit inherited JSObject properties and byte length of ArrayBuffer
+ Address regular_slot =
+ dst->address() + JSArrayBuffer::BodyDescriptor::kStartOffset;
+ Address regular_slots_end =
+ dst->address() + JSArrayBuffer::kByteLengthOffset + kPointerSize;
+ while (regular_slot < regular_slots_end) {
+ RecordMigratedSlot(Memory::Object_at(regular_slot), regular_slot);
+ regular_slot += kPointerSize;
+ }
+
+ // Skip backing store and visit just internal fields
+ Address internal_field_slot = dst->address() + JSArrayBuffer::kSize;
+ Address internal_fields_end =
+ dst->address() + JSArrayBuffer::kSizeWithInternalFields;
+ while (internal_field_slot < internal_fields_end) {
+ RecordMigratedSlot(Memory::Object_at(internal_field_slot),
+ internal_field_slot);
+ internal_field_slot += kPointerSize;
+ }
} else if (FLAG_unbox_double_fields) {
Address dst_addr = dst->address();
Address src_addr = src->address();
@@ -3206,6 +3228,12 @@ bool MarkCompactCollector::IsSlotInLiveObject(Address slot) {
if (object->IsFixedTypedArrayBase()) {
return static_cast<int>(slot - object->address()) ==
FixedTypedArrayBase::kBasePointerOffset;
+ } else if (object->IsJSArrayBuffer()) {
+ int off = static_cast<int>(slot - object->address());
+ return (off >= JSArrayBuffer::BodyDescriptor::kStartOffset &&
+ off <= JSArrayBuffer::kByteLengthOffset) ||
+ (off >= JSArrayBuffer::kSize &&
+ off < JSArrayBuffer::kSizeWithInternalFields);
} else if (FLAG_unbox_double_fields) {
// Filter out slots that happen to point to unboxed double fields.
LayoutDescriptorHelper helper(object->map());
diff --git a/deps/v8/src/heap/objects-visiting-inl.h b/deps/v8/src/heap/objects-visiting-inl.h
index 0103054822..bdb801a1f9 100644
--- a/deps/v8/src/heap/objects-visiting-inl.h
+++ b/deps/v8/src/heap/objects-visiting-inl.h
@@ -81,10 +81,8 @@ int StaticNewSpaceVisitor<StaticVisitor>::VisitJSArrayBuffer(
Map* map, HeapObject* object) {
Heap* heap = map->GetHeap();
- VisitPointers(
- heap,
- HeapObject::RawField(object, JSArrayBuffer::BodyDescriptor::kStartOffset),
- HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields));
+ JSArrayBuffer::JSArrayBufferIterateBody<
+ StaticNewSpaceVisitor<StaticVisitor> >(heap, object);
if (!JSArrayBuffer::cast(object)->is_external()) {
heap->RegisterLiveArrayBuffer(true,
JSArrayBuffer::cast(object)->backing_store());
@@ -503,10 +501,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSArrayBuffer(
Map* map, HeapObject* object) {
Heap* heap = map->GetHeap();
- StaticVisitor::VisitPointers(
- heap,
- HeapObject::RawField(object, JSArrayBuffer::BodyDescriptor::kStartOffset),
- HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields));
+ JSArrayBuffer::JSArrayBufferIterateBody<StaticVisitor>(heap, object);
if (!JSArrayBuffer::cast(object)->is_external()) {
heap->RegisterLiveArrayBuffer(false,
JSArrayBuffer::cast(object)->backing_store());
diff --git a/deps/v8/src/heap/store-buffer.cc b/deps/v8/src/heap/store-buffer.cc
index 03f587f215..efdd0b4708 100644
--- a/deps/v8/src/heap/store-buffer.cc
+++ b/deps/v8/src/heap/store-buffer.cc
@@ -503,6 +503,17 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) {
obj_address + FixedTypedArrayBase::kBasePointerOffset,
obj_address + FixedTypedArrayBase::kHeaderSize,
slot_callback);
+ } else if (heap_object->IsJSArrayBuffer()) {
+ FindPointersToNewSpaceInRegion(
+ obj_address +
+ JSArrayBuffer::BodyDescriptor::kStartOffset,
+ obj_address + JSArrayBuffer::kByteLengthOffset +
+ kPointerSize,
+ slot_callback);
+ FindPointersToNewSpaceInRegion(
+ obj_address + JSArrayBuffer::kSize,
+ obj_address + JSArrayBuffer::kSizeWithInternalFields,
+ slot_callback);
} else if (FLAG_unbox_double_fields) {
LayoutDescriptorHelper helper(heap_object->map());
DCHECK(!helper.all_fields_tagged());
diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h
index fbc2c4ee76..3caf52bff4 100644
--- a/deps/v8/src/objects-inl.h
+++ b/deps/v8/src/objects-inl.h
@@ -1503,6 +1503,8 @@ HeapObjectContents HeapObject::ContentType() {
} else if (type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
type <= LAST_FIXED_TYPED_ARRAY_TYPE) {
return HeapObjectContents::kMixedValues;
+ } else if (type == JS_ARRAY_BUFFER_TYPE) {
+ return HeapObjectContents::kMixedValues;
} else if (type <= LAST_DATA_TYPE) {
// TODO(jochen): Why do we claim that Code and Map contain only raw values?
return HeapObjectContents::kRawValues;
@@ -6091,6 +6093,32 @@ void JSArrayBuffer::set_is_shared(bool value) {
}
+// static
+template <typename StaticVisitor>
+void JSArrayBuffer::JSArrayBufferIterateBody(Heap* heap, HeapObject* obj) {
+ StaticVisitor::VisitPointers(
+ heap,
+ HeapObject::RawField(obj, JSArrayBuffer::BodyDescriptor::kStartOffset),
+ HeapObject::RawField(obj,
+ JSArrayBuffer::kByteLengthOffset + kPointerSize));
+ StaticVisitor::VisitPointers(
+ heap, HeapObject::RawField(obj, JSArrayBuffer::kSize),
+ HeapObject::RawField(obj, JSArrayBuffer::kSizeWithInternalFields));
+}
+
+
+void JSArrayBuffer::JSArrayBufferIterateBody(HeapObject* obj,
+ ObjectVisitor* v) {
+ v->VisitPointers(
+ HeapObject::RawField(obj, JSArrayBuffer::BodyDescriptor::kStartOffset),
+ HeapObject::RawField(obj,
+ JSArrayBuffer::kByteLengthOffset + kPointerSize));
+ v->VisitPointers(
+ HeapObject::RawField(obj, JSArrayBuffer::kSize),
+ HeapObject::RawField(obj, JSArrayBuffer::kSizeWithInternalFields));
+}
+
+
Object* JSArrayBufferView::byte_offset() const {
if (WasNeutered()) return Smi::FromInt(0);
return Object::cast(READ_FIELD(this, kByteOffsetOffset));
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc
index 2b042fda8e..5c863855f8 100644
--- a/deps/v8/src/objects.cc
+++ b/deps/v8/src/objects.cc
@@ -1420,7 +1420,6 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case JS_VALUE_TYPE:
case JS_DATE_TYPE:
case JS_ARRAY_TYPE:
- case JS_ARRAY_BUFFER_TYPE:
case JS_TYPED_ARRAY_TYPE:
case JS_DATA_VIEW_TYPE:
case JS_SET_TYPE:
@@ -1436,6 +1435,9 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case JS_MESSAGE_OBJECT_TYPE:
JSObject::BodyDescriptor::IterateBody(this, object_size, v);
break;
+ case JS_ARRAY_BUFFER_TYPE:
+ JSArrayBuffer::JSArrayBufferIterateBody(this, v);
+ break;
case JS_FUNCTION_TYPE:
reinterpret_cast<JSFunction*>(this)
->JSFunctionIterateBody(object_size, v);
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h
index 7e4fcbafeb..563618ab71 100644
--- a/deps/v8/src/objects.h
+++ b/deps/v8/src/objects.h
@@ -10014,9 +10014,14 @@ class JSArrayBuffer: public JSObject {
DECLARE_PRINTER(JSArrayBuffer)
DECLARE_VERIFIER(JSArrayBuffer)
- static const int kBackingStoreOffset = JSObject::kHeaderSize;
- static const int kByteLengthOffset = kBackingStoreOffset + kPointerSize;
- static const int kBitFieldSlot = kByteLengthOffset + kPointerSize;
+ static const int kByteLengthOffset = JSObject::kHeaderSize;
+
+ // NOTE: GC will visit objects fields:
+ // 1. From JSObject::BodyDescriptor::kStartOffset to kByteLengthOffset +
+ // kPointerSize
+ // 2. From start of the internal fields and up to the end of them
+ static const int kBackingStoreOffset = kByteLengthOffset + kPointerSize;
+ static const int kBitFieldSlot = kBackingStoreOffset + kPointerSize;
#if V8_TARGET_LITTLE_ENDIAN || !V8_HOST_ARCH_64_BIT
static const int kBitFieldOffset = kBitFieldSlot;
#else
@@ -10027,6 +10032,12 @@ class JSArrayBuffer: public JSObject {
static const int kSizeWithInternalFields =
kSize + v8::ArrayBuffer::kInternalFieldCount * kPointerSize;
+ template <typename StaticVisitor>
+ static inline void JSArrayBufferIterateBody(Heap* heap, HeapObject* obj);
+
+ static inline void JSArrayBufferIterateBody(HeapObject* obj,
+ ObjectVisitor* v);
+
class IsExternal : public BitField<bool, 1, 1> {};
class IsNeuterable : public BitField<bool, 2, 1> {};
class WasNeutered : public BitField<bool, 3, 1> {};
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index e464a67e00..ad3190a711 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -14169,6 +14169,28 @@ THREADED_TEST(DataView) {
}
+THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope handle_scope(isolate);
+
+ // Make sure the pointer looks like a heap object
+ uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
+
+ // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
+ Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
+
+ // Should not crash
+ CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
+ CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
+ CcTest::heap()->CollectAllGarbage();
+ CcTest::heap()->CollectAllGarbage();
+
+ // Should not move the pointer
+ CHECK_EQ(ab->GetContents().Data(), store_ptr);
+}
+
+
THREADED_TEST(SharedUint8Array) {
i::FLAG_harmony_sharedarraybuffer = true;
TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array,