The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / test / cctest / test-mark-compact.cc @ 40c0f755

History | View | Annotate | Download (9.88 KB)

1
// Copyright 2006-2008 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

    
32
#include "global-handles.h"
33
#include "snapshot.h"
34
#include "top.h"
35
#include "cctest.h"
36

    
37
using namespace v8::internal;
38

    
39
static v8::Persistent<v8::Context> env;
40

    
41
static void InitializeVM() {
42
  if (env.IsEmpty()) env = v8::Context::New();
43
  v8::HandleScope scope;
44
  env->Enter();
45
}
46

    
47

    
48
TEST(MarkingStack) {
49
  int mem_size = 20 * kPointerSize;
50
  byte* mem = NewArray<byte>(20*kPointerSize);
51
  Address low = reinterpret_cast<Address>(mem);
52
  Address high = low + mem_size;
53
  MarkingStack s;
54
  s.Initialize(low, high);
55

    
56
  Address address = NULL;
57
  while (!s.is_full()) {
58
    s.Push(HeapObject::FromAddress(address));
59
    address += kPointerSize;
60
  }
61

    
62
  while (!s.is_empty()) {
63
    Address value = s.Pop()->address();
64
    address -= kPointerSize;
65
    CHECK_EQ(address, value);
66
  }
67

    
68
  CHECK_EQ(NULL, address);
69
  DeleteArray(mem);
70
}
71

    
72

    
73
TEST(Promotion) {
74
  // Test the situation that some objects in new space are promoted to the
75
  // old space
76
  if (Snapshot::IsEnabled()) return;
77

    
78
  // Ensure that we get a compacting collection so that objects are promoted
79
  // from new space.
80
  FLAG_gc_global = true;
81
  FLAG_always_compact = true;
82
  Heap::ConfigureHeap(2*256*KB, 4*MB);
83

    
84
  InitializeVM();
85

    
86
  v8::HandleScope sc;
87

    
88
  // Allocate a fixed array in the new space.
89
  int array_size =
90
      (Heap::MaxHeapObjectSize() - Array::kHeaderSize) / (kPointerSize * 4);
91
  Object* obj = Heap::AllocateFixedArray(array_size);
92
  CHECK(!obj->IsFailure());
93

    
94
  Handle<FixedArray> array(FixedArray::cast(obj));
95

    
96
  // Array should be in the new space.
97
  CHECK(Heap::InSpace(*array, NEW_SPACE));
98

    
99
  // Call the m-c collector, so array becomes an old object.
100
  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
101

    
102
  // Array now sits in the old space
103
  CHECK(Heap::InSpace(*array, OLD_POINTER_SPACE));
104
}
105

    
106

    
107
TEST(NoPromotion) {
108
  if (Snapshot::IsEnabled()) return;
109
  Heap::ConfigureHeap(2*256*KB, 4*MB);
110

    
111
  // Test the situation that some objects in new space are promoted to
112
  // the old space
113
  InitializeVM();
114

    
115
  v8::HandleScope sc;
116

    
117
  // Do a mark compact GC to shrink the heap.
118
  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
119

    
120
  // Allocate a big Fixed array in the new space.
121
  int size = (Heap::MaxHeapObjectSize() - Array::kHeaderSize) / kPointerSize;
122
  Object* obj = Heap::AllocateFixedArray(size);
123

    
124
  Handle<FixedArray> array(FixedArray::cast(obj));
125

    
126
  // Array still stays in the new space.
127
  CHECK(Heap::InSpace(*array, NEW_SPACE));
128

    
129
  // Allocate objects in the old space until out of memory.
130
  FixedArray* host = *array;
131
  while (true) {
132
    Object* obj = Heap::AllocateFixedArray(100, TENURED);
133
    if (obj->IsFailure()) break;
134

    
135
    host->set(0, obj);
136
    host = FixedArray::cast(obj);
137
  }
138

    
139
  // Call mark compact GC, and it should pass.
140
  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
141

    
142
  // array should not be promoted because the old space is full.
143
  CHECK(Heap::InSpace(*array, NEW_SPACE));
144
}
145

    
146

    
147
TEST(MarkCompactCollector) {
148
  InitializeVM();
149

    
150
  v8::HandleScope sc;
151
  // call mark-compact when heap is empty
152
  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
153

    
154
  // keep allocating garbage in new space until it fails
155
  const int ARRAY_SIZE = 100;
156
  Object* array;
157
  do {
158
    array = Heap::AllocateFixedArray(ARRAY_SIZE);
159
  } while (!array->IsFailure());
160
  CHECK(Heap::CollectGarbage(0, NEW_SPACE));
161

    
162
  array = Heap::AllocateFixedArray(ARRAY_SIZE);
163
  CHECK(!array->IsFailure());
164

    
165
  // keep allocating maps until it fails
166
  Object* mapp;
167
  do {
168
    mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
169
  } while (!mapp->IsFailure());
170
  CHECK(Heap::CollectGarbage(0, MAP_SPACE));
171
  mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
172
  CHECK(!mapp->IsFailure());
173

    
174
  // allocate a garbage
175
  String* func_name = String::cast(Heap::LookupAsciiSymbol("theFunction"));
176
  SharedFunctionInfo* function_share =
177
    SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(func_name));
178
  JSFunction* function =
179
    JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
180
                                            function_share,
181
                                            Heap::undefined_value()));
182
  Map* initial_map =
183
      Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
184
  function->set_initial_map(initial_map);
