diff --git a/BUILD.gn b/BUILD.gn index 36cb9add36..62920cd76c 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -3008,6 +3008,7 @@ v8_source_set("torque_base") { v8_component("v8_libbase") { sources = [ "src/base/adapters.h", + "src/base/address-region.h", "src/base/atomic-utils.h", "src/base/atomicops.h", "src/base/atomicops_internals_atomicword_compat.h", diff --git a/src/allocation.cc b/src/allocation.cc index c16c2b192c..6327a9c965 100644 --- a/src/allocation.cc +++ b/src/allocation.cc @@ -212,10 +212,10 @@ VirtualMemory::VirtualMemory(v8::PageAllocator* page_allocator, size_t size, size_t page_size = page_allocator_->AllocatePageSize(); alignment = RoundUp(alignment, page_size); size = RoundUp(size, page_size); - address_ = reinterpret_cast
(AllocatePages( + Address address = reinterpret_cast(AllocatePages( page_allocator_, hint, size, alignment, PageAllocator::kNoAccess)); - if (address_ != kNullAddress) { - size_ = size; + if (address != kNullAddress) { + region_ = base::AddressRegion(address, size); } } @@ -227,8 +227,7 @@ VirtualMemory::~VirtualMemory() { void VirtualMemory::Reset() { page_allocator_ = nullptr; - address_ = kNullAddress; - size_ = 0; + region_ = base::AddressRegion(); } bool VirtualMemory::SetPermissions(Address address, size_t size, @@ -245,14 +244,13 @@ size_t VirtualMemory::Release(Address free_start) { DCHECK(IsAddressAligned(free_start, page_allocator_->CommitPageSize())); // Notice: Order is important here. The VirtualMemory object might live // inside the allocated region. - const size_t free_size = size_ - (free_start - address_); - size_t old_size = size_; + + const size_t old_size = region_.size(); + const size_t free_size = old_size - (free_start - region_.begin()); CHECK(InVM(free_start, free_size)); - DCHECK_LT(address_, free_start); - DCHECK_LT(free_start, address_ + size_); - size_ -= free_size; - CHECK(ReleasePages(page_allocator_, reinterpret_cast code, int object_size,
bool is_turbofanned, int stack_slots,
int safepoint_table_offset, int handler_table_offset) {
DCHECK(IsAligned(code->address(), kCodeAlignment));
- DCHECK(!heap->memory_allocator()->code_range_valid() ||
- heap->memory_allocator()->code_range_contains(code->address()) ||
- object_size <= heap->code_space()->AreaSize());
+ DCHECK_IMPLIES(
+ !heap->memory_allocator()->code_range().is_empty(),
+ heap->memory_allocator()->code_range().contains(code->address()));
bool has_unwinding_info = desc.unwinding_info != nullptr;
@@ -2674,9 +2674,9 @@ Handle Factory::NewCodeForDeserialization(uint32_t size) {
heap->ZapCodeObject(result->address(), size);
result->set_map_after_allocation(*code_map(), SKIP_WRITE_BARRIER);
DCHECK(IsAligned(result->address(), kCodeAlignment));
- DCHECK(!heap->memory_allocator()->code_range_valid() ||
- heap->memory_allocator()->code_range_contains(result->address()) ||
- static_cast(size) <= heap->code_space()->AreaSize());
+ DCHECK_IMPLIES(
+ !heap->memory_allocator()->code_range().is_empty(),
+ heap->memory_allocator()->code_range().contains(result->address()));
return handle(Code::cast(result), isolate());
}
@@ -2738,9 +2738,9 @@ Handle Factory::CopyCode(Handle code) {
if (FLAG_verify_heap) new_code->ObjectVerify(isolate());
#endif
DCHECK(IsAligned(new_code->address(), kCodeAlignment));
- DCHECK(!heap->memory_allocator()->code_range_valid() ||
- heap->memory_allocator()->code_range_contains(new_code->address()) ||
- obj_size <= heap->code_space()->AreaSize());
+ DCHECK_IMPLIES(
+ !heap->memory_allocator()->code_range().is_empty(),
+ heap->memory_allocator()->code_range().contains(new_code->address()));
return new_code;
}
diff --git a/src/heap/spaces-inl.h b/src/heap/spaces-inl.h
index 5f9a33a1ea..7162769e5e 100644
--- a/src/heap/spaces-inl.h
+++ b/src/heap/spaces-inl.h
@@ -546,32 +546,6 @@ bool LocalAllocationBuffer::TryFreeLast(HeapObject* object, int object_size) {
return false;
}
-// -----------------------------------------------------------------------------
-// MemoryAllocator
-
-bool MemoryAllocator::code_range_valid() const {
- return code_page_allocator_instance_.get() != nullptr;
-}
-
-Address MemoryAllocator::code_range_start() const {
- DCHECK(code_range_valid());
- // TODO(ishell): once a follow-up CL is landed add assert that
- // |code_range_| >= |optional RW pages| + |code_page_allocator_instance_|
- return code_range_start_;
-}
-
-size_t MemoryAllocator::code_range_size() const {
- DCHECK(code_range_valid());
- // TODO(ishell): once a follow-up CL is landed add assert that
- // |code_range_| >= |optional RW pages| + |code_page_allocator_instance_|
- return code_range_size_;
-}
-
-bool MemoryAllocator::code_range_contains(Address address) const {
- DCHECK(code_range_valid());
- return (address - code_range_start_) < code_range_size_;
-}
-
} // namespace internal
} // namespace v8
diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc
index b36620203f..e6a79ffc8a 100644
--- a/src/heap/spaces.cc
+++ b/src/heap/spaces.cc
@@ -123,8 +123,6 @@ MemoryAllocator::MemoryAllocator(Isolate* isolate, size_t capacity,
: isolate_(isolate),
data_page_allocator_(GetPlatformPageAllocator()),
code_page_allocator_(nullptr),
- code_range_start_(kNullAddress),
- code_range_size_(0),
capacity_(RoundUp(capacity, Page::kPageSize)),
size_(0),
size_executable_(0),
@@ -168,8 +166,7 @@ void MemoryAllocator::InitializeCodePageAllocator(
V8::FatalProcessOutOfMemory(isolate_,
"CodeRange setup: allocate virtual memory");
}
- code_range_start_ = reservation.address();
- code_range_size_ = reservation.size();
+ code_range_ = reservation.region();
// We are sure that we have mapped a block of requested addresses.
DCHECK_GE(reservation.size(), requested);
diff --git a/src/heap/spaces.h b/src/heap/spaces.h
index 2aeed2ae4d..3c49dd6d06 100644
--- a/src/heap/spaces.h
+++ b/src/heap/spaces.h
@@ -1389,10 +1389,16 @@ class V8_EXPORT_PRIVATE MemoryAllocator {
: data_page_allocator_;
}
- V8_INLINE bool code_range_valid() const;
- V8_INLINE Address code_range_start() const;
- V8_INLINE size_t code_range_size() const;
- V8_INLINE bool code_range_contains(Address address) const;
+ // A region of memory that may contain executable code including reserved
+ // OS page with read-write access in the beginning.
+ const base::AddressRegion& code_range() const {
+ // |code_range_| >= |optional RW pages| + |code_page_allocator_instance_|
+ DCHECK_IMPLIES(!code_range_.is_empty(), code_page_allocator_instance_);
+ DCHECK_IMPLIES(!code_range_.is_empty(),
+ code_range_.contains(code_page_allocator_instance_->begin(),
+ code_page_allocator_instance_->size()));
+ return code_range_;
+ }
Unmapper* unmapper() { return &unmapper_; }
@@ -1472,14 +1478,12 @@ class V8_EXPORT_PRIVATE MemoryAllocator {
// A part of the |heap_reservation_| that may contain executable code
// including reserved page with read-write access in the beginning.
// See details below.
- // TODO(ishell): introduce base::AddressRange code_range_; instead.
- Address code_range_start_;
- size_t code_range_size_;
+ base::AddressRegion code_range_;
// This unique pointer owns the instance of bounded code allocator
// that controls executable pages allocation. It does not control the
// optionally existing page in the beginning of the |code_range_|.
- // So, summarizing all above, the following condition holds:
+ // So, summarizing all above, the following conditions hold:
// 1) |heap_reservation_| >= |code_range_|
// 2) |code_range_| >= |optional RW pages| + |code_page_allocator_instance_|.
// 3) |heap_reservation_| is AllocatePageSize()-aligned
diff --git a/src/profiler/tick-sample.cc b/src/profiler/tick-sample.cc
index 06986eb3f1..69a6bbf778 100644
--- a/src/profiler/tick-sample.cc
+++ b/src/profiler/tick-sample.cc
@@ -205,8 +205,8 @@ bool TickSample::GetStackSample(Isolate* v8_isolate, RegisterState* regs,
// Check whether we interrupted setup/teardown of a stack frame in JS code.
// Avoid this check for C++ code, as that would trigger false positives.
- if (regs->pc && isolate->heap()->memory_allocator()->code_range_valid() &&
- isolate->heap()->memory_allocator()->code_range_contains(
+ if (regs->pc &&
+ isolate->heap()->memory_allocator()->code_range().contains(
reinterpret_cast(regs->pc)) &&
IsNoFrameRegion(reinterpret_cast(regs->pc))) {
// The frame is not setup, so it'd be hard to iterate the stack. Bailout.
diff --git a/test/unittests/BUILD.gn b/test/unittests/BUILD.gn
index 6a42451722..6c4be258eb 100644
--- a/test/unittests/BUILD.gn
+++ b/test/unittests/BUILD.gn
@@ -55,6 +55,7 @@ v8_source_set("unittests_sources") {
"asmjs/asm-scanner-unittest.cc",
"asmjs/asm-types-unittest.cc",
"asmjs/switch-logic-unittest.cc",
+ "base/address-region-unittest.cc",
"base/atomic-utils-unittest.cc",
"base/bits-unittest.cc",
"base/cpu-unittest.cc",
diff --git a/test/unittests/base/address-region-unittest.cc b/test/unittests/base/address-region-unittest.cc
new file mode 100644
index 0000000000..b0bca8ab35
--- /dev/null
+++ b/test/unittests/base/address-region-unittest.cc
@@ -0,0 +1,64 @@
+// Copyright 2018 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.
+
+#include "src/base/address-region.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace v8 {
+namespace base {
+
+using Address = AddressRegion::Address;
+
+TEST(AddressRegionTest, Contains) {
+ struct {
+ Address start;
+ size_t size;
+ } test_cases[] = {{153, 771}, {0, 227}, {-447, 447}};
+
+ for (size_t i = 0; i < arraysize(test_cases); i++) {
+ Address start = test_cases[i].start;
+ size_t size = test_cases[i].size;
+ Address end = start + size; // exclusive
+
+ AddressRegion region(start, size);
+
+ // Test single-argument contains().
+ CHECK(!region.contains(start - 1041));
+ CHECK(!region.contains(start - 1));
+ CHECK(!region.contains(end));
+ CHECK(!region.contains(end + 1));
+ CHECK(!region.contains(end + 113));
+
+ CHECK(region.contains(start));
+ CHECK(region.contains(start + 1));
+ CHECK(region.contains(start + size / 2));
+ CHECK(region.contains(end - 1));
+
+ // Test two-arguments contains().
+ CHECK(!region.contains(start - 17, 17));
+ CHECK(!region.contains(start - 17, size * 2));
+ CHECK(!region.contains(end, 1));
+ CHECK(!region.contains(end, static_cast(0 - end)));
+
+ CHECK(region.contains(start, size));
+ CHECK(region.contains(start, 10));
+ CHECK(region.contains(start + 11, 120));
+ CHECK(region.contains(end - 13, 13));
+ CHECK(!region.contains(end, 0));
+
+ // Zero-size queries.
+ CHECK(!region.contains(start - 10, 0));
+ CHECK(!region.contains(start - 1, 0));
+ CHECK(!region.contains(end, 0));
+ CHECK(!region.contains(end + 10, 0));
+
+ CHECK(region.contains(start, 0));
+ CHECK(region.contains(start + 10, 0));
+ CHECK(region.contains(end - 1, 0));
+ }
+}
+
+} // namespace base
+} // namespace v8
diff --git a/test/unittests/base/region-allocator-unittest.cc b/test/unittests/base/region-allocator-unittest.cc
index ab8ac7dc8b..599c4ae8ed 100644
--- a/test/unittests/base/region-allocator-unittest.cc
+++ b/test/unittests/base/region-allocator-unittest.cc
@@ -322,56 +322,5 @@ TEST(RegionAllocatorTest, FindRegion) {
}
}
-TEST(RegionAllocatorTest, Contains) {
- using Region = RegionAllocator::Region;
-
- struct {
- Address start;
- size_t size;
- } test_cases[] = {{153, 771}, {0, 227}, {-447, 447}};
-
- for (size_t i = 0; i < arraysize(test_cases); i++) {
- Address start = test_cases[i].start;
- size_t size = test_cases[i].size;
- Address end = start + size; // exclusive
-
- Region region(start, size, true);
-
- // Test single-argument contains().
- CHECK(!region.contains(start - 1041));
- CHECK(!region.contains(start - 1));
- CHECK(!region.contains(end));
- CHECK(!region.contains(end + 1));
- CHECK(!region.contains(end + 113));
-
- CHECK(region.contains(start));
- CHECK(region.contains(start + 1));
- CHECK(region.contains(start + size / 2));
- CHECK(region.contains(end - 1));
-
- // Test two-arguments contains().
- CHECK(!region.contains(start - 17, 17));
- CHECK(!region.contains(start - 17, size * 2));
- CHECK(!region.contains(end, 1));
- CHECK(!region.contains(end, static_cast(0 - end)));
-
- CHECK(region.contains(start, size));
- CHECK(region.contains(start, 10));
- CHECK(region.contains(start + 11, 120));
- CHECK(region.contains(end - 13, 13));
- CHECK(!region.contains(end, 0));
-
- // Zero-size queries.
- CHECK(!region.contains(start - 10, 0));
- CHECK(!region.contains(start - 1, 0));
- CHECK(!region.contains(end, 0));
- CHECK(!region.contains(end + 10, 0));
-
- CHECK(region.contains(start, 0));
- CHECK(region.contains(start + 10, 0));
- CHECK(region.contains(end - 1, 0));
- }
-}
-
} // namespace base
} // namespace v8