blob: 2cb4646d5a8209a06d5116b61b5e10d18f35ce31 [file] [log] [blame]
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +00001// Copyright 2012 the V8 project authors. All rights reserved.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002// 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
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +000030#ifdef __linux__
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
35#include <errno.h>
36#endif
37
ulan@chromium.org57ff8812013-05-10 08:16:55 +000038
39// TODO(dcarney): remove
40#define V8_ALLOW_ACCESS_TO_PERSISTENT_ARROW
41#define V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT
42
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000043#include "v8.h"
44
45#include "global-handles.h"
46#include "snapshot.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000047#include "cctest.h"
48
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000049using namespace v8::internal;
50
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000051
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000052TEST(MarkingDeque) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000053 CcTest::InitializeVM();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000054 int mem_size = 20 * kPointerSize;
55 byte* mem = NewArray<byte>(20*kPointerSize);
56 Address low = reinterpret_cast<Address>(mem);
57 Address high = low + mem_size;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000058 MarkingDeque s;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000059 s.Initialize(low, high);
60
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000061 Address original_address = reinterpret_cast<Address>(&s);
62 Address current_address = original_address;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000063 while (!s.IsFull()) {
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000064 s.PushBlack(HeapObject::FromAddress(current_address));
65 current_address += kPointerSize;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000066 }
67
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000068 while (!s.IsEmpty()) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000069 Address value = s.Pop()->address();
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000070 current_address -= kPointerSize;
71 CHECK_EQ(current_address, value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000072 }
73
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000074 CHECK_EQ(original_address, current_address);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000075 DeleteArray(mem);
76}
77
78
79TEST(Promotion) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +000080 // This test requires compaction. If compaction is turned off, we
81 // skip the entire test.
82 if (FLAG_never_compact) return;
83
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000084 // Ensure that we get a compacting collection so that objects are promoted
85 // from new space.
86 FLAG_gc_global = true;
87 FLAG_always_compact = true;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000088 HEAP->ConfigureHeap(2*256*KB, 8*MB, 8*MB);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000089
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000090 CcTest::InitializeVM();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000091
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000092 v8::HandleScope sc(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000093
94 // Allocate a fixed array in the new space.
kasperl@chromium.orge959c182009-07-27 08:59:04 +000095 int array_size =
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000096 (Page::kMaxNonCodeHeapObjectSize - FixedArray::kHeaderSize) /
ager@chromium.org5aa501c2009-06-23 07:57:28 +000097 (kPointerSize * 4);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000098 Object* obj = HEAP->AllocateFixedArray(array_size)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000099
100 Handle<FixedArray> array(FixedArray::cast(obj));
101
102 // Array should be in the new space.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000103 CHECK(HEAP->InSpace(*array, NEW_SPACE));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000104
105 // Call the m-c collector, so array becomes an old object.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000106 HEAP->CollectGarbage(OLD_POINTER_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000107
108 // Array now sits in the old space
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000109 CHECK(HEAP->InSpace(*array, OLD_POINTER_SPACE));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000110}
111
112
113TEST(NoPromotion) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000114 HEAP->ConfigureHeap(2*256*KB, 8*MB, 8*MB);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000115
116 // Test the situation that some objects in new space are promoted to
117 // the old space
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000118 CcTest::InitializeVM();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000119
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000120 v8::HandleScope sc(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000121
122 // Do a mark compact GC to shrink the heap.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000123 HEAP->CollectGarbage(OLD_POINTER_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000124
125 // Allocate a big Fixed array in the new space.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000126 int max_size =
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000127 Min(Page::kMaxNonCodeHeapObjectSize, HEAP->MaxObjectSizeInNewSpace());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000128
129 int length = (max_size - FixedArray::kHeaderSize) / (2*kPointerSize);
130 Object* obj = i::Isolate::Current()->heap()->AllocateFixedArray(length)->
131 ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000132
133 Handle<FixedArray> array(FixedArray::cast(obj));
134
135 // Array still stays in the new space.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000136 CHECK(HEAP->InSpace(*array, NEW_SPACE));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000137
138 // Allocate objects in the old space until out of memory.
139 FixedArray* host = *array;
140 while (true) {
lrn@chromium.org303ada72010-10-27 09:33:13 +0000141 Object* obj;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000142 { MaybeObject* maybe_obj = HEAP->AllocateFixedArray(100, TENURED);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000143 if (!maybe_obj->ToObject(&obj)) break;
144 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000145
146 host->set(0, obj);
147 host = FixedArray::cast(obj);
148 }
149
150 // Call mark compact GC, and it should pass.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000151 HEAP->CollectGarbage(OLD_POINTER_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000152}
153
154
155TEST(MarkCompactCollector) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000156 CcTest::InitializeVM();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000157
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000158 v8::HandleScope sc(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000159 // call mark-compact when heap is empty
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000160 HEAP->CollectGarbage(OLD_POINTER_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000161
162 // keep allocating garbage in new space until it fails
163 const int ARRAY_SIZE = 100;
164 Object* array;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000165 MaybeObject* maybe_array;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000166 do {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000167 maybe_array = HEAP->AllocateFixedArray(ARRAY_SIZE);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000168 } while (maybe_array->ToObject(&array));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000169 HEAP->CollectGarbage(NEW_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000170
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000171 array = HEAP->AllocateFixedArray(ARRAY_SIZE)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000172
173 // keep allocating maps until it fails
174 Object* mapp;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000175 MaybeObject* maybe_mapp;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000176 do {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000177 maybe_mapp = HEAP->AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000178 } while (maybe_mapp->ToObject(&mapp));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000179 HEAP->CollectGarbage(MAP_SPACE);
180 mapp = HEAP->AllocateMap(JS_OBJECT_TYPE,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000181 JSObject::kHeaderSize)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000182
183 // allocate a garbage
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000184 String* func_name = String::cast(
185 HEAP->InternalizeUtf8String("theFunction")->ToObjectChecked());
lrn@chromium.org303ada72010-10-27 09:33:13 +0000186 SharedFunctionInfo* function_share = SharedFunctionInfo::cast(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000187 HEAP->AllocateSharedFunctionInfo(func_name)->ToObjectChecked());
lrn@chromium.org303ada72010-10-27 09:33:13 +0000188 JSFunction* function = JSFunction::cast(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000189 HEAP->AllocateFunction(*Isolate::Current()->function_map(),
lrn@chromium.org303ada72010-10-27 09:33:13 +0000190 function_share,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000191 HEAP->undefined_value())->ToObjectChecked());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000192 Map* initial_map =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000193 Map::cast(HEAP->AllocateMap(JS_OBJECT_TYPE,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000194 JSObject::kHeaderSize)->ToObjectChecked());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000195 function->set_initial_map(initial_map);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000196 Isolate::Current()->context()->global_object()->SetProperty(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000197 func_name, function, NONE, kNonStrictMode)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000198
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000199 JSObject* obj = JSObject::cast(
200 HEAP->AllocateJSObject(function)->ToObjectChecked());
201 HEAP->CollectGarbage(OLD_POINTER_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000202
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000203 func_name = String::cast(
204 HEAP->InternalizeUtf8String("theFunction")->ToObjectChecked());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000205 CHECK(Isolate::Current()->context()->global_object()->
206 HasLocalProperty(func_name));
207 Object* func_value = Isolate::Current()->context()->global_object()->
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000208 GetProperty(func_name)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000209 CHECK(func_value->IsJSFunction());
210 function = JSFunction::cast(func_value);
211
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000212 obj = JSObject::cast(HEAP->AllocateJSObject(function)->ToObjectChecked());
lrn@chromium.org303ada72010-10-27 09:33:13 +0000213 String* obj_name =
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000214 String::cast(HEAP->InternalizeUtf8String("theObject")->ToObjectChecked());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000215 Isolate::Current()->context()->global_object()->SetProperty(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000216 obj_name, obj, NONE, kNonStrictMode)->ToObjectChecked();
lrn@chromium.org303ada72010-10-27 09:33:13 +0000217 String* prop_name =
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000218 String::cast(HEAP->InternalizeUtf8String("theSlot")->ToObjectChecked());
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000219 obj->SetProperty(prop_name,
220 Smi::FromInt(23),
221 NONE,
222 kNonStrictMode)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000223
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000224 HEAP->CollectGarbage(OLD_POINTER_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000225
lrn@chromium.org303ada72010-10-27 09:33:13 +0000226 obj_name =
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000227 String::cast(HEAP->InternalizeUtf8String("theObject")->ToObjectChecked());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000228 CHECK(Isolate::Current()->context()->global_object()->
229 HasLocalProperty(obj_name));
230 CHECK(Isolate::Current()->context()->global_object()->
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000231 GetProperty(obj_name)->ToObjectChecked()->IsJSObject());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000232 obj = JSObject::cast(Isolate::Current()->context()->global_object()->
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000233 GetProperty(obj_name)->ToObjectChecked());
lrn@chromium.org303ada72010-10-27 09:33:13 +0000234 prop_name =
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000235 String::cast(HEAP->InternalizeUtf8String("theSlot")->ToObjectChecked());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000236 CHECK(obj->GetProperty(prop_name) == Smi::FromInt(23));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000237}
238
239
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000240// TODO(1600): compaction of map space is temporary removed from GC.
241#if 0
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000242static Handle<Map> CreateMap() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000243 return FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000244}
245
246
247TEST(MapCompact) {
248 FLAG_max_map_space_pages = 16;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000249 CcTest::InitializeVM();
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000250
251 {
252 v8::HandleScope sc;
253 // keep allocating maps while pointers are still encodable and thus
254 // mark compact is permitted.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000255 Handle<JSObject> root = FACTORY->NewJSObjectFromMap(CreateMap());
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000256 do {
257 Handle<Map> map = CreateMap();
258 map->set_prototype(*root);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000259 root = FACTORY->NewJSObjectFromMap(map);
260 } while (HEAP->map_space()->MapPointersEncodable());
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000261 }
262 // Now, as we don't have any handles to just allocated maps, we should
263 // be able to trigger map compaction.
264 // To give an additional chance to fail, try to force compaction which
265 // should be impossible right now.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000266 HEAP->CollectAllGarbage(Heap::kForceCompactionMask);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000267 // And now map pointers should be encodable again.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000268 CHECK(HEAP->map_space()->MapPointersEncodable());
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000269}
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000270#endif
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000271
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000272static int gc_starts = 0;
273static int gc_ends = 0;
274
275static void GCPrologueCallbackFunc() {
276 CHECK(gc_starts == gc_ends);
277 gc_starts++;
278}
279
280
281static void GCEpilogueCallbackFunc() {
282 CHECK(gc_starts == gc_ends + 1);
283 gc_ends++;
284}
285
286
287TEST(GCCallback) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000288 CcTest::InitializeVM();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000289
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000290 HEAP->SetGlobalGCPrologueCallback(&GCPrologueCallbackFunc);
291 HEAP->SetGlobalGCEpilogueCallback(&GCEpilogueCallbackFunc);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000292
293 // Scavenge does not call GC callback functions.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000294 HEAP->PerformScavenge();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000295
296 CHECK_EQ(0, gc_starts);
297 CHECK_EQ(gc_ends, gc_starts);
298
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000299 HEAP->CollectGarbage(OLD_POINTER_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000300 CHECK_EQ(1, gc_starts);
301 CHECK_EQ(gc_ends, gc_starts);
302}
303
304
305static int NumberOfWeakCalls = 0;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000306static void WeakPointerCallback(v8::Isolate* isolate,
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000307 v8::Persistent<v8::Value>* handle,
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000308 void* id) {
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000309 ASSERT(id == reinterpret_cast<void*>(1234));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000310 NumberOfWeakCalls++;
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000311 handle->Dispose(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000312}
313
314TEST(ObjectGroups) {
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000315 FLAG_incremental_marking = false;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000316 CcTest::InitializeVM();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000317 GlobalHandles* global_handles = Isolate::Current()->global_handles();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000318
319 NumberOfWeakCalls = 0;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000320 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000321
322 Handle<Object> g1s1 =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000323 global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000324 Handle<Object> g1s2 =
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000325 global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000326 Handle<Object> g1c1 =
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000327 global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000328 global_handles->MakeWeak(g1s1.location(),
329 reinterpret_cast<void*>(1234),
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000330 &WeakPointerCallback,
331 NULL);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000332 global_handles->MakeWeak(g1s2.location(),
333 reinterpret_cast<void*>(1234),
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000334 &WeakPointerCallback,
335 NULL);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000336 global_handles->MakeWeak(g1c1.location(),
337 reinterpret_cast<void*>(1234),
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000338 &WeakPointerCallback,
339 NULL);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000340
341 Handle<Object> g2s1 =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000342 global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000343 Handle<Object> g2s2 =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000344 global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000345 Handle<Object> g2c1 =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000346 global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
347 global_handles->MakeWeak(g2s1.location(),
348 reinterpret_cast<void*>(1234),
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000349 &WeakPointerCallback,
350 NULL);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000351 global_handles->MakeWeak(g2s2.location(),
352 reinterpret_cast<void*>(1234),
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000353 &WeakPointerCallback,
354 NULL);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000355 global_handles->MakeWeak(g2c1.location(),
356 reinterpret_cast<void*>(1234),
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000357 &WeakPointerCallback,
358 NULL);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000359
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000360 Handle<Object> root = global_handles->Create(*g1s1); // make a root.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000361
362 // Connect group 1 and 2, make a cycle.
363 Handle<FixedArray>::cast(g1s2)->set(0, *g2s2);
364 Handle<FixedArray>::cast(g2s1)->set(0, *g1s1);
365
ager@chromium.org8bb60582008-12-11 12:02:20 +0000366 {
367 Object** g1_objects[] = { g1s1.location(), g1s2.location() };
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000368 Object** g1_children[] = { g1c1.location() };
ager@chromium.org8bb60582008-12-11 12:02:20 +0000369 Object** g2_objects[] = { g2s1.location(), g2s2.location() };
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000370 Object** g2_children[] = { g2c1.location() };
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000371 global_handles->AddObjectGroup(g1_objects, 2, NULL);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000372 global_handles->AddImplicitReferences(
373 Handle<HeapObject>::cast(g1s1).location(), g1_children, 1);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000374 global_handles->AddObjectGroup(g2_objects, 2, NULL);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000375 global_handles->AddImplicitReferences(
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000376 Handle<HeapObject>::cast(g2s1).location(), g2_children, 1);
ager@chromium.org8bb60582008-12-11 12:02:20 +0000377 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000378 // Do a full GC
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000379 HEAP->CollectGarbage(OLD_POINTER_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000380
381 // All object should be alive.
382 CHECK_EQ(0, NumberOfWeakCalls);
383
384 // Weaken the root.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000385 global_handles->MakeWeak(root.location(),
386 reinterpret_cast<void*>(1234),
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000387 &WeakPointerCallback,
388 NULL);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000389 // But make children strong roots---all the objects (except for children)
390 // should be collectable now.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000391 global_handles->ClearWeakness(g1c1.location());
392 global_handles->ClearWeakness(g2c1.location());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000393
394 // Groups are deleted, rebuild groups.
ager@chromium.org8bb60582008-12-11 12:02:20 +0000395 {
396 Object** g1_objects[] = { g1s1.location(), g1s2.location() };
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000397 Object** g1_children[] = { g1c1.location() };
ager@chromium.org8bb60582008-12-11 12:02:20 +0000398 Object** g2_objects[] = { g2s1.location(), g2s2.location() };
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000399 Object** g2_children[] = { g2c1.location() };
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000400 global_handles->AddObjectGroup(g1_objects, 2, NULL);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000401 global_handles->AddImplicitReferences(
402 Handle<HeapObject>::cast(g1s1).location(), g1_children, 1);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000403 global_handles->AddObjectGroup(g2_objects, 2, NULL);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000404 global_handles->AddImplicitReferences(
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000405 Handle<HeapObject>::cast(g2s1).location(), g2_children, 1);
ager@chromium.org8bb60582008-12-11 12:02:20 +0000406 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000407
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000408 HEAP->CollectGarbage(OLD_POINTER_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000409
410 // All objects should be gone. 5 global handles in total.
411 CHECK_EQ(5, NumberOfWeakCalls);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000412
413 // And now make children weak again and collect them.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000414 global_handles->MakeWeak(g1c1.location(),
415 reinterpret_cast<void*>(1234),
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000416 &WeakPointerCallback,
417 NULL);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000418 global_handles->MakeWeak(g2c1.location(),
419 reinterpret_cast<void*>(1234),
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000420 &WeakPointerCallback,
421 NULL);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000422
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000423 HEAP->CollectGarbage(OLD_POINTER_SPACE);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000424 CHECK_EQ(7, NumberOfWeakCalls);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000425}
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000426
427
428class TestRetainedObjectInfo : public v8::RetainedObjectInfo {
429 public:
430 TestRetainedObjectInfo() : has_been_disposed_(false) {}
431
432 bool has_been_disposed() { return has_been_disposed_; }
433
434 virtual void Dispose() {
435 ASSERT(!has_been_disposed_);
436 has_been_disposed_ = true;
437 }
438
439 virtual bool IsEquivalent(v8::RetainedObjectInfo* other) {
440 return other == this;
441 }
442
443 virtual intptr_t GetHash() { return 0; }
444
445 virtual const char* GetLabel() { return "whatever"; }
446
447 private:
448 bool has_been_disposed_;
449};
450
451
452TEST(EmptyObjectGroups) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000453 CcTest::InitializeVM();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000454 GlobalHandles* global_handles = Isolate::Current()->global_handles();
455
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000456 v8::HandleScope handle_scope(CcTest::isolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000457
458 Handle<Object> object =
459 global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
460
461 TestRetainedObjectInfo info;
462 global_handles->AddObjectGroup(NULL, 0, &info);
463 ASSERT(info.has_been_disposed());
464
465 global_handles->AddImplicitReferences(
466 Handle<HeapObject>::cast(object).location(), NULL, 0);
467}
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000468
469
470// Here is a memory use test that uses /proc, and is therefore Linux-only. We
471// do not care how much memory the simulator uses, since it is only there for
472// debugging purposes.
473#if defined(__linux__) && !defined(USE_SIMULATOR)
474
475
476static uintptr_t ReadLong(char* buffer, intptr_t* position, int base) {
477 char* end_address = buffer + *position;
478 uintptr_t result = strtoul(buffer + *position, &end_address, base);
479 CHECK(result != ULONG_MAX || errno != ERANGE);
480 CHECK(end_address > buffer + *position);
481 *position = end_address - buffer;
482 return result;
483}
484
485
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +0000486// The memory use computed this way is not entirely accurate and depends on
487// the way malloc allocates memory. That's why the memory use may seem to
488// increase even though the sum of the allocated object sizes decreases. It
489// also means that the memory use depends on the kernel and stdlib.
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000490static intptr_t MemoryInUse() {
491 intptr_t memory_use = 0;
492
493 int fd = open("/proc/self/maps", O_RDONLY);
494 if (fd < 0) return -1;
495
496 const int kBufSize = 10000;
497 char buffer[kBufSize];
498 int length = read(fd, buffer, kBufSize);
499 intptr_t line_start = 0;
500 CHECK_LT(length, kBufSize); // Make the buffer bigger.
501 CHECK_GT(length, 0); // We have to find some data in the file.
502 while (line_start < length) {
503 if (buffer[line_start] == '\n') {
504 line_start++;
505 continue;
506 }
507 intptr_t position = line_start;
508 uintptr_t start = ReadLong(buffer, &position, 16);
509 CHECK_EQ(buffer[position++], '-');
510 uintptr_t end = ReadLong(buffer, &position, 16);
511 CHECK_EQ(buffer[position++], ' ');
512 CHECK(buffer[position] == '-' || buffer[position] == 'r');
513 bool read_permission = (buffer[position++] == 'r');
514 CHECK(buffer[position] == '-' || buffer[position] == 'w');
515 bool write_permission = (buffer[position++] == 'w');
516 CHECK(buffer[position] == '-' || buffer[position] == 'x');
517 bool execute_permission = (buffer[position++] == 'x');
518 CHECK(buffer[position] == '-' || buffer[position] == 'p');
519 bool private_mapping = (buffer[position++] == 'p');
520 CHECK_EQ(buffer[position++], ' ');
521 uintptr_t offset = ReadLong(buffer, &position, 16);
522 USE(offset);
523 CHECK_EQ(buffer[position++], ' ');
524 uintptr_t major = ReadLong(buffer, &position, 16);
525 USE(major);
526 CHECK_EQ(buffer[position++], ':');
527 uintptr_t minor = ReadLong(buffer, &position, 16);
528 USE(minor);
529 CHECK_EQ(buffer[position++], ' ');
530 uintptr_t inode = ReadLong(buffer, &position, 10);
531 while (position < length && buffer[position] != '\n') position++;
532 if ((read_permission || write_permission || execute_permission) &&
533 private_mapping && inode == 0) {
534 memory_use += (end - start);
535 }
536
537 line_start = position;
538 }
539 close(fd);
540 return memory_use;
541}
542
543
544TEST(BootUpMemoryUse) {
545 intptr_t initial_memory = MemoryInUse();
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000546 // Avoid flakiness.
547 FLAG_crankshaft = false;
548 FLAG_parallel_recompilation = false;
549
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000550 // Only Linux has the proc filesystem and only if it is mapped. If it's not
551 // there we just skip the test.
552 if (initial_memory >= 0) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000553 CcTest::InitializeVM();
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +0000554 intptr_t delta = MemoryInUse() - initial_memory;
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +0000555 printf("delta: %" V8_PTR_PREFIX "d kB\n", delta / 1024);
556 if (sizeof(initial_memory) == 8) { // 64-bit.
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000557 if (v8::internal::Snapshot::IsEnabled()) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000558 CHECK_LE(delta, 4000 * 1024);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000559 } else {
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000560 CHECK_LE(delta, 4500 * 1024);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000561 }
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +0000562 } else { // 32-bit.
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000563 if (v8::internal::Snapshot::IsEnabled()) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000564 CHECK_LE(delta, 2900 * 1024);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000565 } else {
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000566 CHECK_LE(delta, 3400 * 1024);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000567 }
568 }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000569 }
570}
571
572#endif // __linux__ and !USE_SIMULATOR