test-spaces.cc 8 KB
Newer Older
1
// Copyright 2011 the V8 project authors. All rights reserved.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <stdlib.h>

#include "v8.h"
#include "cctest.h"

using namespace v8::internal;

35
#if 0
36
static void VerifyRegionMarking(Address page_start) {
37
#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
38 39
  Page* p = Page::FromAddress(page_start);

40
  p->SetRegionMarks(Page::kAllRegionsCleanMarks);
41 42 43 44

  for (Address addr = p->ObjectAreaStart();
       addr < p->ObjectAreaEnd();
       addr += kPointerSize) {
45
    CHECK(!Page::FromAddress(addr)->IsRegionDirty(addr));
46 47 48 49 50
  }

  for (Address addr = p->ObjectAreaStart();
       addr < p->ObjectAreaEnd();
       addr += kPointerSize) {
51
    Page::FromAddress(addr)->MarkRegionDirty(addr);
52 53 54 55 56
  }

  for (Address addr = p->ObjectAreaStart();
       addr < p->ObjectAreaEnd();
       addr += kPointerSize) {
57
    CHECK(Page::FromAddress(addr)->IsRegionDirty(addr));
58
  }
59
#endif
60
}
61
#endif
62 63


64 65
// TODO(gc) you can no longer allocate pages like this. Details are hidden.
#if 0
66 67 68 69 70 71 72 73
TEST(Page) {
  byte* mem = NewArray<byte>(2*Page::kPageSize);
  CHECK(mem != NULL);

  Address start = reinterpret_cast<Address>(mem);
  Address page_start = RoundUp(start, Page::kPageSize);

  Page* p = Page::FromAddress(page_start);
74 75
  // Initialized Page has heap pointer, normally set by memory_allocator.
  p->heap_ = HEAP;
76 77 78 79
  CHECK(p->address() == page_start);
  CHECK(p->is_valid());

  p->opaque_header = 0;
80
  p->SetIsLargeObjectPage(false);
81 82 83 84 85 86 87 88 89 90 91 92
  CHECK(!p->next_page()->is_valid());

  CHECK(p->ObjectAreaStart() == page_start + Page::kObjectStartOffset);
  CHECK(p->ObjectAreaEnd() == page_start + Page::kPageSize);

  CHECK(p->Offset(page_start + Page::kObjectStartOffset) ==
        Page::kObjectStartOffset);
  CHECK(p->Offset(page_start + Page::kPageSize) == Page::kPageSize);

  CHECK(p->OffsetToAddress(Page::kObjectStartOffset) == p->ObjectAreaStart());
  CHECK(p->OffsetToAddress(Page::kPageSize) == p->ObjectAreaEnd());

93 94
  // test region marking
  VerifyRegionMarking(page_start);
95 96 97

  DeleteArray(mem);
}
98
#endif
99 100


101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
namespace v8 {
namespace internal {

// Temporarily sets a given allocator in an isolate.
class TestMemoryAllocatorScope {
 public:
  TestMemoryAllocatorScope(Isolate* isolate, MemoryAllocator* allocator)
      : isolate_(isolate),
        old_allocator_(isolate->memory_allocator_) {
    isolate->memory_allocator_ = allocator;
  }

  ~TestMemoryAllocatorScope() {
    isolate_->memory_allocator_ = old_allocator_;
  }

 private:
  Isolate* isolate_;
  MemoryAllocator* old_allocator_;

  DISALLOW_COPY_AND_ASSIGN(TestMemoryAllocatorScope);
};

} }  // namespace v8::internal


