[heap] Initialize the owner on each page after lospace allocation

The least two bits of the owner field of a Page are used to determine
whether the Page is part of a large object. If these bits are not equal
to 0x11, the page is part of a large object and needs special handling
e.g. in MemoryChunk::FromAnyPointerAddress to determine which chunk it
belongs to.

This CL fixes an issue in which the store buffer overflows after
a large object space allocation but before the object has been fully
initialized. Store buffer overflow handling attempts to look up the
chunk of a page, but fails to do so correctly since the page's owner
field has not yet been initialized.

This CL ensures that the owner field of all pages belonging to a large
object allocation are initialized to a value that is interpreted
correctly.

BUG=chromium:672041

Review-Url: https://codereview.chromium.org/2565713002
Cr-Commit-Position: refs/heads/master@{#41641}
This commit is contained in:
jgruber 2016-12-12 05:18:18 -08:00 committed by Commit bot
parent 222541dff5
commit 9b6808bfb5
3 changed files with 36 additions and 2 deletions

View File

@ -590,6 +590,14 @@ LargePage* LargePage::Initialize(Heap* heap, MemoryChunk* chunk,
FATAL("Code page is too large.");
}
heap->incremental_marking()->SetOldSpacePageFlags(chunk);
// Initialize the owner field for each contained page (except the first, which
// is initialized by MemoryChunk::Initialize).
for (size_t i = Page::kPageSize; i < chunk->size(); i += Page::kPageSize) {
// Clear out kPageHeaderTag.
Memory::Address_at(chunk->address() + i + Page::kOwnerOffset) = 0;
}
return static_cast<LargePage*>(chunk);
}

View File

@ -317,8 +317,11 @@ class MemoryChunk {
static const intptr_t kAlignmentMask = kAlignment - 1;
static const intptr_t kSizeOffset = 0;
static const intptr_t kFlagsOffset = kSizeOffset + kPointerSize;
static const intptr_t kFlagsOffset = kSizeOffset + kSizetSize;
static const intptr_t kAreaStartOffset = kFlagsOffset + kIntptrSize;
static const intptr_t kAreaEndOffset = kAreaStartOffset + kPointerSize;
static const intptr_t kReservationOffset = kAreaEndOffset + kPointerSize;
static const intptr_t kOwnerOffset = kReservationOffset + 2 * kPointerSize;
static const size_t kMinHeaderSize =
kSizeOffset + kSizetSize // size_t size

View File

@ -0,0 +1,23 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Trigger an infinite loop through RegExp.prototype[@@match], which results
// in unbounded growth of the results array.
// Limit the number of iterations to avoid OOM while still triggering large
// object space allocation.
const min_ptr_size = 4;
const max_regular_heap_object_size = 507136;
const num_iterations = max_regular_heap_object_size / min_ptr_size;
const RegExpPrototypeExec = RegExp.prototype.exec;
let i = 0;
RegExp.prototype.__defineGetter__("global", () => true);
RegExp.prototype.exec = function(str) {
return (i++ < num_iterations) ? RegExpPrototypeExec.call(this, str) : null;
};
"a".match();