Reviewers: Toon Verwaest,
Message:
PTAL
Description:
Fast-to-slow migration should wipe out unboxed double fields if they still
reside in the object after migration.
BUG=chromium:436816
LOG=N
Please review this at https://codereview.chromium.org/765473004/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+60, -2 lines):
M src/objects.h
M src/objects.cc
M src/objects-inl.h
M test/cctest/test-unboxed-doubles.cc
Index: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index
03aea64736d818f456c748f76a31d583593dc664..90a39df3ac588a673d218137b3c76b70c78c6fbf
100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -2124,6 +2124,12 @@ void JSObject::RawFastDoublePropertyAtPut(FieldIndex
index, double value) {
}
+void JSObject::WipeOutFastPropertyAt(FieldIndex index) {
+ DCHECK(index.is_inobject());
+ WRITE_FIELD(this, index.offset(), Smi::FromInt(0));
+}
+
+
void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) {
if (IsUnboxedDoubleField(index)) {
DCHECK(value->IsMutableHeapNumber());
@@ -5331,7 +5337,7 @@ void Map::AppendDescriptor(Descriptor* desc) {
Object* Map::GetBackPointer() {
Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
- if (object->IsDescriptorArray()) {
+ if (object->IsTransitionArray()) {
return TransitionArray::cast(object)->back_pointer_storage();
} else {
DCHECK(object->IsMap() || object->IsUndefined());
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index
bd0c2fd4bef0b7f764edd3a178ba024a8dc553c0..d115e31ffb95bd2d6586aa8b7f76491d701bc302
100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -4353,6 +4353,8 @@ void JSObject::MigrateFastToSlow(Handle<JSObject>
object,
Handle<NameDictionary> dictionary =
NameDictionary::New(isolate, property_count);
+ int new_instance_size = new_map->instance_size();
+
Handle<DescriptorArray> descs(map->instance_descriptors());
for (int i = 0; i < real_size; i++) {
PropertyDetails details = descs->GetDetails(i);
@@ -4371,6 +4373,11 @@ void JSObject::MigrateFastToSlow(Handle<JSObject>
object,
if (object->IsUnboxedDoubleField(index)) {
double old_value = object->RawFastDoublePropertyAt(index);
value = isolate->factory()->NewHeapNumber(old_value);
+ if (index.offset() < new_instance_size) {
+ // Ensure that unused in-object space of slow-mode object does
not
+ // contain random garbage.
+ object->WipeOutFastPropertyAt(index);
+ }
} else {
value = handle(object->RawFastPropertyAt(index), isolate);
if (details.representation().IsDouble()) {
@@ -4400,7 +4407,6 @@ void JSObject::MigrateFastToSlow(Handle<JSObject>
object,
DisallowHeapAllocation no_allocation;
// Resize the object in the heap if necessary.
- int new_instance_size = new_map->instance_size();
int instance_size_delta = map->instance_size() - new_instance_size;
DCHECK(instance_size_delta >= 0);
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index
746f88d1c4c0c10083e63263a005f79ec4378b9d..e564e3522533fabd06c4e80da9b1ed2725e8fe5c
100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -2074,6 +2074,7 @@ class JSObject: public JSReceiver {
inline void FastPropertyAtPut(FieldIndex index, Object* value);
inline void RawFastPropertyAtPut(FieldIndex index, Object* value);
inline void RawFastDoublePropertyAtPut(FieldIndex index, double value);
+ inline void WipeOutFastPropertyAt(FieldIndex index);
void WriteToField(int descriptor, Object* value);
// Access to in object properties.
Index: test/cctest/test-unboxed-doubles.cc
diff --git a/test/cctest/test-unboxed-doubles.cc
b/test/cctest/test-unboxed-doubles.cc
index
db1aaaf5c6744fda11d1a1ed7e5cb8622988dcc1..178bc23d10deb4861b4a3254b456cdd5ac7fe26e
100644
--- a/test/cctest/test-unboxed-doubles.cc
+++ b/test/cctest/test-unboxed-doubles.cc
@@ -603,6 +603,51 @@ TEST(LayoutDescriptorAppendIfFastOrUseFullAllDoubles) {
}
+TEST(Regress436820) {
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ Factory* factory = isolate->factory();
+ v8::HandleScope scope(CcTest::isolate());
+
+ const int kPropsCount = kSmiValueSize * 3;
+ PropertyKind props[kPropsCount];
+ for (int i = 0; i < kPropsCount; i++) {
+ props[i] = PROP_DOUBLE;
+ }
+ Handle<DescriptorArray> descriptors =
+ CreateDescriptorArray(isolate, props, kPropsCount);
+
+ Handle<Map> map = Map::Create(isolate, kPropsCount);
+ Handle<LayoutDescriptor> layout_descriptor =
+ LayoutDescriptor::New(map, descriptors, kPropsCount);
+ map->InitializeDescriptors(*descriptors, *layout_descriptor);
+
+ Handle<JSObject> object = factory->NewJSObjectFromMap(map, TENURED);
+
+ Address fake_address = reinterpret_cast<Address>(~kHeapObjectTagMask);
+ HeapObject* fake_object = HeapObject::FromAddress(fake_address);
+ CHECK(fake_object->IsHeapObject());
+
+ double boom_value = bit_cast<double>(fake_object);
+ for (int i = 0; i < kPropsCount; i++) {
+ FieldIndex index = FieldIndex::ForDescriptor(*map, i);
+ CHECK(map->IsUnboxedDoubleField(index));
+ object->RawFastDoublePropertyAtPut(index, boom_value);
+ }
+ CHECK(object->HasFastProperties());
+ CHECK(!object->map()->HasFastPointerLayout());
+
+ Handle<Map> normalized_map =
+ Map::Normalize(map, KEEP_INOBJECT_PROPERTIES, "testing");
+ JSObject::MigrateToMap(object, normalized_map);
+ CHECK(!object->HasFastProperties());
+ CHECK(object->map()->HasFastPointerLayout());
+
+ // Trigger GCs and heap verification.
+ CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+}
+
+
TEST(StoreBufferScanOnScavenge) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.