Commit a274fc65 authored by Ulan Degenbaev's avatar Ulan Degenbaev Committed by Commit Bot

[heap] Properly clear the weak slot in CodeDataContainer.

During iteration of the optimized code list to process weak slots, we
need to clear the next_code_link in the CodeDataContainer of a dying
code object because the CodeDataContainer can still be alive.

BUG=v8:6792

Change-Id: Iec5f7430a4097cb622de2157bdec2a7d539dbba0
Reviewed-on: https://chromium-review.googlesource.com/751663Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49087}
parent aa371fac
...@@ -37,6 +37,10 @@ Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer) { ...@@ -37,6 +37,10 @@ Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer) {
T* candidate = reinterpret_cast<T*>(list); T* candidate = reinterpret_cast<T*>(list);
Object* retained = retainer->RetainAs(list); Object* retained = retainer->RetainAs(list);
// Move to the next element before the WeakNext is cleared.
list = WeakListVisitor<T>::WeakNext(candidate);
if (retained != nullptr) { if (retained != nullptr) {
if (head == undefined) { if (head == undefined) {
// First element in the list. // First element in the list.
...@@ -63,9 +67,6 @@ Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer) { ...@@ -63,9 +67,6 @@ Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer) {
} else { } else {
WeakListVisitor<T>::VisitPhantomObject(heap, candidate); WeakListVisitor<T>::VisitPhantomObject(heap, candidate);
} }
// Move to next element in the list.
list = WeakListVisitor<T>::WeakNext(candidate);
} }
// Terminate the list if there is one or more elements. // Terminate the list if there is one or more elements.
...@@ -103,7 +104,11 @@ struct WeakListVisitor<Code> { ...@@ -103,7 +104,11 @@ struct WeakListVisitor<Code> {
static void VisitLiveObject(Heap*, Code*, WeakObjectRetainer*) {} static void VisitLiveObject(Heap*, Code*, WeakObjectRetainer*) {}
static void VisitPhantomObject(Heap*, Code*) {} static void VisitPhantomObject(Heap* heap, Code* code) {
// Even though the code is dying, its code_data_container can still be
// alive. Clear the next_code_link slot to avoid a dangling pointer.
SetWeakNext(code, heap->undefined_value());
}
}; };
......
...@@ -3909,6 +3909,30 @@ TEST(NextCodeLinkIsWeak) { ...@@ -3909,6 +3909,30 @@ TEST(NextCodeLinkIsWeak) {
CHECK_EQ(code_chain_length_before - 1, code_chain_length_after); CHECK_EQ(code_chain_length_before - 1, code_chain_length_after);
} }
TEST(NextCodeLinkInCodeDataContainerIsCleared) {
FLAG_always_opt = false;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
v8::internal::Heap* heap = CcTest::heap();
if (!isolate->use_optimizer()) return;
HandleScope outer_scope(heap->isolate());
Handle<CodeDataContainer> code_data_container;
{
HandleScope scope(heap->isolate());
Handle<JSFunction> mortal1 =
OptimizeDummyFunction(CcTest::isolate(), "mortal1");
Handle<JSFunction> mortal2 =
OptimizeDummyFunction(CcTest::isolate(), "mortal2");
CHECK_EQ(mortal2->code()->next_code_link(), mortal1->code());
code_data_container = scope.CloseAndEscape(
Handle<CodeDataContainer>(mortal2->code()->code_data_container()));
CompileRun("mortal1 = null; mortal2 = null;");
}
CcTest::CollectAllAvailableGarbage();
CHECK(code_data_container->next_code_link()->IsUndefined(isolate));
}
static Handle<Code> DummyOptimizedCode(Isolate* isolate) { static Handle<Code> DummyOptimizedCode(Isolate* isolate) {
i::byte buffer[i::Assembler::kMinimalBufferSize]; i::byte buffer[i::Assembler::kMinimalBufferSize];
......
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