test-mark-compact.cc revision a7e24c173cf37484693b9abb38e494fa7bd7baeb
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdlib.h> 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "global-handles.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "snapshot.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "top.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "cctest.h" 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing namespace v8::internal; 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic v8::Persistent<v8::Context> env; 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void InitializeVM() { 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (env.IsEmpty()) env = v8::Context::New(); 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block env->Enter(); 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MarkingStack) { 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mem_size = 20 * kPointerSize; 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* mem = NewArray<byte>(20*kPointerSize); 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address low = reinterpret_cast<Address>(mem); 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address high = low + mem_size; 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkingStack s; 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block s.Initialize(low, high); 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address address = NULL; 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (!s.is_full()) { 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block s.Push(HeapObject::FromAddress(address)); 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block address += kPointerSize; 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (!s.is_empty()) { 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address value = s.Pop()->address(); 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block address -= kPointerSize; 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(address, value); 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(NULL, address); 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DeleteArray(mem); 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(Promotion) { 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Test the situation that some objects in new space are promoted to the 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // old space 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (Snapshot::IsEnabled()) return; 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Ensure that we get a compacting collection so that objects are promoted 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // from new space. 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FLAG_gc_global = true; 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FLAG_always_compact = true; 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::ConfigureHeap(2*256*KB, 4*MB); 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InitializeVM(); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope sc; 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate a fixed array in the new space. 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int array_size = 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (Heap::MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (kPointerSize * 4); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* obj = Heap::AllocateFixedArray(array_size); 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(!obj->IsFailure()); 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray> array(FixedArray::cast(obj)); 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Array should be in the new space. 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::InSpace(*array, NEW_SPACE)); 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the m-c collector, so array becomes an old object. 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Array now sits in the old space 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::InSpace(*array, OLD_POINTER_SPACE)); 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(NoPromotion) { 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (Snapshot::IsEnabled()) return; 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::ConfigureHeap(2*256*KB, 4*MB); 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Test the situation that some objects in new space are promoted to 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the old space 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InitializeVM(); 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope sc; 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do a mark compact GC to shrink the heap. 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate a big Fixed array in the new space. 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size = (Heap::MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block kPointerSize; 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* obj = Heap::AllocateFixedArray(size); 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray> array(FixedArray::cast(obj)); 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Array still stays in the new space. 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::InSpace(*array, NEW_SPACE)); 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate objects in the old space until out of memory. 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FixedArray* host = *array; 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* obj = Heap::AllocateFixedArray(100, TENURED); 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (obj->IsFailure()) break; 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block host->set(0, obj); 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block host = FixedArray::cast(obj); 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call mark compact GC, and it should pass. 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array should not be promoted because the old space is full. 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::InSpace(*array, NEW_SPACE)); 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MarkCompactCollector) { 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InitializeVM(); 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope sc; 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // call mark-compact when heap is empty 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // keep allocating garbage in new space until it fails 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int ARRAY_SIZE = 100; 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* array; 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block do { 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block array = Heap::AllocateFixedArray(ARRAY_SIZE); 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } while (!array->IsFailure()); 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::CollectGarbage(0, NEW_SPACE)); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block array = Heap::AllocateFixedArray(ARRAY_SIZE); 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(!array->IsFailure()); 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // keep allocating maps until it fails 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* mapp; 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block do { 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } while (!mapp->IsFailure()); 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::CollectGarbage(0, MAP_SPACE)); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(!mapp->IsFailure()); 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // allocate a garbage 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* func_name = String::cast(Heap::LookupAsciiSymbol("theFunction")); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SharedFunctionInfo* function_share = 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(func_name)); 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSFunction* function = 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSFunction::cast(Heap::AllocateFunction(*Top::function_map(), 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block function_share, 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::undefined_value())); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* initial_map = 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize)); 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block function->set_initial_map(initial_map); 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Top::context()->global()->SetProperty(func_name, function, NONE); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function)); 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block func_name = String::cast(Heap::LookupAsciiSymbol("theFunction")); 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Top::context()->global()->HasLocalProperty(func_name)); 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* func_value = Top::context()->global()->GetProperty(func_name); 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(func_value->IsJSFunction()); 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block function = JSFunction::cast(func_value); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block obj = JSObject::cast(Heap::AllocateJSObject(function)); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* obj_name = String::cast(Heap::LookupAsciiSymbol("theObject")); 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Top::context()->global()->SetProperty(obj_name, obj, NONE); 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot")); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block obj->SetProperty(prop_name, Smi::FromInt(23), NONE); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block obj_name = String::cast(Heap::LookupAsciiSymbol("theObject")); 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Top::context()->global()->HasLocalProperty(obj_name)); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Top::context()->global()->GetProperty(obj_name)->IsJSObject()); 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block obj = JSObject::cast(Top::context()->global()->GetProperty(obj_name)); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot")); 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(obj->GetProperty(prop_name) == Smi::FromInt(23)); 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int gc_starts = 0; 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int gc_ends = 0; 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GCPrologueCallbackFunc() { 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(gc_starts == gc_ends); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block gc_starts++; 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GCEpilogueCallbackFunc() { 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(gc_starts == gc_ends + 1); 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block gc_ends++; 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(GCCallback) { 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InitializeVM(); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::SetGlobalGCPrologueCallback(&GCPrologueCallbackFunc); 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::SetGlobalGCEpilogueCallback(&GCEpilogueCallbackFunc); 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Scavenge does not call GC callback functions. 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::PerformScavenge(); 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(0, gc_starts); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(gc_ends, gc_starts); 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(1, gc_starts); 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(gc_ends, gc_starts); 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int NumberOfWeakCalls = 0; 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void WeakPointerCallback(v8::Persistent<v8::Value> handle, void* id) { 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NumberOfWeakCalls++; 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ObjectGroups) { 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InitializeVM(); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NumberOfWeakCalls = 0; 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope handle_scope; 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> g1s1 = 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::Create(Heap::AllocateFixedArray(1)); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> g1s2 = 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::Create(Heap::AllocateFixedArray(1)); 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::MakeWeak(g1s1.location(), 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<void*>(1234), 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &WeakPointerCallback); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::MakeWeak(g1s2.location(), 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<void*>(1234), 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &WeakPointerCallback); 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> g2s1 = 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::Create(Heap::AllocateFixedArray(1)); 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> g2s2 = 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::Create(Heap::AllocateFixedArray(1)); 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::MakeWeak(g2s1.location(), 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<void*>(1234), 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &WeakPointerCallback); 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::MakeWeak(g2s2.location(), 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<void*>(1234), 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &WeakPointerCallback); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> root = GlobalHandles::Create(*g1s1); // make a root. 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Connect group 1 and 2, make a cycle. 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray>::cast(g1s2)->set(0, *g2s2); 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray>::cast(g2s1)->set(0, *g1s1); 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object** g1_objects[] = { g1s1.location(), g1s2.location() }; 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object** g2_objects[] = { g2s1.location(), g2s2.location() }; 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::AddGroup(g1_objects, 2); 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::AddGroup(g2_objects, 2); 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do a full GC 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All object should be alive. 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(0, NumberOfWeakCalls); 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Weaken the root. 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::MakeWeak(root.location(), 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<void*>(1234), 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &WeakPointerCallback); 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Groups are deleted, rebuild groups. 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object** g1_objects[] = { g1s1.location(), g1s2.location() }; 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object** g2_objects[] = { g2s1.location(), g2s2.location() }; 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::AddGroup(g1_objects, 2); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::AddGroup(g2_objects, 2); 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All objects should be gone. 5 global handles in total. 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(5, NumberOfWeakCalls); 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 317