[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:
parent
222541dff5
commit
9b6808bfb5
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
23
test/mjsunit/regress/regress-672041.js
Normal file
23
test/mjsunit/regress/regress-672041.js
Normal 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();
|
Loading…
Reference in New Issue
Block a user