[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/751663 Reviewed-by: Michael Lippautz <mlippautz@chromium.org> Commit-Queue: Ulan Degenbaev <ulan@chromium.org> Cr-Commit-Position: refs/heads/master@{#49087}
This commit is contained in:
parent
aa371fac37
commit
a274fc6536
@ -37,6 +37,10 @@ Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer) {
|
||||
T* candidate = reinterpret_cast<T*>(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 (head == undefined) {
|
||||
// First element in the list.
|
||||
@ -63,9 +67,6 @@ Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer) {
|
||||
} else {
|
||||
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.
|
||||
@ -103,7 +104,11 @@ struct WeakListVisitor<Code> {
|
||||
|
||||
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) {
|
||||
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) {
|
||||
i::byte buffer[i::Assembler::kMinimalBufferSize];
|
||||
|
Loading…
Reference in New Issue
Block a user