185
  Top::context()->global()->SetProperty(func_name, function, NONE);
186

    
187
  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));
188
  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
189

    
190
  func_name = String::cast(Heap::LookupAsciiSymbol("theFunction"));
191
  CHECK(Top::context()->global()->HasLocalProperty(func_name));
192
  Object* func_value = Top::context()->global()->GetProperty(func_name);
193
  CHECK(func_value->IsJSFunction());
194
  function = JSFunction::cast(func_value);
195

    
196
  obj = JSObject::cast(Heap::AllocateJSObject(function));
197
  String* obj_name = String::cast(Heap::LookupAsciiSymbol("theObject"));
198
  Top::context()->global()->SetProperty(obj_name, obj, NONE);
199
  String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
200
  obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
201

    
202
  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
203

    
204
  obj_name = String::cast(Heap::LookupAsciiSymbol("theObject"));
205
  CHECK(Top::context()->global()->HasLocalProperty(obj_name));
206
  CHECK(Top::context()->global()->GetProperty(obj_name)->IsJSObject());
207
  obj = JSObject::cast(Top::context()->global()->GetProperty(obj_name));
208
  prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
209
  CHECK(obj->GetProperty(prop_name) == Smi::FromInt(23));
210
}
211

    
212

    
213
static int gc_starts = 0;
214
static int gc_ends = 0;
215

    
216
static void GCPrologueCallbackFunc() {
217
  CHECK(gc_starts == gc_ends);
218
  gc_starts++;
219
}
220

    
221

    
222
static void GCEpilogueCallbackFunc() {
223
  CHECK(gc_starts == gc_ends + 1);
224
  gc_ends++;
225
}
226

    
227

    
228
TEST(GCCallback) {
229
  InitializeVM();
230

    
231
  Heap::SetGlobalGCPrologueCallback(&GCPrologueCallbackFunc);
232
  Heap::SetGlobalGCEpilogueCallback(&GCEpilogueCallbackFunc);
233

    
234
  // Scavenge does not call GC callback functions.
235
  Heap::PerformScavenge();
236

    
237
  CHECK_EQ(0, gc_starts);
238
  CHECK_EQ(gc_ends, gc_starts);
239

    
240
  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
241
  CHECK_EQ(1, gc_starts);
242
  CHECK_EQ(gc_ends, gc_starts);
243
}
244

    
245

    
246
static int NumberOfWeakCalls = 0;
247
static void WeakPointerCallback(v8::Persistent<v8::Value> handle, void* id) {
248
  NumberOfWeakCalls++;
249
}
250

    
251
TEST(ObjectGroups) {
252
  InitializeVM();
253

    
254
  NumberOfWeakCalls = 0;
255
  v8::HandleScope handle_scope;
256

    
257
  Handle<Object> g1s1 =
258
    GlobalHandles::Create(Heap::AllocateFixedArray(1));
259
  Handle<Object> g1s2 =
260
    GlobalHandles::Create(Heap::AllocateFixedArray(1));
261
  GlobalHandles::MakeWeak(g1s1.location(),
262
                          reinterpret_cast<void*>(1234),
263
                          &WeakPointerCallback);
264
  GlobalHandles::MakeWeak(g1s2.location(),
265
                          reinterpret_cast<void*>(1234),
266
                          &WeakPointerCallback);
267

    
268
  Handle<Object> g2s1 =
269
    GlobalHandles::Create(Heap::AllocateFixedArray(1));
270
  Handle<Object> g2s2 =
271
    GlobalHandles::Create(Heap::AllocateFixedArray(1));
272
  GlobalHandles::MakeWeak(g2s1.location(),
273
                          reinterpret_cast<void*>(1234),
274
                          &WeakPointerCallback);
275
  GlobalHandles::MakeWeak(g2s2.location(),
276
                          reinterpret_cast<void*>(1234),
277
                          &WeakPointerCallback);
278

    
279
  Handle<Object> root = GlobalHandles::Create(*g1s1);  // make a root.
280

    
281
  // Connect group 1 and 2, make a cycle.
282
  Handle<FixedArray>::cast(g1s2)->set(0, *g2s2);
283
  Handle<FixedArray>::cast(g2s1)->set(0, *g1s1);
284

    
285
  {
286
    Object** g1_objects[] = { g1s1.location(), g1s2.location() };
287
    Object** g2_objects[] = { g2s1.location(), g2s2.location() };
288
    GlobalHandles::AddGroup(g1_objects, 2);
289
    GlobalHandles::AddGroup(g2_objects, 2);
290
  }
291
  // Do a full GC
292
  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
293

    
294
  // All object should be alive.
295
  CHECK_EQ(0, NumberOfWeakCalls);
296

    
297
  // Weaken the root.
298
  GlobalHandles::MakeWeak(root.location(),
299
                          reinterpret_cast<void*>(1234),
300
                          &WeakPointerCallback);
301

    
302
  // Groups are deleted, rebuild groups.
303
  {
304
    Object** g1_objects[] = { g1s1.location(), g1s2.location() };
305
    Object** g2_objects[] = { g2s1.location(), g2s2.location() };
306
    GlobalHandles::AddGroup(g1_objects, 2);
307
    GlobalHandles::AddGroup(g2_objects, 2);
308
  }
309

    
310
  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
311

    
312
  // All objects should be gone. 5 global handles in total.
313
  CHECK_EQ(5, NumberOfWeakCalls);
314
}