127
TEST(MemoryAllocator) {
128 129
  OS::Setup();
  Isolate* isolate = Isolate::Current();
130 131
  isolate->InitializeLoggingAndCounters();
  Heap* heap = isolate->heap();
132 133
  CHECK(isolate->heap()->ConfigureHeapDefault());

134 135 136 137
  MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
  CHECK(memory_allocator->Setup(heap->MaxReserved(),
                                heap->MaxExecutableSize()));

138
  int total_pages = 0;
139 140
  OldSpace faked_space(heap,
                       heap->MaxReserved(),
141 142
                       OLD_POINTER_SPACE,
                       NOT_EXECUTABLE);
143 144 145 146
  Page* first_page =
      memory_allocator->AllocatePage(&faked_space, NOT_EXECUTABLE);

  first_page->InsertAfter(faked_space.anchor()->prev_page());
147
  CHECK(first_page->is_valid());
148 149
  CHECK(first_page->next_page() == faked_space.anchor());
  total_pages++;
150

151 152
  for (Page* p = first_page; p != faked_space.anchor(); p = p->next_page()) {
    CHECK(p->owner() == &faked_space);
153 154
  }

155
  // Again, we should get n or n - 1 pages.
156 157 158 159 160
  Page* other =
      memory_allocator->AllocatePage(&faked_space, NOT_EXECUTABLE);
  CHECK(other->is_valid());
  total_pages++;
  other->InsertAfter(first_page);
161
  int page_count = 0;
162 163
  for (Page* p = first_page; p != faked_space.anchor(); p = p->next_page()) {
    CHECK(p->owner() == &faked_space);
164 165 166 167 168 169
    page_count++;
  }
  CHECK(total_pages == page_count);

  Page* second_page = first_page->next_page();
  CHECK(second_page->is_valid());
170 171
  memory_allocator->Free(first_page);
  memory_allocator->Free(second_page);
172 173
  memory_allocator->TearDown();
  delete memory_allocator;
174 175 176 177
}


TEST(NewSpace) {
178
  OS::Setup();
179 180 181 182 183 184 185 186
  Isolate* isolate = Isolate::Current();
  isolate->InitializeLoggingAndCounters();
  Heap* heap = isolate->heap();
  CHECK(heap->ConfigureHeapDefault());
  MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
  CHECK(memory_allocator->Setup(heap->MaxReserved(),
                                heap->MaxExecutableSize()));
  TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
187

188
  NewSpace new_space(heap);
189

190 191
  CHECK(new_space.Setup(HEAP->ReservedSemiSpaceSize(),
                        HEAP->ReservedSemiSpaceSize()));
192
  CHECK(new_space.HasBeenSetup());
193

194
  while (new_space.Available() >= Page::kMaxHeapObjectSize) {
195 196
    Object* obj =
        new_space.AllocateRaw(Page::kMaxHeapObjectSize)->ToObjectUnchecked();
197
    CHECK(new_space.Contains(HeapObject::cast(obj)));
198 199
  }

200
  new_space.TearDown();
201 202
  memory_allocator->TearDown();
  delete memory_allocator;
203 204 205 206
}


TEST(OldSpace) {
207
  OS::Setup();
208 209 210 211 212 213 214 215 216 217 218
  Isolate* isolate = Isolate::Current();
  isolate->InitializeLoggingAndCounters();
  Heap* heap = isolate->heap();
  CHECK(heap->ConfigureHeapDefault());
  MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
  CHECK(memory_allocator->Setup(heap->MaxReserved(),
                                heap->MaxExecutableSize()));
  TestMemoryAllocatorScope test_scope(isolate, memory_allocator);

  OldSpace* s = new OldSpace(heap,
                             heap->MaxOldGenerationSize(),
219 220
                             OLD_POINTER_SPACE,
                             NOT_EXECUTABLE);
221 222
  CHECK(s != NULL);

223
  CHECK(s->Setup());
224 225

  while (s->Available() > 0) {
226
    s->AllocateRaw(Page::kMaxHeapObjectSize)->ToObjectUnchecked();
227 228 229 230
  }

  s->TearDown();
  delete s;
231 232
  memory_allocator->TearDown();
  delete memory_allocator;
233 234 235 236
}


TEST(LargeObjectSpace) {
237
  v8::V8::Initialize();
238

239
  LargeObjectSpace* lo = HEAP->lo_space();
240 241 242 243
  CHECK(lo != NULL);

  int lo_size = Page::kPageSize;

244
  Object* obj = lo->AllocateRaw(lo_size, NOT_EXECUTABLE)->ToObjectUnchecked();
245 246 247 248 249 250 251 252 253 254 255
  CHECK(obj->IsHeapObject());

  HeapObject* ho = HeapObject::cast(obj);

  CHECK(lo->Contains(HeapObject::cast(obj)));

  CHECK(lo->FindObject(ho->address()) == obj);

  CHECK(lo->Contains(ho));

  while (true) {
256
    intptr_t available = lo->Available();
257
    { MaybeObject* maybe_obj = lo->AllocateRaw(lo_size, NOT_EXECUTABLE);
258 259
      if (!maybe_obj->ToObject(&obj)) break;
    }
260 261 262 263 264
    CHECK(lo->Available() < available);
  };

  CHECK(!lo->IsEmpty());

265
  CHECK(lo->AllocateRaw(lo_size, NOT_EXECUTABLE)->IsFailure());
266
}