Commit 876b48f3 authored by ulan@chromium.org's avatar ulan@chromium.org

Skip write barriers when updating the weak hash table.

Write barrier on the weak hash table makes all its pointers strong,
which can cause a memory leak.

BUG=359401
LOG=Y
TEST=cctest/test-heap/NoWeakHashTableLeakWithIncrementalMarking
R=hpayer@chromium.org, mstarzinger@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21299 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f5631f73
...@@ -5460,6 +5460,8 @@ void Heap::AddWeakObjectToCodeDependency(Handle<Object> obj, ...@@ -5460,6 +5460,8 @@ void Heap::AddWeakObjectToCodeDependency(Handle<Object> obj,
Handle<DependentCode> dep) { Handle<DependentCode> dep) {
ASSERT(!InNewSpace(*obj)); ASSERT(!InNewSpace(*obj));
ASSERT(!InNewSpace(*dep)); ASSERT(!InNewSpace(*dep));
// This handle scope keeps the table handle local to this function, which
// allows us to safely skip write barriers in table update operations.
HandleScope scope(isolate()); HandleScope scope(isolate());
Handle<WeakHashTable> table(WeakHashTable::cast(weak_object_to_code_table_), Handle<WeakHashTable> table(WeakHashTable::cast(weak_object_to_code_table_),
isolate()); isolate());
......
...@@ -2634,6 +2634,7 @@ void MarkCompactCollector::ClearNonLiveReferences() { ...@@ -2634,6 +2634,7 @@ void MarkCompactCollector::ClearNonLiveReferences() {
ClearDependentCode(DependentCode::cast(value)); ClearDependentCode(DependentCode::cast(value));
table->set(key_index, heap_->the_hole_value()); table->set(key_index, heap_->the_hole_value());
table->set(value_index, heap_->the_hole_value()); table->set(value_index, heap_->the_hole_value());
table->ElementRemoved();
} }
} }
} }
......
...@@ -16168,7 +16168,10 @@ Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table, ...@@ -16168,7 +16168,10 @@ Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
int entry = table->FindEntry(key); int entry = table->FindEntry(key);
// Key is already in table, just overwrite value. // Key is already in table, just overwrite value.
if (entry != kNotFound) { if (entry != kNotFound) {
table->set(EntryToValueIndex(entry), *value); // TODO(ulan): Skipping write barrier is a temporary solution to avoid
// memory leaks. Remove this once we have special visitor for weak fixed
// arrays.
table->set(EntryToValueIndex(entry), *value, SKIP_WRITE_BARRIER);
return table; return table;
} }
...@@ -16184,8 +16187,11 @@ void WeakHashTable::AddEntry(int entry, ...@@ -16184,8 +16187,11 @@ void WeakHashTable::AddEntry(int entry,
Handle<Object> key, Handle<Object> key,
Handle<Object> value) { Handle<Object> value) {
DisallowHeapAllocation no_allocation; DisallowHeapAllocation no_allocation;
set(EntryToIndex(entry), *key); // TODO(ulan): Skipping write barrier is a temporary solution to avoid
set(EntryToValueIndex(entry), *value); // memory leaks. Remove this once we have special visitor for weak fixed
// arrays.
set(EntryToIndex(entry), *key, SKIP_WRITE_BARRIER);
set(EntryToValueIndex(entry), *value, SKIP_WRITE_BARRIER);
ElementAdded(); ElementAdded();
} }
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
using namespace v8::internal; using namespace v8::internal;
// Go through all incremental marking steps in one swoop. // Go through all incremental marking steps in one swoop.
static void SimulateIncrementalMarking() { static void SimulateIncrementalMarking() {
MarkCompactCollector* collector = CcTest::heap()->mark_compact_collector(); MarkCompactCollector* collector = CcTest::heap()->mark_compact_collector();
...@@ -3888,6 +3887,42 @@ TEST(ObjectsInOptimizedCodeAreWeak) { ...@@ -3888,6 +3887,42 @@ TEST(ObjectsInOptimizedCodeAreWeak) {
} }
TEST(NoWeakHashTableLeakWithIncrementalMarking) {
if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
if (!i::FLAG_incremental_marking) return;
i::FLAG_weak_embedded_objects_in_optimized_code = true;
i::FLAG_allow_natives_syntax = true;
i::FLAG_compilation_cache = false;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
v8::internal::Heap* heap = CcTest::heap();
if (!isolate->use_crankshaft()) return;
HandleScope outer_scope(heap->isolate());
for (int i = 0; i < 3; i++) {
SimulateIncrementalMarking();
{
LocalContext context;
HandleScope scope(heap->isolate());
EmbeddedVector<char, 256> source;
OS::SNPrintF(source,
"function bar%d() {"
" return foo%d(1);"
"};"
"function foo%d(x) { with (x) { return 1 + x; } };"
"bar%d();"
"bar%d();"
"bar%d();"
"%OptimizeFunctionOnNextCall(bar%d);"
"bar%d();", i, i, i, i, i, i, i, i);
CompileRun(source.start());
}
heap->CollectAllGarbage(i::Heap::kNoGCFlags);
}
WeakHashTable* table = WeakHashTable::cast(heap->weak_object_to_code_table());
CHECK_EQ(0, table->NumberOfElements());
}
static Handle<JSFunction> OptimizeDummyFunction(const char* name) { static Handle<JSFunction> OptimizeDummyFunction(const char* name) {
EmbeddedVector<char, 256> source; EmbeddedVector<char, 256> source;
......
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