Commit b57be748 authored by marja's avatar marja Committed by Commit bot

Revert of Fix memory leak caused by field type in descriptor array. (patchset...

Revert of Fix memory leak caused by field type in descriptor array. (patchset #3 id:40001 of https://codereview.chromium.org/955063002/)

Reason for revert:
Breaks test/mjsunit/debug-clearbreakpointgroup.js on arm64.debug.

Original issue's description:
> Fix memory leak caused by field type in descriptor array.
>
> When a field type is a map, it is wrapped in a weak cell upon storing to the descriptor array.
>
> Map::GetFieldType(i) does the unwrapping.
>
> BUG=v8:3877
> LOG=N
> TEST=cctest/test-heap/Regress3877
>
> Committed: https://crrev.com/77d3ae0e119893ac8d34ea6ca090cddd5bbf987e
> Cr-Commit-Position: refs/heads/master@{#26879}

TBR=verwaest@chromium.org,ulan@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:3877

Review URL: https://codereview.chromium.org/960103003

Cr-Commit-Position: refs/heads/master@{#26883}
parent 6517181c
...@@ -3136,12 +3136,7 @@ int DescriptorArray::GetFieldIndex(int descriptor_number) { ...@@ -3136,12 +3136,7 @@ int DescriptorArray::GetFieldIndex(int descriptor_number) {
HeapType* DescriptorArray::GetFieldType(int descriptor_number) { HeapType* DescriptorArray::GetFieldType(int descriptor_number) {
DCHECK(GetDetails(descriptor_number).location() == kField); DCHECK(GetDetails(descriptor_number).location() == kField);
Object* value = GetValue(descriptor_number); return HeapType::cast(GetValue(descriptor_number));
if (value->IsWeakCell()) {
if (WeakCell::cast(value)->cleared()) return HeapType::Any();
value = WeakCell::cast(value)->value();
}
return HeapType::cast(value);
} }
......
...@@ -1704,12 +1704,6 @@ String* JSReceiver::constructor_name() { ...@@ -1704,12 +1704,6 @@ String* JSReceiver::constructor_name() {
} }
static Handle<Object> WrapType(Handle<HeapType> type) {
if (type->IsClass()) return Map::WeakCellForMap(type->AsClass()->Map());
return type;
}
MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, MaybeHandle<Map> Map::CopyWithField(Handle<Map> map,
Handle<Name> name, Handle<Name> name,
Handle<HeapType> type, Handle<HeapType> type,
...@@ -1735,10 +1729,7 @@ MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, ...@@ -1735,10 +1729,7 @@ MaybeHandle<Map> Map::CopyWithField(Handle<Map> map,
type = HeapType::Any(isolate); type = HeapType::Any(isolate);
} }
Handle<Object> wrapped_type(WrapType(type)); DataDescriptor new_field_desc(name, index, type, attributes, representation);
DataDescriptor new_field_desc(name, index, wrapped_type, attributes,
representation);
Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag); Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
int unused_property_fields = new_map->unused_property_fields() - 1; int unused_property_fields = new_map->unused_property_fields() - 1;
if (unused_property_fields < 0) { if (unused_property_fields < 0) {
...@@ -2314,16 +2305,15 @@ Map* Map::FindFieldOwner(int descriptor) { ...@@ -2314,16 +2305,15 @@ Map* Map::FindFieldOwner(int descriptor) {
void Map::UpdateFieldType(int descriptor, Handle<Name> name, void Map::UpdateFieldType(int descriptor, Handle<Name> name,
Representation new_representation, Representation new_representation,
Handle<Object> new_wrapped_type) { Handle<HeapType> new_type) {
DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell());
DisallowHeapAllocation no_allocation; DisallowHeapAllocation no_allocation;
PropertyDetails details = instance_descriptors()->GetDetails(descriptor); PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
if (details.type() != DATA) return; if (details.type() != DATA) return;
if (HasTransitionArray()) { if (HasTransitionArray()) {
TransitionArray* transitions = this->transitions(); TransitionArray* transitions = this->transitions();
for (int i = 0; i < transitions->number_of_transitions(); ++i) { for (int i = 0; i < transitions->number_of_transitions(); ++i) {
transitions->GetTarget(i)->UpdateFieldType( transitions->GetTarget(i)
descriptor, name, new_representation, new_wrapped_type); ->UpdateFieldType(descriptor, name, new_representation, new_type);
} }
} }
// It is allowed to change representation here only from None to something. // It is allowed to change representation here only from None to something.
...@@ -2331,9 +2321,9 @@ void Map::UpdateFieldType(int descriptor, Handle<Name> name, ...@@ -2331,9 +2321,9 @@ void Map::UpdateFieldType(int descriptor, Handle<Name> name,
details.representation().IsNone()); details.representation().IsNone());
// Skip if already updated the shared descriptor. // Skip if already updated the shared descriptor.
if (instance_descriptors()->GetValue(descriptor) == *new_wrapped_type) return; if (instance_descriptors()->GetFieldType(descriptor) == *new_type) return;
DataDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor), DataDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor),
new_wrapped_type, details.attributes(), new_representation); new_type, details.attributes(), new_representation);
instance_descriptors()->Replace(descriptor, &d); instance_descriptors()->Replace(descriptor, &d);
} }
...@@ -2381,10 +2371,8 @@ void Map::GeneralizeFieldType(Handle<Map> map, int modify_index, ...@@ -2381,10 +2371,8 @@ void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
PropertyDetails details = descriptors->GetDetails(modify_index); PropertyDetails details = descriptors->GetDetails(modify_index);
Handle<Name> name(descriptors->GetKey(modify_index)); Handle<Name> name(descriptors->GetKey(modify_index));
Handle<Object> wrapped_type(WrapType(new_field_type));
field_owner->UpdateFieldType(modify_index, name, new_representation, field_owner->UpdateFieldType(modify_index, name, new_representation,
wrapped_type); new_field_type);
field_owner->dependent_code()->DeoptimizeDependentCodeGroup( field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
isolate, DependentCode::kFieldTypeGroup); isolate, DependentCode::kFieldTypeGroup);
...@@ -2776,8 +2764,7 @@ Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index, ...@@ -2776,8 +2764,7 @@ Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,
next_field_type = next_field_type =
GeneralizeFieldType(target_field_type, old_field_type, isolate); GeneralizeFieldType(target_field_type, old_field_type, isolate);
} }
Handle<Object> wrapped_type(WrapType(next_field_type)); DataDescriptor d(target_key, current_offset, next_field_type,
DataDescriptor d(target_key, current_offset, wrapped_type,
next_attributes, next_representation); next_attributes, next_representation);
current_offset += d.GetDetails().field_width_in_words(); current_offset += d.GetDetails().field_width_in_words();
new_descriptors->Set(i, &d); new_descriptors->Set(i, &d);
...@@ -2845,10 +2832,8 @@ Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index, ...@@ -2845,10 +2832,8 @@ Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,
next_field_type = old_field_type; next_field_type = old_field_type;
} }
Handle<Object> wrapped_type(WrapType(next_field_type)); DataDescriptor d(old_key, current_offset, next_field_type,
next_attributes, next_representation);
DataDescriptor d(old_key, current_offset, wrapped_type, next_attributes,
next_representation);
current_offset += d.GetDetails().field_width_in_words(); current_offset += d.GetDetails().field_width_in_words();
new_descriptors->Set(i, &d); new_descriptors->Set(i, &d);
} else { } else {
...@@ -2979,41 +2964,33 @@ MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) { ...@@ -2979,41 +2964,33 @@ MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) {
if (!old_details.representation().fits_into(new_details.representation())) { if (!old_details.representation().fits_into(new_details.representation())) {
return MaybeHandle<Map>(); return MaybeHandle<Map>();
} }
Object* new_value = new_descriptors->GetValue(i);
Object* old_value = old_descriptors->GetValue(i);
switch (new_details.type()) { switch (new_details.type()) {
case DATA: { case DATA: {
HeapType* new_type = new_descriptors->GetFieldType(i); PropertyType old_type = old_details.type();
PropertyType old_property_type = old_details.type(); if (old_type == DATA) {
if (old_property_type == DATA) { if (!HeapType::cast(old_value)->NowIs(HeapType::cast(new_value))) {
HeapType* old_type = old_descriptors->GetFieldType(i);
if (!old_type->NowIs(new_type)) {
return MaybeHandle<Map>(); return MaybeHandle<Map>();
} }
} else { } else {
DCHECK(old_property_type == DATA_CONSTANT); DCHECK(old_type == DATA_CONSTANT);
Object* old_value = old_descriptors->GetValue(i); if (!HeapType::cast(new_value)->NowContains(old_value)) {
if (!new_type->NowContains(old_value)) {
return MaybeHandle<Map>(); return MaybeHandle<Map>();
} }
} }
break; break;
} }
case ACCESSOR: { case ACCESSOR:
#ifdef DEBUG DCHECK(HeapType::Any()->Is(HeapType::cast(new_value)));
HeapType* new_type = new_descriptors->GetFieldType(i);
DCHECK(HeapType::Any()->Is(new_type));
#endif
break; break;
}
case DATA_CONSTANT: case DATA_CONSTANT:
case ACCESSOR_CONSTANT: { case ACCESSOR_CONSTANT:
Object* old_value = old_descriptors->GetValue(i);
Object* new_value = new_descriptors->GetValue(i);
if (old_details.location() == kField || old_value != new_value) { if (old_details.location() == kField || old_value != new_value) {
return MaybeHandle<Map>(); return MaybeHandle<Map>();
} }
break; break;
}
} }
} }
if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>(); if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>();
......
...@@ -6443,12 +6443,9 @@ class Map: public HeapObject { ...@@ -6443,12 +6443,9 @@ class Map: public HeapObject {
Map* FindLastMatchMap(int verbatim, int length, DescriptorArray* descriptors); Map* FindLastMatchMap(int verbatim, int length, DescriptorArray* descriptors);
// Update field type of the given descriptor to new representation and new
// type. The type must be prepared for storing in descriptor array:
// it must be either a simple type or a map wrapped in a weak cell.
void UpdateFieldType(int descriptor_number, Handle<Name> name, void UpdateFieldType(int descriptor_number, Handle<Name> name,
Representation new_representation, Representation new_representation,
Handle<Object> new_wrapped_type); Handle<HeapType> new_type);
void PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind, void PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind,
PropertyAttributes attributes); PropertyAttributes attributes);
......
...@@ -79,14 +79,10 @@ class DataDescriptor FINAL : public Descriptor { ...@@ -79,14 +79,10 @@ class DataDescriptor FINAL : public Descriptor {
PropertyAttributes attributes, Representation representation) PropertyAttributes attributes, Representation representation)
: Descriptor(key, HeapType::Any(key->GetIsolate()), attributes, DATA, : Descriptor(key, HeapType::Any(key->GetIsolate()), attributes, DATA,
representation, field_index) {} representation, field_index) {}
// The field type is either a simple type or a map wrapped in a weak cell. DataDescriptor(Handle<Name> key, int field_index, Handle<HeapType> field_type,
DataDescriptor(Handle<Name> key, int field_index,
Handle<Object> wrapped_field_type,
PropertyAttributes attributes, Representation representation) PropertyAttributes attributes, Representation representation)
: Descriptor(key, wrapped_field_type, attributes, DATA, representation, : Descriptor(key, field_type, attributes, DATA, representation,
field_index) { field_index) {}
DCHECK(wrapped_field_type->IsSmi() || wrapped_field_type->IsWeakCell());
}
}; };
......
...@@ -5083,40 +5083,6 @@ TEST(NumberStringCacheSize) { ...@@ -5083,40 +5083,6 @@ TEST(NumberStringCacheSize) {
} }
TEST(Regress3877) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
Factory* factory = isolate->factory();
HandleScope scope(isolate);
CompileRun("function cls() { this.x = 10; }");
Handle<WeakCell> weak_prototype;
{
HandleScope inner_scope(isolate);
v8::Local<v8::Value> result = CompileRun("cls.prototype");
Handle<JSObject> proto =
v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(result));
weak_prototype = inner_scope.CloseAndEscape(factory->NewWeakCell(proto));
}
CHECK(!weak_prototype->cleared());
CompileRun(
"var a = { };"
"a.x = new cls();"
"cls.prototype = null;");
for (int i = 0; i < 4; i++) {
heap->CollectAllGarbage(Heap::kNoGCFlags);
}
// The map of a.x keeps prototype alive
CHECK(!weak_prototype->cleared());
// Change the map of a.x and make the previous map garbage collectable.
CompileRun("a.x.__proto__ = {};");
for (int i = 0; i < 4; i++) {
heap->CollectAllGarbage(Heap::kNoGCFlags);
}
CHECK(weak_prototype->cleared());
}
#ifdef DEBUG #ifdef DEBUG
TEST(PathTracer) { TEST(PathTracer) {
CcTest::InitializeVM(); CcTest::InitializeVM();
......
...@@ -233,14 +233,12 @@ class Expectations { ...@@ -233,14 +233,12 @@ class Expectations {
representations_[descriptor])) { representations_[descriptor])) {
return false; return false;
} }
Object* value = descriptors->GetValue(descriptor);
Object* expected_value = *values_[descriptor]; Object* expected_value = *values_[descriptor];
Object* value = descriptors->GetValue(descriptor);
switch (type) { switch (type) {
case DATA: case DATA:
case ACCESSOR: { case ACCESSOR:
HeapType* type = descriptors->GetFieldType(descriptor); return HeapType::cast(expected_value)->Equals(HeapType::cast(value));
return HeapType::cast(expected_value)->Equals(type);
}
case DATA_CONSTANT: case DATA_CONSTANT:
return value == expected_value; return value == expected_value;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment