1// Copyright 2011 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28#include <stdlib.h> 29 30#include "v8.h" 31#include "cctest.h" 32 33using namespace v8::internal; 34 35#if 0 36static void VerifyRegionMarking(Address page_start) { 37#ifdef ENABLE_CARDMARKING_WRITE_BARRIER 38 Page* p = Page::FromAddress(page_start); 39 40 p->SetRegionMarks(Page::kAllRegionsCleanMarks); 41 42 for (Address addr = p->ObjectAreaStart(); 43 addr < p->ObjectAreaEnd(); 44 addr += kPointerSize) { 45 CHECK(!Page::FromAddress(addr)->IsRegionDirty(addr)); 46 } 47 48 for (Address addr = p->ObjectAreaStart(); 49 addr < p->ObjectAreaEnd(); 50 addr += kPointerSize) { 51 Page::FromAddress(addr)->MarkRegionDirty(addr); 52 } 53 54 for (Address addr = p->ObjectAreaStart(); 55 addr < p->ObjectAreaEnd(); 56 addr += kPointerSize) { 57 CHECK(Page::FromAddress(addr)->IsRegionDirty(addr)); 58 } 59#endif 60} 61#endif 62 63 64// TODO(gc) you can no longer allocate pages like this. Details are hidden. 65#if 0 66TEST(Page) { 67 byte* mem = NewArray<byte>(2*Page::kPageSize); 68 CHECK(mem != NULL); 69 70 Address start = reinterpret_cast<Address>(mem); 71 Address page_start = RoundUp(start, Page::kPageSize); 72 73 Page* p = Page::FromAddress(page_start); 74 // Initialized Page has heap pointer, normally set by memory_allocator. 75 p->heap_ = HEAP; 76 CHECK(p->address() == page_start); 77 CHECK(p->is_valid()); 78 79 p->opaque_header = 0; 80 p->SetIsLargeObjectPage(false); 81 CHECK(!p->next_page()->is_valid()); 82 83 CHECK(p->ObjectAreaStart() == page_start + Page::kObjectStartOffset); 84 CHECK(p->ObjectAreaEnd() == page_start + Page::kPageSize); 85 86 CHECK(p->Offset(page_start + Page::kObjectStartOffset) == 87 Page::kObjectStartOffset); 88 CHECK(p->Offset(page_start + Page::kPageSize) == Page::kPageSize); 89 90 CHECK(p->OffsetToAddress(Page::kObjectStartOffset) == p->ObjectAreaStart()); 91 CHECK(p->OffsetToAddress(Page::kPageSize) == p->ObjectAreaEnd()); 92 93 // test region marking 94 VerifyRegionMarking(page_start); 95 96 DeleteArray(mem); 97} 98#endif 99 100 101namespace v8 { 102namespace internal { 103 104// Temporarily sets a given allocator in an isolate. 105class TestMemoryAllocatorScope { 106 public: 107 TestMemoryAllocatorScope(Isolate* isolate, MemoryAllocator* allocator) 108 : isolate_(isolate), 109 old_allocator_(isolate->memory_allocator_) { 110 isolate->memory_allocator_ = allocator; 111 } 112 113 ~TestMemoryAllocatorScope() { 114 isolate_->memory_allocator_ = old_allocator_; 115 } 116 117 private: 118 Isolate* isolate_; 119 MemoryAllocator* old_allocator_; 120 121 DISALLOW_COPY_AND_ASSIGN(TestMemoryAllocatorScope); 122}; 123 124} } // namespace v8::internal 125 126 127TEST(MemoryAllocator) { 128 OS::SetUp(); 129 Isolate* isolate = Isolate::Current(); 130 isolate->InitializeLoggingAndCounters(); 131 Heap* heap = isolate->heap(); 132 CHECK(isolate->heap()->ConfigureHeapDefault()); 133 134 MemoryAllocator* memory_allocator = new MemoryAllocator(isolate); 135 CHECK(memory_allocator->SetUp(heap->MaxReserved(), 136 heap->MaxExecutableSize())); 137 138 int total_pages = 0; 139 OldSpace faked_space(heap, 140 heap->MaxReserved(), 141 OLD_POINTER_SPACE, 142 NOT_EXECUTABLE); 143 Page* first_page = 144 memory_allocator->AllocatePage(&faked_space, NOT_EXECUTABLE); 145 146 first_page->InsertAfter(faked_space.anchor()->prev_page()); 147 CHECK(first_page->is_valid()); 148 CHECK(first_page->next_page() == faked_space.anchor()); 149 total_pages++; 150 151 for (Page* p = first_page; p != faked_space.anchor(); p = p->next_page()) { 152 CHECK(p->owner() == &faked_space); 153 } 154 155 // Again, we should get n or n - 1 pages. 156 Page* other = 157 memory_allocator->AllocatePage(&faked_space, NOT_EXECUTABLE); 158 CHECK(other->is_valid()); 159 total_pages++; 160 other->InsertAfter(first_page); 161 int page_count = 0; 162 for (Page* p = first_page; p != faked_space.anchor(); p = p->next_page()) { 163 CHECK(p->owner() == &faked_space); 164 page_count++; 165 } 166 CHECK(total_pages == page_count); 167 168 Page* second_page = first_page->next_page(); 169 CHECK(second_page->is_valid()); 170 memory_allocator->Free(first_page); 171 memory_allocator->Free(second_page); 172 memory_allocator->TearDown(); 173 delete memory_allocator; 174} 175 176 177TEST(NewSpace) { 178 OS::SetUp(); 179 Isolate* isolate = Isolate::Current(); 180 isolate->InitializeLoggingAndCounters(); 181 Heap* heap = isolate->heap(); 182 CHECK(heap->ConfigureHeapDefault()); 183 MemoryAllocator* memory_allocator = new MemoryAllocator(isolate); 184 CHECK(memory_allocator->SetUp(heap->MaxReserved(), 185 heap->MaxExecutableSize())); 186 TestMemoryAllocatorScope test_scope(isolate, memory_allocator); 187 188 NewSpace new_space(heap); 189 190 CHECK(new_space.SetUp(HEAP->ReservedSemiSpaceSize(), 191 HEAP->ReservedSemiSpaceSize())); 192 CHECK(new_space.HasBeenSetUp()); 193 194 while (new_space.Available() >= Page::kMaxNonCodeHeapObjectSize) { 195 Object* obj = 196 new_space.AllocateRaw(Page::kMaxNonCodeHeapObjectSize)-> 197 ToObjectUnchecked(); 198 CHECK(new_space.Contains(HeapObject::cast(obj))); 199 } 200 201 new_space.TearDown(); 202 memory_allocator->TearDown(); 203 delete memory_allocator; 204} 205 206 207TEST(OldSpace) { 208 OS::SetUp(); 209 Isolate* isolate = Isolate::Current(); 210 isolate->InitializeLoggingAndCounters(); 211 Heap* heap = isolate->heap(); 212 CHECK(heap->ConfigureHeapDefault()); 213 MemoryAllocator* memory_allocator = new MemoryAllocator(isolate); 214 CHECK(memory_allocator->SetUp(heap->MaxReserved(), 215 heap->MaxExecutableSize())); 216 TestMemoryAllocatorScope test_scope(isolate, memory_allocator); 217 218 OldSpace* s = new OldSpace(heap, 219 heap->MaxOldGenerationSize(), 220 OLD_POINTER_SPACE, 221 NOT_EXECUTABLE); 222 CHECK(s != NULL); 223 224 CHECK(s->SetUp()); 225 226 while (s->Available() > 0) { 227 s->AllocateRaw(Page::kMaxNonCodeHeapObjectSize)->ToObjectUnchecked(); 228 } 229 230 s->TearDown(); 231 delete s; 232 memory_allocator->TearDown(); 233 delete memory_allocator; 234} 235 236 237TEST(LargeObjectSpace) { 238 v8::V8::Initialize(); 239 240 LargeObjectSpace* lo = HEAP->lo_space(); 241 CHECK(lo != NULL); 242 243 int lo_size = Page::kPageSize; 244 245 Object* obj = lo->AllocateRaw(lo_size, NOT_EXECUTABLE)->ToObjectUnchecked(); 246 CHECK(obj->IsHeapObject()); 247 248 HeapObject* ho = HeapObject::cast(obj); 249 250 CHECK(lo->Contains(HeapObject::cast(obj))); 251 252 CHECK(lo->FindObject(ho->address()) == obj); 253 254 CHECK(lo->Contains(ho)); 255 256 while (true) { 257 intptr_t available = lo->Available(); 258 { MaybeObject* maybe_obj = lo->AllocateRaw(lo_size, NOT_EXECUTABLE); 259 if (!maybe_obj->ToObject(&obj)) break; 260 } 261 CHECK(lo->Available() < available); 262 }; 263 264 CHECK(!lo->IsEmpty()); 265 266 CHECK(lo->AllocateRaw(lo_size, NOT_EXECUTABLE)->IsFailure()); 267} 268