13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 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
303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef __linux__
313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include <sys/types.h>
323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include <sys/stat.h>
333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include <fcntl.h>
343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include <unistd.h>
353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include <errno.h>
363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "global-handles.h"
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "snapshot.h"
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "cctest.h"
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing namespace v8::internal;
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic v8::Persistent<v8::Context> env;
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void InitializeVM() {
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (env.IsEmpty()) env = v8::Context::New();
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope scope;
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Enter();
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(MarkingDeque) {
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mem_size = 20 * kPointerSize;
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* mem = NewArray<byte>(20*kPointerSize);
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address low = reinterpret_cast<Address>(mem);
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address high = low + mem_size;
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MarkingDeque s;
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  s.Initialize(low, high);
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address address = NULL;
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!s.IsFull()) {
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    s.PushBlack(HeapObject::FromAddress(address));
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    address += kPointerSize;
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!s.IsEmpty()) {
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address value = s.Pop()->address();
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    address -= kPointerSize;
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(address, value);
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NULL, address);
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DeleteArray(mem);
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(Promotion) {
81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // This test requires compaction. If compaction is turned off, we
82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // skip the entire test.
83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_never_compact) return;
84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Ensure that we get a compacting collection so that objects are promoted
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // from new space.
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FLAG_gc_global = true;
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FLAG_always_compact = true;
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->ConfigureHeap(2*256*KB, 8*MB, 8*MB);
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope sc;
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate a fixed array in the new space.
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int array_size =
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (Page::kMaxNonCodeHeapObjectSize - FixedArray::kHeaderSize) /
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      (kPointerSize * 4);
9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* obj = HEAP->AllocateFixedArray(array_size)->ToObjectChecked();
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<FixedArray> array(FixedArray::cast(obj));
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Array should be in the new space.
10444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(HEAP->InSpace(*array, NEW_SPACE));
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call the m-c collector, so array becomes an old object.
10744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(OLD_POINTER_SPACE);
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Array now sits in the old space
11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(HEAP->InSpace(*array, OLD_POINTER_SPACE));
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(NoPromotion) {
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->ConfigureHeap(2*256*KB, 8*MB, 8*MB);
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test the situation that some objects in new space are promoted to
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the old space
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope sc;
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do a mark compact GC to shrink the heap.
12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(OLD_POINTER_SPACE);
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate a big Fixed array in the new space.
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int max_size =
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Min(Page::kMaxNonCodeHeapObjectSize, HEAP->MaxObjectSizeInNewSpace());
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int length = (max_size - FixedArray::kHeaderSize) / (2*kPointerSize);
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Object* obj = i::Isolate::Current()->heap()->AllocateFixedArray(length)->
1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ToObjectChecked();
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<FixedArray> array(FixedArray::cast(obj));
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Array still stays in the new space.
13744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(HEAP->InSpace(*array, NEW_SPACE));
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate objects in the old space until out of memory.
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FixedArray* host = *array;
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
1425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Object* obj;
14344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    { MaybeObject* maybe_obj = HEAP->AllocateFixedArray(100, TENURED);
1445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (!maybe_obj->ToObject(&obj)) break;
1455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    host->set(0, obj);
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    host = FixedArray::cast(obj);
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call mark compact GC, and it should pass.
15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(OLD_POINTER_SPACE);
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MarkCompactCollector) {
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope sc;
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // call mark-compact when heap is empty
16144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(OLD_POINTER_SPACE);
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // keep allocating garbage in new space until it fails
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int ARRAY_SIZE = 100;
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* array;
1665913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MaybeObject* maybe_array;
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  do {
16844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    maybe_array = HEAP->AllocateFixedArray(ARRAY_SIZE);
1695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  } while (maybe_array->ToObject(&array));
17044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(NEW_SPACE);
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  array = HEAP->AllocateFixedArray(ARRAY_SIZE)->ToObjectChecked();
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // keep allocating maps until it fails
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* mapp;
1765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MaybeObject* maybe_mapp;
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  do {
17844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    maybe_mapp = HEAP->AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
1795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  } while (maybe_mapp->ToObject(&mapp));
18044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(MAP_SPACE);
18144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mapp = HEAP->AllocateMap(JS_OBJECT_TYPE,
1825913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                           JSObject::kHeaderSize)->ToObjectChecked();
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // allocate a garbage
1855913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  String* func_name =
18644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      String::cast(HEAP->LookupAsciiSymbol("theFunction")->ToObjectChecked());
1875913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  SharedFunctionInfo* function_share = SharedFunctionInfo::cast(
18844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HEAP->AllocateSharedFunctionInfo(func_name)->ToObjectChecked());
1895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  JSFunction* function = JSFunction::cast(
19044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HEAP->AllocateFunction(*Isolate::Current()->function_map(),
1915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                             function_share,
19244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             HEAP->undefined_value())->ToObjectChecked());
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Map* initial_map =
19444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Map::cast(HEAP->AllocateMap(JS_OBJECT_TYPE,
1955913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                  JSObject::kHeaderSize)->ToObjectChecked());
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  function->set_initial_map(initial_map);
19744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->context()->global()->SetProperty(
19844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      func_name, function, NONE, kNonStrictMode)->ToObjectChecked();
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  JSObject* obj = JSObject::cast(
20144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HEAP->AllocateJSObject(function)->ToObjectChecked());
20244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(OLD_POINTER_SPACE);
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2045913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  func_name =
20544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      String::cast(HEAP->LookupAsciiSymbol("theFunction")->ToObjectChecked());
20644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(Isolate::Current()->context()->global()->HasLocalProperty(func_name));
20744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* func_value = Isolate::Current()->context()->global()->
20844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      GetProperty(func_name)->ToObjectChecked();
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(func_value->IsJSFunction());
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  function = JSFunction::cast(func_value);
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  obj = JSObject::cast(HEAP->AllocateJSObject(function)->ToObjectChecked());
2135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  String* obj_name =
21444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      String::cast(HEAP->LookupAsciiSymbol("theObject")->ToObjectChecked());
21544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->context()->global()->SetProperty(
21644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      obj_name, obj, NONE, kNonStrictMode)->ToObjectChecked();
2175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  String* prop_name =
21844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      String::cast(HEAP->LookupAsciiSymbol("theSlot")->ToObjectChecked());
219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->SetProperty(prop_name,
220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                   Smi::FromInt(23),
221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                   NONE,
222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                   kNonStrictMode)->ToObjectChecked();
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(OLD_POINTER_SPACE);
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  obj_name =
22744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      String::cast(HEAP->LookupAsciiSymbol("theObject")->ToObjectChecked());
22844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(Isolate::Current()->context()->global()->HasLocalProperty(obj_name));
22944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(Isolate::Current()->context()->global()->
23044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        GetProperty(obj_name)->ToObjectChecked()->IsJSObject());
23144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  obj = JSObject::cast(Isolate::Current()->context()->global()->
23244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                       GetProperty(obj_name)->ToObjectChecked());
2335913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  prop_name =
23444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      String::cast(HEAP->LookupAsciiSymbol("theSlot")->ToObjectChecked());
23544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(obj->GetProperty(prop_name) == Smi::FromInt(23));
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// TODO(1600): compaction of map space is temporary removed from GC.
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#if 0
241d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic Handle<Map> CreateMap() {
24244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
243d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
244d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
245d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
246d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeTEST(MapCompact) {
247d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  FLAG_max_map_space_pages = 16;
248d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  InitializeVM();
249d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
250d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  {
251d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    v8::HandleScope sc;
252d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // keep allocating maps while pointers are still encodable and thus
253d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // mark compact is permitted.
25444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<JSObject> root = FACTORY->NewJSObjectFromMap(CreateMap());
255d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    do {
256d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Handle<Map> map = CreateMap();
257d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      map->set_prototype(*root);
25844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      root = FACTORY->NewJSObjectFromMap(map);
25944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } while (HEAP->map_space()->MapPointersEncodable());
260d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
261d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Now, as we don't have any handles to just allocated maps, we should
262d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // be able to trigger map compaction.
263d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // To give an additional chance to fail, try to force compaction which
264d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // should be impossible right now.
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kForceCompactionMask);
266d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // And now map pointers should be encodable again.
26744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(HEAP->map_space()->MapPointersEncodable());
268d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
270d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int gc_starts = 0;
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int gc_ends = 0;
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GCPrologueCallbackFunc() {
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(gc_starts == gc_ends);
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  gc_starts++;
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GCEpilogueCallbackFunc() {
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(gc_starts == gc_ends + 1);
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  gc_ends++;
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(GCCallback) {
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->SetGlobalGCPrologueCallback(&GCPrologueCallbackFunc);
29044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->SetGlobalGCEpilogueCallback(&GCEpilogueCallbackFunc);
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scavenge does not call GC callback functions.
29344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->PerformScavenge();
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, gc_starts);
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(gc_ends, gc_starts);
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(OLD_POINTER_SPACE);
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, gc_starts);
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(gc_ends, gc_starts);
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int NumberOfWeakCalls = 0;
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void WeakPointerCallback(v8::Persistent<v8::Value> handle, void* id) {
30644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(id == reinterpret_cast<void*>(1234));
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NumberOfWeakCalls++;
30850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  handle.Dispose();
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ObjectGroups) {
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
3138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  GlobalHandles* global_handles = Isolate::Current()->global_handles();
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NumberOfWeakCalls = 0;
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope handle_scope;
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> g1s1 =
31944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> g1s2 =
3218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
32244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Object> g1c1 =
3238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
32444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->MakeWeak(g1s1.location(),
32544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           reinterpret_cast<void*>(1234),
32644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           &WeakPointerCallback);
32744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->MakeWeak(g1s2.location(),
32844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           reinterpret_cast<void*>(1234),
32944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           &WeakPointerCallback);
33044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->MakeWeak(g1c1.location(),
33144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           reinterpret_cast<void*>(1234),
33244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           &WeakPointerCallback);
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> g2s1 =
33544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> g2s2 =
33744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
33844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Object> g2c1 =
33944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
34044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->MakeWeak(g2s1.location(),
34144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           reinterpret_cast<void*>(1234),
34244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           &WeakPointerCallback);
34344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->MakeWeak(g2s2.location(),
34444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           reinterpret_cast<void*>(1234),
34544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           &WeakPointerCallback);
34644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->MakeWeak(g2c1.location(),
34744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           reinterpret_cast<void*>(1234),
34844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           &WeakPointerCallback);
34944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
35044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Object> root = global_handles->Create(*g1s1);  // make a root.
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Connect group 1 and 2, make a cycle.
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<FixedArray>::cast(g1s2)->set(0, *g2s2);
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<FixedArray>::cast(g2s1)->set(0, *g1s1);
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Object** g1_objects[] = { g1s1.location(), g1s2.location() };
35844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object** g1_children[] = { g1c1.location() };
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Object** g2_objects[] = { g2s1.location(), g2s2.location() };
36044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object** g2_children[] = { g2c1.location() };
36144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    global_handles->AddObjectGroup(g1_objects, 2, NULL);
3628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    global_handles->AddImplicitReferences(
3638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        Handle<HeapObject>::cast(g1s1).location(), g1_children, 1);
36444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    global_handles->AddObjectGroup(g2_objects, 2, NULL);
3658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    global_handles->AddImplicitReferences(
3668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        Handle<HeapObject>::cast(g2s2).location(), g2_children, 1);
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do a full GC
36944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(OLD_POINTER_SPACE);
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All object should be alive.
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, NumberOfWeakCalls);
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Weaken the root.
37544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->MakeWeak(root.location(),
37644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           reinterpret_cast<void*>(1234),
37744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           &WeakPointerCallback);
37844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // But make children strong roots---all the objects (except for children)
37944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // should be collectable now.
38044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->ClearWeakness(g1c1.location());
38144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->ClearWeakness(g2c1.location());
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Groups are deleted, rebuild groups.
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Object** g1_objects[] = { g1s1.location(), g1s2.location() };
38644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object** g1_children[] = { g1c1.location() };
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Object** g2_objects[] = { g2s1.location(), g2s2.location() };
38844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object** g2_children[] = { g2c1.location() };
38944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    global_handles->AddObjectGroup(g1_objects, 2, NULL);
3908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    global_handles->AddImplicitReferences(
3918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        Handle<HeapObject>::cast(g1s1).location(), g1_children, 1);
39244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    global_handles->AddObjectGroup(g2_objects, 2, NULL);
3938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    global_handles->AddImplicitReferences(
3948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        Handle<HeapObject>::cast(g2s2).location(), g2_children, 1);
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(OLD_POINTER_SPACE);
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All objects should be gone. 5 global handles in total.
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5, NumberOfWeakCalls);
40144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
40244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // And now make children weak again and collect them.
40344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->MakeWeak(g1c1.location(),
40444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           reinterpret_cast<void*>(1234),
40544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           &WeakPointerCallback);
40644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->MakeWeak(g2c1.location(),
40744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           reinterpret_cast<void*>(1234),
40844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           &WeakPointerCallback);
40944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
41044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(OLD_POINTER_SPACE);
41144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(7, NumberOfWeakCalls);
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass TestRetainedObjectInfo : public v8::RetainedObjectInfo {
4168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch public:
4178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  TestRetainedObjectInfo() : has_been_disposed_(false) {}
4188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  bool has_been_disposed() { return has_been_disposed_; }
4208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  virtual void Dispose() {
4228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(!has_been_disposed_);
4238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    has_been_disposed_ = true;
4248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
4258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  virtual bool IsEquivalent(v8::RetainedObjectInfo* other) {
4278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return other == this;
4288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
4298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  virtual intptr_t GetHash() { return 0; }
4318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  virtual const char* GetLabel() { return "whatever"; }
4338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private:
4358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  bool has_been_disposed_;
4368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch};
4378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4398b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochTEST(EmptyObjectGroups) {
4408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  InitializeVM();
4418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  GlobalHandles* global_handles = Isolate::Current()->global_handles();
4428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  v8::HandleScope handle_scope;
4448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<Object> object =
4468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
4478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  TestRetainedObjectInfo info;
4498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  global_handles->AddObjectGroup(NULL, 0, &info);
4508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(info.has_been_disposed());
4518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  global_handles->AddImplicitReferences(
4538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        Handle<HeapObject>::cast(object).location(), NULL, 0);
4548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Here is a memory use test that uses /proc, and is therefore Linux-only.  We
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// do not care how much memory the simulator uses, since it is only there for
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// debugging purposes.
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#if defined(__linux__) && !defined(USE_SIMULATOR)
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic uintptr_t ReadLong(char* buffer, intptr_t* position, int base) {
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  char* end_address = buffer + *position;
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uintptr_t result = strtoul(buffer + *position, &end_address, base);
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(result != ULONG_MAX || errno != ERANGE);
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(end_address > buffer + *position);
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *position = end_address - buffer;
4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return result;
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic intptr_t MemoryInUse() {
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t memory_use = 0;
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int fd = open("/proc/self/maps", O_RDONLY);
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (fd < 0) return -1;
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int kBufSize = 10000;
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  char buffer[kBufSize];
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int length = read(fd, buffer, kBufSize);
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t line_start = 0;
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_LT(length, kBufSize);  // Make the buffer bigger.
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_GT(length, 0);  // We have to find some data in the file.
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (line_start < length) {
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (buffer[line_start] == '\n') {
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      line_start++;
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      continue;
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    intptr_t position = line_start;
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uintptr_t start = ReadLong(buffer, &position, 16);
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(buffer[position++], '-');
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uintptr_t end = ReadLong(buffer, &position, 16);
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(buffer[position++], ' ');
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK(buffer[position] == '-' || buffer[position] == 'r');
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool read_permission = (buffer[position++] == 'r');
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK(buffer[position] == '-' || buffer[position] == 'w');
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool write_permission = (buffer[position++] == 'w');
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK(buffer[position] == '-' || buffer[position] == 'x');
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool execute_permission = (buffer[position++] == 'x');
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK(buffer[position] == '-' || buffer[position] == 'p');
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool private_mapping = (buffer[position++] == 'p');
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(buffer[position++], ' ');
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uintptr_t offset = ReadLong(buffer, &position, 16);
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    USE(offset);
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(buffer[position++], ' ');
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uintptr_t major = ReadLong(buffer, &position, 16);
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    USE(major);
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(buffer[position++], ':');
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uintptr_t minor = ReadLong(buffer, &position, 16);
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    USE(minor);
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(buffer[position++], ' ');
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uintptr_t inode = ReadLong(buffer, &position, 10);
5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    while (position < length && buffer[position] != '\n') position++;
5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if ((read_permission || write_permission || execute_permission) &&
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        private_mapping && inode == 0) {
5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      memory_use += (end - start);
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    line_start = position;
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  close(fd);
5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return memory_use;
5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(BootUpMemoryUse) {
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t initial_memory = MemoryInUse();
5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FLAG_crankshaft = false;  // Avoid flakiness.
5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Only Linux has the proc filesystem and only if it is mapped.  If it's not
5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // there we just skip the test.
5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (initial_memory >= 0) {
5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InitializeVM();
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    intptr_t booted_memory = MemoryInUse();
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (sizeof(initial_memory) == 8) {
5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (v8::internal::Snapshot::IsEnabled()) {
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CHECK_LE(booted_memory - initial_memory, 6686 * 1024);  // 6476.
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CHECK_LE(booted_memory - initial_memory, 6809 * 1024);  // 6628.
5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (v8::internal::Snapshot::IsEnabled()) {
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CHECK_LE(booted_memory - initial_memory, 6532 * 1024);  // 6388.
5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CHECK_LE(booted_memory - initial_memory, 6940 * 1024);  // 6456
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif  // __linux__ and !USE_SIMULATOR
552